Simulation: cleanup dna data
This commit is contained in:
@@ -112,9 +112,8 @@ static void simulation_copy_data(Main *bmain, ID *id_dst, const ID *id_src, cons
|
||||
BKE_simulation_state_copy_data(state_src, state_dst);
|
||||
}
|
||||
|
||||
BLI_listbase_clear(&simulation_dst->persistent_data_handles);
|
||||
BLI_duplicatelist(&simulation_dst->persistent_data_handles,
|
||||
&simulation_src->persistent_data_handles);
|
||||
BLI_listbase_clear(&simulation_dst->dependencies);
|
||||
BLI_duplicatelist(&simulation_dst->dependencies, &simulation_src->dependencies);
|
||||
}
|
||||
|
||||
static void simulation_free_data(ID *id)
|
||||
@@ -131,7 +130,7 @@ static void simulation_free_data(ID *id)
|
||||
|
||||
BKE_simulation_state_remove_all(simulation);
|
||||
|
||||
BLI_freelistN(&simulation->persistent_data_handles);
|
||||
BLI_freelistN(&simulation->dependencies);
|
||||
}
|
||||
|
||||
static void simulation_foreach_id(ID *id, LibraryForeachIDData *data)
|
||||
@@ -141,9 +140,8 @@ static void simulation_foreach_id(ID *id, LibraryForeachIDData *data)
|
||||
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
|
||||
BKE_library_foreach_ID_embedded(data, (ID **)&simulation->nodetree);
|
||||
}
|
||||
LISTBASE_FOREACH (
|
||||
PersistentDataHandleItem *, handle_item, &simulation->persistent_data_handles) {
|
||||
BKE_LIB_FOREACHID_PROCESS_ID(data, handle_item->id, IDWALK_CB_USER);
|
||||
LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation->dependencies) {
|
||||
BKE_LIB_FOREACHID_PROCESS_ID(data, dependency->id, IDWALK_CB_USER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8677,9 +8677,8 @@ static void direct_link_volume(BlendDataReader *reader, Volume *volume)
|
||||
|
||||
static void lib_link_simulation(BlendLibReader *reader, Simulation *simulation)
|
||||
{
|
||||
LISTBASE_FOREACH (
|
||||
PersistentDataHandleItem *, handle_item, &simulation->persistent_data_handles) {
|
||||
BLO_read_id_address(reader, simulation->id.lib, &handle_item->id);
|
||||
LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation->dependencies) {
|
||||
BLO_read_id_address(reader, simulation->id.lib, &dependency->id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8698,7 +8697,7 @@ static void direct_link_simulation(BlendDataReader *reader, Simulation *simulati
|
||||
}
|
||||
}
|
||||
|
||||
BLO_read_list(reader, &simulation->persistent_data_handles);
|
||||
BLO_read_list(reader, &simulation->dependencies);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -11107,9 +11106,8 @@ static void expand_simulation(BlendExpander *expander, Simulation *simulation)
|
||||
if (simulation->adt) {
|
||||
expand_animdata(expander, simulation->adt);
|
||||
}
|
||||
LISTBASE_FOREACH (
|
||||
PersistentDataHandleItem *, handle_item, &simulation->persistent_data_handles) {
|
||||
BLO_expand(expander, handle_item->id);
|
||||
LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation->dependencies) {
|
||||
BLO_expand(expander, dependency->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3862,7 +3862,7 @@ static void write_simulation(BlendWriter *writer, Simulation *simulation, const
|
||||
}
|
||||
}
|
||||
|
||||
BLO_write_struct_list(writer, PersistentDataHandleItem, &simulation->persistent_data_handles);
|
||||
BLO_write_struct_list(writer, SimulationDependency, &simulation->dependencies);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2636,19 +2636,18 @@ void DepsgraphRelationBuilder::build_simulation(Simulation *simulation)
|
||||
&simulation->nodetree->id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EXIT);
|
||||
add_relation(nodetree_key, simulation_eval_key, "NodeTree -> Simulation", 0);
|
||||
|
||||
LISTBASE_FOREACH (
|
||||
PersistentDataHandleItem *, handle_item, &simulation->persistent_data_handles) {
|
||||
if (handle_item->id == nullptr) {
|
||||
LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation->dependencies) {
|
||||
if (dependency->id == nullptr) {
|
||||
continue;
|
||||
}
|
||||
build_id(handle_item->id);
|
||||
if (GS(handle_item->id->name) == ID_OB) {
|
||||
Object *object = (Object *)handle_item->id;
|
||||
if (handle_item->flag & SIM_HANDLE_DEPENDS_ON_TRANSFORM) {
|
||||
build_id(dependency->id);
|
||||
if (GS(dependency->id->name) == ID_OB) {
|
||||
Object *object = (Object *)dependency->id;
|
||||
if (dependency->flag & SIM_DEPENDS_ON_TRANSFORM) {
|
||||
ComponentKey object_transform_key(&object->id, NodeType::TRANSFORM);
|
||||
add_relation(object_transform_key, simulation_eval_key, "Object Transform -> Simulation");
|
||||
}
|
||||
if (handle_item->flag & SIM_HANDLE_DEPENDS_ON_GEOMETRY) {
|
||||
if (dependency->flag & SIM_DEPENDS_ON_GEOMETRY) {
|
||||
ComponentKey object_geometry_key(&object->id, NodeType::GEOMETRY);
|
||||
add_relation(object_geometry_key, simulation_eval_key, "Object Geometry -> Simulation");
|
||||
}
|
||||
|
||||
@@ -30,16 +30,21 @@ typedef struct Simulation {
|
||||
|
||||
struct bNodeTree *nodetree;
|
||||
|
||||
int flag;
|
||||
uint32_t flag;
|
||||
|
||||
/** This is the frame in scene time, that the states correspond to. */
|
||||
float current_frame;
|
||||
|
||||
/** Time since the start of the simulation in simulation time (which might differ from scene
|
||||
* time). */
|
||||
float current_simulation_time;
|
||||
char _pad[4];
|
||||
|
||||
/** List containing SimulationState objects. */
|
||||
struct ListBase states;
|
||||
|
||||
/** List containing PersistentDataHandleItem objects. */
|
||||
struct ListBase persistent_data_handles;
|
||||
/** List containing SimulationDependency objects. */
|
||||
struct ListBase dependencies;
|
||||
} Simulation;
|
||||
|
||||
typedef struct SimulationState {
|
||||
@@ -54,8 +59,8 @@ typedef struct ParticleSimulationState {
|
||||
SimulationState head;
|
||||
|
||||
/** Contains the state of the particles at time Simulation->current_frame. */
|
||||
int tot_particles;
|
||||
int next_particle_id;
|
||||
int32_t tot_particles;
|
||||
int32_t next_particle_id;
|
||||
struct CustomData attributes;
|
||||
} ParticleSimulationState;
|
||||
|
||||
@@ -66,24 +71,25 @@ typedef struct ParticleMeshEmitterSimulationState {
|
||||
char _pad[4];
|
||||
} ParticleMeshEmitterSimulationState;
|
||||
|
||||
/** Stores a mapping between an integer handle and a corresponding ID data block. */
|
||||
typedef struct PersistentDataHandleItem {
|
||||
struct PersistentDataHandleItem *next;
|
||||
struct PersistentDataHandleItem *prev;
|
||||
/** Stores a reference to data that the simulation depends on. This is partially derived from the
|
||||
* simulation node tree. */
|
||||
typedef struct SimulationDependency {
|
||||
struct SimulationDependency *next;
|
||||
struct SimulationDependency *prev;
|
||||
struct ID *id;
|
||||
int handle;
|
||||
int flag;
|
||||
} PersistentDataHandleItem;
|
||||
int32_t handle;
|
||||
uint32_t flag;
|
||||
} SimulationDependency;
|
||||
|
||||
/* Simulation.flag */
|
||||
enum {
|
||||
SIM_DS_EXPAND = (1 << 0),
|
||||
};
|
||||
|
||||
/* PersistentDataHandleItem.flag */
|
||||
/* SimulationDependency.flag */
|
||||
enum {
|
||||
SIM_HANDLE_DEPENDS_ON_TRANSFORM = (1 << 0),
|
||||
SIM_HANDLE_DEPENDS_ON_GEOMETRY = (1 << 1),
|
||||
SIM_DEPENDS_ON_TRANSFORM = (1 << 0),
|
||||
SIM_DEPENDS_ON_GEOMETRY = (1 << 1),
|
||||
};
|
||||
|
||||
#define SIM_TYPE_NAME_PARTICLE_SIMULATION "Particle Simulation"
|
||||
|
||||
@@ -115,10 +115,9 @@ void update_simulation_in_depsgraph(Depsgraph *depsgraph,
|
||||
collect_simulation_influences(*simulation_cow, resources, influences, required_states);
|
||||
|
||||
bke::PersistentDataHandleMap handle_map;
|
||||
LISTBASE_FOREACH (
|
||||
PersistentDataHandleItem *, handle_item, &simulation_orig->persistent_data_handles) {
|
||||
ID *id_cow = DEG_get_evaluated_id(depsgraph, handle_item->id);
|
||||
handle_map.add(handle_item->handle, *id_cow);
|
||||
LISTBASE_FOREACH (SimulationDependency *, dependency, &simulation_orig->dependencies) {
|
||||
ID *id_cow = DEG_get_evaluated_id(depsgraph, dependency->id);
|
||||
handle_map.add(dependency->handle, *id_cow);
|
||||
}
|
||||
|
||||
if (current_frame == 1) {
|
||||
@@ -146,28 +145,28 @@ bool update_simulation_dependencies(Simulation *simulation)
|
||||
nodes::NodeTreeDependencies dependencies = nodes::find_node_tree_dependencies(
|
||||
*simulation->nodetree);
|
||||
|
||||
ListBase *handle_list = &simulation->persistent_data_handles;
|
||||
ListBase *dependency_list = &simulation->dependencies;
|
||||
|
||||
bool dependencies_changed = false;
|
||||
|
||||
Map<ID *, PersistentDataHandleItem *> handle_item_by_id;
|
||||
Map<PersistentDataHandleItem *, int> old_flag_by_handle_item;
|
||||
Map<ID *, SimulationDependency *> dependency_by_id;
|
||||
Map<SimulationDependency *, int> old_flag_by_dependency;
|
||||
Set<int> used_handles;
|
||||
|
||||
/* Remove unused handle items and clear flags that are reinitialized later. */
|
||||
LISTBASE_FOREACH_MUTABLE (PersistentDataHandleItem *, handle_item, handle_list) {
|
||||
if (dependencies.depends_on(handle_item->id)) {
|
||||
handle_item_by_id.add_new(handle_item->id, handle_item);
|
||||
used_handles.add_new(handle_item->handle);
|
||||
old_flag_by_handle_item.add_new(handle_item, handle_item->flag);
|
||||
handle_item->flag &= ~(SIM_HANDLE_DEPENDS_ON_TRANSFORM | SIM_HANDLE_DEPENDS_ON_GEOMETRY);
|
||||
LISTBASE_FOREACH_MUTABLE (SimulationDependency *, dependency, dependency_list) {
|
||||
if (dependencies.depends_on(dependency->id)) {
|
||||
dependency_by_id.add_new(dependency->id, dependency);
|
||||
used_handles.add_new(dependency->handle);
|
||||
old_flag_by_dependency.add_new(dependency, dependency->flag);
|
||||
dependency->flag &= ~(SIM_DEPENDS_ON_TRANSFORM | SIM_DEPENDS_ON_GEOMETRY);
|
||||
}
|
||||
else {
|
||||
if (handle_item->id != nullptr) {
|
||||
id_us_min(handle_item->id);
|
||||
if (dependency->id != nullptr) {
|
||||
id_us_min(dependency->id);
|
||||
}
|
||||
BLI_remlink(handle_list, handle_item);
|
||||
MEM_freeN(handle_item);
|
||||
BLI_remlink(dependency_list, dependency);
|
||||
MEM_freeN(dependency);
|
||||
dependencies_changed = true;
|
||||
}
|
||||
}
|
||||
@@ -175,38 +174,38 @@ bool update_simulation_dependencies(Simulation *simulation)
|
||||
/* Add handle items for new id dependencies. */
|
||||
int next_handle = 0;
|
||||
for (ID *id : dependencies.id_dependencies()) {
|
||||
handle_item_by_id.lookup_or_add_cb(id, [&]() {
|
||||
dependency_by_id.lookup_or_add_cb(id, [&]() {
|
||||
while (used_handles.contains(next_handle)) {
|
||||
next_handle++;
|
||||
}
|
||||
used_handles.add_new(next_handle);
|
||||
|
||||
PersistentDataHandleItem *handle_item = (PersistentDataHandleItem *)MEM_callocN(
|
||||
sizeof(*handle_item), AT);
|
||||
SimulationDependency *dependency = (SimulationDependency *)MEM_callocN(sizeof(*dependency),
|
||||
AT);
|
||||
id_us_plus(id);
|
||||
handle_item->id = id;
|
||||
handle_item->handle = next_handle;
|
||||
BLI_addtail(handle_list, handle_item);
|
||||
dependency->id = id;
|
||||
dependency->handle = next_handle;
|
||||
BLI_addtail(dependency_list, dependency);
|
||||
|
||||
return handle_item;
|
||||
return dependency;
|
||||
});
|
||||
}
|
||||
|
||||
/* Set appropriate dependency flags. */
|
||||
for (Object *object : dependencies.transform_dependencies()) {
|
||||
PersistentDataHandleItem *handle_item = handle_item_by_id.lookup(&object->id);
|
||||
handle_item->flag |= SIM_HANDLE_DEPENDS_ON_TRANSFORM;
|
||||
SimulationDependency *dependency = dependency_by_id.lookup(&object->id);
|
||||
dependency->flag |= SIM_DEPENDS_ON_TRANSFORM;
|
||||
}
|
||||
for (Object *object : dependencies.geometry_dependencies()) {
|
||||
PersistentDataHandleItem *handle_item = handle_item_by_id.lookup(&object->id);
|
||||
handle_item->flag |= SIM_HANDLE_DEPENDS_ON_GEOMETRY;
|
||||
SimulationDependency *dependency = dependency_by_id.lookup(&object->id);
|
||||
dependency->flag |= SIM_DEPENDS_ON_GEOMETRY;
|
||||
}
|
||||
|
||||
if (!dependencies_changed) {
|
||||
/* Check if any flags have changed. */
|
||||
LISTBASE_FOREACH (PersistentDataHandleItem *, handle_item, handle_list) {
|
||||
int old_flag = old_flag_by_handle_item.lookup_default(handle_item, 0);
|
||||
int new_flag = handle_item->flag;
|
||||
LISTBASE_FOREACH (SimulationDependency *, dependency, dependency_list) {
|
||||
uint32_t old_flag = old_flag_by_dependency.lookup_default(dependency, 0);
|
||||
uint32_t new_flag = dependency->flag;
|
||||
if (old_flag != new_flag) {
|
||||
dependencies_changed = true;
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user