Depsgraph: Refactor, split runtime backup into smaller files

It started to be a long code of all various cases in a single file,
which started to be really confusing.
This commit is contained in:
Sergey Sharybin
2019-11-29 11:43:40 +01:00
parent fc2b966fc7
commit d1166dcf31
20 changed files with 1176 additions and 541 deletions

View File

@@ -58,6 +58,15 @@ set(SRC
intern/eval/deg_eval.cc
intern/eval/deg_eval_copy_on_write.cc
intern/eval/deg_eval_flush.cc
intern/eval/deg_eval_runtime_backup.cc
intern/eval/deg_eval_runtime_backup_modifier.cc
intern/eval/deg_eval_runtime_backup_movieclip.cc
intern/eval/deg_eval_runtime_backup_object.cc
intern/eval/deg_eval_runtime_backup_pose.cc
intern/eval/deg_eval_runtime_backup_scene.cc
intern/eval/deg_eval_runtime_backup_sequence.cc
intern/eval/deg_eval_runtime_backup_sequencer.cc
intern/eval/deg_eval_runtime_backup_sound.cc
intern/eval/deg_eval_stats.cc
intern/node/deg_node.cc
intern/node/deg_node_component.cc
@@ -98,6 +107,15 @@ set(SRC
intern/eval/deg_eval.h
intern/eval/deg_eval_copy_on_write.h
intern/eval/deg_eval_flush.h
intern/eval/deg_eval_runtime_backup.h
intern/eval/deg_eval_runtime_backup_modifier.h
intern/eval/deg_eval_runtime_backup_movieclip.h
intern/eval/deg_eval_runtime_backup_object.h
intern/eval/deg_eval_runtime_backup_pose.h
intern/eval/deg_eval_runtime_backup_scene.h
intern/eval/deg_eval_runtime_backup_sequence.h
intern/eval/deg_eval_runtime_backup_sequencer.h
intern/eval/deg_eval_runtime_backup_sound.h
intern/eval/deg_eval_stats.h
intern/node/deg_node.h
intern/node/deg_node_component.h

View File

@@ -21,7 +21,7 @@
* \ingroup depsgraph
*/
/* Enable special; trickery to treat nested owned IDs (such as nodetree of
/* Enable special trickery to treat nested owned IDs (such as nodetree of
* material) to be handled in same way as "real" data-blocks, even tho some
* internal BKE routines doesn't treat them like that.
*
@@ -95,6 +95,7 @@ extern "C" {
#include "intern/depsgraph.h"
#include "intern/builder/deg_builder.h"
#include "intern/builder/deg_builder_nodes.h"
#include "intern/eval/deg_eval_runtime_backup.h"
#include "intern/node/deg_node.h"
#include "intern/node/deg_node_id.h"
@@ -945,545 +946,6 @@ ID *deg_expand_copy_on_write_datablock(const Depsgraph *depsgraph,
return deg_expand_copy_on_write_datablock(depsgraph, id_node, node_builder, create_placeholders);
}
namespace {
/* Backup of sequencer strips runtime data. */
/* Backup of a single strip. */
class SequenceBackup {
public:
SequenceBackup()
{
reset();
}
inline void reset()
{
scene_sound = NULL;
}
void init_from_sequence(Sequence *sequence)
{
scene_sound = sequence->scene_sound;
sequence->scene_sound = NULL;
}
void restore_to_sequence(Sequence *sequence)
{
sequence->scene_sound = scene_sound;
reset();
}
inline bool isEmpty() const
{
return (scene_sound == NULL);
}
void *scene_sound;
};
class SequencerBackup {
public:
SequencerBackup();
void init_from_scene(Scene *scene);
void restore_to_scene(Scene *scene);
typedef map<Sequence *, SequenceBackup> SequencesBackupMap;
SequencesBackupMap sequences_backup;
};
SequencerBackup::SequencerBackup()
{
}
void SequencerBackup::init_from_scene(Scene *scene)
{
Sequence *sequence;
SEQ_BEGIN (scene->ed, sequence) {
SequenceBackup sequence_backup;
sequence_backup.init_from_sequence(sequence);
if (!sequence_backup.isEmpty()) {
sequences_backup.insert(make_pair(sequence->orig_sequence, sequence_backup));
}
}
SEQ_END;
}
void SequencerBackup::restore_to_scene(Scene *scene)
{
Sequence *sequence;
SEQ_BEGIN (scene->ed, sequence) {
SequencesBackupMap::iterator it = sequences_backup.find(sequence->orig_sequence);
if (it == sequences_backup.end()) {
continue;
}
SequenceBackup &sequence_backup = it->second;
sequence_backup.restore_to_sequence(sequence);
}
SEQ_END;
/* Cleanup audio while the scene is still known. */
for (SequencesBackupMap::value_type &it : sequences_backup) {
SequenceBackup &sequence_backup = it.second;
if (sequence_backup.scene_sound != NULL) {
BKE_sound_remove_scene_sound(scene, sequence_backup.scene_sound);
}
}
}
/* Backup of scene runtime data. */
class SceneBackup {
public:
SceneBackup();
void reset();
void init_from_scene(Scene *scene);
void restore_to_scene(Scene *scene);
/* Sound/audio related pointers of the scene itself.
*
* NOTE: Scene can not disappear after relations update, because otherwise the entire dependency
* graph will be gone. This means we don't need to compare original scene pointer, or worry about
* freeing those if they cant' be restored: we just copy them over to a new scene. */
void *sound_scene;
void *playback_handle;
void *sound_scrub_handle;
void *speaker_handles;
float rigidbody_last_time;
SequencerBackup sequencer_backup;
};
SceneBackup::SceneBackup()
{
reset();
}
void SceneBackup::reset()
{
sound_scene = NULL;
playback_handle = NULL;
sound_scrub_handle = NULL;
speaker_handles = NULL;
rigidbody_last_time = -1;
}
void SceneBackup::init_from_scene(Scene *scene)
{
sound_scene = scene->sound_scene;
playback_handle = scene->playback_handle;
sound_scrub_handle = scene->sound_scrub_handle;
speaker_handles = scene->speaker_handles;
if (scene->rigidbody_world != NULL) {
rigidbody_last_time = scene->rigidbody_world->ltime;
}
/* Clear pointers stored in the scene, so they are not freed when copied-on-written datablock
* is freed for re-allocation. */
scene->sound_scene = NULL;
scene->playback_handle = NULL;
scene->sound_scrub_handle = NULL;
scene->speaker_handles = NULL;
sequencer_backup.init_from_scene(scene);
}
void SceneBackup::restore_to_scene(Scene *scene)
{
scene->sound_scene = sound_scene;
scene->playback_handle = playback_handle;
scene->sound_scrub_handle = sound_scrub_handle;
scene->speaker_handles = speaker_handles;
if (scene->rigidbody_world != NULL) {
scene->rigidbody_world->ltime = rigidbody_last_time;
}
sequencer_backup.restore_to_scene(scene);
reset();
}
/* Backup of sound datablocks runtime data. */
class SoundBackup {
public:
SoundBackup();
void reset();
void init_from_sound(bSound *sound);
void restore_to_sound(bSound *sound);
void *cache;
void *waveform;
void *playback_handle;
};
SoundBackup::SoundBackup()
{
reset();
}
void SoundBackup::reset()
{
cache = NULL;
waveform = NULL;
playback_handle = NULL;
}
void SoundBackup::init_from_sound(bSound *sound)
{
cache = sound->cache;
waveform = sound->waveform;
playback_handle = sound->playback_handle;
sound->cache = NULL;
sound->waveform = NULL;
sound->playback_handle = NULL;
}
void SoundBackup::restore_to_sound(bSound *sound)
{
sound->cache = cache;
sound->waveform = waveform;
sound->playback_handle = playback_handle;
reset();
}
/* Identifier used to match modifiers to backup/restore their runtime data.
* Identification is happening using original modifier data pointer and the
* modifier type.
* It is not enough to only pointer, since it's possible to have a situation
* when modifier is removed and a new one added, and due to memory allocation
* policy they might have same pointer.
* By adding type into matching we are at least ensuring that modifier will not
* try to interpret runtime data created by another modifier type. */
class ModifierDataBackupID {
public:
ModifierDataBackupID() : ModifierDataBackupID(NULL, eModifierType_None)
{
}
ModifierDataBackupID(ModifierData *modifier_data, ModifierType type)
: modifier_data(modifier_data), type(type)
{
}
bool operator<(const ModifierDataBackupID &other) const
{
if (modifier_data < other.modifier_data) {
return true;
}
if (modifier_data == other.modifier_data) {
return static_cast<int>(type) < static_cast<int>(other.type);
}
return false;
}
ModifierData *modifier_data;
ModifierType type;
};
/* Storage for backed up runtime modifier data. */
typedef map<ModifierDataBackupID, void *> ModifierRuntimeDataBackup;
/* Storage for backed up pose channel runtime data. */
typedef map<bPoseChannel *, bPoseChannel_Runtime> PoseChannelRuntimeDataBackup;
class ObjectRuntimeBackup {
public:
ObjectRuntimeBackup() : base_flag(0), base_local_view_bits(0)
{
/* TODO(sergey): Use something like BKE_object_runtime_reset(). */
memset(&runtime, 0, sizeof(runtime));
}
/* Make a backup of object's evaluation runtime data, additionally
* make object to be safe for free without invalidating backed up
* pointers. */
void init_from_object(Object *object);
void backup_modifier_runtime_data(Object *object);
void backup_pose_channel_runtime_data(Object *object);
/* Restore all fields to the given object. */
void restore_to_object(Object *object);
/* NOTE: Will free all runtime data which has not been restored. */
void restore_modifier_runtime_data(Object *object);
void restore_pose_channel_runtime_data(Object *object);
Object_Runtime runtime;
short base_flag;
unsigned short base_local_view_bits;
ModifierRuntimeDataBackup modifier_runtime_data;
PoseChannelRuntimeDataBackup pose_channel_runtime_data;
};
void ObjectRuntimeBackup::init_from_object(Object *object)
{
/* Store evaluated mesh and curve_cache, and make sure we don't free it. */
Mesh *mesh_eval = object->runtime.mesh_eval;
runtime = object->runtime;
BKE_object_runtime_reset(object);
/* Keep bbox (for now at least). */
object->runtime.bb = runtime.bb;
/* Object update will override actual object->data to an evaluated version.
* Need to make sure we don't have data set to evaluated one before free
* anything. */
if (mesh_eval != NULL && object->data == mesh_eval) {
object->data = runtime.mesh_orig;
}
/* Make a backup of base flags. */
base_flag = object->base_flag;
base_local_view_bits = object->base_local_view_bits;
/* Backup tuntime data of all modifiers. */
backup_modifier_runtime_data(object);
/* Backup runtime data of all pose channels. */
backup_pose_channel_runtime_data(object);
}
inline ModifierDataBackupID create_modifier_data_id(const ModifierData *modifier_data)
{
return ModifierDataBackupID(modifier_data->orig_modifier_data,
static_cast<ModifierType>(modifier_data->type));
}
void ObjectRuntimeBackup::backup_modifier_runtime_data(Object *object)
{
LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) {
if (modifier_data->runtime == NULL) {
continue;
}
BLI_assert(modifier_data->orig_modifier_data != NULL);
ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data);
modifier_runtime_data.insert(make_pair(modifier_data_id, modifier_data->runtime));
modifier_data->runtime = NULL;
}
}
void ObjectRuntimeBackup::backup_pose_channel_runtime_data(Object *object)
{
if (object->pose != NULL) {
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
/* This is NULL in Edit mode. */
if (pchan->orig_pchan != NULL) {
pose_channel_runtime_data[pchan->orig_pchan] = pchan->runtime;
BKE_pose_channel_runtime_reset(&pchan->runtime);
}
}
}
}
void ObjectRuntimeBackup::restore_to_object(Object *object)
{
Mesh *mesh_orig = object->runtime.mesh_orig;
BoundBox *bb = object->runtime.bb;
object->runtime = runtime;
object->runtime.mesh_orig = mesh_orig;
object->runtime.bb = bb;
if (object->type == OB_MESH && object->runtime.mesh_eval != NULL) {
if (object->id.recalc & ID_RECALC_GEOMETRY) {
/* If geometry is tagged for update it means, that part of
* evaluated mesh are not valid anymore. In this case we can not
* have any "persistent" pointers to point to an invalid data.
*
* We restore object's data datablock to an original copy of
* that datablock. */
object->data = mesh_orig;
/* After that, immediately free the invalidated caches. */
BKE_object_free_derived_caches(object);
}
else {
Mesh *mesh_eval = object->runtime.mesh_eval;
/* Do same thing as object update: override actual object data
* pointer with evaluated datablock. */
object->data = mesh_eval;
/* Evaluated mesh simply copied edit_mesh pointer from
* original mesh during update, need to make sure no dead
* pointers are left behind. */
mesh_eval->edit_mesh = mesh_orig->edit_mesh;
}
}
object->base_flag = base_flag;
object->base_local_view_bits = base_local_view_bits;
/* Restore modifier's runtime data.
* NOTE: Data of unused modifiers will be freed there. */
restore_modifier_runtime_data(object);
restore_pose_channel_runtime_data(object);
}
void ObjectRuntimeBackup::restore_modifier_runtime_data(Object *object)
{
LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) {
BLI_assert(modifier_data->orig_modifier_data != NULL);
ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data);
ModifierRuntimeDataBackup::iterator runtime_data_iterator = modifier_runtime_data.find(
modifier_data_id);
if (runtime_data_iterator != modifier_runtime_data.end()) {
modifier_data->runtime = runtime_data_iterator->second;
runtime_data_iterator->second = NULL;
}
}
for (ModifierRuntimeDataBackup::value_type value : modifier_runtime_data) {
const ModifierDataBackupID modifier_data_id = value.first;
void *runtime = value.second;
if (value.second == NULL) {
continue;
}
const ModifierTypeInfo *modifier_type_info = modifierType_getInfo(modifier_data_id.type);
BLI_assert(modifier_type_info != NULL);
modifier_type_info->freeRuntimeData(runtime);
}
}
void ObjectRuntimeBackup::restore_pose_channel_runtime_data(Object *object)
{
if (object->pose != NULL) {
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
/* This is NULL in Edit mode. */
if (pchan->orig_pchan != NULL) {
PoseChannelRuntimeDataBackup::iterator runtime_data_iterator =
pose_channel_runtime_data.find(pchan->orig_pchan);
if (runtime_data_iterator != pose_channel_runtime_data.end()) {
pchan->runtime = runtime_data_iterator->second;
pose_channel_runtime_data.erase(runtime_data_iterator);
}
}
}
}
for (PoseChannelRuntimeDataBackup::value_type &value : pose_channel_runtime_data) {
BKE_pose_channel_runtime_free(&value.second);
}
}
/* Backup of movie clip runtime data. */
class MovieClipBackup {
public:
MovieClipBackup();
void reset();
void init_from_movieclip(MovieClip *movieclip);
void restore_to_movieclip(MovieClip *movieclip);
struct anim *anim;
struct MovieClipCache *cache;
};
MovieClipBackup::MovieClipBackup()
{
reset();
}
void MovieClipBackup::reset()
{
anim = NULL;
cache = NULL;
}
void MovieClipBackup::init_from_movieclip(MovieClip *movieclip)
{
anim = movieclip->anim;
cache = movieclip->cache;
/* Clear pointers stored in the movie clip, so they are not freed when copied-on-written
* datablock is freed for re-allocation. */
movieclip->anim = NULL;
movieclip->cache = NULL;
}
void MovieClipBackup::restore_to_movieclip(MovieClip *movieclip)
{
movieclip->anim = anim;
movieclip->cache = cache;
reset();
}
class RuntimeBackup {
public:
RuntimeBackup() : drawdata_ptr(NULL)
{
drawdata_backup.first = drawdata_backup.last = NULL;
}
/* NOTE: Will reset all runbtime fields which has been backed up to NULL. */
void init_from_id(ID *id);
/* Restore fields to the given ID. */
void restore_to_id(ID *id);
SceneBackup scene_backup;
SoundBackup sound_backup;
ObjectRuntimeBackup object_backup;
DrawDataList drawdata_backup;
DrawDataList *drawdata_ptr;
MovieClipBackup movieclip_backup;
};
void RuntimeBackup::init_from_id(ID *id)
{
if (!check_datablock_expanded(id)) {
return;
}
const ID_Type id_type = GS(id->name);
switch (id_type) {
case ID_OB:
object_backup.init_from_object(reinterpret_cast<Object *>(id));
break;
case ID_SCE:
scene_backup.init_from_scene(reinterpret_cast<Scene *>(id));
break;
case ID_SO:
sound_backup.init_from_sound(reinterpret_cast<bSound *>(id));
break;
case ID_MC:
movieclip_backup.init_from_movieclip(reinterpret_cast<MovieClip *>(id));
break;
default:
break;
}
/* Note that we never free GPU draw data from here since that's not
* safe for threading and draw data is likely to be re-used. */
drawdata_ptr = DRW_drawdatalist_from_id(id);
if (drawdata_ptr != NULL) {
drawdata_backup = *drawdata_ptr;
drawdata_ptr->first = drawdata_ptr->last = NULL;
}
}
void RuntimeBackup::restore_to_id(ID *id)
{
const ID_Type id_type = GS(id->name);
switch (id_type) {
case ID_OB:
object_backup.restore_to_object(reinterpret_cast<Object *>(id));
break;
case ID_SCE:
scene_backup.restore_to_scene(reinterpret_cast<Scene *>(id));
break;
case ID_SO:
sound_backup.restore_to_sound(reinterpret_cast<bSound *>(id));
break;
case ID_MC:
movieclip_backup.restore_to_movieclip(reinterpret_cast<MovieClip *>(id));
break;
default:
break;
}
if (drawdata_ptr != NULL) {
*drawdata_ptr = drawdata_backup;
}
}
} // namespace
ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode *id_node)
{
const ID *id_orig = id_node->id_orig;
@@ -1492,7 +954,7 @@ ID *deg_update_copy_on_write_datablock(const Depsgraph *depsgraph, const IDNode
if (!deg_copy_on_write_is_needed(id_orig)) {
return id_cow;
}
RuntimeBackup backup;
RuntimeBackup backup(depsgraph);
backup.init_from_id(id_cow);
deg_free_copy_on_write_datablock(id_cow);
deg_expand_copy_on_write_datablock(depsgraph, id_node);

View File

@@ -0,0 +1,101 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2017 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*/
#include "intern/eval/deg_eval_runtime_backup.h"
#include "intern/eval/deg_eval_copy_on_write.h"
#include "BLI_utildefines.h"
#include "DRW_engine.h"
namespace DEG {
RuntimeBackup::RuntimeBackup(const Depsgraph *depsgraph)
: scene_backup(depsgraph),
sound_backup(depsgraph),
object_backup(depsgraph),
drawdata_ptr(NULL),
movieclip_backup(depsgraph)
{
drawdata_backup.first = drawdata_backup.last = NULL;
}
void RuntimeBackup::init_from_id(ID *id)
{
if (!deg_copy_on_write_is_expanded(id)) {
return;
}
const ID_Type id_type = GS(id->name);
switch (id_type) {
case ID_OB:
object_backup.init_from_object(reinterpret_cast<Object *>(id));
break;
case ID_SCE:
scene_backup.init_from_scene(reinterpret_cast<Scene *>(id));
break;
case ID_SO:
sound_backup.init_from_sound(reinterpret_cast<bSound *>(id));
break;
case ID_MC:
movieclip_backup.init_from_movieclip(reinterpret_cast<MovieClip *>(id));
break;
default:
break;
}
/* Note that we never free GPU draw data from here since that's not
* safe for threading and draw data is likely to be re-used. */
drawdata_ptr = DRW_drawdatalist_from_id(id);
if (drawdata_ptr != NULL) {
drawdata_backup = *drawdata_ptr;
drawdata_ptr->first = drawdata_ptr->last = NULL;
}
}
void RuntimeBackup::restore_to_id(ID *id)
{
const ID_Type id_type = GS(id->name);
switch (id_type) {
case ID_OB:
object_backup.restore_to_object(reinterpret_cast<Object *>(id));
break;
case ID_SCE:
scene_backup.restore_to_scene(reinterpret_cast<Scene *>(id));
break;
case ID_SO:
sound_backup.restore_to_sound(reinterpret_cast<bSound *>(id));
break;
case ID_MC:
movieclip_backup.restore_to_movieclip(reinterpret_cast<MovieClip *>(id));
break;
default:
break;
}
if (drawdata_ptr != NULL) {
*drawdata_ptr = drawdata_backup;
}
}
} // namespace DEG

View File

@@ -0,0 +1,55 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*/
#pragma once
#include "DNA_ID.h"
#include "intern/eval/deg_eval_runtime_backup_movieclip.h"
#include "intern/eval/deg_eval_runtime_backup_object.h"
#include "intern/eval/deg_eval_runtime_backup_scene.h"
#include "intern/eval/deg_eval_runtime_backup_sound.h"
namespace DEG {
struct Depsgraph;
class RuntimeBackup {
public:
explicit RuntimeBackup(const Depsgraph *depsgraph);
/* NOTE: Will reset all runtime fields which has been backed up to NULL. */
void init_from_id(ID *id);
/* Restore fields to the given ID. */
void restore_to_id(ID *id);
SceneBackup scene_backup;
SoundBackup sound_backup;
ObjectRuntimeBackup object_backup;
DrawDataList drawdata_backup;
DrawDataList *drawdata_ptr;
MovieClipBackup movieclip_backup;
};
} // namespace DEG

View File

@@ -0,0 +1,49 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*/
#include "intern/eval/deg_eval_runtime_backup_modifier.h"
namespace DEG {
ModifierDataBackupID::ModifierDataBackupID(const Depsgraph * /*depsgraph*/)
: ModifierDataBackupID(NULL, eModifierType_None)
{
}
ModifierDataBackupID::ModifierDataBackupID(ModifierData *modifier_data, ModifierType type)
: modifier_data(modifier_data), type(type)
{
}
bool ModifierDataBackupID::operator<(const ModifierDataBackupID &other) const
{
if (modifier_data < other.modifier_data) {
return true;
}
if (modifier_data == other.modifier_data) {
return static_cast<int>(type) < static_cast<int>(other.type);
}
return false;
}
} // namespace DEG

View File

@@ -0,0 +1,58 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*/
#pragma once
#include "BKE_modifier.h"
#include "intern/depsgraph_type.h"
struct ModifierData;
namespace DEG {
struct Depsgraph;
/* Identifier used to match modifiers to backup/restore their runtime data.
* Identification is happening using original modifier data pointer and the
* modifier type.
* It is not enough to only pointer, since it's possible to have a situation
* when modifier is removed and a new one added, and due to memory allocation
* policy they might have same pointer.
* By adding type into matching we are at least ensuring that modifier will not
* try to interpret runtime data created by another modifier type. */
class ModifierDataBackupID {
public:
ModifierDataBackupID(const Depsgraph *depsgraph);
ModifierDataBackupID(ModifierData *modifier_data, ModifierType type);
bool operator<(const ModifierDataBackupID &other) const;
ModifierData *modifier_data;
ModifierType type;
};
/* Storage for backed up runtime modifier data. */
typedef map<ModifierDataBackupID, void *> ModifierRuntimeDataBackup;
} // namespace DEG

View File

@@ -0,0 +1,61 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*/
#include "intern/eval/deg_eval_runtime_backup_movieclip.h"
#include "DNA_movieclip_types.h"
#include "BLI_utildefines.h"
namespace DEG {
MovieClipBackup::MovieClipBackup(const Depsgraph * /*depsgraph*/)
{
reset();
}
void MovieClipBackup::reset()
{
anim = NULL;
cache = NULL;
}
void MovieClipBackup::init_from_movieclip(MovieClip *movieclip)
{
anim = movieclip->anim;
cache = movieclip->cache;
/* Clear pointers stored in the movie clip, so they are not freed when copied-on-written
* datablock is freed for re-allocation. */
movieclip->anim = NULL;
movieclip->cache = NULL;
}
void MovieClipBackup::restore_to_movieclip(MovieClip *movieclip)
{
movieclip->anim = anim;
movieclip->cache = cache;
reset();
}
} // namespace DEG

View File

@@ -0,0 +1,48 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*/
#pragma once
struct anim;
struct MovieClip;
struct MovieClipCache;
namespace DEG {
struct Depsgraph;
/* Backup of movie clip runtime data. */
class MovieClipBackup {
public:
MovieClipBackup(const Depsgraph *depsgraph);
void reset();
void init_from_movieclip(MovieClip *movieclip);
void restore_to_movieclip(MovieClip *movieclip);
struct anim *anim;
struct MovieClipCache *cache;
};
} // namespace DEG

View File

@@ -0,0 +1,182 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*/
#include "intern/eval/deg_eval_runtime_backup_object.h"
#include <cstring>
#include "DNA_mesh_types.h"
#include "BLI_listbase.h"
#include "BKE_action.h"
#include "BKE_object.h"
namespace DEG {
ObjectRuntimeBackup::ObjectRuntimeBackup(const Depsgraph * /*depsgraph*/)
: base_flag(0), base_local_view_bits(0)
{
/* TODO(sergey): Use something like BKE_object_runtime_reset(). */
memset(&runtime, 0, sizeof(runtime));
}
void ObjectRuntimeBackup::init_from_object(Object *object)
{
/* Store evaluated mesh and curve_cache, and make sure we don't free it. */
Mesh *mesh_eval = object->runtime.mesh_eval;
runtime = object->runtime;
BKE_object_runtime_reset(object);
/* Keep bbox (for now at least). */
object->runtime.bb = runtime.bb;
/* Object update will override actual object->data to an evaluated version.
* Need to make sure we don't have data set to evaluated one before free
* anything. */
if (mesh_eval != NULL && object->data == mesh_eval) {
object->data = runtime.mesh_orig;
}
/* Make a backup of base flags. */
base_flag = object->base_flag;
base_local_view_bits = object->base_local_view_bits;
/* Backup tuntime data of all modifiers. */
backup_modifier_runtime_data(object);
/* Backup runtime data of all pose channels. */
backup_pose_channel_runtime_data(object);
}
inline ModifierDataBackupID create_modifier_data_id(const ModifierData *modifier_data)
{
return ModifierDataBackupID(modifier_data->orig_modifier_data,
static_cast<ModifierType>(modifier_data->type));
}
void ObjectRuntimeBackup::backup_modifier_runtime_data(Object *object)
{
LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) {
if (modifier_data->runtime == NULL) {
continue;
}
BLI_assert(modifier_data->orig_modifier_data != NULL);
ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data);
modifier_runtime_data.insert(make_pair(modifier_data_id, modifier_data->runtime));
modifier_data->runtime = NULL;
}
}
void ObjectRuntimeBackup::backup_pose_channel_runtime_data(Object *object)
{
if (object->pose != NULL) {
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
/* This is NULL in Edit mode. */
if (pchan->orig_pchan != NULL) {
pose_channel_runtime_data[pchan->orig_pchan] = pchan->runtime;
BKE_pose_channel_runtime_reset(&pchan->runtime);
}
}
}
}
void ObjectRuntimeBackup::restore_to_object(Object *object)
{
Mesh *mesh_orig = object->runtime.mesh_orig;
BoundBox *bb = object->runtime.bb;
object->runtime = runtime;
object->runtime.mesh_orig = mesh_orig;
object->runtime.bb = bb;
if (object->type == OB_MESH && object->runtime.mesh_eval != NULL) {
if (object->id.recalc & ID_RECALC_GEOMETRY) {
/* If geometry is tagged for update it means, that part of
* evaluated mesh are not valid anymore. In this case we can not
* have any "persistent" pointers to point to an invalid data.
*
* We restore object's data datablock to an original copy of
* that datablock. */
object->data = mesh_orig;
/* After that, immediately free the invalidated caches. */
BKE_object_free_derived_caches(object);
}
else {
Mesh *mesh_eval = object->runtime.mesh_eval;
/* Do same thing as object update: override actual object data
* pointer with evaluated datablock. */
object->data = mesh_eval;
/* Evaluated mesh simply copied edit_mesh pointer from
* original mesh during update, need to make sure no dead
* pointers are left behind. */
mesh_eval->edit_mesh = mesh_orig->edit_mesh;
}
}
object->base_flag = base_flag;
object->base_local_view_bits = base_local_view_bits;
/* Restore modifier's runtime data.
* NOTE: Data of unused modifiers will be freed there. */
restore_modifier_runtime_data(object);
restore_pose_channel_runtime_data(object);
}
void ObjectRuntimeBackup::restore_modifier_runtime_data(Object *object)
{
LISTBASE_FOREACH (ModifierData *, modifier_data, &object->modifiers) {
BLI_assert(modifier_data->orig_modifier_data != NULL);
ModifierDataBackupID modifier_data_id = create_modifier_data_id(modifier_data);
ModifierRuntimeDataBackup::iterator runtime_data_iterator = modifier_runtime_data.find(
modifier_data_id);
if (runtime_data_iterator != modifier_runtime_data.end()) {
modifier_data->runtime = runtime_data_iterator->second;
runtime_data_iterator->second = NULL;
}
}
for (ModifierRuntimeDataBackup::value_type value : modifier_runtime_data) {
const ModifierDataBackupID modifier_data_id = value.first;
void *runtime = value.second;
if (value.second == NULL) {
continue;
}
const ModifierTypeInfo *modifier_type_info = modifierType_getInfo(modifier_data_id.type);
BLI_assert(modifier_type_info != NULL);
modifier_type_info->freeRuntimeData(runtime);
}
}
void ObjectRuntimeBackup::restore_pose_channel_runtime_data(Object *object)
{
if (object->pose != NULL) {
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
/* This is NULL in Edit mode. */
if (pchan->orig_pchan != NULL) {
PoseChannelRuntimeDataBackup::iterator runtime_data_iterator =
pose_channel_runtime_data.find(pchan->orig_pchan);
if (runtime_data_iterator != pose_channel_runtime_data.end()) {
pchan->runtime = runtime_data_iterator->second;
pose_channel_runtime_data.erase(runtime_data_iterator);
}
}
}
}
for (PoseChannelRuntimeDataBackup::value_type &value : pose_channel_runtime_data) {
BKE_pose_channel_runtime_free(&value.second);
}
}
} // namespace DEG

