[Bf-blender-cvs] [60b3fc82399] functions: better handling of attribute name collisions

Jacques Lucke noreply at git.blender.org
Tue Dec 10 23:21:01 CET 2019


Commit: 60b3fc823998cf16387ebb4e730bea3ce239d710
Author: Jacques Lucke
Date:   Tue Dec 10 22:53:32 2019 +0100
Branches: functions
https://developer.blender.org/rB60b3fc823998cf16387ebb4e730bea3ce239d710

better handling of attribute name collisions

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

M	source/blender/functions/FN_attributes_ref.h
M	source/blender/simulations/bparticles/emitters.cpp
M	source/blender/simulations/bparticles/node_frontend.cpp

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

diff --git a/source/blender/functions/FN_attributes_ref.h b/source/blender/functions/FN_attributes_ref.h
index 89042f9bca5..9f7e5ccd785 100644
--- a/source/blender/functions/FN_attributes_ref.h
+++ b/source/blender/functions/FN_attributes_ref.h
@@ -59,6 +59,21 @@ class AttributesInfoBuilder : BLI::NonCopyable, BLI::NonMovable {
     }
   }
 
+  bool name_and_type_collide_with_existing(StringRef name, const CPPType &type) const
+  {
+    int index = m_names.index_try(name);
+    if (index == -1) {
+      return false;
+    }
+
+    const CPPType *existing_type = m_types[index];
+    if (*existing_type == type) {
+      return false;
+    }
+
+    return true;
+  }
+
   uint size() const
   {
     return m_names.size();
@@ -121,6 +136,11 @@ class AttributesInfo : BLI::NonCopyable, BLI::NonMovable {
     return this->default_of(this->index_of(name));
   }
 
+  bool has_attribute(StringRef name, const CPPType &type) const
+  {
+    return this->try_index_of(name, type) >= 0;
+  }
+
   int try_index_of(StringRef name, const CPPType &type) const
   {
     int index = this->try_index_of(name);
diff --git a/source/blender/simulations/bparticles/emitters.cpp b/source/blender/simulations/bparticles/emitters.cpp
index 8b906b31fe8..b076e02d9c8 100644
--- a/source/blender/simulations/bparticles/emitters.cpp
+++ b/source/blender/simulations/bparticles/emitters.cpp
@@ -409,6 +409,7 @@ void CustomEmitter::emit(EmitterInterface &interface)
   for (StringRef system_name : m_systems_to_emit) {
     auto new_particles = interface.particle_allocator().request(system_name, particle_count);
     new_particles.fill<float>("Birth Time", interface.time_span().end());
+    const AttributesInfo &info = new_particles.info();
 
     for (uint param_index : m_emitter_function.param_indices()) {
       MFParamType param_type = m_emitter_function.param_type(param_index);
@@ -417,19 +418,23 @@ void CustomEmitter::emit(EmitterInterface &interface)
         FN::GenericVectorArray &vector_array = params_builder.computed_vector_array(param_index);
         FN::GenericArrayRef array = vector_array[0];
         const FN::CPPType &base_type = array.type();
-        if (array.size() == 0) {
-          void *default_buffer = alloca(base_type.size());
-          base_type.construct_default(default_buffer);
-          new_particles.fill(attribute_name, base_type, default_buffer);
-        }
-        else {
-          new_particles.set_repeated(attribute_name, array);
+        if (info.has_attribute(attribute_name, base_type)) {
+          if (array.size() == 0) {
+            void *default_buffer = alloca(base_type.size());
+            base_type.construct_default(default_buffer);
+            new_particles.fill(attribute_name, base_type, default_buffer);
+          }
+          else {
+            new_particles.set_repeated(attribute_name, array);
+          }
         }
       }
       else if (param_type.is_single_output()) {
         FN::GenericMutableArrayRef array = params_builder.computed_array(param_index);
         const FN::CPPType &type = array.type();
-        new_particles.fill(attribute_name, type, array[0]);
+        if (info.has_attribute(attribute_name, type)) {
+          new_particles.fill(attribute_name, type, array[0]);
+        }
       }
       else {
         BLI_assert(false);
diff --git a/source/blender/simulations/bparticles/node_frontend.cpp b/source/blender/simulations/bparticles/node_frontend.cpp
index 8830e2847e1..0782c95b40e 100644
--- a/source/blender/simulations/bparticles/node_frontend.cpp
+++ b/source/blender/simulations/bparticles/node_frontend.cpp
@@ -230,6 +230,30 @@ class InlinedTreeData {
     return fn_ptr;
   }
 
+  bool try_add_attribute(InfluencesCollector &collector,
+                         ArrayRef<std::string> system_names,
+                         StringRef name,
+                         const CPPType &type,
+                         const void *default_value)
+  {
+    bool collides_with_existing = false;
+    for (StringRef system_name : system_names) {
+      AttributesInfoBuilder *attributes = collector.m_attributes.lookup(system_name);
+      collides_with_existing = collides_with_existing ||
+                               attributes->name_and_type_collide_with_existing(name, type);
+    }
+
+    if (collides_with_existing) {
+      return false;
+    }
+
+    for (StringRef system_name : system_names) {
+      collector.m_attributes.lookup(system_name)->add(name, type, default_value);
+    }
+
+    return true;
+  }
+
  private:
   Vector<const XNode *> find_target_system_nodes(const XOutputSocket &xsocket)
   {
@@ -348,19 +372,24 @@ class XSocketActionBuilder {
     return m_inlined_tree_data.compute_all_data_inputs(m_execute_xsocket.node());
   }
 
-  template<typename T> void add_attribute_to_affected_particles(StringRef name, T default_value)
+  template<typename T>
+  bool try_add_attribute_to_affected_particles(StringRef name, T default_value)
   {
-    this->add_attribute_to_affected_particles(
+    return this->try_add_attribute_to_affected_particles(
         name, FN::CPP_TYPE<T>(), (const void *)&default_value);
   }
 
-  void add_attribute_to_affected_particles(StringRef name,
-                                           const CPPType &type,
-                                           const void *default_value = nullptr)
+  bool try_add_attribute_to_affected_particles(StringRef name,
+                                               const CPPType &type,
+                                               const void *default_value = nullptr)
   {
     /* Add attribute to all particle systems for now. */
-    m_influences_collector.m_attributes.foreach_value(
-        [&](AttributesInfoBuilder *builder) { builder->add(name, type, default_value); });
+    Vector<std::string> system_names;
+    m_influences_collector.m_attributes.foreach_key(
+        [&](StringRef name) { system_names.append(name); });
+
+    return m_inlined_tree_data.try_add_attribute(
+        m_influences_collector, system_names, name, type, default_value);
   }
 };
 
@@ -471,8 +500,12 @@ static void ACTION_add_to_group(XSocketActionBuilder &builder)
     return;
   }
 
-  std::string group_name = inputs->relocate_out<std::string>(0, "Group");
-  builder.add_attribute_to_affected_particles<bool>(group_name, false);
+  std::string group_name = "private/group/" + inputs->relocate_out<std::string>(0, "Group");
+  bool attribute_added = builder.try_add_attribute_to_affected_particles<bool>(group_name, false);
+  if (!attribute_added) {
+    return;
+  }
+
   builder.set_constructed<AddToGroupAction>(group_name);
 }
 
@@ -506,7 +539,11 @@ static void ACTION_set_attribute(XSocketActionBuilder &builder)
   std::string attribute_name = RNA_get_string_std(builder.node_rna(), "attribute_name");
   const CPPType &type = builder.base_type_of(builder.xsocket().node().input(0));
 
-  builder.add_attribute_to_affected_particles(attribute_name, type);
+  bool attribute_added = builder.try_add_attribute_to_affected_particles(attribute_name, type);
+  if (!attribute_added) {
+    return;
+  }
+
   builder.set_constructed<SetAttributeAction>(attribute_name, type, *inputs_fn);
 }
 
@@ -615,6 +652,7 @@ class XNodeInfluencesBuilder {
   std::string node_identifier()
   {
     std::stringstream ss;
+    ss << "private/node";
     for (const BKE::XParentNode *parent = m_xnode.parent(); parent; parent = parent->parent()) {
       ss << "/" << parent->vnode().name();
     }
@@ -645,19 +683,18 @@ class XNodeInfluencesBuilder {
   }
 
   template<typename T>
-  void add_attribute(ArrayRef<std::string> system_names, StringRef name, T default_value)
+  bool try_add_attribute(ArrayRef<std::string> system_names, StringRef name, T default_value)
   {
-    this->add_attribute(system_names, name, (const void *)&default_value);
+    return this->try_add_attribute(system_names, name, (const void *)&default_value);
   }
 
-  void add_attribute(ArrayRef<std::string> system_names,
-                     StringRef name,
-                     const CPPType &type,
-                     const void *default_value = nullptr)
+  bool try_add_attribute(ArrayRef<std::string> system_names,
+                         StringRef name,
+                         const CPPType &type,
+                         const void *default_value = nullptr)
   {
-    for (StringRef system_name : system_names) {
-      m_influences_collector.m_attributes.lookup(system_name)->add(name, type, default_value);
-    }
+    return m_inlined_tree_data.try_add_attribute(
+        m_influences_collector, system_names, name, type, default_value);
   }
 };
 
@@ -719,7 +756,7 @@ static void PARSE_custom_emitter(XNodeInfluencesBuilder &builder)
       BLI_assert(false);
     }
 
-    builder.add_attribute(system_names, attribute_name, *attribute_type);
+    builder.try_add_attribute(system_names, attribute_name, *attribute_type);
   }
 
   Action &action = builder.build_action_list("Execute on Birth");
@@ -811,11 +848,15 @@ static void PARSE_age_reached_event(XNodeInfluencesBuilder &builder)
   }
 
   ArrayRef<std::string> system_names = builder.find_target_system_names(0, "Event");
-  Action &action = builder.build_action_list("Execute on Event");
-
   std::string is_triggered_attribute = builder.node_identifier();
 
-  builder.add_attribute<bool>(system_names, is_triggered_attribute, false);
+  bool attribute_added = builder.try_add_attribute<bool>(
+      system_names, is_triggered_attribute, false);
+  if (!attribute_added) {
+    return;
+  }
+
+  Action &action = builder.build_action_list("Execute on Event");
   Event &event = builder.construct<AgeReachedEvent>(is_triggered_attribute, inputs_fn, action);
   builder.add_event(system_names, event);
 }
@@ -883,10 +924,14 @@ static void PARSE_mesh_collision(XNodeInfluencesBuilder &builder)
       builder.world_transition().update_float4x4(object->id.name, "obmat", object->obmat).start;
 
   std::string last_collision_attribute = builder.node_identifier();
+  bool attribute_added = builder.try_add_attribute<int32_t>(
+      system_names, last_collision_attribute, -1);
+  if (!attribute_added) {
+    return;
+  }
 
   Event &event = builder.construct<MeshCollisionEvent>(
       last_collis

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list