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:
Diffstat (limited to 'source/blender/editors/space_outliner/outliner_tree.c')
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c389
1 files changed, 249 insertions, 140 deletions
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index ec46c5df9a0..e7a866524fd 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -61,8 +61,10 @@
#include "BLT_translation.h"
+#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_main.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_modifier.h"
#include "BKE_sequencer.h"
@@ -83,6 +85,9 @@
# include "BLI_math_base.h" /* M_PI */
#endif
+/* prototypes */
+static void outliner_make_hierarchy(ListBase *lb);
+
/* ********************************************************* */
/* Persistent Data */
@@ -199,105 +204,6 @@ void outliner_cleanup_tree(SpaceOops *soops)
outliner_storage_cleanup(soops);
}
-/* Find specific item from the treestore */
-TreeElement *outliner_find_tree_element(ListBase *lb, const TreeStoreElem *store_elem)
-{
- TreeElement *te, *tes;
- for (te = lb->first; te; te = te->next) {
- if (te->store_elem == store_elem) return te;
- tes = outliner_find_tree_element(&te->subtree, store_elem);
- if (tes) return tes;
- }
- return NULL;
-}
-
-/* tse is not in the treestore, we use its contents to find a match */
-TreeElement *outliner_find_tse(SpaceOops *soops, const TreeStoreElem *tse)
-{
- TreeStoreElem *tselem;
-
- if (tse->id == NULL) return NULL;
-
- /* check if 'tse' is in treestore */
- tselem = BKE_outliner_treehash_lookup_any(soops->treehash, tse->type, tse->nr, tse->id);
- if (tselem)
- return outliner_find_tree_element(&soops->tree, tselem);
-
- return NULL;
-}
-
-/* Find treestore that refers to given ID */
-TreeElement *outliner_find_id(SpaceOops *soops, ListBase *lb, const ID *id)
-{
- for (TreeElement *te = lb->first; te; te = te->next) {
- TreeStoreElem *tselem = TREESTORE(te);
- if (tselem->type == 0) {
- if (tselem->id == id) {
- return te;
- }
- /* only deeper on scene or object */
- if (ELEM(te->idcode, ID_OB, ID_SCE) ||
- ((soops->outlinevis == SO_GROUPS) && (te->idcode == ID_GR)))
- {
- TreeElement *tes = outliner_find_id(soops, &te->subtree, id);
- if (tes) {
- return tes;
- }
- }
- }
- }
- return NULL;
-}
-
-TreeElement *outliner_find_posechannel(ListBase *lb, const bPoseChannel *pchan)
-{
- for (TreeElement *te = lb->first; te; te = te->next) {
- if (te->directdata == pchan) {
- return te;
- }
-
- TreeStoreElem *tselem = TREESTORE(te);
- if (ELEM(tselem->type, TSE_POSE_BASE, TSE_POSE_CHANNEL)) {
- TreeElement *tes = outliner_find_posechannel(&te->subtree, pchan);
- if (tes) {
- return tes;
- }
- }
- }
- return NULL;
-}
-
-TreeElement *outliner_find_editbone(ListBase *lb, const EditBone *ebone)
-{
- for (TreeElement *te = lb->first; te; te = te->next) {
- if (te->directdata == ebone) {
- return te;
- }
-
- TreeStoreElem *tselem = TREESTORE(te);
- if (ELEM(tselem->type, 0, TSE_EBONE)) {
- TreeElement *tes = outliner_find_editbone(&te->subtree, ebone);
- if (tes) {
- return tes;
- }
- }
- }
- return NULL;
-}
-
-ID *outliner_search_back(SpaceOops *UNUSED(soops), TreeElement *te, short idcode)
-{
- TreeStoreElem *tselem;
- te = te->parent;
-
- while (te) {
- tselem = TREESTORE(te);
- if (tselem->type == 0 && te->idcode == idcode) return tselem->id;
- te = te->parent;
- }
- return NULL;
-}
-
/* ********************************************************* */
@@ -483,12 +389,57 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s
#endif
}
+static void outliner_object_reorder(
+ Main *UNUSED(bmain), const Scene *scene,
+ TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action)
+{
+ TreeStoreElem *tselem_insert = TREESTORE(insert_element);
+ Object *ob = (Object *)tselem_insert->id;
+ SceneCollection *sc = outliner_scene_collection_from_tree_element(insert_handle);
+ SceneCollection *sc_ob_parent = NULL;
+
+ BLI_assert(action == TE_INSERT_INTO);
+ UNUSED_VARS_NDEBUG(action);
+
+ /* find parent scene-collection of object */
+ if (insert_element->parent) {
+ for (TreeElement *te_ob_parent = insert_element->parent; te_ob_parent; te_ob_parent = te_ob_parent->parent) {
+ if (ELEM(TREESTORE(te_ob_parent)->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION)) {
+ sc_ob_parent = outliner_scene_collection_from_tree_element(te_ob_parent);
+ break;
+ }
+ }
+ }
+ else {
+ sc_ob_parent = BKE_collection_master(scene);
+ }
+ BKE_collection_object_move(scene, sc, sc_ob_parent, ob);
+}
+
+static bool outliner_object_reorder_poll(
+ const Scene *UNUSED(scene), const TreeElement *insert_element,
+ TreeElement **io_insert_handle, TreeElementInsertType *io_action)
+{
+ TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
+ if (ELEM(tselem_handle->type, TSE_SCENE_COLLECTION, TSE_LAYER_COLLECTION) &&
+ (insert_element->parent != *io_insert_handle))
+ {
+ *io_action = TE_INSERT_INTO;
+ return true;
+ }
+
+ return false;
+}
+
// can be inlined if necessary
static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, Object *ob)
{
+ te->reinsert = outliner_object_reorder;
+ te->reinsert_poll = outliner_object_reorder_poll;
+
if (outliner_animdata_test(ob->adt))
outliner_add_element(soops, &te->subtree, ob, te, TSE_ANIM_DATA, 0);
-
+
outliner_add_element(soops, &te->subtree, ob->poselib, te, 0, 0); // XXX FIXME.. add a special type for this
if (ob->proxy && !ID_IS_LINKED_DATABLOCK(ob))
@@ -903,8 +854,8 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
id = TREESTORE(parent)->id;
}
- /* One exception */
- if (type == TSE_ID_BASE) {
+ /* exceptions */
+ if (ELEM(type, TSE_ID_BASE, TSE_LAYER_COLLECTION)) {
/* pass */
}
else if (id == NULL) {
@@ -941,6 +892,9 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
else if (type == TSE_GP_LAYER) {
/* pass */
}
+ else if (ELEM(type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION)) {
+ /* pass */
+ }
else if (type == TSE_ID_BASE) {
/* pass */
}
@@ -1233,6 +1187,15 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
return te;
}
+/**
+ * \note Really only removes \a tselem, not it's TreeElement instance or any children.
+ */
+void outliner_remove_treestore_element(SpaceOops *soops, TreeStoreElem *tselem)
+{
+ BKE_outliner_treehash_remove_element(soops->treehash, tselem);
+ BLI_mempool_free(soops->treestore, tselem);
+}
+
/* ======================================================= */
/* Sequencer mode tree building */
@@ -1370,6 +1333,141 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
}
}
+static void outliner_layer_collections_reorder(
+ Main *bmain, const Scene *scene,
+ TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action)
+{
+ LayerCollection *lc_insert = insert_element->directdata;
+ LayerCollection *lc_handle = insert_handle->directdata;
+
+ if (action == TE_INSERT_BEFORE) {
+ BKE_layer_collection_move_above(scene, lc_handle, lc_insert);
+ }
+ else if (action == TE_INSERT_AFTER) {
+ BKE_layer_collection_move_below(scene, lc_handle, lc_insert);
+ }
+ else if (action == TE_INSERT_INTO) {
+ BKE_layer_collection_move_into(scene, lc_handle, lc_insert);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ DAG_relations_tag_update(bmain);
+}
+static bool outliner_layer_collections_reorder_poll(
+ const Scene *UNUSED(scene), const TreeElement *UNUSED(insert_element),
+ TreeElement **io_insert_handle, TreeElementInsertType *UNUSED(io_action))
+{
+ const TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
+ return ELEM(tselem_handle->type, TSE_LAYER_COLLECTION);
+}
+
+static void outliner_add_layer_collections_recursive(
+ SpaceOops *soops, ListBase *tree, ListBase *layer_collections, TreeElement *parent_ten)
+{
+ for (LayerCollection *collection = layer_collections->first; collection; collection = collection->next) {
+ TreeElement *ten = outliner_add_element(soops, tree, collection, parent_ten, TSE_LAYER_COLLECTION, 0);
+
+ ten->name = collection->scene_collection->name;
+ ten->directdata = collection;
+ ten->reinsert = outliner_layer_collections_reorder;
+ ten->reinsert_poll = outliner_layer_collections_reorder_poll;
+
+ outliner_add_layer_collections_recursive(soops, &ten->subtree, &collection->layer_collections, ten);
+ for (LinkData *link = collection->object_bases.first; link; link = link->next) {
+ Base *base = (Base *)link->data;
+ TreeElement *te_object = outliner_add_element(soops, &ten->subtree, base->object, ten, 0, 0);
+ te_object->directdata = base;
+ }
+ outliner_make_hierarchy(&ten->subtree);
+ }
+}
+static void outliner_add_collections_act_layer(SpaceOops *soops, SceneLayer *layer)
+{
+ outliner_add_layer_collections_recursive(soops, &soops->tree, &layer->layer_collections, NULL);
+}
+
+static void outliner_scene_collections_reorder(
+ Main *bmain, const Scene *scene,
+ TreeElement *insert_element, TreeElement *insert_handle, TreeElementInsertType action)
+{
+ SceneCollection *sc_insert = insert_element->directdata;
+ SceneCollection *sc_handle = insert_handle->directdata;
+
+ BLI_assert((action == TE_INSERT_INTO) || (sc_handle != BKE_collection_master(scene)));
+ if (action == TE_INSERT_BEFORE) {
+ BKE_collection_move_above(scene, sc_handle, sc_insert);
+ }
+ else if (action == TE_INSERT_AFTER) {
+ BKE_collection_move_below(scene, sc_handle, sc_insert);
+ }
+ else if (action == TE_INSERT_INTO) {
+ BKE_collection_move_into(scene, sc_handle, sc_insert);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ DAG_relations_tag_update(bmain);
+}
+static bool outliner_scene_collections_reorder_poll(
+ const Scene *scene, const TreeElement *UNUSED(insert_element),
+ TreeElement **io_insert_handle, TreeElementInsertType *io_action)
+{
+ const TreeStoreElem *tselem_handle = TREESTORE(*io_insert_handle);
+ SceneCollection *sc_master = BKE_collection_master(scene);
+ SceneCollection *sc_handle = (*io_insert_handle)->directdata;
+
+ if (!ELEM(tselem_handle->type, TSE_SCENE_COLLECTION)) {
+ return false;
+ }
+
+ if (sc_handle == sc_master) {
+ /* exception: Can't insert before/after master selection, has to be one of its childs */
+ TreeElement *te_master = *io_insert_handle;
+ if (*io_action == TE_INSERT_BEFORE) {
+ /* can't go higher than master collection, insert into it */
+ *io_action = TE_INSERT_INTO;
+ }
+ else if (*io_action == TE_INSERT_AFTER) {
+ *io_insert_handle = te_master->subtree.last;
+ }
+ }
+ return true;
+}
+
+static void outliner_add_scene_collection_objects(
+ SpaceOops *soops, ListBase *tree, SceneCollection *collection, TreeElement *parent)
+{
+ for (LinkData *link = collection->objects.first; link; link = link->next) {
+ outliner_add_element(soops, tree, link->data, parent, 0, 0);
+ }
+ outliner_make_hierarchy(tree);
+}
+
+static void outliner_add_scene_collections_recursive(
+ SpaceOops *soops, ListBase *tree, ListBase *scene_collections, TreeElement *parent_ten)
+{
+ for (SceneCollection *collection = scene_collections->first; collection; collection = collection->next) {
+ TreeElement *ten = outliner_add_element(soops, tree, collection, parent_ten, TSE_SCENE_COLLECTION, 0);
+
+ ten->name = collection->name;
+ ten->directdata = collection;
+ ten->reinsert = outliner_scene_collections_reorder;
+ ten->reinsert_poll = outliner_scene_collections_reorder_poll;
+
+ outliner_add_scene_collections_recursive(soops, &ten->subtree, &collection->scene_collections, ten);
+ outliner_add_scene_collection_objects(soops, &ten->subtree, collection, ten);
+ }
+}
+static void outliner_add_collections_master(SpaceOops *soops, Scene *scene)
+{
+ SceneCollection *master = BKE_collection_master(scene);
+ outliner_add_scene_collections_recursive(soops, &soops->tree, &master->scene_collections, NULL);
+ outliner_add_scene_collection_objects(soops, &soops->tree, master, NULL);
+}
+
/* ======================================================= */
/* Generic Tree Building helpers - order these are called is top to bottom */
@@ -1483,18 +1581,15 @@ static void outliner_sort(ListBase *lb)
{
TreeElement *te;
TreeStoreElem *tselem;
- int totelem = 0;
te = lb->last;
if (te == NULL) return;
tselem = TREESTORE(te);
-
+
/* sorting rules; only object lists, ID lists, or deformgroups */
- if ( ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) || (tselem->type == 0 && te->idcode == ID_OB)) {
-
- /* count first */
- for (te = lb->first; te; te = te->next) totelem++;
-
+ if (ELEM(tselem->type, TSE_DEFGROUP, TSE_ID_BASE) || (tselem->type == 0 && te->idcode == ID_OB)) {
+ int totelem = BLI_listbase_count(lb);
+
if (totelem > 1) {
tTreeSort *tear = MEM_mallocN(totelem * sizeof(tTreeSort), "tree sort array");
tTreeSort *tp = tear;
@@ -1619,9 +1714,8 @@ static int outliner_filter_tree(SpaceOops *soops, ListBase *lb)
/* Main entry point for building the tree data-structure that the outliner represents */
// TODO: split each mode into its own function?
-void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
+void outliner_build_tree(Main *mainvar, Scene *scene, SceneLayer *sl, SpaceOops *soops)
{
- Base *base;
TreeElement *te = NULL, *ten;
TreeStoreElem *tselem;
int show_opened = !soops->treestore || !BLI_mempool_count(soops->treestore); /* on first view, we open scenes */
@@ -1702,31 +1796,42 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
tselem = TREESTORE(te);
if (sce == scene && show_opened)
tselem->flag &= ~TSE_CLOSED;
-
- for (base = sce->base.first; base; base = base->next) {
- ten = outliner_add_element(soops, &te->subtree, base->object, te, 0, 0);
- ten->directdata = base;
+
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ outliner_add_element(soops, &te->subtree, ob, te, 0, 0);
}
+ FOREACH_SCENE_OBJECT_END
+
outliner_make_hierarchy(&te->subtree);
+
/* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */
- for (base = sce->base.first; base; base = base->next) base->object->id.newid = NULL;
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ ob->id.newid = NULL;
+ }
+ FOREACH_SCENE_OBJECT_END
}
}
else if (soops->outlinevis == SO_CUR_SCENE) {
outliner_add_scene_contents(soops, &soops->tree, scene, NULL);
-
- for (base = scene->base.first; base; base = base->next) {
- ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
- ten->directdata = base;
+
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0);
}
+ FOREACH_SCENE_OBJECT_END
outliner_make_hierarchy(&soops->tree);
}
else if (soops->outlinevis == SO_VISIBLE) {
- for (base = scene->base.first; base; base = base->next) {
- if (base->lay & scene->lay)
- outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ FOREACH_VISIBLE_BASE(sl, base)
+ {
+ ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ ten->directdata = base;
+
}
+ FOREACH_VISIBLE_BASE_END
outliner_make_hierarchy(&soops->tree);
}
else if (soops->outlinevis == SO_GROUPS) {
@@ -1738,8 +1843,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
te = outliner_add_element(soops, &soops->tree, group, NULL, 0, 0);
for (go = group->gobject.first; go; go = go->next) {
- ten = outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0);
- ten->directdata = NULL; /* eh, why? */
+ outliner_add_element(soops, &te->subtree, go->ob, te, 0, 0);
}
outliner_make_hierarchy(&te->subtree);
/* clear id.newid, to prevent objects be inserted in wrong scenes (parent in other scene) */
@@ -1748,26 +1852,25 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
}
}
else if (soops->outlinevis == SO_SAME_TYPE) {
- Object *ob = OBACT;
- if (ob) {
- for (base = scene->base.first; base; base = base->next) {
- if (base->object->type == ob->type) {
- ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
- ten->directdata = base;
+ Object *ob_active = OBACT_NEW;
+ if (ob_active) {
+ FOREACH_SCENE_OBJECT(scene, ob)
+ {
+ if (ob->type == ob_active->type) {
+ outliner_add_element(soops, &soops->tree, ob, NULL, 0, 0);
}
}
+ FOREACH_SCENE_OBJECT_END
outliner_make_hierarchy(&soops->tree);
}
}
else if (soops->outlinevis == SO_SELECTED) {
- for (base = scene->base.first; base; base = base->next) {
- if (base->lay & scene->lay) {
- if (base->flag & SELECT) {
- ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
- ten->directdata = base;
- }
- }
+ FOREACH_SELECTED_BASE(sl, base)
+ {
+ ten = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ ten->directdata = base;
}
+ FOREACH_SELECTED_BASE_END
outliner_make_hierarchy(&soops->tree);
}
else if (soops->outlinevis == SO_SEQUENCE) {
@@ -1821,9 +1924,15 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops)
else if (soops->outlinevis == SO_ID_ORPHANS) {
outliner_add_orphaned_datablocks(mainvar, soops);
}
+ else if (soops->outlinevis == SO_ACT_LAYER) {
+ outliner_add_collections_act_layer(soops, BKE_scene_layer_context_active(scene));
+ }
+ else if (soops->outlinevis == SO_COLLECTIONS) {
+ outliner_add_collections_master(soops, scene);
+ }
else {
- ten = outliner_add_element(soops, &soops->tree, OBACT, NULL, 0, 0);
- if (ten) ten->directdata = BASACT;
+ ten = outliner_add_element(soops, &soops->tree, OBACT_NEW, NULL, 0, 0);
+ ten->directdata = BASACT_NEW;
}
if ((soops->flag & SO_SKIP_SORT_ALPHA) == 0) {