[Bf-blender-cvs] [3810bcc1604] master: Spreadsheet: breadcrumbs and node pinning

Jacques Lucke noreply at git.blender.org
Thu Apr 15 09:02:35 CEST 2021


Commit: 3810bcc1604756f433b5b799b66d8b81645767ca
Author: Jacques Lucke
Date:   Thu Apr 15 08:57:10 2021 +0200
Branches: master
https://developer.blender.org/rB3810bcc1604756f433b5b799b66d8b81645767ca

Spreadsheet: breadcrumbs and node pinning

This introduces a context path to the spreadsheet editor, which contains
information about what data is shown in the spreadsheet. The context
path (breadcrumbs) can reference a specific node in a node group
hierarchy. During object evaluation, the geometry nodes modifier checks
what data is currently requested by visible spreadsheets and stores
the corresponding geometry sets separately for later access.

The context path can be updated by the user explicitely, by clicking
on the new icon in the header of nodes. Under some circumstances,
the context path is updated automatically based on Blender's context.

This patch also consolidates the "Node" and "Final" object evaluation
mode to just "Evaluated". Based on the current context path, either
the final geometry set of an object will be displayed, or the data at
a specific node.

The new preview icon in geometry nodes now behaves more like
a toggle. It can be clicked again to clear the context path in an
open spreadsheet editor.

Previously, only an object could be pinned in the spreadsheet editor.
Now it is possible to pin the entire context path. That allows two
different spreadsheets to display geometry data from two different
nodes.

The breadcrumbs in the spreadsheet header can be collapsed by
clicking on the arrow icons. It's not ideal but works well for now.
This might be changed again, if we get a data set region on the left.

Differential Revision: https://developer.blender.org/D10931

===================================================================

M	release/scripts/startup/bl_operators/node.py
M	release/scripts/startup/bl_operators/spreadsheet.py
M	release/scripts/startup/bl_ui/space_spreadsheet.py
M	source/blender/blenkernel/BKE_object.h
M	source/blender/blenkernel/intern/object.c
M	source/blender/blenkernel/intern/screen.c
M	source/blender/blenlib/BLI_multi_value_map.hh
M	source/blender/blenloader/intern/readfile.c
M	source/blender/blenloader/intern/versioning_290.c
A	source/blender/editors/include/ED_spreadsheet.h
M	source/blender/editors/space_node/node_draw.cc
M	source/blender/editors/space_node/node_edit.c
M	source/blender/editors/space_node/node_ops.c
M	source/blender/editors/space_spreadsheet/CMakeLists.txt
M	source/blender/editors/space_spreadsheet/space_spreadsheet.cc
A	source/blender/editors/space_spreadsheet/spreadsheet_breadcrumb.cc
A	source/blender/editors/space_spreadsheet/spreadsheet_breadcrumb.hh
M	source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc
M	source/blender/editors/util/CMakeLists.txt
M	source/blender/makesdna/DNA_object_types.h
M	source/blender/makesdna/DNA_space_types.h
M	source/blender/makesrna/RNA_access.h
M	source/blender/makesrna/intern/rna_nodetree.c
M	source/blender/makesrna/intern/rna_space.c
M	source/blender/modifiers/intern/MOD_nodes.cc

===================================================================

diff --git a/release/scripts/startup/bl_operators/node.py b/release/scripts/startup/bl_operators/node.py
index 63da9c6af55..e0d0fc1e145 100644
--- a/release/scripts/startup/bl_operators/node.py
+++ b/release/scripts/startup/bl_operators/node.py
@@ -306,6 +306,62 @@ class NODE_OT_tree_path_parent(Operator):
         return {'FINISHED'}
 
 
