Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/object/object_edit.c
| Show First 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | |||||
| #include "BKE_sca.h" | #include "BKE_sca.h" | ||||
| #include "BKE_softbody.h" | #include "BKE_softbody.h" | ||||
| #include "BKE_modifier.h" | #include "BKE_modifier.h" | ||||
| #include "BKE_editlattice.h" | #include "BKE_editlattice.h" | ||||
| #include "BKE_editmesh.h" | #include "BKE_editmesh.h" | ||||
| #include "BKE_report.h" | #include "BKE_report.h" | ||||
| #include "BKE_object.h" | #include "BKE_object.h" | ||||
| #include "BKE_workspace.h" | #include "BKE_workspace.h" | ||||
| #include "BKE_layer.h" | |||||
| #include "DEG_depsgraph.h" | #include "DEG_depsgraph.h" | ||||
| #include "DEG_depsgraph_build.h" | #include "DEG_depsgraph_build.h" | ||||
| #include "ED_armature.h" | #include "ED_armature.h" | ||||
| #include "ED_curve.h" | #include "ED_curve.h" | ||||
| #include "ED_mesh.h" | #include "ED_mesh.h" | ||||
| #include "ED_mball.h" | #include "ED_mball.h" | ||||
| ▲ Show 20 Lines • Show All 172 Lines • ▼ Show 20 Lines | |||||
| * \param C: Can be NULL, only if #EM_DO_UNDO isn't set. | * \param C: Can be NULL, only if #EM_DO_UNDO isn't set. | ||||
| * \param flag: | * \param flag: | ||||
| * - Only in exceptional cases should #EM_DO_UNDO NOT be in the flag. | * - Only in exceptional cases should #EM_DO_UNDO NOT be in the flag. | ||||
| * - If #EM_FREEDATA isn't in the flag, use ED_object_editmode_load directly. | * - If #EM_FREEDATA isn't in the flag, use ED_object_editmode_load directly. | ||||
| */ | */ | ||||
| void ED_object_editmode_exit_ex(bContext *C, Scene *scene, Object *obedit, int flag) | void ED_object_editmode_exit_ex(bContext *C, Scene *scene, Object *obedit, int flag) | ||||
| { | { | ||||
| BLI_assert(C || !(flag & EM_DO_UNDO)); | BLI_assert(C || !(flag & EM_DO_UNDO)); | ||||
| /* Note! only in exceptional cases should 'EM_DO_UNDO' NOT be in the flag */ | |||||
| /* Note! if 'EM_FREEDATA' isn't in the flag, use ED_object_editmode_load directly */ | |||||
| ViewLayer *view_layer = CTX_data_view_layer(C); | |||||
| const bool freedata = (flag & EM_FREEDATA) != 0; | const bool freedata = (flag & EM_FREEDATA) != 0; | ||||
| if (flag & EM_WAITCURSOR) waitcursor(1); | if (flag & EM_WAITCURSOR) waitcursor(1); | ||||
| if (ED_object_editmode_load_ex(G.main, obedit, freedata) == false) { | if (ED_object_editmode_load_ex(G.main, obedit, freedata) == false) { | ||||
| /* in rare cases (background mode) its possible active object | /* in rare cases (background mode) its possible active object | ||||
| * is flagged for editmode, without 'obedit' being set [#35489] */ | * is flagged for editmode, without 'obedit' being set [#35489] */ | ||||
| if (UNLIKELY(view_layer->basact && (view_layer->basact->object->mode & OB_MODE_EDIT))) { | if (UNLIKELY(obedit && obedit->mode & OB_MODE_EDIT)) { | ||||
| view_layer->basact->object->mode &= ~OB_MODE_EDIT; | obedit->mode &= ~OB_MODE_EDIT; | ||||
| } | } | ||||
| if (flag & EM_WAITCURSOR) waitcursor(0); | if (flag & EM_WAITCURSOR) waitcursor(0); | ||||
| return; | return; | ||||
| } | } | ||||
| /* freedata only 0 now on file saves and render */ | /* freedata only 0 now on file saves and render */ | ||||
| if (freedata) { | if (freedata) { | ||||
| ListBase pidlist; | ListBase pidlist; | ||||
| Show All 10 Lines | if (freedata) { | ||||
| BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED); | BKE_ptcache_object_reset(scene, obedit, PTCACHE_RESET_OUTDATED); | ||||
| /* also flush ob recalc, doesn't take much overhead, but used for particles */ | /* also flush ob recalc, doesn't take much overhead, but used for particles */ | ||||
| DEG_id_tag_update(&obedit->id, OB_RECALC_OB | OB_RECALC_DATA); | DEG_id_tag_update(&obedit->id, OB_RECALC_OB | OB_RECALC_DATA); | ||||
| if (flag & EM_DO_UNDO) | if (flag & EM_DO_UNDO) | ||||
| ED_undo_push(C, "Editmode"); | ED_undo_push(C, "Editmode"); | ||||
| if (C != NULL) { | |||||
| WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene); | WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene); | ||||
| } | |||||
| else { | |||||
| WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene); | |||||
| } | |||||
| obedit->mode &= ~OB_MODE_EDIT; | obedit->mode &= ~OB_MODE_EDIT; | ||||
| } | } | ||||
| if (flag & EM_WAITCURSOR) waitcursor(0); | if (flag & EM_WAITCURSOR) waitcursor(0); | ||||
| /* This way we ensure scene's obedit is copied into all CoW scenes. */ | |||||
| DEG_id_tag_update(&scene->id, 0); | |||||
| } | } | ||||
| void ED_object_editmode_exit(bContext *C, int flag) | void ED_object_editmode_exit(bContext *C, int flag) | ||||
| { | { | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| Object *obedit = CTX_data_edit_object(C); | Object *obedit = CTX_data_edit_object(C); | ||||
| ED_object_editmode_exit_ex(C, scene, obedit, flag); | ED_object_editmode_exit_ex(C, scene, obedit, flag); | ||||
| } | } | ||||
| void ED_object_editmode_enter(bContext *C, int flag) | void ED_object_editmode_enter_ex(Scene *scene, Object *ob, int flag) | ||||
| { | { | ||||
| Scene *scene = CTX_data_scene(C); | |||||
| ViewLayer *view_layer = CTX_data_view_layer(C); | |||||
| Object *ob; | |||||
| bool ok = false; | bool ok = false; | ||||
| if (ID_IS_LINKED(scene)) return; | |||||
| if ((flag & EM_IGNORE_LAYER) == 0) { | |||||
| ob = CTX_data_active_object(C); /* active layer checked here for view3d */ | |||||
| if (ob == NULL) return; | |||||
| } | |||||
| else { | |||||
| ob = view_layer->basact->object; | |||||
| } | |||||
| if (ELEM(NULL, ob, ob->data)) return; | if (ELEM(NULL, ob, ob->data)) return; | ||||
| if (ID_IS_LINKED(ob)) return; | |||||
| /* this checks actual object->data, for cases when other scenes have it in editmode context */ | /* this checks actual object->data, for cases when other scenes have it in editmode context */ | ||||
| if (BKE_object_is_in_editmode(ob)) | if (BKE_object_is_in_editmode(ob)) | ||||
| return; | return; | ||||
| if (BKE_object_obdata_is_libdata(ob)) { | if (BKE_object_obdata_is_libdata(ob)) { | ||||
| error_libdata(); | error_libdata(); | ||||
| return; | return; | ||||
| } | } | ||||
| if (flag & EM_WAITCURSOR) waitcursor(1); | if (flag & EM_WAITCURSOR) waitcursor(1); | ||||
| ob->restore_mode = ob->mode; | ob->restore_mode = ob->mode; | ||||
| /* note, when switching scenes the object can have editmode data but | |||||
| * not be scene->obedit: bug 22954, this avoids calling self eternally */ | |||||
| if ((ob->restore_mode & OB_MODE_EDIT) == 0) | |||||
| ED_object_mode_toggle(C, ob->mode); | |||||
| ob->mode = OB_MODE_EDIT; | ob->mode = OB_MODE_EDIT; | ||||
| if (ob->type == OB_MESH) { | if (ob->type == OB_MESH) { | ||||
| BMEditMesh *em; | BMEditMesh *em; | ||||
| ok = 1; | ok = 1; | ||||
| const bool use_key_index = mesh_needs_keyindex(ob->data); | const bool use_key_index = mesh_needs_keyindex(ob->data); | ||||
| EDBM_mesh_make(ob, scene->toolsettings->selectmode, use_key_index); | EDBM_mesh_make(ob, scene->toolsettings->selectmode, use_key_index); | ||||
| em = BKE_editmesh_from_object(ob); | em = BKE_editmesh_from_object(ob); | ||||
| if (LIKELY(em)) { | if (LIKELY(em)) { | ||||
| /* order doesn't matter */ | /* order doesn't matter */ | ||||
| EDBM_mesh_normals_update(em); | EDBM_mesh_normals_update(em); | ||||
| BKE_editmesh_tessface_calc(em); | BKE_editmesh_tessface_calc(em); | ||||
| } | } | ||||
| WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_MESH, scene); | WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MESH, NULL); | ||||
| } | } | ||||
| else if (ob->type == OB_ARMATURE) { | else if (ob->type == OB_ARMATURE) { | ||||
| bArmature *arm = ob->data; | bArmature *arm = ob->data; | ||||
| if (!arm) return; | if (!arm) return; | ||||
| /* | /* | ||||
| * The function BKE_object_obdata_is_libdata make a problem here, the | * The function BKE_object_obdata_is_libdata make a problem here, the | ||||
| * check for ob->proxy return 0 and let blender enter to edit mode | * check for ob->proxy return 0 and let blender enter to edit mode | ||||
| * this causes a crash when you try leave the edit mode. | * this causes a crash when you try leave the edit mode. | ||||
| * The problem is that i can't remove the ob->proxy check from | * The problem is that i can't remove the ob->proxy check from | ||||
| * BKE_object_obdata_is_libdata that prevent the bugfix #6614, so | * BKE_object_obdata_is_libdata that prevent the bugfix #6614, so | ||||
| * i add this little hack here. | * i add this little hack here. | ||||
| */ | */ | ||||
| if (ID_IS_LINKED(arm)) { | if (ID_IS_LINKED(arm)) { | ||||
| error_libdata(); | error_libdata(); | ||||
| return; | return; | ||||
| } | } | ||||
| ok = 1; | ok = 1; | ||||
| ED_armature_to_edit(arm); | ED_armature_to_edit(arm); | ||||
| /* to ensure all goes in restposition and without striding */ | /* to ensure all goes in restposition and without striding */ | ||||
| DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); /* XXX: should this be OB_RECALC_DATA? */ | DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); /* XXX: should this be OB_RECALC_DATA? */ | ||||
| WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_ARMATURE, scene); | WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_ARMATURE, scene); | ||||
| } | } | ||||
| else if (ob->type == OB_FONT) { | else if (ob->type == OB_FONT) { | ||||
| ok = 1; | ok = 1; | ||||
| ED_curve_editfont_make(ob); | ED_curve_editfont_make(ob); | ||||
| WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_TEXT, scene); | WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_TEXT, scene); | ||||
| } | } | ||||
| else if (ob->type == OB_MBALL) { | else if (ob->type == OB_MBALL) { | ||||
| ok = 1; | ok = 1; | ||||
| ED_mball_editmball_make(ob); | ED_mball_editmball_make(ob); | ||||
| WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_MBALL, scene); | WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MBALL, scene); | ||||
| } | } | ||||
| else if (ob->type == OB_LATTICE) { | else if (ob->type == OB_LATTICE) { | ||||
| ok = 1; | ok = 1; | ||||
| BKE_editlattice_make(ob); | BKE_editlattice_make(ob); | ||||
| WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_LATTICE, scene); | WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_LATTICE, scene); | ||||
| } | } | ||||
| else if (ob->type == OB_SURF || ob->type == OB_CURVE) { | else if (ob->type == OB_SURF || ob->type == OB_CURVE) { | ||||
| ok = 1; | ok = 1; | ||||
| ED_curve_editnurb_make(ob); | ED_curve_editnurb_make(ob); | ||||
| WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_CURVE, scene); | WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_CURVE, scene); | ||||
| } | } | ||||
| if (ok) { | if (ok) { | ||||
| DEG_id_tag_update(&ob->id, OB_RECALC_DATA); | DEG_id_tag_update(&ob->id, OB_RECALC_DATA); | ||||
| /* This way we ensure scene's obedit is copied into all CoW scenes. */ | |||||
| DEG_id_tag_update(&scene->id, 0); | |||||
| } | } | ||||
| else { | else { | ||||
| if ((flag & EM_NO_CONTEXT) == 0) { | |||||
| ob->mode &= ~OB_MODE_EDIT; | ob->mode &= ~OB_MODE_EDIT; | ||||
| WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene); | } | ||||
| WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene); | |||||
| } | } | ||||
| if (flag & EM_DO_UNDO) ED_undo_push(C, "Enter Editmode"); | |||||
| if (flag & EM_WAITCURSOR) waitcursor(0); | if (flag & EM_WAITCURSOR) waitcursor(0); | ||||
| BLI_assert((flag & EM_DO_UNDO) == 0); | |||||
| } | |||||
| void ED_object_editmode_enter(bContext *C, int flag) | |||||
| { | |||||
| Scene *scene = CTX_data_scene(C); | |||||
| ViewLayer *view_layer = CTX_data_view_layer(C); | |||||
| Object *ob; | |||||
| if ((flag & EM_IGNORE_LAYER) == 0) { | |||||
| ob = CTX_data_active_object(C); /* active layer checked here for view3d */ | |||||
| } | |||||
| else { | |||||
| ob = view_layer->basact->object; | |||||
| } | |||||
| if (ob == NULL) return; | |||||
| if (ID_IS_LINKED(ob)) return; | |||||
| ED_object_editmode_enter_ex(scene, ob, flag & ~EM_DO_UNDO); | |||||
| if (flag & EM_DO_UNDO) ED_undo_push(C, "Enter Editmode"); | |||||
| } | } | ||||
| static int editmode_toggle_exec(bContext *C, wmOperator *op) | static int editmode_toggle_exec(bContext *C, wmOperator *op) | ||||
| { | { | ||||
| const int mode_flag = OB_MODE_EDIT; | const int mode_flag = OB_MODE_EDIT; | ||||
| const bool is_mode_set = (CTX_data_edit_object(C) != NULL); | const bool is_mode_set = (CTX_data_edit_object(C) != NULL); | ||||
| Scene *scene = CTX_data_scene(C); | Scene *scene = CTX_data_scene(C); | ||||
| ViewLayer *view_layer = CTX_data_view_layer(C); | |||||
| Object *obact = OBACT(view_layer); | |||||
| if (!is_mode_set) { | if (!is_mode_set) { | ||||
| Object *ob = CTX_data_active_object(C); | if (!ED_object_mode_compat_set(C, obact, mode_flag, op->reports)) { | ||||
| if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) { | |||||
| return OPERATOR_CANCELLED; | return OPERATOR_CANCELLED; | ||||
| } | } | ||||
| } | } | ||||
| if (!is_mode_set) | if (!is_mode_set) { | ||||
| ED_object_editmode_enter(C, EM_WAITCURSOR); | ED_object_editmode_enter(C, EM_WAITCURSOR); | ||||
| else | if (obact->mode & mode_flag) { | ||||
| FOREACH_SELECTED_OBJECT_BEGIN(view_layer, ob) | |||||
| { | |||||
| if (ob != obact) { | |||||
| if (ob->flag & SELECT) { | |||||
| ED_object_editmode_enter_ex(scene, ob, EM_WAITCURSOR | EM_NO_CONTEXT); | |||||
| } | |||||
| } | |||||
| } | |||||
| FOREACH_SELECTED_OBJECT_END; | |||||
| } | |||||
| } | |||||
| else { | |||||
| ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR); /* had EM_DO_UNDO but op flag calls undo too [#24685] */ | ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR); /* had EM_DO_UNDO but op flag calls undo too [#24685] */ | ||||
| } | |||||
| ED_space_image_uv_sculpt_update(CTX_wm_manager(C), scene); | ED_space_image_uv_sculpt_update(CTX_wm_manager(C), scene); | ||||
| return OPERATOR_FINISHED; | return OPERATOR_FINISHED; | ||||
| } | } | ||||
| static int editmode_toggle_poll(bContext *C) | static int editmode_toggle_poll(bContext *C) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 1,828 Lines • Show Last 20 Lines | |||||