View File

@@ -0,0 +1,59 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*/
#pragma once
#include "DNA_object_types.h"
#include "intern/eval/deg_eval_runtime_backup_modifier.h"
#include "intern/eval/deg_eval_runtime_backup_pose.h"
struct Object;
namespace DEG {
class ObjectRuntimeBackup {
public:
ObjectRuntimeBackup(const Depsgraph *depsgraph);
/* Make a backup of object's evaluation runtime data, additionally
* make object to be safe for free without invalidating backed up
* pointers. */
void init_from_object(Object *object);
void backup_modifier_runtime_data(Object *object);
void backup_pose_channel_runtime_data(Object *object);
/* Restore all fields to the given object. */
void restore_to_object(Object *object);
/* NOTE: Will free all runtime data which has not been restored. */
void restore_modifier_runtime_data(Object *object);
void restore_pose_channel_runtime_data(Object *object);
Object_Runtime runtime;
short base_flag;
unsigned short base_local_view_bits;
ModifierRuntimeDataBackup modifier_runtime_data;
PoseChannelRuntimeDataBackup pose_channel_runtime_data;
};
} // namespace DEG

View File

@@ -0,0 +1,28 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*/
#include "intern/eval/deg_eval_runtime_backup_pose.h"
namespace DEG {
} // namespace DEG

