Geometry Nodes: simplify retrieving data of instance reference
Specifically it's now easier to get the name, geometry set and icon.
This commit is contained in:
parent
406554c11e
commit
7bce839e25
@ -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();
|
||||
|
||||
|
@ -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<bke::Instances> instances_ptr = std::make_unique<bke::Instances>();
|
||||
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_) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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<DataSource> data_source_from_geometry(const bContext *C, Object *object_eval);
|
||||
|
||||
} // namespace blender::ed::spreadsheet
|
||||
|
@ -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<bke::InstanceReference>()) {
|
||||
const bke::InstanceReference value = data.get<bke::InstanceReference>(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<std::string>()) {
|
||||
|
@ -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<float3> src,
|
||||
const float4x4 &transform,
|
||||
MutableSpan<float3> dst)
|
||||
@ -500,33 +481,6 @@ static Vector<std::pair<int, GSpan>> 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<bke::Instances> instances_ptr = std::make_unique<bke::Instances>();
|
||||
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<void(const bke::GeometrySet &geometry_set, const float4x4 &transform, uint32_t id)>
|
||||
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,
|
||||
|
Loading…
Reference in New Issue
Block a user