Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlijenstina <lijenstina@gmail.com>2017-07-23 16:02:05 +0300
committerlijenstina <lijenstina@gmail.com>2017-07-23 16:02:05 +0300
commit88918dcef321754ebb0a1859e88b2d538f7c87d4 (patch)
tree4ee6ea420c1a5e305657bfe3f28dd4dc5f297c89
parent9b0ebd3926f2c3556ee183a44c692642eb27b30f (diff)
Autotrack: Cleanup, add some report messages
Bumped version to 0.1.1 Pep8 cleanup Imports as tuples, remove unused ones Simplify the UI code Change the Cancel tip to Stop as it has different meaning for Operators (as the results are kept) Use a debug_print instead of regular print enabled / disabled by a DEBUG global as from the code it seems that is for debugging purposes Add some operator report messages to be more clear what happens
-rw-r--r--space_clip_editor_autotracker.py397
1 files changed, 213 insertions, 184 deletions
diff --git a/space_clip_editor_autotracker.py b/space_clip_editor_autotracker.py
index 9dea7e54..1cd20886 100644
--- a/space_clip_editor_autotracker.py
+++ b/space_clip_editor_autotracker.py
@@ -19,7 +19,7 @@
bl_info = {
"name": "Autotrack",
"author": "Miika Puustinen, Matti Kaihola, Stephen Leger",
- "version": (0, 1, 0),
+ "version": (0, 1, 1),
"blender": (2, 78, 0),
"location": "Movie clip Editor > Tools Panel > Autotrack",
"description": "Motion Tracking with automatic feature detection.",
@@ -31,35 +31,58 @@ bl_info = {
import bpy
import bgl
import blf
-import math
-from mathutils import Vector
-from bpy.types import Operator, Panel, PropertyGroup, WindowManager
-from bpy.props import BoolProperty, FloatProperty, IntProperty, EnumProperty, PointerProperty
+from bpy.types import (
+ Operator,
+ Panel,
+ PropertyGroup,
+ WindowManager,
+ )
+from bpy.props import (
+ BoolProperty,
+ FloatProperty,
+ IntProperty,
+ EnumProperty,
+ PointerProperty,
+ )
-# for debug purpose
+# for debug purposes
import time
+# set to True to enable debug prints
+DEBUG = False
+
+
+# pass variables just like for the regular prints
+def debug_print(*args, **kwargs):
+ global DEBUG
+ if DEBUG:
+ print(*args, **kwargs)
+
+
# http://blenderscripting.blogspot.ch/2011/07/bgl-drawing-with-opengl-onto-blender-25.html
class GlDrawOnScreen():
black = (0.0, 0.0, 0.0, 0.7)
white = (1.0, 1.0, 1.0, 0.5)
progress_colour = (0.2, 0.7, 0.2, 0.5)
+
def String(self, text, x, y, size, colour):
''' my_string : the text we want to print
pos_x, pos_y : coordinates in integer values
size : font height.
colour : used for definining the colour'''
- dpi, font_id = 72, 0 # dirty fast assignment
+ dpi, font_id = 72, 0 # dirty fast assignment
bgl.glColor4f(*colour)
blf.position(font_id, x, y, 0)
blf.size(font_id, size, dpi)
blf.draw(font_id, text)
+
def _end(self):
bgl.glEnd()
bgl.glPopAttrib()
bgl.glLineWidth(1)
bgl.glDisable(bgl.GL_BLEND)
bgl.glColor4f(0.0, 0.0, 0.0, 1.0)
+
def _start_line(self, colour, width=2, style=bgl.GL_LINE_STIPPLE):
bgl.glPushAttrib(bgl.GL_ENABLE_BIT)
bgl.glLineStipple(1, 0x9999)
@@ -68,123 +91,127 @@ class GlDrawOnScreen():
bgl.glColor4f(*colour)
bgl.glLineWidth(width)
bgl.glBegin(bgl.GL_LINE_STRIP)
+
def Rectangle(self, x0, y0, x1, y1, colour, width=2, style=bgl.GL_LINE):
- self._start_line(colour, width, style)
+ self._start_line(colour, width, style)
bgl.glVertex2i(x0, y0)
bgl.glVertex2i(x1, y0)
bgl.glVertex2i(x1, y1)
bgl.glVertex2i(x0, y1)
bgl.glVertex2i(x0, y0)
self._end()
+
def Polygon(self, pts, colour):
bgl.glPushAttrib(bgl.GL_ENABLE_BIT)
bgl.glEnable(bgl.GL_BLEND)
- bgl.glColor4f(*colour)
+ bgl.glColor4f(*colour)
bgl.glBegin(bgl.GL_POLYGON)
for pt in pts:
x, y = pt
- bgl.glVertex2f(x, y)
+ bgl.glVertex2f(x, y)
self._end()
+
def ProgressBar(self, x, y, width, height, start, percent):
- x1, y1 = x+width, y+height
+ x1, y1 = x + width, y + height
# progress from current point to either start or end
- xs = x+(x1-x) * float(start)
+ xs = x + (x1 - x) * float(start)
if percent > 0:
# going forward
- xi = xs+(x1-xs) * float(percent)
+ xi = xs + (x1 - xs) * float(percent)
else:
# going backward
- xi = xs-(x-xs) * float(percent)
+ xi = xs - (x - xs) * float(percent)
self.Polygon([(xs, y), (xs, y1), (xi, y1), (xi, y)], self.progress_colour)
self.Rectangle(x, y, x1, y1, self.white, width=1)
-
+
+
def draw_callback(self, context):
- #print("draw_callback : %s" % (self.progress))
self.gl.ProgressBar(10, 24, 200, 16, self.start, self.progress)
- self.gl.String(str(int(100*abs(self.progress)))+"% ESC to Cancel", 14, 28, 10, self.gl.white)
-
+ self.gl.String(str(int(100 * abs(self.progress))) + "% ESC to Stop", 14, 28, 10, self.gl.white)
+
+
class OP_Tracking_auto_tracker(Operator):
- """Autotrack. Esc to cancel."""
bl_idname = "tracking.auto_track"
bl_label = "AutoTracking"
+ bl_description = ("Start Autotracking, Press Esc to Stop \n"
+ "When stopped, the added Track Markers will be kept")
_timer = None
_draw_handler = None
-
+
gl = GlDrawOnScreen()
progress = 0
limits = 0
t = 0
-
+
def find_track_start(self, track):
for m in track.markers:
if not m.mute:
return m.frame
return track.markers[0].frame
-
+
def find_track_end(self, track):
for m in reversed(track.markers):
if not m.mute:
return m.frame
- return track.markers[-1].frame-1
-
+ return track.markers[-1].frame - 1
+
def find_track_length(self, track):
tstart = self.find_track_start(track)
- tend = self.find_track_end(track)
- return tend-tstart
-
+ tend = self.find_track_end(track)
+ return tend - tstart
+
def show_tracks(self, context):
- scene = context.scene
- clip = context.area.spaces.active.clip
+ clip = context.area.spaces.active.clip
tracks = clip.tracking.tracks
for track in tracks:
track.hide = False
-
- def get_vars_from_context(self, context):
+
+ def get_vars_from_context(self, context):
scene = context.scene
props = context.window_manager.autotracker_props
- clip = context.area.spaces.active.clip
+ clip = context.area.spaces.active.clip
tracks = clip.tracking.tracks
current_frame = scene.frame_current
- clip_end = clip.frame_start+clip.frame_duration
+ clip_end = clip.frame_start + clip.frame_duration
clip_start = clip.frame_start
if props.track_backwards:
- last_frame = min(clip_end, current_frame+props.frame_separation)
+ last_frame = min(clip_end, current_frame + props.frame_separation)
else:
- last_frame = max(clip_start, current_frame-props.frame_separation)
+ last_frame = max(clip_start, current_frame - props.frame_separation)
return scene, props, clip, tracks, current_frame, last_frame
-
+
def delete_tracks(self, to_delete):
bpy.ops.clip.select_all(action='DESELECT')
for track in to_delete:
track.select = True
bpy.ops.clip.delete_track()
-
+
# DETECT FEATURES
def auto_features(self, context):
"""
- Detect features
+ Detect features
"""
t = time.time()
-
+
scene, props, clip, tracks, current_frame, last_frame = self.get_vars_from_context(context)
-
+
selected = []
old = []
to_delete = []
width = clip.size[0]
- delete_threshold = float(props.delete_threshold)/100.0
-
+ delete_threshold = float(props.delete_threshold) / 100.0
+
bpy.ops.clip.select_all(action='DESELECT')
-
+
# Detect Features
bpy.ops.clip.detect_features(
- threshold=props.df_threshold,
- min_distance=props.df_distance/100.0*width,
- margin=props.df_margin/100.0*width,
- placement=props.placement_list
- )
-
+ threshold=props.df_threshold,
+ min_distance=props.df_distance / 100.0 * width,
+ margin=props.df_margin / 100.0 * width,
+ placement=props.placement_list
+ )
+
# filter new and old tracks
for track in tracks:
if track.hide or track.lock:
@@ -195,41 +222,40 @@ class OP_Tracking_auto_tracker(Operator):
old.append(track)
if track.select:
selected.append(track)
-
+
added_tracks = len(selected)
-
+
# Select overlapping new markers
for track_new in selected:
marker0 = track_new.markers.find_frame(current_frame)
for track_old in old:
marker1 = track_old.markers.find_frame(current_frame)
- distance = (marker1.co-marker0.co).length
+ distance = (marker1.co - marker0.co).length
if distance < delete_threshold:
to_delete.append(track_new)
added_tracks -= 1
break
-
+
# Delete Overlapping Markers
self.delete_tracks(to_delete)
- print("auto_features %.4f seconds add:%s tracks." % (time.time()-t, added_tracks))
-
+ debug_print("auto_features %.4f seconds, add: %s tracks" % (time.time() - t, added_tracks))
+
# AUTOTRACK FRAMES
def track_frames_backward(self):
# INVOKE_DEFAULT to show progress and take account of frame_limit
t = time.time()
res = bpy.ops.clip.track_markers('INVOKE_DEFAULT', backwards=True, sequence=True)
- print("track_frames_backward %.2f seconds %s" % (time.time()-t, res))
-
+ debug_print("track_frames_backward %.2f seconds %s" % (time.time() - t, res))
+
def track_frames_forward(self):
# INVOKE_DEFAULT to show progress and take account of frame_limit
t = time.time()
res = bpy.ops.clip.track_markers('INVOKE_DEFAULT', backwards=False, sequence=True)
- print("track_frames_forward %.2f seconds %s" % (time.time()-t, res))
-
+ debug_print("track_frames_forward %.2f seconds %s" % (time.time() - t, res))
+
def get_active_tracks(self, context):
scene, props, clip, tracks, current_frame, last_frame = self.get_vars_from_context(context)
- # Select active trackers for tracking
- #bpy.ops.clip.select_all(action='DESELECT')
+
active_tracks = []
for track in tracks:
if track.hide or track.lock:
@@ -239,9 +265,9 @@ class OP_Tracking_auto_tracker(Operator):
else:
marker = track.markers.find_frame(current_frame)
if (marker is not None) and (not marker.mute):
- active_tracks.append(track)
+ active_tracks.append(track)
return active_tracks
-
+
def select_active_tracks(self, context):
t = time.time()
scene, props, clip, tracks, current_frame, last_frame = self.get_vars_from_context(context)
@@ -250,9 +276,10 @@ class OP_Tracking_auto_tracker(Operator):
selected = self.get_active_tracks(context)
for track in selected:
track.select = True
- print("select_active_tracks %.2f seconds selected:%s" % (time.time()-t, len(selected)))
+ debug_print("select_active_tracks %.2f seconds,"
+ " selected: %s" % (time.time() - t, len(selected)))
return selected
-
+
def estimate_motion(self, context, last, frame):
"""
compute mean pixel motion for current frame
@@ -270,7 +297,7 @@ class OP_Tracking_auto_tracker(Operator):
marker0 = track.markers.find_frame(frame)
marker1 = track.markers.find_frame(last)
if marker0 is not None and marker1 is not None:
- d = (marker0.co-marker1.co).length
+ d = (marker0.co - marker1.co).length
# skip fixed tracks
if d > 0:
distance += d
@@ -280,9 +307,9 @@ class OP_Tracking_auto_tracker(Operator):
else:
# arbitrary set to prevent division by 0 error
mean = 10
-
+
return mean
-
+
# REMOVE SMALL TRACKS
def remove_small(self, context):
t = time.time()
@@ -298,8 +325,8 @@ class OP_Tracking_auto_tracker(Operator):
to_delete.append(track)
deleted_tracks = len(to_delete)
self.delete_tracks(to_delete)
- print("remove_small %.4f seconds %s tracks deleted." % (time.time()-t, deleted_tracks))
-
+ debug_print("remove_small %.4f seconds, %s tracks deleted" % (time.time() - t, deleted_tracks))
+
def split_track(self, context, track, split_frame, skip=0):
scene, props, clip, tracks, current_frame, last_frame = self.get_vars_from_context(context)
if props.track_backwards:
@@ -308,14 +335,14 @@ class OP_Tracking_auto_tracker(Operator):
else:
end = scene.frame_end
step = 1
- new_track = \
- tracks.new(frame=split_frame)
+ new_track = tracks.new(frame=split_frame)
+
for frame in range(split_frame, end, step):
marker = track.markers.find_frame(frame)
if marker is None:
return
- # add new marker on new track for frame
- if abs(frame - split_frame) >= skip:
+ # add new marker on new track for frame
+ if abs(frame - split_frame) >= skip:
new_marker = new_track.markers.find_frame(frame)
if new_marker is None:
new_marker = new_track.markers.insert_frame(frame)
@@ -326,268 +353,274 @@ class OP_Tracking_auto_tracker(Operator):
else:
track.markers.delete_frame(frame)
marker.mute = True
-
+
# REMOVE JUMPING MARKERS
def remove_jumping(self, context):
-
+
t = time.time()
-
scene, props, clip, tracks, current_frame, last_frame = self.get_vars_from_context(context)
-
+
if props.track_backwards:
step = -1
else:
step = 1
-
+
to_split = [None for track in tracks]
for frame in range(last_frame, current_frame, step):
-
+
last = frame - step
-
+
# mean motion (normalized [0-1]) distance for tracks between last and current frame
mean = self.estimate_motion(context, last, frame)
-
- # how much a track is allowed to move
+
+ # how much a track is allowed to move
allowed = mean * props.jump_cut
-
+
for i, track in enumerate(tracks):
if track.hide or track.lock:
continue
marker0 = track.markers.find_frame(frame)
marker1 = track.markers.find_frame(last)
if marker0 is not None and marker1 is not None:
- distance = (marker0.co-marker1.co).length
+ distance = (marker0.co - marker1.co).length
# Jump Cut threshold
if distance > allowed:
if to_split[i] is None:
to_split[i] = [frame, frame]
else:
- to_split[i][1] = frame
-
+ to_split[i][1] = frame
+
jumping = 0
for i, split in enumerate(to_split):
if split is not None:
- self.split_track(context, tracks[i], split[0], abs(split[0]-split[1]))
+ self.split_track(context, tracks[i], split[0], abs(split[0] - split[1]))
jumping += 1
-
- print("remove_jumping :%.4f seconds %s tracks cut." % (time.time()-t, jumping))
-
+
+ debug_print("remove_jumping: %.4f seconds, %s tracks cut." % (time.time() - t, jumping))
+
def get_frame_range(self, context):
"""
get tracking frames range
- use clip limits when clip shorter than scene
+ use clip limits when clip shorter than scene
else use scene limits
"""
scene, props, clip, tracks, current_frame, last_frame = self.get_vars_from_context(context)
frame_start = max(scene.frame_start, clip.frame_start)
- frame_end = min(scene.frame_end, clip.frame_start+clip.frame_duration)
+ frame_end = min(scene.frame_end, clip.frame_start + clip.frame_duration)
frame_duration = frame_end - frame_start
return frame_start, frame_end, frame_duration
-
+
def modal(self, context, event):
-
+
if event.type in {'ESC'}:
- print("Cancelling")
+ self.report({'INFO'},
+ "Stopping, up to now added Markers will be kept. Autotracking Finished")
self.cancel(context)
return {'FINISHED'}
-
+
scene, props, clip, tracks, current_frame, last_frame = self.get_vars_from_context(context)
frame_start, frame_end, frame_duration = self.get_frame_range(context)
-
+
if (((not props.track_backwards) and current_frame >= frame_end) or
- (props.track_backwards and current_frame <= frame_start)):
- print("Reached clip end")
+ (props.track_backwards and current_frame <= frame_start)):
+
+ self.report({'INFO'},
+ "Reached the end of the Clip. Autotracking Finished")
self.cancel(context)
return {'FINISHED'}
-
- # dont run this modal while tracking operator runs
- # Known issue, youll have to keep ESC pressed
+
+ # do not run this modal while tracking operator runs
+ # Known issue, you'll have to keep ESC pressed
if event.type not in {'TIMER'} or context.scene.frame_current != self.next_frame:
return {'PASS_THROUGH'}
-
+
# prevent own TIMER event while running
self.stop_timer(context)
-
+
if props.track_backwards:
self.next_frame = scene.frame_current - props.frame_separation
total = self.start_frame - frame_start
else:
self.next_frame = scene.frame_current + props.frame_separation
total = frame_end - self.start_frame
-
+
if total > 0:
- self.progress = (current_frame-self.start_frame)/total
+ self.progress = (current_frame - self.start_frame) / total
else:
self.progress = 0
-
- print("Tracking frame %s" % (scene.frame_current))
-
+
+ debug_print("Tracking frame %s" % (scene.frame_current))
+
# Remove bad tracks before adding new ones
self.remove_small(context)
self.remove_jumping(context)
-
+
# add new tracks
self.auto_features(context)
# Select active trackers for tracking
active_tracks = self.select_active_tracks(context)
-
+
# finish if there is nothing to track
if len(active_tracks) == 0:
- print("No new tracks created. Doing nothing.")
+ self.report({'INFO'},
+ "No new tracks created, nothing to track. Autotrack Finished")
self.cancel(context)
return {'FINISHED'}
-
+
# setup frame_limit on tracks
for track in active_tracks:
track.frames_limit = 0
active_tracks[0].frames_limit = props.frame_separation
-
+
# Forwards or backwards tracking
if props.track_backwards:
self.track_frames_backward()
else:
self.track_frames_forward()
-
- # setup a timer to broadcast a TIMER event to force modal to re-run as fast as possible (not waiting for any mouse or keyboard event)
+
+ # setup a timer to broadcast a TIMER event to force modal to
+ # re-run as fast as possible (not waiting for any mouse or keyboard event)
self.start_timer(context)
-
+
return {'RUNNING_MODAL'}
-
+
def invoke(self, context, event):
scene = context.scene
frame_start, frame_end, frame_duration = self.get_frame_range(context)
-
+
if scene.frame_current > frame_end:
scene.frame_current = frame_end
elif scene.frame_current < frame_start:
scene.frame_current = frame_start
-
+
self.start_frame = scene.frame_current
- self.start = (scene.frame_current-frame_start) / (frame_duration)
+ self.start = (scene.frame_current - frame_start) / (frame_duration)
self.progress = 0
-
+
# keep track of frame at witch we should detect new features and filter tracks
self.next_frame = scene.frame_current
-
+
# draw progress
args = (self, context)
- self._draw_handler = bpy.types.SpaceClipEditor.draw_handler_add(draw_callback, args, 'WINDOW', 'POST_PIXEL')
-
+ self._draw_handler = bpy.types.SpaceClipEditor.draw_handler_add(
+ draw_callback, args,
+ 'WINDOW', 'POST_PIXEL'
+ )
self.start_timer(context)
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
-
+
def __init__(self):
self.t = time.time()
def __del__(self):
- print("AutoTrack %.2f seconds" % (time.time()-self.t))
-
+ debug_print("AutoTrack %.2f seconds" % (time.time() - self.t))
+
def execute(self, context):
- print("execute")
+ debug_print("Autotrack execute called")
return {'FINISHED'}
-
+
def stop_timer(self, context):
context.window_manager.event_timer_remove(self._timer)
-
+
def start_timer(self, context):
self._timer = context.window_manager.event_timer_add(time_step=0.1, window=context.window)
-
+
def cancel(self, context):
self.stop_timer(context)
- self.show_tracks(context)
+ self.show_tracks(context)
bpy.types.SpaceClipEditor.draw_handler_remove(self._draw_handler, 'WINDOW')
-
+
@classmethod
def poll(cls, context):
- return (context.area.spaces.active.clip is not None)
-
+ return (context.area.spaces.active.clip is not None)
+
+
class AutotrackerSettings(PropertyGroup):
"""Create properties"""
df_margin = FloatProperty(
name="Detect Features Margin",
- description="Only features further margin pixels from the image edges are considered.",
+ description="Only consider features from pixels located outside\n"
+ "the defined margin from the clip borders",
subtype='PERCENTAGE',
default=5,
min=0,
max=100
)
-
df_threshold = FloatProperty(
name="Detect Features Threshold",
- description="Threshold level to concider feature good enough for tracking.",
+ description="Threshold level to deem a feature being good enough for tracking",
default=0.3,
min=0.0,
max=1.0
)
- # Note: merge this one with delete_threshold
+ # Note: merge this one with delete_threshold
df_distance = FloatProperty(
name="Detect Features Distance",
- description="Minimal distance accepted between two features.",
+ description="Minimal acceptable distance between two features",
subtype='PERCENTAGE',
default=8,
min=1,
max=100
)
-
delete_threshold = FloatProperty(
name="New Marker Threshold",
- description="Threshold how near new features can appear during autotracking.",
+ description="Threshold of how close a new features can appear during tracking",
subtype='PERCENTAGE',
default=8,
min=1,
max=100
)
-
small_tracks = IntProperty(
name="Minimum track length",
- description="Delete tracks shortest than this number of frames (set to 0 to keep all tracks).",
+ description="Delete tracks shorter than this number of frames\n"
+ "Note: set to 0 for keeping all tracks",
default=50,
min=1,
max=1000
)
-
frame_separation = IntProperty(
name="Frame Separation",
- description="How often new features are generated.",
+ description="How often new features are generated",
default=5,
min=1,
max=100
)
-
jump_cut = FloatProperty(
name="Jump Cut",
- description="Distance how much a marker can travel before it is considered "
- "to be a bad track and cut. A new track is added. (factor relative to mean motion)",
+ description="How much distance a marker can travel before it is considered "
+ "to be a bad track and cut.\nA new track wil be added "
+ "(factor relative to mean motion)",
default=5.0,
min=0.0,
max=50.0
)
-
track_backwards = BoolProperty(
name="AutoTrack Backwards",
- description="Autotrack backwards.",
+ description="Track from the last frame of the selected clip",
default=False
)
-
# Dropdown menu
list_items = [
- ("FRAME", "Whole Frame", "", 1),
- ("INSIDE_GPENCIL", "Inside Grease Pencil", "", 2),
- ("OUTSIDE_GPENCIL", "Outside Grease Pencil", "", 3),
- ]
-
+ ("FRAME", "Whole Frame", "", 1),
+ ("INSIDE_GPENCIL", "Inside Grease Pencil", "", 2),
+ ("OUTSIDE_GPENCIL", "Outside Grease Pencil", "", 3),
+ ]
placement_list = EnumProperty(
name="Placement",
description="Feature Placement",
items=list_items
)
-
+
+
"""
NOTE:
- All size properties are in percent of clip size, so presets does not depends on clip size
+ All size properties are in percent of the clip size,
+ so presets do not depend on the clip size
"""
+
+
class AutotrackerPanel(Panel):
"""Creates a Panel in the Render Layer properties window"""
bl_label = "Autotrack"
@@ -595,19 +628,18 @@ class AutotrackerPanel(Panel):
bl_space_type = 'CLIP_EDITOR'
bl_region_type = 'TOOLS'
bl_category = "Track"
-
+
@classmethod
def poll(cls, context):
- return (context.area.spaces.active.clip is not None)
-
- # Draw UI
+ return (context.area.spaces.active.clip is not None)
+
def draw(self, context):
layout = self.layout
wm = context.window_manager
-
+
row = layout.row()
row.scale_y = 1.5
- props = row.operator("tracking.auto_track", text="Autotrack! ", icon='PLAY')
+ row.operator("tracking.auto_track", text="Autotrack! ", icon='PLAY')
row = layout.row()
row.prop(wm.autotracker_props, "track_backwards")
@@ -615,39 +647,36 @@ class AutotrackerPanel(Panel):
row = layout.row()
col = layout.column(align=True)
col.prop(wm.autotracker_props, "delete_threshold")
- sub = col.row(align=True)
- sub.prop(wm.autotracker_props, "small_tracks")
- sub = col.row(align=True)
- sub.prop(wm.autotracker_props, "frame_separation", text="Frame Separation")
- sub = col.row(align=True)
- sub.prop(wm.autotracker_props, "jump_cut", text="Jump Threshold")
+ col.prop(wm.autotracker_props, "small_tracks")
+ col.prop(wm.autotracker_props, "frame_separation", text="Frame Separation")
+ col.prop(wm.autotracker_props, "jump_cut", text="Jump Threshold")
row = layout.row()
row.label(text="Detect Features Settings:")
col = layout.column(align=True)
col.prop(wm.autotracker_props, "df_margin", text="Margin:")
- sub = col.row(align=True)
- sub.prop(wm.autotracker_props, "df_distance", text="Distance:")
- sub = col.row(align=True)
- sub.prop(wm.autotracker_props, "df_threshold", text="Threshold:")
+ col.prop(wm.autotracker_props, "df_distance", text="Distance:")
+ col.prop(wm.autotracker_props, "df_threshold", text="Threshold:")
row = layout.row()
row.label(text="Feature Placement:")
col = layout.column(align=True)
col.prop(wm.autotracker_props, "placement_list", text="")
- layout.separator()
-
+
def register():
bpy.utils.register_class(AutotrackerSettings)
- WindowManager.autotracker_props = \
- PointerProperty(type=AutotrackerSettings)
- bpy.utils.register_module(__name__)
-
+ WindowManager.autotracker_props = PointerProperty(
+ type=AutotrackerSettings
+ )
+ bpy.utils.register_module(__name__)
+
+
def unregister():
bpy.utils.unregister_class(AutotrackerSettings)
- bpy.utils.unregister_module(__name__)
+ bpy.utils.unregister_module(__name__)
del WindowManager.autotracker_props
+
if __name__ == "__main__":
register()