View File

@@ -0,0 +1,37 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*/
#pragma once
#include "intern/depsgraph_type.h"
#include "DNA_action_types.h"
struct bPoseChannel;
namespace DEG {
/* Storage for backed up pose channel runtime data. */
typedef map<bPoseChannel *, bPoseChannel_Runtime> PoseChannelRuntimeDataBackup;
} // namespace DEG

View File

@@ -0,0 +1,82 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*/
#include "intern/eval/deg_eval_runtime_backup_scene.h"
#include "DNA_scene_types.h"
#include "DNA_rigidbody_types.h"
namespace DEG {
SceneBackup::SceneBackup(const Depsgraph *depsgraph) : sequencer_backup(depsgraph)
{
reset();
}
void SceneBackup::reset()
{
sound_scene = NULL;
playback_handle = NULL;
sound_scrub_handle = NULL;
speaker_handles = NULL;
rigidbody_last_time = -1;
}
void SceneBackup::init_from_scene(Scene *scene)
{
sound_scene = scene->sound_scene;
playback_handle = scene->playback_handle;
sound_scrub_handle = scene->sound_scrub_handle;
speaker_handles = scene->speaker_handles;
if (scene->rigidbody_world != NULL) {
rigidbody_last_time = scene->rigidbody_world->ltime;
}
/* Clear pointers stored in the scene, so they are not freed when copied-on-written datablock
* is freed for re-allocation. */
scene->sound_scene = NULL;
scene->playback_handle = NULL;
scene->sound_scrub_handle = NULL;
scene->speaker_handles = NULL;
sequencer_backup.init_from_scene(scene);
}
void SceneBackup::restore_to_scene(Scene *scene)
{
scene->sound_scene = sound_scene;
scene->playback_handle = playback_handle;
scene->sound_scrub_handle = sound_scrub_handle;
scene->speaker_handles = speaker_handles;
if (scene->rigidbody_world != NULL) {
scene->rigidbody_world->ltime = rigidbody_last_time;
}
sequencer_backup.restore_to_scene(scene);
reset();
}
} // namespace DEG

