Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/object/object_add.c
| Show First 20 Lines • Show All 3,463 Lines • ▼ Show 20 Lines | |||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Add Named Object Operator | /** \name Add Named Object Operator | ||||
| * | * | ||||
| * Use for drag & drop. | * Use for drag & drop. | ||||
| * \{ */ | * \{ */ | ||||
| static Base *object_add_ensure_in_view_layer(Main *bmain, ViewLayer *view_layer, Object *ob) | |||||
| { | |||||
| Base *base = BKE_view_layer_base_find(view_layer, ob); | |||||
| if (!base) { | |||||
| LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer); | |||||
| BKE_collection_object_add(bmain, layer_collection->collection, ob); | |||||
| base = BKE_view_layer_base_find(view_layer, ob); | |||||
| } | |||||
| return base; | |||||
| } | |||||
| static int object_add_named_exec(bContext *C, wmOperator *op) | static int object_add_named_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| 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); | ViewLayer *view_layer = CTX_data_view_layer(C); | ||||
| Base *basen; | Base *basen; | ||||
| Object *ob; | Object *ob; | ||||
| const bool duplicate = RNA_boolean_get(op->ptr, "duplicate"); | const bool linked = RNA_boolean_get(op->ptr, "linked"); | ||||
| const bool linked = duplicate && RNA_boolean_get(op->ptr, "linked"); | |||||
| const eDupli_ID_Flags dupflag = (linked) ? 0 : (eDupli_ID_Flags)U.dupflag; | const eDupli_ID_Flags dupflag = (linked) ? 0 : (eDupli_ID_Flags)U.dupflag; | ||||
| char name[MAX_ID_NAME - 2]; | char name[MAX_ID_NAME - 2]; | ||||
| /* find object, create fake base */ | /* find object, create fake base */ | ||||
| RNA_string_get(op->ptr, "name", name); | RNA_string_get(op->ptr, "name", name); | ||||
| ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name); | ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name); | ||||
| if (ob == NULL) { | if (ob == NULL) { | ||||
| BKE_report(op->reports, RPT_ERROR, "Object not found"); | BKE_report(op->reports, RPT_ERROR, "Object not found"); | ||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| /* prepare dupli */ | /* prepare dupli */ | ||||
| if (duplicate) { | |||||
| basen = object_add_duplicate_internal( | basen = object_add_duplicate_internal( | ||||
| bmain, | bmain, | ||||
| scene, | scene, | ||||
| view_layer, | view_layer, | ||||
| ob, | ob, | ||||
| dupflag, | dupflag, | ||||
| /* Sub-process flag because the new-ID remapping (#BKE_libblock_relink_to_newid()) in this | /* Sub-process flag because the new-ID remapping (#BKE_libblock_relink_to_newid()) in this | ||||
| * function will only work if the object is already linked in the view layer, which is not | * function will only work if the object is already linked in the view layer, which is not | ||||
| * the case here. So we have to do the new-ID relinking ourselves | * the case here. So we have to do the new-ID relinking ourselves | ||||
| * (#copy_object_set_idnew()). | * (#copy_object_set_idnew()). | ||||
| */ | */ | ||||
| LIB_ID_DUPLICATE_IS_SUBPROCESS | LIB_ID_DUPLICATE_IS_ROOT_ID); | LIB_ID_DUPLICATE_IS_SUBPROCESS | LIB_ID_DUPLICATE_IS_ROOT_ID); | ||||
| } | |||||
| else { | |||||
| /* basen is actually not a new base in this case. */ | |||||
| basen = object_add_ensure_in_view_layer(bmain, view_layer, ob); | |||||
| } | |||||
| if (basen == NULL) { | if (basen == NULL) { | ||||
| BKE_report(op->reports, | BKE_report(op->reports, RPT_ERROR, "Object could not be duplicated"); | ||||
| RPT_ERROR, | |||||
| duplicate ? "Object could not be duplicated" : | |||||
| "Object could not be linked to the view layer"); | |||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| basen->object->visibility_flag &= ~OB_HIDE_VIEWPORT; | basen->object->visibility_flag &= ~OB_HIDE_VIEWPORT; | ||||
| int mval[2]; | int mval[2]; | ||||
| if (object_add_drop_xy_get(C, op, &mval)) { | if (object_add_drop_xy_get(C, op, &mval)) { | ||||
| ED_object_location_from_view(C, basen->object->loc); | ED_object_location_from_view(C, basen->object->loc); | ||||
| Show All 30 Lines | void OBJECT_OT_add_named(wmOperatorType *ot) | ||||
| /* api callbacks */ | /* api callbacks */ | ||||
| ot->invoke = object_add_drop_xy_generic_invoke; | ot->invoke = object_add_drop_xy_generic_invoke; | ||||
| ot->exec = object_add_named_exec; | ot->exec = object_add_named_exec; | ||||
| ot->poll = ED_operator_objectmode; | ot->poll = ED_operator_objectmode; | ||||
| /* flags */ | /* flags */ | ||||
| ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | ||||
| PropertyRNA *prop; | |||||
| prop = RNA_def_boolean( | |||||
| ot->srna, | |||||
| "duplicate", | |||||
| true, | |||||
| "Duplicate", | |||||
| "Create a duplicate of the object. If not set, only ensures the object is linked into the " | |||||
| "active view layer, positions and selects/activates it (deselecting others)"); | |||||
| RNA_def_property_flag(prop, PROP_HIDDEN); | |||||
| RNA_def_boolean(ot->srna, | RNA_def_boolean(ot->srna, | ||||
| "linked", | "linked", | ||||
| false, | false, | ||||
| "Linked", | "Linked", | ||||
| "Duplicate object but not object data, linking to the original data (ignored if " | "Duplicate object but not object data, linking to the original data"); | ||||
| "'duplicate' is false)"); | |||||
| RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Object name to add"); | RNA_def_string(ot->srna, "name", NULL, MAX_ID_NAME - 2, "Name", "Object name to add"); | ||||
| object_add_drop_xy_props(ot); | object_add_drop_xy_props(ot); | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Transform Object to Mouse Operator | |||||
| * \{ */ | |||||
| /** | |||||
| * Alternate behavior for dropping an asset that positions the appended object(s). | |||||
| */ | |||||
| static int object_transform_to_mouse_exec(bContext *C, wmOperator *op) | |||||
| { | |||||
| Main *bmain = CTX_data_main(C); | |||||
| ViewLayer *view_layer = CTX_data_view_layer(C); | |||||
| Object *ob; | |||||
| if (RNA_struct_property_is_set(op->ptr, "name")) { | |||||
| char name[MAX_ID_NAME - 2]; | |||||
| RNA_string_get(op->ptr, "name", name); | |||||
| ob = (Object *)BKE_libblock_find_name(bmain, ID_OB, name); | |||||
| } | |||||
| else { | |||||
| ob = OBACT(view_layer); | |||||
| } | |||||
| if (ob == NULL) { | |||||
| BKE_report(op->reports, RPT_ERROR, "Object not found"); | |||||
| return OPERATOR_CANCELLED; | |||||
| } | |||||
| /* Ensure the locations are updated so snap reads the evaluated active location. */ | |||||
| CTX_data_ensure_evaluated_depsgraph(C); | |||||
| int mval[2]; | |||||
| if (object_add_drop_xy_get(C, op, &mval)) { | |||||
| float cursor[3]; | |||||
| ED_object_location_from_view(C, cursor); | |||||
| ED_view3d_cursor3d_position(C, mval, false, cursor); | |||||
| /* Use the active objects location since this is the ID which the user selected to drop. | |||||
| * | |||||
Severin: This mention clearly this transforms the entire selection, so that delta transforms with… | |||||
| * This transforms all selected objects, so that dropping a single object which links in | |||||
| * other objects will have their relative transformation preserved. | |||||
Not Done Inline ActionsWhat's that hyphen doing there, looks wrong? :) Severin: What's that hyphen doing there, looks wrong? :)
I'd also mention child-parent and boolean… | |||||
| * For example a child/parent relationship or other objects used with a boolean modifier. | |||||
| * | |||||
| * The caller is responsible for ensuring the selection state gives useful results. | |||||
Not Done Inline Actionss/do/does? Severin: `s/do/does`? | |||||
| * Link/append does this using #FILE_AUTOSELECT. */ | |||||
| ED_view3d_snap_selected_to_location(C, cursor, V3D_AROUND_ACTIVE); | |||||
| } | |||||
| return OPERATOR_FINISHED; | |||||
| } | |||||
| void OBJECT_OT_transform_to_mouse(wmOperatorType *ot) | |||||
Not Done Inline ActionsWith D12912: Assets: Snapping with visual feedback while dragging, the name transform_to_mouse doesn't make much sense anymore, since it would transform to a given matrix. Maybe rename it to drop_transform? Severin: With {D12912}, the name `transform_to_mouse` doesn't make much sense anymore, since it would… | |||||
| { | |||||
| /* identifiers */ | |||||
| ot->name = "Place Object Under Mouse"; | |||||
| ot->description = "Snap selected item(s) to the mouse location"; | |||||
| ot->idname = "OBJECT_OT_transform_to_mouse"; | |||||
| /* api callbacks */ | |||||
| ot->invoke = object_add_drop_xy_generic_invoke; | |||||
| ot->exec = object_transform_to_mouse_exec; | |||||
| ot->poll = ED_operator_objectmode; | |||||
| /* flags */ | |||||
| ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | |||||
| RNA_def_string(ot->srna, | |||||
| "name", | |||||
| NULL, | |||||
| MAX_ID_NAME - 2, | |||||
| "Name", | |||||
| "Object name to place (when unset use the active object)"); | |||||
| object_add_drop_xy_props(ot); | |||||
| } | |||||
| /** \} */ | |||||
| /* -------------------------------------------------------------------- */ | |||||
| /** \name Join Object Operator | /** \name Join Object Operator | ||||
| * \{ */ | * \{ */ | ||||
| static bool object_join_poll(bContext *C) | static bool object_join_poll(bContext *C) | ||||
| { | { | ||||
| Object *ob = CTX_data_active_object(C); | Object *ob = CTX_data_active_object(C); | ||||
| if (ob == NULL || ob->data == NULL || ID_IS_LINKED(ob) || ID_IS_OVERRIDE_LIBRARY(ob) || | if (ob == NULL || ob->data == NULL || ID_IS_LINKED(ob) || ID_IS_OVERRIDE_LIBRARY(ob) || | ||||
| ▲ Show 20 Lines • Show All 144 Lines • Show Last 20 Lines | |||||
This mention clearly this transforms the entire selection, so that delta transforms with parents, boolean-objects, etc. are preserved.