From a58bfe9a7623ac584e6ff3310f802da7ab71c624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Fri, 4 Nov 2016 12:04:38 +0100 Subject: [PATCH] Be more explicit in strip ObjectID conflicts. Shows more warnings in the UI, and the conflict status is now saved on an RNA property atc_object_id_conflict. --- blender_cloud/attract/__init__.py | 57 +++++++++++++++++++++++++++++++ blender_cloud/attract/draw.py | 17 +++------ 2 files changed, 61 insertions(+), 13 deletions(-) diff --git a/blender_cloud/attract/__init__.py b/blender_cloud/attract/__init__.py index 8aaa33e..13881e6 100644 --- a/blender_cloud/attract/__init__.py +++ b/blender_cloud/attract/__init__.py @@ -79,6 +79,18 @@ def selected_shots(context): yield strip +def shown_strips(context): + """Returns the strips from the current meta-strip-stack, or top-level strips. + + What is returned depends on what the user is currently editing. + """ + + if context.scene.sequence_editor.meta_stack: + return context.scene.sequence_editor.meta_stack[-1].sequences + + return context.scene.sequence_editor.sequences + + def remove_atc_props(strip): """Resets the attract custom properties assigned to a VSE strip""" @@ -88,6 +100,38 @@ def remove_atc_props(strip): strip.atc_is_synced = False +def shot_id_use(strips): + """Returns a mapping from shot Object ID to a list of strips that use it.""" + + import collections + + # Count the number of uses per Object ID, so that we can highlight double use. + ids_in_use = collections.defaultdict(list) + for strip in strips: + if not getattr(strip, 'atc_is_synced', False): + continue + + ids_in_use[strip.atc_object_id].append(strip) + + return ids_in_use + + +def compute_strip_conflicts(context): + """Sets the strip property atc_object_id_conflict for each strip.""" + + # FIXME: this only considers the currently shown strips, so only draws conflicts either within + # the same metastrip or not in metastrips. Cross-metastrip boundaries are not crossed to check. + all_strips = shown_strips(context) + ids_in_use = shot_id_use(all_strips) + + for strips in ids_in_use.values(): + is_conflict = len(strips) > 1 + for strip in strips: + strip.atc_object_id_conflict = is_conflict + + return ids_in_use + + class ToolsPanel(Panel): bl_label = 'Attract' bl_space_type = 'SEQUENCE_EDITOR' @@ -110,6 +154,12 @@ class ToolsPanel(Panel): else: noun = 'This Shot' + if strip.atc_object_id_conflict: + warnbox = layout.box() + warnbox.alert = True + warnbox.label('Warning: This shot is linked to multiple sequencer strips.', + icon='ERROR') + layout.prop(strip, 'atc_name', text='Name') layout.prop(strip, 'atc_status', text='Status') @@ -222,6 +272,7 @@ class AttractOperatorMixin: strip.atc_notes = node['properties']['notes'] strip.atc_status = node['properties']['status'] + compute_strip_conflicts(bpy.context) draw.tag_redraw_all_sequencer_editors() def submit_update(self, strip): @@ -266,6 +317,7 @@ class AttractOperatorMixin: strip.atc_notes = node.properties.notes or '' strip.atc_description = node.description or '' + compute_strip_conflicts(bpy.context) draw.tag_redraw_all_sequencer_editors() @@ -699,6 +751,10 @@ def draw_strip_movie_meta(self, context): def register(): bpy.types.Sequence.atc_is_synced = bpy.props.BoolProperty(name="Is Synced") bpy.types.Sequence.atc_object_id = bpy.props.StringProperty(name="Attract Object ID") + bpy.types.Sequence.atc_object_id_conflict = bpy.props.BoolProperty( + name='Object ID Conflict', + description='Attract Object ID used multiple times', + default=False) bpy.types.Sequence.atc_name = bpy.props.StringProperty(name="Shot Name") bpy.types.Sequence.atc_description = bpy.props.StringProperty(name="Shot Description") bpy.types.Sequence.atc_notes = bpy.props.StringProperty(name="Shot Notes") @@ -734,6 +790,7 @@ def unregister(): bpy.utils.unregister_module(__name__) del bpy.types.Sequence.atc_is_synced del bpy.types.Sequence.atc_object_id + del bpy.types.Sequence.atc_object_id_conflict del bpy.types.Sequence.atc_name del bpy.types.Sequence.atc_description del bpy.types.Sequence.atc_notes diff --git a/blender_cloud/attract/draw.py b/blender_cloud/attract/draw.py index 6ab00d8..68b9a96 100644 --- a/blender_cloud/attract/draw.py +++ b/blender_cloud/attract/draw.py @@ -108,29 +108,20 @@ def draw_strip_conflict(strip_coords, pixel_size_x): def draw_callback_px(): - import collections - context = bpy.context if not context.scene.sequence_editor: return + from . import shown_strips + region = context.region xwin1, ywin1 = region.view2d.region_to_view(0, 0) xwin2, ywin2 = region.view2d.region_to_view(region.width, region.height) one_pixel_further_x, one_pixel_further_y = region.view2d.region_to_view(1, 1) pixel_size_x = one_pixel_further_x - xwin1 - pixel_size_y = one_pixel_further_y - ywin1 - if context.scene.sequence_editor.meta_stack: - strips = context.scene.sequence_editor.meta_stack[-1].sequences - else: - strips = context.scene.sequence_editor.sequences - - # Count the number of uses per Object ID, so that we can highlight double use. - ids_in_use = collections.defaultdict(int) - for strip in strips: - ids_in_use[strip.atc_object_id] += bool(getattr(strip, 'atc_is_synced', False)) + strips = shown_strips(context) for strip in strips: if not strip.atc_object_id: @@ -154,7 +145,7 @@ def draw_callback_px(): alpha = 1.0 if strip.atc_is_synced else 0.5 draw_underline_in_strip(strip_coords, pixel_size_x, color + (alpha,)) - if strip.atc_is_synced and ids_in_use[strip.atc_object_id] > 1: + if strip.atc_is_synced and strip.atc_object_id_conflict: draw_strip_conflict(strip_coords, pixel_size_x)