View File

@@ -0,0 +1,58 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*/
#pragma once
#include "intern/eval/deg_eval_runtime_backup_sequencer.h"
struct Scene;
namespace DEG {
struct Depsgraph;
/* Backup of scene runtime data. */
class SceneBackup {
public:
SceneBackup(const Depsgraph *depsgraph);
void reset();
void init_from_scene(Scene *scene);
void restore_to_scene(Scene *scene);
/* Sound/audio related pointers of the scene itself.
*
* NOTE: Scene can not disappear after relations update, because otherwise the entire dependency
* graph will be gone. This means we don't need to compare original scene pointer, or worry about
* freeing those if they cant' be restored: we just copy them over to a new scene. */
void *sound_scene;
void *playback_handle;
void *sound_scrub_handle;
void *speaker_handles;
float rigidbody_last_time;
SequencerBackup sequencer_backup;
};
} // namespace DEG

View File

@@ -0,0 +1,58 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*/
#include "intern/eval/deg_eval_runtime_backup_sequence.h"
#include "DNA_sequence_types.h"
namespace DEG {
SequenceBackup::SequenceBackup(const Depsgraph * /*depsgraph*/)
{
reset();
}
void SequenceBackup::reset()
{
scene_sound = NULL;
}
void SequenceBackup::init_from_sequence(Sequence *sequence)
{
scene_sound = sequence->scene_sound;
sequence->scene_sound = NULL;
}
void SequenceBackup::restore_to_sequence(Sequence *sequence)
{
sequence->scene_sound = scene_sound;
reset();
}
bool SequenceBackup::isEmpty() const
{
return (scene_sound == NULL);
}
} // namespace DEG

