[Bf-blender-cvs] [4ed208bcd82] master: Spreadsheet: support showing data from original/unevaluated object

Jacques Lucke noreply at git.blender.org
Mon Mar 15 10:17:06 CET 2021


Commit: 4ed208bcd82e912fa9a0da6137af6e87004e9365
Author: Jacques Lucke
Date:   Mon Mar 15 10:16:11 2021 +0100
Branches: master
https://developer.blender.org/rB4ed208bcd82e912fa9a0da6137af6e87004e9365

Spreadsheet: support showing data from original/unevaluated object

There are two caveats of the current implementation which still need
to be resolved in a separate step:
* In theory the data on the original object can be editable in the spreadsheet.
* If a complex object is in edit mode, and its original data is displayed,
  the drawing code can be slow, because the bmesh is converted to a mesh
  every time. The proper solution is to draw the data from the bmesh directly.
  This should become easier after an upcoming refactor.

Ref T86141.

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

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

M	release/scripts/startup/bl_ui/space_spreadsheet.py
M	source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc
M	source/blender/makesdna/DNA_space_types.h
M	source/blender/makesrna/intern/rna_space.c

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

diff --git a/release/scripts/startup/bl_ui/space_spreadsheet.py b/release/scripts/startup/bl_ui/space_spreadsheet.py
index 1ba650fa096..a12fe68c9a5 100644
--- a/release/scripts/startup/bl_ui/space_spreadsheet.py
+++ b/release/scripts/startup/bl_ui/space_spreadsheet.py
@@ -31,7 +31,9 @@ class SPREADSHEET_HT_header(bpy.types.Header):
         pinned_id = space.pinned_id
         used_id = pinned_id if pinned_id else context.active_object
 
-        layout.prop(space, "geometry_component_type", text="")
+        layout.prop(space, "object_eval_state", text="")
+        if space.object_eval_state != "ORIGINAL":
+            layout.prop(space, "geometry_component_type", text="")
         layout.prop(space, "attribute_domain", text="")
 
         if used_id:
diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc
index 0cb937628f5..b60a1478352 100644
--- a/source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc
+++ b/source/blender/editors/space_spreadsheet/spreadsheet_from_geometry.cc
@@ -24,6 +24,8 @@
 
 #include "BKE_context.h"
 #include "BKE_editmesh.h"
+#include "BKE_lib_id.h"
+#include "BKE_mesh.h"
 #include "BKE_mesh_wrapper.h"
 #include "BKE_modifier.h"
 
@@ -333,24 +335,56 @@ static void add_columns_for_attribute(const ReadAttribute *attribute,
   }
 }
 