+class NODE_OT_active_preview_toggle(Operator):
+    '''Toggle active preview state of node'''
+    bl_idname = "node.active_preview_toggle"
+    bl_label = "Toggle Active Preview"
+    bl_options = {'REGISTER', 'UNDO'}
+
+    @classmethod
+    def poll(cls, context):
+        space = context.space_data
+        if space.type != 'NODE_EDITOR':
+            return False
+        if space.edit_tree is None:
+            return False
+        if space.edit_tree.nodes.active is None:
+            return False
+        return True
+
+    def execute(self, context):
+        node_editor = context.space_data
+        ntree = node_editor.edit_tree
+        active_node = ntree.nodes.active
+
+        if active_node.active_preview:
+            self.disable_preview(context, ntree, active_node)
+        else:
+            self.enable_preview(context, node_editor, ntree, active_node)
+
+        return {'FINISHED'}
+
+    def enable_preview(self, context, node_editor, ntree, active_node):
+        spreadsheets = self.find_unpinned_spreadsheets(context)
+
+        for spreadsheet in spreadsheets:
+            spreadsheet.set_geometry_node_context(node_editor, active_node)
+
+        for node in ntree.nodes:
+            node.active_preview = False
+        active_node.active_preview = True
+
+    def disable_preview(self, context, ntree, active_node):
+        spreadsheets = self.find_unpinned_spreadsheets(context)
+        for spreadsheet in spreadsheets:
+            spreadsheet.context_path.clear()
+
+        active_node.active_preview = False
+
+    def find_unpinned_spreadsheets(self, context):
+        spreadsheets = []
+        for window in context.window_manager.windows:
+            for area in window.screen.areas:
+                space = area.spaces.active
+                if space.type == 'SPREADSHEET' and not space.is_pinned:
+                    spreadsheets.append(space)
+        return spreadsheets
+
+
 classes = (
     NodeSetting,
 
@@ -314,4 +370,5 @@ classes = (
     NODE_OT_add_search,
     NODE_OT_collapse_hide_unused_toggle,
     NODE_OT_tree_path_parent,
+    NODE_OT_active_preview_toggle,
 )
diff --git a/release/scripts/startup/bl_operators/spreadsheet.py b/release/scripts/startup/bl_operators/spreadsheet.py
index 91fca883bb5..5cc83d4eddd 100644
--- a/release/scripts/startup/bl_operators/spreadsheet.py
+++ b/release/scripts/startup/bl_operators/spreadsheet.py
@@ -34,13 +34,45 @@ class SPREADSHEET_OT_toggle_pin(Operator):
     def execute(self, context):
         space = context.space_data
 
-        if space.pinned_id:
-            space.pinned_id = None
+        if space.is_pinned:
+            self.unpin(context)
         else:
-            space.pinned_id = context.active_object
-
+            self.pin(context)
         return {'FINISHED'}
 
+    def pin(self, context):
+        space = context.space_data
+        space.is_pinned = True
+
+    def unpin(self, context):
+        space = context.space_data
+        space.is_pinned = False
+
+        space.context_path.clear()
+
+        # Try to find a node with an active preview in any open editor.
+        if space.object_eval_state == 'EVALUATED':
+            node_editors = self.find_geometry_node_editors(context)
+            for node_editor in node_editors:
+                ntree = node_editor.edit_tree
+                for node in ntree.nodes:
+                    if node.active_preview:
+                        space.set_geometry_node_context(node_editor, node)
+                        return
+
+    def find_geometry_node_editors(self, context):
+        editors = []
+        for window in context.window_manager.windows:
+            for area in window.screen.areas:
+                space = area.spaces.active
+                if space.type != 'NODE_EDITOR':
+                    continue
+                if space.edit_tree is None:
+                    continue
+                if space.edit_tree.type == 'GEOMETRY':
+                    editors.append(space)
+        return editors
+
 
 classes = (
     SPREADSHEET_OT_toggle_pin,
diff --git a/release/scripts/startup/bl_ui/space_spreadsheet.py b/release/scripts/startup/bl_ui/space_spreadsheet.py
index 188eddbcce3..13e435a7350 100644
--- a/release/scripts/startup/bl_ui/space_spreadsheet.py
+++ b/release/scripts/startup/bl_ui/space_spreadsheet.py
@@ -28,8 +28,17 @@ class SPREADSHEET_HT_header(bpy.types.Header):
 
         layout.template_header()
 
-        pinned_id = space.pinned_id
-        used_id = pinned_id if pinned_id else context.active_object
+        if len(space.context_path) == 0:
+            self.draw_without_context_path(layout)
+            return
+        root_context = space.context_path[0]
+        if root_context.type != 'OBJECT':
+            self.draw_without_context_path(layout)
+            return
+        obj = root_context.object
+        if obj is None:
+            self.draw_without_context_path(layout)
+            return
 
         layout.prop(space, "object_eval_state", text="")
         if space.object_eval_state != 'ORIGINAL':
@@ -37,16 +46,61 @@ class SPREADSHEET_HT_header(bpy.types.Header):
         if space.geometry_component_type != 'INSTANCES':
             layout.prop(space, "attribute_domain", text="")
 
-        if used_id:
-            layout.label(text=used_id.name, icon='OBJECT_DATA')
+        context_path = space.context_path
+        if space.object_eval_state == 'ORIGINAL':
+            # Only show first context.
+            context_path = context_path[:1]
+        if space.display_context_path_collapsed:
+            self.draw_collapsed_context_path(context, layout, context_path)
+        else:
+            self.draw_full_context_path(context, layout, context_path)
 
-        layout.operator("spreadsheet.toggle_pin", text="", icon='PINNED' if pinned_id else 'UNPINNED', emboss=False)
+        pin_icon = 'PINNED' if space.is_pinned else 'UNPINNED'
+        layout.operator("spreadsheet.toggle_pin", text="", icon=pin_icon, emboss=False)
 
         layout.separator_spacer()
 
-        if isinstance(used_id, bpy.types.Object) and used_id.mode == 'EDIT':
+        if isinstance(obj, bpy.types.Object) and obj.mode == 'EDIT':
             layout.prop(space, "show_only_selected", text="Selected Only")
 
+    def draw_without_context_path(self, layout):
+        layout.label(text="No active context")
+
+    def draw_full_context_path(self, context, layout, context_path):
+        space = context.space_data
+        row = layout.row()
+        for ctx in context_path[:-1]:
+            subrow = row.row(align=True)
+            self.draw_spreadsheet_context(subrow, ctx)
+            self.draw_spreadsheet_context_path_icon(subrow, space)
+
+        self.draw_spreadsheet_context(row, context_path[-1])
+
+    def draw_collapsed_context_path(self, context, layout, context_path):
+        space = context.space_data
+        row = layout.row(align=True)
+        self.draw_spreadsheet_context(row, context_path[0])
+        if len(context_path) == 1:
+            return
+        self.draw_spreadsheet_context_path_icon(row, space)
+        if len(context_path) > 2:
+            self.draw_spreadsheet_context_path_icon(row, space, icon='DOT')
+            self.draw_spreadsheet_context_path_icon(row, space)
+        self.draw_spreadsheet_context(row, context_path[-1])
+
+    def draw_spreadsheet_context(self, layout, ctx):
+        if ctx.type == 'OBJECT':
+            if ctx.object is None:
+                layout.label(text="<no object>", icon='OBJECT_DATA')
+            else:
+                layout.label(text=ctx.object.name, icon='OBJECT_DATA')
+        elif ctx.type == 'MODIFIER':
+            layout.label(text=ctx.modifier_name, icon='MODIFIER')
+        elif ctx.type == 'NODE':
+            layout.label(text=ctx.node_name, icon='NODE')
+
+    def draw_spreadsheet_context_path_icon(self, layout, space, icon='RIGHTARROW_THIN'):
+        layout.prop(space, "display_context_path_collapsed", icon_only=True, emboss=False, icon=icon)
 
 classes = (
     SPREADSHEET_HT_header,
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 6d5638375d6..9fe286df36d 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -70,7 +70,9 @@ void BKE_object_free_curve_cache(struct Object *ob);
 void BKE_object_free_derived_caches(struct Object *ob);
 void BKE_object_free_caches(struct Object *object);
 
-void BKE_object_set_preview_geometry_set(struct Object *ob, struct GeometrySet *geometry_set);
+void BKE_object_preview_geometry_set_add(struct Object *ob,
+                                         const uint64_t key,
+                                         struct GeometrySet *geometry_set);
 
 void BKE_object_modifier_hook_reset(struct Object *ob, struct HookModifierData *hmd);
 void BKE_object_modifier_gpencil_hook_reset(struct Object *ob,
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index d96942e47e7..5eb935f4651 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -1761,9 +1761,9 @@ void BKE_object_free_derived_caches(Object *ob)
     BKE_geometry_set_free(ob->runtime.geometry_set_eval);
     ob->runtime.geometry_set_eval = NULL;
   }
-  if (ob->runtime.geometry_set_preview != NULL) {
-    BKE_geometry_set_free(ob->runtime.geometry_set_preview);
-    ob->runtime.geometry_set_preview = NULL;
+  if (ob->runtime.geometry_set_previews != NULL) {
+    BLI_ghash_free(ob->runtime.geometry_set_previews, NULL, (GHashValFreeFP)BKE_geometry_set_free);
+    ob->runtime.geometry_set_previews = NULL;
   }
 }
 
@@ -1816,14 +1816,20 @@ void BKE_object_free_caches(Object *object)
 }
 
 /* Can be called from multiple threads. */
-void BKE_object_set_preview_geometry_set(Object *ob, struct GeometrySet *geome

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list