Compare commits
9 Commits
temp-linux
...
temp-scale
Author | SHA1 | Date | |
---|---|---|---|
0375b51776 | |||
32e8381e0e | |||
c31a346ec5 | |||
00c5fa3bf1 | |||
2f6a84bee9 | |||
f9e03a5e16 | |||
abaed315d5 | |||
05a7f7c1fd | |||
7e3459ff78 |
@@ -149,6 +149,7 @@ def mesh_node_items(context):
|
|||||||
yield NodeItem("GeometryNodeSubdivideMesh")
|
yield NodeItem("GeometryNodeSubdivideMesh")
|
||||||
yield NodeItem("GeometryNodeSubdivisionSurface")
|
yield NodeItem("GeometryNodeSubdivisionSurface")
|
||||||
yield NodeItem("GeometryNodeTriangulate")
|
yield NodeItem("GeometryNodeTriangulate")
|
||||||
|
yield NodeItem("GeometryNodeScaleElements")
|
||||||
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
|
yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
|
||||||
yield NodeItem("GeometryNodeInputMeshEdgeAngle")
|
yield NodeItem("GeometryNodeInputMeshEdgeAngle")
|
||||||
yield NodeItem("GeometryNodeInputMeshEdgeNeighbors")
|
yield NodeItem("GeometryNodeInputMeshEdgeNeighbors")
|
||||||
|
@@ -1710,6 +1710,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
|
|||||||
#define GEO_NODE_INPUT_SCENE_TIME 1145
|
#define GEO_NODE_INPUT_SCENE_TIME 1145
|
||||||
#define GEO_NODE_ACCUMULATE_FIELD 1146
|
#define GEO_NODE_ACCUMULATE_FIELD 1146
|
||||||
#define GEO_NODE_INPUT_MESH_EDGE_ANGLE 1147
|
#define GEO_NODE_INPUT_MESH_EDGE_ANGLE 1147
|
||||||
|
#define GEO_NODE_SCALE_ELEMENTS 1148
|
||||||
|
|
||||||
/** \} */
|
/** \} */
|
||||||
|
|
||||||
|
@@ -4970,6 +4970,7 @@ static void registerGeometryNodes()
|
|||||||
register_node_type_geo_realize_instances();
|
register_node_type_geo_realize_instances();
|
||||||
register_node_type_geo_rotate_instances();
|
register_node_type_geo_rotate_instances();
|
||||||
register_node_type_geo_sample_texture();
|
register_node_type_geo_sample_texture();
|
||||||
|
register_node_type_geo_scale_elements();
|
||||||
register_node_type_geo_scale_instances();
|
register_node_type_geo_scale_instances();
|
||||||
register_node_type_geo_separate_components();
|
register_node_type_geo_separate_components();
|
||||||
register_node_type_geo_separate_geometry();
|
register_node_type_geo_separate_geometry();
|
||||||
|
@@ -30,6 +30,7 @@ class DisjointSet {
|
|||||||
private:
|
private:
|
||||||
Array<int64_t> parents_;
|
Array<int64_t> parents_;
|
||||||
Array<int64_t> ranks_;
|
Array<int64_t> ranks_;
|
||||||
|
bool all_roots_ensured_ = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
@@ -49,6 +50,8 @@ class DisjointSet {
|
|||||||
*/
|
*/
|
||||||
void join(int64_t x, int64_t y)
|
void join(int64_t x, int64_t y)
|
||||||
{
|
{
|
||||||
|
BLI_assert_msg(!all_roots_ensured_, "Cannot join after `ensure_all_roots` has been called.");
|
||||||
|
|
||||||
int64_t root1 = this->find_root(x);
|
int64_t root1 = this->find_root(x);
|
||||||
int64_t root2 = this->find_root(y);
|
int64_t root2 = this->find_root(y);
|
||||||
|
|
||||||
@@ -98,6 +101,16 @@ class DisjointSet {
|
|||||||
|
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Span<int64_t> ensure_all_roots()
|
||||||
|
{
|
||||||
|
for (const int64_t i : parents_.index_range()) {
|
||||||
|
/* Updates `parents_` when doing path compression. */
|
||||||
|
this->find_root(i);
|
||||||
|
}
|
||||||
|
all_roots_ensured_ = true;
|
||||||
|
return parents_;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace blender
|
} // namespace blender
|
||||||
|
@@ -2315,6 +2315,12 @@ typedef enum GeometryNodeRealizeInstancesFlag {
|
|||||||
GEO_NODE_REALIZE_INSTANCES_LEGACY_BEHAVIOR = (1 << 0),
|
GEO_NODE_REALIZE_INSTANCES_LEGACY_BEHAVIOR = (1 << 0),
|
||||||
} GeometryNodeRealizeInstancesFlag;
|
} GeometryNodeRealizeInstancesFlag;
|
||||||
|
|
||||||
|
typedef enum GeometryNodeScaleElementsMode {
|
||||||
|
GEO_NODE_SCALE_ELEMENTS_MODE_FACE = 0,
|
||||||
|
GEO_NODE_SCALE_ELEMENTS_MODE_EDGE = 1,
|
||||||
|
GEO_NODE_SCALE_ELEMENTS_MODE_CURVE = 2,
|
||||||
|
} GeometryNodeScaleElementsMode;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -11287,6 +11287,33 @@ static void def_geo_realize_instances(StructRNA *srna)
|
|||||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_GeometryNode_socket_update");
|
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_GeometryNode_socket_update");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void def_geo_scale_elements(StructRNA *srna)
|
||||||
|
{
|
||||||
|
PropertyRNA *prop;
|
||||||
|
|
||||||
|
static const EnumPropertyItem scale_elements_mode_items[] = {
|
||||||
|
{GEO_NODE_SCALE_ELEMENTS_MODE_FACE,
|
||||||
|
"FACE",
|
||||||
|
ICON_NONE,
|
||||||
|
"Face",
|
||||||
|
"Scale individual faces or neighbouring face islands"},
|
||||||
|
{GEO_NODE_SCALE_ELEMENTS_MODE_EDGE,
|
||||||
|
"EDGE",
|
||||||
|
ICON_NONE,
|
||||||
|
"Edge",
|
||||||
|
"Scale individual edges or neighbouring edge islands"},
|
||||||
|
{GEO_NODE_SCALE_ELEMENTS_MODE_CURVE, "CURVE", ICON_NONE, "Curve", "Scale individual curves"},
|
||||||
|
{0, NULL, 0, NULL, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_sdna(prop, NULL, "custom1");
|
||||||
|
RNA_def_property_enum_items(prop, scale_elements_mode_items);
|
||||||
|
RNA_def_property_enum_default(prop, GEO_NODE_SCALE_ELEMENTS_MODE_FACE);
|
||||||
|
RNA_def_property_ui_text(prop, "Mode", "Element type to transform");
|
||||||
|
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_GeometryNode_socket_update");
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static void rna_def_shader_node(BlenderRNA *brna)
|
static void rna_def_shader_node(BlenderRNA *brna)
|
||||||
|
@@ -153,6 +153,7 @@ void register_node_type_geo_raycast(void);
|
|||||||
void register_node_type_geo_realize_instances(void);
|
void register_node_type_geo_realize_instances(void);
|
||||||
void register_node_type_geo_rotate_instances(void);
|
void register_node_type_geo_rotate_instances(void);
|
||||||
void register_node_type_geo_sample_texture(void);
|
void register_node_type_geo_sample_texture(void);
|
||||||
|
void register_node_type_geo_scale_elements(void);
|
||||||
void register_node_type_geo_scale_instances(void);
|
void register_node_type_geo_scale_instances(void);
|
||||||
void register_node_type_geo_select_by_handle_type(void);
|
void register_node_type_geo_select_by_handle_type(void);
|
||||||
void register_node_type_geo_separate_components(void);
|
void register_node_type_geo_separate_components(void);
|
||||||
|
@@ -402,6 +402,7 @@ DefNode(GeometryNode, GEO_NODE_RESAMPLE_CURVE, def_geo_curve_resample, "RESAMPLE
|
|||||||
DefNode(GeometryNode, GEO_NODE_REVERSE_CURVE, 0, "REVERSE_CURVE", ReverseCurve, "Reverse Curve", "")
|
DefNode(GeometryNode, GEO_NODE_REVERSE_CURVE, 0, "REVERSE_CURVE", ReverseCurve, "Reverse Curve", "")
|
||||||
DefNode(GeometryNode, GEO_NODE_ROTATE_INSTANCES, 0, "ROTATE_INSTANCES", RotateInstances, "Rotate Instances", "")
|
DefNode(GeometryNode, GEO_NODE_ROTATE_INSTANCES, 0, "ROTATE_INSTANCES", RotateInstances, "Rotate Instances", "")
|
||||||
DefNode(GeometryNode, GEO_NODE_SAMPLE_CURVE, def_geo_curve_sample, "SAMPLE_CURVE", SampleCurve, "Sample Curve", "")
|
DefNode(GeometryNode, GEO_NODE_SAMPLE_CURVE, def_geo_curve_sample, "SAMPLE_CURVE", SampleCurve, "Sample Curve", "")
|
||||||
|
DefNode(GeometryNode, GEO_NODE_SCALE_ELEMENTS, def_geo_scale_elements, "SCALE_ELEMENTS", ScaleElements, "Scale Elements", "")
|
||||||
DefNode(GeometryNode, GEO_NODE_SCALE_INSTANCES, 0, "SCALE_INSTANCES", ScaleInstances, "Scale Instances", "")
|
DefNode(GeometryNode, GEO_NODE_SCALE_INSTANCES, 0, "SCALE_INSTANCES", ScaleInstances, "Scale Instances", "")
|
||||||
DefNode(GeometryNode, GEO_NODE_SEPARATE_COMPONENTS, 0, "SEPARATE_COMPONENTS", SeparateComponents, "Separate Components", "")
|
DefNode(GeometryNode, GEO_NODE_SEPARATE_COMPONENTS, 0, "SEPARATE_COMPONENTS", SeparateComponents, "Separate Components", "")
|
||||||
DefNode(GeometryNode, GEO_NODE_SEPARATE_GEOMETRY, def_geo_separate_geometry, "SEPARATE_GEOMETRY", SeparateGeometry, "Separate Geometry", "")
|
DefNode(GeometryNode, GEO_NODE_SEPARATE_GEOMETRY, def_geo_separate_geometry, "SEPARATE_GEOMETRY", SeparateGeometry, "Separate Geometry", "")
|
||||||
|
@@ -164,6 +164,7 @@ set(SRC
|
|||||||
nodes/node_geo_raycast.cc
|
nodes/node_geo_raycast.cc
|
||||||
nodes/node_geo_realize_instances.cc
|
nodes/node_geo_realize_instances.cc
|
||||||
nodes/node_geo_rotate_instances.cc
|
nodes/node_geo_rotate_instances.cc
|
||||||
|
nodes/node_geo_scale_elements.cc
|
||||||
nodes/node_geo_scale_instances.cc
|
nodes/node_geo_scale_instances.cc
|
||||||
nodes/node_geo_separate_components.cc
|
nodes/node_geo_separate_components.cc
|
||||||
nodes/node_geo_separate_geometry.cc
|
nodes/node_geo_separate_geometry.cc
|
||||||
|
201
source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc
Normal file
201
source/blender/nodes/geometry/nodes/node_geo_scale_elements.cc
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "BLI_disjoint_set.hh"
|
||||||
|
#include "BLI_task.hh"
|
||||||
|
|
||||||
|
#include "DNA_mesh_types.h"
|
||||||
|
#include "DNA_meshdata_types.h"
|
||||||
|
|
||||||
|
#include "node_geometry_util.hh"
|
||||||
|
|
||||||
|
namespace blender::nodes::node_geo_scale_elements_cc {
|
||||||
|
|
||||||
|
static void node_declare(NodeDeclarationBuilder &b)
|
||||||
|
{
|
||||||
|
b.add_input<decl::Geometry>(N_("Geometry")).supported_type(GEO_COMPONENT_TYPE_MESH);
|
||||||
|
b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
|
||||||
|
b.add_input<decl::Vector>(N_("Scale")).default_value({1.0f, 1.0f, 1.0f}).supports_field();
|
||||||
|
b.add_input<decl::Vector>(N_("Pivot")).subtype(PROP_TRANSLATION).implicit_field();
|
||||||
|
b.add_input<decl::Vector>(N_("X Axis")).default_value({1.0f, 0.0f, 0.0f}).supports_field();
|
||||||
|
b.add_input<decl::Vector>(N_("Up")).default_value({0.0f, 0.0f, 1.0f}).supports_field();
|
||||||
|
b.add_output<decl::Geometry>(N_("Geometry"));
|
||||||
|
};
|
||||||
|
|
||||||
|
struct InputFields {
|
||||||
|
Field<bool> selection;
|
||||||
|
Field<float3> scale;
|
||||||
|
Field<float3> pivot;
|
||||||
|
Field<float3> x_axis;
|
||||||
|
Field<float3> up;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void scale_faces(MeshComponent &mesh_component, const InputFields &input_fields)
|
||||||
|
{
|
||||||
|
Mesh *mesh = mesh_component.get_for_write();
|
||||||
|
mesh->mvert = static_cast<MVert *>(
|
||||||
|
CustomData_duplicate_referenced_layer(&mesh->vdata, CD_MVERT, mesh->totvert));
|
||||||
|
|
||||||
|
GeometryComponentFieldContext field_context{mesh_component, ATTR_DOMAIN_FACE};
|
||||||
|
FieldEvaluator evaluator{field_context, mesh->totpoly};
|
||||||
|
evaluator.set_selection(input_fields.selection);
|
||||||
|
VArray<float3> scales;
|
||||||
|
VArray<float3> pivots;
|
||||||
|
VArray<float3> x_axis_vectors;
|
||||||
|
VArray<float3> up_vectors;
|
||||||
|
evaluator.add(input_fields.scale, &scales);
|
||||||
|
evaluator.add(input_fields.pivot, &pivots);
|
||||||
|
evaluator.add(input_fields.x_axis, &x_axis_vectors);
|
||||||
|
evaluator.add(input_fields.up, &up_vectors);
|
||||||
|
evaluator.evaluate();
|
||||||
|
const IndexMask selection = evaluator.get_evaluated_selection_as_mask();
|
||||||
|
|
||||||
|
DisjointSet disjoint_set(mesh->totvert);
|
||||||
|
for (const int poly_index : selection) {
|
||||||
|
const MPoly &poly = mesh->mpoly[poly_index];
|
||||||
|
const Span<MLoop> poly_loops{mesh->mloop + poly.loopstart, poly.totloop};
|
||||||
|
for (const int loop_index : IndexRange(poly.totloop - 1)) {
|
||||||
|
const int v1 = poly_loops[loop_index].v;
|
||||||
|
const int v2 = poly_loops[loop_index + 1].v;
|
||||||
|
disjoint_set.join(v1, v2);
|
||||||
|
}
|
||||||
|
disjoint_set.join(poly_loops.first().v, poly_loops.last().v);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Span<int64_t> group_by_vertex_index = disjoint_set.ensure_all_roots();
|
||||||
|
|
||||||
|
struct GroupData {
|
||||||
|
float3 scale = {0.0f, 0.0f, 0.0f};
|
||||||
|
float3 pivot = {0.0f, 0.0f, 0.0f};
|
||||||
|
float3 x_axis = {0.0f, 0.0f, 0.0f};
|
||||||
|
float3 up = {0.0f, 0.0f, 0.0f};
|
||||||
|
int tot_faces = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const int group_amount = mesh->totvert;
|
||||||
|
Array<GroupData> groups_data(group_amount);
|
||||||
|
for (const int poly_index : selection) {
|
||||||
|
const MPoly &poly = mesh->mpoly[poly_index];
|
||||||
|
const int first_vertex = mesh->mloop[poly.loopstart].v;
|
||||||
|
const int group_index = group_by_vertex_index[first_vertex];
|
||||||
|
GroupData &group_info = groups_data[group_index];
|
||||||
|
group_info.pivot += pivots[poly_index];
|
||||||
|
group_info.scale += scales[poly_index];
|
||||||
|
group_info.x_axis += x_axis_vectors[poly_index];
|
||||||
|
group_info.up += up_vectors[poly_index];
|
||||||
|
group_info.tot_faces++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Array<float4x4> transforms(group_amount);
|
||||||
|
threading::parallel_for(IndexRange(mesh->totvert), 1024, [&](const IndexRange range) {
|
||||||
|
for (const int vert_index : range) {
|
||||||
|
GroupData &group_data = groups_data[vert_index];
|
||||||
|
if (group_data.tot_faces == 0) {
|
||||||
|
transforms[vert_index] = float4x4::identity();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float f = 1.0f / group_data.tot_faces;
|
||||||
|
group_data.scale *= f;
|
||||||
|
group_data.pivot *= f;
|
||||||
|
|
||||||
|
const float3 x_axis = group_data.x_axis.normalized();
|
||||||
|
const float3 y_axis = -float3::cross(x_axis, group_data.up).normalized();
|
||||||
|
const float3 z_axis = float3::cross(x_axis, y_axis);
|
||||||
|
|
||||||
|
const float3 pivot = group_data.pivot;
|
||||||
|
|
||||||
|
float4x4 &transform = transforms[vert_index];
|
||||||
|
unit_m4(transform.values);
|
||||||
|
sub_v3_v3(transform.values[3], pivot);
|
||||||
|
|
||||||
|
float4x4 axis_transform;
|
||||||
|
unit_m4(axis_transform.values);
|
||||||
|
copy_v3_v3(axis_transform.values[0], x_axis);
|
||||||
|
copy_v3_v3(axis_transform.values[1], y_axis);
|
||||||
|
copy_v3_v3(axis_transform.values[2], z_axis);
|
||||||
|
|
||||||
|
float4x4 axis_transform_inv = axis_transform.transposed();
|
||||||
|
|
||||||
|
float4x4 scale_transform;
|
||||||
|
unit_m4(scale_transform.values);
|
||||||
|
scale_transform.values[0][0] = group_data.scale.x;
|
||||||
|
scale_transform.values[1][1] = group_data.scale.y;
|
||||||
|
scale_transform.values[2][2] = group_data.scale.z;
|
||||||
|
|
||||||
|
transform = axis_transform * scale_transform * axis_transform_inv * transform;
|
||||||
|
add_v3_v3(transform.values[3], pivot);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
threading::parallel_for(IndexRange(mesh->totvert), 1024, [&](const IndexRange range) {
|
||||||
|
for (const int vert_index : range) {
|
||||||
|
const int group_index = group_by_vertex_index[vert_index];
|
||||||
|
MVert &vert = mesh->mvert[vert_index];
|
||||||
|
const float3 old_position = vert.co;
|
||||||
|
const float3 new_position = transforms[group_index] * old_position;
|
||||||
|
copy_v3_v3(vert.co, new_position);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void node_geo_exec(GeoNodeExecParams params)
|
||||||
|
{
|
||||||
|
const GeometryNodeScaleElementsMode mode = static_cast<GeometryNodeScaleElementsMode>(
|
||||||
|
params.node().custom1);
|
||||||
|
|
||||||
|
GeometrySet geometry = params.extract_input<GeometrySet>("Geometry");
|
||||||
|
InputFields input_fields;
|
||||||
|
input_fields.selection = params.get_input<Field<bool>>("Selection");
|
||||||
|
input_fields.scale = params.get_input<Field<float3>>("Scale");
|
||||||
|
input_fields.pivot = params.get_input<Field<float3>>("Pivot");
|
||||||
|
input_fields.x_axis = params.get_input<Field<float3>>("X Axis");
|
||||||
|
input_fields.up = params.get_input<Field<float3>>("Up");
|
||||||
|
|
||||||
|
geometry.modify_geometry_sets([&](GeometrySet &geometry) {
|
||||||
|
switch (mode) {
|
||||||
|
case GEO_NODE_SCALE_ELEMENTS_MODE_FACE: {
|
||||||
|
if (geometry.has_mesh()) {
|
||||||
|
MeshComponent &mesh_component = geometry.get_component_for_write<MeshComponent>();
|
||||||
|
scale_faces(mesh_component, input_fields);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GEO_NODE_SCALE_ELEMENTS_MODE_EDGE: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GEO_NODE_SCALE_ELEMENTS_MODE_CURVE: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
params.set_output("Geometry", std::move(geometry));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace blender::nodes::node_geo_scale_elements_cc
|
||||||
|
|
||||||
|
void register_node_type_geo_scale_elements()
|
||||||
|
{
|
||||||
|
namespace file_ns = blender::nodes::node_geo_scale_elements_cc;
|
||||||
|
|
||||||
|
static bNodeType ntype;
|
||||||
|
|
||||||
|
geo_node_type_base(&ntype, GEO_NODE_SCALE_ELEMENTS, "Scale Elements", NODE_CLASS_GEOMETRY);
|
||||||
|
ntype.geometry_node_execute = file_ns::node_geo_exec;
|
||||||
|
ntype.declare = file_ns::node_declare;
|
||||||
|
nodeRegisterType(&ntype);
|
||||||
|
}
|
@@ -59,7 +59,7 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||||||
const NodeGeometrySeparateGeometry &storage = node_storage(params.node());
|
const NodeGeometrySeparateGeometry &storage = node_storage(params.node());
|
||||||
const AttributeDomain domain = static_cast<AttributeDomain>(storage.domain);
|
const AttributeDomain domain = static_cast<AttributeDomain>(storage.domain);
|
||||||
|
|
||||||
auto separate_geometry_maybe_recursively = [&](bool invert) {
|
auto separate_geometry_maybe_recursively = [&](GeometrySet &geometry_set, bool invert) {
|
||||||
bool is_error;
|
bool is_error;
|
||||||
if (domain == ATTR_DOMAIN_INSTANCE) {
|
if (domain == ATTR_DOMAIN_INSTANCE) {
|
||||||
/* Only delete top level instances. */
|
/* Only delete top level instances. */
|
||||||
@@ -84,11 +84,11 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||||||
|
|
||||||
GeometrySet second_set(geometry_set);
|
GeometrySet second_set(geometry_set);
|
||||||
if (params.output_is_required("Selection")) {
|
if (params.output_is_required("Selection")) {
|
||||||
separate_geometry_maybe_recursively(false);
|
separate_geometry_maybe_recursively(geometry_set, false);
|
||||||
params.set_output("Selection", std::move(geometry_set));
|
params.set_output("Selection", std::move(geometry_set));
|
||||||
}
|
}
|
||||||
if (params.output_is_required("Inverted")) {
|
if (params.output_is_required("Inverted")) {
|
||||||
separate_geometry_maybe_recursively(true);
|
separate_geometry_maybe_recursively(second_set, true);
|
||||||
params.set_output("Inverted", std::move(second_set));
|
params.set_output("Inverted", std::move(second_set));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user