Fix #125944: Outliner: Child objects missing when linked to other collection
Objects inside `lc.collection->gobject / te_parent->subtree` are not order according to ob-parent heirarchy. Due to this, some child object tree elements are iterated before the parent inside `make_object_parent_hierarchy_collections` while building the hierarchy. This ignores the case for objects when they are in the different collection (lets say "Collection2"), see `if(!found)`. To fix this, store ordered list of object hierarchy in a Vector `ordered_objects`. This way, the parent element is first added to collection2. Then while iterating its child, `parent_ob_tree_elements` has more than one elements (i.e. possible to add child object inside Collection2) Also resolves #100393 Steps to Reproduce: Just open the .blend from above report Alternative for !136872 Pull Request: https://projects.blender.org/blender/blender/pulls/136971
This commit is contained in:
committed by
Pratik Borhade
parent
cf34e9e75f
commit
6fe4496f4c
@@ -16,6 +16,7 @@
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_listbase_wrapper.hh"
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_set.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
#include "../outliner_intern.hh"
|
||||
@@ -32,6 +33,14 @@ class ObjectsChildrenBuilder {
|
||||
|
||||
SpaceOutliner &outliner_;
|
||||
ObjectTreeElementsMap object_tree_elements_map_;
|
||||
/**
|
||||
* Stores objects such that parents are before children.
|
||||
*/
|
||||
Vector<Object *> ordered_objects_;
|
||||
/**
|
||||
* Holds objects that were already added to #ordered_objects_, to prevent duplicates.
|
||||
*/
|
||||
Set<Object *> objects_in_ordered_objects_;
|
||||
|
||||
public:
|
||||
ObjectsChildrenBuilder(SpaceOutliner &space_outliner);
|
||||
@@ -42,6 +51,7 @@ class ObjectsChildrenBuilder {
|
||||
private:
|
||||
void object_tree_elements_lookup_create_recursive(TreeElement *te_parent);
|
||||
void make_object_parent_hierarchy_collections();
|
||||
void add_object_and_parents_in_order(Object *ob);
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
@@ -221,7 +231,7 @@ void ObjectsChildrenBuilder::object_tree_elements_lookup_create_recursive(TreeEl
|
||||
Object *ob = (Object *)tselem->id;
|
||||
/* Lookup children or add new, empty children vector. */
|
||||
Vector<TreeElement *> &tree_elements = object_tree_elements_map_.lookup_or_add(ob, {});
|
||||
|
||||
add_object_and_parents_in_order(ob);
|
||||
tree_elements.append(te);
|
||||
object_tree_elements_lookup_create_recursive(te);
|
||||
}
|
||||
@@ -234,16 +244,17 @@ void ObjectsChildrenBuilder::object_tree_elements_lookup_create_recursive(TreeEl
|
||||
*/
|
||||
void ObjectsChildrenBuilder::make_object_parent_hierarchy_collections()
|
||||
{
|
||||
for (ObjectTreeElementsMap::MutableItem item : object_tree_elements_map_.items()) {
|
||||
Object *child = item.key;
|
||||
|
||||
if (child->parent == nullptr) {
|
||||
/* Ordered list (parent before children) is important. Otherwise, it is easy to miss objects that
|
||||
* are linked with another collection. For details, see: !136971. */
|
||||
for (Object *ob : ordered_objects_) {
|
||||
if (ob->parent == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Vector<TreeElement *> &child_ob_tree_elements = item.value;
|
||||
Vector<TreeElement *> *parent_ob_tree_elements = object_tree_elements_map_.lookup_ptr(
|
||||
child->parent);
|
||||
ob->parent);
|
||||
Vector<TreeElement *> &child_ob_tree_elements = *object_tree_elements_map_.lookup_ptr(ob);
|
||||
|
||||
if (parent_ob_tree_elements == nullptr) {
|
||||
continue;
|
||||
}
|
||||
@@ -279,7 +290,7 @@ void ObjectsChildrenBuilder::make_object_parent_hierarchy_collections()
|
||||
TreeElement *child_ob_tree_element = AbstractTreeDisplay::add_element(
|
||||
&outliner_,
|
||||
&parent_ob_tree_element->subtree,
|
||||
reinterpret_cast<ID *>(child),
|
||||
reinterpret_cast<ID *>(ob),
|
||||
nullptr,
|
||||
parent_ob_tree_element,
|
||||
TSE_SOME_ID,
|
||||
@@ -292,6 +303,16 @@ void ObjectsChildrenBuilder::make_object_parent_hierarchy_collections()
|
||||
}
|
||||
}
|
||||
|
||||
void ObjectsChildrenBuilder::add_object_and_parents_in_order(Object *ob)
|
||||
{
|
||||
if (Object *parent = ob->parent) {
|
||||
add_object_and_parents_in_order(parent);
|
||||
}
|
||||
if (objects_in_ordered_objects_.add(ob)) {
|
||||
ordered_objects_.append(ob);
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::ed::outliner
|
||||
|
||||
Reference in New Issue
Block a user