View File

@@ -0,0 +1,47 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*/
#pragma once
struct Sequence;
namespace DEG {
struct Depsgraph;
/* Backup of a single strip. */
class SequenceBackup {
public:
SequenceBackup(const Depsgraph *depsgraph);
void reset();
void init_from_sequence(Sequence *sequence);
void restore_to_sequence(Sequence *sequence);
bool isEmpty() const;
void *scene_sound;
};
} // namespace DEG

View File

@@ -0,0 +1,72 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*/
#include "intern/eval/deg_eval_runtime_backup_sequencer.h"
#include "DNA_scene_types.h"
#include "DNA_sequence_types.h"
#include "BKE_sequencer.h"
#include "BKE_sound.h"
namespace DEG {
SequencerBackup::SequencerBackup(const Depsgraph *depsgraph) : depsgraph(depsgraph)
{
}
void SequencerBackup::init_from_scene(Scene *scene)
{
Sequence *sequence;
SEQ_BEGIN (scene->ed, sequence) {
SequenceBackup sequence_backup(depsgraph);
sequence_backup.init_from_sequence(sequence);
if (!sequence_backup.isEmpty()) {
sequences_backup.insert(make_pair(sequence->orig_sequence, sequence_backup));
}
}
SEQ_END;
}
void SequencerBackup::restore_to_scene(Scene *scene)
{
Sequence *sequence;
SEQ_BEGIN (scene->ed, sequence) {
SequencesBackupMap::iterator it = sequences_backup.find(sequence->orig_sequence);
if (it == sequences_backup.end()) {
continue;
}
SequenceBackup &sequence_backup = it->second;
sequence_backup.restore_to_sequence(sequence);
}
SEQ_END;
/* Cleanup audio while the scene is still known. */
for (SequencesBackupMap::value_type &it : sequences_backup) {
SequenceBackup &sequence_backup = it.second;
if (sequence_backup.scene_sound != NULL) {
BKE_sound_remove_scene_sound(scene, sequence_backup.scene_sound);
}
}
}
} // namespace DEG

