diff options
Diffstat (limited to 'modules')
21 files changed, 936 insertions, 32 deletions
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp index e785151a6b..ceb6d5a5f0 100644 --- a/modules/gdscript/gdscript_analyzer.cpp +++ b/modules/gdscript/gdscript_analyzer.cpp @@ -1187,12 +1187,28 @@ void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) { } } - if (!list_resolved) { + GDScriptParser::DataType variable_type; + if (list_resolved) { + variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED; + variable_type.kind = GDScriptParser::DataType::BUILTIN; + variable_type.builtin_type = Variant::INT; // Can this ever be a float or something else? + p_for->variable->set_datatype(variable_type); + } else { resolve_node(p_for->list); + if (p_for->list->datatype.has_container_element_type()) { + variable_type = p_for->list->datatype.get_container_element_type(); + variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED; + } else if (p_for->list->datatype.is_typed_container_type()) { + variable_type = p_for->list->datatype.get_typed_container_type(); + variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED; + } else { + // Last resort + // TODO: Must other cases be handled? Must we mark as unsafe? + variable_type.type_source = GDScriptParser::DataType::UNDETECTED; + variable_type.kind = GDScriptParser::DataType::VARIANT; + } } - - // TODO: If list is a typed array, the variable should be an element. - // Also applicable for constant range() (so variable is int or float). + p_for->variable->set_datatype(variable_type); resolve_suite(p_for->loop); p_for->set_datatype(p_for->loop->get_datatype()); @@ -1480,8 +1496,7 @@ void GDScriptAnalyzer::resolve_parameter(GDScriptParser::ParameterNode *p_parame } if (p_parameter->datatype_specifier != nullptr) { - resolve_datatype(p_parameter->datatype_specifier); - result = p_parameter->datatype_specifier->get_datatype(); + result = resolve_datatype(p_parameter->datatype_specifier); result.is_meta_type = false; if (p_parameter->default_value != nullptr) { @@ -1767,6 +1782,15 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig identifier->variable_source->set_datatype(id_type); } } break; + case GDScriptParser::IdentifierNode::FUNCTION_PARAMETER: { + GDScriptParser::DataType id_type = identifier->parameter_source->get_datatype(); + if (!id_type.is_hard_type()) { + id_type = assigned_value_type; + id_type.type_source = GDScriptParser::DataType::INFERRED; + id_type.is_constant = false; + identifier->parameter_source->set_datatype(id_type); + } + } break; case GDScriptParser::IdentifierNode::LOCAL_VARIABLE: { GDScriptParser::DataType id_type = identifier->variable_source->get_datatype(); if (!id_type.is_hard_type()) { @@ -2428,13 +2452,15 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod p_identifier->is_constant = true; p_identifier->reduced_value = result; p_identifier->set_datatype(type_from_variant(result, p_identifier)); - } else { + } else if (base.is_hard_type()) { push_error(vformat(R"(Cannot find constant "%s" on type "%s".)", name, base.to_string()), p_identifier); } } else { switch (base.builtin_type) { case Variant::NIL: { - push_error(vformat(R"(Invalid get index "%s" on base Nil)", name), p_identifier); + if (base.is_hard_type()) { + push_error(vformat(R"(Invalid get index "%s" on base Nil)", name), p_identifier); + } return; } case Variant::DICTIONARY: { @@ -2455,7 +2481,9 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod return; } } - push_error(vformat(R"(Cannot find property "%s" on base "%s".)", name, base.to_string()), p_identifier); + if (base.is_hard_type()) { + push_error(vformat(R"(Cannot find property "%s" on base "%s".)", name, base.to_string()), p_identifier); + } } } } diff --git a/modules/gdscript/gdscript_cache.cpp b/modules/gdscript/gdscript_cache.cpp index 07f50d14dc..8121053245 100644 --- a/modules/gdscript/gdscript_cache.cpp +++ b/modules/gdscript/gdscript_cache.cpp @@ -51,7 +51,9 @@ GDScriptParser *GDScriptParserRef::get_parser() const { Error GDScriptParserRef::raise_status(Status p_new_status) { ERR_FAIL_COND_V(parser == nullptr, ERR_INVALID_DATA); - Error result = OK; + if (result != OK) { + return result; + } while (p_new_status > status) { switch (status) { @@ -86,14 +88,6 @@ Error GDScriptParserRef::raise_status(Status p_new_status) { } } if (result != OK) { - if (parser != nullptr) { - memdelete(parser); - parser = nullptr; - } - if (analyzer != nullptr) { - memdelete(analyzer); - analyzer = nullptr; - } return result; } } diff --git a/modules/gdscript/gdscript_cache.h b/modules/gdscript/gdscript_cache.h index 943638d29f..9fb661d031 100644 --- a/modules/gdscript/gdscript_cache.h +++ b/modules/gdscript/gdscript_cache.h @@ -54,6 +54,7 @@ private: GDScriptParser *parser = nullptr; GDScriptAnalyzer *analyzer = nullptr; Status status = EMPTY; + Error result = OK; String path; friend class GDScriptCache; diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index d555be1e8d..c901d9f68f 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -2592,6 +2592,10 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_subscript(ExpressionNode * subscript->base = p_previous_operand; subscript->index = parse_expression(false); + if (subscript->index == nullptr) { + push_error(R"(Expected expression after "[".)"); + } + pop_multiline(); consume(GDScriptTokenizer::Token::BRACKET_CLOSE, R"(Expected "]" after subscription index.)"); @@ -3587,6 +3591,39 @@ String GDScriptParser::DataType::to_string() const { ERR_FAIL_V_MSG("<unresolved type", "Kind set outside the enum range."); } +static Variant::Type _variant_type_to_typed_array_element_type(Variant::Type p_type) { + switch (p_type) { + case Variant::PACKED_BYTE_ARRAY: + case Variant::PACKED_INT32_ARRAY: + case Variant::PACKED_INT64_ARRAY: + return Variant::INT; + case Variant::PACKED_FLOAT32_ARRAY: + case Variant::PACKED_FLOAT64_ARRAY: + return Variant::FLOAT; + case Variant::PACKED_STRING_ARRAY: + return Variant::STRING; + case Variant::PACKED_VECTOR2_ARRAY: + return Variant::VECTOR2; + case Variant::PACKED_VECTOR3_ARRAY: + return Variant::VECTOR3; + case Variant::PACKED_COLOR_ARRAY: + return Variant::COLOR; + default: + return Variant::NIL; + } +} + +bool GDScriptParser::DataType::is_typed_container_type() const { + return kind == GDScriptParser::DataType::BUILTIN && _variant_type_to_typed_array_element_type(builtin_type) != Variant::NIL; +} + +GDScriptParser::DataType GDScriptParser::DataType::get_typed_container_type() const { + GDScriptParser::DataType type; + type.kind = GDScriptParser::DataType::BUILTIN; + type.builtin_type = _variant_type_to_typed_array_element_type(builtin_type); + return type; +} + /*---------- PRETTY PRINT FOR DEBUG ----------*/ #ifdef DEBUG_ENABLED diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h index 4902f0d4a6..a641c1052d 100644 --- a/modules/gdscript/gdscript_parser.h +++ b/modules/gdscript/gdscript_parser.h @@ -161,6 +161,10 @@ public: container_element_type = nullptr; } + bool is_typed_container_type() const; + + GDScriptParser::DataType get_typed_container_type() const; + bool operator==(const DataType &p_other) const { if (type_source == UNDETECTED || p_other.type_source == UNDETECTED) { return true; // Can be consireded equal for parsing purposes. diff --git a/modules/gdscript/tests/scripts/analyzer/features/auto_inferred_type_dont_error.gd b/modules/gdscript/tests/scripts/analyzer/features/auto_inferred_type_dont_error.gd new file mode 100644 index 0000000000..f64dce26c9 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/auto_inferred_type_dont_error.gd @@ -0,0 +1,9 @@ +func inferred_parameter(param = null): + if param == null: + param = Node.new() + param.name = "Ok" + print(param.name) + param.free() + +func test(): + inferred_parameter() diff --git a/modules/gdscript/tests/scripts/analyzer/features/auto_inferred_type_dont_error.out b/modules/gdscript/tests/scripts/analyzer/features/auto_inferred_type_dont_error.out new file mode 100644 index 0000000000..0e9f482af4 --- /dev/null +++ b/modules/gdscript/tests/scripts/analyzer/features/auto_inferred_type_dont_error.out @@ -0,0 +1,2 @@ +GDTEST_OK +Ok diff --git a/modules/gdscript/tests/scripts/parser/errors/subscript_without_index.gd b/modules/gdscript/tests/scripts/parser/errors/subscript_without_index.gd new file mode 100644 index 0000000000..c30c05e4da --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/subscript_without_index.gd @@ -0,0 +1,3 @@ +func test(): + var array = [1, 2, 3] + array[] = 4 diff --git a/modules/gdscript/tests/scripts/parser/errors/subscript_without_index.out b/modules/gdscript/tests/scripts/parser/errors/subscript_without_index.out new file mode 100644 index 0000000000..7017c7b4aa --- /dev/null +++ b/modules/gdscript/tests/scripts/parser/errors/subscript_without_index.out @@ -0,0 +1,2 @@ +GDTEST_PARSER_ERROR +Expected expression after "[". diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.gd b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.gd new file mode 100644 index 0000000000..c6645c2c34 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.gd @@ -0,0 +1,138 @@ +func test(): + var value + + # null + value = null + print(value == null) + + # bool + value = false + print(value == null) + + # int + value = 0 + print(value == null) + + # float + value = 0.0 + print(value == null) + + # String + value = "" + print(value == null) + + # Vector2 + value = Vector2() + print(value == null) + + # Vector2i + value = Vector2i() + print(value == null) + + # Rect2 + value = Rect2() + print(value == null) + + # Rect2i + value = Rect2i() + print(value == null) + + # Vector3 + value = Vector3() + print(value == null) + + # Vector3i + value = Vector3i() + print(value == null) + + # Transform2D + value = Transform2D() + print(value == null) + + # Plane + value = Plane() + print(value == null) + + # Quaternion + value = Quaternion() + print(value == null) + + # AABB + value = AABB() + print(value == null) + + # Basis + value = Basis() + print(value == null) + + # Transform3D + value = Transform3D() + print(value == null) + + # Color + value = Color() + print(value == null) + + # StringName + value = &"" + print(value == null) + + # NodePath + value = ^"" + print(value == null) + + # RID + value = RID() + print(value == null) + + # Callable + value = Callable() + print(value == null) + + # Signal + value = Signal() + print(value == null) + + # Dictionary + value = {} + print(value == null) + + # Array + value = [] + print(value == null) + + # PackedByteArray + value = PackedByteArray() + print(value == null) + + # PackedInt32Array + value = PackedInt32Array() + print(value == null) + + # PackedInt64Array + value = PackedInt64Array() + print(value == null) + + # PackedFloat32Array + value = PackedFloat32Array() + print(value == null) + + # PackedFloat64Array + value = PackedFloat64Array() + print(value == null) + + # PackedStringArray + value = PackedStringArray() + print(value == null) + + # PackedVector2Array + value = PackedVector2Array() + print(value == null) + + # PackedVector3Array + value = PackedVector3Array() + print(value == null) + + # PackedColorArray + value = PackedColorArray() + print(value == null) diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.out b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.out new file mode 100644 index 0000000000..639f6027b9 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-equals-null.out @@ -0,0 +1,35 @@ +GDTEST_OK +true +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.gd b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.gd new file mode 100644 index 0000000000..ee622bf22f --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.gd @@ -0,0 +1,138 @@ +func test(): + var value + + # null + value = null + print(value != null) + + # bool + value = false + print(value != null) + + # int + value = 0 + print(value != null) + + # float + value = 0.0 + print(value != null) + + # String + value = "" + print(value != null) + + # Vector2 + value = Vector2() + print(value != null) + + # Vector2i + value = Vector2i() + print(value != null) + + # Rect2 + value = Rect2() + print(value != null) + + # Rect2i + value = Rect2i() + print(value != null) + + # Vector3 + value = Vector3() + print(value != null) + + # Vector3i + value = Vector3i() + print(value != null) + + # Transform2D + value = Transform2D() + print(value != null) + + # Plane + value = Plane() + print(value != null) + + # Quaternion + value = Quaternion() + print(value != null) + + # AABB + value = AABB() + print(value != null) + + # Basis + value = Basis() + print(value != null) + + # Transform3D + value = Transform3D() + print(value != null) + + # Color + value = Color() + print(value != null) + + # StringName + value = &"" + print(value != null) + + # NodePath + value = ^"" + print(value != null) + + # RID + value = RID() + print(value != null) + + # Callable + value = Callable() + print(value != null) + + # Signal + value = Signal() + print(value != null) + + # Dictionary + value = {} + print(value != null) + + # Array + value = [] + print(value != null) + + # PackedByteArray + value = PackedByteArray() + print(value != null) + + # PackedInt32Array + value = PackedInt32Array() + print(value != null) + + # PackedInt64Array + value = PackedInt64Array() + print(value != null) + + # PackedFloat32Array + value = PackedFloat32Array() + print(value != null) + + # PackedFloat64Array + value = PackedFloat64Array() + print(value != null) + + # PackedStringArray + value = PackedStringArray() + print(value != null) + + # PackedVector2Array + value = PackedVector2Array() + print(value != null) + + # PackedVector3Array + value = PackedVector3Array() + print(value != null) + + # PackedColorArray + value = PackedColorArray() + print(value != null) diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.out b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.out new file mode 100644 index 0000000000..d1e332afba --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/compare-builtin-not-equals-null.out @@ -0,0 +1,35 @@ +GDTEST_OK +false +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-null-equals-builtin.gd b/modules/gdscript/tests/scripts/runtime/features/compare-null-equals-builtin.gd new file mode 100644 index 0000000000..7649062fda --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/compare-null-equals-builtin.gd @@ -0,0 +1,138 @@ +func test(): + var value + + # null + value = null + print(null == value) + + # bool + value = false + print(null == value) + + # int + value = 0 + print(null == value) + + # float + value = 0.0 + print(null == value) + + # String + value = "" + print(null == value) + + # Vector2 + value = Vector2() + print(null == value) + + # Vector2i + value = Vector2i() + print(null == value) + + # Rect2 + value = Rect2() + print(null == value) + + # Rect2i + value = Rect2i() + print(null == value) + + # Vector3 + value = Vector3() + print(null == value) + + # Vector3i + value = Vector3i() + print(null == value) + + # Transform2D + value = Transform2D() + print(null == value) + + # Plane + value = Plane() + print(null == value) + + # Quaternion + value = Quaternion() + print(null == value) + + # AABB + value = AABB() + print(null == value) + + # Basis + value = Basis() + print(null == value) + + # Transform3D + value = Transform3D() + print(null == value) + + # Color + value = Color() + print(null == value) + + # StringName + value = &"" + print(null == value) + + # NodePath + value = ^"" + print(null == value) + + # RID + value = RID() + print(null == value) + + # Callable + value = Callable() + print(null == value) + + # Signal + value = Signal() + print(null == value) + + # Dictionary + value = {} + print(null == value) + + # Array + value = [] + print(null == value) + + # PackedByteArray + value = PackedByteArray() + print(null == value) + + # PackedInt32Array + value = PackedInt32Array() + print(null == value) + + # PackedInt64Array + value = PackedInt64Array() + print(null == value) + + # PackedFloat32Array + value = PackedFloat32Array() + print(null == value) + + # PackedFloat64Array + value = PackedFloat64Array() + print(null == value) + + # PackedStringArray + value = PackedStringArray() + print(null == value) + + # PackedVector2Array + value = PackedVector2Array() + print(null == value) + + # PackedVector3Array + value = PackedVector3Array() + print(null == value) + + # PackedColorArray + value = PackedColorArray() + print(null == value) diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-null-equals-builtin.out b/modules/gdscript/tests/scripts/runtime/features/compare-null-equals-builtin.out new file mode 100644 index 0000000000..639f6027b9 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/compare-null-equals-builtin.out @@ -0,0 +1,35 @@ +GDTEST_OK +true +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false +false diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-null-not-equals-builtin.gd b/modules/gdscript/tests/scripts/runtime/features/compare-null-not-equals-builtin.gd new file mode 100644 index 0000000000..8d5f9df1b8 --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/compare-null-not-equals-builtin.gd @@ -0,0 +1,138 @@ +func test(): + var value + + # null + value = null + print(null != value) + + # bool + value = false + print(null != value) + + # int + value = 0 + print(null != value) + + # float + value = 0.0 + print(null != value) + + # String + value = "" + print(null != value) + + # Vector2 + value = Vector2() + print(null != value) + + # Vector2i + value = Vector2i() + print(null != value) + + # Rect2 + value = Rect2() + print(null != value) + + # Rect2i + value = Rect2i() + print(null != value) + + # Vector3 + value = Vector3() + print(null != value) + + # Vector3i + value = Vector3i() + print(null != value) + + # Transform2D + value = Transform2D() + print(null != value) + + # Plane + value = Plane() + print(null != value) + + # Quaternion + value = Quaternion() + print(null != value) + + # AABB + value = AABB() + print(null != value) + + # Basis + value = Basis() + print(null != value) + + # Transform3D + value = Transform3D() + print(null != value) + + # Color + value = Color() + print(null != value) + + # StringName + value = &"" + print(null != value) + + # NodePath + value = ^"" + print(null != value) + + # RID + value = RID() + print(null != value) + + # Callable + value = Callable() + print(null != value) + + # Signal + value = Signal() + print(null != value) + + # Dictionary + value = {} + print(null != value) + + # Array + value = [] + print(null != value) + + # PackedByteArray + value = PackedByteArray() + print(null != value) + + # PackedInt32Array + value = PackedInt32Array() + print(null != value) + + # PackedInt64Array + value = PackedInt64Array() + print(null != value) + + # PackedFloat32Array + value = PackedFloat32Array() + print(null != value) + + # PackedFloat64Array + value = PackedFloat64Array() + print(null != value) + + # PackedStringArray + value = PackedStringArray() + print(null != value) + + # PackedVector2Array + value = PackedVector2Array() + print(null != value) + + # PackedVector3Array + value = PackedVector3Array() + print(null != value) + + # PackedColorArray + value = PackedColorArray() + print(null != value) diff --git a/modules/gdscript/tests/scripts/runtime/features/compare-null-not-equals-builtin.out b/modules/gdscript/tests/scripts/runtime/features/compare-null-not-equals-builtin.out new file mode 100644 index 0000000000..d1e332afba --- /dev/null +++ b/modules/gdscript/tests/scripts/runtime/features/compare-null-not-equals-builtin.out @@ -0,0 +1,35 @@ +GDTEST_OK +false +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true +true diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 17846eb281..6cc7ddb424 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -2891,12 +2891,24 @@ int CSharpScript::_try_get_member_export_hint(IMonoClassMember *p_member, Manage ERR_FAIL_COND_V_MSG(elem_variant_type == Variant::NIL, -1, "Unknown array element type."); - int hint_res = _try_get_member_export_hint(p_member, elem_type, elem_variant_type, /* allow_generics: */ false, elem_hint, elem_hint_string); + bool preset_hint = false; + if (elem_variant_type == Variant::STRING) { + MonoObject *attr = p_member->get_attribute(CACHED_CLASS(ExportAttribute)); + if (PropertyHint(CACHED_FIELD(ExportAttribute, hint)->get_int_value(attr)) == PROPERTY_HINT_ENUM) { + r_hint_string = itos(elem_variant_type) + "/" + itos(PROPERTY_HINT_ENUM) + ":" + CACHED_FIELD(ExportAttribute, hintString)->get_string_value(attr); + preset_hint = true; + } + } + + if (!preset_hint) { + int hint_res = _try_get_member_export_hint(p_member, elem_type, elem_variant_type, /* allow_generics: */ false, elem_hint, elem_hint_string); - ERR_FAIL_COND_V_MSG(hint_res == -1, -1, "Error while trying to determine information about the array element type."); + ERR_FAIL_COND_V_MSG(hint_res == -1, -1, "Error while trying to determine information about the array element type."); + + // Format: type/hint:hint_string + r_hint_string = itos(elem_variant_type) + "/" + itos(elem_hint) + ":" + elem_hint_string; + } - // Format: type/hint:hint_string - r_hint_string = itos(elem_variant_type) + "/" + itos(elem_hint) + ":" + elem_hint_string; r_hint = PROPERTY_HINT_TYPE_STRING; } else if (p_allow_generics && p_variant_type == Variant::DICTIONARY) { diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs index daea09ba72..fa215b6df8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs @@ -361,6 +361,7 @@ namespace Godot /// <seealso cref="XformInv(Vector2)"/> /// <param name="v">A vector to transform.</param> /// <returns>The transformed vector.</returns> + [Obsolete("Xform is deprecated. Use the multiplication operator (Transform2D * Vector2) instead.")] public Vector2 Xform(Vector2 v) { return new Vector2(Tdotx(v), Tdoty(v)) + origin; @@ -372,6 +373,7 @@ namespace Godot /// <seealso cref="Xform(Vector2)"/> /// <param name="v">A vector to inversely transform.</param> /// <returns>The inversely transformed vector.</returns> + [Obsolete("XformInv is deprecated. Use the multiplication operator (Vector2 * Transform2D) instead.")] public Vector2 XformInv(Vector2 v) { Vector2 vInv = v - origin; @@ -447,7 +449,7 @@ namespace Godot public static Transform2D operator *(Transform2D left, Transform2D right) { - left.origin = left.Xform(right.origin); + left.origin = left * right.origin; real_t x0 = left.Tdotx(right.x); real_t x1 = left.Tdoty(right.x); @@ -462,6 +464,96 @@ namespace Godot return left; } + /// <summary> + /// Returns a Vector2 transformed (multiplied) by transformation matrix. + /// </summary> + /// <param name="transform">The transformation to apply.</param> + /// <param name="vector">A Vector2 to transform.</param> + /// <returns>The transformed Vector2.</returns> + public static Vector2 operator *(Transform2D transform, Vector2 vector) + { + return new Vector2(transform.Tdotx(vector), transform.Tdoty(vector)) + transform.origin; + } + + /// <summary> + /// Returns a Vector2 transformed (multiplied) by the inverse transformation matrix. + /// </summary> + /// <param name="vector">A vector to inversely transform.</param> + /// <param name="transform">The transformation to apply.</param> + /// <returns>The inversely transformed Vector2.</returns> + public static Vector2 operator *(Vector2 vector, Transform2D transform) + { + Vector2 vInv = vector - transform.origin; + return new Vector2(transform.x.Dot(vInv), transform.y.Dot(vInv)); + } + + /// <summary> + /// Returns a Rect2 transformed (multiplied) by transformation matrix. + /// </summary> + /// <param name="transform">The transformation to apply.</param> + /// <param name="rect">A Rect2 to transform.</param> + /// <returns>The transformed Rect2.</returns> + public static Rect2 operator *(Transform2D transform, Rect2 rect) + { + Vector2 pos = transform * rect.Position; + Vector2 toX = transform.x * rect.Size.x; + Vector2 toY = transform.y * rect.Size.y; + + return new Rect2(pos, rect.Size).Expand(pos + toX).Expand(pos + toY).Expand(pos + toX + toY); + } + + /// <summary> + /// Returns a Rect2 transformed (multiplied) by the inverse transformation matrix. + /// </summary> + /// <param name="rect">A Rect2 to inversely transform.</param> + /// <param name="transform">The transformation to apply.</param> + /// <returns>The inversely transformed Rect2.</returns> + public static Rect2 operator *(Rect2 rect, Transform2D transform) + { + Vector2 pos = rect.Position * transform; + Vector2 to1 = new Vector2(rect.Position.x, rect.Position.y + rect.Size.y) * transform; + Vector2 to2 = new Vector2(rect.Position.x + rect.Size.x, rect.Position.y + rect.Size.y) * transform; + Vector2 to3 = new Vector2(rect.Position.x + rect.Size.x, rect.Position.y) * transform; + + return new Rect2(pos, rect.Size).Expand(to1).Expand(to2).Expand(to3); + } + + /// <summary> + /// Returns a copy of the given Vector2[] transformed (multiplied) by transformation matrix. + /// </summary> + /// <param name="transform">The transformation to apply.</param> + /// <param name="array">a Vector2[] to transform.</param> + /// <returns>The transformed copy of the Vector2[].</returns> + public static Vector2[] operator *(Transform2D transform, Vector2[] array) + { + Vector2[] newArray = new Vector2[array.Length]; + + for (int i = 0; i < array.Length; i++) + { + newArray[i] = transform * array[i]; + } + + return newArray; + } + + /// <summary> + /// Returns a copy of the given Vector2[] transformed (multiplied) by the inverse transformation matrix. + /// </summary> + /// <param name="array">A Vector2[] to inversely transform.</param> + /// <param name="transform">The transformation to apply.</param> + /// <returns>The inversely transformed copy of the Vector2[].</returns> + public static Vector2[] operator *(Vector2[] array, Transform2D transform) + { + Vector2[] newArray = new Vector2[array.Length]; + + for (int i = 0; i < array.Length; i++) + { + newArray[i] = array[i] * transform; + } + + return newArray; + } + public static bool operator ==(Transform2D left, Transform2D right) { return left.Equals(right); diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index eee9e8f32b..0a6bcedf31 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -2546,16 +2546,11 @@ void VisualScriptEditor::goto_line(int p_line, bool p_with_error) { error_line = p_line; } - List<StringName> functions; - script->get_function_list(&functions); - for (const StringName &E : functions) { - if (script->has_node(p_line)) { - _update_graph(); - _update_members(); + if (script->has_node(p_line)) { + _update_graph(); + _update_members(); - call_deferred(SNAME("call_deferred"), "_center_on_node", E, p_line); //editor might be just created and size might not exist yet - return; - } + call_deferred(SNAME("call_deferred"), "_center_on_node", p_line); // The editor might be just created and size might not exist yet. } } @@ -3592,6 +3587,11 @@ void VisualScriptEditor::_hide_timer() { hint_text->hide(); } +void VisualScriptEditor::_toggle_scripts_pressed() { + ScriptEditor::get_singleton()->toggle_scripts_panel(); + update_toggle_scripts_button(); +} + void VisualScriptEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { @@ -3606,6 +3606,8 @@ void VisualScriptEditor::_notification(int p_what) { return; } + update_toggle_scripts_button(); + edit_variable_edit->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); edit_signal_edit->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); func_input_scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); @@ -3650,6 +3652,7 @@ void VisualScriptEditor::_notification(int p_what) { } } break; case NOTIFICATION_VISIBILITY_CHANGED: { + update_toggle_scripts_button(); members_section->set_visible(is_visible_in_tree()); } break; } @@ -4232,6 +4235,15 @@ void VisualScriptEditor::add_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_h void VisualScriptEditor::set_syntax_highlighter(Ref<EditorSyntaxHighlighter> p_highlighter) { } +void VisualScriptEditor::update_toggle_scripts_button() { + if (is_layout_rtl()) { + toggle_scripts_button->set_icon(Control::get_theme_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? SNAME("Forward") : SNAME("Back"), SNAME("EditorIcons"))); + } else { + toggle_scripts_button->set_icon(Control::get_theme_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? SNAME("Back") : SNAME("Forward"), SNAME("EditorIcons"))); + } + toggle_scripts_button->set_tooltip(vformat("%s (%s)", TTR("Toggle Scripts Panel"), ED_GET_SHORTCUT("script_editor/toggle_scripts_panel")->get_as_text())); +} + void VisualScriptEditor::_bind_methods() { ClassDB::bind_method("_move_node", &VisualScriptEditor::_move_node); ClassDB::bind_method("_update_graph", &VisualScriptEditor::_update_graph, DEFVAL(-1)); @@ -4333,6 +4345,16 @@ VisualScriptEditor::VisualScriptEditor() { graph->hide(); graph->connect("scroll_offset_changed", callable_mp(this, &VisualScriptEditor::_graph_ofs_changed)); + status_bar = memnew(HBoxContainer); + add_child(status_bar); + status_bar->set_h_size_flags(SIZE_EXPAND_FILL); + status_bar->set_custom_minimum_size(Size2(0, 24 * EDSCALE)); + + toggle_scripts_button = memnew(Button); + toggle_scripts_button->set_flat(true); + toggle_scripts_button->connect("pressed", callable_mp(this, &VisualScriptEditor::_toggle_scripts_pressed)); + status_bar->add_child(toggle_scripts_button); + /// Add Buttons to Top Bar/Zoom bar. HBoxContainer *graph_hbc = graph->get_zoom_hbox(); diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index ab32aae7aa..19f5aabac9 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -93,6 +93,8 @@ class VisualScriptEditor : public ScriptEditorBase { ConfirmationDialog *function_create_dialog; GraphEdit *graph; + HBoxContainer *status_bar; + Button *toggle_scripts_button; VisualScriptEditorSignalEdit *signal_editor; @@ -281,6 +283,8 @@ class VisualScriptEditor : public ScriptEditorBase { void _member_rmb_selected(const Vector2 &p_pos); void _member_option(int p_option); + void _toggle_scripts_pressed(); + protected: void _notification(int p_what); static void _bind_methods(); @@ -330,6 +334,8 @@ public: static void free_clipboard(); + void update_toggle_scripts_button() override; + VisualScriptEditor(); ~VisualScriptEditor(); }; |