diff options
author | Julian Eisel <eiseljulian@gmail.com> | 2017-04-04 22:39:57 +0300 |
---|---|---|
committer | Julian Eisel <eiseljulian@gmail.com> | 2017-04-04 22:39:57 +0300 |
commit | 7576ad3d043ac5d15e0c5a68e65339904441b5e7 (patch) | |
tree | bb990cce1eec04d45ab57e8a42af2669f9d7522f /source/blender/blenkernel/intern/collection.c | |
parent | 10b24eabbab0193f6944cdf3bec7b386c75d5445 (diff) | |
parent | db0f67f46454fd0bfeb886d3e61227b65fbc6ac1 (diff) |
Merge branch 'blender2.8' into transform-manipulatorstransform-manipulators
Conflicts:
intern/gawain/gawain/immediate.h
intern/gawain/src/immediate.c
source/blender/editors/physics/physics_ops.c
source/blender/editors/screen/glutil.c
source/blender/editors/space_view3d/space_view3d.c
source/blender/editors/space_view3d/view3d_draw.c
source/blender/editors/space_view3d/view3d_edit.c
source/blender/editors/space_view3d/view3d_ops.c
source/blender/editors/transform/transform_manipulator.c
Diffstat (limited to 'source/blender/blenkernel/intern/collection.c')
-rw-r--r-- | source/blender/blenkernel/intern/collection.c | 225 |
1 files changed, 206 insertions, 19 deletions
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 289586153ea..b16162dfbc0 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -24,6 +24,8 @@ * \ingroup bke */ +#include <string.h> + #include "BLI_blenlib.h" #include "BLI_ghash.h" #include "BLI_iterator.h" @@ -44,6 +46,7 @@ #include "MEM_guardedalloc.h" + /** * Add a collection to a collection ListBase and syncronize all render layers * The ListBase is NULL when the collection is to be added to the master collection @@ -61,9 +64,7 @@ SceneCollection *BKE_collection_add(Scene *scene, SceneCollection *sc_parent, co sc_parent = sc_master; } - BLI_strncpy(sc->name, name, sizeof(sc->name)); - BLI_uniquename(&sc_master->scene_collections, sc, DATA_("Collection"), '.', offsetof(SceneCollection, name), sizeof(sc->name)); - + BKE_collection_rename(scene, sc, name); BLI_addtail(&sc_parent->scene_collections, sc); BKE_layer_sync_new_scene_collection(scene, sc_parent, sc); @@ -93,12 +94,11 @@ static void collection_free(SceneCollection *sc) /** * Unlink the collection recursively - * return true if unlinked + * \return true if unlinked. */ static bool collection_remlink(SceneCollection *sc_parent, SceneCollection *sc_gone) { - for (SceneCollection *sc = sc_parent->scene_collections.first; sc; sc = sc->next) - { + for (SceneCollection *sc = sc_parent->scene_collections.first; sc; sc = sc->next) { if (sc == sc_gone) { BLI_remlink(&sc_parent->scene_collections, sc_gone); return true; @@ -117,9 +117,8 @@ static bool collection_remlink(SceneCollection *sc_parent, SceneCollection *sc_g static void layer_collection_remove(SceneLayer *sl, ListBase *lb, const SceneCollection *sc) { LayerCollection *lc = lb->first; - while(lc) { + while (lc) { if (lc->scene_collection == sc) { - BKE_scene_layer_engine_settings_collection_recalculate(sl, lc); BKE_layer_collection_free(sl, lc); BLI_remlink(lb, lc); @@ -165,7 +164,6 @@ bool BKE_collection_remove(Scene *scene, SceneCollection *sc) /* check all layers that use this collection and clear them */ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) { layer_collection_remove(sl, &sl->layer_collections, sc); - BKE_scene_layer_base_flag_recalculate(sl); sl->active_collection = 0; } @@ -176,20 +174,55 @@ bool BKE_collection_remove(Scene *scene, SceneCollection *sc) /** * Returns the master collection */ -SceneCollection *BKE_collection_master(Scene *scene) +SceneCollection *BKE_collection_master(const Scene *scene) { return scene->collection; } +struct UniqueNameCheckData { + ListBase *lb; + SceneCollection *lookup_sc; +}; + +static bool collection_unique_name_check(void *arg, const char *name) +{ + struct UniqueNameCheckData *data = arg; + + for (SceneCollection *sc = data->lb->first; sc; sc = sc->next) { + struct UniqueNameCheckData child_data = {.lb = &sc->scene_collections, .lookup_sc = data->lookup_sc}; + + if (sc != data->lookup_sc) { + if (STREQ(sc->name, name)) { + return true; + } + } + if (collection_unique_name_check(&child_data, name)) { + return true; + } + } + + return false; +} + +void BKE_collection_rename(const Scene *scene, SceneCollection *sc, const char *name) +{ + SceneCollection *sc_master = BKE_collection_master(scene); + struct UniqueNameCheckData data = {.lb = &sc_master->scene_collections, .lookup_sc = sc}; + + BLI_strncpy(sc->name, name, sizeof(sc->name)); + BLI_uniquename_cb(collection_unique_name_check, &data, DATA_("Collection"), '.', sc->name, sizeof(sc->name)); +} + /** * Free (or release) any data used by the master collection (does not free the master collection itself). * Used only to clear the entire scene data since it's not doing re-syncing of the LayerCollection tree */ -void BKE_collection_master_free(Scene *scene){ +void BKE_collection_master_free(Scene *scene) +{ collection_free(BKE_collection_master(scene)); } -static void collection_object_add(Scene *scene, SceneCollection *sc, Object *ob) +static void collection_object_add(const Scene *scene, SceneCollection *sc, Object *ob) { BLI_addtail(&sc->objects, BLI_genericNodeN(ob)); id_us_plus((ID *)ob); @@ -199,7 +232,7 @@ static void collection_object_add(Scene *scene, SceneCollection *sc, Object *ob) /** * Add object to collection */ -void BKE_collection_object_add(Scene *scene, SceneCollection *sc, Object *ob) +void BKE_collection_object_add(const Scene *scene, SceneCollection *sc, Object *ob) { if (BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) { /* don't add the same object twice */ @@ -214,7 +247,6 @@ void BKE_collection_object_add(Scene *scene, SceneCollection *sc, Object *ob) */ void BKE_collection_object_add_from(Scene *scene, Object *ob_src, Object *ob_dst) { - SceneCollection *sc; FOREACH_SCENE_COLLECTION(scene, sc) { if (BLI_findptr(&sc->objects, ob_src, offsetof(LinkData, data))) { @@ -225,9 +257,10 @@ void BKE_collection_object_add_from(Scene *scene, Object *ob_src, Object *ob_dst } /** - * Remove object from collection + * Remove object from collection. + * \param bmain: Can be NULL if free_us is false. */ -void BKE_collection_object_remove(Main *bmain, Scene *scene, SceneCollection *sc, Object *ob, const bool free_us) +void BKE_collection_object_remove(Main *bmain, const Scene *scene, SceneCollection *sc, Object *ob, const bool free_us) { LinkData *link = BLI_findptr(&sc->objects, ob, offsetof(LinkData, data)); @@ -251,13 +284,21 @@ void BKE_collection_object_remove(Main *bmain, Scene *scene, SceneCollection *sc } /** + * Move object from a collection into another + */ +void BKE_collection_object_move(const Scene *scene, SceneCollection *sc_dst, SceneCollection *sc_src, Object *ob) +{ + BKE_collection_object_add(scene, sc_dst, ob); + BKE_collection_object_remove(NULL, scene, sc_src, ob, false); +} + +/** * Remove object from all collections of scene */ void BKE_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const bool free_us) { BKE_scene_remove_rigidbody_object(scene, ob); - SceneCollection *sc; FOREACH_SCENE_COLLECTION(scene, sc) { BKE_collection_object_remove(bmain, scene, sc, ob, free_us); @@ -266,6 +307,152 @@ void BKE_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const } /* ---------------------------------------------------------------------- */ +/* Outliner drag and drop */ + +/** + * Find and return the SceneCollection that has \a sc_child as one of its directly + * nested SceneCollection. + * + * \param sc_parent Initial SceneCollection to look into recursively, usually the master collection + */ +static SceneCollection *find_collection_parent(const SceneCollection *sc_child, SceneCollection *sc_parent) +{ + for (SceneCollection *sc_nested = sc_parent->scene_collections.first; sc_nested; sc_nested = sc_nested->next) { + if (sc_nested == sc_child) { + return sc_parent; + } + + SceneCollection *found = find_collection_parent(sc_child, sc_nested); + if (found) { + return found; + } + } + + return NULL; +} + +/** + * Check if \a sc_reference is nested to \a sc_parent SceneCollection + */ +static bool is_collection_in_tree(const SceneCollection *sc_reference, SceneCollection *sc_parent) +{ + return find_collection_parent(sc_reference, sc_parent) != NULL; +} + +bool BKE_collection_move_above(const Scene *scene, SceneCollection *sc_dst, SceneCollection *sc_src) +{ + /* Find the SceneCollection the sc_src belongs to */ + SceneCollection *sc_master = BKE_collection_master(scene); + + /* Master Layer can't be moved around*/ + if (ELEM(sc_master, sc_src, sc_dst)) { + return false; + } + + /* collection is already where we wanted it to be */ + if (sc_dst->prev == sc_src) { + return false; + } + + /* We can't move a collection fs the destiny collection + * is nested to the source collection */ + if (is_collection_in_tree(sc_dst, sc_src)) { + return false; + } + + SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master); + SceneCollection *sc_dst_parent = find_collection_parent(sc_dst, sc_master); + BLI_assert(sc_src_parent); + BLI_assert(sc_dst_parent); + + /* Remove sc_src from its parent */ + BLI_remlink(&sc_src_parent->scene_collections, sc_src); + + /* Re-insert it where it belongs */ + BLI_insertlinkbefore(&sc_dst_parent->scene_collections, sc_dst, sc_src); + + /* Update the tree */ + BKE_layer_collection_resync(scene, sc_src_parent); + BKE_layer_collection_resync(scene, sc_dst_parent); + + return true; +} + +bool BKE_collection_move_below(const Scene *scene, SceneCollection *sc_dst, SceneCollection *sc_src) +{ + /* Find the SceneCollection the sc_src belongs to */ + SceneCollection *sc_master = BKE_collection_master(scene); + + /* Master Layer can't be moved around*/ + if (ELEM(sc_master, sc_src, sc_dst)) { + return false; + } + + /* Collection is already where we wanted it to be */ + if (sc_dst->next == sc_src) { + return false; + } + + /* We can't move a collection if the destiny collection + * is nested to the source collection */ + if (is_collection_in_tree(sc_dst, sc_src)) { + return false; + } + + SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master); + SceneCollection *sc_dst_parent = find_collection_parent(sc_dst, sc_master); + BLI_assert(sc_src_parent); + BLI_assert(sc_dst_parent); + + /* Remove sc_src from its parent */ + BLI_remlink(&sc_src_parent->scene_collections, sc_src); + + /* Re-insert it where it belongs */ + BLI_insertlinkafter(&sc_dst_parent->scene_collections, sc_dst, sc_src); + + /* Update the tree */ + BKE_layer_collection_resync(scene, sc_src_parent); + BKE_layer_collection_resync(scene, sc_dst_parent); + + return true; +} + +bool BKE_collection_move_into(const Scene *scene, SceneCollection *sc_dst, SceneCollection *sc_src) +{ + /* Find the SceneCollection the sc_src belongs to */ + SceneCollection *sc_master = BKE_collection_master(scene); + if (sc_src == sc_master) { + return false; + } + + /* We can't move a collection if the destiny collection + * is nested to the source collection */ + if (is_collection_in_tree(sc_dst, sc_src)) { + return false; + } + + SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master); + BLI_assert(sc_src_parent); + + /* collection is already where we wanted it to be */ + if (sc_dst->scene_collections.last == sc_src) { + return false; + } + + /* Remove sc_src from it */ + BLI_remlink(&sc_src_parent->scene_collections, sc_src); + + /* Insert sc_src into sc_dst */ + BLI_addtail(&sc_dst->scene_collections, sc_src); + + /* Update the tree */ + BKE_layer_collection_resync(scene, sc_src_parent); + BKE_layer_collection_resync(scene, sc_dst); + + return true; +} + +/* ---------------------------------------------------------------------- */ /* Iteractors */ /* scene collection iteractor */ @@ -273,7 +460,7 @@ typedef struct SceneCollectionsIteratorData { Scene *scene; void **array; int tot, cur; - } SceneCollectionsIteratorData; +} SceneCollectionsIteratorData; static void scene_collection_callback(SceneCollection *sc, BKE_scene_collections_Cb callback, void *data) { @@ -384,7 +571,7 @@ void BKE_scene_objects_Iterator_begin(Iterator *iter, void *data_in) BKE_scene_collections_Iterator_begin(&data->scene_collection_iter, scene); SceneCollection *sc = data->scene_collection_iter.current; - iter->current = sc->objects.first; + iter->current = sc->objects.first ? ((LinkData *)sc->objects.first)->data : NULL; iter->valid = true; if (iter->current == NULL) { |