diff --git a/source/blender/blenkernel/BKE_instances.hh b/source/blender/blenkernel/BKE_instances.hh index 82eb4e6c5d1..edbfece0627 100644 --- a/source/blender/blenkernel/BKE_instances.hh +++ b/source/blender/blenkernel/BKE_instances.hh @@ -86,6 +86,16 @@ class InstanceReference { GeometrySet &geometry_set(); const GeometrySet &geometry_set() const; + /** + * Converts the instance reference to a geometry set, even if it was an object or collection + * before. + * + * \note Uses out-parameter to be able to use #GeometrySet forward declaration. + */ + void to_geometry_set(GeometrySet &r_geometry_set) const; + + std::string name() const; + bool owns_direct_data() const; void ensure_owns_direct_data(); diff --git a/source/blender/blenkernel/intern/instances.cc b/source/blender/blenkernel/intern/instances.cc index 6319bd74092..e64f829f268 100644 --- a/source/blender/blenkernel/intern/instances.cc +++ b/source/blender/blenkernel/intern/instances.cc @@ -3,13 +3,20 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ #include "BLI_array_utils.hh" +#include "BLI_listbase.h" #include "BLI_rand.hh" #include "BLI_task.hh" +#include "DNA_collection_types.h" +#include "DNA_object_types.h" + #include "BKE_customdata.hh" #include "BKE_geometry_set.hh" +#include "BKE_geometry_set_instances.hh" #include "BKE_instances.hh" +#include "BLT_translation.hh" + namespace blender::bke { InstanceReference::InstanceReference(GeometrySet geometry_set) @@ -35,6 +42,67 @@ bool InstanceReference::owns_direct_data() const return geometry_set_->owns_direct_data(); } +static void convert_collection_to_instances(const Collection &collection, + bke::Instances &instances) +{ + LISTBASE_FOREACH (CollectionChild *, collection_child, &collection.children) { + float4x4 transform = float4x4::identity(); + transform.location() += float3(collection_child->collection->instance_offset); + transform.location() -= float3(collection.instance_offset); + const int handle = instances.add_reference(*collection_child->collection); + instances.add_instance(handle, transform); + } + + LISTBASE_FOREACH (CollectionObject *, collection_object, &collection.gobject) { + float4x4 transform = float4x4::identity(); + transform.location() -= float3(collection.instance_offset); + transform *= (collection_object->ob)->object_to_world(); + const int handle = instances.add_reference(*collection_object->ob); + instances.add_instance(handle, transform); + } +} + +void InstanceReference::to_geometry_set(GeometrySet &r_geometry_set) const +{ + r_geometry_set.clear(); + switch (type_) { + case Type::Object: { + const Object &object = this->object(); + r_geometry_set = bke::object_get_evaluated_geometry_set(object); + break; + } + case Type::Collection: { + const Collection &collection = this->collection(); + std::unique_ptr instances_ptr = std::make_unique(); + convert_collection_to_instances(collection, *instances_ptr); + r_geometry_set.replace_instances(instances_ptr.release()); + break; + } + case Type::GeometrySet: { + r_geometry_set = this->geometry_set(); + break; + } + case Type::None: { + break; + } + } +} + +std::string InstanceReference::name() const +{ + switch (type_) { + case Type::Object: + return this->object().id.name + 2; + case Type::Collection: + return this->collection().id.name + 2; + case Type::GeometrySet: + return IFACE_("Geometry"); + case Type::None: + break; + } + return ""; +} + bool operator==(const InstanceReference &a, const InstanceReference &b) { if (a.geometry_set_ && b.geometry_set_) { diff --git a/source/blender/editors/include/ED_outliner.hh b/source/blender/editors/include/ED_outliner.hh index 49b6c6fff19..b2aee00f556 100644 --- a/source/blender/editors/include/ED_outliner.hh +++ b/source/blender/editors/include/ED_outliner.hh @@ -12,6 +12,7 @@ struct Base; struct ListBase; struct SpaceOutliner; struct bContext; +struct ID; bool ED_outliner_collections_editor_poll(bContext *C); @@ -47,3 +48,5 @@ void ED_outliner_select_sync_from_outliner(bContext *C, SpaceOutliner *space_out * Copy sync select dirty flag from window manager to all outliners to be synced lazily on draw. */ void ED_outliner_select_sync_flag_outliners(const bContext *C); + +int ED_outliner_icon_from_id(const ID &id); diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc index f163d50f4c5..d8207aa2177 100644 --- a/source/blender/editors/space_outliner/outliner_draw.cc +++ b/source/blender/editors/space_outliner/outliner_draw.cc @@ -4130,3 +4130,8 @@ void draw_outliner(const bContext *C) /** \} */ } // namespace blender::ed::outliner + +int ED_outliner_icon_from_id(const ID &id) +{ + return blender::ed::outliner::tree_element_get_icon_from_id(&id); +} diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc index cb47f3c888b..47e59b11803 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.cc @@ -32,6 +32,7 @@ #include "DEG_depsgraph_query.hh" #include "ED_curves.hh" +#include "ED_outliner.hh" #include "ED_spreadsheet.hh" #include "NOD_geometry_nodes_lazy_function.hh" @@ -42,6 +43,8 @@ #include "RNA_access.hh" #include "RNA_enum_types.hh" +#include "UI_resources.hh" + #include "bmesh.hh" #include "spreadsheet_data_source_geometry.hh" @@ -545,6 +548,26 @@ int VolumeDataSource::tot_rows() const return BKE_volume_num_grids(volume); } +int get_instance_reference_icon(const bke::InstanceReference &reference) +{ + switch (reference.type()) { + case bke::InstanceReference::Type::Object: { + const Object &object = reference.object(); + return ED_outliner_icon_from_id(object.id); + } + case bke::InstanceReference::Type::Collection: { + return ICON_OUTLINER_COLLECTION; + } + case bke::InstanceReference::Type::GeometrySet: { + return ICON_EMPTY_AXIS; + } + case bke::InstanceReference::Type::None: { + break; + } + } + return ICON_NONE; +} + bke::GeometrySet spreadsheet_get_display_geometry_set(const SpaceSpreadsheet *sspreadsheet, Object *object_eval) { diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh index 592c1e6958e..0fa25b7d360 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh +++ b/source/blender/editors/space_spreadsheet/spreadsheet_data_source_geometry.hh @@ -9,6 +9,7 @@ #include "BLI_resource_scope.hh" #include "BKE_geometry_set.hh" +#include "BKE_instances.hh" #include "spreadsheet_data_source.hh" @@ -109,6 +110,8 @@ class VolumeDataSource : public DataSource { int tot_rows() const override; }; +int get_instance_reference_icon(const bke::InstanceReference &reference); + std::unique_ptr data_source_from_geometry(const bContext *C, Object *object_eval); } // namespace blender::ed::spreadsheet diff --git a/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc b/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc index 08abb6b96be..f876f0e7458 100644 --- a/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc +++ b/source/blender/editors/space_spreadsheet/spreadsheet_layout.cc @@ -15,6 +15,7 @@ #include "BKE_instances.hh" #include "spreadsheet_column_values.hh" +#include "spreadsheet_data_source_geometry.hh" #include "spreadsheet_layout.hh" #include "DNA_collection_types.h" @@ -203,60 +204,22 @@ class SpreadsheetLayoutDrawer : public SpreadsheetDrawer { } else if (data.type().is()) { const bke::InstanceReference value = data.get(real_index); - switch (value.type()) { - case bke::InstanceReference::Type::Object: { - const Object &object = value.object(); - uiDefIconTextBut(params.block, - UI_BTYPE_LABEL, - 0, - ICON_OBJECT_DATA, - object.id.name + 2, - params.xmin, - params.ymin, - params.width, - params.height, - nullptr, - 0, - 0, - nullptr); - break; - } - case bke::InstanceReference::Type::Collection: { - Collection &collection = value.collection(); - uiDefIconTextBut(params.block, - UI_BTYPE_LABEL, - 0, - ICON_OUTLINER_COLLECTION, - collection.id.name + 2, - params.xmin, - params.ymin, - params.width, - params.height, - nullptr, - 0, - 0, - nullptr); - break; - } - case bke::InstanceReference::Type::GeometrySet: { - uiDefIconTextBut(params.block, - UI_BTYPE_LABEL, - 0, - ICON_MESH_DATA, - "Geometry", - params.xmin, - params.ymin, - params.width, - params.height, - nullptr, - 0, - 0, - nullptr); - break; - } - case bke::InstanceReference::Type::None: { - break; - } + const std::string name = value.name(); + const int icon = get_instance_reference_icon(value); + if (!name.empty()) { + uiDefIconTextBut(params.block, + UI_BTYPE_LABEL, + 0, + icon, + name.c_str(), + params.xmin, + params.ymin, + params.width, + params.height, + nullptr, + 0, + 0, + nullptr); } } else if (data.type().is()) { diff --git a/source/blender/geometry/intern/realize_instances.cc b/source/blender/geometry/intern/realize_instances.cc index 4bc8b9e1a63..c666dff52f3 100644 --- a/source/blender/geometry/intern/realize_instances.cc +++ b/source/blender/geometry/intern/realize_instances.cc @@ -320,25 +320,6 @@ static int64_t get_final_points_num(const GatherTasks &tasks) return points_num; } -static void realize_collections(Collection &collection, bke::Instances &instances) -{ - LISTBASE_FOREACH (CollectionChild *, collection_child, &collection.children) { - float4x4 transform = float4x4::identity(); - transform.location() += float3(collection_child->collection->instance_offset); - transform.location() -= float3(collection.instance_offset); - const int handle = instances.add_reference(*collection_child->collection); - instances.add_instance(handle, transform); - } - - LISTBASE_FOREACH (CollectionObject *, collection_object, &collection.gobject) { - float4x4 transform = float4x4::identity(); - transform.location() -= float3(collection.instance_offset); - transform *= (collection_object->ob)->object_to_world(); - const int handle = instances.add_reference(*collection_object->ob); - instances.add_instance(handle, transform); - } -} - static void copy_transformed_positions(const Span src, const float4x4 &transform, MutableSpan dst) @@ -500,33 +481,6 @@ static Vector> prepare_attribute_fallbacks( return attributes_to_override; } -static bke::GeometrySet geometry_set_from_reference(const InstanceReference &reference) -{ - switch (reference.type()) { - case InstanceReference::Type::Object: { - const Object &object = reference.object(); - const bke::GeometrySet geometry_set = bke::object_get_evaluated_geometry_set(object); - return geometry_set; - } - case InstanceReference::Type::Collection: { - std::unique_ptr instances_ptr = std::make_unique(); - realize_collections(reference.collection(), *instances_ptr); - bke::GeometrySet geometry_set; - geometry_set.replace_instances(instances_ptr.release()); - return geometry_set; - } - case InstanceReference::Type::GeometrySet: { - const bke::GeometrySet geometry_set = reference.geometry_set(); - return geometry_set; - } - case InstanceReference::Type::None: { - /* Return an empty GeometrySet for None type. */ - return {}; - } - } - return {}; -} - /** * Calls #fn for every geometry in the given #InstanceReference. Also passes on the transformation * that is applied to every instance. @@ -538,7 +492,8 @@ static void foreach_geometry_in_reference( FunctionRef fn) { - bke::GeometrySet geometry_set = geometry_set_from_reference(reference); + bke::GeometrySet geometry_set; + reference.to_geometry_set(geometry_set); fn(geometry_set, base_transform, id); } @@ -770,8 +725,10 @@ static bool attribute_foreach(const bke::GeometrySet &geometry_set, IndexMask(IndexRange(instances.instances_num())); indices.foreach_index([&](const int i) { const int child_depth_target = (0 == current_depth) ? instance_depth[i] : depth_target; - bke::GeometrySet instance_geometry_set = geometry_set_from_reference( - instances.references()[instances.reference_handles()[i]]); + const bke::InstanceReference &reference = + instances.references()[instances.reference_handles()[i]]; + bke::GeometrySet instance_geometry_set; + reference.to_geometry_set(instance_geometry_set); /* Process child instances with a recursive call. */ if (current_depth != child_depth_target) { child_has_component = child_has_component | attribute_foreach(instance_geometry_set,