View File

@@ -0,0 +1,49 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*/
#pragma once
#include "intern/eval/deg_eval_runtime_backup_sequence.h"
#include "intern/depsgraph_type.h"
struct Scene;
namespace DEG {
struct Depsgraph;
/* Backup of sequencer strips runtime data. */
class SequencerBackup {
public:
SequencerBackup(const Depsgraph *depsgraph);
void init_from_scene(Scene *scene);
void restore_to_scene(Scene *scene);
const Depsgraph *depsgraph;
typedef map<Sequence *, SequenceBackup> SequencesBackupMap;
SequencesBackupMap sequences_backup;
};
} // namespace DEG

View File

@@ -0,0 +1,64 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*/
#include "intern/eval/deg_eval_runtime_backup_sound.h"
#include "BLI_utildefines.h"
#include "DNA_sound_types.h"
namespace DEG {
SoundBackup::SoundBackup(const Depsgraph * /*depsgraph*/)
{
reset();
}
void SoundBackup::reset()
{
cache = NULL;
waveform = NULL;
playback_handle = NULL;
}
void SoundBackup::init_from_sound(bSound *sound)
{
cache = sound->cache;
waveform = sound->waveform;
playback_handle = sound->playback_handle;
sound->cache = NULL;
sound->waveform = NULL;
sound->playback_handle = NULL;
}
void SoundBackup::restore_to_sound(bSound *sound)
{
sound->cache = cache;
sound->waveform = waveform;
sound->playback_handle = playback_handle;
reset();
}
} // namespace DEG

View File

@@ -0,0 +1,47 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*/
#pragma once
struct bSound;
namespace DEG {
struct Depsgraph;
/* Backup of sound datablocks runtime data. */
class SoundBackup {
public:
SoundBackup(const Depsgraph *depsgraph);
void reset();
void init_from_sound(bSound *sound);
void restore_to_sound(bSound *sound);
void *cache;
void *waveform;
void *playback_handle;
};
} // namespace DEG