diff options
-rw-r--r-- | release/scripts/startup/bl_ui/space_outliner.py | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_collection.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_layer.h | 7 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/collection.c | 55 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/layer.c | 164 | ||||
-rw-r--r-- | source/blender/editors/space_outliner/outliner_collections.c | 80 | ||||
-rw-r--r-- | source/blender/editors/space_outliner/outliner_intern.h | 1 | ||||
-rw-r--r-- | source/blender/editors/space_outliner/outliner_ops.c | 1 | ||||
-rw-r--r-- | source/blender/editors/space_outliner/outliner_tools.c | 7 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_layer.c | 46 |
10 files changed, 346 insertions, 17 deletions
diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py index 28644428cf8..122fe84763d 100644 --- a/release/scripts/startup/bl_ui/space_outliner.py +++ b/release/scripts/startup/bl_ui/space_outliner.py @@ -195,6 +195,7 @@ class OUTLINER_MT_context_scene_collection(Menu): layout = self.layout layout.operator("outliner.collection_nested_new", text="New Collection", icon='NEW') + layout.operator("outliner.collection_duplicate", text="Duplicate Collection") layout.operator("outliner.collection_delete_selected", text="Delete Collections", icon='X') layout.separator() layout.operator("outliner.collection_objects_add", text="Add Selected", icon='ZOOMIN') diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h index 48b4ff881ae..618e60550b7 100644 --- a/source/blender/blenkernel/BKE_collection.h +++ b/source/blender/blenkernel/BKE_collection.h @@ -49,6 +49,7 @@ struct SceneCollection *BKE_collection_add( struct ID *owner_id, struct SceneCollection *sc_parent, const int type, const char *name); bool BKE_collection_remove(struct ID *owner_id, struct SceneCollection *sc); void BKE_collection_copy_data(struct SceneCollection *sc_dst, struct SceneCollection *sc_src, const int flag); +struct SceneCollection *BKE_collection_duplicate(struct ID *owner_id, struct SceneCollection *scene_collection); struct SceneCollection *BKE_collection_master(const struct ID *owner_id); void BKE_collection_rename(const struct Scene *scene, struct SceneCollection *sc, const char *name); void BKE_collection_master_free(struct ID *owner_id, const bool do_id_user); diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h index f098a7e7468..633cb2c6044 100644 --- a/source/blender/blenkernel/BKE_layer.h +++ b/source/blender/blenkernel/BKE_layer.h @@ -78,11 +78,18 @@ struct Base *BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Objec void BKE_view_layer_base_deselect_all(struct ViewLayer *view_layer); void BKE_view_layer_base_select(struct ViewLayer *view_layer, struct Base *selbase); +void BKE_layer_collection_sync_flags( + struct ID *owner_id, + struct SceneCollection *scene_collection_dst, + struct SceneCollection *scene_collection_src); + void BKE_view_layer_copy_data( struct ViewLayer *view_layer_dst, struct ViewLayer *view_layer_src, struct SceneCollection *mc_dst, struct SceneCollection *mc_src, const int flag); +struct LayerCollection *BKE_layer_collection_duplicate(struct ID *owner_id, struct LayerCollection *layer_collection); + void BKE_layer_collection_free(struct ViewLayer *view_layer, struct LayerCollection *lc); struct LayerCollection *BKE_layer_collection_get_active(struct ViewLayer *view_layer); diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index ca77969ccaa..729be02bfc7 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -68,10 +68,9 @@ static SceneCollection *collection_master_from_id(const ID *owner_id) } /** - * 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 + * Add a new collection, but don't handle syncing with layer collections */ -SceneCollection *BKE_collection_add(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name_custom) +static SceneCollection *collection_add(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name_custom) { SceneCollection *sc_master = collection_master_from_id(owner_id); SceneCollection *sc = MEM_callocN(sizeof(SceneCollection), "New Collection"); @@ -99,8 +98,6 @@ SceneCollection *BKE_collection_add(ID *owner_id, SceneCollection *sc_parent, co BLI_addtail(&sc_parent->scene_collections, sc); BKE_collection_rename((Scene *)owner_id, sc, name); - BKE_layer_sync_new_scene_collection(owner_id, sc_parent, sc); - if (name != name_custom) { MEM_freeN((char *)name); } @@ -109,6 +106,17 @@ SceneCollection *BKE_collection_add(ID *owner_id, SceneCollection *sc_parent, co } /** + * 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(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name_custom) +{ + SceneCollection *scene_collection = collection_add(owner_id, sc_parent, type, name_custom); + BKE_layer_sync_new_scene_collection(owner_id, sc_parent, scene_collection); + return scene_collection; +} + +/** * Free the collection items recursively */ static void collection_free(SceneCollection *sc, const bool do_id_user) @@ -270,6 +278,43 @@ void BKE_collection_copy_data(SceneCollection *sc_dst, SceneCollection *sc_src, } } +/** + * Makes a shallow copy of a SceneCollection + * + * Add a new collection in the same level as the old one, copy any nested collections + * but link the objects to the new collection (as oppose to copy them). + */ +SceneCollection *BKE_collection_duplicate(ID *owner_id, SceneCollection *scene_collection) +{ + SceneCollection *scene_collection_master = BKE_collection_master(owner_id); + SceneCollection *scene_collection_parent = find_collection_parent(scene_collection, scene_collection_master); + + /* It's not allowed to copy the master collection. */ + if (scene_collection_master == scene_collection) { + return NULL; + } + + SceneCollection *scene_collection_new = collection_add( + owner_id, + scene_collection_parent, + scene_collection->type, + scene_collection->name); + + if (scene_collection_new != scene_collection->next) { + BLI_remlink(&scene_collection_parent->scene_collections, scene_collection_new); + BLI_insertlinkafter(&scene_collection_parent->scene_collections, scene_collection, scene_collection_new); + } + + BKE_collection_copy_data(scene_collection_new, scene_collection, 0); + BKE_layer_sync_new_scene_collection(owner_id, scene_collection_parent, scene_collection_new); + + /* Make sure every linked instance of the new collection has the same values (flags, overrides, ...) as the + * corresponding original collection. */ + BKE_layer_collection_sync_flags(owner_id, scene_collection_new, scene_collection); + + return scene_collection_new; +} + static SceneCollection *master_collection_from_id(const ID *owner_id) { switch (GS(owner_id->name)) { diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c index 4333faea863..9807c6e4f10 100644 --- a/source/blender/blenkernel/intern/layer.c +++ b/source/blender/blenkernel/intern/layer.c @@ -61,6 +61,7 @@ /* prototype */ struct EngineSettingsCB_Type; +static void layer_collections_sync_flags(ListBase *layer_collections_dst, const ListBase *layer_collections_src); static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc); static void layer_collection_objects_populate(ViewLayer *view_layer, LayerCollection *lc, ListBase *objects); static LayerCollection *layer_collection_add(ViewLayer *view_layer, LayerCollection *parent, SceneCollection *sc); @@ -353,27 +354,94 @@ static SceneCollection *scene_collection_from_new_tree( return NULL; } +static void layer_collection_sync_flags( + LayerCollection *layer_collection_dst, + const LayerCollection *layer_collection_src) +{ + layer_collection_dst->flag = layer_collection_src->flag; + + if (layer_collection_dst->properties != NULL) { + IDP_FreeProperty(layer_collection_dst->properties); + MEM_SAFE_FREE(layer_collection_dst->properties); + } + + if (layer_collection_src->properties != NULL) { + layer_collection_dst->properties = IDP_CopyProperty(layer_collection_src->properties); + } + + layer_collections_sync_flags(&layer_collection_dst->layer_collections, + &layer_collection_src->layer_collections); +} + static void layer_collections_sync_flags(ListBase *layer_collections_dst, const ListBase *layer_collections_src) { LayerCollection *layer_collection_dst = (LayerCollection *)layer_collections_dst->first; const LayerCollection *layer_collection_src = (const LayerCollection *)layer_collections_src->first; while (layer_collection_dst != NULL) { - layer_collection_dst->flag = layer_collection_src->flag; + layer_collection_sync_flags(layer_collection_dst, layer_collection_src); + layer_collection_dst = layer_collection_dst->next; + layer_collection_src = layer_collection_src->next; + } +} - if (layer_collection_dst->properties != NULL) { - IDP_FreeProperty(layer_collection_dst->properties); - MEM_SAFE_FREE(layer_collection_dst->properties); +static bool layer_collection_sync_if_match( + ListBase *lb, + const SceneCollection *scene_collection_dst, + const SceneCollection *scene_collection_src) +{ + for (LayerCollection *layer_collection = lb->first; + layer_collection; + layer_collection = layer_collection->next) + { + if (layer_collection->scene_collection == scene_collection_src) { + LayerCollection *layer_collection_dst = + BLI_findptr( + lb, + scene_collection_dst, + offsetof(LayerCollection, scene_collection)); + + if (layer_collection_dst != NULL) { + layer_collection_sync_flags(layer_collection_dst, layer_collection); + } + return true; } - - if (layer_collection_src->properties != NULL) { - layer_collection_dst->properties = IDP_CopyProperty(layer_collection_src->properties); + else { + if (layer_collection_sync_if_match( + &layer_collection->layer_collections, + scene_collection_dst, + scene_collection_src)) + { + return true; + } } + } + return false; +} - layer_collections_sync_flags(&layer_collection_dst->layer_collections, - &layer_collection_src->layer_collections); - - layer_collection_dst = layer_collection_dst->next; - layer_collection_src = layer_collection_src->next; +/** + * Sync sibling collections across all view layers + * + * Make sure every linked instance of \a scene_collection_dst has the same values + * (flags, overrides, ...) as the corresponding scene_collection_src. + * + * \note expect scene_collection_dst to be scene_collection_src->next, and it also + * expects both collections to have the same ammount of sub-collections. + */ +void BKE_layer_collection_sync_flags( + ID *owner_id, + SceneCollection *scene_collection_dst, + SceneCollection *scene_collection_src) +{ + for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { + for (LayerCollection *layer_collection = view_layer->layer_collections.first; + layer_collection; + layer_collection = layer_collection->next) + { + layer_collection_sync_if_match( + &layer_collection->layer_collections, + scene_collection_dst, + scene_collection_src); + } } } @@ -438,6 +506,78 @@ void BKE_view_layer_copy_data( } } +/** + * Find and return the ListBase of LayerCollection that has \a lc_child as one of its directly + * nested LayerCollection. + * + * \param lb_parent Initial ListBase of LayerCollection to look into recursively + * usually the view layer's collection list + */ +static ListBase *find_layer_collection_parent_list_base(ListBase *lb_parent, const LayerCollection *lc_child) +{ + for (LayerCollection *lc_nested = lb_parent->first; lc_nested; lc_nested = lc_nested->next) { + if (lc_nested == lc_child) { + return lb_parent; + } + + ListBase *found = find_layer_collection_parent_list_base(&lc_nested->layer_collections, lc_child); + if (found != NULL) { + return found; + } + } + + return NULL; +} + +/** + * Makes a shallow copy of a LayerCollection + * + * Add a new collection in the same level as the old one (linking if necessary), + * and copy all the collection data across them. + */ +struct LayerCollection *BKE_layer_collection_duplicate(struct ID *owner_id, struct LayerCollection *layer_collection) +{ + SceneCollection *scene_collection, *scene_collection_new; + + scene_collection = layer_collection->scene_collection; + scene_collection_new = BKE_collection_duplicate(owner_id, scene_collection); + + LayerCollection *layer_collection_new = NULL; + + /* If the original layer_collection was directly linked to the view layer + we need to link the new scene collection here as well. */ + for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { + if (BLI_findindex(&view_layer->layer_collections, layer_collection) != -1) { + layer_collection_new = BKE_collection_link(view_layer, scene_collection_new); + layer_collection_sync_flags(layer_collection_new, layer_collection); + + if (layer_collection_new != layer_collection->next) { + BLI_remlink(&view_layer->layer_collections, layer_collection_new); + BLI_insertlinkafter(&view_layer->layer_collections, layer_collection, layer_collection_new); + } + break; + } + } + + /* Otherwise just try to find the corresponding layer collection to return it back. */ + if (layer_collection_new == NULL) { + for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { + ListBase *layer_collections_parent; + layer_collections_parent = find_layer_collection_parent_list_base( + &view_layer->layer_collections, + layer_collection); + if (layer_collections_parent != NULL) { + layer_collection_new = BLI_findptr( + layer_collections_parent, + scene_collection_new, + offsetof(LayerCollection, scene_collection)); + break; + } + } + } + return layer_collection_new; +} + static void view_layer_object_base_unref(ViewLayer *view_layer, Base *base) { base->refcount--; diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c index 394a7a80b39..89f1240f86d 100644 --- a/source/blender/editors/space_outliner/outliner_collections.c +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -91,6 +91,12 @@ static int view_layer_editor_poll(bContext *C) return (so != NULL) && (so->outlinevis == SO_VIEW_LAYER); } +static int outliner_either_collection_editor_poll(bContext *C) +{ + SpaceOops *so = CTX_wm_space_outliner(C); + return (so != NULL) && (ELEM(so->outlinevis, SO_VIEW_LAYER, SO_COLLECTIONS)); +} + /* -------------------------------------------------------------------- */ /* collection manager operators */ @@ -819,3 +825,77 @@ void OUTLINER_OT_collection_objects_select(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } + +struct CollectionDuplicateData { + TreeElement *te; +}; + +static TreeTraversalAction outliner_find_first_selected_collection(TreeElement *te, void *customdata) +{ + struct CollectionDuplicateData *data = customdata; + TreeStoreElem *tselem = TREESTORE(te); + + switch (tselem->type) { + case TSE_LAYER_COLLECTION: + case TSE_SCENE_COLLECTION: + data->te = te; + return TRAVERSE_BREAK; + case TSE_LAYER_COLLECTION_BASE: + default: + return TRAVERSE_CONTINUE; + } +} + +static TreeElement *outliner_active_collection(bContext *C) +{ + SpaceOops *soops = CTX_wm_space_outliner(C); + + struct CollectionDuplicateData data = { + .te = NULL, + }; + + outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, outliner_find_first_selected_collection, &data); + return data.te; +} + +static int collection_duplicate_exec(bContext *C, wmOperator *op) +{ + SpaceOops *soops = CTX_wm_space_outliner(C); + TreeElement *te = outliner_active_collection(C); + + BLI_assert(te != NULL); + if (BKE_collection_master(TREESTORE(te)->id) == outliner_scene_collection_from_tree_element(te)) { + BKE_report(op->reports, RPT_ERROR, "You can't duplicate the master collection"); + return OPERATOR_CANCELLED; + } + + switch (soops->outlinevis) { + case SO_COLLECTIONS: + BKE_collection_duplicate(TREESTORE(te)->id, (SceneCollection *)te->directdata); + break; + case SO_VIEW_LAYER: + case SO_GROUPS: + BKE_layer_collection_duplicate(TREESTORE(te)->id, (LayerCollection *)te->directdata); + break; + } + + DEG_relations_tag_update(CTX_data_main(C)); + WM_main_add_notifier(NC_SCENE | ND_LAYER, CTX_data_scene(C)); + + return OPERATOR_FINISHED; +} + +void OUTLINER_OT_collection_duplicate(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Duplicate Collection"; + ot->idname = "OUTLINER_OT_collection_duplicate"; + ot->description = "Duplicate collection"; + + /* api callbacks */ + ot->exec = collection_duplicate_exec; + ot->poll = outliner_either_collection_editor_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 06d06d66326..ab10e5a3036 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -344,6 +344,7 @@ void OUTLINER_OT_collection_toggle(struct wmOperatorType *ot); void OUTLINER_OT_collection_link(struct wmOperatorType *ot); void OUTLINER_OT_collection_unlink(struct wmOperatorType *ot); void OUTLINER_OT_collection_new(struct wmOperatorType *ot); +void OUTLINER_OT_collection_duplicate(struct wmOperatorType *ot); void OUTLINER_OT_collection_objects_remove(struct wmOperatorType *ot); void OUTLINER_OT_collection_objects_select(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index b5b4fbbf039..eb42fe47cbf 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -474,6 +474,7 @@ void outliner_operatortypes(void) WM_operatortype_append(OUTLINER_OT_collection_link); WM_operatortype_append(OUTLINER_OT_collection_unlink); WM_operatortype_append(OUTLINER_OT_collection_new); + WM_operatortype_append(OUTLINER_OT_collection_duplicate); WM_operatortype_append(OUTLINER_OT_collection_nested_new); WM_operatortype_append(OUTLINER_OT_collection_delete_selected); diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index c4d032e34ee..3ee0d011bbb 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -677,6 +677,7 @@ typedef enum eOutliner_PropCollectionOps { OL_COLLECTION_OP_OBJECTS_REMOVE, OL_COLLECTION_OP_OBJECTS_SELECT, OL_COLLECTION_OP_COLLECTION_NEW, + OL_COLLECTION_OP_COLLECTION_COPY, OL_COLLECTION_OP_COLLECTION_DEL, OL_COLLECTION_OP_COLLECTION_UNLINK, OL_COLLECTION_OP_GROUP_CREATE, @@ -875,6 +876,11 @@ static void collection_cb(int event, TreeElement *te, TreeStoreElem *UNUSED(tsel } WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); } + else if (event == OL_COLLECTION_OP_COLLECTION_COPY) { + BKE_layer_collection_duplicate(id, lc); + DEG_relations_tag_update(CTX_data_main(C)); + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, scene); + } else if (event == OL_COLLECTION_OP_COLLECTION_UNLINK) { ViewLayer *view_layer = CTX_data_view_layer(C); @@ -1851,6 +1857,7 @@ static EnumPropertyItem prop_collection_op_types[] = { {OL_COLLECTION_OP_OBJECTS_REMOVE, "OBJECTS_REMOVE", ICON_X, "Remove Selected", "Remove selected objects from collection"}, {OL_COLLECTION_OP_OBJECTS_SELECT, "OBJECTS_SELECT", ICON_RESTRICT_SELECT_OFF, "Select Objects", "Selected collection objects"}, {OL_COLLECTION_OP_COLLECTION_NEW, "COLLECTION_NEW", ICON_NEW, "New Collection", "Add a new nested collection"}, + {OL_COLLECTION_OP_COLLECTION_COPY, "COLLECTION_DUPLI", ICON_NONE, "Duplicate Collection", "Duplicate the collection"}, {OL_COLLECTION_OP_COLLECTION_UNLINK, "COLLECTION_UNLINK", ICON_UNLINKED, "Unlink", "Unlink collection"}, {OL_COLLECTION_OP_COLLECTION_DEL, "COLLECTION_DEL", ICON_X, "Delete Collection", "Delete the collection"}, {OL_COLLECTION_OP_GROUP_CREATE, "GROUP_CREATE", ICON_GROUP, "Create Group", "Turn the collection into a group collection"}, diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c index 68c4a15e06b..6930aa115c7 100644 --- a/source/blender/makesrna/intern/rna_layer.c +++ b/source/blender/makesrna/intern/rna_layer.c @@ -141,6 +141,23 @@ static int rna_SceneCollection_move_into(ID *id, SceneCollection *sc_src, Main * return 1; } +static SceneCollection *rna_SceneCollection_duplicate( + ID *id, SceneCollection *scene_collection, Main *bmain, bContext *C, ReportList *reports) +{ + if (scene_collection == BKE_collection_master(id)) { + BKE_report(reports, RPT_ERROR, "The master collection can't be duplicated"); + return NULL; + } + + SceneCollection *scene_collection_new = BKE_collection_duplicate(id, scene_collection); + + DEG_relations_tag_update(bmain); + /* Don't use id here, since the layer collection may come from a group. */ + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, CTX_data_scene(C)); + + return scene_collection_new; +} + static SceneCollection *rna_SceneCollection_new( ID *id, SceneCollection *sc_parent, Main *bmain, const char *name) { @@ -717,6 +734,23 @@ static Group *rna_LayerCollection_create_group( return group; } +static LayerCollection *rna_LayerCollection_duplicate( + ID *id, LayerCollection *layer_collection, Main *bmain, bContext *C, ReportList *reports) +{ + if (layer_collection->scene_collection == BKE_collection_master(id)) { + BKE_report(reports, RPT_ERROR, "The master collection can't be duplicated"); + return NULL; + } + + LayerCollection *layer_collection_new = BKE_layer_collection_duplicate(id, layer_collection); + + DEG_relations_tag_update(bmain); + /* Don't use id here, since the layer collection may come from a group. */ + WM_event_add_notifier(C, NC_SCENE | ND_LAYER, CTX_data_scene(C)); + + return layer_collection_new; +} + static int rna_LayerCollections_active_collection_index_get(PointerRNA *ptr) { ViewLayer *view_layer = (ViewLayer *)ptr->data; @@ -1084,6 +1118,12 @@ static void rna_def_scene_collection(BlenderRNA *brna) parm = RNA_def_pointer(func, "sc_dst", "SceneCollection", "Collection", "Collection to insert into"); parm = RNA_def_boolean(func, "result", false, "Result", "Whether the operation succeded"); RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "duplicate", "rna_SceneCollection_duplicate"); + RNA_def_function_ui_description(func, "Create a copy of the collection"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_CONTEXT | FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "result", "SceneCollection", "", "Newly created collection"); + RNA_def_function_return(func, parm); } static void rna_def_layer_collection_override(BlenderRNA *brna) @@ -1998,6 +2038,12 @@ static void rna_def_layer_collection(BlenderRNA *brna) parm = RNA_def_pointer(func, "result", "Group", "", "Newly created Group"); RNA_def_function_return(func, parm); + func = RNA_def_function(srna, "duplicate", "rna_LayerCollection_duplicate"); + RNA_def_function_ui_description(func, "Create a copy of the collection"); + RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN | FUNC_USE_CONTEXT | FUNC_USE_REPORTS); + parm = RNA_def_pointer(func, "result", "LayerCollection", "", "Newly created collection"); + RNA_def_function_return(func, parm); + /* Flags */ prop = RNA_def_property(srna, "selectable", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", COLLECTION_SELECTABLE); |