Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/space_outliner/outliner_collections.c
| Show First 20 Lines • Show All 177 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name New Collection | /** \name New Collection | ||||
| * \{ */ | * \{ */ | ||||
| struct CollectionNewData { | typedef enum NewCollectionMethod { | ||||
| bool error; | COLLECTION_NEW, | ||||
| Collection *collection; | COLLECTION_NEW_MOVE_SELECTION, | ||||
| }; | COLLECTION_NEW_LINK_SELECTION, | ||||
| } NewCollectionMethod; | |||||
| static TreeTraversalAction collection_find_selected_to_add(TreeElement *te, void *customdata) | static Collection *find_parent_collection(TreeElement *te) | ||||
| { | { | ||||
| struct CollectionNewData *data = customdata; | while (te) { | ||||
| Collection *collection = outliner_collection_from_tree_element(te); | te = te->parent; | ||||
| if (outliner_is_collection_tree_element(te)) { | |||||
| if (!collection) { | return outliner_collection_from_tree_element(te); | ||||
| return TRAVERSE_SKIP_CHILDS; | |||||
| } | } | ||||
| if (data->collection != NULL) { | |||||
| data->error = true; | |||||
| return TRAVERSE_BREAK; | |||||
| } | } | ||||
| return NULL; | |||||
| data->collection = collection; | |||||
| return TRAVERSE_CONTINUE; | |||||
| } | } | ||||
| static int collection_new_exec(bContext *C, wmOperator *op) | static int collection_new_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); | SpaceOutliner *space_outliner = CTX_wm_space_outliner(C); | ||||
| ARegion *region = CTX_wm_region(C); | |||||
| Main *bmain = CTX_data_main(C); | Main *bmain = CTX_data_main(C); | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| ViewLayer *view_layer = CTX_data_view_layer(C); | const short method = RNA_enum_get(op->ptr, "method"); | ||||
HooglyBoogly: Just declare the variable where it's assigned, the style guide discourages the pattern of… | |||||
| struct CollectionNewData data = { | /* Make new collection a child of the active collection */ | ||||
| .error = false, | Collection *collection = CTX_data_layer_collection(C)->collection; | ||||
| .collection = NULL, | if (ID_IS_LINKED(collection)) { | ||||
| }; | collection = scene->master_collection; | ||||
| } | |||||
| if (RNA_boolean_get(op->ptr, "nested")) { | if (ID_IS_LINKED(scene)) { | ||||
| outliner_build_tree(bmain, scene, view_layer, space_outliner, region); | BKE_report(op->reports, RPT_ERROR, "Can't add a new collection to linked scene/collection"); | ||||
| return OPERATOR_CANCELLED; | |||||
| } | |||||
| Collection *collection_new = BKE_collection_add(bmain, collection, NULL); | |||||
| if (method != COLLECTION_NEW) { | |||||
| /* Move selected objects into new collection */ | |||||
| struct IDsSelectedData data = {{NULL}}; | |||||
| outliner_tree_traverse(space_outliner, | outliner_tree_traverse(space_outliner, | ||||
| &space_outliner->tree, | &space_outliner->tree, | ||||
| 0, | 0, | ||||
| TSE_SELECTED, | TSE_SELECTED, | ||||
| collection_find_selected_to_add, | outliner_find_selected_objects, | ||||
| &data); | &data); | ||||
| if (data.error) { | LISTBASE_FOREACH (LinkData *, link, &data.selected_array) { | ||||
| BKE_report(op->reports, RPT_ERROR, "More than one collection is selected"); | TreeElement *te = (TreeElement *)link->data; | ||||
| return OPERATOR_CANCELLED; | TreeStoreElem *tselem = TREESTORE(te); | ||||
| Collection *parent = find_parent_collection(te); | |||||
| Object *ob = (Object *)tselem->id; | |||||
| if (method == COLLECTION_NEW_MOVE_SELECTION) { | |||||
| BKE_collection_object_move(bmain, scene, collection_new, parent, ob); | |||||
| } | } | ||||
| else { | |||||
| BKE_collection_object_add(bmain, collection_new, ob); | |||||
| } | } | ||||
| if (data.collection == NULL || ID_IS_LINKED(data.collection)) { | |||||
| data.collection = scene->master_collection; | |||||
| } | } | ||||
| BLI_freelistN(&data.selected_array); | |||||
| if (ID_IS_LINKED(scene)) { | |||||
| BKE_report(op->reports, RPT_ERROR, "Can't add a new collection to linked scene/collection"); | |||||
| return OPERATOR_CANCELLED; | |||||
| } | } | ||||
| BKE_collection_add(bmain, data.collection, NULL); | DEG_id_tag_update(&collection->id, ID_RECALC_COPY_ON_WRITE); | ||||
| DEG_id_tag_update(&data.collection->id, ID_RECALC_COPY_ON_WRITE); | |||||
| DEG_relations_tag_update(bmain); | DEG_relations_tag_update(bmain); | ||||
| outliner_cleanup_tree(space_outliner); | outliner_cleanup_tree(space_outliner); | ||||
| WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); | WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL); | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| void OUTLINER_OT_collection_new(wmOperatorType *ot) | void OUTLINER_OT_collection_new(wmOperatorType *ot) | ||||
| { | { | ||||
| static EnumPropertyItem method_items[] = { | |||||
| {COLLECTION_NEW, | |||||
| "EMPTY", | |||||
| 0, | |||||
| "Empty", | |||||
| "Create a new collection inside the active collection"}, | |||||
| {COLLECTION_NEW_MOVE_SELECTION, | |||||
| "SELECTION", | |||||
| 0, | |||||
| "Move Objects", | |||||
| "Move the selected objects to a new collection"}, | |||||
| {COLLECTION_NEW_LINK_SELECTION, | |||||
| "SELECTION_LINKED", | |||||
| 0, | |||||
| "Link Objects", | |||||
| "Link the selected objects to a new collection"}, | |||||
| {0, NULL, 0, NULL, NULL}, | |||||
| }; | |||||
| /* identifiers */ | /* identifiers */ | ||||
| ot->name = "New Collection"; | ot->name = "New Collection"; | ||||
| ot->idname = "OUTLINER_OT_collection_new"; | ot->idname = "OUTLINER_OT_collection_new"; | ||||
| ot->description = "Add a new collection inside selected collection"; | ot->description = "Create a new collection"; | ||||
Not Done Inline ActionsThis could be a little bit more descriptive. How about "Add a new collection to the scene collection hierarchy"? Severin: This could be a little bit more descriptive. How about "Add a new collection to the scene… | |||||
| /* api callbacks */ | /* api callbacks */ | ||||
| ot->exec = collection_new_exec; | ot->exec = collection_new_exec; | ||||
| ot->poll = ED_outliner_collections_editor_poll; | ot->poll = ED_outliner_collections_editor_poll; | ||||
| /* flags */ | /* flags */ | ||||
| ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | ||||
| /* properties */ | /* properties */ | ||||
| PropertyRNA *prop = RNA_def_boolean( | ot->prop = RNA_def_enum( | ||||
| ot->srna, "nested", true, "Nested", "Add as child of selected collection"); | ot->srna, "method", method_items, COLLECTION_NEW_MOVE_SELECTION, "Method", ""); | ||||
Done Inline Actions"type" doesn't seem like the right word here, it's not the type of the collection, it's the manner in which it's added that changes. I would suggest using "Mode" HooglyBoogly: "type" doesn't seem like the right word here, it's not the type of the collection, it's the… | |||||
| RNA_def_property_flag(prop, PROP_SKIP_SAVE); | |||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Delete Collection | /** \name Delete Collection | ||||
| * \{ */ | * \{ */ | ||||
| ▲ Show 20 Lines • Show All 1,312 Lines • Show Last 20 Lines | |||||
Just declare the variable where it's assigned, the style guide discourages the pattern of declaring variables before they're used.