Depsgraph: Expose helper functions for manual dupli iteration
Refactor some internal DEG_iterator code into public functions. This shouldn't cause any functional change, but it's required for #140378. Pull Request: https://projects.blender.org/blender/blender/pulls/140674
This commit is contained in:
@@ -313,6 +313,59 @@ void DEG_iterator_objects_end(BLI_Iterator *iter);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name DEG object iterators - Manual dupli iteration
|
||||
* Helper functions for handling dupli instances iteration manually (ie. without passing
|
||||
* DEG_ITER_OBJECT_FLAG_DUPLI to DEGObjectIterSettings::flags)
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Returns true if the object should be visible on the given context.
|
||||
*/
|
||||
bool DEG_iterator_object_is_visible(eEvaluationMode eval_mode, const Object *ob);
|
||||
|
||||
/**
|
||||
* Returns true if the dupli instance should be visible on the given context.
|
||||
*/
|
||||
bool DEG_iterator_dupli_is_visible(const DupliObject *dupli, eEvaluationMode eval_mode);
|
||||
|
||||
namespace evil {
|
||||
/**
|
||||
* WARNING: DON'T USE!!!
|
||||
*
|
||||
* These functions are exposed publicly as a temporary measure while we figure out how to fully get
|
||||
* rid of temporary objects in the Draw module (See #144811).
|
||||
*
|
||||
* DON'T ADD NEW USE CASES FOR THESE FUNCTIONS.
|
||||
*/
|
||||
|
||||
/**
|
||||
* WARNING: DON'T USE!!!
|
||||
* Generates a temporary object for a given dupli instance.
|
||||
*
|
||||
* Returns true if the resulting object should be visible, otherwise the temp object should be
|
||||
* considered invalid.
|
||||
* NOTE: DEG_iterator_temp_object_free_properties should be called regardless.
|
||||
*
|
||||
* \param do_matrix_setup: If false, the temp_object won't have valid
|
||||
* object_to_world/world_to_object matrices, and the OB_NEG_SCALE flag will never be set.
|
||||
*/
|
||||
[[nodiscard]] bool DEG_iterator_temp_object_from_dupli(const Object *dupli_parent,
|
||||
const DupliObject *dupli,
|
||||
eEvaluationMode eval_mode,
|
||||
bool do_matrix_setup,
|
||||
Object *r_temp_object,
|
||||
ObjectRuntimeHandle *r_temp_runtime);
|
||||
|
||||
/**
|
||||
* WARNING: DON'T USE!!!
|
||||
* Frees any property allocated when calling DEG_iterator_temp_object_from_dupli.
|
||||
*/
|
||||
void DEG_iterator_temp_object_free_properties(const DupliObject *dupli, Object *temp_object);
|
||||
} // namespace evil
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name DEG ID iterators
|
||||
* \{ */
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
|
||||
namespace deg = blender::deg;
|
||||
|
||||
using evil::DEG_iterator_temp_object_free_properties;
|
||||
using evil::DEG_iterator_temp_object_from_dupli;
|
||||
|
||||
/* ************************ DEG ITERATORS ********************* */
|
||||
|
||||
namespace {
|
||||
@@ -62,37 +65,7 @@ void deg_invalidate_iterator_work_data(DEGObjectIterData *data)
|
||||
#endif
|
||||
}
|
||||
|
||||
void ensure_id_properties_freed(const IDProperty *dupli_idprops, IDProperty **temp_dupli_idprops)
|
||||
{
|
||||
if (*temp_dupli_idprops == nullptr) {
|
||||
/* No ID properties in temp data-block -- no leak is possible. */
|
||||
return;
|
||||
}
|
||||
if (*temp_dupli_idprops == dupli_idprops) {
|
||||
/* Temp copy of object did not modify ID properties. */
|
||||
return;
|
||||
}
|
||||
/* Free memory which is owned by temporary storage which is about to get overwritten. */
|
||||
IDP_FreeProperty(*temp_dupli_idprops);
|
||||
*temp_dupli_idprops = nullptr;
|
||||
}
|
||||
|
||||
void free_owned_memory(DEGObjectIterData *data)
|
||||
{
|
||||
if (data->dupli_object_current == nullptr) {
|
||||
/* We didn't enter duplication yet, so we can't have any dangling pointers. */
|
||||
return;
|
||||
}
|
||||
|
||||
const Object *dupli_object = data->dupli_object_current->ob;
|
||||
Object *temp_dupli_object = &data->temp_dupli_object;
|
||||
|
||||
ensure_id_properties_freed(dupli_object->id.properties, &temp_dupli_object->id.properties);
|
||||
ensure_id_properties_freed(dupli_object->id.system_properties,
|
||||
&temp_dupli_object->id.system_properties);
|
||||
}
|
||||
|
||||
bool deg_object_hide_original(eEvaluationMode eval_mode, Object *ob, DupliObject *dob)
|
||||
bool deg_object_hide_original(eEvaluationMode eval_mode, const Object *ob, const DupliObject *dob)
|
||||
{
|
||||
/* Automatic hiding if this object is being instanced on verts/faces/frames
|
||||
* by its parent. Ideally this should not be needed, but due to the wrong
|
||||
@@ -141,16 +114,11 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data)
|
||||
data->dupli_object_next_index = -1;
|
||||
}
|
||||
|
||||
if (dob->no_draw) {
|
||||
continue;
|
||||
}
|
||||
if (dob->ob_data && GS(dob->ob_data->name) == ID_MB) {
|
||||
continue;
|
||||
}
|
||||
if (obd->type != OB_MBALL && deg_object_hide_original(data->eval_mode, dob->ob, dob)) {
|
||||
if (!DEG_iterator_dupli_is_visible(dob, data->eval_mode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* TODO: Can this be removed? included_objects is already passed to object_duplilist(). */
|
||||
DEGObjectIterSettings *settings = data->settings;
|
||||
if (settings->included_objects) {
|
||||
Object *object_orig = DEG_get_original(obd);
|
||||
@@ -159,51 +127,26 @@ bool deg_iterator_duplis_step(DEGObjectIterData *data)
|
||||
}
|
||||
}
|
||||
|
||||
free_owned_memory(data);
|
||||
if (data->dupli_object_current) {
|
||||
DEG_iterator_temp_object_free_properties(data->dupli_object_current,
|
||||
&data->temp_dupli_object);
|
||||
}
|
||||
|
||||
data->dupli_object_current = dob;
|
||||
|
||||
/* Temporary object to evaluate. */
|
||||
Object *dupli_parent = data->dupli_parent;
|
||||
Object *temp_dupli_object = &data->temp_dupli_object;
|
||||
|
||||
*temp_dupli_object = blender::dna::shallow_copy(*dob->ob);
|
||||
temp_dupli_object->runtime = &data->temp_dupli_object_runtime;
|
||||
*temp_dupli_object->runtime = *dob->ob->runtime;
|
||||
|
||||
temp_dupli_object->base_flag = dupli_parent->base_flag | BASE_FROM_DUPLI;
|
||||
temp_dupli_object->base_local_view_bits = dupli_parent->base_local_view_bits;
|
||||
temp_dupli_object->runtime->local_collections_bits =
|
||||
dupli_parent->runtime->local_collections_bits;
|
||||
temp_dupli_object->dt = std::min(temp_dupli_object->dt, dupli_parent->dt);
|
||||
copy_v4_v4(temp_dupli_object->color, dupli_parent->color);
|
||||
temp_dupli_object->runtime->select_id = dupli_parent->runtime->select_id;
|
||||
if (dob->ob->data != dob->ob_data) {
|
||||
BKE_object_replace_data_on_shallow_copy(temp_dupli_object, dob->ob_data);
|
||||
if (DEG_iterator_temp_object_from_dupli(data->dupli_parent,
|
||||
data->dupli_object_current,
|
||||
data->eval_mode,
|
||||
true,
|
||||
&data->temp_dupli_object,
|
||||
&data->temp_dupli_object_runtime))
|
||||
{
|
||||
data->next_object = &data->temp_dupli_object;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Duplicated elements shouldn't care whether their original collection is visible or not. */
|
||||
temp_dupli_object->base_flag |= BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT;
|
||||
|
||||
int ob_visibility = BKE_object_visibility(temp_dupli_object, data->eval_mode);
|
||||
if ((ob_visibility & (OB_VISIBLE_SELF | OB_VISIBLE_PARTICLES)) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* This could be avoided by refactoring make_dupli() in order to track all negative scaling
|
||||
* recursively. */
|
||||
bool is_neg_scale = is_negative_m4(dob->mat);
|
||||
SET_FLAG_FROM_TEST(data->temp_dupli_object.transflag, is_neg_scale, OB_NEG_SCALE);
|
||||
|
||||
copy_m4_m4(data->temp_dupli_object.runtime->object_to_world.ptr(), dob->mat);
|
||||
invert_m4_m4(data->temp_dupli_object.runtime->world_to_object.ptr(),
|
||||
data->temp_dupli_object.object_to_world().ptr());
|
||||
data->next_object = &data->temp_dupli_object;
|
||||
BLI_assert(deg::deg_validate_eval_copy_datablock(&data->temp_dupli_object.id));
|
||||
return true;
|
||||
}
|
||||
|
||||
free_owned_memory(data);
|
||||
DEG_iterator_temp_object_free_properties(data->dupli_object_current, &data->temp_dupli_object);
|
||||
data->dupli_list.clear();
|
||||
data->dupli_parent = nullptr;
|
||||
data->dupli_object_next = nullptr;
|
||||
@@ -284,7 +227,7 @@ bool deg_iterator_objects_step(DEGObjectIterData *data)
|
||||
if (data->flag & DEG_ITER_OBJECT_FLAG_VISIBLE) {
|
||||
ob_visibility = BKE_object_visibility(object, data->eval_mode);
|
||||
|
||||
if (object->type != OB_MBALL && deg_object_hide_original(data->eval_mode, object, nullptr)) {
|
||||
if (!DEG_iterator_object_is_visible(data->eval_mode, object)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -509,3 +452,94 @@ void DEG_iterator_ids_next(BLI_Iterator *iter)
|
||||
}
|
||||
|
||||
void DEG_iterator_ids_end(BLI_Iterator * /*iter*/) {}
|
||||
|
||||
bool DEG_iterator_object_is_visible(eEvaluationMode eval_mode, const Object *ob)
|
||||
{
|
||||
if (ob->type == OB_MBALL) {
|
||||
return true;
|
||||
}
|
||||
return !deg_object_hide_original(eval_mode, ob, nullptr);
|
||||
}
|
||||
|
||||
bool DEG_iterator_dupli_is_visible(const DupliObject *dupli, eEvaluationMode eval_mode)
|
||||
{
|
||||
if (dupli->no_draw) {
|
||||
return false;
|
||||
}
|
||||
if (dupli->ob_data && GS(dupli->ob_data->name) == ID_MB) {
|
||||
return false;
|
||||
}
|
||||
if (dupli->ob->type != OB_MBALL && deg_object_hide_original(eval_mode, dupli->ob, dupli)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool evil::DEG_iterator_temp_object_from_dupli(const Object *dupli_parent,
|
||||
const DupliObject *dupli,
|
||||
eEvaluationMode eval_mode,
|
||||
bool do_matrix_setup,
|
||||
Object *r_temp_object,
|
||||
ObjectRuntimeHandle *r_temp_runtime)
|
||||
{
|
||||
*r_temp_object = blender::dna::shallow_copy(*dupli->ob);
|
||||
r_temp_object->runtime = r_temp_runtime;
|
||||
*r_temp_object->runtime = *dupli->ob->runtime;
|
||||
|
||||
r_temp_object->base_flag = dupli_parent->base_flag | BASE_FROM_DUPLI;
|
||||
r_temp_object->base_local_view_bits = dupli_parent->base_local_view_bits;
|
||||
r_temp_object->runtime->local_collections_bits = dupli_parent->runtime->local_collections_bits;
|
||||
r_temp_object->dt = std::min(r_temp_object->dt, dupli_parent->dt);
|
||||
copy_v4_v4(r_temp_object->color, dupli_parent->color);
|
||||
r_temp_object->runtime->select_id = dupli_parent->runtime->select_id;
|
||||
if (dupli->ob->data != dupli->ob_data) {
|
||||
BKE_object_replace_data_on_shallow_copy(r_temp_object, dupli->ob_data);
|
||||
}
|
||||
|
||||
/* Duplicated elements shouldn't care whether their original collection is visible or not. */
|
||||
r_temp_object->base_flag |= BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT;
|
||||
|
||||
/* TODO: Could this be computed in DEG_iterator_dupli_is_visible,
|
||||
* before setting up the shallow copy? */
|
||||
int ob_visibility = BKE_object_visibility(r_temp_object, eval_mode);
|
||||
if ((ob_visibility & (OB_VISIBLE_SELF | OB_VISIBLE_PARTICLES)) == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (do_matrix_setup) {
|
||||
/* This could be avoided by refactoring make_dupli() in order to track all negative scaling
|
||||
* recursively. */
|
||||
bool is_neg_scale = is_negative_m4(dupli->mat);
|
||||
SET_FLAG_FROM_TEST(r_temp_object->transflag, is_neg_scale, OB_NEG_SCALE);
|
||||
|
||||
copy_m4_m4(r_temp_object->runtime->object_to_world.ptr(), dupli->mat);
|
||||
invert_m4_m4(r_temp_object->runtime->world_to_object.ptr(),
|
||||
r_temp_object->object_to_world().ptr());
|
||||
}
|
||||
|
||||
BLI_assert(deg::deg_validate_eval_copy_datablock(&r_temp_object->id));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ensure_id_properties_freed(const IDProperty *dupli_idprops, IDProperty **temp_dupli_idprops)
|
||||
{
|
||||
if (*temp_dupli_idprops == nullptr) {
|
||||
/* No ID properties in temp data-block -- no leak is possible. */
|
||||
return;
|
||||
}
|
||||
if (*temp_dupli_idprops == dupli_idprops) {
|
||||
/* Temp copy of object did not modify ID properties. */
|
||||
return;
|
||||
}
|
||||
/* Free memory which is owned by temporary storage which is about to get overwritten. */
|
||||
IDP_FreeProperty(*temp_dupli_idprops);
|
||||
*temp_dupli_idprops = nullptr;
|
||||
}
|
||||
|
||||
void evil::DEG_iterator_temp_object_free_properties(const DupliObject *dupli, Object *temp_object)
|
||||
{
|
||||
ensure_id_properties_freed(dupli->ob->id.properties, &temp_object->id.properties);
|
||||
ensure_id_properties_freed(dupli->ob->id.system_properties, &temp_object->id.system_properties);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user