Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h4
-rw-r--r--source/blender/blenkernel/intern/customdata.c2
-rw-r--r--source/blender/blenkernel/intern/pointcache.c20
-rw-r--r--source/blender/blenkernel/intern/simulation.cc366
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/blenloader/intern/writefile.c1
-rw-r--r--source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc13
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h2
-rw-r--r--source/blender/makesdna/DNA_simulation_types.h12
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c38
-rw-r--r--source/blender/modifiers/intern/MOD_simulation.cc53
11 files changed, 387 insertions, 125 deletions
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index b0973ed458c..f919a31c165 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -296,7 +296,9 @@ void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid,
struct Object *ob,
struct DynamicPaintSurface *surface);
void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, struct Object *ob, struct RigidBodyWorld *rbw);
-void BKE_ptcache_id_from_sim_particles(PTCacheID *pid, struct ParticleSimulationState *state);
+void BKE_ptcache_id_from_sim_particles(PTCacheID *pid,
+ struct ParticleSimulationState *state_orig,
+ struct ParticleSimulationState *state_cow);
PTCacheID BKE_ptcache_id_find(struct Object *ob, struct Scene *scene, struct PointCache *cache);
void BKE_ptcache_ids_from_object(struct ListBase *lb,
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index 76bc7a7bfb7..c11fa69db76 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -1772,7 +1772,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 42: CD_SCULPT_FACE_SETS */
{sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 43: CD_LOCATION */
- {sizeof(float[3]), "vec3f", 1, NULL, NULL, NULL, NULL, NULL, NULL},
+ {sizeof(float[3]), "vec3f", 1, "Location", NULL, NULL, NULL, NULL, NULL},
/* 44: CD_RADIUS */
{sizeof(float), "MFloatProperty", 1, NULL, NULL, NULL, NULL, NULL, NULL},
/* 45: CD_HAIRCURVE */
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index dbd6d99c7fe..ce5402551b6 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -1898,19 +1898,13 @@ static void ptcache_sim_particle_read(
PTCACHE_DATA_TO(data, BPHYS_DATA_LOCATION, 0, positions + (index * 3));
}
-void BKE_ptcache_id_from_sim_particles(PTCacheID *pid, ParticleSimulationState *state)
+void BKE_ptcache_id_from_sim_particles(PTCacheID *pid,
+ ParticleSimulationState *state_orig,
+ ParticleSimulationState *state_cow)
{
memset(pid, 0, sizeof(PTCacheID));
- ParticleSimulationState *state_orig;
- if (state->head.orig_state != NULL) {
- state_orig = (ParticleSimulationState *)state->head.orig_state;
- }
- else {
- state_orig = state;
- }
-
- pid->calldata = state;
+ pid->calldata = state_cow;
pid->type = PTCACHE_TYPE_SIM_PARTICLES;
pid->cache = state_orig->point_cache;
pid->cache_ptr = &state_orig->point_cache;
@@ -2050,11 +2044,7 @@ static bool foreach_object_modifier_ptcache(Object *object,
LISTBASE_FOREACH (SimulationState *, state, &smd->simulation->states) {
switch ((eSimulationStateType)state->type) {
case SIM_STATE_TYPE_PARTICLES: {
- ParticleSimulationState *particle_state = (ParticleSimulationState *)state;
- BKE_ptcache_id_from_sim_particles(&pid, particle_state);
- if (!callback(&pid, callback_user_data)) {
- return false;
- }
+ /* TODO(jacques) */
break;
}
}
diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc
index c4a35141b0d..35ef664dce3 100644
--- a/source/blender/blenkernel/intern/simulation.cc
+++ b/source/blender/blenkernel/intern/simulation.cc
@@ -31,6 +31,7 @@
#include "BLI_float3.hh"
#include "BLI_listbase.h"
#include "BLI_math.h"
+#include "BLI_rand.h"
#include "BLI_span.hh"
#include "BLI_string.h"
#include "BLI_utildefines.h"
@@ -44,6 +45,7 @@
#include "BKE_lib_remap.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BKE_node_tree_multi_function.hh"
#include "BKE_pointcache.h"
#include "BKE_simulation.h"
@@ -51,9 +53,18 @@
#include "BLT_translation.h"
+#include "FN_attributes_ref.hh"
+#include "FN_cpp_types.hh"
+#include "FN_multi_function_network_evaluation.hh"
+#include "FN_multi_function_network_optimization.hh"
+
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
+extern "C" {
+void WM_clipboard_text_set(const char *buf, bool selection);
+}
+
static void simulation_init_data(ID *id)
{
Simulation *simulation = (Simulation *)id;
@@ -63,14 +74,6 @@ static void simulation_init_data(ID *id)
bNodeTree *ntree = ntreeAddTree(nullptr, "Simulation Nodetree", ntreeType_Simulation->idname);
simulation->nodetree = ntree;
-
- /* Add a default particle simulation state for now. */
- ParticleSimulationState *state = (ParticleSimulationState *)MEM_callocN(
- sizeof(ParticleSimulationState), __func__);
- CustomData_reset(&state->attributes);
-
- state->point_cache = BKE_ptcache_add(&state->ptcaches);
- BLI_addtail(&simulation->states, state);
}
static void simulation_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag)
@@ -89,19 +92,19 @@ static void simulation_copy_data(Main *bmain, ID *id_dst, const ID *id_src, cons
}
BLI_listbase_clear(&simulation_dst->states);
+}
- LISTBASE_FOREACH (const SimulationState *, state_src, &simulation_src->states) {
- switch ((eSimulationStateType)state_src->type) {
- case SIM_STATE_TYPE_PARTICLES: {
- ParticleSimulationState *particle_state_dst = (ParticleSimulationState *)MEM_callocN(
- sizeof(ParticleSimulationState), __func__);
- CustomData_reset(&particle_state_dst->attributes);
+static void free_simulation_state_head(SimulationState *state)
+{
+ MEM_freeN(state->name);
+}
- BLI_addtail(&simulation_dst->states, particle_state_dst);
- break;
- }
- }
- }
+static void free_particle_simulation_state(ParticleSimulationState *state)
+{
+ free_simulation_state_head(&state->head);
+ CustomData_free(&state->attributes, state->tot_particles);
+ BKE_ptcache_free_list(&state->ptcaches);
+ MEM_freeN(state);
}
static void simulation_free_data(ID *id)
@@ -119,13 +122,10 @@ static void simulation_free_data(ID *id)
LISTBASE_FOREACH_MUTABLE (SimulationState *, state, &simulation->states) {
switch ((eSimulationStateType)state->type) {
case SIM_STATE_TYPE_PARTICLES: {
- ParticleSimulationState *particle_state = (ParticleSimulationState *)state;
- CustomData_free(&particle_state->attributes, particle_state->tot_particles);
- BKE_ptcache_free_list(&particle_state->ptcaches);
+ free_particle_simulation_state((ParticleSimulationState *)state);
break;
}
}
- MEM_freeN(state);
}
}
@@ -166,59 +166,230 @@ void *BKE_simulation_add(Main *bmain, const char *name)
namespace blender::bke {
-static MutableSpan<float3> get_particle_positions(ParticleSimulationState *state)
-{
- return MutableSpan<float3>(
- (float3 *)CustomData_get_layer_named(&state->attributes, CD_LOCATION, "Position"),
- state->tot_particles);
-}
-
static void ensure_attributes_exist(ParticleSimulationState *state)
{
if (CustomData_get_layer_named(&state->attributes, CD_LOCATION, "Position") == nullptr) {
CustomData_add_layer_named(
&state->attributes, CD_LOCATION, CD_CALLOC, nullptr, state->tot_particles, "Position");
}
+ if (CustomData_get_layer_named(&state->attributes, CD_LOCATION, "Velocity") == nullptr) {
+ CustomData_add_layer_named(
+ &state->attributes, CD_LOCATION, CD_CALLOC, nullptr, state->tot_particles, "Velocity");
+ }
}
-static void copy_particle_state_to_cow(ParticleSimulationState *state_orig,
- ParticleSimulationState *state_cow)
+static void copy_states_to_cow(Simulation *simulation_orig, Simulation *simulation_cow)
{
- ensure_attributes_exist(state_cow);
- CustomData_free(&state_cow->attributes, state_cow->tot_particles);
- CustomData_copy(&state_orig->attributes,
- &state_cow->attributes,
- CD_MASK_ALL,
- CD_DUPLICATE,
- state_orig->tot_particles);
- state_cow->current_frame = state_orig->current_frame;
- state_cow->tot_particles = state_orig->tot_particles;
+ LISTBASE_FOREACH_MUTABLE (SimulationState *, state_cow, &simulation_cow->states) {
+ switch ((eSimulationStateType)state_cow->type) {
+ case SIM_STATE_TYPE_PARTICLES: {
+ BLI_remlink(&simulation_cow->states, state_cow);
+ free_particle_simulation_state((ParticleSimulationState *)state_cow);
+ break;
+ }
+ }
+ }
+ simulation_cow->current_frame = simulation_orig->current_frame;
+
+ LISTBASE_FOREACH (SimulationState *, state_orig, &simulation_orig->states) {
+ switch ((eSimulationStateType)state_orig->type) {
+ case SIM_STATE_TYPE_PARTICLES: {
+ ParticleSimulationState *particle_state_orig = (ParticleSimulationState *)state_orig;
+ ParticleSimulationState *particle_state_cow = (ParticleSimulationState *)MEM_callocN(
+ sizeof(*particle_state_cow), AT);
+ particle_state_cow->tot_particles = particle_state_orig->tot_particles;
+ particle_state_cow->head.name = BLI_strdup(state_orig->name);
+ CustomData_copy(&particle_state_orig->attributes,
+ &particle_state_cow->attributes,
+ CD_MASK_ALL,
+ CD_DUPLICATE,
+ particle_state_orig->tot_particles);
+ BLI_addtail(&simulation_cow->states, particle_state_cow);
+ break;
+ }
+ }
+ }
}
-static void simulation_data_update(Depsgraph *depsgraph, Scene *scene, Simulation *simulation)
+using AttributeNodeMap = Map<fn::MFDummyNode *, std::pair<std::string, fn::MFDataType>>;
+
+static AttributeNodeMap deduplicate_attribute_nodes(fn::MFNetwork &network,
+ MFNetworkTreeMap &network_map,
+ const DerivedNodeTree &tree)
{
- int current_frame = scene->r.cfra;
+ Span<const DNode *> attribute_dnodes = tree.nodes_by_type("SimulationNodeParticleAttribute");
+ uint amount = attribute_dnodes.size();
+ if (amount == 0) {
+ return {};
+ }
- ParticleSimulationState *state_cow = (ParticleSimulationState *)simulation->states.first;
- ParticleSimulationState *state_orig = (ParticleSimulationState *)state_cow->head.orig_state;
+ Vector<fn::MFInputSocket *> name_sockets;
+ for (const DNode *dnode : attribute_dnodes) {
+ fn::MFInputSocket &name_socket = network_map.lookup_dummy(dnode->input(0));
+ name_sockets.append(&name_socket);
+ }
- if (current_frame == state_cow->current_frame) {
- return;
+ fn::MFNetworkEvaluator network_fn{{}, name_sockets.as_span()};
+
+ fn::MFParamsBuilder params{network_fn, 1};
+
+ Array<std::string> attribute_names{amount, NoInitialization()};
+ for (uint i : IndexRange(amount)) {
+ params.add_uninitialized_single_output(
+ fn::GMutableSpan(fn::CPPType_string, attribute_names.data() + i, 1));
+ }
+
+ fn::MFContextBuilder context;
+ /* Todo: Check that the names don't depend on dummy nodes. */
+ network_fn.call({0}, params, context);
+
+ Map<std::pair<std::string, fn::MFDataType>, Vector<fn::MFNode *>>
+ attribute_nodes_by_name_and_type;
+ for (uint i : IndexRange(amount)) {
+ attribute_nodes_by_name_and_type
+ .lookup_or_add_default({attribute_names[i], name_sockets[i]->data_type()})
+ .append(&name_sockets[i]->node());
}
- /* Number of particles should be stored in the cache, but for now assume it is constant. */
- state_cow->tot_particles = state_orig->tot_particles;
- CustomData_realloc(&state_cow->attributes, state_orig->tot_particles);
- ensure_attributes_exist(state_cow);
+ AttributeNodeMap final_attribute_nodes;
+ for (auto item : attribute_nodes_by_name_and_type.items()) {
+ StringRef attribute_name = item.key.first;
+ fn::MFDataType data_type = item.key.second;
+ Span<fn::MFNode *> nodes = item.value;
- PTCacheID pid_cow;
- BKE_ptcache_id_from_sim_particles(&pid_cow, state_cow);
- BKE_ptcache_id_time(&pid_cow, scene, current_frame, nullptr, nullptr, nullptr);
+ fn::MFOutputSocket &new_attribute_socket = network.add_input(
+ "Attribute '" + attribute_name + "'", data_type);
+ for (fn::MFNode *node : nodes) {
+ network.relink(node->output(0), new_attribute_socket);
+ }
+ network.remove(nodes);
+
+ final_attribute_nodes.add_new(&new_attribute_socket.node().as_dummy(), item.key);
+ }
+
+ return final_attribute_nodes;
+}
+
+class CustomDataAttributesRef {
+ private:
+ Vector<void *> buffers_;
+ uint size_;
+ std::unique_ptr<fn::AttributesInfo> info_;
+
+ public:
+ CustomDataAttributesRef(CustomData &custom_data, uint size)
+ {
+ fn::AttributesInfoBuilder builder;
+ for (const CustomDataLayer &layer : Span(custom_data.layers, custom_data.totlayer)) {
+ buffers_.append(layer.data);
+ builder.add<float3>(layer.name, {0, 0, 0});
+ }
+ info_ = std::make_unique<fn::AttributesInfo>(builder);
+ size_ = size;
+ }
+
+ operator fn::MutableAttributesRef()
+ {
+ return fn::MutableAttributesRef(*info_, buffers_, size_);
+ }
- /* If successfull, this will read the state directly into the cow state. */
- int cache_result = BKE_ptcache_read(&pid_cow, current_frame, true);
- if (cache_result == PTCACHE_READ_EXACT) {
- state_cow->current_frame = current_frame;
+ operator fn::AttributesRef() const
+ {
+ return fn::AttributesRef(*info_, buffers_, size_);
+ }
+};
+
+static std::string dnode_to_path(const DNode &dnode)
+{
+ std::string path;
+ for (const DParentNode *parent = dnode.parent(); parent; parent = parent->parent()) {
+ path = parent->node_ref().name() + "/" + path;
+ }
+ path = path + dnode.name();
+ return path;
+}
+
+static void remove_unused_states(Simulation *simulation, const VectorSet<std::string> &state_names)
+{
+ LISTBASE_FOREACH_MUTABLE (SimulationState *, state, &simulation->states) {
+ if (!state_names.contains(state->name)) {
+ BLI_remlink(&simulation->states, state);
+ free_particle_simulation_state((ParticleSimulationState *)state);
+ }
+ }
+}
+
+static void reset_states(Simulation *simulation)
+{
+ LISTBASE_FOREACH (SimulationState *, state, &simulation->states) {
+ switch ((eSimulationStateType)state->type) {
+ case SIM_STATE_TYPE_PARTICLES: {
+ ParticleSimulationState *particle_state = (ParticleSimulationState *)state;
+ CustomData_free(&particle_state->attributes, particle_state->tot_particles);
+ particle_state->tot_particles = 0;
+ break;
+ }
+ }
+ }
+}
+
+static SimulationState *try_find_state_by_name(Simulation *simulation, StringRef name)
+{
+ LISTBASE_FOREACH (SimulationState *, state, &simulation->states) {
+ if (state->name == name) {
+ return state;
+ }
+ }
+ return nullptr;
+}
+
+static void add_missing_particle_states(Simulation *simulation, Span<std::string> state_names)
+{
+ for (StringRefNull name : state_names) {
+ SimulationState *state = try_find_state_by_name(simulation, name);
+ if (state != nullptr) {
+ BLI_assert(state->type == SIM_STATE_TYPE_PARTICLES);
+ continue;
+ }
+
+ ParticleSimulationState *particle_state = (ParticleSimulationState *)MEM_callocN(
+ sizeof(*particle_state), AT);
+ particle_state->head.type = SIM_STATE_TYPE_PARTICLES;
+ particle_state->head.name = BLI_strdup(name.data());
+ CustomData_reset(&particle_state->attributes);
+ particle_state->point_cache = BKE_ptcache_add(&particle_state->ptcaches);
+ BLI_addtail(&simulation->states, particle_state);
+ }
+}
+
+static void reinitialize_empty_simulation_states(Simulation *simulation,
+ const DerivedNodeTree &tree)
+{
+ VectorSet<std::string> state_names;
+ for (const DNode *dnode : tree.nodes_by_type("SimulationNodeParticleSimulation")) {
+ state_names.add(dnode_to_path(*dnode));
+ }
+
+ remove_unused_states(simulation, state_names);
+ reset_states(simulation);
+ add_missing_particle_states(simulation, state_names);
+}
+
+static void update_simulation_state_list(Simulation *simulation, const DerivedNodeTree &tree)
+{
+ VectorSet<std::string> state_names;
+ for (const DNode *dnode : tree.nodes_by_type("SimulationNodeParticleSimulation")) {
+ state_names.add(dnode_to_path(*dnode));
+ }
+
+ remove_unused_states(simulation, state_names);
+ add_missing_particle_states(simulation, state_names);
+}
+
+static void simulation_data_update(Depsgraph *depsgraph, Scene *scene, Simulation *simulation_cow)
+{
+ int current_frame = scene->r.cfra;
+ if (simulation_cow->current_frame == current_frame) {
return;
}
@@ -227,34 +398,71 @@ static void simulation_data_update(Depsgraph *depsgraph, Scene *scene, Simulatio
return;
}
- PTCacheID pid_orig;
- BKE_ptcache_id_from_sim_particles(&pid_orig, state_orig);
- BKE_ptcache_id_time(&pid_orig, scene, current_frame, nullptr, nullptr, nullptr);
+ Simulation *simulation_orig = (Simulation *)DEG_get_original_id(&simulation_cow->id);
+
+ NodeTreeRefMap tree_refs;
+ /* TODO: Use simulation_cow, but need to add depsgraph relations before that. */
+ const DerivedNodeTree tree{simulation_orig->nodetree, tree_refs};
+ fn::MFNetwork network;
+ ResourceCollector resources;
+ MFNetworkTreeMap network_map = insert_node_tree_into_mf_network(network, tree, resources);
+ AttributeNodeMap attribute_node_map = deduplicate_attribute_nodes(network, network_map, tree);
+ fn::mf_network_optimization::constant_folding(network, resources);
+ fn::mf_network_optimization::common_subnetwork_elimination(network);
+ fn::mf_network_optimization::dead_node_removal(network);
+ UNUSED_VARS(attribute_node_map);
+ // WM_clipboard_text_set(network.to_dot().c_str(), false);
if (current_frame == 1) {
- state_orig->tot_particles = 100;
- state_orig->current_frame = 1;
- CustomData_realloc(&state_orig->attributes, state_orig->tot_particles);
- ensure_attributes_exist(state_orig);
-
- MutableSpan<float3> positions = get_particle_positions(state_orig);
- for (uint i : positions.index_range()) {
- positions[i] = {i / 10.0f, 0, 0};
+ reinitialize_empty_simulation_states(simulation_orig, tree);
+
+ RNG *rng = BLI_rng_new(0);
+
+ simulation_orig->current_frame = 1;
+ LISTBASE_FOREACH (ParticleSimulationState *, state, &simulation_orig->states) {
+ state->tot_particles = 100;
+ CustomData_realloc(&state->attributes, state->tot_particles);
+ ensure_attributes_exist(state);
+
+ CustomDataAttributesRef custom_data_attributes{state->attributes,
+ (uint)state->tot_particles};
+
+ fn::MutableAttributesRef attributes = custom_data_attributes;
+ MutableSpan<float3> positions = attributes.get<float3>("Position");
+ MutableSpan<float3> velocities = attributes.get<float3>("Velocity");
+
+ for (uint i : positions.index_range()) {
+ positions[i] = {i / 10.0f, 0, 0};
+ velocities[i] = {0, BLI_rng_get_float(rng), BLI_rng_get_float(rng) * 2 + 1};
+ }
}
- BKE_ptcache_write(&pid_orig, current_frame);
- copy_particle_state_to_cow(state_orig, state_cow);
+ BLI_rng_free(rng);
+
+ copy_states_to_cow(simulation_orig, simulation_cow);
}
- else if (current_frame == state_orig->current_frame + 1) {
- state_orig->current_frame = current_frame;
- ensure_attributes_exist(state_orig);
- MutableSpan<float3> positions = get_particle_positions(state_orig);
- for (float3 &position : positions) {
- position.z += 0.1f;
+ else if (current_frame == simulation_orig->current_frame + 1) {
+ update_simulation_state_list(simulation_orig, tree);
+ float time_step = 1.0f / 24.0f;
+ simulation_orig->current_frame = current_frame;
+
+ LISTBASE_FOREACH (ParticleSimulationState *, state, &simulation_orig->states) {
+ ensure_attributes_exist(state);
+
+ CustomDataAttributesRef custom_data_attributes{state->attributes,
+ (uint)state->tot_particles};
+
+ fn::MutableAttributesRef attributes = custom_data_attributes;
+ MutableSpan<float3> positions = attributes.get<float3>("Position");
+ MutableSpan<float3> velocities = attributes.get<float3>("Velocity");
+
+ for (uint i : positions.index_range()) {
+ velocities[i].z += -1.0f * time_step;
+ positions[i] += velocities[i] * time_step;
+ }
}
- BKE_ptcache_write(&pid_orig, current_frame);
- copy_particle_state_to_cow(state_orig, state_cow);
+ copy_states_to_cow(simulation_orig, simulation_cow);
}
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 274d56ac5f7..44a1a6ec44a 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -8686,6 +8686,7 @@ static void direct_link_simulation(BlendDataReader *reader, Simulation *simulati
BLO_read_list(reader, &simulation->states);
LISTBASE_FOREACH (SimulationState *, state, &simulation->states) {
+ BLO_read_data_address(reader, &state->name);
switch ((eSimulationStateType)state->type) {
case SIM_STATE_TYPE_PARTICLES: {
ParticleSimulationState *particle_state = (ParticleSimulationState *)state;
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 2ce8abff3c5..4e2b4fef9a0 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -3832,6 +3832,7 @@ static void write_simulation(BlendWriter *writer, Simulation *simulation, const
}
LISTBASE_FOREACH (SimulationState *, state, &simulation->states) {
+ BLO_write_string(writer, state->name);
switch ((eSimulationStateType)state->type) {
case SIM_STATE_TYPE_PARTICLES: {
ParticleSimulationState *particle_state = (ParticleSimulationState *)state;
diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
index 38350d50da6..79d6c8d6a77 100644
--- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
+++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc
@@ -711,13 +711,6 @@ void update_modifiers_orig_pointers(const Object *object_orig, Object *object_co
&object_orig->modifiers, &object_cow->modifiers, &ModifierData::orig_modifier_data);
}
-void update_simulation_states_orig_pointers(const Simulation *simulation_orig,
- Simulation *simulation_cow)
-{
- update_list_orig_pointers(
- &simulation_orig->states, &simulation_cow->states, &SimulationState::orig_state);
-}
-
void update_nla_strips_orig_pointers(const ListBase *strips_orig, ListBase *strips_cow)
{
NlaStrip *strip_orig = reinterpret_cast<NlaStrip *>(strips_orig->first);
@@ -817,12 +810,6 @@ void update_id_after_copy(const Depsgraph *depsgraph,
update_scene_orig_pointers(scene_orig, scene_cow);
break;
}
- case ID_SIM: {
- Simulation *simulation_cow = (Simulation *)id_cow;
- const Simulation *simulation_orig = (const Simulation *)id_orig;
- update_simulation_states_orig_pointers(simulation_orig, simulation_cow);
- break;
- }
default:
break;
}
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 60ad0eae576..50b4739e09f 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -2146,7 +2146,7 @@ typedef struct SimulationModifierData {
ModifierData modifier;
struct Simulation *simulation;
- char data_path[64];
+ char *data_path;
} SimulationModifierData;
#ifdef __cplusplus
diff --git a/source/blender/makesdna/DNA_simulation_types.h b/source/blender/makesdna/DNA_simulation_types.h
index 93ba9c425f0..a2b81b731d3 100644
--- a/source/blender/makesdna/DNA_simulation_types.h
+++ b/source/blender/makesdna/DNA_simulation_types.h
@@ -31,7 +31,7 @@ typedef struct Simulation {
struct bNodeTree *nodetree;
int flag;
- int _pad;
+ float current_frame;
/** List containing SimulationState objects. */
struct ListBase states;
@@ -41,23 +41,19 @@ typedef struct SimulationState {
struct SimulationState *next;
struct SimulationState *prev;
- /** This is only initialized on cow copies of the simulation. It points to the state on the
- * original data block. That is where the cache is stored. */
- struct SimulationState *orig_state;
-
/** eSimulationStateType */
int type;
int _pad;
- char name[64];
+ char *name;
} SimulationState;
typedef struct ParticleSimulationState {
SimulationState head;
- /** Contains the state of the particles at time current_frame. */
- float current_frame;
+ /** Contains the state of the particles at time Simulation->current_frame. */
int tot_particles;
+ int _pad;
struct CustomData attributes;
/** Caches the state of the particles over time. The cache only exists on the original data
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index eab7326868b..20648970bd1 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -1639,6 +1639,40 @@ static void rna_SimulationModifier_simulation_update(Main *bmain, Scene *scene,
rna_Modifier_dependency_update(bmain, scene, ptr);
}
+static void rna_SimulationModifier_data_path_get(PointerRNA *ptr, char *value)
+{
+ SimulationModifierData *smd = ptr->data;
+
+ if (smd->data_path) {
+ strcpy(value, smd->data_path);
+ }
+ else {
+ value[0] = '\0';
+ }
+}
+
+static int rna_SimulationModifier_data_path_length(PointerRNA *ptr)
+{
+ SimulationModifierData *smd = ptr->data;
+ return smd->data_path ? strlen(smd->data_path) : 0;
+}
+
+static void rna_SimulationModifier_data_path_set(PointerRNA *ptr, const char *value)
+{
+ SimulationModifierData *smd = ptr->data;
+
+ if (smd->data_path) {
+ MEM_freeN(smd->data_path);
+ }
+
+ if (value[0]) {
+ smd->data_path = BLI_strdup(value);
+ }
+ else {
+ smd->data_path = NULL;
+ }
+}
+
/**
* Special set callback that just changes the first bit of the expansion flag.
* This way the expansion state of all the sub-panels is not changed by RNA.
@@ -6859,6 +6893,10 @@ static void rna_def_modifier_simulation(BlenderRNA *brna)
RNA_def_property_update(prop, 0, "rna_SimulationModifier_simulation_update");
prop = RNA_def_property(srna, "data_path", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop,
+ "rna_SimulationModifier_data_path_get",
+ "rna_SimulationModifier_data_path_length",
+ "rna_SimulationModifier_data_path_set");
RNA_def_property_ui_text(
prop, "Data Path", "Identifier of the simulation component that should be accessed");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
diff --git a/source/blender/modifiers/intern/MOD_simulation.cc b/source/blender/modifiers/intern/MOD_simulation.cc
index 85eb66cd826..69a7bfd91ac 100644
--- a/source/blender/modifiers/intern/MOD_simulation.cc
+++ b/source/blender/modifiers/intern/MOD_simulation.cc
@@ -29,6 +29,7 @@
#include "BLI_float3.hh"
#include "BLI_listbase.h"
+#include "BLI_string.h"
#include "BLI_utildefines.h"
#include "DNA_mesh_types.h"
@@ -47,6 +48,8 @@
#include "BKE_pointcloud.h"
#include "BKE_simulation.h"
+#include "BLO_read_write.h"
+
/* SpaceType struct has a member called 'new' which obviously conflicts with C++
* so temporarily redefining the new keyword to make it compile. */
#define new extern_new
@@ -93,9 +96,14 @@ static const ParticleSimulationState *find_particle_state(SimulationModifierData
if (smd->simulation == nullptr) {
return nullptr;
}
+ if (smd->data_path == nullptr) {
+ return nullptr;
+ }
LISTBASE_FOREACH (const SimulationState *, state, &smd->simulation->states) {
- if (state->type == SIM_STATE_TYPE_PARTICLES) {
- return (ParticleSimulationState *)state;
+ if (STREQ(smd->data_path, state->name)) {
+ if (state->type == SIM_STATE_TYPE_PARTICLES) {
+ return (ParticleSimulationState *)state;
+ }
}
}
return nullptr;
@@ -121,7 +129,7 @@ static PointCloud *modifyPointCloud(ModifierData *md,
memcpy(pointcloud->co, positions, sizeof(float3) * state->tot_particles);
for (int i = 0; i < state->tot_particles; i++) {
- pointcloud->radius[i] = 0.05f;
+ pointcloud->radius[i] = 0.1f;
}
return pointcloud;
@@ -146,6 +154,37 @@ static void panelRegister(ARegionType *region_type)
modifier_panel_register(region_type, eModifierType_Simulation, panel_draw);
}
+static void blendWrite(BlendWriter *writer, const ModifierData *md)
+{
+ const SimulationModifierData *smd = (const SimulationModifierData *)md;
+ BLO_write_string(writer, smd->data_path);
+}
+
+static void blendRead(BlendDataReader *reader, ModifierData *md)
+{
+ SimulationModifierData *smd = (SimulationModifierData *)md;
+ BLO_read_data_address(reader, &smd->data_path);
+}
+
+static void copyData(const ModifierData *md, ModifierData *target, const int flag)
+{
+ const SimulationModifierData *smd = (const SimulationModifierData *)md;
+ SimulationModifierData *tsmd = (SimulationModifierData *)target;
+
+ BKE_modifier_copydata_generic(md, target, flag);
+ if (smd->data_path != nullptr) {
+ tsmd->data_path = BLI_strdup(smd->data_path);
+ }
+}
+
+static void freeData(ModifierData *md)
+{
+ SimulationModifierData *smd = (SimulationModifierData *)md;
+ if (smd->data_path) {
+ MEM_freeN(smd->data_path);
+ }
+}
+
ModifierTypeInfo modifierType_Simulation = {
/* name */ "Simulation",
/* structName */ "SimulationModifierData",
@@ -153,7 +192,7 @@ ModifierTypeInfo modifierType_Simulation = {
/* type */ eModifierTypeType_None,
/* flags */ (ModifierTypeFlag)0,
- /* copyData */ BKE_modifier_copydata_generic,
+ /* copyData */ copyData,
/* deformVerts */ NULL,
/* deformMatrices */ NULL,
@@ -166,7 +205,7 @@ ModifierTypeInfo modifierType_Simulation = {
/* initData */ NULL,
/* requiredDataMask */ NULL,
- /* freeData */ NULL,
+ /* freeData */ freeData,
/* isDisabled */ isDisabled,
/* updateDepsgraph */ updateDepsgraph,
/* dependsOnTime */ NULL,
@@ -176,6 +215,6 @@ ModifierTypeInfo modifierType_Simulation = {
/* foreachTexLink */ NULL,
/* freeRuntimeData */ NULL,
/* panelRegister */ panelRegister,
- /* blendWrite */ NULL,
- /* blendRead */ NULL,
+ /* blendWrite */ blendWrite,
+ /* blendRead */ blendRead,
};