-static GeometrySet get_display_geometry_set(Object *object_eval,
+static GeometrySet get_display_geometry_set(SpaceSpreadsheet *sspreadsheet,
+                                            Object *object_eval,
                                             const GeometryComponentType used_component_type)
 {
   GeometrySet geometry_set;
-  if (used_component_type == GEO_COMPONENT_TYPE_MESH && object_eval->mode == OB_MODE_EDIT) {
-    Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(object_eval, false);
-    if (mesh == nullptr) {
-      return geometry_set;
+  if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_FINAL) {
+    if (used_component_type == GEO_COMPONENT_TYPE_MESH && object_eval->mode == OB_MODE_EDIT) {
+      Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(object_eval, false);
+      if (mesh == nullptr) {
+        return geometry_set;
+      }
+      BKE_mesh_wrapper_ensure_mdata(mesh);
+      MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
+      mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly);
+      mesh_component.copy_vertex_group_names_from_object(*object_eval);
+    }
+    else {
+      if (object_eval->runtime.geometry_set_eval != nullptr) {
+        /* This does not copy the geometry data itself. */
+        geometry_set = *object_eval->runtime.geometry_set_eval;
+      }
     }
-    BKE_mesh_wrapper_ensure_mdata(mesh);
-    MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
-    mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly);
-    mesh_component.copy_vertex_group_names_from_object(*object_eval);
   }
   else {
-    if (object_eval->runtime.geometry_set_eval != nullptr) {
-      /* This does not copy the geometry data itself. */
-      geometry_set = *object_eval->runtime.geometry_set_eval;
+    Object *object_orig = DEG_get_original_object(object_eval);
+    if (object_orig->type == OB_MESH) {
+      MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>();
+      if (object_orig->mode == OB_MODE_EDIT) {
+        Mesh *mesh = (Mesh *)object_orig->data;
+        BMEditMesh *em = mesh->edit_mesh;
+        if (em != nullptr) {
+          Mesh *new_mesh = (Mesh *)BKE_id_new_nomain(ID_ME, nullptr);
+          /* This is a potentially heavy operation to do on every redraw. The best solution here is
+           * to display the data directly from the bmesh without a conversion, which can be
+           * implemented a bit later. */
+          BM_mesh_bm_to_me_for_eval(em->bm, new_mesh, nullptr);
+          mesh_component.replace(new_mesh, GeometryOwnershipType::Owned);
+        }
+      }
+      else {
+        Mesh *mesh = (Mesh *)object_orig->data;
+        mesh_component.replace(mesh, GeometryOwnershipType::ReadOnly);
+      }
+      mesh_component.copy_vertex_group_names_from_object(*object_orig);
+    }
+    else if (object_orig->type == OB_POINTCLOUD) {
+      PointCloud *pointcloud = (PointCloud *)object_orig->data;
+      PointCloudComponent &pointcloud_component =
+          geometry_set.get_component_for_write<PointCloudComponent>();
+      pointcloud_component.replace(pointcloud, GeometryOwnershipType::ReadOnly);
     }
   }
   return geometry_set;
@@ -480,18 +514,29 @@ static Span<int64_t> filter_mesh_elements_by_selection(const bContext *C,
   return IndexRange(domain_size).as_span();
 }
 
+static GeometryComponentType get_display_component_type(const bContext *C, Object *object_eval)
+{
+  SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
+  if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_FINAL) {
+    return (GeometryComponentType)sspreadsheet->geometry_component_type;
+  }
+  if (object_eval->type == OB_POINTCLOUD) {
+    return GEO_COMPONENT_TYPE_POINT_CLOUD;
+  }
+  return GEO_COMPONENT_TYPE_MESH;
+}
+
 std::unique_ptr<SpreadsheetDrawer> spreadsheet_drawer_from_geometry_attributes(const bContext *C,
                                                                                Object *object_eval)
 {
   SpaceSpreadsheet *sspreadsheet = CTX_wm_space_spreadsheet(C);
   const AttributeDomain domain = (AttributeDomain)sspreadsheet->attribute_domain;
-  const GeometryComponentType component_type = (GeometryComponentType)
-                                                   sspreadsheet->geometry_component_type;
+  const GeometryComponentType component_type = get_display_component_type(C, object_eval);
 
   /* Create a resource collector that owns stuff that needs to live until drawing is done. */
   std::unique_ptr<ResourceCollector> resources = std::make_unique<ResourceCollector>();
   GeometrySet &geometry_set = resources->add_value(
-      get_display_geometry_set(object_eval, component_type), "geometry set");
+      get_display_geometry_set(sspreadsheet, object_eval, component_type), "geometry set");
 
   const GeometryComponent *component = geometry_set.get_component_for_read(component_type);
   if (component == nullptr) {
diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h
index 9007d3b6cf4..dec3097a9ae 100644
--- a/source/blender/makesdna/DNA_space_types.h
+++ b/source/blender/makesdna/DNA_space_types.h
@@ -1865,8 +1865,10 @@ typedef struct SpaceSpreadsheet {
   uint8_t geometry_component_type;
   /* #AttributeDomain. */
   uint8_t attribute_domain;
+  /* eSpaceSpreadsheet_ObjectContext. */
+  uint8_t object_eval_state;
 
-  char _pad1[5];
+  char _pad1[4];
 
   SpaceSpreadsheet_Runtime *runtime;
 } SpaceSpreadsheet;
@@ -1877,6 +1879,11 @@ typedef enum eSpaceSpreadsheet_FilterFlag {
   SPREADSHEET_FILTER_SELECTED_ONLY = (1 << 0),
 } eSpaceSpreadsheet_FilterFlag;
 
+typedef enum eSpaceSpreadsheet_ObjectEvalState {
+  SPREADSHEET_OBJECT_EVAL_STATE_FINAL = 0,
+  SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL = 1,
+} eSpaceSpreadsheet_Context;
+
 /* -------------------------------------------------------------------- */
 /** \name Space Defines (eSpace_Type)
  * \{ */
diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c
index db36909d2f9..63600571c0d 100644
--- a/source/blender/makesrna/intern/rna_space.c
+++ b/source/blender/makesrna/intern/rna_space.c
@@ -26,6 +26,7 @@
 #include "BLT_translation.h"
 
 #include "BKE_attribute.h"
+#include "BKE_context.h"
 #include "BKE_geometry_set.h"
 #include "BKE_image.h"
 #include "BKE_key.h"
@@ -3003,17 +3004,33 @@ static void rna_SpaceSpreadsheet_geometry_component_type_update(Main *UNUSED(bma
   }
 }
 
-const EnumPropertyItem *rna_SpaceSpreadsheet_attribute_domain_itemf(bContext *UNUSED(C),
+const EnumPropertyItem *rna_SpaceSpreadsheet_attribute_domain_itemf(bContext *C,
                                                                     PointerRNA *ptr,
                                                                     PropertyRNA *UNUSED(prop),
                                                                     bool *r_free)
 {
   SpaceSpreadsheet *sspreadsheet = (SpaceSpreadsheet *)ptr->data;
+  GeometryComponentType component_type = sspreadsheet->geometry_component_type;
+  if (sspreadsheet->object_eval_state == SPREADSHEET_OBJECT_EVAL_STATE_ORIGINAL) {
+    Object *active_object = CTX_data_active_object(C);
+    Object *used_object = (sspreadsheet->pinned_id && GS(sspreadsheet->pinned_id->name) == ID_OB) ?
+                              (Object *)sspreadsheet->pinned_id :
+                              active_object;
+    if (used_object != NULL) {
+      if (used_object->type == OB_POINTCLOUD) {
+        component_type = GEO_COMPONENT_TYPE_POINT_CLOUD;
+      }
+      else {
+        component_type = GEO_COMPONENT_TYPE_MESH;
+      }
+    }
+  }
+
   EnumPropertyItem *item_array = NULL;
   int items_len = 0;
   for (const EnumPropertyItem *item = rna_enum_attribute_domain_items; item->identifier != NULL;
        item++) {
-    if (sspreadsheet->geometry_component_type == GEO_COMPONENT_TYPE_MESH) {
+    if (component_type == GEO_COMPONENT_TYPE_MESH) {
       if (!ELEM(item->value,
                 ATTR_DOMAIN_CORNER,
                 ATTR_DOMAIN_EDGE,
@@ -3022,7 +3039,7 @@ const EnumPropertyItem *rna_SpaceSpreadsheet_attribute_domain_itemf(bContext *UN
         continue;
       }
     }
-    if (sspreadsheet->geometry_component_type == GEO_COMPONENT_TYPE_POINT_CLOUD) {
+    if (component_type == GEO_COMPONENT_TYPE_POINT_CLOUD) {
       if (item->value != ATTR_DOMAIN_POINT) {
         continue;
       }
@@ -7254,6 +7271,20 @@ static void rna_def_space_spreadsheet(BlenderRNA *brna)
       {0, NULL, 0, NULL, NULL},
   };
 
+  static const EnumPropertyItem object_eval_state_items[] = {
+      {SPREADSHEET_OBJECT_EVAL_STATE_FINAL,
+       "FINAL",
+       ICON_NONE,
+       "Final",
+       "Use data from ob

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list