Fix: Geometry Nodes: crash when converting layers to instances
The crash/assert happened because the case when there are instances already was not handled. Pull Request: https://projects.blender.org/blender/blender/pulls/127299
This commit is contained in:
committed by
Jacques Lucke
parent
334e9be8f4
commit
74f98b1e92
@@ -658,6 +658,8 @@ class InstancesComponent : public GeometryComponent {
|
||||
|
||||
bool is_empty() const final;
|
||||
|
||||
Instances *release();
|
||||
|
||||
bool owns_direct_data() const override;
|
||||
void ensure_owns_direct_data() override;
|
||||
|
||||
|
||||
@@ -102,6 +102,14 @@ void InstancesComponent::replace(Instances *instances, GeometryOwnershipType own
|
||||
ownership_ = ownership;
|
||||
}
|
||||
|
||||
Instances *InstancesComponent::release()
|
||||
{
|
||||
BLI_assert(this->is_mutable());
|
||||
Instances *instance = instances_;
|
||||
instances_ = nullptr;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void InstancesComponent::count_memory(MemoryCounter &memory) const
|
||||
{
|
||||
if (instances_) {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "UI_resources.hh"
|
||||
|
||||
#include "GEO_join_geometries.hh"
|
||||
#include "GEO_randomize.hh"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
@@ -70,13 +71,7 @@ static void grease_pencil_to_mesh(GeometrySet &geometry_set,
|
||||
return;
|
||||
}
|
||||
|
||||
InstancesComponent &instances_component =
|
||||
geometry_set.get_component_for_write<InstancesComponent>();
|
||||
bke::Instances *instances = instances_component.get_for_write();
|
||||
if (instances == nullptr) {
|
||||
instances = new bke::Instances();
|
||||
instances_component.replace(instances);
|
||||
}
|
||||
bke::Instances *instances = new bke::Instances();
|
||||
for (Mesh *mesh : mesh_by_layer) {
|
||||
if (!mesh) {
|
||||
/* Add an empty reference so the number of layers and instances match.
|
||||
@@ -92,8 +87,14 @@ static void grease_pencil_to_mesh(GeometrySet &geometry_set,
|
||||
}
|
||||
GeometrySet::propagate_attributes_from_layer_to_instances(
|
||||
geometry_set.get_grease_pencil()->attributes(),
|
||||
geometry_set.get_instances_for_write()->attributes_for_write(),
|
||||
instances->attributes_for_write(),
|
||||
attribute_filter);
|
||||
InstancesComponent &dst_component = geometry_set.get_component_for_write<InstancesComponent>();
|
||||
GeometrySet new_instances = geometry::join_geometries(
|
||||
{GeometrySet::from_instances(dst_component.release()),
|
||||
GeometrySet::from_instances(instances)},
|
||||
attribute_filter);
|
||||
dst_component.replace(new_instances.get_component_for_write<InstancesComponent>().release());
|
||||
geometry_set.replace_grease_pencil(nullptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "BKE_instances.hh"
|
||||
#include "BKE_pointcloud.hh"
|
||||
|
||||
#include "GEO_join_geometries.hh"
|
||||
#include "GEO_resample_curves.hh"
|
||||
|
||||
#include "NOD_rna_define.hh"
|
||||
@@ -272,13 +273,7 @@ static void grease_pencil_to_points(GeometrySet &geometry_set,
|
||||
rotation_anonymous_id);
|
||||
}
|
||||
if (!pointcloud_by_layer.is_empty()) {
|
||||
InstancesComponent &instances_component =
|
||||
geometry_set.get_component_for_write<InstancesComponent>();
|
||||
bke::Instances *instances = instances_component.get_for_write();
|
||||
if (instances == nullptr) {
|
||||
instances = new bke::Instances();
|
||||
instances_component.replace(instances);
|
||||
}
|
||||
bke::Instances *instances = new bke::Instances();
|
||||
for (PointCloud *pointcloud : pointcloud_by_layer) {
|
||||
if (!pointcloud) {
|
||||
/* Add an empty reference so the number of layers and instances match.
|
||||
@@ -294,8 +289,15 @@ static void grease_pencil_to_points(GeometrySet &geometry_set,
|
||||
}
|
||||
GeometrySet::propagate_attributes_from_layer_to_instances(
|
||||
geometry.get_grease_pencil()->attributes(),
|
||||
geometry.get_instances_for_write()->attributes_for_write(),
|
||||
instances->attributes_for_write(),
|
||||
attribute_filter);
|
||||
InstancesComponent &dst_component = geometry.get_component_for_write<InstancesComponent>();
|
||||
GeometrySet new_instances = geometry::join_geometries(
|
||||
{GeometrySet::from_instances(dst_component.release()),
|
||||
GeometrySet::from_instances(instances)},
|
||||
attribute_filter);
|
||||
dst_component.replace(
|
||||
new_instances.get_component_for_write<InstancesComponent>().release());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include "BKE_grease_pencil.hh"
|
||||
#include "BKE_instances.hh"
|
||||
|
||||
#include "GEO_join_geometries.hh"
|
||||
|
||||
#include "node_geometry_util.hh"
|
||||
|
||||
namespace blender::nodes::node_geo_instance_on_points_cc {
|
||||
@@ -225,6 +227,7 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
if (geometry_set.has_grease_pencil()) {
|
||||
using namespace bke::greasepencil;
|
||||
const GreasePencil &grease_pencil = *geometry_set.get_grease_pencil();
|
||||
bke::Instances *instances = new bke::Instances();
|
||||
for (const int layer_index : grease_pencil.layers().index_range()) {
|
||||
const Drawing *drawing = grease_pencil.get_eval_drawing(grease_pencil.layer(layer_index));
|
||||
if (drawing == nullptr) {
|
||||
@@ -235,30 +238,35 @@ static void node_geo_exec(GeoNodeExecParams params)
|
||||
/* Add an empty reference so the number of layers and instances match.
|
||||
* This makes it easy to reconstruct the layers afterwards and keep their attributes.
|
||||
* Although in this particular case we don't propagate the attributes. */
|
||||
const int handle = dst_instances->add_reference(bke::InstanceReference());
|
||||
dst_instances->add_instance(handle, float4x4::identity());
|
||||
const int handle = instances->add_reference(bke::InstanceReference());
|
||||
instances->add_instance(handle, float4x4::identity());
|
||||
continue;
|
||||
}
|
||||
/* TODO: Attributes are not propagating from the curves or the points. */
|
||||
bke::Instances *instances = new bke::Instances();
|
||||
bke::Instances *layer_instances = new bke::Instances();
|
||||
const bke::GreasePencilLayerFieldContext field_context(
|
||||
grease_pencil, AttrDomain::Point, layer_index);
|
||||
add_instances_from_component(*instances,
|
||||
add_instances_from_component(*layer_instances,
|
||||
src_curves.attributes(),
|
||||
instance,
|
||||
field_context,
|
||||
params,
|
||||
attributes_to_propagate);
|
||||
GeometrySet temp_set = GeometrySet::from_instances(instances);
|
||||
const int handle = dst_instances->add_reference(bke::InstanceReference{temp_set});
|
||||
dst_instances->add_instance(handle, float4x4::identity());
|
||||
}
|
||||
if (geometry_set.has_instances()) {
|
||||
GeometrySet::propagate_attributes_from_layer_to_instances(
|
||||
geometry_set.get_grease_pencil()->attributes(),
|
||||
geometry_set.get_instances_for_write()->attributes_for_write(),
|
||||
attribute_filter);
|
||||
GeometrySet temp_set = GeometrySet::from_instances(layer_instances);
|
||||
const int handle = instances->add_reference(bke::InstanceReference{temp_set});
|
||||
instances->add_instance(handle, float4x4::identity());
|
||||
}
|
||||
GeometrySet::propagate_attributes_from_layer_to_instances(
|
||||
geometry_set.get_grease_pencil()->attributes(),
|
||||
instances->attributes_for_write(),
|
||||
attribute_filter);
|
||||
GeometrySet new_instances = geometry::join_geometries(
|
||||
{GeometrySet::from_instances(dst_instances, bke::GeometryOwnershipType::Editable),
|
||||
GeometrySet::from_instances(instances)},
|
||||
attribute_filter);
|
||||
instances_component.replace(
|
||||
new_instances.get_component_for_write<InstancesComponent>().release());
|
||||
|
||||
geometry_set.replace_grease_pencil(nullptr);
|
||||
}
|
||||
geometry_set.remove_geometry_during_modify();
|
||||
|
||||
Reference in New Issue
Block a user