diff options
author | Dalai Felinto <dfelinto@gmail.com> | 2016-12-10 19:54:35 +0300 |
---|---|---|
committer | Dalai Felinto <dfelinto@gmail.com> | 2016-12-12 14:12:42 +0300 |
commit | c96c3c8bbe51a7dd26addcdeac9d0bb2e992cca1 (patch) | |
tree | ab57375b818795e66019cec09f0eb68de2b0975e /source | |
parent | ef6a35b0afa256b9ed5b293f684a29909c44fe9c (diff) |
Scene copy (full or link) working for layers
I'm using the flags in the objects instead of bases.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_collection.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_context.h | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_layer.h | 9 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/collection.c | 19 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/context.c | 28 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/layer.c | 15 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 83 | ||||
-rw-r--r-- | source/blender/editors/object/object_relations.c | 139 |
8 files changed, 247 insertions, 50 deletions
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h index a839824d229..fc2cf1c268d 100644 --- a/source/blender/blenkernel/BKE_collection.h +++ b/source/blender/blenkernel/BKE_collection.h @@ -41,6 +41,7 @@ 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_remove(struct Scene *scene, struct SceneCollection *sc, struct Object *object); +void BKE_collection_objects_callback(struct SceneCollection *sc, void (*callback)(struct Object *_ob, void *_data), void *data); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index c6795f87eab..d22941cac6a 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -46,6 +46,7 @@ struct Object; struct PointerRNA; struct ReportList; struct Scene; +struct SceneLayer; struct ScrArea; struct SpaceLink; struct View3D; @@ -238,6 +239,7 @@ 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 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); @@ -245,6 +247,7 @@ int CTX_data_mode_enum(const bContext *C); void CTX_data_main_set(bContext *C, struct Main *bmain); void CTX_data_scene_set(bContext *C, struct Scene *bmain); +void CTX_data_scene_layer_set(bContext *C, struct SceneLayer *sl); int CTX_data_selected_editable_objects(const bContext *C, ListBase *list); int CTX_data_selected_editable_bases(const bContext *C, ListBase *list); diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h index 26df4ef466b..acfad811693 100644 --- a/source/blender/blenkernel/BKE_layer.h +++ b/source/blender/blenkernel/BKE_layer.h @@ -31,8 +31,11 @@ extern "C" { #endif -#define TODO_LAYER_SYNC -#define TODO_LAYER_OVERRIDE +#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 /* generic todo */ struct LayerCollection; struct ID; @@ -51,6 +54,8 @@ 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 ObjectBase *BKE_scene_layer_base_find(struct SceneLayer *sl, struct Object *ob); void BKE_layer_collection_free(struct SceneLayer *sl, struct LayerCollection *lc); diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index ed9aef21dd6..a3112097141 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -34,6 +34,7 @@ #include "DNA_ID.h" #include "DNA_layer_types.h" +#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "MEM_guardedalloc.h" @@ -196,3 +197,21 @@ void BKE_collection_object_remove(struct Scene *UNUSED(scene), struct SceneColle /* remove the equivalent object base to all layers that have this collection * also remove all reference to ob in the filter_objects */ } + +/* + * Recursively calls the callback function for the objects in a SceneCollection + */ +void BKE_collection_objects_callback(SceneCollection *sc, void (*callback)(struct Object *_ob, void *_data), void *data) +{ + for (LinkData *link= sc->objects.first; link; link = link->next) { + callback(link->data, data); + } + + for (LinkData *link= sc->filter_objects.first; link; link = link->next) { + callback(link->data, data); + } + + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + BKE_collection_objects_callback(nsc, callback, data); + } +} diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index b38f59a3723..c9454f84690 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" @@ -78,6 +79,7 @@ struct bContext { struct { struct Main *main; struct Scene *scene; + struct SceneLayer *render_layer; int recursion; int py_init; /* true if python is initialized */ @@ -836,8 +838,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 +899,16 @@ 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 + return C->data.render_layer; +} + int CTX_data_mode_enum(const bContext *C) { Object *obedit = CTX_data_edit_object(C); @@ -960,6 +973,17 @@ const char *CTX_data_mode_string(const bContext *C) void CTX_data_scene_set(bContext *C, Scene *scene) { C->data.scene = scene; + TODO_LAYER_CONTEXT + + /* render_layer comes from workspace (or even viewport) actually + * this is only while we wait for workspace changes to be merged + */ + CTX_data_scene_layer_set(C, scene->render_layers.last); +} + +void CTX_data_scene_layer_set(bContext *C, SceneLayer *sl) +{ + C->data.render_layer = sl; } ToolSettings *CTX_data_tool_settings(const bContext *C) diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index b34f6dac13c..a1d1e9649cd 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -127,6 +127,21 @@ 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 (ObjectBase *ob_base = sl->object_bases.first; ob_base; ob_base = ob_base->next) { + if ((ob_base->flag & BASE_SELECTED) != 0) { + ob_base->object->flag |= tag; + } + else { + ob_base->object->flag &= ~tag; + } + } +} + /* ObjectBase */ ObjectBase *BKE_scene_layer_base_find(SceneLayer *sl, Object *ob) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 88c386abb80..200041747c5 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -154,6 +154,59 @@ 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; @@ -246,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 (ObjectBase *ob_base = new_sl->object_bases.first; ob_base; ob_base = ob_base->next) { + if (ob_base->object == active_ob) { + new_sl->basact = ob_base; + break; + } + } + } + new_sl = new_sl->next; + } } /* copy color management settings */ diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index a3ff8dcb676..18884881a04 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -62,6 +62,7 @@ #include "BKE_animsys.h" #include "BKE_armature.h" #include "BKE_camera.h" +#include "BKE_collection.h" #include "BKE_context.h" #include "BKE_constraint.h" #include "BKE_curve.h" @@ -73,6 +74,7 @@ #include "BKE_fcurve.h" #include "BKE_lamp.h" #include "BKE_lattice.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_main.h" @@ -1730,10 +1732,68 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot) /**************************** Make Single User ********************************/ +static Object *single_object_users_object(Main *bmain, Scene *scene, Object *ob, const bool copy_groups) +{ + if (!ID_IS_LINKED_DATABLOCK(ob) && ob->id.us > 1) { + /* base gets copy of object */ + Object *obn = BKE_object_copy(bmain, ob); + + if (copy_groups) { + if (ob->flag & OB_FROMGROUP) { + obn->flag |= OB_FROMGROUP; + } + } + else { + /* copy already clears */ + } + /* remap gpencil parenting */ + + if (scene->gpd) { + bGPdata *gpd = scene->gpd; + for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { + if (gpl->parent == ob) { + gpl->parent = obn; + } + } + } + + id_us_min(&ob->id); + return obn; + } + return NULL; +} + +static void libblock_relink_scene_collection(SceneCollection *sc) +{ + for (LinkData *link = sc->objects.first; link; link = link->next) { + BKE_libblock_relink(link->data); + } + + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + libblock_relink_scene_collection(nsc); + } +} + +static void single_object_users_scene_collection(Main *bmain, Scene *scene, SceneCollection *sc, const int flag, const bool copy_groups) +{ + for (LinkData *link = sc->objects.first; link; link = link->next) { + Object *ob = link->data; + /* an object may be in more than one collection */ + if ((ob->id.newid == NULL) && ((ob->flag & flag) == flag)) { + link->data = single_object_users_object(bmain, scene, link->data, copy_groups); + } + } + + /* we reset filter objects because they should be regenerated after this */ + BLI_freelistN(&sc->filter_objects); + + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + single_object_users_scene_collection(bmain, scene, nsc, flag, copy_groups); + } +} + static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const int flag, const bool copy_groups) { - Base *base; - Object *ob, *obn; Group *group, *groupn; GroupObject *go; @@ -1750,39 +1810,14 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in } } - /* duplicate (must set newid) */ - for (base = FIRSTBASE; base; base = base->next) { - ob = base->object; - - if ((base->flag & flag) == flag) { - if (!ID_IS_LINKED_DATABLOCK(ob) && ob->id.us > 1) { - /* base gets copy of object */ - obn = BKE_object_copy(bmain, ob); - base->object = obn; - - if (copy_groups) { - if (ob->flag & OB_FROMGROUP) { - obn->flag |= OB_FROMGROUP; - } - } - else { - /* copy already clears */ - } - /* remap gpencil parenting */ + /* duplicate all the objects of the scene */ + SceneCollection *msc = BKE_collection_master(scene); + single_object_users_scene_collection(bmain, scene, msc, flag, copy_groups); - if (scene->gpd) { - bGPdata *gpd = scene->gpd; - for (bGPDlayer *gpl = gpd->layers.first; gpl; gpl = gpl->next) { - if (gpl->parent == ob) { - gpl->parent = obn; - } - } - } - - base->flag = obn->flag; - - id_us_min(&ob->id); - } + /* loop over SceneLayers and assign the pointers accordingly */ + for (SceneLayer *sl = scene->render_layers.first; sl; sl = sl->next) { + for (ObjectBase *ob_base = sl->object_bases.first; ob_base; ob_base = ob_base->next) { + ID_NEW(ob_base->object); } } @@ -1816,26 +1851,28 @@ static void single_object_users(Main *bmain, Scene *scene, View3D *v3d, const in if (v3d) ID_NEW(v3d->camera); /* object and group pointers */ - for (base = FIRSTBASE; base; base = base->next) { - BKE_libblock_relink(&base->object->id); - } + libblock_relink_scene_collection(msc); set_sca_new_poins(); + + /* TODO redo filter */ + TODO_LAYER_SYNC_FILTER +} + +static void object_untag_OB_DONE(Object *ob, void *UNUSED(data)) +{ + ob->flag &= ~OB_DONE; } /* not an especially efficient function, only added so the single user * button can be functional.*/ void ED_object_single_user(Main *bmain, Scene *scene, Object *ob) { - Base *base; - const bool copy_groups = false; - - for (base = FIRSTBASE; base; base = base->next) { - if (base->object == ob) base->flag |= OB_DONE; - else base->flag &= ~OB_DONE; - } + SceneCollection *msc = BKE_collection_master(scene); + BKE_collection_objects_callback(msc, object_untag_OB_DONE, NULL); - single_object_users(bmain, scene, NULL, OB_DONE, copy_groups); + ob->flag |= OB_DONE; + single_object_users(bmain, scene, NULL, OB_DONE, false); } static void new_id_matar(Main *bmain, Material **matar, const int totcol) @@ -1872,6 +1909,8 @@ static void single_obdata_users(Main *bmain, Scene *scene, const int flag) ID *id; int a; + TODO_LAYER; /* need to use scene->collection base instead of scene->bases */ + for (base = FIRSTBASE; base; base = base->next) { ob = base->object; if (!ID_IS_LINKED_DATABLOCK(ob) && (base->flag & flag) == flag) { @@ -2379,7 +2418,15 @@ static int make_single_user_exec(bContext *C, wmOperator *op) BKE_main_id_clear_newpoins(bmain); if (RNA_boolean_get(op->ptr, "object")) { - single_object_users(bmain, scene, v3d, flag, copy_groups); + if (flag == SELECT) { + SceneLayer *sl = CTX_data_scene_layer(C); + + BKE_scene_layer_selected_objects_tag(sl, OB_DONE); + single_object_users(bmain, scene, v3d, OB_DONE, copy_groups); + } + else { + single_object_users(bmain, scene, v3d, 0, copy_groups); + } /* needed since object relationships may have changed */ update_deps = true; |