From 18bb0bc5693927f0e7393f717fdb7d844d4cd69d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 16 Feb 2018 23:37:47 +1100 Subject: Object Mode: exit sculpt on selection --- source/blender/editors/include/ED_object.h | 5 + source/blender/editors/object/object_select.c | 6 +- source/blender/editors/sculpt_paint/paint_hide.c | 2 +- source/blender/editors/sculpt_paint/paint_mask.c | 6 +- source/blender/editors/sculpt_paint/sculpt.c | 171 ++++++++++++++------- .../blender/editors/sculpt_paint/sculpt_intern.h | 19 ++- source/blender/editors/sculpt_paint/sculpt_undo.c | 4 +- source/blender/editors/util/undo.c | 2 +- source/blender/windowmanager/WM_api.h | 2 +- source/blender/windowmanager/intern/wm_files.c | 6 +- 10 files changed, 148 insertions(+), 75 deletions(-) diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 0452464f9d0..5df46dd26b8 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -150,6 +150,11 @@ void ED_object_vpaintmode_exit(struct bContext *C); void ED_object_wpaintmode_exit_ex(struct WorkSpace *workspace, struct Object *ob); void ED_object_wpaintmode_exit(struct bContext *C); +void ED_object_sculptmode_exit_ex( + const struct EvaluationContext *eval_ctx, + struct WorkSpace *workspace, struct Scene *scene, struct Object *ob); +void ED_object_sculptmode_exit(struct bContext *C); + void ED_object_location_from_view(struct bContext *C, float loc[3]); void ED_object_rotation_from_view(struct bContext *C, float rot[3], const char align_axis); void ED_object_base_init_transform(struct bContext *C, struct Base *base, const float loc[3], const float rot[3]); diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index 55c0b4c2bdd..8a62438dc80 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -146,7 +146,6 @@ void ED_object_base_activate(bContext *C, Base *base) * Not correct because it's possible other work-spaces use these. * although that's a corner case. */ if (workspace->object_mode & OB_MODE_EDIT) { - Object *obact = OBACT(view_layer); FOREACH_OBJECT(view_layer, ob) { if (ob != base->object) { if (BKE_object_is_in_editmode(ob)) { @@ -157,7 +156,8 @@ void ED_object_base_activate(bContext *C, Base *base) FOREACH_OBJECT_END; } else if (workspace->object_mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_SCULPT)) { - Object *obact = OBACT(view_layer); + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); FOREACH_OBJECT(view_layer, ob) { if (ob != base->object) { if (ob->sculpt) { @@ -174,7 +174,7 @@ void ED_object_base_activate(bContext *C, Base *base) } case OB_MODE_SCULPT: { - /* TODO */ + ED_object_sculptmode_exit_ex(&eval_ctx, workspace, scene, ob); break; } } diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c index 4c6cd8d6d22..b175a33934a 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.c +++ b/source/blender/editors/sculpt_paint/paint_hide.c @@ -418,7 +418,7 @@ static int hide_show_exec(bContext *C, wmOperator *op) MEM_freeN(nodes); /* end undo */ - sculpt_undo_push_end(C); + sculpt_undo_push_end(); /* ensure that edges and faces get hidden as well (not used by * sculpt but it looks wrong when entering editmode otherwise) */ diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index ff261a808da..d8dcacbd981 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -171,7 +171,7 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op) if (multires) multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED); - sculpt_undo_push_end(C); + sculpt_undo_push_end(); if (nodes) MEM_freeN(nodes); @@ -327,7 +327,7 @@ int ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti *r if (multires) multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED); - sculpt_undo_push_end(C); + sculpt_undo_push_end(); ED_region_tag_redraw(ar); @@ -514,7 +514,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) if (multires) multires_mark_as_modified(ob, MULTIRES_COORDS_MODIFIED); - sculpt_undo_push_end(C); + sculpt_undo_push_end(); ED_region_tag_redraw(vc.ar); MEM_freeN((void *)mcords); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 02404ef2d8e..48633e2031e 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -5047,7 +5047,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str sculpt_cache_free(ss->cache); ss->cache = NULL; - sculpt_undo_push_end(C); + sculpt_undo_push_end(); BKE_pbvh_update(ss->pbvh, PBVH_UpdateOriginalBB, NULL); @@ -5255,24 +5255,21 @@ void sculpt_dyntopo_node_layers_add(SculptSession *ss) } -void sculpt_update_after_dynamic_topology_toggle(bContext *C) +void sculpt_update_after_dynamic_topology_toggle( + const EvaluationContext *eval_ctx, + Scene *scene, Object *ob) { - Scene *scene = CTX_data_scene(C); - Object *ob = CTX_data_active_object(C); - EvaluationContext eval_ctx; Sculpt *sd = scene->toolsettings->sculpt; - CTX_data_eval_ctx(C, &eval_ctx); - /* Create the PBVH */ - BKE_sculpt_update_mesh_elements(&eval_ctx, scene, sd, ob, false, false); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); + BKE_sculpt_update_mesh_elements(eval_ctx, scene, sd, ob, false, false); + WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob); } -void sculpt_dynamic_topology_enable(bContext *C) +void sculpt_dynamic_topology_enable_ex( + const EvaluationContext *eval_ctx, + Scene *scene, Object *ob) { - Scene *scene = CTX_data_scene(C); - Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; Mesh *me = ob->data; const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me); @@ -5308,17 +5305,17 @@ void sculpt_dynamic_topology_enable(bContext *C) ss->bm_log = BM_log_create(ss->bm); /* Refresh */ - sculpt_update_after_dynamic_topology_toggle(C); + sculpt_update_after_dynamic_topology_toggle(eval_ctx, scene, ob); } /* Free the sculpt BMesh and BMLog * * If 'unode' is given, the BMesh's data is copied out to the unode * before the BMesh is deleted so that it can be restored from */ -void sculpt_dynamic_topology_disable(bContext *C, - SculptUndoNode *unode) +void sculpt_dynamic_topology_disable_ex( + const EvaluationContext *eval_ctx, + Scene *scene, Object *ob, SculptUndoNode *unode) { - Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; Mesh *me = ob->data; @@ -5367,28 +5364,59 @@ void sculpt_dynamic_topology_disable(bContext *C, } /* Refresh */ - sculpt_update_after_dynamic_topology_toggle(C); + sculpt_update_after_dynamic_topology_toggle(eval_ctx, scene, ob); } +void sculpt_dynamic_topology_disable(bContext *C, SculptUndoNode *unode) +{ + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_active_object(C); + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + sculpt_dynamic_topology_disable_ex(&eval_ctx, scene, ob, unode); +} + +static void sculpt_dynamic_topology_disable_with_undo( + const EvaluationContext *eval_ctx, Scene *scene, Object *ob) +{ + SculptSession *ss = ob->sculpt; + if (ss->bm) { + sculpt_undo_push_begin("Dynamic topology disable"); + sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_END); + sculpt_dynamic_topology_disable_ex(eval_ctx, scene, ob, NULL); + sculpt_undo_push_end(); + } +} + +static void sculpt_dynamic_topology_enable_with_undo( + const EvaluationContext *eval_ctx, + Scene *scene, Object *ob) +{ + SculptSession *ss = ob->sculpt; + if (ss->bm == NULL) { + sculpt_undo_push_begin("Dynamic topology enable"); + sculpt_dynamic_topology_enable_ex(eval_ctx, scene, ob); + sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN); + sculpt_undo_push_end(); + } +} static int sculpt_dynamic_topology_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { + Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); WM_cursor_wait(1); if (ss->bm) { - sculpt_undo_push_begin("Dynamic topology disable"); - sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_END); - sculpt_dynamic_topology_disable(C, NULL); + sculpt_dynamic_topology_disable_with_undo(&eval_ctx, scene, ob); } else { - sculpt_undo_push_begin("Dynamic topology enable"); - sculpt_dynamic_topology_enable(C); - sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN); + sculpt_dynamic_topology_enable_with_undo(&eval_ctx, scene, ob); } - sculpt_undo_push_end(C); WM_cursor_wait(0); @@ -5576,7 +5604,7 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op)) /* Finish undo */ BM_log_all_added(ss->bm, ss->bm_log); - sculpt_undo_push_end(C); + sculpt_undo_push_end(); /* Redraw */ sculpt_pbvh_clear(ob); @@ -5605,9 +5633,61 @@ static void sculpt_init_session(const EvaluationContext *eval_ctx, Scene *scene, BKE_sculpt_toolsettings_data_ensure(scene); ob->sculpt = MEM_callocN(sizeof(SculptSession), "sculpt session"); + ob->sculpt->mode_type = OB_MODE_SCULPT; BKE_sculpt_update_mesh_elements(eval_ctx, scene, scene->toolsettings->sculpt, ob, 0, false); } +void ED_object_sculptmode_exit_ex( + const EvaluationContext *eval_ctx, + WorkSpace *workspace, Scene *scene, Object *ob) +{ + const int mode_flag = OB_MODE_SCULPT; + Mesh *me = BKE_mesh_from_object(ob); + + MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob); + if (mmd) { + multires_force_update(ob); + } + + /* Always for now, so leaving sculpt mode always ensures scene is in + * a consistent state. + */ + if (true || /* flush_recalc || */ (ob->sculpt && ob->sculpt->bm)) { + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); + } + + if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) { + /* Dynamic topology must be disabled before exiting sculpt + * mode to ensure the undo stack stays in a consistent + * state */ + sculpt_dynamic_topology_disable_with_undo(eval_ctx, scene, ob); + + /* store so we know to re-enable when entering sculpt mode */ + me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY; + } + + /* Leave sculptmode */ + workspace->object_mode &= ~mode_flag; + + BKE_sculptsession_free(ob); + + paint_cursor_delete_textures(); + + /* VBO no longer valid */ + if (ob->derivedFinal) { + GPU_drawobject_free(ob->derivedFinal); + } +} + +void ED_object_sculptmode_exit(bContext *C) +{ + WorkSpace *workspace = CTX_wm_workspace(C); + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_active_object(C); + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + ED_object_sculptmode_exit_ex(&eval_ctx, workspace, scene, ob); +} static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) { @@ -5634,32 +5714,9 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) flush_recalc |= sculpt_has_active_modifiers(scene, ob); if (is_mode_set) { - if (mmd) - multires_force_update(ob); - - /* Always for now, so leaving sculpt mode always ensures scene is in - * a consistent state. - */ - if (true || flush_recalc || (ob->sculpt && ob->sculpt->bm)) { - DEG_id_tag_update(&ob->id, OB_RECALC_DATA); - } - - if (me->flag & ME_SCULPT_DYNAMIC_TOPOLOGY) { - /* Dynamic topology must be disabled before exiting sculpt - * mode to ensure the undo stack stays in a consistent - * state */ - sculpt_dynamic_topology_toggle_exec(C, NULL); - - /* store so we know to re-enable when entering sculpt mode */ - me->flag |= ME_SCULPT_DYNAMIC_TOPOLOGY; - } - - /* Leave sculptmode */ - workspace->object_mode &= ~mode_flag; - - BKE_sculptsession_free(ob); - - paint_cursor_delete_textures(); + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + ED_object_sculptmode_exit_ex(&eval_ctx, workspace, scene, ob); } else { /* Enter sculptmode */ @@ -5732,7 +5789,7 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) if (message_unsupported == NULL) { /* undo push is needed to prevent memory leak */ sculpt_undo_push_begin("Dynamic topology enable"); - sculpt_dynamic_topology_enable(C); + sculpt_dynamic_topology_enable_ex(&eval_ctx, scene, ob); sculpt_undo_push_node(ob, NULL, SCULPT_UNDO_DYNTOPO_BEGIN); } else { @@ -5742,10 +5799,12 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY; } } - } - if (ob->derivedFinal) /* VBO no longer valid */ - GPU_drawobject_free(ob->derivedFinal); + /* VBO no longer valid */ + if (ob->derivedFinal) { + GPU_drawobject_free(ob->derivedFinal); + } + } WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene); @@ -5815,7 +5874,7 @@ static int sculpt_detail_flood_fill_exec(bContext *C, wmOperator *UNUSED(op)) } MEM_freeN(nodes); - sculpt_undo_push_end(C); + sculpt_undo_push_end(); /* force rebuild of pbvh for better BB placement */ sculpt_pbvh_clear(ob); diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 5fb9eee805f..54cdbb18693 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -60,10 +60,19 @@ bool sculpt_stroke_get_location(struct bContext *C, float out[3], const float mo /* Dynamic topology */ void sculpt_pbvh_clear(Object *ob); void sculpt_dyntopo_node_layers_add(struct SculptSession *ss); -void sculpt_update_after_dynamic_topology_toggle(struct bContext *C); -void sculpt_dynamic_topology_enable(struct bContext *C); -void sculpt_dynamic_topology_disable(struct bContext *C, - struct SculptUndoNode *unode); +void sculpt_update_after_dynamic_topology_toggle( + const struct EvaluationContext *eval_ctx, + struct Scene *scene, struct Object *ob); +void sculpt_dynamic_topology_enable_ex( + const struct EvaluationContext *eval_ctx, + struct Scene *scene, struct Object *ob); +void sculpt_dynamic_topology_enable(bContext *C); + +void sculpt_dynamic_topology_disable_ex( + const struct EvaluationContext *eval_ctx, + struct Scene *scene, struct Object *ob, + struct SculptUndoNode *unode); +void sculpt_dynamic_topology_disable(bContext *C, struct SculptUndoNode *unode); /* Undo */ @@ -342,7 +351,7 @@ void sculpt_cache_free(StrokeCache *cache); SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, SculptUndoType type); SculptUndoNode *sculpt_undo_get_node(PBVHNode *node); void sculpt_undo_push_begin(const char *name); -void sculpt_undo_push_end(const struct bContext *C); +void sculpt_undo_push_end(void); void sculpt_vertcos_to_key(Object *ob, KeyBlock *kb, float (*vertCos)[3]); diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index c304ed1f02f..55950a51fba 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -964,7 +964,7 @@ void sculpt_undo_push_begin(const char *name) sculpt_undo_restore, sculpt_undo_free, sculpt_undo_cleanup); } -void sculpt_undo_push_end(const bContext *C) +void sculpt_undo_push_end(void) { ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_MESH); SculptUndoNode *unode; @@ -982,5 +982,5 @@ void sculpt_undo_push_end(const bContext *C) ED_undo_paint_push_end(UNDO_PAINT_MESH); - WM_file_tag_modified(C); + WM_file_tag_modified(); } diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c index 64055b46431..3a2d67c8703 100644 --- a/source/blender/editors/util/undo.c +++ b/source/blender/editors/util/undo.c @@ -117,7 +117,7 @@ void ED_undo_push(bContext *C, const char *str) BKE_undo_write(C, str); } - WM_file_tag_modified(C); + WM_file_tag_modified(); } /* note: also check undo_history_exec() in bottom if you change notifiers */ diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 50efc4d3252..7e2dead52ee 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -141,7 +141,7 @@ void WM_file_autoexec_init(const char *filepath); bool WM_file_read(struct bContext *C, const char *filepath, struct ReportList *reports); void WM_autosave_init(struct wmWindowManager *wm); void WM_recover_last_session(struct bContext *C, struct ReportList *reports); -void WM_file_tag_modified(const struct bContext *C); +void WM_file_tag_modified(void); void WM_lib_reload(struct Library *lib, struct bContext *C, struct ReportList *reports); diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 0056ef06a29..98606379a61 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -1363,13 +1363,13 @@ void wm_open_init_use_scripts(wmOperator *op, bool use_prefs) /** \} */ -void WM_file_tag_modified(const bContext *C) +void WM_file_tag_modified(void) { - wmWindowManager *wm = CTX_wm_manager(C); + wmWindowManager *wm = G.main->wm.first; if (wm->file_saved) { wm->file_saved = 0; /* notifier that data changed, for save-over warning or header */ - WM_event_add_notifier(C, NC_WM | ND_DATACHANGED, NULL); + WM_main_add_notifier(NC_WM | ND_DATACHANGED, NULL); } } -- cgit v1.2.3