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:
authorDalai Felinto <dfelinto@gmail.com>2017-02-07 12:18:38 +0300
committerDalai Felinto <dfelinto@gmail.com>2017-02-07 13:11:00 +0300
commitaeb8e81f2741aabc95d14bce7a83cef45481959c (patch)
tree16a9a4af34f0b7cd114c66ea38625b1ca8e453e6 /source/blender/blenkernel
parent97fa285ae1b9b320f04ac0ac427917abc2de180a (diff)
Render Layers and Collections (merge from render-layers)
Design Documents ---------------- * https://wiki.blender.org/index.php/Dev:2.8/Source/Layers * https://wiki.blender.org/index.php/Dev:2.8/Source/DataDesignRevised User Commit Log --------------- * New Layer and Collection system to replace render layers and viewport layers. * A layer is a set of collections of objects (and their drawing options) required for specific tasks. * A collection is a set of objects, equivalent of the old layers in Blender. A collection can be shared across multiple layers. * All Scenes have a master collection that all other collections are children of. * New collection "context" tab (in Properties Editor) * New temporary viewport "collections" panel to control per-collection visibility Missing User Features --------------------- * Collection "Filter" Option to add objects based on their names * Collection Manager operators The existing buttons are placeholders * Collection Manager drawing The editor main region is empty * Collection Override * Per-Collection engine settings This will come as a separate commit, as part of the clay-engine branch Dev Commit Log -------------- * New DNA file (DNA_layer_types.h) with the new structs We are replacing Base by a new extended Base while keeping it backward compatible with some legacy settings (i.e., lay, flag_legacy). Renamed all Base to BaseLegacy to make it clear the areas of code that still need to be converted Note: manual changes were required on - deg_builder_nodes.h, rna_object.c, KX_Light.cpp * Unittesting for main syncronization requirements - read, write, add/copy/remove objects, copy scene, collection link/unlinking, context) * New Editor: Collection Manager Based on patch by Julian Eisel This is extracted from the layer-manager branch. With the following changes: - Renamed references of layer manager to collections manager - I doesn't include the editors/space_collections/ draw and util files - The drawing code itself will be implemented separately by Julian * Base / Object: A little note about them. Original Blender code would try to keep them in sync through the code, juggling flags back and forth. This will now be handled by Depsgraph, keeping Object and Bases more separated throughout the non-rendering code. Scene.base is being cleared in doversion, and the old viewport drawing code was poorly converted to use the new bases while the new viewport code doesn't get merged and replace the old one. Python API Changes ------------------ ``` - scene.layers + # no longer exists - scene.objects + scene.scene_layers.active.objects - scene.objects.active + scene.render_layers.active.objects.active - bpy.context.scene.objects.link() + bpy.context.scene_collection.objects.link() - bpy_extras.object_utils.object_data_add(context, obdata, operator=None, use_active_layer=True, name=None) + bpy_extras.object_utils.object_data_add(context, obdata, operator=None, name=None) - bpy.context.object.select + bpy.context.object.select = True + bpy.context.object.select = False + bpy.context.object.select_get() + bpy.context.object.select_set(action='SELECT') + bpy.context.object.select_set(action='DESELECT') -AddObjectHelper.layers + # no longer exists ```
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_collection.h91
-rw-r--r--source/blender/blenkernel/BKE_context.h8
-rw-r--r--source/blender/blenkernel/BKE_group.h5
-rw-r--r--source/blender/blenkernel/BKE_layer.h189
-rw-r--r--source/blender/blenkernel/BKE_node.h7
-rw-r--r--source/blender/blenkernel/BKE_object.h9
-rw-r--r--source/blender/blenkernel/BKE_scene.h23
-rw-r--r--source/blender/blenkernel/CMakeLists.txt4
-rw-r--r--source/blender/blenkernel/intern/anim.c4
-rw-r--r--source/blender/blenkernel/intern/cachefile.c2
-rw-r--r--source/blender/blenkernel/intern/camera.c2
-rw-r--r--source/blender/blenkernel/intern/collection.c455
-rw-r--r--source/blender/blenkernel/intern/collision.c4
-rw-r--r--source/blender/blenkernel/intern/context.c70
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c4
-rw-r--r--source/blender/blenkernel/intern/effect.c2
-rw-r--r--source/blender/blenkernel/intern/group.c17
-rw-r--r--source/blender/blenkernel/intern/layer.c684
-rw-r--r--source/blender/blenkernel/intern/library_query.c27
-rw-r--r--source/blender/blenkernel/intern/library_remap.c63
-rw-r--r--source/blender/blenkernel/intern/mball.c32
-rw-r--r--source/blender/blenkernel/intern/mball_tessellate.c4
-rw-r--r--source/blender/blenkernel/intern/node.c17
-rw-r--r--source/blender/blenkernel/intern/object.c40
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c2
-rw-r--r--source/blender/blenkernel/intern/particle_system.c2
-rw-r--r--source/blender/blenkernel/intern/pointcache.c2
-rw-r--r--source/blender/blenkernel/intern/scene.c240
-rw-r--r--source/blender/blenkernel/intern/smoke.c2
-rw-r--r--source/blender/blenkernel/intern/softbody.c6
-rw-r--r--source/blender/blenkernel/intern/sound.c2
31 files changed, 1849 insertions, 170 deletions
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
new file mode 100644
index 00000000000..c3f461dacd6
--- /dev/null
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -0,0 +1,91 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * Contributor(s): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_COLLECTION_H__
+#define __BKE_COLLECTION_H__
+
+/** \file blender/blenkernel/BKE_collection.h
+ * \ingroup bke
+ */
+
+#include "BLI_ghash.h"
+#include "BLI_iterator.h"
+#include "DNA_listBase.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Iterator;
+struct SceneCollection;
+struct Object;
+struct Base;
+struct Main;
+struct Scene;
+
+struct SceneCollection *BKE_collection_add(struct Scene *scene, struct SceneCollection *sc_parent, const char *name);
+bool BKE_collection_remove(struct Scene *scene, struct SceneCollection *sc);
+struct SceneCollection *BKE_collection_master(struct Scene *scene);
+void BKE_collection_master_free(struct Scene *scene);
+void BKE_collection_object_add(struct Scene *scene, struct SceneCollection *sc, struct Object *object);
+void BKE_collection_object_add_from(struct Scene *scene, struct Object *ob_src, struct Object *ob_dst);
+void BKE_collection_object_remove(struct Main *bmain, struct Scene *scene, struct SceneCollection *sc, struct Object *object, const bool free_us);
+void BKE_collections_object_remove(struct Main *bmain, struct Scene *scene, struct Object *object, const bool free_us);
+
+typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data);
+typedef void (*BKE_scene_collections_Cb)(struct SceneCollection *ob, void *data);
+
+void BKE_scene_collections_callback(struct Scene *scene, BKE_scene_collections_Cb callback, void *data);
+void BKE_scene_objects_callback(struct Scene *scene, BKE_scene_objects_Cb callback, void *data);
+
+/* iterators */
+void BKE_scene_collections_Iterator_begin(struct Iterator *iter, void *data_in);
+void BKE_scene_collections_Iterator_next(struct Iterator *iter);
+void BKE_scene_collections_Iterator_end(struct Iterator *iter);
+
+void BKE_scene_objects_Iterator_begin(struct Iterator *iter, void *data_in);
+void BKE_scene_objects_Iterator_next(struct Iterator *iter);
+void BKE_scene_objects_Iterator_end(struct Iterator *iter);
+
+#define FOREACH_SCENE_COLLECTION(scene, _sc) \
+ ITER_BEGIN(BKE_scene_collections_Iterator_begin, \
+ BKE_scene_collections_Iterator_next, \
+ BKE_scene_collections_Iterator_end, \
+ scene, _sc)
+
+#define FOREACH_SCENE_COLLECTION_END \
+ ITER_END
+
+#define FOREACH_SCENE_OBJECT(scene, _ob) \
+ ITER_BEGIN(BKE_scene_objects_Iterator_begin, \
+ BKE_scene_objects_Iterator_next, \
+ BKE_scene_objects_Iterator_end, \
+ scene, _ob)
+
+#define FOREACH_SCENE_OBJECT_END \
+ ITER_END
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BKE_COLLECTION_H__ */
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 4da6a61cbfa..23f9ff28f8b 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -40,12 +40,16 @@ extern "C" {
struct ARegion;
struct bScreen;
struct CacheFile;
+struct LayerCollection;
struct ListBase;
struct Main;
struct Object;
+struct Base;
struct PointerRNA;
struct ReportList;
struct Scene;
+struct SceneCollection;
+struct SceneLayer;
struct ScrArea;
struct SpaceLink;
struct View3D;
@@ -166,6 +170,7 @@ struct SpaceAction *CTX_wm_space_action(const bContext *C);
struct SpaceInfo *CTX_wm_space_info(const bContext *C);
struct SpaceUserPref *CTX_wm_space_userpref(const bContext *C);
struct SpaceClip *CTX_wm_space_clip(const bContext *C);
+struct SpaceCollections *CTX_wm_space_collections(const bContext *C);
void CTX_wm_manager_set(bContext *C, struct wmWindowManager *wm);
void CTX_wm_window_set(bContext *C, struct wmWindow *win);
@@ -239,6 +244,9 @@ int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBas
struct Main *CTX_data_main(const bContext *C);
struct Scene *CTX_data_scene(const bContext *C);
+struct LayerCollection *CTX_data_layer_collection(const bContext *C);
+struct SceneCollection *CTX_data_scene_collection(const bContext *C);
+struct SceneLayer *CTX_data_scene_layer(const bContext *C);
struct ToolSettings *CTX_data_tool_settings(const bContext *C);
const char *CTX_data_mode_string(const bContext *C);
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
index 09a069ee36f..f718e9c8555 100644
--- a/source/blender/blenkernel/BKE_group.h
+++ b/source/blender/blenkernel/BKE_group.h
@@ -33,6 +33,7 @@
* \author nzc
*/
+struct BaseLegacy;
struct Base;
struct EvaluationContext;
struct Group;
@@ -44,8 +45,8 @@ void BKE_group_free(struct Group *group);
struct Group *BKE_group_add(struct Main *bmain, const char *name);
struct Group *BKE_group_copy(struct Main *bmain, struct Group *group);
void BKE_group_make_local(struct Main *bmain, struct Group *group, const bool lib_local);
-bool BKE_group_object_add(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
-bool BKE_group_object_unlink(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
+bool BKE_group_object_add(struct Group *group, struct Object *ob);
+bool BKE_group_object_unlink(struct Group *group, struct Object *ob);
struct Group *BKE_group_object_find(struct Group *group, struct Object *ob);
bool BKE_group_object_exists(struct Group *group, struct Object *ob);
bool BKE_group_object_cyclic_check(struct Main *bmain, struct Object *object, struct Group *group);
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
new file mode 100644
index 00000000000..850c63f535f
--- /dev/null
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -0,0 +1,189 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * Contributor(s): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_LAYER_H__
+#define __BKE_LAYER_H__
+
+/** \file blender/blenkernel/BKE_layer.h
+ * \ingroup bke
+ */
+
+#include "BKE_collection.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TODO_LAYER_SYNC /* syncing of SceneCollection and LayerCollection trees*/
+#define TODO_LAYER_SYNC_FILTER /* syncing of filter_objects across all trees */
+#define TODO_LAYER_OVERRIDE /* CollectionOverride */
+#define TODO_LAYER_CONTEXT /* get/set current (context) SceneLayer */
+#define TODO_LAYER_BASE /* BaseLegacy to Base related TODO */
+#define TODO_LAYER_OPERATORS /* collection mamanger and property panel operators */
+#define TODO_LAYER /* generic todo */
+
+struct Base;
+struct ID;
+struct LayerCollection;
+struct Main;
+struct Object;
+struct Scene;
+struct SceneCollection;
+struct SceneLayer;
+
+struct SceneLayer *BKE_scene_layer_add(struct Scene *scene, const char *name);
+
+bool BKE_scene_layer_remove(struct Main *bmain, struct Scene *scene, struct SceneLayer *sl);
+
+void BKE_scene_layer_free(struct SceneLayer *sl);
+
+void BKE_scene_layer_engine_set(struct SceneLayer *sl, const char *engine);
+
+void BKE_scene_layer_selected_objects_tag(struct SceneLayer *sl, const int tag);
+
+struct SceneLayer *BKE_scene_layer_find_from_collection(struct Scene *scene, struct LayerCollection *lc);
+struct Base *BKE_scene_layer_base_find(struct SceneLayer *sl, struct Object *ob);
+void BKE_scene_layer_base_deselect_all(struct SceneLayer *sl);
+void BKE_scene_layer_base_select(struct SceneLayer *sl, struct Base *selbase);
+void BKE_scene_layer_base_flag_recalculate(struct SceneLayer *sl);
+
+void BKE_layer_collection_free(struct SceneLayer *sl, struct LayerCollection *lc);
+
+struct LayerCollection *BKE_layer_collection_active(struct SceneLayer *sl);
+
+int BKE_layer_collection_count(struct SceneLayer *sl);
+
+int BKE_layer_collection_findindex(struct SceneLayer *sl, struct LayerCollection *lc);
+
+struct LayerCollection *BKE_collection_link(struct SceneLayer *sl, struct SceneCollection *sc);
+
+void BKE_collection_unlink(struct SceneLayer *sl, struct LayerCollection *lc);
+
+bool BKE_scene_layer_has_collection(struct SceneLayer *sl, struct SceneCollection *sc);
+bool BKE_scene_has_object(struct Scene *scene, struct Object *ob);
+
+/* syncing */
+
+void BKE_layer_sync_new_scene_collection(struct Scene *scene, const struct SceneCollection *sc_parent, struct SceneCollection *sc);
+void BKE_layer_sync_object_link(struct Scene *scene, struct SceneCollection *sc, struct Object *ob);
+void BKE_layer_sync_object_unlink(struct Scene *scene, struct SceneCollection *sc, struct Object *ob);
+
+/* override */
+
+void BKE_collection_override_datablock_add(struct LayerCollection *lc, const char *data_path, struct ID *id);
+
+/* iterators */
+
+void BKE_selected_objects_Iterator_begin(Iterator *iter, void *data_in);
+void BKE_selected_objects_Iterator_next(Iterator *iter);
+void BKE_selected_objects_Iterator_end(Iterator *iter);
+
+void BKE_visible_objects_Iterator_begin(Iterator *iter, void *data_in);
+void BKE_visible_objects_Iterator_next(Iterator *iter);
+void BKE_visible_objects_Iterator_end(Iterator *iter);
+
+void BKE_visible_bases_Iterator_begin(Iterator *iter, void *data_in);
+void BKE_visible_bases_Iterator_next(Iterator *iter);
+void BKE_visible_bases_Iterator_end(Iterator *iter);
+
+#define FOREACH_SELECTED_OBJECT(sl, _ob) \
+ ITER_BEGIN(BKE_selected_objects_Iterator_begin, \
+ BKE_selected_objects_Iterator_next, \
+ BKE_selected_objects_Iterator_end, \
+ sl, _ob)
+
+#define FOREACH_SELECTED_OBJECT_END \
+ ITER_END
+
+#define FOREACH_VISIBLE_OBJECT(sl, _ob) \
+ ITER_BEGIN(BKE_visible_objects_Iterator_begin, \
+ BKE_visible_objects_Iterator_next, \
+ BKE_visible_objects_Iterator_end, \
+ sl, _ob)
+
+#define FOREACH_VISIBLE_OBJECT_END \
+ ITER_END
+
+
+#define FOREACH_VISIBLE_BASE(sl, _object_base) \
+ ITER_BEGIN(BKE_visible_bases_Iterator_begin, \
+ BKE_visible_bases_Iterator_next, \
+ BKE_visible_bases_Iterator_end, \
+ sl, _object_base)
+
+#define FOREACH_VISIBLE_BASE_END \
+ ITER_END
+
+
+#define FOREACH_OBJECT(sl, _ob) \
+{ \
+ Base *base; \
+ for (base = sl->object_bases.first; base; base = base->next) { \
+ _ob = base->object;
+
+#define FOREACH_OBJECT_END \
+ } \
+}
+
+#define FOREACH_OBJECT_FLAG(scene, sl, flag, _ob) \
+{ \
+ IteratorBeginCb func_begin; \
+ IteratorCb func_next, func_end; \
+ void *data_in; \
+ \
+ if (flag == SELECT) { \
+ func_begin = &BKE_selected_objects_Iterator_begin; \
+ func_next = &BKE_selected_objects_Iterator_next; \
+ func_end = &BKE_selected_objects_Iterator_end; \
+ data_in = sl; \
+ } \
+ else { \
+ func_begin = BKE_scene_objects_Iterator_begin; \
+ func_next = BKE_scene_objects_Iterator_next; \
+ func_end = BKE_scene_objects_Iterator_end; \
+ data_in = scene; \
+ } \
+ ITER_BEGIN(func_begin, func_next, func_end, data_in, _ob)
+
+
+#define FOREACH_OBJECT_FLAG_END \
+ ITER_END \
+}
+
+/* temporary hacky solution waiting for final depsgraph evaluation */
+#define DEG_OBJECT_ITER(sl_, ob_) \
+{ \
+ /* flush all the data to objects*/ \
+ Base *base_; \
+ for (base_ = sl->object_bases.first; base_; base_ = base_->next) { \
+ ob_ = base_->object; \
+ ob_->base_flag = base_->flag;
+
+#define DEG_OBJECT_ITER_END \
+ } \
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BKE_LAYER_H__ */
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 546f0d97c2b..67f7fa5e029 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -687,6 +687,13 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Tree
+ */
+
+void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, const int layer_index);
+
/* -------------------------------------------------------------------- */
/** \name Shader Nodes
*/
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index b1e218d3e5f..c1655d3e9c6 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -35,12 +35,13 @@ extern "C" {
#include "BLI_compiler_attrs.h"
-struct Base;
+struct BaseLegacy;
struct EvaluationContext;
struct Scene;
struct Object;
struct BoundBox;
struct View3D;
+struct SceneLayer;
struct SoftBody;
struct BulletSoftBody;
struct MovieClip;
@@ -89,9 +90,9 @@ struct Object *BKE_object_add_only_object(
int type, const char *name)
ATTR_NONNULL(1) ATTR_RETURNS_NONNULL;
struct Object *BKE_object_add(
- struct Main *bmain, struct Scene *scene,
+ struct Main *bmain, struct Scene *scene, struct SceneLayer *sl,
int type, const char *name)
- ATTR_NONNULL(1, 2) ATTR_RETURNS_NONNULL;
+ ATTR_NONNULL(1, 2, 3) ATTR_RETURNS_NONNULL;
void *BKE_object_obdata_add_from_type(
struct Main *bmain,
int type, const char *name)
@@ -255,7 +256,7 @@ typedef enum eObjectSet {
struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter);
struct LinkNode *BKE_object_groups(struct Object *ob);
-void BKE_object_groups_clear(struct Scene *scene, struct Base *base, struct Object *object);
+void BKE_object_groups_clear(struct Object *object);
struct KDTree *BKE_object_as_kdtree(struct Object *ob, int *r_tot);
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index d2152950bff..53bb69aedb6 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -38,10 +38,11 @@ extern "C" {
#endif
struct AviCodecData;
-struct Base;
+struct BaseLegacy;
struct EvaluationContext;
struct Main;
struct Object;
+struct Base;
struct QuicktimeCodecData;
struct RenderData;
struct SceneRenderLayer;
@@ -61,7 +62,7 @@ struct Main;
_base; \
_base = _setlooper_base_step(&_sce_iter, _base)
-struct Base *_setlooper_base_step(struct Scene **sce_iter, struct Base *base);
+struct BaseLegacy *_setlooper_base_step(struct Scene **sce_iter, struct BaseLegacy *base);
void free_avicodecdata(struct AviCodecData *acd);
void free_qtcodecdata(struct QuicktimeCodecData *acd);
@@ -70,13 +71,15 @@ void BKE_scene_free(struct Scene *sce);
void BKE_scene_init(struct Scene *sce);
struct Scene *BKE_scene_add(struct Main *bmain, const char *name);
+void BKE_scene_remove_rigidbody_object(struct Scene *scene, struct Object *ob);
+
/* base functions */
-struct Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name);
-struct Base *BKE_scene_base_find(struct Scene *scene, struct Object *ob);
-struct Base *BKE_scene_base_add(struct Scene *sce, struct Object *ob);
-void BKE_scene_base_unlink(struct Scene *sce, struct Base *base);
+struct BaseLegacy *BKE_scene_base_find_by_name(struct Scene *scene, const char *name);
+struct BaseLegacy *BKE_scene_base_find(struct Scene *scene, struct Object *ob);
+struct BaseLegacy *BKE_scene_base_add(struct Scene *sce, struct Object *ob);
+void BKE_scene_base_unlink(struct Scene *sce, struct BaseLegacy *base);
void BKE_scene_base_deselect_all(struct Scene *sce);
-void BKE_scene_base_select(struct Scene *sce, struct Base *selbase);
+void BKE_scene_base_select(struct Scene *sce, struct BaseLegacy *selbase);
/* Scene base iteration function.
* Define struct here, so no need to bother with alloc/free it.
@@ -90,10 +93,14 @@ typedef struct SceneBaseIter {
} SceneBaseIter;
int BKE_scene_base_iter_next(struct EvaluationContext *eval_ctx, struct SceneBaseIter *iter,
- struct Scene **scene, int val, struct Base **base, struct Object **ob);
+ struct Scene **scene, int val, struct BaseLegacy **base, struct Object **ob);
void BKE_scene_base_flag_to_objects(struct Scene *scene);
void BKE_scene_base_flag_from_objects(struct Scene *scene);
+void BKE_scene_base_flag_sync_from_base(struct BaseLegacy *base);
+void BKE_scene_base_flag_sync_from_object(struct BaseLegacy *base);
+void BKE_scene_object_base_flag_sync_from_base(struct Base *base);
+void BKE_scene_object_base_flag_sync_from_object(struct Base *base);
void BKE_scene_set_background(struct Main *bmain, struct Scene *sce);
struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index f3bab55b47d..6202c84f320 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -85,6 +85,7 @@ set(SRC
intern/camera.c
intern/cdderivedmesh.c
intern/cloth.c
+ intern/collection.c
intern/collision.c
intern/colortools.c
intern/constraint.c
@@ -157,6 +158,7 @@ set(SRC
intern/pbvh_bmesh.c
intern/pointcache.c
intern/property.c
+ intern/layer.c
intern/report.c
intern/rigidbody.c
intern/sca.c
@@ -214,6 +216,7 @@ set(SRC
BKE_ccg.h
BKE_cdderivedmesh.h
BKE_cloth.h
+ BKE_collection.h
BKE_collision.h
BKE_colortools.h
BKE_constraint.h
@@ -274,6 +277,7 @@ set(SRC
BKE_pbvh.h
BKE_pointcache.h
BKE_property.h
+ BKE_layer.h
BKE_report.h
BKE_rigidbody.h
BKE_sca.h
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 2f65e71c6d2..237e4e80172 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -283,7 +283,7 @@ void animviz_get_object_motionpaths(Object *ob, ListBase *targets)
/* tweak the object ordering to trick depsgraph into making MotionPath calculations run faster */
static void motionpaths_calc_optimise_depsgraph(Scene *scene, ListBase *targets)
{
- Base *base, *baseNext;
+ BaseLegacy *base, *baseNext;
MPathTarget *mpt;
/* make sure our temp-tag isn't already in use */
@@ -321,7 +321,7 @@ static void motionpaths_calc_update_scene(Scene *scene)
BKE_scene_update_for_newframe(G.main->eval_ctx, G.main, scene, scene->lay);
}
else { /* otherwise we can optimize by restricting updates */
- Base *base, *last = NULL;
+ BaseLegacy *base, *last = NULL;
/* only stuff that moves or needs display still */
DAG_scene_update_flags(G.main, scene, scene->lay, true, false);
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index 3dce08eb756..8630e8562b0 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -205,7 +205,7 @@ float BKE_cachefile_time_offset(CacheFile *cache_file, const float time, const f
/* TODO(kevin): replace this with some depsgraph mechanism, or something similar. */
void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file)
{
- for (Base *base = scene->base.first; base; base = base->next) {
+ for (BaseLegacy *base = scene->base.first; base; base = base->next) {
Object *ob = base->object;
ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache);
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 9cb553aa27b..978204f1cf5 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -853,7 +853,7 @@ static Object *camera_multiview_advanced(Scene *scene, Object *camera, const cha
}
if (name[0] != '\0') {
- Base *base = BKE_scene_base_find_by_name(scene, name);
+ BaseLegacy *base = BKE_scene_base_find_by_name(scene, name);
if (base) {
return base->object;
}
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
new file mode 100644
index 00000000000..f374ebd1e53
--- /dev/null
+++ b/source/blender/blenkernel/intern/collection.c
@@ -0,0 +1,455 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * Contributor(s): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/collection.c
+ * \ingroup bke
+ */
+
+#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
+#include "BLI_iterator.h"
+#include "BLI_listbase.h"
+#include "BLT_translation.h"
+#include "BLI_string_utils.h"
+
+#include "BKE_collection.h"
+#include "BKE_layer.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+
+#include "DNA_ID.h"
+#include "DNA_layer_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#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
+ */
+SceneCollection *BKE_collection_add(Scene *scene, SceneCollection *sc_parent, const char *name)
+{
+ SceneCollection *sc_master = BKE_collection_master(scene);
+ SceneCollection *sc = MEM_callocN(sizeof(SceneCollection), "New Collection");
+
+ if (!name) {
+ name = DATA_("New Collection");
+ }
+
+ if (!sc_parent) {
+ 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));
+
+ BLI_addtail(&sc_parent->scene_collections, sc);
+
+ BKE_layer_sync_new_scene_collection(scene, sc_parent, sc);
+ return sc;
+}
+
+/**
+ * Free the collection items recursively
+ */
+static void collection_free(SceneCollection *sc)
+{
+ for (LinkData *link = sc->objects.first; link; link = link->next) {
+ id_us_min(link->data);
+ }
+ BLI_freelistN(&sc->objects);
+
+ for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
+ id_us_min(link->data);
+ }
+ BLI_freelistN(&sc->filter_objects);
+
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ collection_free(nsc);
+ }
+ BLI_freelistN(&sc->scene_collections);
+}
+
+/**
+ * Unlink the collection recursively
+ * 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)
+ {
+ if (sc == sc_gone) {
+ BLI_remlink(&sc_parent->scene_collections, sc_gone);
+ return true;
+ }
+
+ if (collection_remlink(sc, sc_gone)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Recursively remove any instance of this SceneCollection
+ */
+static void layer_collection_remove(SceneLayer *sl, ListBase *lb, const SceneCollection *sc)
+{
+ LayerCollection *lc = lb->first;
+ while(lc) {
+ if (lc->scene_collection == sc) {
+ BKE_layer_collection_free(sl, lc);
+ BLI_remlink(lb, lc);
+
+ LayerCollection *lc_next = lc->next;
+ MEM_freeN(lc);
+ lc = lc_next;
+
+ /* only the "top-level" layer collections may have the
+ * same SceneCollection in a sibling tree.
+ */
+ if (lb != &sl->layer_collections) {
+ return;
+ }
+ }
+
+ else {
+ layer_collection_remove(sl, &lc->layer_collections, sc);
+ lc = lc->next;
+ }
+ }
+}
+
+/**
+ * Remove a collection from the scene, and syncronize all render layers
+ */
+bool BKE_collection_remove(Scene *scene, SceneCollection *sc)
+{
+ SceneCollection *sc_master = BKE_collection_master(scene);
+
+ /* the master collection cannot be removed */
+ if (sc == sc_master) {
+ return false;
+ }
+
+ /* unlink from the respective collection tree */
+ if (!collection_remlink(sc_master, sc)) {
+ BLI_assert(false);
+ }
+
+ /* clear the collection items */
+ collection_free(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;
+ }
+
+ MEM_freeN(sc);
+ return true;
+}
+
+/**
+ * Returns the master collection
+ */
+SceneCollection *BKE_collection_master(Scene *scene)
+{
+ return scene->collection;
+}
+
+/**
+ * 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){
+ collection_free(BKE_collection_master(scene));
+}
+
+static void collection_object_add(Scene *scene, SceneCollection *sc, Object *ob)
+{
+ BLI_addtail(&sc->objects, BLI_genericNodeN(ob));
+ id_us_plus((ID *)ob);
+ BKE_layer_sync_object_link(scene, sc, ob);
+}
+
+/**
+ * Add object to collection
+ */
+void BKE_collection_object_add(Scene *scene, SceneCollection *sc, Object *ob)
+{
+ if (BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) {
+ /* don't add the same object twice */
+ return;
+ }
+ collection_object_add(scene, sc, ob);
+}
+
+/**
+ * Add object to all collections that reference objects is in
+ * (used to copy objects)
+ */
+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))) {
+ collection_object_add(scene, sc, ob_dst);
+ }
+ }
+ FOREACH_SCENE_COLLECTION_END
+}
+
+/**
+ * Remove object from collection
+ */
+void BKE_collection_object_remove(Main *bmain, Scene *scene, SceneCollection *sc, Object *ob, const bool free_us)
+{
+
+ LinkData *link = BLI_findptr(&sc->objects, ob, offsetof(LinkData, data));
+
+ if (link == NULL) {
+ return;
+ }
+
+ BLI_remlink(&sc->objects, link);
+ MEM_freeN(link);
+
+ TODO_LAYER_SYNC_FILTER; /* need to remove all instances of ob in scene collections -> filter_objects */
+ BKE_layer_sync_object_unlink(scene, sc, ob);
+
+ if (free_us) {
+ BKE_libblock_free_us(bmain, ob);
+ }
+ else {
+ id_us_min(&ob->id);
+ }
+}
+
+/**
+ * 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);
+ }
+ FOREACH_SCENE_COLLECTION_END
+}
+
+/* ---------------------------------------------------------------------- */
+/* Iteractors */
+/* scene collection iteractor */
+
+typedef struct SceneCollectionsIteratorData {
+ Scene *scene;
+ void **array;
+ int tot, cur;
+ } SceneCollectionsIteratorData;
+
+static void scene_collection_callback(SceneCollection *sc, BKE_scene_collections_Cb callback, void *data)
+{
+ callback(sc, data);
+
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ scene_collection_callback(nsc, callback, data);
+ }
+}
+
+static void scene_collections_count(SceneCollection *UNUSED(sc), void *data)
+{
+ int *tot = data;
+ (*tot)++;
+}
+
+static void scene_collections_build_array(SceneCollection *sc, void *data)
+{
+ SceneCollection ***array = data;
+ **array = sc;
+ (*array)++;
+}
+
+static void scene_collections_array(Scene *scene, SceneCollection ***collections_array, int *tot)
+{
+ SceneCollection *sc = BKE_collection_master(scene);
+ SceneCollection **array;
+
+ *collections_array = NULL;
+ *tot = 0;
+
+ if (scene == NULL)
+ return;
+
+ scene_collection_callback(sc, scene_collections_count, tot);
+
+ if (*tot == 0)
+ return;
+
+ *collections_array = array = MEM_mallocN(sizeof(SceneCollection *) * (*tot), "SceneCollectionArray");
+ scene_collection_callback(sc, scene_collections_build_array, &array);
+}
+
+/**
+ * Only use this in non-performance critical situations
+ * (it iterates over all scene collections twice)
+ */
+void BKE_scene_collections_Iterator_begin(Iterator *iter, void *data_in)
+{
+ Scene *scene = data_in;
+ SceneCollectionsIteratorData *data = MEM_callocN(sizeof(SceneCollectionsIteratorData), __FUNCTION__);
+
+ data->scene = scene;
+ iter->data = data;
+
+ scene_collections_array(scene, (SceneCollection ***)&data->array, &data->tot);
+ BLI_assert(data->tot != 0);
+
+ data->cur = 0;
+ iter->current = data->array[data->cur];
+ iter->valid = true;
+}
+
+void BKE_scene_collections_Iterator_next(struct Iterator *iter)
+{
+ SceneCollectionsIteratorData *data = iter->data;
+
+ if (++data->cur < data->tot) {
+ iter->current = data->array[data->cur];
+ }
+ else {
+ iter->valid = false;
+ }
+}
+
+void BKE_scene_collections_Iterator_end(struct Iterator *iter)
+{
+ SceneCollectionsIteratorData *data = iter->data;
+
+ if (data) {
+ if (data->array) {
+ MEM_freeN(data->array);
+ }
+ MEM_freeN(data);
+ }
+ iter->valid = false;
+}
+
+
+/* scene objects iteractor */
+
+typedef struct SceneObjectsIteratorData {
+ GSet *visited;
+ LinkData *link;
+ Iterator scene_collection_iter;
+} SceneObjectsIteratorData;
+
+void BKE_scene_objects_Iterator_begin(Iterator *iter, void *data_in)
+{
+ Scene *scene = data_in;
+ SceneObjectsIteratorData *data = MEM_callocN(sizeof(SceneObjectsIteratorData), __FUNCTION__);
+ iter->data = data;
+
+ /* lookup list ot make sure each object is object called once */
+ data->visited = BLI_gset_ptr_new(__func__);
+
+ /* we wrap the scenecollection iterator here to go over the scene collections */
+ BKE_scene_collections_Iterator_begin(&data->scene_collection_iter, scene);
+
+ SceneCollection *sc = data->scene_collection_iter.current;
+ iter->current = sc->objects.first;
+
+ if (iter->current == NULL) {
+ BKE_scene_objects_Iterator_next(iter);
+ }
+}
+
+/**
+ * Gets the next unique object
+ */
+static LinkData *object_base_next(GSet *gs, LinkData *link)
+{
+ if (link == NULL) {
+ return NULL;
+ }
+
+ LinkData *link_next = link->next;
+ if (link_next) {
+ Object *ob = link_next->data;
+ if (!BLI_gset_haskey(gs, ob)) {
+ BLI_gset_add(gs, ob);
+ return link_next;
+ }
+ else {
+ return object_base_next(gs, link_next);
+ }
+ }
+ return NULL;
+}
+
+void BKE_scene_objects_Iterator_next(Iterator *iter)
+{
+ SceneObjectsIteratorData *data = iter->data;
+ LinkData *link = object_base_next(data->visited, data->link);
+
+ if (link) {
+ data->link = link;
+ iter->current = link->data;
+ }
+ else {
+ /* if this is the last object of this ListBase look at the next SceneCollection */
+ SceneCollection *sc;
+ BKE_scene_collections_Iterator_next(&data->scene_collection_iter);
+ do {
+ sc = data->scene_collection_iter.current;
+ /* get the first unique object of this collection */
+ LinkData *new_link = object_base_next(data->visited, sc->objects.first);
+ if (new_link) {
+ data->link = new_link;
+ iter->current = data->link->data;
+ return;
+ }
+ BKE_scene_collections_Iterator_next(&data->scene_collection_iter);
+ } while (data->scene_collection_iter.valid);
+
+ if (!data->scene_collection_iter.valid) {
+ iter->valid = false;
+ }
+ }
+}
+
+void BKE_scene_objects_Iterator_end(Iterator *iter)
+{
+ SceneObjectsIteratorData *data = iter->data;
+ if (data) {
+ BKE_scene_collections_Iterator_end(&data->scene_collection_iter);
+ BLI_gset_free(data->visited, NULL);
+ MEM_freeN(data);
+ }
+}
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index ee25be36855..b5f76240c0b 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -514,7 +514,7 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned
// collision object will exclude self
Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, int layer, unsigned int *numcollobj, unsigned int modifier_type, bool dupli)
{
- Base *base;
+ BaseLegacy *base;
Object **objs;
GroupObject *go;
unsigned int numobj= 0, maxobj= 100;
@@ -596,7 +596,7 @@ ListBase *get_collider_cache(Scene *scene, Object *self, Group *group)
}
else {
Scene *sce_iter;
- Base *base;
+ BaseLegacy *base;
/* add objects in same layer in scene */
for (SETLOOPER(scene, sce_iter, base)) {
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 4c01bfd35f2..1cbf8cf01c8 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -47,6 +47,7 @@
#include "BLT_translation.h"
#include "BKE_context.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_screen.h"
#include "BKE_sound.h"
@@ -814,6 +815,14 @@ struct SpaceClip *CTX_wm_space_clip(const bContext *C)
return NULL;
}
+struct SpaceCollections *CTX_wm_space_collections(const bContext *C)
+{
+ ScrArea *sa = CTX_wm_area(C);
+ if (sa && sa->spacetype == SPACE_COLLECTIONS)
+ return sa->spacedata.first;
+ return NULL;
+}
+
void CTX_wm_manager_set(bContext *C, wmWindowManager *wm)
{
C->wm.manager = wm;
@@ -836,8 +845,9 @@ void CTX_wm_window_set(bContext *C, wmWindow *win)
void CTX_wm_screen_set(bContext *C, bScreen *screen)
{
C->wm.screen = screen;
- if (C->wm.screen)
- C->data.scene = C->wm.screen->scene;
+ if (C->wm.screen) {
+ CTX_data_scene_set(C, C->wm.screen->scene);
+ }
C->wm.area = NULL;
C->wm.region = NULL;
}
@@ -896,6 +906,62 @@ Scene *CTX_data_scene(const bContext *C)
return C->data.scene;
}
+SceneLayer *CTX_data_scene_layer(const bContext *C)
+{
+ SceneLayer *sl;
+
+ if (ctx_data_pointer_verify(C, "render_layer", (void *)&sl)) {
+ return sl;
+ }
+ else {
+ Scene *scene = CTX_data_scene(C);
+ sl = BLI_findlink(&scene->render_layers, scene->active_layer);
+ BLI_assert(sl);
+ return sl;
+ }
+}
+
+/**
+ * This is tricky. Sometimes the user overrides the render_layer
+ * but not the scene_collection. In this case what to do?
+ *
+ * If the scene_collection is linked to the SceneLayer we use it.
+ * Otherwise we fallback to the active one of the SceneLayer.
+ */
+LayerCollection *CTX_data_layer_collection(const bContext *C)
+{
+ SceneLayer *sl = CTX_data_scene_layer(C);
+ LayerCollection *lc;
+
+ if (ctx_data_pointer_verify(C, "layer_collection", (void *)&lc)) {
+ if (BKE_scene_layer_has_collection(sl, lc->scene_collection)) {
+ return lc;
+ }
+ }
+
+ /* fallback */
+ return BKE_layer_collection_active(sl);
+}
+
+SceneCollection *CTX_data_scene_collection(const bContext *C)
+{
+ SceneCollection *sc;
+ if (ctx_data_pointer_verify(C, "scene_collection", (void *)&sc)) {
+ if (BKE_scene_layer_has_collection(CTX_data_scene_layer(C), sc)) {
+ return sc;
+ }
+ }
+
+ LayerCollection *lc = CTX_data_layer_collection(C);
+ if (lc) {
+ return lc->scene_collection;
+ }
+
+ /* fallback */
+ Scene *scene = CTX_data_scene(C);
+ return BKE_collection_master(scene);
+}
+
int CTX_data_mode_enum(const bContext *C)
{
Object *obedit = CTX_data_edit_object(C);
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index bc9871aee54..39d06a13e6e 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -488,7 +488,7 @@ static void scene_setSubframe(Scene *scene, float subframe)
static int surface_getBrushFlags(DynamicPaintSurface *surface, const Scene *scene)
{
- Base *base = NULL;
+ BaseLegacy *base = NULL;
GroupObject *go = NULL;
Object *brushObj = NULL;
ModifierData *md = NULL;
@@ -5780,7 +5780,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
* Loop through surface's target paint objects and do painting
*/
{
- Base *base = NULL;
+ BaseLegacy *base = NULL;
GroupObject *go = NULL;
Object *brushObj = NULL;
ModifierData *md = NULL;
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index fe8f5ebdca6..668d4d6c9e2 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -209,7 +209,7 @@ static void add_particles_to_effectors(ListBase **effectors, Scene *scene, Effec
ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src,
EffectorWeights *weights, bool for_simulation)
{
- Base *base;
+ BaseLegacy *base;
unsigned int layer= ob_src->lay;
ListBase *effectors = NULL;
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index 9b011dbb003..9c81a8b49be 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -130,18 +130,11 @@ static bool group_object_add_internal(Group *group, Object *ob)
return true;
}
-bool BKE_group_object_add(Group *group, Object *object, Scene *scene, Base *base)
+bool BKE_group_object_add(Group *group, Object *object)
{
if (group_object_add_internal(group, object)) {
if ((object->flag & OB_FROMGROUP) == 0) {
-
- if (scene && base == NULL)
- base = BKE_scene_base_find(scene, object);
-
object->flag |= OB_FROMGROUP;
-
- if (base)
- base->flag |= OB_FROMGROUP;
}
return true;
}
@@ -208,18 +201,12 @@ bool BKE_group_object_cyclic_check(Main *bmain, Object *object, Group *group)
return group_object_cyclic_check_internal(object, group);
}
-bool BKE_group_object_unlink(Group *group, Object *object, Scene *scene, Base *base)
+bool BKE_group_object_unlink(Group *group, Object *object)
{
if (group_object_unlink_internal(group, object)) {
/* object can be NULL */
if (object && BKE_group_object_find(NULL, object) == NULL) {
- if (scene && base == NULL)
- base = BKE_scene_base_find(scene, object);
-
object->flag &= ~OB_FROMGROUP;
-
- if (base)
- base->flag &= ~OB_FROMGROUP;
}
return true;
}
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
new file mode 100644
index 00000000000..cec1d70463f
--- /dev/null
+++ b/source/blender/blenkernel/intern/layer.c
@@ -0,0 +1,684 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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.
+ *
+ * Contributor(s): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/layer.c
+ * \ingroup bke
+ */
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_string_utf8.h"
+#include "BLI_string_utils.h"
+#include "BLT_translation.h"
+
+#include "BKE_layer.h"
+#include "BKE_collection.h"
+#include "BKE_layer.h"
+#include "BKE_main.h"
+#include "BKE_node.h"
+
+#include "DNA_ID.h"
+#include "DNA_layer_types.h"
+#include "DNA_object_types.h"
+#include "DNA_node_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+/* prototype */
+static void layer_collection_free(SceneLayer *sl, LayerCollection *lc);
+static LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, SceneCollection *sc);
+static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc);
+static void object_bases_Iterator_next(Iterator *iter, const int flag);
+
+/* RenderLayer */
+
+/**
+ * Add a new renderlayer
+ * by default, a renderlayer has the master collection
+ */
+SceneLayer *BKE_scene_layer_add(Scene *scene, const char *name)
+{
+ if (!name) {
+ name = DATA_("Render Layer");
+ }
+
+ SceneLayer *sl = MEM_callocN(sizeof(SceneLayer), "Scene Layer");
+ sl->flag |= SCENE_LAYER_RENDER;
+
+ BLI_addtail(&scene->render_layers, sl);
+
+ /* unique name */
+ BLI_strncpy_utf8(sl->name, name, sizeof(sl->name));
+ BLI_uniquename(&scene->render_layers, sl, DATA_("SceneLayer"), '.', offsetof(SceneLayer, name), sizeof(sl->name));
+
+ SceneCollection *sc = BKE_collection_master(scene);
+ layer_collection_add(sl, &sl->layer_collections, sc);
+
+ return sl;
+}
+
+bool BKE_scene_layer_remove(Main *bmain, Scene *scene, SceneLayer *sl)
+{
+ const int act = BLI_findindex(&scene->render_layers, sl);
+
+ if (act == -1) {
+ return false;
+ }
+ else if ( (scene->render_layers.first == scene->render_layers.last) &&
+ (scene->render_layers.first == sl))
+ {
+ /* ensure 1 layer is kept */
+ return false;
+ }
+
+ BLI_remlink(&scene->render_layers, sl);
+
+ BKE_scene_layer_free(sl);
+ MEM_freeN(sl);
+
+ scene->active_layer = 0;
+ /* TODO WORKSPACE: set active_layer to 0 */
+
+ for (Scene *sce = bmain->scene.first; sce; sce = sce->id.next) {
+ if (sce->nodetree) {
+ BKE_nodetree_remove_layer_n(sce->nodetree, scene, act);
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Free (or release) any data used by this SceneLayer (does not free the SceneLayer itself).
+ */
+void BKE_scene_layer_free(SceneLayer *sl)
+{
+ sl->basact = NULL;
+ BLI_freelistN(&sl->object_bases);
+
+ for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+ layer_collection_free(NULL, lc);
+ }
+ BLI_freelistN(&sl->layer_collections);
+}
+
+/**
+ * Set the render engine of a renderlayer
+ */
+void BKE_scene_layer_engine_set(SceneLayer *sl, const char *engine)
+{
+ BLI_strncpy_utf8(sl->engine, engine, sizeof(sl->engine));
+}
+
+/**
+ * Tag all the selected objects of a renderlayer
+ */
+void BKE_scene_layer_selected_objects_tag(SceneLayer *sl, const int tag)
+{
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTED) != 0) {
+ base->object->flag |= tag;
+ }
+ else {
+ base->object->flag &= ~tag;
+ }
+ }
+}
+
+static bool find_scene_collection_in_scene_collections(ListBase *lb, const LayerCollection *lc)
+{
+ for (LayerCollection *lcn = lb->first; lcn; lcn = lcn->next) {
+ if (lcn == lc) {
+ return true;
+ }
+ if (find_scene_collection_in_scene_collections(&lcn->layer_collections, lc)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Find the SceneLayer a LayerCollection belongs to
+ */
+SceneLayer *BKE_scene_layer_find_from_collection(Scene *scene, LayerCollection *lc)
+{
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ if (find_scene_collection_in_scene_collections(&sl->layer_collections, lc)) {
+ return sl;
+ }
+ }
+ return NULL;
+}
+
+/* Base */
+
+Base *BKE_scene_layer_base_find(SceneLayer *sl, Object *ob)
+{
+ return BLI_findptr(&sl->object_bases, ob, offsetof(Base, object));
+}
+
+void BKE_scene_layer_base_deselect_all(SceneLayer *sl)
+{
+ Base *base;
+
+ for (base = sl->object_bases.first; base; base = base->next) {
+ base->flag &= ~BASE_SELECTED;
+ }
+}
+
+void BKE_scene_layer_base_select(struct SceneLayer *sl, Base *selbase)
+{
+ sl->basact = selbase;
+ if ((selbase->flag & BASE_SELECTABLED) != 0) {
+ selbase->flag |= BASE_SELECTED;
+ }
+}
+
+static void scene_layer_object_base_unref(SceneLayer* sl, Base *base)
+{
+ base->refcount--;
+
+ /* It only exists in the RenderLayer */
+ if (base->refcount == 0) {
+ if (sl->basact == base) {
+ sl->basact = NULL;
+ }
+
+ BLI_remlink(&sl->object_bases, base);
+ MEM_freeN(base);
+ }
+}
+
+static void layer_collection_base_flag_recalculate(LayerCollection *lc, const bool tree_is_visible, const bool tree_is_selectable)
+{
+ bool is_visible = tree_is_visible && ((lc->flag & COLLECTION_VISIBLE) != 0);
+ /* an object can only be selected if it's visible */
+ bool is_selectable = tree_is_selectable && is_visible && ((lc->flag & COLLECTION_SELECTABLE) != 0);
+
+ for (LinkData *link = lc->object_bases.first; link; link = link->next) {
+ Base *base = link->data;
+
+ if (is_visible) {
+ base->flag |= BASE_VISIBLED;
+ }
+ else {
+ base->flag &= ~BASE_VISIBLED;
+ }
+
+ if (is_selectable) {
+ base->flag |= BASE_SELECTABLED;
+ }
+ else {
+ base->flag &= ~BASE_SELECTABLED;
+ }
+ }
+
+ for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) {
+ layer_collection_base_flag_recalculate(lcn, is_visible, is_selectable);
+ }
+}
+
+/**
+ * Re-evaluate the ObjectBase flags for SceneLayer
+ */
+void BKE_scene_layer_base_flag_recalculate(SceneLayer *sl)
+{
+ for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+ layer_collection_base_flag_recalculate(lc, true, true);
+ }
+
+ /* if base is not selectabled, clear select */
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTABLED) == 0) {
+ base->flag &= ~BASE_SELECTED;
+ }
+ }
+}
+
+/**
+ * Return the base if existent, or create it if necessary
+ * Always bump the refcount
+ */
+static Base *object_base_add(SceneLayer *sl, Object *ob)
+{
+ Base *base;
+ base = BKE_scene_layer_base_find(sl, ob);
+
+ if (base == NULL) {
+ base = MEM_callocN(sizeof(Base), "Object Base");
+
+ /* do not bump user count, leave it for SceneCollections */
+ base->object = ob;
+ BLI_addtail(&sl->object_bases, base);
+ }
+ base->refcount++;
+ return base;
+}
+
+/* LayerCollection */
+
+/**
+ * When freeing the entire SceneLayer at once we don't bother with unref
+ * otherwise SceneLayer is passed to keep the syncing of the LayerCollection tree
+ */
+static void layer_collection_free(SceneLayer *sl, LayerCollection *lc)
+{
+ if (sl) {
+ for (LinkData *link = lc->object_bases.first; link; link = link->next) {
+ scene_layer_object_base_unref(sl, link->data);
+ }
+ }
+
+ BLI_freelistN(&lc->object_bases);
+ BLI_freelistN(&lc->overrides);
+
+ for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ layer_collection_free(sl, nlc);
+ }
+ BLI_freelistN(&lc->layer_collections);
+}
+
+/**
+ * Free (or release) LayerCollection from SceneLayer
+ * (does not free the LayerCollection itself).
+ */
+void BKE_layer_collection_free(SceneLayer *sl, LayerCollection *lc)
+{
+ layer_collection_free(sl, lc);
+}
+
+/* LayerCollection */
+
+/**
+ * Recursively get the collection for a given index
+ */
+static LayerCollection *collection_from_index(ListBase *lb, const int number, int *i)
+{
+ for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+ if (*i == number) {
+ return lc;
+ }
+
+ (*i)++;
+
+ LayerCollection *lc_nested = collection_from_index(&lc->layer_collections, number, i);
+ if (lc_nested) {
+ return lc_nested;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Get the active collection
+ */
+LayerCollection *BKE_layer_collection_active(SceneLayer *sl)
+{
+ int i = 0;
+ return collection_from_index(&sl->layer_collections, sl->active_collection, &i);
+}
+
+/**
+ * Recursively get the count of collections
+ */
+static int collection_count(ListBase *lb)
+{
+ int i = 0;
+ for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+ i += collection_count(&lc->layer_collections) + 1;
+ }
+ return i;
+}
+
+/**
+ * Get the total number of collections
+ * (including all the nested collections)
+ */
+int BKE_layer_collection_count(SceneLayer *sl)
+{
+ return collection_count(&sl->layer_collections);
+}
+
+/**
+ * Recursively get the index for a given collection
+ */
+static int index_from_collection(ListBase *lb, LayerCollection *lc, int *i)
+{
+ for (LayerCollection *lcol = lb->first; lcol; lcol = lcol->next) {
+ if (lcol == lc) {
+ return *i;
+ }
+
+ (*i)++;
+
+ int i_nested = index_from_collection(&lcol->layer_collections, lc, i);
+ if (i_nested != -1) {
+ return i_nested;
+ }
+ }
+ return -1;
+}
+
+/**
+ * Return -1 if not found
+ */
+int BKE_layer_collection_findindex(SceneLayer *sl, LayerCollection *lc)
+{
+ int i = 0;
+ return index_from_collection(&sl->layer_collections, lc, &i);
+}
+
+/**
+ * Link a collection to a renderlayer
+ * The collection needs to be created separately
+ */
+LayerCollection *BKE_collection_link(SceneLayer *sl, SceneCollection *sc)
+{
+ LayerCollection *lc = layer_collection_add(sl, &sl->layer_collections, sc);
+ sl->active_collection = BKE_layer_collection_findindex(sl, lc);
+ return lc;
+}
+
+/**
+ * Unlink a collection base from a renderlayer
+ * The corresponding collection is not removed from the master collection
+ */
+void BKE_collection_unlink(SceneLayer *sl, LayerCollection *lc)
+{
+ BKE_layer_collection_free(sl, lc);
+ BKE_scene_layer_base_flag_recalculate(sl);
+
+ BLI_remlink(&sl->layer_collections, lc);
+ MEM_freeN(lc);
+ sl->active_collection = 0;
+}
+
+static void layer_collection_object_add(SceneLayer *sl, LayerCollection *lc, Object *ob)
+{
+ Base *base = object_base_add(sl, ob);
+
+ /* only add an object once - prevent SceneCollection->objects and
+ * SceneCollection->filter_objects to add the same object */
+
+ if (BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data))) {
+ return;
+ }
+
+ BLI_addtail(&lc->object_bases, BLI_genericNodeN(base));
+
+ BKE_scene_layer_base_flag_recalculate(sl);
+}
+
+static void layer_collection_object_remove(SceneLayer *sl, LayerCollection *lc, Object *ob)
+{
+ Base *base;
+ base = BKE_scene_layer_base_find(sl, ob);
+
+ LinkData *link = BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data));
+ BLI_remlink(&lc->object_bases, link);
+ MEM_freeN(link);
+
+ scene_layer_object_base_unref(sl, base);
+}
+
+static void layer_collection_objects_populate(SceneLayer *sl, LayerCollection *lc, ListBase *objects)
+{
+ for (LinkData *link = objects->first; link; link = link->next) {
+ layer_collection_object_add(sl, lc, link->data);
+ }
+}
+
+static void layer_collection_populate(SceneLayer *sl, LayerCollection *lc, SceneCollection *sc)
+{
+ layer_collection_objects_populate(sl, lc, &sc->objects);
+ layer_collection_objects_populate(sl, lc, &sc->filter_objects);
+
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ layer_collection_add(sl, &lc->layer_collections, nsc);
+ }
+}
+
+static LayerCollection *layer_collection_add(SceneLayer *sl, ListBase *lb, SceneCollection *sc)
+{
+ LayerCollection *lc = MEM_callocN(sizeof(LayerCollection), "Collection Base");
+ BLI_addtail(lb, lc);
+
+ lc->scene_collection = sc;
+ lc->flag = COLLECTION_VISIBLE + COLLECTION_SELECTABLE + COLLECTION_FOLDED;
+
+ layer_collection_populate(sl, lc, sc);
+ return lc;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+/**
+ * See if render layer has the scene collection linked directly, or indirectly (nested)
+ */
+bool BKE_scene_layer_has_collection(struct SceneLayer *sl, struct SceneCollection *sc)
+{
+ for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+ if (find_layer_collection_by_scene_collection(lc, sc) != NULL) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * See if the object is in any of the scene layers of the scene
+ */
+bool BKE_scene_has_object(Scene *scene, Object *ob)
+{
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ Base *base = BKE_scene_layer_base_find(sl, ob);
+ if (base) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/* ---------------------------------------------------------------------- */
+/* Syncing */
+
+static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc)
+{
+ if (lc->scene_collection == sc) {
+ return lc;
+ }
+
+ for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ LayerCollection *found = find_layer_collection_by_scene_collection(nlc, sc);
+ if (found) {
+ return found;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Add a new LayerCollection for all the SceneLayers that have sc_parent
+ */
+void BKE_layer_sync_new_scene_collection(Scene *scene, const SceneCollection *sc_parent, SceneCollection *sc)
+{
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+ LayerCollection *lc_parent = find_layer_collection_by_scene_collection(lc, sc_parent);
+ if (lc_parent) {
+ layer_collection_add(sl, &lc_parent->layer_collections, sc);
+ }
+ }
+ }
+}
+
+/**
+ * Add a corresponding ObjectBase to all the equivalent LayerCollection
+ */
+void BKE_layer_sync_object_link(Scene *scene, SceneCollection *sc, Object *ob)
+{
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+ LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc);
+ if (found) {
+ layer_collection_object_add(sl, found, ob);
+ }
+ }
+ }
+}
+
+/**
+ * Remove the equivalent object base to all layers that have this collection
+ * also remove all reference to ob in the filter_objects
+ */
+void BKE_layer_sync_object_unlink(Scene *scene, SceneCollection *sc, Object *ob)
+{
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ for (LayerCollection *lc = sl->layer_collections.first; lc; lc = lc->next) {
+ LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc);
+ if (found) {
+ layer_collection_object_remove(sl, found, ob);
+ }
+ }
+ BKE_scene_layer_base_flag_recalculate(sl);
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* Override */
+
+/**
+ * Add a new datablock override
+ */
+void BKE_collection_override_datablock_add(LayerCollection *UNUSED(lc), const char *UNUSED(data_path), ID *UNUSED(id))
+{
+ TODO_LAYER_OVERRIDE;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Iterators */
+
+static void object_bases_Iterator_begin(Iterator *iter, void *data_in, const int flag)
+{
+ SceneLayer *sl = data_in;
+ Base *base = sl->object_bases.first;
+
+ /* when there are no objects */
+ if (base == NULL) {
+ iter->valid = false;
+ return;
+ }
+
+ iter->valid = true;
+ iter->data = base;
+
+ if ((base->flag & flag) == 0) {
+ object_bases_Iterator_next(iter, flag);
+ }
+ else {
+ iter->current = base;
+ }
+}
+
+static void object_bases_Iterator_next(Iterator *iter, const int flag)
+{
+ Base *base = ((Base *)iter->data)->next;
+
+ while (base) {
+ if ((base->flag & flag) != 0) {
+ iter->current = base;
+ iter->data = base;
+ return;
+ }
+ base = base->next;
+ }
+
+ iter->current = NULL;
+ iter->valid = false;
+}
+
+static void objects_Iterator_begin(Iterator *iter, void *data_in, const int flag)
+{
+ object_bases_Iterator_begin(iter, data_in, flag);
+
+ if (iter->valid) {
+ iter->current = ((Base *)iter->current)->object;
+ }
+}
+
+static void objects_Iterator_next(Iterator *iter, const int flag)
+{
+ object_bases_Iterator_next(iter, flag);
+
+ if (iter->valid) {
+ iter->current = ((Base *)iter->current)->object;
+ }
+}
+
+void BKE_selected_objects_Iterator_begin(Iterator *iter, void *data_in)
+{
+ objects_Iterator_begin(iter, data_in, BASE_SELECTED);
+}
+
+void BKE_selected_objects_Iterator_next(Iterator *iter)
+{
+ objects_Iterator_next(iter, BASE_SELECTED);
+}
+
+void BKE_selected_objects_Iterator_end(Iterator *UNUSED(iter))
+{
+ /* do nothing */
+}
+
+void BKE_visible_objects_Iterator_begin(Iterator *iter, void *data_in)
+{
+ objects_Iterator_begin(iter, data_in, BASE_VISIBLED);
+}
+
+void BKE_visible_objects_Iterator_next(Iterator *iter)
+{
+ objects_Iterator_next(iter, BASE_VISIBLED);
+}
+
+void BKE_visible_objects_Iterator_end(Iterator *UNUSED(iter))
+{
+ /* do nothing */
+}
+
+void BKE_visible_bases_Iterator_begin(Iterator *iter, void *data_in)
+{
+ object_bases_Iterator_begin(iter, data_in, BASE_VISIBLED);
+}
+
+void BKE_visible_bases_Iterator_next(Iterator *iter)
+{
+ object_bases_Iterator_next(iter, BASE_VISIBLED);
+}
+
+void BKE_visible_bases_Iterator_end(Iterator *UNUSED(iter))
+{
+ /* do nothing */
+}
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index 9685f1f5af6..a071b3202be 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -68,6 +68,7 @@
#include "BLI_linklist_stack.h"
#include "BKE_animsys.h"
+#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_fcurve.h"
#include "BKE_library.h"
@@ -354,7 +355,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
Scene *scene = (Scene *) id;
ToolSettings *toolsett = scene->toolsettings;
SceneRenderLayer *srl;
- Base *base;
+ BaseLegacy *legacy_base;
CALLBACK_INVOKE(scene->camera, IDWALK_CB_NOP);
CALLBACK_INVOKE(scene->world, IDWALK_CB_USER);
@@ -411,8 +412,28 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
CALLBACK_INVOKE(scene->gpd, IDWALK_CB_USER);
- for (base = scene->base.first; base; base = base->next) {
- CALLBACK_INVOKE(base->object, IDWALK_CB_USER);
+ for (legacy_base = scene->base.first; legacy_base; legacy_base = legacy_base->next) {
+ CALLBACK_INVOKE(legacy_base->object, IDWALK_CB_USER);
+ }
+
+ SceneCollection *sc;
+ FOREACH_SCENE_COLLECTION(scene, sc)
+ {
+ for (LinkData *link = sc->objects.first; link; link = link->next) {
+ CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER);
+ }
+
+ for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
+ CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER);
+ }
+ }
+ FOREACH_SCENE_COLLECTION_END
+
+ SceneLayer *sl;
+ for (sl = scene->render_layers.first; sl; sl = sl->next) {
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ CALLBACK_INVOKE(base->object, IDWALK_NOP);
+ }
}
for (TimeMarker *marker = scene->markers.first; marker; marker = marker->next) {
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index a408b498f18..9946d1cc81f 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -71,6 +71,7 @@
#include "BKE_brush.h"
#include "BKE_camera.h"
#include "BKE_cachefile.h"
+#include "BKE_collection.h"
#include "BKE_curve.h"
#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
@@ -242,7 +243,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
/* Some reamapping unfortunately require extra and/or specific handling, tackle those here. */
static void libblock_remap_data_preprocess_scene_base_unlink(
- IDRemap *r_id_remap_data, Scene *sce, Base *base, const bool skip_indirect, const bool is_indirect)
+ IDRemap *r_id_remap_data, Scene *sce, BaseLegacy *base, const bool skip_indirect, const bool is_indirect)
{
if (skip_indirect && is_indirect) {
r_id_remap_data->skipped_indirect++;
@@ -258,6 +259,22 @@ static void libblock_remap_data_preprocess_scene_base_unlink(
}
}
+/* Some remapping unfortunately require extra and/or specific handling, tackle those here. */
+static void libblock_remap_data_preprocess_scene_object_unlink(
+ IDRemap *r_id_remap_data, Scene *sce, Object *ob, const bool skip_indirect, const bool is_indirect)
+{
+ if (skip_indirect && is_indirect) {
+ r_id_remap_data->skipped_indirect++;
+ r_id_remap_data->skipped_refcounted++;
+ }
+ else {
+ BKE_collections_object_remove(r_id_remap_data->bmain, sce, ob, false);
+ if (!is_indirect) {
+ r_id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
+ }
+ }
+}
+
static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
{
switch (GS(r_id_remap_data->id->name)) {
@@ -272,7 +289,16 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
/* In case we are unlinking... */
if (!r_id_remap_data->old_id) {
/* ... everything from scene. */
- Base *base, *base_next;
+ Object *ob_iter;
+ FOREACH_SCENE_OBJECT(sce, ob_iter)
+ {
+ libblock_remap_data_preprocess_scene_object_unlink(
+ r_id_remap_data, sce, ob_iter, skip_indirect, is_indirect);
+ }
+ FOREACH_SCENE_OBJECT_END
+
+
+ BaseLegacy *base, *base_next;
for (base = sce->base.first; base; base = base_next) {
base_next = base->next;
libblock_remap_data_preprocess_scene_base_unlink(
@@ -282,8 +308,11 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
else if (GS(r_id_remap_data->old_id->name) == ID_OB) {
/* ... a specific object from scene. */
Object *old_ob = (Object *)r_id_remap_data->old_id;
- Base *base = BKE_scene_base_find(sce, old_ob);
+ libblock_remap_data_preprocess_scene_object_unlink(
+ r_id_remap_data, sce, old_ob, skip_indirect, is_indirect);
+
+ BaseLegacy *base = BKE_scene_base_find(sce, old_ob);
if (base) {
libblock_remap_data_preprocess_scene_base_unlink(
r_id_remap_data, sce, base, skip_indirect, is_indirect);
@@ -329,7 +358,7 @@ static void libblock_remap_data_postprocess_object_fromgroup_update(Main *bmain,
}
if (new_ob == NULL) { /* We need to remove NULL-ified groupobjects... */
for (Group *group = bmain->group.first; group; group = group->id.next) {
- BKE_group_object_unlink(group, NULL, NULL, NULL);
+ BKE_group_object_unlink(group, NULL);
}
}
else {
@@ -342,23 +371,17 @@ static void libblock_remap_data_postprocess_group_scene_unlink(Main *UNUSED(bmai
{
/* Note that here we assume no object has no base (i.e. all objects are assumed instanced
* in one scene...). */
- for (Base *base = sce->base.first; base; base = base->next) {
- if (base->flag & OB_FROMGROUP) {
- Object *ob = base->object;
-
- if (ob->flag & OB_FROMGROUP) {
- Group *grp = BKE_group_object_find(NULL, ob);
-
- /* Unlinked group (old_id) is still in bmain... */
- if (grp && (&grp->id == old_id || grp->id.us == 0)) {
- grp = BKE_group_object_find(grp, ob);
- }
- if (!grp) {
- ob->flag &= ~OB_FROMGROUP;
- }
+ for (BaseLegacy *base = sce->base.first; base; base = base->next) {
+ Object *ob = base->object;
+ if (ob->flag & OB_FROMGROUP) {
+ Group *grp = BKE_group_object_find(NULL, ob);
+
+ /* Unlinked group (old_id) is still in bmain... */
+ if (grp && (&grp->id == old_id || grp->id.us == 0)) {
+ grp = BKE_group_object_find(grp, ob);
}
- if (!(ob->flag & OB_FROMGROUP)) {
- base->flag &= ~OB_FROMGROUP;
+ if (!grp) {
+ ob->flag &= ~OB_FROMGROUP;
}
}
}
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 97033a9555d..2632acea58b 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -316,7 +316,7 @@ bool BKE_mball_is_basis_for(Object *ob1, Object *ob2)
void BKE_mball_properties_copy(Scene *scene, Object *active_object)
{
Scene *sce_iter = scene;
- Base *base;
+ BaseLegacy *base;
Object *ob;
MetaBall *active_mball = (MetaBall *)active_object->data;
int basisnr, obnr;
@@ -359,27 +359,25 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object)
*/
Object *BKE_mball_basis_find(Scene *scene, Object *basis)
{
- Scene *sce_iter = scene;
- Base *base;
- Object *ob, *bob = basis;
+ Object *bob = basis;
int basisnr, obnr;
char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
- SceneBaseIter iter;
- EvaluationContext *eval_ctx = G.main->eval_ctx;
BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.');
- BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
- while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
- if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) {
- if (ob != bob) {
- BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
-
- /* object ob has to be in same "group" ... it means, that it has to have same base of its name */
- if (STREQ(obname, basisname)) {
- if (obnr < basisnr) {
- basis = ob;
- basisnr = obnr;
+ for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) {
+ for (Base *base = sl->object_bases.first; base; base = base->next) {
+ Object *ob = base->object;
+ if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) {
+ if (ob != bob) {
+ BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
+
+ /* object ob has to be in same "group" ... it means, that it has to have same base of its name */
+ if (STREQ(obname, basisname)) {
+ if (obnr < basisnr) {
+ basis = ob;
+ basisnr = obnr;
+ }
}
}
}
diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c
index 5c0b09f0ff0..144a885ffd4 100644
--- a/source/blender/blenkernel/intern/mball_tessellate.c
+++ b/source/blender/blenkernel/intern/mball_tessellate.c
@@ -1080,7 +1080,7 @@ static void polygonize(PROCESS *process)
static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob)
{
Scene *sce_iter = scene;
- Base *base;
+ BaseLegacy *base;
Object *bob;
MetaBall *mb;
const MetaElem *ml;
@@ -1102,7 +1102,7 @@ static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scen
zero_size = 0;
ml = NULL;
- if (bob == ob && (base->flag & OB_FROMDUPLI) == 0) {
+ if (bob == ob && (base->flag_legacy & OB_FROMDUPLI) == 0) {
mb = ob->data;
if (mb->editelems) ml = mb->editelems->first;
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 3f3b4896653..05422a01dbf 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -3776,3 +3776,20 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
return true;
}
+
+/* -------------------------------------------------------------------- */
+/* NodeTree kernel functions */
+
+void BKE_nodetree_remove_layer_n(bNodeTree *ntree, Scene *scene, const int layer_index)
+{
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_R_LAYERS && (Scene *)node->id == scene) {
+ if (node->custom1 == layer_index) {
+ node->custom1 = 0;
+ }
+ else if (node->custom1 > layer_index) {
+ node->custom1--;
+ }
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index ff8be5892e9..08cb9e57ab4 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -91,6 +91,7 @@
#include "BKE_icons.h"
#include "BKE_key.h"
#include "BKE_lamp.h"
+#include "BKE_layer.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
@@ -153,7 +154,7 @@ void BKE_object_workob_clear(Object *workob)
void BKE_object_update_base_layer(struct Scene *scene, Object *ob)
{
- Base *base = scene->base.first;
+ BaseLegacy *base = scene->base.first;
while (base) {
if (base->object == ob) base->lay = ob->lay;
@@ -677,23 +678,25 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
/* general add: to scene, with layer from area and default name */
/* creates minimum required data, but without vertices etc. */
Object *BKE_object_add(
- Main *bmain, Scene *scene,
+ Main *bmain, Scene *scene, SceneLayer *sl,
int type, const char *name)
{
Object *ob;
Base *base;
+ LayerCollection *lc;
ob = BKE_object_add_only_object(bmain, type, name);
ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
- ob->lay = scene->lay;
-
- base = BKE_scene_base_add(scene, ob);
- BKE_scene_base_deselect_all(scene);
- BKE_scene_base_select(scene, base);
- DAG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ lc = BKE_layer_collection_active(sl);
+ BKE_collection_object_add(scene, lc->scene_collection, ob);
+
+ base = BKE_scene_layer_base_find(sl, ob);
+ BKE_scene_layer_base_deselect_all(sl);
+ BKE_scene_layer_base_select(sl, base);
+ DAG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
return ob;
}
@@ -2542,11 +2545,11 @@ void BKE_scene_foreach_display_point(
Scene *scene, View3D *v3d, const short flag,
void (*func_cb)(const float[3], void *), void *user_data)
{
- Base *base;
+ BaseLegacy *base;
Object *ob;
for (base = FIRSTBASE; base; base = base->next) {
- if (BASE_VISIBLE_BGMODE(v3d, scene, base) && (base->flag & flag) == flag) {
+ if (BASE_VISIBLE_BGMODE(v3d, scene, base) && (base->flag_legacy & flag) == flag) {
ob = base->object;
if ((ob->transflag & OB_DUPLI) == 0) {
@@ -3351,7 +3354,7 @@ LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectS
{
LinkNode *links = NULL;
- Base *base;
+ BaseLegacy *base;
/* Remove markers from all objects */
for (base = scene->base.first; base; base = base->next) {
@@ -3395,7 +3398,7 @@ LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectS
/* child relationship */
if (includeFilter & (OB_REL_CHILDREN | OB_REL_CHILDREN_RECURSIVE)) {
- Base *local_base;
+ BaseLegacy *local_base;
for (local_base = scene->base.first; local_base; local_base = local_base->next) {
if (BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, local_base)) {
@@ -3441,18 +3444,11 @@ struct LinkNode *BKE_object_groups(Object *ob)
return group_linknode;
}
-void BKE_object_groups_clear(Scene *scene, Base *base, Object *object)
+void BKE_object_groups_clear(Object *ob)
{
Group *group = NULL;
-
- BLI_assert((base == NULL) || (base->object == object));
-
- if (scene && base == NULL) {
- base = BKE_scene_base_find(scene, object);
- }
-
- while ((group = BKE_group_object_find(group, base->object))) {
- BKE_group_object_unlink(group, object, scene, base);
+ while ((group = BKE_group_object_find(group, ob))) {
+ BKE_group_object_unlink(group, ob);
}
}
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index e3b801b3193..26af1c48afb 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -241,7 +241,7 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild
else {
unsigned int lay = ctx->scene->lay;
int baseid = 0;
- Base *base;
+ BaseLegacy *base;
for (base = ctx->scene->base.first; base; base = base->next, baseid++) {
Object *ob = base->object;
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 943dc781246..8531c7c9df9 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -2896,7 +2896,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons
ParticleSystem *psys = sim->psys;
ParticleSettings *part = psys->part;
ParticleEditSettings *pset = &sim->scene->toolsettings->particle;
- Base *base;
+ BaseLegacy *base;
int distr=0, alloc=0, skip=0;
if ((psys->part->childtype && psys->totchild != psys_get_tot_child(sim->scene, psys)) || psys->recalc&PSYS_RECALC_RESET)
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 30eb8dcb287..c3f2107c5af 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -3541,7 +3541,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
Main *bmain = baker->main;
Scene *scene = baker->scene;
Scene *sce_iter; /* SETLOOPER macro only */
- Base *base;
+ BaseLegacy *base;
ListBase pidlist;
PTCacheID *pid = &baker->pid;
PointCache *cache = NULL;
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index a1338b4ea10..d47982f96eb 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -67,6 +67,7 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_cachefile.h"
+#include "BKE_collection.h"
#include "BKE_colortools.h"
#include "BKE_depsgraph.h"
#include "BKE_editmesh.h"
@@ -78,6 +79,7 @@
#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_remap.h"
#include "BKE_linestyle.h"
@@ -154,13 +156,66 @@ static void remove_sequencer_fcurves(Scene *sce)
}
}
+/* copy SceneCollection tree but keep pointing to the same objects */
+static void scene_collection_copy(SceneCollection *scn, SceneCollection *sc)
+{
+ BLI_duplicatelist(&scn->objects, &sc->objects);
+ for (LinkData *link = scn->objects.first; link; link = link->next) {
+ id_us_plus(link->data);
+ }
+
+ BLI_duplicatelist(&scn->filter_objects, &sc->filter_objects);
+ for (LinkData *link = scn->filter_objects.first; link; link = link->next) {
+ id_us_plus(link->data);
+ }
+
+ BLI_duplicatelist(&scn->scene_collections, &sc->scene_collections);
+ SceneCollection *nscn = scn->scene_collections.first; /* nested SceneCollection new */
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ scene_collection_copy(nscn, nsc);
+ nscn = nscn->next;
+ }
+}
+
+/* Find the equivalent SceneCollection in the new tree */
+static SceneCollection *scene_collection_from_new_tree(SceneCollection *sc_reference, SceneCollection *scn, SceneCollection *sc)
+{
+ if (sc == sc_reference) {
+ return scn;
+ }
+
+ SceneCollection *nscn = scn->scene_collections.first; /* nested master collection new */
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+
+ SceneCollection *found = scene_collection_from_new_tree(sc_reference, nscn, nsc);
+ if (found) {
+ return found;
+ }
+ nscn = nscn->next;
+ }
+ return NULL;
+}
+
+/* recreate the LayerCollection tree */
+static void layer_collections_recreate(SceneLayer *sl, ListBase *lb, SceneCollection *mcn, SceneCollection *mc)
+{
+ for (LayerCollection *lc = lb->first; lc; lc = lc->next) {
+
+ SceneCollection *sc = scene_collection_from_new_tree(lc->scene_collection, mcn, mc);
+ BLI_assert(sc);
+
+ /* instead of syncronizing both trees we simply re-create it */
+ BKE_collection_link(sl, sc);
+ }
+}
+
Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
{
Scene *scen;
SceneRenderLayer *srl, *new_srl;
FreestyleLineSet *lineset;
ToolSettings *ts;
- Base *base, *obase;
+ BaseLegacy *legacy_base, *olegacy_base;
if (type == SCE_COPY_EMPTY) {
ListBase rl, rv;
@@ -214,14 +269,14 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
BKE_libblock_relink_ex(bmain, scen->nodetree, &sce->id, &scen->id, false);
}
- obase = sce->base.first;
- base = scen->base.first;
- while (base) {
- id_us_plus(&base->object->id);
- if (obase == sce->basact) scen->basact = base;
+ olegacy_base = sce->base.first;
+ legacy_base = scen->base.first;
+ while (legacy_base) {
+ id_us_plus(&legacy_base->object->id);
+ if (olegacy_base == sce->basact) scen->basact = legacy_base;
- obase = obase->next;
- base = base->next;
+ olegacy_base = olegacy_base->next;
+ legacy_base = legacy_base->next;
}
/* copy action and remove animation used by sequencer */
@@ -244,6 +299,36 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
}
new_srl = new_srl->next;
}
+
+ /* layers and collections */
+ scen->collection = MEM_dupallocN(sce->collection);
+ SceneCollection *mcn = BKE_collection_master(scen);
+ SceneCollection *mc = BKE_collection_master(sce);
+
+ /* recursively creates a new SceneCollection tree */
+ scene_collection_copy(mcn, mc);
+
+ BLI_duplicatelist(&scen->render_layers, &sce->render_layers);
+ SceneLayer *new_sl = scen->render_layers.first;
+ for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
+
+ /* we start fresh with no overrides and no visibility flags set
+ * instead of syncing both trees we simply unlink and relink the scene collection */
+ BLI_listbase_clear(&new_sl->layer_collections);
+ BLI_listbase_clear(&new_sl->object_bases);
+ layer_collections_recreate(new_sl, &sl->layer_collections, mcn, mc);
+
+ if (sl->basact) {
+ Object *active_ob = sl->basact->object;
+ for (Base *base = new_sl->object_bases.first; base; base = base->next) {
+ if (base->object == active_ob) {
+ new_sl->basact = base;
+ break;
+ }
+ }
+ }
+ new_sl = new_sl->next;
+ }
}
/* copy color management settings */
@@ -471,6 +556,16 @@ void BKE_scene_free(Scene *sce)
BKE_previewimg_free(&sce->preview);
curvemapping_free_data(&sce->r.mblur_shutter_curve);
+
+ for (SceneLayer *sl = sce->render_layers.first; sl; sl = sl->next) {
+ BKE_scene_layer_free(sl);
+ }
+ BLI_freelistN(&sce->render_layers);
+
+ /* Master Collection */
+ BKE_collection_master_free(sce);
+ MEM_freeN(sce->collection);
+ sce->collection = NULL;
}
void BKE_scene_init(Scene *sce)
@@ -820,6 +915,12 @@ void BKE_scene_init(Scene *sce)
sce->toolsettings->gpencil_v2d_align = GP_PROJECT_VIEWSPACE;
sce->toolsettings->gpencil_seq_align = GP_PROJECT_VIEWSPACE;
sce->toolsettings->gpencil_ima_align = GP_PROJECT_VIEWSPACE;
+
+ /* Master Collection */
+ sce->collection = MEM_callocN(sizeof(SceneCollection), "Master Collection");
+ BLI_strncpy(sce->collection->name, "Master Collection", sizeof(sce->collection->name));
+
+ BKE_scene_layer_add(sce, "Render Layer");
}
Scene *BKE_scene_add(Main *bmain, const char *name)
@@ -835,9 +936,9 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
return sce;
}
-Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name)
+BaseLegacy *BKE_scene_base_find_by_name(struct Scene *scene, const char *name)
{
- Base *base;
+ BaseLegacy *base;
for (base = scene->base.first; base; base = base->next) {
if (STREQ(base->object->id.name + 2, name)) {
@@ -848,9 +949,9 @@ Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name)
return base;
}
-Base *BKE_scene_base_find(Scene *scene, Object *ob)
+BaseLegacy *BKE_scene_base_find(Scene *scene, Object *ob)
{
- return BLI_findptr(&scene->base, ob, offsetof(Base, object));
+ return BLI_findptr(&scene->base, ob, offsetof(BaseLegacy, object));
}
/**
@@ -861,11 +962,10 @@ Base *BKE_scene_base_find(Scene *scene, Object *ob)
void BKE_scene_set_background(Main *bmain, Scene *scene)
{
Scene *sce;
- Base *base;
+ BaseLegacy *base;
Object *ob;
Group *group;
GroupObject *go;
- int flag;
/* check for cyclic sets, for reading old files but also for definite security (py?) */
BKE_scene_validate_setscene(bmain, scene);
@@ -897,13 +997,7 @@ void BKE_scene_set_background(Main *bmain, Scene *scene)
ob->lay = base->lay;
/* group patch... */
- base->flag &= ~(OB_FROMGROUP);
- flag = ob->flag & (OB_FROMGROUP);
- base->flag |= flag;
-
- /* not too nice... for recovering objects with lost data */
- //if (ob->pose == NULL) base->flag &= ~OB_POSEMODE;
- ob->flag = base->flag;
+ BKE_scene_base_flag_sync_from_base(base);
}
/* no full animation update, this to enable render code to work (render code calls own animation updates) */
}
@@ -924,7 +1018,7 @@ Scene *BKE_scene_set_name(Main *bmain, const char *name)
/* Used by metaballs, return *all* objects (including duplis) existing in the scene (including scene's sets) */
int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
- Scene **scene, int val, Base **base, Object **ob)
+ Scene **scene, int val, BaseLegacy **base, Object **ob)
{
bool run_again = true;
@@ -1006,7 +1100,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
}
/* handle dupli's */
if (iter->dupob) {
- (*base)->flag |= OB_FROMDUPLI;
+ (*base)->flag_legacy |= OB_FROMDUPLI;
*ob = iter->dupob->ob;
iter->phase = F_DUPLI;
@@ -1025,7 +1119,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
}
else if (iter->phase == F_DUPLI) {
iter->phase = F_SCENE;
- (*base)->flag &= ~OB_FROMDUPLI;
+ (*base)->flag_legacy &= ~OB_FROMDUPLI;
if (iter->dupli_refob) {
/* Restore last object's real matrix. */
@@ -1052,7 +1146,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
Object *BKE_scene_camera_find(Scene *sc)
{
- Base *base;
+ BaseLegacy *base;
for (base = sc->base.first; base; base = base->next)
if (base->object->type == OB_CAMERA)
@@ -1154,28 +1248,32 @@ char *BKE_scene_find_last_marker_name(Scene *scene, int frame)
return best_marker ? best_marker->name : NULL;
}
+void BKE_scene_remove_rigidbody_object(Scene *scene, Object *ob)
+{
+ /* remove rigid body constraint from world before removing object */
+ if (ob->rigidbody_constraint)
+ BKE_rigidbody_remove_constraint(scene, ob);
+ /* remove rigid body object from world before removing object */
+ if (ob->rigidbody_object)
+ BKE_rigidbody_remove_object(scene, ob);
+}
-Base *BKE_scene_base_add(Scene *sce, Object *ob)
+BaseLegacy *BKE_scene_base_add(Scene *sce, Object *ob)
{
- Base *b = MEM_callocN(sizeof(*b), __func__);
+ BaseLegacy *b = MEM_callocN(sizeof(*b), __func__);
BLI_addhead(&sce->base, b);
b->object = ob;
- b->flag = ob->flag;
+ b->flag_legacy = ob->flag;
b->lay = ob->lay;
return b;
}
-void BKE_scene_base_unlink(Scene *sce, Base *base)
+void BKE_scene_base_unlink(Scene *sce, BaseLegacy *base)
{
- /* remove rigid body constraint from world before removing object */
- if (base->object->rigidbody_constraint)
- BKE_rigidbody_remove_constraint(sce, base->object);
- /* remove rigid body object from world before removing object */
- if (base->object->rigidbody_object)
- BKE_rigidbody_remove_object(sce, base->object);
-
+ BKE_scene_remove_rigidbody_object(sce, base->object);
+
BLI_remlink(&sce->base, base);
if (sce->basact == base)
sce->basact = NULL;
@@ -1183,18 +1281,20 @@ void BKE_scene_base_unlink(Scene *sce, Base *base)
void BKE_scene_base_deselect_all(Scene *sce)
{
- Base *b;
+ BaseLegacy *b;
for (b = sce->base.first; b; b = b->next) {
- b->flag &= ~SELECT;
- b->object->flag = b->flag;
+ b->flag_legacy &= ~SELECT;
+ int flag = b->object->flag & (OB_FROMGROUP);
+ b->object->flag = b->flag_legacy;
+ b->object->flag |= flag;
}
}
-void BKE_scene_base_select(Scene *sce, Base *selbase)
+void BKE_scene_base_select(Scene *sce, BaseLegacy *selbase)
{
- selbase->flag |= SELECT;
- selbase->object->flag = selbase->flag;
+ selbase->flag_legacy |= SELECT;
+ selbase->object->flag = selbase->flag_legacy;
sce->basact = selbase;
}
@@ -1492,15 +1592,7 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer *
for (sce = bmain->scene.first; sce; sce = sce->id.next) {
if (sce->nodetree) {
- bNode *node;
- for (node = sce->nodetree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_R_LAYERS && (Scene *)node->id == scene) {
- if (node->custom1 == act)
- node->custom1 = 0;
- else if (node->custom1 > act)
- node->custom1--;
- }
- }
+ BKE_nodetree_remove_layer_n(sce->nodetree, scene, act);
}
}
@@ -1588,7 +1680,7 @@ float get_render_aosss_error(const RenderData *r, float error)
}
/* helper function for the SETLOOPER macro */
-Base *_setlooper_base_step(Scene **sce_iter, Base *base)
+BaseLegacy *_setlooper_base_step(Scene **sce_iter, BaseLegacy *base)
{
if (base && base->next) {
/* common case, step to the next */
@@ -1596,12 +1688,12 @@ Base *_setlooper_base_step(Scene **sce_iter, Base *base)
}
else if (base == NULL && (*sce_iter)->base.first) {
/* first time looping, return the scenes first base */
- return (Base *)(*sce_iter)->base.first;
+ return (BaseLegacy *)(*sce_iter)->base.first;
}
else {
/* reached the end, get the next base in the set */
while ((*sce_iter = (*sce_iter)->set)) {
- base = (Base *)(*sce_iter)->base.first;
+ base = (BaseLegacy *)(*sce_iter)->base.first;
if (base) {
return base;
}
@@ -1648,24 +1740,56 @@ bool BKE_scene_uses_blender_game(const Scene *scene)
void BKE_scene_base_flag_to_objects(struct Scene *scene)
{
- Base *base = scene->base.first;
+ BaseLegacy *base = scene->base.first;
while (base) {
- base->object->flag = base->flag;
+ BKE_scene_base_flag_sync_from_base(base);
base = base->next;
}
}
void BKE_scene_base_flag_from_objects(struct Scene *scene)
{
- Base *base = scene->base.first;
+ BaseLegacy *base = scene->base.first;
while (base) {
- base->flag = base->object->flag;
+ BKE_scene_base_flag_sync_from_object(base);
base = base->next;
}
}
+void BKE_scene_base_flag_sync_from_base(BaseLegacy *base)
+{
+ Object *ob = base->object;
+
+ /* keep the object only flags untouched */
+ int flag = ob->flag & OB_FROMGROUP;
+
+ ob->flag = base->flag_legacy;
+ ob->flag |= flag;
+}
+
+void BKE_scene_base_flag_sync_from_object(BaseLegacy *base)
+{
+ base->flag_legacy = base->object->flag;
+}
+
+void BKE_scene_object_base_flag_sync_from_base(Base *base)
+{
+ Object *ob = base->object;
+
+ /* keep the object only flags untouched */
+ int flag = ob->flag & OB_FROMGROUP;
+
+ ob->flag = base->flag;
+ ob->flag |= flag;
+}
+
+void BKE_scene_object_base_flag_sync_from_object(Base *base)
+{
+ base->flag = base->object->flag;
+}
+
void BKE_scene_disable_color_management(Scene *scene)
{
ColorManagedDisplaySettings *display_settings = &scene->display_settings;
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index d0ef5cfc092..f1ce69d3945 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -698,7 +698,7 @@ static float calc_voxel_transp(float *result, float *input, int res[3], int *pix
static int get_lamp(Scene *scene, float *light)
{
- Base *base_tmp = NULL;
+ BaseLegacy *base_tmp = NULL;
int found_lamp = 0;
// try to find a lamp, preferably local
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 660107eb2e6..e7df1d810c9 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -530,7 +530,7 @@ static void ccd_build_deflector_hash(Scene *scene, Group *group, Object *vertexo
}
}
else {
- for (Base *base = scene->base.first; base; base = base->next) {
+ for (BaseLegacy *base = scene->base.first; base; base = base->next) {
/*Only proceed for mesh object in same layer */
if (base->object->type == OB_MESH && (base->lay & vertexowner->lay)) {
ob= base->object;
@@ -576,7 +576,7 @@ static void ccd_update_deflector_hash(Scene *scene, Group *group, Object *vertex
}
}
else {
- for (Base *base = scene->base.first; base; base = base->next) {
+ for (BaseLegacy *base = scene->base.first; base; base = base->next) {
/*Only proceed for mesh object in same layer */
if (base->object->type == OB_MESH && (base->lay & vertexowner->lay)) {
ob= base->object;
@@ -986,7 +986,7 @@ static bool are_there_deflectors(Scene *scene, Group *group, unsigned int layer)
}
}
else {
- for (Base *base = scene->base.first; base; base= base->next) {
+ for (BaseLegacy *base = scene->base.first; base; base= base->next) {
if ( (base->lay & layer) && base->object->pd) {
if (base->object->pd->deflect)
return 1;
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index 22288127119..e10f9207896 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -782,7 +782,7 @@ void BKE_sound_read_waveform(bSound *sound, short *stop)
void BKE_sound_update_scene(Main *bmain, struct Scene *scene)
{
Object *ob;
- Base *base;
+ BaseLegacy *base;
NlaTrack *track;
NlaStrip *strip;
Speaker *speaker;