[Bf-blender-cvs] [4df45d1c4ce] functions: initial Custom Emitter node
Jacques Lucke
noreply at git.blender.org
Tue Dec 10 18:13:02 CET 2019
Commit: 4df45d1c4cebe693a05bff312ba57f0edff6c16e
Author: Jacques Lucke
Date: Tue Dec 10 18:12:51 2019 +0100
Branches: functions
https://developer.blender.org/rB4df45d1c4cebe693a05bff312ba57f0edff6c16e
initial Custom Emitter node
===================================================================
A release/scripts/startup/nodes/bparticle_nodes/custom_emitter.py
M source/blender/blenkernel/BKE_inlined_node_tree.h
M source/blender/blenkernel/intern/inlined_node_tree.cc
M source/blender/functions/FN_attributes_ref.h
M source/blender/functions/FN_generic_array_ref.h
M source/blender/simulations/bparticles/emitters.cpp
M source/blender/simulations/bparticles/emitters.hpp
M source/blender/simulations/bparticles/node_frontend.cpp
===================================================================
diff --git a/release/scripts/startup/nodes/bparticle_nodes/custom_emitter.py b/release/scripts/startup/nodes/bparticle_nodes/custom_emitter.py
new file mode 100644
index 00000000000..54f099e8f2f
--- /dev/null
+++ b/release/scripts/startup/nodes/bparticle_nodes/custom_emitter.py
@@ -0,0 +1,48 @@
+import bpy
+import uuid
+from bpy.props import *
+from .. base import SimulationNode
+from .. node_builder import NodeBuilder
+from .. types import type_infos
+
+
+class CustomEmitterAttribute(bpy.types.PropertyGroup):
+ attribute_name: StringProperty()
+ attribute_type: StringProperty()
+ identifier: StringProperty()
+ is_list: NodeBuilder.VectorizedProperty()
+
+
+class CustomEmitter(bpy.types.Node, SimulationNode):
+ bl_idname = "fn_CustomEmitterNode"
+ bl_label = "Custom Emitter"
+
+ execute_on_birth__prop: NodeBuilder.ExecuteInputProperty()
+
+ attributes: CollectionProperty(
+ type=CustomEmitterAttribute,
+ )
+
+ new_attribute_name: StringProperty(default="My Attribute")
+
+ def declaration(self, builder: NodeBuilder):
+ for i, item in enumerate(self.attributes):
+ builder.vectorized_input(
+ item.identifier,
+ f"attributes[{i}].is_list",
+ item.attribute_name,
+ item.attribute_name,
+ item.attribute_type)
+ builder.execute_input("execute_on_birth", "Execute on Birth", "execute_on_birth__prop")
+ builder.influences_output("emitter", "Emitter")
+
+ def draw(self, layout):
+ layout.prop(self, "new_attribute_name")
+ self.invoke_type_selection(layout, "add_attribute", "Add Attribute", mode="BASE")
+
+ def add_attribute(self, data_type):
+ item = self.attributes.add()
+ item.identifier = str(uuid.uuid4())
+ item.attribute_name = self.new_attribute_name
+ item.attribute_type = data_type
+ self.sync_tree()
diff --git a/source/blender/blenkernel/BKE_inlined_node_tree.h b/source/blender/blenkernel/BKE_inlined_node_tree.h
index 40bc039b7b7..a7dab0d008a 100644
--- a/source/blender/blenkernel/BKE_inlined_node_tree.h
+++ b/source/blender/blenkernel/BKE_inlined_node_tree.h
@@ -44,6 +44,8 @@ class XSocket : BLI::NonCopyable, BLI::NonMovable {
PointerRNA *rna() const;
StringRefNull idname() const;
StringRefNull name() const;
+
+ uint index() const;
};
class XInputSocket : public XSocket {
@@ -120,6 +122,8 @@ class XNode : BLI::NonCopyable, BLI::NonMovable {
PointerRNA *rna() const;
StringRefNull idname() const;
StringRefNull name() const;
+
+ const XInputSocket *input_with_name_prefix(StringRef name_prefix) const;
};
class XParentNode : BLI::NonCopyable, BLI::NonMovable {
@@ -334,6 +338,11 @@ inline StringRefNull XSocket::name() const
return m_vsocket->name();
}
+inline uint XSocket::index() const
+{
+ return m_vsocket->index();
+}
+
inline const VInputSocket &XInputSocket::vsocket() const
{
return m_vsocket->as_input();
diff --git a/source/blender/blenkernel/intern/inlined_node_tree.cc b/source/blender/blenkernel/intern/inlined_node_tree.cc
index 7ce8c89fed3..341e842bc47 100644
--- a/source/blender/blenkernel/intern/inlined_node_tree.cc
+++ b/source/blender/blenkernel/intern/inlined_node_tree.cc
@@ -471,4 +471,14 @@ void InlinedNodeTree::to_dot__clipboard() const
WM_clipboard_text_set(dot.c_str(), false);
}
+const XInputSocket *XNode::input_with_name_prefix(StringRef name_prefix) const
+{
+ for (const XInputSocket *xsocket : m_inputs) {
+ if (xsocket->name().startswith(name_prefix)) {
+ return xsocket;
+ }
+ }
+ return nullptr;
+}
+
} // namespace BKE
diff --git a/source/blender/functions/FN_attributes_ref.h b/source/blender/functions/FN_attributes_ref.h
index 43a950ef6e4..89042f9bca5 100644
--- a/source/blender/functions/FN_attributes_ref.h
+++ b/source/blender/functions/FN_attributes_ref.h
@@ -41,12 +41,17 @@ class AttributesInfoBuilder : BLI::NonCopyable, BLI::NonMovable {
this->add(name, CPP_TYPE<T>(), (const void *)&default_value);
}
- void add(StringRef name, const CPPType &type, const void *default_value)
+ void add(StringRef name, const CPPType &type, const void *default_value = nullptr)
{
if (m_names.add(name)) {
m_types.append(&type);
void *dst = m_allocator.allocate(type.size(), type.alignment());
- type.copy_to_uninitialized(default_value, dst);
+ if (default_value == nullptr) {
+ type.construct_default(dst);
+ }
+ else {
+ type.copy_to_uninitialized(default_value, dst);
+ }
m_defaults.append(dst);
}
else {
@@ -312,6 +317,30 @@ class AttributesRefGroup {
this->set_repeated(m_info->index_of(name), data);
}
+ void set_repeated(uint index, GenericArrayRef data)
+ {
+ BLI_assert(m_total_size == 0 || data.size() > 0);
+ BLI_assert(m_info->type_of(index) == data.type());
+
+ uint src_index = 0;
+ for (AttributesRef attributes : *this) {
+ GenericMutableArrayRef array = attributes.get(index);
+
+ for (uint i = 0; i < attributes.size(); i++) {
+ array.copy_in__initialized(i, data[src_index]);
+ src_index++;
+ if (src_index == data.size()) {
+ src_index = 0;
+ }
+ }
+ }
+ }
+
+ void set_repeated(StringRef name, GenericArrayRef data)
+ {
+ this->set_repeated(m_info->index_of(name), data);
+ }
+
template<typename T> void fill(uint index, const T &value)
{
BLI_assert(m_info->type_of(index) == CPP_TYPE<T>());
@@ -327,6 +356,22 @@ class AttributesRefGroup {
this->fill(m_info->index_of(name), value);
}
+ void fill(uint index, const CPPType &type, const void *value)
+ {
+ BLI_assert(m_info->type_of(index) == type);
+ UNUSED_VARS_NDEBUG(type);
+
+ for (AttributesRef attributes : *this) {
+ GenericMutableArrayRef array = attributes.get(index);
+ array.fill__initialized(value);
+ }
+ }
+
+ void fill(StringRef name, const CPPType &type, const void *value)
+ {
+ this->fill(m_info->index_of(name), type, value);
+ }
+
class Iterator {
private:
AttributesRefGroup *m_group;
diff --git a/source/blender/functions/FN_generic_array_ref.h b/source/blender/functions/FN_generic_array_ref.h
index 4bf9d417e71..1b51233d306 100644
--- a/source/blender/functions/FN_generic_array_ref.h
+++ b/source/blender/functions/FN_generic_array_ref.h
@@ -133,6 +133,13 @@ class GenericMutableArrayRef {
}
}
+ void fill__initialized(const void *value)
+ {
+ for (uint i = 0; i < m_size; i++) {
+ m_type->copy_to_initialized(value, (*this)[i]);
+ }
+ }
+
void copy_in__uninitialized(uint index, const void *src)
{
BLI_assert(index < m_size);
@@ -140,6 +147,13 @@ class GenericMutableArrayRef {
m_type->copy_to_uninitialized(src, dst);
}
+ void copy_in__initialized(uint index, const void *src)
+ {
+ BLI_assert(index < m_size);
+ void *dst = POINTER_OFFSET(m_buffer, m_type->size() * index);
+ m_type->copy_to_initialized(src, dst);
+ }
+
static void RelocateUninitialized(GenericMutableArrayRef from, GenericMutableArrayRef to);
void *operator[](uint index)
diff --git a/source/blender/simulations/bparticles/emitters.cpp b/source/blender/simulations/bparticles/emitters.cpp
index 7b3ba4e83cd..8b906b31fe8 100644
--- a/source/blender/simulations/bparticles/emitters.cpp
+++ b/source/blender/simulations/bparticles/emitters.cpp
@@ -357,4 +357,87 @@ void InitialGridEmitter::emit(EmitterInterface &interface)
}
}
+using FN::MFParamType;
+
+void CustomEmitter::emit(EmitterInterface &interface)
+{
+ FN::MFParamsBuilder params_builder{m_emitter_function, 1};
+
+ for (uint param_index : m_emitter_function.param_indices()) {
+ MFParamType param_type = m_emitter_function.param_type(param_index);
+ switch (param_type.type()) {
+ case MFParamType::SingleInput:
+ case MFParamType::VectorInput:
+ case MFParamType::MutableSingle:
+ case MFParamType::MutableVector:
+ BLI_assert(false);
+ break;
+ case MFParamType::SingleOutput: {
+ const FN::CPPType &type = param_type.data_type().single__cpp_type();
+ void *buffer = MEM_mallocN(type.size(), __func__);
+ FN::GenericMutableArrayRef array{type, buffer, 1};
+ params_builder.add_single_output(array);
+ break;
+ }
+ case MFParamType::VectorOutput: {
+ const FN::CPPType &base_type = param_type.data_type().vector__cpp_base_type();
+ FN::GenericVectorArray *vector_array = new FN::GenericVectorArray(base_type, 1);
+ params_builder.add_vector_output(*vector_array);
+ break;
+ }
+ }
+ }
+
+ FN::MFContextBuilder context_builder;
+ m_emitter_function.call({0}, params_builder, context_builder);
+
+ int particle_count = -1;
+
+ for (uint param_index : m_emitter_function.param_indices()) {
+ MFParamType param_type = m_emitter_function.param_type(param_index);
+ if (param_type.is_vector_output()) {
+ FN::GenericVectorArray &vector_array = params_builder.computed_vector_array(param_index);
+ FN::GenericArrayRef array = vector_array[0];
+ particle_count = std::max<int>(particle_count, array.size());
+ }
+ }
+
+ if (particle_count == -1) {
+ particle_count = 1;
+ }
+
+ 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());
+
+ for (uint param_index : m_emitter_function.param_indices()) {
+ MFParamType param_type = m_emitter_function.param_type(param_index);
+ StringRef attribute_name = m_attribute_names[param_index];
+ if (param_type.is_vector_output()) {
+ 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);
+ }
+ els
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list