diff options
-rw-r--r-- | core/multiplayer/multiplayer_replicator.cpp | 2 | ||||
-rw-r--r-- | core/object/undo_redo.cpp | 59 | ||||
-rw-r--r-- | core/object/undo_redo.h | 5 | ||||
-rw-r--r-- | doc/classes/UndoRedo.xml | 14 | ||||
-rw-r--r-- | modules/gdscript/gdscript_analyzer.cpp | 4 | ||||
-rw-r--r-- | modules/gdscript/tests/scripts/analyzer/errors/setter_parameter_uses_property_type.gd | 8 | ||||
-rw-r--r-- | modules/gdscript/tests/scripts/analyzer/errors/setter_parameter_uses_property_type.out | 2 |
7 files changed, 79 insertions, 15 deletions
diff --git a/core/multiplayer/multiplayer_replicator.cpp b/core/multiplayer/multiplayer_replicator.cpp index a4ea74327c..6604510394 100644 --- a/core/multiplayer/multiplayer_replicator.cpp +++ b/core/multiplayer/multiplayer_replicator.cpp @@ -572,7 +572,7 @@ Error MultiplayerReplicator::_spawn_despawn(ResourceUID::ID p_scene_id, Object * args[0] = p_peer; args[1] = p_scene_id; args[2] = p_obj; - args[3] = true; + args[3] = p_spawn; const Variant *argp[] = { &args[0], &args[1], &args[2], &args[3] }; Callable::CallError ce; Variant ret; diff --git a/core/object/undo_redo.cpp b/core/object/undo_redo.cpp index b7d2bac96d..905bb587a8 100644 --- a/core/object/undo_redo.cpp +++ b/core/object/undo_redo.cpp @@ -32,6 +32,7 @@ #include "core/io/resource.h" #include "core/os/os.h" +#include "core/templates/local_vector.h" void UndoRedo::_discard_redo() { if (current_action == actions.size() - 1) { @@ -85,10 +86,17 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) { current_action = actions.size() - 2; if (p_mode == MERGE_ENDS) { - // Clear all do ops from last action, and delete all object references - List<Operation>::Element *E = actions.write[current_action + 1].do_ops.front(); + // Clear all do ops from last action if they are not forced kept + LocalVector<List<Operation>::Element *> to_remove; + for (List<Operation>::Element *E = actions.write[current_action + 1].do_ops.front(); E; E = E->next()) { + if (!E->get().force_keep_in_merge_ends) { + to_remove.push_back(E); + } + } - while (E) { + for (unsigned int i = 0; i < to_remove.size(); i++) { + List<Operation>::Element *E = to_remove[i]; + // Delete all object references if (E->get().type == Operation::TYPE_REFERENCE) { Object *obj = ObjectDB::get_instance(E->get().object); @@ -96,27 +104,34 @@ void UndoRedo::create_action(const String &p_name, MergeMode p_mode) { memdelete(obj); } } - - E = E->next(); - actions.write[current_action + 1].do_ops.pop_front(); + String s = "removed " + E->get().name + ": "; + for (int j = 0; j < VARIANT_ARG_MAX; j++) { + if (E->get().args[j].get_type() == Variant::NIL) { + break; + } + s += String(E->get().args[j]); + } + print_line(s); + E->erase(); } } actions.write[actions.size() - 1].last_tick = ticks; - merge_mode = p_mode; merging = true; } else { Action new_action; new_action.name = p_name; new_action.last_tick = ticks; actions.push_back(new_action); - - merge_mode = MERGE_DISABLE; } + + merge_mode = p_mode; } action_level++; + + force_keep_in_merge_ends = false; } void UndoRedo::add_do_method(Object *p_object, const StringName &p_method, VARIANT_ARG_DECLARE) { @@ -146,7 +161,7 @@ void UndoRedo::add_undo_method(Object *p_object, const StringName &p_method, VAR ERR_FAIL_COND((current_action + 1) >= actions.size()); // No undo if the merge mode is MERGE_ENDS - if (merge_mode == MERGE_ENDS) { + if (!force_keep_in_merge_ends && merge_mode == MERGE_ENDS) { return; } @@ -157,6 +172,7 @@ void UndoRedo::add_undo_method(Object *p_object, const StringName &p_method, VAR } undo_op.type = Operation::TYPE_METHOD; + undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends; undo_op.name = p_method; for (int i = 0; i < VARIANT_ARG_MAX; i++) { @@ -187,7 +203,7 @@ void UndoRedo::add_undo_property(Object *p_object, const StringName &p_property, ERR_FAIL_COND((current_action + 1) >= actions.size()); // No undo if the merge mode is MERGE_ENDS - if (merge_mode == MERGE_ENDS) { + if (!force_keep_in_merge_ends && merge_mode == MERGE_ENDS) { return; } @@ -198,6 +214,7 @@ void UndoRedo::add_undo_property(Object *p_object, const StringName &p_property, } undo_op.type = Operation::TYPE_PROPERTY; + undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends; undo_op.name = p_property; undo_op.args[0] = p_value; actions.write[current_action + 1].undo_ops.push_back(undo_op); @@ -223,7 +240,7 @@ void UndoRedo::add_undo_reference(Object *p_object) { ERR_FAIL_COND((current_action + 1) >= actions.size()); // No undo if the merge mode is MERGE_ENDS - if (merge_mode == MERGE_ENDS) { + if (!force_keep_in_merge_ends && merge_mode == MERGE_ENDS) { return; } @@ -234,9 +251,24 @@ void UndoRedo::add_undo_reference(Object *p_object) { } undo_op.type = Operation::TYPE_REFERENCE; + undo_op.force_keep_in_merge_ends = force_keep_in_merge_ends; actions.write[current_action + 1].undo_ops.push_back(undo_op); } +void UndoRedo::start_force_keep_in_merge_ends() { + ERR_FAIL_COND(action_level <= 0); + ERR_FAIL_COND((current_action + 1) >= actions.size()); + + force_keep_in_merge_ends = true; +} + +void UndoRedo::end_force_keep_in_merge_ends() { + ERR_FAIL_COND(action_level <= 0); + ERR_FAIL_COND((current_action + 1) >= actions.size()); + + force_keep_in_merge_ends = false; +} + void UndoRedo::_pop_history_tail() { _discard_redo(); @@ -538,6 +570,9 @@ void UndoRedo::_bind_methods() { ClassDB::bind_method(D_METHOD("add_do_reference", "object"), &UndoRedo::add_do_reference); ClassDB::bind_method(D_METHOD("add_undo_reference", "object"), &UndoRedo::add_undo_reference); + ClassDB::bind_method(D_METHOD("start_force_keep_in_merge_ends"), &UndoRedo::start_force_keep_in_merge_ends); + ClassDB::bind_method(D_METHOD("end_force_keep_in_merge_ends"), &UndoRedo::end_force_keep_in_merge_ends); + ClassDB::bind_method(D_METHOD("get_history_count"), &UndoRedo::get_history_count); ClassDB::bind_method(D_METHOD("get_current_action"), &UndoRedo::get_current_action); ClassDB::bind_method(D_METHOD("get_action_name", "id"), &UndoRedo::get_action_name); diff --git a/core/object/undo_redo.h b/core/object/undo_redo.h index d1ce252d86..a757d154e2 100644 --- a/core/object/undo_redo.h +++ b/core/object/undo_redo.h @@ -61,6 +61,7 @@ private: }; Type type; + bool force_keep_in_merge_ends; Ref<RefCounted> ref; ObjectID object; StringName name; @@ -76,6 +77,7 @@ private: Vector<Action> actions; int current_action = -1; + bool force_keep_in_merge_ends = false; int action_level = 0; MergeMode merge_mode = MERGE_DISABLE; bool merging = false; @@ -109,6 +111,9 @@ public: void add_do_reference(Object *p_object); void add_undo_reference(Object *p_object); + void start_force_keep_in_merge_ends(); + void end_force_keep_in_merge_ends(); + bool is_committing_action() const; void commit_action(bool p_execute = true); diff --git a/doc/classes/UndoRedo.xml b/doc/classes/UndoRedo.xml index def6fe5d1f..044460f569 100644 --- a/doc/classes/UndoRedo.xml +++ b/doc/classes/UndoRedo.xml @@ -134,6 +134,12 @@ The way actions are merged is dictated by the [code]merge_mode[/code] argument. See [enum MergeMode] for details. </description> </method> + <method name="end_force_keep_in_merge_ends"> + <return type="void" /> + <description> + Stops marking operations as to be processed even if the action gets merged with another in the [constant MERGE_ENDS] mode. See [method start_force_keep_in_merge_ends]. + </description> + </method> <method name="get_action_name"> <return type="String" /> <argument index="0" name="id" type="int" /> @@ -190,6 +196,12 @@ Redo the last action. </description> </method> + <method name="start_force_keep_in_merge_ends"> + <return type="void" /> + <description> + Marks the next "do" and "undo" operations to be processed even if the action gets merged with another in the [constant MERGE_ENDS] mode. Return to normal operation using [method end_force_keep_in_merge_ends]. + </description> + </method> <method name="undo"> <return type="bool" /> <description> @@ -209,7 +221,7 @@ Makes "do"/"undo" operations stay in separate actions. </constant> <constant name="MERGE_ENDS" value="1" enum="MergeMode"> - Makes so that the action's "do" operation is from the first action created and the "undo" operation is from the last subsequent action with the same name. + Makes so that the action's "undo" operations are from the first action created and the "do" operations are from the last subsequent action with the same name. </constant> <constant name="MERGE_ALL" value="2" enum="MergeMode"> Makes subsequent actions with the same name be merged into one. diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index 9ae8323680..8bd288cf0f 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -894,11 +894,13 @@ void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class) { resolve_function_body(member.variable->getter); } if (member.variable->setter != nullptr) { + resolve_function_signature(member.variable->setter); + if (member.variable->setter->parameters.size() > 0) { member.variable->setter->parameters[0]->datatype_specifier = member.variable->datatype_specifier; + member.variable->setter->parameters[0]->set_datatype(member.get_datatype()); } - resolve_function_signature(member.variable->setter); resolve_function_body(member.variable->setter); } } diff --git a/modules/gdscript/tests/scripts/analyzer/errors/setter_parameter_uses_property_type.gd b/modules/gdscript/tests/scripts/analyzer/errors/setter_parameter_uses_property_type.gd new file mode 100644 index 0000000000..3bbee5f5f7 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/setter_parameter_uses_property_type.gd @@ -0,0 +1,8 @@ +var with_setter := 0: + set(val): + var x: String = val + with_setter = val + +func test(): + with_setter = 1 + print(with_setter) diff --git a/modules/gdscript/tests/scripts/analyzer/errors/setter_parameter_uses_property_type.out b/modules/gdscript/tests/scripts/analyzer/errors/setter_parameter_uses_property_type.out new file mode 100644 index 0000000000..9eb2a42ccd --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/errors/setter_parameter_uses_property_type.out @@ -0,0 +1,2 @@ +GDTEST_ANALYZER_ERROR +Value of type "int" cannot be assigned to a variable of type "String". |