diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp index d6d32ccaef..99740b365c 100644 --- a/core/undo_redo.cpp +++ b/core/undo_redo.cpp @@ -52,26 +52,46 @@ void UndoRedo::_discard_redo() { } - -void UndoRedo::create_action(const String& p_name,bool p_mergeable) { +void UndoRedo::create_action(const String& p_name,MergeMode p_mode) { if (action_level==0) { _discard_redo(); - if (p_mergeable && actions.size() && actions[actions.size()-1].name==p_name) { - //old will replace new (it's mergeable after all) - // should check references though! + // Check if the merge operation is valid + if (p_mode!=MERGE_DISABLE && actions.size() && actions[actions.size()-1].name==p_name) { + current_action=actions.size()-2; - actions[current_action+1].do_ops.clear(); - //actions[current_action+1].undo_ops.clear(); - no, this is kept - merging=true; + + if (p_mode==MERGE_ENDS) { + + // Clear all do ops from last action, and delete all object references + List::Element *E=actions[current_action+1].do_ops.front(); + + while (E) { + + if (E->get().type==Operation::TYPE_REFERENCE) { + + Object *obj=ObjectDB::get_instance(E->get().object); + + if (obj) + memdelete(obj); + } + + E=E->next(); + actions[current_action+1].do_ops.pop_front(); + } + } + + merge_mode=p_mode; } else { + Action new_action; new_action.name=p_name; actions.push_back(new_action); - merging=false; + + merge_mode=MERGE_DISABLE; } } @@ -102,8 +122,10 @@ void UndoRedo::add_undo_method(Object *p_object,const String& p_method,VARIANT_A VARIANT_ARGPTRS ERR_FAIL_COND(action_level<=0); ERR_FAIL_COND((current_action+1)>=actions.size()); - if (merging) - return; //- no undo if merging + + // No undo if the merge mode is MERGE_ENDS + if (merge_mode==MERGE_ENDS) + return; Operation undo_op; undo_op.object=p_object->get_instance_ID(); @@ -139,6 +161,10 @@ void UndoRedo::add_undo_property(Object *p_object,const String& p_property,const ERR_FAIL_COND(action_level<=0); ERR_FAIL_COND((current_action+1)>=actions.size()); + // No undo if the merge mode is MERGE_ENDS + if (merge_mode==MERGE_ENDS) + return; + Operation undo_op; undo_op.object=p_object->get_instance_ID(); if (p_object->cast_to()) @@ -167,6 +193,11 @@ void UndoRedo::add_undo_reference(Object *p_object) { ERR_FAIL_COND(action_level<=0); ERR_FAIL_COND((current_action+1)>=actions.size()); + + // No undo if the merge mode is MERGE_ENDS + if (merge_mode==MERGE_ENDS) + return; + Operation undo_op; undo_op.object=p_object->get_instance_ID(); if (p_object->cast_to()) @@ -352,7 +383,7 @@ UndoRedo::UndoRedo() { action_level=0; current_action=-1; max_steps=-1; - merging=true; + merge_mode=MERGE_DISABLE; callback=NULL; callback_ud=NULL; @@ -448,7 +479,7 @@ Variant UndoRedo::_add_undo_method(const Variant** p_args, int p_argcount, Varia void UndoRedo::_bind_methods() { - ObjectTypeDB::bind_method(_MD("create_action","name","mergeable"),&UndoRedo::create_action, DEFVAL(false) ); + ObjectTypeDB::bind_method(_MD("create_action","name","merge_mode"),&UndoRedo::create_action, DEFVAL(MERGE_DISABLE) ); ObjectTypeDB::bind_method(_MD("commit_action"),&UndoRedo::commit_action); //ObjectTypeDB::bind_method(_MD("add_do_method","p_object", "p_method", "VARIANT_ARG_LIST"),&UndoRedo::add_do_method); @@ -489,4 +520,8 @@ void UndoRedo::_bind_methods() { ObjectTypeDB::bind_method(_MD("clear_history"),&UndoRedo::clear_history); ObjectTypeDB::bind_method(_MD("get_current_action_name"),&UndoRedo::get_current_action_name); ObjectTypeDB::bind_method(_MD("get_version"),&UndoRedo::get_version); + + BIND_CONSTANT(MERGE_DISABLE); + BIND_CONSTANT(MERGE_ENDS); + BIND_CONSTANT(MERGE_ALL); } diff --git a/core/undo_redo.h b/core/undo_redo.h index 7f63ba9ed6..208eb6ed5e 100644 --- a/core/undo_redo.h +++ b/core/undo_redo.h @@ -41,6 +41,12 @@ class UndoRedo : public Object { OBJ_SAVE_TYPE( UndoRedo ); public: + enum MergeMode { + MERGE_DISABLE, + MERGE_ENDS, + MERGE_ALL + }; + typedef void (*CommitNotifyCallback)(void *p_ud,const String& p_name); Variant _add_do_method(const Variant** p_args, int p_argcount, Variant::CallError& r_error); Variant _add_undo_method(const Variant** p_args, int p_argcount, Variant::CallError& r_error); @@ -76,7 +82,7 @@ private: int current_action; int action_level; int max_steps; - bool merging; + MergeMode merge_mode; uint64_t version; void _pop_history_tail(); @@ -98,7 +104,7 @@ protected: public: - void create_action(const String& p_name="",bool p_mergeable=false); + void create_action(const String& p_name="",MergeMode p_mode=MERGE_DISABLE); void add_do_method(Object *p_object,const String& p_method,VARIANT_ARG_LIST); void add_undo_method(Object *p_object,const String& p_method,VARIANT_ARG_LIST); @@ -128,4 +134,6 @@ public: ~UndoRedo(); }; +VARIANT_ENUM_CAST( UndoRedo::MergeMode ); + #endif // UNDO_REDO_H diff --git a/tools/editor/animation_editor.cpp b/tools/editor/animation_editor.cpp index aa0156b0c0..2f67df1fc3 100644 --- a/tools/editor/animation_editor.cpp +++ b/tools/editor/animation_editor.cpp @@ -316,7 +316,7 @@ public: int existing = animation->track_find_key(track,new_time,true); setting=true; - undo_redo->create_action(TTR("Move Add Key"),false); + undo_redo->create_action(TTR("Move Add Key"),UndoRedo::MERGE_ENDS); Variant val = animation->track_get_key_value(track,key); float trans = animation->track_get_key_transition(track,key); @@ -344,7 +344,7 @@ public: float val = p_value; float prev_val = animation->track_get_key_transition(track,key); setting=true; - undo_redo->create_action(TTR("Anim Change Transition"),true); + undo_redo->create_action(TTR("Anim Change Transition"),UndoRedo::MERGE_ENDS); undo_redo->add_do_method(animation.ptr(),"track_set_key_transition",track,key,val); undo_redo->add_undo_method(animation.ptr(),"track_set_key_transition",track,key,prev_val); undo_redo->add_do_method(this,"_update_obj",animation); @@ -387,7 +387,7 @@ public: } setting=true; - undo_redo->create_action(TTR("Anim Change Value"),true); + undo_redo->create_action(TTR("Anim Change Value"),UndoRedo::MERGE_ENDS); Variant prev = animation->track_get_key_value(track,key); undo_redo->add_do_method(animation.ptr(),"track_set_key_value",track,key,value); undo_redo->add_undo_method(animation.ptr(),"track_set_key_value",track,key,prev); @@ -463,7 +463,11 @@ public: } } - undo_redo->create_action(TTR("Anim Change Call"),mergeable); + if (mergeable) + undo_redo->create_action(TTR("Anim Change Call"),UndoRedo::MERGE_ENDS); + else + undo_redo->create_action(TTR("Anim Change Call")); + Variant prev = animation->track_get_key_value(track,key); setting=true; undo_redo->add_do_method(animation.ptr(),"track_set_key_value",track,key,d_new); @@ -1715,9 +1719,9 @@ void AnimationKeyEditor::_curve_transition_changed(float p_what) { if (selection.size()==0) return; if (selection.size()==1) - undo_redo->create_action(TTR("Edit Node Curve"),true); + undo_redo->create_action(TTR("Edit Node Curve"),UndoRedo::MERGE_ENDS); else - undo_redo->create_action(TTR("Edit Selection Curve"),true); + undo_redo->create_action(TTR("Edit Selection Curve"),UndoRedo::MERGE_ENDS); for(Map::Element *E=selection.front();E;E=E->next()) { diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp index 02a24f8ddb..ec6bdc91d1 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.cpp +++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp @@ -648,7 +648,7 @@ void CanvasItemEditor::_key_move(const Vector2& p_dir, bool p_snap, KeyMoveMODE if (editor_selection->get_selected_node_list().empty()) return; - undo_redo->create_action(TTR("Move Action"),true); + undo_redo->create_action(TTR("Move Action"),UndoRedo::MERGE_ENDS); List &selection = editor_selection->get_selected_node_list(); diff --git a/tools/editor/plugins/color_ramp_editor_plugin.cpp b/tools/editor/plugins/color_ramp_editor_plugin.cpp index cb7f6a1809..4e2045edc6 100644 --- a/tools/editor/plugins/color_ramp_editor_plugin.cpp +++ b/tools/editor/plugins/color_ramp_editor_plugin.cpp @@ -84,7 +84,7 @@ void ColorRampEditorPlugin::_ramp_changed() { if (old_offsets.size()!=new_offsets.size()) ur->create_action(TTR("Add/Remove Color Ramp Point")); else - ur->create_action(TTR("Modify Color Ramp"),true); + ur->create_action(TTR("Modify Color Ramp"),UndoRedo::MERGE_ENDS); ur->add_do_method(this,"undo_redo_color_ramp",new_offsets,new_colors); ur->add_undo_method(this,"undo_redo_color_ramp",old_offsets,old_colors); ur->commit_action(); diff --git a/tools/editor/plugins/shader_graph_editor_plugin.cpp b/tools/editor/plugins/shader_graph_editor_plugin.cpp index 375220051c..815da48e96 100644 --- a/tools/editor/plugins/shader_graph_editor_plugin.cpp +++ b/tools/editor/plugins/shader_graph_editor_plugin.cpp @@ -675,7 +675,7 @@ GraphCurveMapEdit::GraphCurveMapEdit(){ void ShaderGraphView::_scalar_const_changed(double p_value,int p_id) { UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Change Scalar Constant"),true); + ur->create_action(TTR("Change Scalar Constant"),UndoRedo::MERGE_ENDS); ur->add_do_method(graph.ptr(),"scalar_const_node_set_value",type,p_id,p_value); ur->add_undo_method(graph.ptr(),"scalar_const_node_set_value",type,p_id,graph->scalar_const_node_get_value(type,p_id)); ur->add_do_method(this,"_update_graph"); @@ -693,7 +693,7 @@ void ShaderGraphView::_vec_const_changed(double p_value, int p_id,Array p_arr){ } UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Change Vec Constant"),true); + ur->create_action(TTR("Change Vec Constant"),UndoRedo::MERGE_ENDS); ur->add_do_method(graph.ptr(),"vec_const_node_set_value",type,p_id,val); ur->add_undo_method(graph.ptr(),"vec_const_node_set_value",type,p_id,graph->vec_const_node_get_value(type,p_id)); ur->add_do_method(this,"_update_graph"); @@ -706,7 +706,7 @@ void ShaderGraphView::_vec_const_changed(double p_value, int p_id,Array p_arr){ void ShaderGraphView::_rgb_const_changed(const Color& p_color, int p_id){ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Change RGB Constant"),true); + ur->create_action(TTR("Change RGB Constant"),UndoRedo::MERGE_ENDS); ur->add_do_method(graph.ptr(),"rgb_const_node_set_value",type,p_id,p_color); ur->add_undo_method(graph.ptr(),"rgb_const_node_set_value",type,p_id,graph->rgb_const_node_get_value(type,p_id)); ur->add_do_method(this,"_update_graph"); @@ -807,7 +807,7 @@ void ShaderGraphView::_vec_func_changed(int p_func, int p_id){ void ShaderGraphView::_scalar_input_changed(double p_value,int p_id){ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Change Scalar Uniform"),true); + ur->create_action(TTR("Change Scalar Uniform"),UndoRedo::MERGE_ENDS); ur->add_do_method(graph.ptr(),"scalar_input_node_set_value",type,p_id,p_value); ur->add_undo_method(graph.ptr(),"scalar_input_node_set_value",type,p_id,graph->scalar_input_node_get_value(type,p_id)); ur->add_do_method(this,"_update_graph"); @@ -825,7 +825,7 @@ void ShaderGraphView::_vec_input_changed(double p_value, int p_id,Array p_arr){ } UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Change Vec Uniform"),true); + ur->create_action(TTR("Change Vec Uniform"),UndoRedo::MERGE_ENDS); ur->add_do_method(graph.ptr(),"vec_input_node_set_value",type,p_id,val); ur->add_undo_method(graph.ptr(),"vec_input_node_set_value",type,p_id,graph->vec_input_node_get_value(type,p_id)); ur->add_do_method(this,"_update_graph"); @@ -863,7 +863,7 @@ void ShaderGraphView::_rgb_input_changed(const Color& p_color, int p_id){ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); - ur->create_action(TTR("Change RGB Uniform"),true); + ur->create_action(TTR("Change RGB Uniform"),UndoRedo::MERGE_ENDS); ur->add_do_method(graph.ptr(),"rgb_input_node_set_value",type,p_id,p_color); ur->add_undo_method(graph.ptr(),"rgb_input_node_set_value",type,p_id,graph->rgb_input_node_get_value(type,p_id)); ur->add_do_method(this,"_update_graph"); @@ -963,7 +963,7 @@ void ShaderGraphView::_comment_edited(int p_id,Node* p_button) { UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); TextEdit *te=p_button->cast_to(); - ur->create_action(TTR("Change Comment"),true); + ur->create_action(TTR("Change Comment"),UndoRedo::MERGE_ENDS); ur->add_do_method(graph.ptr(),"comment_node_set_text",type,p_id,te->get_text()); ur->add_undo_method(graph.ptr(),"comment_node_set_text",type,p_id,graph->comment_node_get_text(type,p_id)); ur->add_do_method(this,"_update_graph"); @@ -1005,7 +1005,7 @@ void ShaderGraphView::_color_ramp_changed(int p_id,Node* p_ramp) { if (old_offsets.size()!=new_offsets.size()) ur->create_action(TTR("Add/Remove to Color Ramp")); else - ur->create_action(TTR("Modify Color Ramp"),true); + ur->create_action(TTR("Modify Color Ramp"),UndoRedo::MERGE_ENDS); ur->add_do_method(graph.ptr(),"color_ramp_node_set_ramp",type,p_id,new_colors,new_offsets); ur->add_undo_method(graph.ptr(),"color_ramp_node_set_ramp",type,p_id,old_colors,old_offsets); @@ -1041,7 +1041,7 @@ void ShaderGraphView::_curve_changed(int p_id,Node* p_curve) { if (old_points.size()!=new_points.size()) ur->create_action(TTR("Add/Remove to Curve Map")); else - ur->create_action(TTR("Modify Curve Map"),true); + ur->create_action(TTR("Modify Curve Map"),UndoRedo::MERGE_ENDS); ur->add_do_method(graph.ptr(),"curve_map_node_set_points",type,p_id,new_points); ur->add_undo_method(graph.ptr(),"curve_map_node_set_points",type,p_id,old_points); diff --git a/tools/editor/plugins/sprite_frames_editor_plugin.cpp b/tools/editor/plugins/sprite_frames_editor_plugin.cpp index e29a0c8d52..41beaa96a1 100644 --- a/tools/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/tools/editor/plugins/sprite_frames_editor_plugin.cpp @@ -524,7 +524,7 @@ void SpriteFramesEditor::_animation_fps_changed(double p_value) { if (updating) return; - undo_redo->create_action(TTR("Change Animation FPS"),true); + undo_redo->create_action(TTR("Change Animation FPS"),UndoRedo::MERGE_ENDS); undo_redo->add_do_method(frames,"set_animation_speed",edited_anim,p_value); undo_redo->add_undo_method(frames,"set_animation_speed",edited_anim,frames->get_animation_speed(edited_anim)); undo_redo->add_do_method(this,"_update_library",true); diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index 26a49e92f0..58182bcd54 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -3482,7 +3482,7 @@ void PropertyEditor::_edit_set(const String& p_name, const Variant& p_value) { } else { - undo_redo->create_action(TTR("Set")+" "+p_name,true); + undo_redo->create_action(TTR("Set")+" "+p_name,UndoRedo::MERGE_ENDS); undo_redo->add_do_property(obj,p_name,p_value); undo_redo->add_undo_property(obj,p_name,obj->get(p_name)); undo_redo->add_do_method(this,"_changed_callback",obj,p_name);