Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/sculpt_paint/sculpt_undo.c
| Show First 20 Lines • Show All 121 Lines • ▼ Show 20 Lines | if (test_swap_v3_v3(coord, unode->orig_co[uindex])) { | ||||
| copy_v3_v3(unode->co[uindex], ss->deform_cos[oindex]); | copy_v3_v3(unode->co[uindex], ss->deform_cos[oindex]); | ||||
| return true; | return true; | ||||
| } | } | ||||
| else { | else { | ||||
| return false; | return false; | ||||
| } | } | ||||
| } | } | ||||
| static bool sculpt_undo_restore_coords(bContext *C, SculptUndoNode *unode) | static bool sculpt_undo_restore_coords(bContext *C, Depsgraph *depsgraph, SculptUndoNode *unode) | ||||
| { | { | ||||
| ViewLayer *view_layer = CTX_data_view_layer(C); | ViewLayer *view_layer = CTX_data_view_layer(C); | ||||
| Object *ob = OBACT(view_layer); | Object *ob = OBACT(view_layer); | ||||
| Depsgraph *depsgraph = CTX_data_depsgraph(C); | |||||
| SculptSession *ss = ob->sculpt; | SculptSession *ss = ob->sculpt; | ||||
| SubdivCCG *subdiv_ccg = ss->subdiv_ccg; | SubdivCCG *subdiv_ccg = ss->subdiv_ccg; | ||||
| MVert *mvert; | MVert *mvert; | ||||
| int *index; | int *index; | ||||
| if (unode->maxvert) { | if (unode->maxvert) { | ||||
| /* regular mesh restore */ | /* regular mesh restore */ | ||||
| if (ss->kb && !STREQ(ss->kb->name, unode->shapeName)) { | if (ss->kb && !STREQ(ss->kb->name, unode->shapeName)) { | ||||
| /* shape key has been changed before calling undo operator */ | /* shape key has been changed before calling undo operator */ | ||||
| Key *key = BKE_key_from_object(ob); | Key *key = BKE_key_from_object(ob); | ||||
| KeyBlock *kb = key ? BKE_keyblock_find_name(key, unode->shapeName) : NULL; | KeyBlock *kb = key ? BKE_keyblock_find_name(key, unode->shapeName) : NULL; | ||||
| if (kb) { | if (kb) { | ||||
| ob->shapenr = BLI_findindex(&key->block, kb) + 1; | ob->shapenr = BLI_findindex(&key->block, kb) + 1; | ||||
| BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false); | BKE_sculpt_update_object_for_edit(depsgraph, ob, false, false); | ||||
brecht: I don't think depsgraph evaluation should ever happen in undo code? | |||||
Done Inline ActionsWith the current code in BKE_sculpt_update_object_for_edit() this is unavoidable. sergey: With the current code in `BKE_sculpt_update_object_for_edit()` this is unavoidable. | |||||
| WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob); | WM_event_add_notifier(C, NC_OBJECT | ND_DATA, ob); | ||||
| } | } | ||||
| else { | else { | ||||
| /* key has been removed -- skip this undo node */ | /* key has been removed -- skip this undo node */ | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 289 Lines • ▼ Show 20 Lines | default: | ||||
| return true; | return true; | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| static void sculpt_undo_restore_list(bContext *C, ListBase *lb) | static void sculpt_undo_restore_list(bContext *C, Depsgraph *depsgraph, ListBase *lb) | ||||
| { | { | ||||
| 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); | ||||
| View3D *v3d = CTX_wm_view3d(C); | View3D *v3d = CTX_wm_view3d(C); | ||||
| Object *ob = OBACT(view_layer); | Object *ob = OBACT(view_layer); | ||||
| Depsgraph *depsgraph = CTX_data_depsgraph(C); | |||||
| SculptSession *ss = ob->sculpt; | SculptSession *ss = ob->sculpt; | ||||
Not Done Inline ActionsSame comment. brecht: Same comment. | |||||
Done Inline ActionsSame answer. sergey: Same answer. | |||||
| SubdivCCG *subdiv_ccg = ss->subdiv_ccg; | SubdivCCG *subdiv_ccg = ss->subdiv_ccg; | ||||
| SculptUndoNode *unode; | SculptUndoNode *unode; | ||||
| bool update = false, rebuild = false; | bool update = false, rebuild = false; | ||||
| bool need_mask = false; | bool need_mask = false; | ||||
| bool partial_update = true; | bool partial_update = true; | ||||
| for (unode = lb->first; unode; unode = unode->next) { | for (unode = lb->first; unode; unode = unode->next) { | ||||
| if (STREQ(unode->idname, ob->id.name)) { | if (STREQ(unode->idname, ob->id.name)) { | ||||
| Show All 33 Lines | else if (unode->maxgrid && subdiv_ccg != NULL) { | ||||
| } | } | ||||
| /* multi-res can't do partial updates since it doesn't flag edited vertices */ | /* multi-res can't do partial updates since it doesn't flag edited vertices */ | ||||
| partial_update = false; | partial_update = false; | ||||
| } | } | ||||
| switch (unode->type) { | switch (unode->type) { | ||||
| case SCULPT_UNDO_COORDS: | case SCULPT_UNDO_COORDS: | ||||
| if (sculpt_undo_restore_coords(C, unode)) { | if (sculpt_undo_restore_coords(C, depsgraph, unode)) { | ||||
| update = true; | update = true; | ||||
| } | } | ||||
| break; | break; | ||||
| case SCULPT_UNDO_HIDDEN: | case SCULPT_UNDO_HIDDEN: | ||||
| if (sculpt_undo_restore_hidden(C, unode)) { | if (sculpt_undo_restore_hidden(C, unode)) { | ||||
| rebuild = true; | rebuild = true; | ||||
| } | } | ||||
| break; | break; | ||||
| ▲ Show 20 Lines • Show All 533 Lines • ▼ Show 20 Lines | static bool sculpt_undosys_step_encode(struct bContext *UNUSED(C), | ||||
| SculptUndoNode *unode = us->data.nodes.last; | SculptUndoNode *unode = us->data.nodes.last; | ||||
| if (unode && unode->type == SCULPT_UNDO_DYNTOPO_END) { | if (unode && unode->type == SCULPT_UNDO_DYNTOPO_END) { | ||||
| us->step.use_memfile_step = true; | us->step.use_memfile_step = true; | ||||
| } | } | ||||
| us->step.is_applied = true; | us->step.is_applied = true; | ||||
| return true; | return true; | ||||
| } | } | ||||
| static void sculpt_undosys_step_decode_undo_impl(struct bContext *C, SculptUndoStep *us) | static void sculpt_undosys_step_decode_undo_impl(struct bContext *C, | ||||
| Depsgraph *depsgraph, | |||||
| SculptUndoStep *us) | |||||
| { | { | ||||
| BLI_assert(us->step.is_applied == true); | BLI_assert(us->step.is_applied == true); | ||||
| sculpt_undo_restore_list(C, &us->data.nodes); | sculpt_undo_restore_list(C, depsgraph, &us->data.nodes); | ||||
| us->step.is_applied = false; | us->step.is_applied = false; | ||||
| } | } | ||||
| static void sculpt_undosys_step_decode_redo_impl(struct bContext *C, SculptUndoStep *us) | static void sculpt_undosys_step_decode_redo_impl(struct bContext *C, | ||||
| Depsgraph *depsgraph, | |||||
| SculptUndoStep *us) | |||||
| { | { | ||||
| BLI_assert(us->step.is_applied == false); | BLI_assert(us->step.is_applied == false); | ||||
| sculpt_undo_restore_list(C, &us->data.nodes); | sculpt_undo_restore_list(C, depsgraph, &us->data.nodes); | ||||
| us->step.is_applied = true; | us->step.is_applied = true; | ||||
| } | } | ||||
| static void sculpt_undosys_step_decode_undo(struct bContext *C, SculptUndoStep *us) | static void sculpt_undosys_step_decode_undo(struct bContext *C, | ||||
| Depsgraph *depsgraph, | |||||
| SculptUndoStep *us) | |||||
| { | { | ||||
| SculptUndoStep *us_iter = us; | SculptUndoStep *us_iter = us; | ||||
| while (us_iter->step.next && (us_iter->step.next->type == us_iter->step.type)) { | while (us_iter->step.next && (us_iter->step.next->type == us_iter->step.type)) { | ||||
| if (us_iter->step.next->is_applied == false) { | if (us_iter->step.next->is_applied == false) { | ||||
| break; | break; | ||||
| } | } | ||||
| us_iter = (SculptUndoStep *)us_iter->step.next; | us_iter = (SculptUndoStep *)us_iter->step.next; | ||||
| } | } | ||||
| while (us_iter != us) { | while (us_iter != us) { | ||||
| sculpt_undosys_step_decode_undo_impl(C, us_iter); | sculpt_undosys_step_decode_undo_impl(C, depsgraph, us_iter); | ||||
| us_iter = (SculptUndoStep *)us_iter->step.prev; | us_iter = (SculptUndoStep *)us_iter->step.prev; | ||||
| } | } | ||||
| } | } | ||||
| static void sculpt_undosys_step_decode_redo(struct bContext *C, SculptUndoStep *us) | static void sculpt_undosys_step_decode_redo(struct bContext *C, | ||||
| Depsgraph *depsgraph, | |||||
| SculptUndoStep *us) | |||||
| { | { | ||||
| SculptUndoStep *us_iter = us; | SculptUndoStep *us_iter = us; | ||||
| while (us_iter->step.prev && (us_iter->step.prev->type == us_iter->step.type)) { | while (us_iter->step.prev && (us_iter->step.prev->type == us_iter->step.type)) { | ||||
| if (us_iter->step.prev->is_applied == true) { | if (us_iter->step.prev->is_applied == true) { | ||||
| break; | break; | ||||
| } | } | ||||
| us_iter = (SculptUndoStep *)us_iter->step.prev; | us_iter = (SculptUndoStep *)us_iter->step.prev; | ||||
| } | } | ||||
| while (us_iter && (us_iter->step.is_applied == false)) { | while (us_iter && (us_iter->step.is_applied == false)) { | ||||
| sculpt_undosys_step_decode_redo_impl(C, us_iter); | sculpt_undosys_step_decode_redo_impl(C, depsgraph, us_iter); | ||||
| if (us_iter == us) { | if (us_iter == us) { | ||||
| break; | break; | ||||
| } | } | ||||
| us_iter = (SculptUndoStep *)us_iter->step.next; | us_iter = (SculptUndoStep *)us_iter->step.next; | ||||
| } | } | ||||
| } | } | ||||
| static void sculpt_undosys_step_decode( | static void sculpt_undosys_step_decode( | ||||
| struct bContext *C, struct Main *bmain, UndoStep *us_p, int dir, bool UNUSED(is_final)) | struct bContext *C, struct Main *bmain, UndoStep *us_p, int dir, bool UNUSED(is_final)) | ||||
| { | { | ||||
| Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); | |||||
| /* Ensure sculpt mode. */ | /* Ensure sculpt mode. */ | ||||
| { | { | ||||
| 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); | ||||
| /* Sculpt needs evaluated state. */ | /* Sculpt needs evaluated state. */ | ||||
| BKE_scene_view_layer_graph_evaluated_ensure(bmain, scene, view_layer); | BKE_scene_view_layer_graph_evaluated_ensure(bmain, scene, view_layer); | ||||
| Object *ob = OBACT(view_layer); | Object *ob = OBACT(view_layer); | ||||
| if (ob && (ob->type == OB_MESH)) { | if (ob && (ob->type == OB_MESH)) { | ||||
| Depsgraph *depsgraph = CTX_data_depsgraph(C); | |||||
| if (ob->mode & OB_MODE_SCULPT) { | if (ob->mode & OB_MODE_SCULPT) { | ||||
| /* pass */ | /* pass */ | ||||
| } | } | ||||
| else { | else { | ||||
| ED_object_mode_generic_exit(bmain, depsgraph, scene, ob); | ED_object_mode_generic_exit(bmain, depsgraph, scene, ob); | ||||
Not Done Inline ActionsSame comment. brecht: Same comment. | |||||
Done Inline ActionsSame answer (ED_object_sculptmode_enter_ex -> sculpt_init_session -> BKE_sculpt_update_object_for_edit). sergey: Same answer (`ED_object_sculptmode_enter_ex` -> `sculpt_init_session` ->… | |||||
| Mesh *me = ob->data; | Mesh *me = ob->data; | ||||
| /* Don't add sculpt topology undo steps when reading back undo state. | /* Don't add sculpt topology undo steps when reading back undo state. | ||||
| * The undo steps must enter/exit for us. */ | * The undo steps must enter/exit for us. */ | ||||
| me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY; | me->flag &= ~ME_SCULPT_DYNAMIC_TOPOLOGY; | ||||
| ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, true, NULL); | ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, true, NULL); | ||||
| } | } | ||||
| BLI_assert(sculpt_undosys_poll(C)); | BLI_assert(sculpt_undosys_poll(C)); | ||||
| } | } | ||||
| else { | else { | ||||
| BLI_assert(0); | BLI_assert(0); | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| SculptUndoStep *us = (SculptUndoStep *)us_p; | SculptUndoStep *us = (SculptUndoStep *)us_p; | ||||
| if (dir < 0) { | if (dir < 0) { | ||||
| sculpt_undosys_step_decode_undo(C, us); | sculpt_undosys_step_decode_undo(C, depsgraph, us); | ||||
| } | } | ||||
| else { | else { | ||||
| sculpt_undosys_step_decode_redo(C, us); | sculpt_undosys_step_decode_redo(C, depsgraph, us); | ||||
| } | } | ||||
| } | } | ||||
| static void sculpt_undosys_step_free(UndoStep *us_p) | static void sculpt_undosys_step_free(UndoStep *us_p) | ||||
| { | { | ||||
| SculptUndoStep *us = (SculptUndoStep *)us_p; | SculptUndoStep *us = (SculptUndoStep *)us_p; | ||||
| sculpt_undo_free_list(&us->data.nodes); | sculpt_undo_free_list(&us->data.nodes); | ||||
| } | } | ||||
| Show All 36 Lines | |||||
I don't think depsgraph evaluation should ever happen in undo code?