Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/object/object_edit.c
| Show First 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | |||||
| #include "ED_mesh.h" | #include "ED_mesh.h" | ||||
| #include "ED_mball.h" | #include "ED_mball.h" | ||||
| #include "ED_lattice.h" | #include "ED_lattice.h" | ||||
| #include "ED_object.h" | #include "ED_object.h" | ||||
| #include "ED_outliner.h" | #include "ED_outliner.h" | ||||
| #include "ED_screen.h" | #include "ED_screen.h" | ||||
| #include "ED_undo.h" | #include "ED_undo.h" | ||||
| #include "ED_image.h" | #include "ED_image.h" | ||||
| #include "ED_gpencil.h" | |||||
| #include "RNA_access.h" | #include "RNA_access.h" | ||||
| #include "RNA_define.h" | #include "RNA_define.h" | ||||
| #include "RNA_enum_types.h" | #include "RNA_enum_types.h" | ||||
| /* for menu/popup icons etc etc*/ | /* for menu/popup icons etc etc*/ | ||||
| #include "UI_interface.h" | #include "UI_interface.h" | ||||
| ▲ Show 20 Lines • Show All 1,423 Lines • ▼ Show 20 Lines | |||||
| /* ********************** */ | /* ********************** */ | ||||
| static const EnumPropertyItem *object_mode_set_itemsf( | static const EnumPropertyItem *object_mode_set_itemsf( | ||||
| bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) | bContext *C, PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), bool *r_free) | ||||
| { | { | ||||
| const EnumPropertyItem *input = rna_enum_object_mode_items; | const EnumPropertyItem *input = rna_enum_object_mode_items; | ||||
| EnumPropertyItem *item = NULL; | EnumPropertyItem *item = NULL; | ||||
| Object *ob; | Object *ob; | ||||
| bGPdata *gpd; | |||||
| int totitem = 0; | int totitem = 0; | ||||
| if (!C) /* needed for docs */ | if (!C) /* needed for docs */ | ||||
| return rna_enum_object_mode_items; | return rna_enum_object_mode_items; | ||||
| ob = CTX_data_active_object(C); | ob = CTX_data_active_object(C); | ||||
| if (ob) { | if (ob) { | ||||
| const bool use_mode_particle_edit = (BLI_listbase_is_empty(&ob->particlesystem) == false) || | const bool use_mode_particle_edit = (BLI_listbase_is_empty(&ob->particlesystem) == false) || | ||||
| (ob->soft != NULL) || | (ob->soft != NULL) || | ||||
| (modifiers_findByType(ob, eModifierType_Cloth) != NULL); | (modifiers_findByType(ob, eModifierType_Cloth) != NULL); | ||||
| while (input->identifier) { | while (input->identifier) { | ||||
| if ((input->value == OB_MODE_EDIT && OB_TYPE_SUPPORT_EDITMODE(ob->type)) || | if ((input->value == OB_MODE_EDIT && OB_TYPE_SUPPORT_EDITMODE(ob->type)) || | ||||
| (input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) || | (input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) || | ||||
| (input->value == OB_MODE_PARTICLE_EDIT && use_mode_particle_edit) || | (input->value == OB_MODE_PARTICLE_EDIT && use_mode_particle_edit) || | ||||
| (ELEM(input->value, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, | (ELEM(input->value, OB_MODE_SCULPT, OB_MODE_VERTEX_PAINT, | ||||
| OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT) && (ob->type == OB_MESH)) || | OB_MODE_WEIGHT_PAINT, OB_MODE_TEXTURE_PAINT) && (ob->type == OB_MESH)) || | ||||
| (ELEM(input->value, OB_MODE_GPENCIL_EDIT, OB_MODE_GPENCIL_PAINT, | |||||
| OB_MODE_GPENCIL_SCULPT, OB_MODE_GPENCIL_WEIGHT) && (ob->type == OB_GPENCIL)) || | |||||
| (input->value == OB_MODE_OBJECT)) | (input->value == OB_MODE_OBJECT)) | ||||
| { | { | ||||
| RNA_enum_item_add(&item, &totitem, input); | RNA_enum_item_add(&item, &totitem, input); | ||||
| } | } | ||||
| input++; | input++; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| /* We need at least this one! */ | /* We need at least this one! */ | ||||
| RNA_enum_items_add_value(&item, &totitem, input, OB_MODE_OBJECT); | RNA_enum_items_add_value(&item, &totitem, input, OB_MODE_OBJECT); | ||||
| } | } | ||||
| /* On top of all the rest, GPencil Stroke Edit Mode | |||||
| * is available if there's a valid gp datablock... | |||||
| */ | |||||
| gpd = CTX_data_gpencil_data(C); | |||||
| if (gpd) { | |||||
| RNA_enum_items_add_value(&item, &totitem, rna_enum_object_mode_items, OB_MODE_GPENCIL); | |||||
| } | |||||
| RNA_enum_item_end(&item, &totitem); | RNA_enum_item_end(&item, &totitem); | ||||
| *r_free = true; | *r_free = true; | ||||
| return item; | return item; | ||||
| } | } | ||||
| static bool object_mode_set_poll(bContext *C) | static bool object_mode_set_poll(bContext *C) | ||||
| { | { | ||||
| /* Since Grease Pencil editmode is also handled here, | /* Since Grease Pencil editmode is also handled here, | ||||
| * we have a special exception for allowing this operator | * we have a special exception for allowing this operator | ||||
| * to still work in that case when there's no active object | * to still work in that case when there's no active object | ||||
| * so that users can exit editmode this way as per normal. | * so that users can exit editmode this way as per normal. | ||||
| */ | */ | ||||
| if (ED_operator_object_active_editable(C)) | if (ED_operator_object_active_editable(C)) | ||||
| return true; | return true; | ||||
| else | else | ||||
| return (CTX_data_gpencil_data(C) != NULL); | return (CTX_data_gpencil_data(C) != NULL); | ||||
| } | } | ||||
| static int object_mode_set_exec(bContext *C, wmOperator *op) | static int object_mode_set_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_or_submode"); | bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_or_submode"); | ||||
| Object *ob = CTX_data_active_object(C); | Object *ob = CTX_data_active_object(C); | ||||
| bGPdata *gpd = CTX_data_gpencil_data(C); | |||||
| eObjectMode mode = RNA_enum_get(op->ptr, "mode"); | eObjectMode mode = RNA_enum_get(op->ptr, "mode"); | ||||
| eObjectMode restore_mode = (ob) ? ob->mode : OB_MODE_OBJECT; | eObjectMode restore_mode = (ob) ? ob->mode : OB_MODE_OBJECT; | ||||
| const bool toggle = RNA_boolean_get(op->ptr, "toggle"); | const bool toggle = RNA_boolean_get(op->ptr, "toggle"); | ||||
| if (use_submode) { | if (use_submode) { | ||||
| /* When not changing modes use submodes, see: T55162. */ | /* When not changing modes use submodes, see: T55162. */ | ||||
| if (toggle == false) { | if (toggle == false) { | ||||
| if (mode == restore_mode) { | if (mode == restore_mode) { | ||||
| switch (mode) { | switch (mode) { | ||||
| case OB_MODE_EDIT: | case OB_MODE_EDIT: | ||||
| WM_menu_name_call(C, "VIEW3D_MT_edit_mesh_select_mode", WM_OP_INVOKE_REGION_WIN); | WM_menu_name_call(C, "VIEW3D_MT_edit_mesh_select_mode", WM_OP_INVOKE_REGION_WIN); | ||||
| return OPERATOR_INTERFACE; | return OPERATOR_INTERFACE; | ||||
| default: | default: | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| #if 0 /* GPXX */ | |||||
| if (gpd) { | if (gpd) { | ||||
| /* GP Mode is not bound to a specific object. Therefore, | /* GP Mode is not bound to a specific object. Therefore, | ||||
| * we don't want it to be actually saved on any objects, | * we don't want it to be actually saved on any objects, | ||||
| * as weirdness can happen if you select other objects, | * as weirdness can happen if you select other objects, | ||||
| * or load old files. | * or load old files. | ||||
| * | * | ||||
| * Instead, we use the following 2 rules to ensure that | * Instead, we use the following 2 rules to ensure that | ||||
| * the mode selector works as expected: | * the mode selector works as expected: | ||||
| * 1) If there's no object, we want to enter editmode. | * 1) If there's no object, we want to enter editmode. | ||||
| * (i.e. with no object, we're in object mode) | * (i.e. with no object, we're in object mode) | ||||
| * 2) Otherwise, exit stroke editmode, so that we can | * 2) Otherwise, exit stroke editmode, so that we can | ||||
| * enter another mode... | * enter another mode... | ||||
| */ | */ | ||||
| if (!ob || (gpd->flag & GP_DATA_STROKE_EDITMODE)) { | if (!ob || (gpd->flag & GP_DATA_STROKE_EDITMODE)) { | ||||
| WM_operator_name_call(C, "GPENCIL_OT_editmode_toggle", WM_OP_EXEC_REGION_WIN, NULL); | WM_operator_name_call(C, "GPENCIL_OT_editmode_toggle", WM_OP_EXEC_REGION_WIN, NULL); | ||||
| } | } | ||||
| } | } | ||||
| #endif | |||||
| if (!ob || !ED_object_mode_compat_test(ob, mode)) | if (!ob || !ED_object_mode_compat_test(ob, mode)) | ||||
| return OPERATOR_PASS_THROUGH; | return OPERATOR_PASS_THROUGH; | ||||
| if (ob->mode != mode) { | if (ob->mode != mode) { | ||||
| /* we should be able to remove this call, each operator calls */ | /* we should be able to remove this call, each operator calls */ | ||||
| ED_object_mode_compat_set(C, ob, mode, op->reports); | ED_object_mode_compat_set(C, ob, mode, op->reports); | ||||
| } | } | ||||
| Show All 13 Lines | else if (ob->mode == mode) { | ||||
| /* For toggling, store old mode so we know what to go back to */ | /* For toggling, store old mode so we know what to go back to */ | ||||
| ob->restore_mode = restore_mode; | ob->restore_mode = restore_mode; | ||||
| } | } | ||||
| else if (ob->restore_mode != OB_MODE_OBJECT && ob->restore_mode != mode) { | else if (ob->restore_mode != OB_MODE_OBJECT && ob->restore_mode != mode) { | ||||
| ED_object_mode_toggle(C, ob->restore_mode); | ED_object_mode_toggle(C, ob->restore_mode); | ||||
| } | } | ||||
| } | } | ||||
| /* if type is OB_GPENCIL, set cursor mode */ | |||||
| if ((ob) && (ob->type == OB_GPENCIL)) { | |||||
| if (ob->data) { | |||||
| bGPdata *gpd = (bGPdata *)ob->data; | |||||
| ED_gpencil_setup_modes(C, gpd, ob->mode); | |||||
| } | |||||
| } | |||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| void OBJECT_OT_mode_set(wmOperatorType *ot) | void OBJECT_OT_mode_set(wmOperatorType *ot) | ||||
| { | { | ||||
| PropertyRNA *prop; | PropertyRNA *prop; | ||||
| /* identifiers */ | /* identifiers */ | ||||
| ▲ Show 20 Lines • Show All 426 Lines • Show Last 20 Lines | |||||