diff options
36 files changed, 480 insertions, 151 deletions
diff --git a/SConstruct b/SConstruct index a5a233fa11..f2c20ea91e 100644 --- a/SConstruct +++ b/SConstruct @@ -333,39 +333,39 @@ if selected_platform in platform_list: env.Prepend(CCFLAGS=['/std:c++17', '/permissive-']) # Enforce our minimal compiler version requirements - version = methods.get_compiler_version(env) - if version is not None and methods.using_gcc(env): - major = int(version[0]) - minor = int(version[1]) + cc_version = methods.get_compiler_version(env) or [-1, -1] + cc_version_major = cc_version[0] + cc_version_minor = cc_version[1] + + if methods.using_gcc(env): # GCC 8 before 8.4 has a regression in the support of guaranteed copy elision # which causes a build failure: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86521 - if major == 8 and minor < 4: + if cc_version_major == 8 and cc_version_minor < 4: print("Detected GCC 8 version < 8.4, which is not supported due to a " "regression in its C++17 guaranteed copy elision support. Use a " "newer GCC version, or Clang 6 or later by passing \"use_llvm=yes\" " "to the SCons command line.") sys.exit(255) - elif major < 7: + elif cc_version_major < 7: print("Detected GCC version older than 7, which does not fully support " "C++17. Supported versions are GCC 7, 9 and later. Use a newer GCC " "version, or Clang 6 or later by passing \"use_llvm=yes\" to the " "SCons command line.") sys.exit(255) - elif version is not None and methods.using_clang(env): - major = int(version[0]) + elif methods.using_clang(env): # Apple LLVM versions differ from upstream LLVM version \o/, compare # in https://en.wikipedia.org/wiki/Xcode#Toolchain_versions if env["platform"] == "osx" or env["platform"] == "iphone": vanilla = methods.is_vanilla_clang(env) - if vanilla and major < 6: + if vanilla and cc_version_major < 6: print("Detected Clang version older than 6, which does not fully support " "C++17. Supported versions are Clang 6 and later.") sys.exit(255) - elif not vanilla and major < 10: + elif not vanilla and cc_version_major < 10: print("Detected Apple Clang version older than 10, which does not fully " "support C++17. Supported versions are Apple Clang 10 and later.") sys.exit(255) - elif major < 6: + elif cc_version_major < 6: print("Detected Clang version older than 6, which does not fully support " "C++17. Supported versions are Clang 6 and later.") sys.exit(255) @@ -393,8 +393,7 @@ if selected_platform in platform_list: all_plus_warnings = ['-Wwrite-strings'] if methods.using_gcc(env): - version = methods.get_compiler_version(env) - if version != None and version[0] >= '7': + if cc_version_major >= 7: shadow_local_warning = ['-Wshadow-local'] if (env["warnings"] == 'extra'): @@ -407,8 +406,7 @@ if selected_platform in platform_list: '-Wstringop-overflow=4', '-Wlogical-op']) # -Wnoexcept was removed temporarily due to GH-36325. env.Append(CXXFLAGS=['-Wplacement-new=1']) - version = methods.get_compiler_version(env) - if version != None and version[0] >= '9': + if cc_version_major >= 9: env.Append(CCFLAGS=['-Wattribute-alias=2']) if methods.using_clang(env): env.Append(CCFLAGS=['-Wimplicit-fallthrough']) diff --git a/core/io/multiplayer_api.cpp b/core/io/multiplayer_api.cpp index 6a0eeea513..2aef0a3274 100644 --- a/core/io/multiplayer_api.cpp +++ b/core/io/multiplayer_api.cpp @@ -34,6 +34,10 @@ #include "scene/main/node.h" #include <stdint.h> +#define NODE_ID_COMPRESSION_SHIFT 3 +#define NAME_ID_COMPRESSION_SHIFT 5 +#define BYTE_ONLY_OR_NO_ARGS_SHIFT 6 + #ifdef DEBUG_ENABLED #include "core/os/os.h" #endif @@ -168,6 +172,16 @@ Ref<NetworkedMultiplayerPeer> MultiplayerAPI::get_network_peer() const { return network_peer; } +// Returns the packet size stripping the node path added when the node is not yet cached. +int get_packet_len(uint32_t p_node_target, int p_packet_len) { + if (p_node_target & 0x80000000) { + int ofs = p_node_target & 0x7FFFFFFF; + return p_packet_len - (p_packet_len - ofs); + } else { + return p_packet_len; + } +} + void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_packet_len) { ERR_FAIL_COND_MSG(root_node == NULL, "Multiplayer root node was not initialized. If you are using custom multiplayer, remember to set the root node via MultiplayerAPI.set_root_node before using it."); @@ -204,8 +218,8 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_ int name_id_offset = 1; ERR_FAIL_COND_MSG(p_packet_len < packet_min_size, "Invalid packet received. Size too small."); // Compute the meta size, which depends on the compression level. - int node_id_compression = (p_packet[0] & 24) >> 3; - int name_id_compression = (p_packet[0] & 32) >> 5; + int node_id_compression = (p_packet[0] & 24) >> NODE_ID_COMPRESSION_SHIFT; + int name_id_compression = (p_packet[0] & 32) >> NAME_ID_COMPRESSION_SHIFT; switch (node_id_compression) { case NETWORK_NODE_ID_COMPRESSION_8: @@ -250,6 +264,7 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_ // Unreachable, checked before. CRASH_NOW(); } + Node *node = _process_get_node(p_from, p_packet, node_target, p_packet_len); ERR_FAIL_COND_MSG(node == NULL, "Invalid packet received. Requested node was not found."); @@ -266,13 +281,14 @@ void MultiplayerAPI::_process_packet(int p_from, const uint8_t *p_packet, int p_ CRASH_NOW(); } + const int packet_len = get_packet_len(node_target, p_packet_len); if (packet_type == NETWORK_COMMAND_REMOTE_CALL) { - _process_rpc(node, name_id, p_from, p_packet, p_packet_len, packet_min_size); + _process_rpc(node, name_id, p_from, p_packet, packet_len, packet_min_size); } else { - _process_rset(node, name_id, p_from, p_packet, p_packet_len, packet_min_size); + _process_rset(node, name_id, p_from, p_packet, packet_len, packet_min_size); } } break; @@ -326,7 +342,7 @@ Node *MultiplayerAPI::_process_get_node(int p_from, const uint8_t *p_packet, uin void MultiplayerAPI::_process_rpc(Node *p_node, const uint16_t p_rpc_method_id, int p_from, const uint8_t *p_packet, int p_packet_len, int p_offset) { - ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small."); + ERR_FAIL_COND_MSG(p_offset > p_packet_len, "Invalid packet received. Size too small."); // Check that remote can call the RPC on this node. StringName name = p_node->get_node_rpc_method(p_rpc_method_id); @@ -340,14 +356,30 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const uint16_t p_rpc_method_id, bool can_call = _can_call_mode(p_node, rpc_mode, p_from); ERR_FAIL_COND_MSG(!can_call, "RPC '" + String(name) + "' is not allowed on node " + p_node->get_path() + " from: " + itos(p_from) + ". Mode is " + itos((int)rpc_mode) + ", master is " + itos(p_node->get_network_master()) + "."); - int argc = p_packet[p_offset]; + int argc = 0; + bool byte_only = false; + + const bool byte_only_or_no_args = ((p_packet[0] & 64) >> BYTE_ONLY_OR_NO_ARGS_SHIFT) == 1; + if (byte_only_or_no_args) { + if (p_offset < p_packet_len) { + // This packet contains only bytes. + argc = 1; + byte_only = true; + } else { + // This rpc calls a method without parameters. + } + } else { + // Normal variant, takes the argument count from the packet. + ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small."); + argc = p_packet[p_offset]; + p_offset += 1; + } + Vector<Variant> args; Vector<const Variant *> argp; args.resize(argc); argp.resize(argc); - p_offset++; - #ifdef DEBUG_ENABLED if (profiling) { ObjectID id = p_node->get_instance_id(); @@ -356,16 +388,26 @@ void MultiplayerAPI::_process_rpc(Node *p_node, const uint16_t p_rpc_method_id, } #endif - for (int i = 0; i < argc; i++) { + if (byte_only) { + Vector<uint8_t> pure_data; + const int len = p_packet_len - p_offset; + pure_data.resize(len); + memcpy(pure_data.ptrw(), &p_packet[p_offset], len); + args.write[0] = pure_data; + argp.write[0] = &args[0]; + p_offset += len; + } else { + for (int i = 0; i < argc; i++) { - ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small."); + ERR_FAIL_COND_MSG(p_offset >= p_packet_len, "Invalid packet received. Size too small."); - int vlen; - Error err = _decode_and_decompress_variant(args.write[i], &p_packet[p_offset], p_packet_len - p_offset, &vlen); - ERR_FAIL_COND_MSG(err != OK, "Invalid packet received. Unable to decode RPC argument."); + int vlen; + Error err = _decode_and_decompress_variant(args.write[i], &p_packet[p_offset], p_packet_len - p_offset, &vlen); + ERR_FAIL_COND_MSG(err != OK, "Invalid packet received. Unable to decode RPC argument."); - argp.write[i] = &args[i]; - p_offset += vlen; + argp.write[i] = &args[i]; + p_offset += vlen; + } } Callable::CallError ce; @@ -742,10 +784,12 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p // - `NetworkCommands` in the first three bits. // - `NetworkNodeIdCompression` in the next 2 bits. // - `NetworkNameIdCompression` in the next 1 bit. - // - So we still have the last two bits free! + // - `byte_only_or_no_args` in the next 1 bit. + // - So we still have the last bit free! uint8_t command_type = p_set ? NETWORK_COMMAND_REMOTE_SET : NETWORK_COMMAND_REMOTE_CALL; uint8_t node_id_compression = UINT8_MAX; uint8_t name_id_compression = UINT8_MAX; + bool byte_only_or_no_args = false; MAKE_ROOM(1); // The meta is composed along the way, so just set 0 for now. @@ -835,17 +879,28 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p ofs += 2; } - // Call arguments. - MAKE_ROOM(ofs + 1); - packet_cache.write[ofs] = p_argcount; - ofs += 1; - for (int i = 0; i < p_argcount; i++) { - int len(0); - Error err = _encode_and_compress_variant(*p_arg[i], NULL, len); - ERR_FAIL_COND_MSG(err != OK, "Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!"); - MAKE_ROOM(ofs + len); - _encode_and_compress_variant(*p_arg[i], &(packet_cache.write[ofs]), len); - ofs += len; + if (p_argcount == 0) { + byte_only_or_no_args = true; + } else if (p_argcount == 1 && p_arg[0]->get_type() == Variant::PACKED_BYTE_ARRAY) { + byte_only_or_no_args = true; + // Special optimization when only the byte vector is sent. + const Vector<uint8_t> data = *p_arg[0]; + MAKE_ROOM(ofs + data.size()); + copymem(&(packet_cache.write[ofs]), data.ptr(), sizeof(uint8_t) * data.size()); + ofs += data.size(); + } else { + // Arguments + MAKE_ROOM(ofs + 1); + packet_cache.write[ofs] = p_argcount; + ofs += 1; + for (int i = 0; i < p_argcount; i++) { + int len(0); + Error err = _encode_and_compress_variant(*p_arg[i], NULL, len); + ERR_FAIL_COND_MSG(err != OK, "Unable to encode RPC argument. THIS IS LIKELY A BUG IN THE ENGINE!"); + MAKE_ROOM(ofs + len); + _encode_and_compress_variant(*p_arg[i], &(packet_cache.write[ofs]), len); + ofs += len; + } } } @@ -854,7 +909,7 @@ void MultiplayerAPI::_send_rpc(Node *p_from, int p_to, bool p_unreliable, bool p ERR_FAIL_COND(name_id_compression > 1); // We can now set the meta - packet_cache.write[0] = command_type + (node_id_compression << 3) + (name_id_compression << 5); + packet_cache.write[0] = command_type + (node_id_compression << NODE_ID_COMPRESSION_SHIFT) + (name_id_compression << NAME_ID_COMPRESSION_SHIFT) + ((byte_only_or_no_args ? 1 : 0) << BYTE_ONLY_OR_NO_ARGS_SHIFT); #ifdef DEBUG_ENABLED if (profiling) { diff --git a/core/reference.h b/core/reference.h index 36e7d5c6a6..fd42c4e537 100644 --- a/core/reference.h +++ b/core/reference.h @@ -38,7 +38,6 @@ class Reference : public Object { GDCLASS(Reference, Object); - friend class RefBase; SafeRefCount refcount; SafeRefCount refcount_init; diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 3ddc3af200..eb15bc2ad9 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -129,21 +129,23 @@ child_node.get_parent().remove_child(child_node) add_child(child_node) [/codeblock] + If you need the child node to be added below a specific node in the list of children, use [method add_child_below_node] instead of this method. [b]Note:[/b] If you want a child to be persisted to a [PackedScene], you must set [member owner] in addition to calling [method add_child]. This is typically relevant for [url=https://godot.readthedocs.io/en/latest/tutorials/misc/running_code_in_the_editor.html]tool scripts[/url] and [url=https://godot.readthedocs.io/en/latest/tutorials/plugins/editor/index.html]editor plugins[/url]. If [method add_child] is called without setting [member owner], the newly added [Node] will not be visible in the scene tree, though it will be visible in the 2D/3D view. </description> </method> <method name="add_child_below_node"> <return type="void"> </return> - <argument index="0" name="node" type="Node"> + <argument index="0" name="preceding_node" type="Node"> </argument> - <argument index="1" name="child_node" type="Node"> + <argument index="1" name="node" type="Node"> </argument> <argument index="2" name="legible_unique_name" type="bool" default="false"> </argument> <description> - Adds a child node. The child is placed below the given node in the list of children. + Adds a child node below the [code]preceding_node[/code]. If [code]legible_unique_name[/code] is [code]true[/code], the child node will have an human-readable name based on the name of the node being instanced instead of its type. + Use [method add_child] instead of this method if you don't need the child node to be added below a specific node in the list of children. </description> </method> <method name="add_to_group"> diff --git a/doc/classes/VisualShaderNodeCompare.xml b/doc/classes/VisualShaderNodeCompare.xml index f207cba0a5..32f7be3ec3 100644 --- a/doc/classes/VisualShaderNodeCompare.xml +++ b/doc/classes/VisualShaderNodeCompare.xml @@ -50,7 +50,7 @@ Comparison for less than ([code]a < b[/code]). Cannot be used if [member type] set to [constant CTYPE_BOOLEAN] or [constant CTYPE_TRANSFORM]. </constant> <constant name="FUNC_LESS_THAN_EQUAL" value="5" enum="Function"> - Comparison for less than or equal ([code]a < b[/code]). Cannot be used if [member type] set to [constant CTYPE_BOOLEAN] or [constant CTYPE_TRANSFORM]. + Comparison for less than or equal ([code]a <= b[/code]). Cannot be used if [member type] set to [constant CTYPE_BOOLEAN] or [constant CTYPE_TRANSFORM]. </constant> <constant name="COND_ALL" value="0" enum="Condition"> The result will be true if all of component in vector satisfy the comparison condition. diff --git a/doc/classes/VisualShaderNodeFloatConstant.xml b/doc/classes/VisualShaderNodeFloatConstant.xml index 267570121d..3ba9ff07d3 100644 --- a/doc/classes/VisualShaderNodeFloatConstant.xml +++ b/doc/classes/VisualShaderNodeFloatConstant.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualShaderNodeFloatConstant" inherits="VisualShaderNode" version="4.0"> <brief_description> + A scalar floating-point constant to be used within the visual shader graph. </brief_description> <description> + Translated to [code]float[/code] in the shader language. </description> <tutorials> </tutorials> @@ -10,6 +12,7 @@ </methods> <members> <member name="constant" type="float" setter="set_constant" getter="get_constant" default="0.0"> + A floating-point constant which represents a state of this node. </member> </members> <constants> diff --git a/doc/classes/VisualShaderNodeFloatFunc.xml b/doc/classes/VisualShaderNodeFloatFunc.xml index de1f902f2c..bb7486e8cf 100644 --- a/doc/classes/VisualShaderNodeFloatFunc.xml +++ b/doc/classes/VisualShaderNodeFloatFunc.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualShaderNodeFloatFunc" inherits="VisualShaderNode" version="4.0"> <brief_description> + A scalar floating-point function to be used within the visual shader graph. </brief_description> <description> + Accept a floating-point scalar ([code]x[/code]) to the input port and transform it according to [member function]. </description> <tutorials> </tutorials> @@ -10,72 +12,105 @@ </methods> <members> <member name="function" type="int" setter="set_function" getter="get_function" enum="VisualShaderNodeFloatFunc.Function" default="13"> + A function to be applied to the scalar. See [enum Function] for options. </member> </members> <constants> <constant name="FUNC_SIN" value="0" enum="Function"> + Returns the sine of the parameter. Translates to [code]sin(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_COS" value="1" enum="Function"> + Returns the cosine of the parameter. Translates to [code]cos(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_TAN" value="2" enum="Function"> + Returns the tangent of the parameter. Translates to [code]tan(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_ASIN" value="3" enum="Function"> + Returns the arc-sine of the parameter. Translates to [code]asin(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_ACOS" value="4" enum="Function"> + Returns the arc-cosine of the parameter. Translates to [code]acos(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_ATAN" value="5" enum="Function"> + Returns the arc-tangent of the parameter. Translates to [code]atan(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_SINH" value="6" enum="Function"> + Returns the hyperbolic sine of the parameter. Translates to [code]sinh(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_COSH" value="7" enum="Function"> + Returns the hyperbolic cosine of the parameter. Translates to [code]cosh(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_TANH" value="8" enum="Function"> + Returns the hyperbolic tangent of the parameter. Translates to [code]tanh(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_LOG" value="9" enum="Function"> + Returns the natural logarithm of the parameter. Translates to [code]log(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_EXP" value="10" enum="Function"> + Returns the natural exponentiation of the parameter. Translates to [code]exp(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_SQRT" value="11" enum="Function"> + Returns the square root of the parameter. Translates to [code]sqrt(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_ABS" value="12" enum="Function"> + Returns the absolute value of the parameter. Translates to [code]abs(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_SIGN" value="13" enum="Function"> + Extracts the sign of the parameter. Translates to [code]sign(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_FLOOR" value="14" enum="Function"> + Finds the nearest integer less than or equal to the parameter. Translates to [code]floor(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_ROUND" value="15" enum="Function"> + Finds the nearest integer to the parameter. Translates to [code]round(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_CEIL" value="16" enum="Function"> + Finds the nearest integer that is greater than or equal to the parameter. Translates to [code]ceil(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_FRAC" value="17" enum="Function"> + Computes the fractional part of the argument. Translates to [code]fract(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_SATURATE" value="18" enum="Function"> + Clamps the value between [code]0.0[/code] and [code]1.0[/code] using [code]min(max(x, 0.0), 1.0)[/code]. </constant> <constant name="FUNC_NEGATE" value="19" enum="Function"> + Negates the [code]x[/code] using [code]-(x)[/code]. </constant> <constant name="FUNC_ACOSH" value="20" enum="Function"> + Returns the arc-hyperbolic-cosine of the parameter. Translates to [code]acosh(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_ASINH" value="21" enum="Function"> + Returns the arc-hyperbolic-sine of the parameter. Translates to [code]asinh(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_ATANH" value="22" enum="Function"> + Returns the arc-hyperbolic-tangent of the parameter. Translates to [code]atanh(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_DEGREES" value="23" enum="Function"> + Convert a quantity in radians to degrees. Translates to [code]degrees(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_EXP2" value="24" enum="Function"> + Returns 2 raised by the power of the parameter. Translates to [code]exp2(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_INVERSE_SQRT" value="25" enum="Function"> + Returns the inverse of the square root of the parameter. Translates to [code]inversesqrt(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_LOG2" value="26" enum="Function"> + Returns the base 2 logarithm of the parameter. Translates to [code]log2(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_RADIANS" value="27" enum="Function"> + Convert a quantity in degrees to radians. Translates to [code]radians(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_RECIPROCAL" value="28" enum="Function"> + Finds reciprocal value of dividing 1 by [code]x[/code] (i.e. [code]1 / x[/code]). </constant> <constant name="FUNC_ROUNDEVEN" value="29" enum="Function"> + Finds the nearest even integer to the parameter. Translates to [code]roundEven(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_TRUNC" value="30" enum="Function"> + Returns a value equal to the nearest integer to [code]x[/code] whose absolute value is not larger than the absolute value of [code]x[/code]. Translates to [code]trunc(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_ONEMINUS" value="31" enum="Function"> + Subtracts scalar [code]x[/code] from 1 (i.e. [code]1 - x[/code]). </constant> </constants> </class> diff --git a/doc/classes/VisualShaderNodeFloatOp.xml b/doc/classes/VisualShaderNodeFloatOp.xml index 50ba08701c..2c9ebabb89 100644 --- a/doc/classes/VisualShaderNodeFloatOp.xml +++ b/doc/classes/VisualShaderNodeFloatOp.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualShaderNodeFloatOp" inherits="VisualShaderNode" version="4.0"> <brief_description> + A floating-point scalar operator to be used within the visual shader graph. </brief_description> <description> + Applies [member operator] to two floating-point inputs: [code]a[/code] and [code]b[/code]. </description> <tutorials> </tutorials> @@ -10,28 +12,39 @@ </methods> <members> <member name="operator" type="int" setter="set_operator" getter="get_operator" enum="VisualShaderNodeFloatOp.Operator" default="0"> + An operator to be applied to the inputs. See [enum Operator] for options. </member> </members> <constants> <constant name="OP_ADD" value="0" enum="Operator"> + Sums two numbers using [code]a + b[/code]. </constant> <constant name="OP_SUB" value="1" enum="Operator"> + Subtracts two numbers using [code]a - b[/code]. </constant> <constant name="OP_MUL" value="2" enum="Operator"> + Multiplies two numbers using [code]a * b[/code]. </constant> <constant name="OP_DIV" value="3" enum="Operator"> + Divides two numbers using [code]a / b[/code]. </constant> <constant name="OP_MOD" value="4" enum="Operator"> + Calculates the remainder of two numbers. Translates to [code]mod(a, b)[/code] in the Godot Shader Language. </constant> <constant name="OP_POW" value="5" enum="Operator"> + Raises the [code]a[/code] to the power of [code]b[/code]. Translates to [code]pow(a, b)[/code] in the Godot Shader Language. </constant> <constant name="OP_MAX" value="6" enum="Operator"> + Returns the greater of two numbers. Translates to [code]max(a, b)[/code] in the Godot Shader Language. </constant> <constant name="OP_MIN" value="7" enum="Operator"> + Returns the lesser of two numbers. Translates to [code]min(a, b)[/code] in the Godot Shader Language. </constant> <constant name="OP_ATAN2" value="8" enum="Operator"> + Returns the arc-tangent of the parameters. Translates to [code]atan(a, b)[/code] in the Godot Shader Language. </constant> <constant name="OP_STEP" value="9" enum="Operator"> + Generates a step function by comparing [code]b[/code](x) to [code]a[/code](edge). Returns 0.0 if [code]x[/code] is smaller than [code]edge[/code] and otherwise 1.0. Translates to [code]step(a, b)[/code] in the Godot Shader Language. </constant> </constants> </class> diff --git a/doc/classes/VisualShaderNodeIf.xml b/doc/classes/VisualShaderNodeIf.xml index 0a8fdcfd4d..1ebd945d42 100644 --- a/doc/classes/VisualShaderNodeIf.xml +++ b/doc/classes/VisualShaderNodeIf.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualShaderNodeIf" inherits="VisualShaderNode" version="4.0"> <brief_description> + Compares two floating-point numbers in order to return a required vector within the visual shader graph. </brief_description> <description> + First two ports are scalar floatin-point numbers to compare, third is tolerance comparsion amount and last three ports represents a vectors returned if [code]a == b[/code], [code]a > b[/code] and [code]a < b[/code] respectivly. </description> <tutorials> </tutorials> diff --git a/doc/classes/VisualShaderNodeInput.xml b/doc/classes/VisualShaderNodeInput.xml index 1c8d8d84c4..ed629508d0 100644 --- a/doc/classes/VisualShaderNodeInput.xml +++ b/doc/classes/VisualShaderNodeInput.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualShaderNodeInput" inherits="VisualShaderNode" version="4.0"> <brief_description> + Represents the input shader parameter within the visual shader graph. </brief_description> <description> </description> @@ -11,16 +12,19 @@ <return type="String"> </return> <description> + Returns a translated name of the current constant in the Godot Shader Language. eg. [code]"ALBEDO"[/code] if the [member input_name] equal to [code]"albedo"[/code]. </description> </method> </methods> <members> <member name="input_name" type="String" setter="set_input_name" getter="get_input_name" default=""[None]""> + One of the several input constants in lower-case style like: "vertex"([/code]VERTEX[code]) or "point_size"([code]POINT_SIZE[/code]). </member> </members> <signals> <signal name="input_type_changed"> <description> + Emitted when input is changed via [member input_name]. </description> </signal> </signals> diff --git a/doc/classes/VisualShaderNodeIntConstant.xml b/doc/classes/VisualShaderNodeIntConstant.xml index cb05d589d2..1c407b21ca 100644 --- a/doc/classes/VisualShaderNodeIntConstant.xml +++ b/doc/classes/VisualShaderNodeIntConstant.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualShaderNodeIntConstant" inherits="VisualShaderNode" version="4.0"> <brief_description> + A scalar integer constant to be used within the visual shader graph. </brief_description> <description> + Translated to [code]int[/code] in the shader language. </description> <tutorials> </tutorials> @@ -10,6 +12,7 @@ </methods> <members> <member name="constant" type="int" setter="set_constant" getter="get_constant" default="0"> + An integer constant which represents a state of this node. </member> </members> <constants> diff --git a/doc/classes/VisualShaderNodeIntFunc.xml b/doc/classes/VisualShaderNodeIntFunc.xml index 9196250e38..4b5d4ca8d2 100644 --- a/doc/classes/VisualShaderNodeIntFunc.xml +++ b/doc/classes/VisualShaderNodeIntFunc.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualShaderNodeIntFunc" inherits="VisualShaderNode" version="4.0"> <brief_description> + A scalar integer function to be used within the visual shader graph. </brief_description> <description> + Accept an integer scalar ([code]x[/code]) to the input port and transform it according to [member function]. </description> <tutorials> </tutorials> @@ -10,16 +12,21 @@ </methods> <members> <member name="function" type="int" setter="set_function" getter="get_function" enum="VisualShaderNodeIntFunc.Function" default="0"> + A function to be applied to the scalar. See [enum Function] for options. </member> </members> <constants> <constant name="FUNC_ABS" value="0" enum="Function"> + Returns the absolute value of the parameter. Translates to [code]abs(x)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_CLAMP" value="1" enum="Function"> + Constrains a parameter between [code]min[/code] and [code]max[/code]. Translates to [code]clamp(x, min, max)[/code] in the Godot Shader Language. </constant> <constant name="FUNC_NEGATE" value="2" enum="Function"> + Negates the [code]x[/code] using [code]-(x)[/code]. </constant> <constant name="FUNC_SIGN" value="3" enum="Function"> + Extracts the sign of the parameter. Translates to [code]sign(x)[/code] in the Godot Shader Language. </constant> </constants> </class> diff --git a/doc/classes/VisualShaderNodeIntOp.xml b/doc/classes/VisualShaderNodeIntOp.xml index 5e7020c75c..fc9a0a9a0a 100644 --- a/doc/classes/VisualShaderNodeIntOp.xml +++ b/doc/classes/VisualShaderNodeIntOp.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VisualShaderNodeIntOp" inherits="VisualShaderNode" version="4.0"> <brief_description> + An integer scalar operator to be used within the visual shader graph. </brief_description> <description> + Applies [member operator] to two integer inputs: [code]a[/code] and [code]b[/code]. </description> <tutorials> </tutorials> @@ -10,22 +12,30 @@ </methods> <members> <member name="operator" type="int" setter="set_operator" getter="get_operator" enum="VisualShaderNodeIntOp.Operator" default="0"> + An operator to be applied to the inputs. See [enum Operator] for options. </member> </members> <constants> <constant name="OP_ADD" value="0" enum="Operator"> + Sums two numbers using [code]a + b[/code]. </constant> <constant name="OP_SUB" value="1" enum="Operator"> + Subtracts two numbers using [code]a - b[/code]. </constant> <constant name="OP_MUL" value="2" enum="Operator"> + Multiplies two numbers using [code]a * b[/code]. </constant> <constant name="OP_DIV" value="3" enum="Operator"> + Divides two numbers using [code]a / b[/code]. </constant> <constant name="OP_MOD" value="4" enum="Operator"> + Calculates the remainder of two numbers using [code]a % b[/code]. </constant> <constant name="OP_MAX" value="5" enum="Operator"> + Returns the greater of two numbers. Translates to [code]max(a, b)[/code] in the Godot Shader Language. </constant> <constant name="OP_MIN" value="6" enum="Operator"> + Returns the lesser of two numbers. Translates to [code]max(a, b)[/code] in the Godot Shader Language. </constant> </constants> </class> diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 9742cadfd3..8758fbcfc9 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -2480,6 +2480,9 @@ void AnimationTrackEdit::_path_entered(const String &p_text) { bool AnimationTrackEdit::_is_value_key_valid(const Variant &p_key_value, Variant::Type &r_valid_type) const { + if (root == nullptr) + return false; + RES res; Vector<StringName> leftover_path; Node *node = root->get_node_and_resource(animation->track_get_path(track), res, leftover_path); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index b632e7594c..9cc6134f27 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -6147,7 +6147,7 @@ EditorNode::EditorNode() { ED_SHORTCUT("editor/next_tab", TTR("Next tab"), KEY_MASK_CMD + KEY_TAB); ED_SHORTCUT("editor/prev_tab", TTR("Previous tab"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_TAB); - ED_SHORTCUT("editor/filter_files", TTR("Filter Files..."), KEY_MASK_ALT + KEY_MASK_CMD + KEY_P); + ED_SHORTCUT("editor/filter_files", TTR("Filter Files..."), KEY_MASK_CMD + KEY_MASK_ALT + KEY_P); PopupMenu *p; file_menu->set_tooltip(TTR("Operations with scene files.")); @@ -6162,13 +6162,14 @@ EditorNode::EditorNode() { p->add_separator(); p->add_shortcut(ED_SHORTCUT("editor/save_scene", TTR("Save Scene"), KEY_MASK_CMD + KEY_S), FILE_SAVE_SCENE); - p->add_shortcut(ED_SHORTCUT("editor/save_scene_as", TTR("Save Scene As..."), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_S), FILE_SAVE_AS_SCENE); - p->add_shortcut(ED_SHORTCUT("editor/save_all_scenes", TTR("Save All Scenes"), KEY_MASK_ALT + KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_S), FILE_SAVE_ALL_SCENES); + p->add_shortcut(ED_SHORTCUT("editor/save_scene_as", TTR("Save Scene As..."), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_S), FILE_SAVE_AS_SCENE); + p->add_shortcut(ED_SHORTCUT("editor/save_all_scenes", TTR("Save All Scenes"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_S), FILE_SAVE_ALL_SCENES); p->add_separator(); + p->add_shortcut(ED_SHORTCUT("editor/quick_open", TTR("Quick Open..."), KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_O), FILE_QUICK_OPEN); - p->add_shortcut(ED_SHORTCUT("editor/quick_open_scene", TTR("Quick Open Scene..."), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_O), FILE_QUICK_OPEN_SCENE); - p->add_shortcut(ED_SHORTCUT("editor/quick_open_script", TTR("Quick Open Script..."), KEY_MASK_ALT + KEY_MASK_CMD + KEY_O), FILE_QUICK_OPEN_SCRIPT); + p->add_shortcut(ED_SHORTCUT("editor/quick_open_scene", TTR("Quick Open Scene..."), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_O), FILE_QUICK_OPEN_SCENE); + p->add_shortcut(ED_SHORTCUT("editor/quick_open_script", TTR("Quick Open Script..."), KEY_MASK_CMD + KEY_MASK_ALT + KEY_O), FILE_QUICK_OPEN_SCRIPT); p->add_separator(); PopupMenu *pm_export = memnew(PopupMenu); @@ -6181,11 +6182,11 @@ EditorNode::EditorNode() { p->add_separator(); p->add_shortcut(ED_SHORTCUT("editor/undo", TTR("Undo"), KEY_MASK_CMD + KEY_Z), EDIT_UNDO, true); - p->add_shortcut(ED_SHORTCUT("editor/redo", TTR("Redo"), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_Z), EDIT_REDO, true); + p->add_shortcut(ED_SHORTCUT("editor/redo", TTR("Redo"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_Z), EDIT_REDO, true); p->add_separator(); p->add_shortcut(ED_SHORTCUT("editor/revert_scene", TTR("Revert Scene")), EDIT_REVERT); - p->add_shortcut(ED_SHORTCUT("editor/close_scene", TTR("Close Scene"), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_W), FILE_CLOSE); + p->add_shortcut(ED_SHORTCUT("editor/close_scene", TTR("Close Scene"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_W), FILE_CLOSE); recent_scenes = memnew(PopupMenu); recent_scenes->set_name("RecentScenes"); @@ -6237,7 +6238,7 @@ EditorNode::EditorNode() { #ifdef OSX_ENABLED p->add_shortcut(ED_SHORTCUT("editor/quit_to_project_list", TTR("Quit to Project List"), KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_Q), RUN_PROJECT_MANAGER, true); #else - p->add_shortcut(ED_SHORTCUT("editor/quit_to_project_list", TTR("Quit to Project List"), KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_Q), RUN_PROJECT_MANAGER, true); + p->add_shortcut(ED_SHORTCUT("editor/quit_to_project_list", TTR("Quit to Project List"), KEY_MASK_CMD + KEY_MASK_SHIFT + KEY_Q), RUN_PROJECT_MANAGER, true); #endif menu_hb->add_spacer(); diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index 5c012183e7..0bc9b0585c 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -594,6 +594,12 @@ FindInFilesPanel::FindInFilesPanel() { _status_label = memnew(Label); hbc->add_child(_status_label); + _refresh_button = memnew(Button); + _refresh_button->set_text(TTR("Refresh")); + _refresh_button->connect_compat("pressed", this, "_on_refresh_button_clicked"); + _refresh_button->hide(); + hbc->add_child(_refresh_button); + _cancel_button = memnew(Button); _cancel_button->set_text(TTR("Cancel")); _cancel_button->connect_compat("pressed", this, "_on_cancel_button_clicked"); @@ -681,6 +687,7 @@ void FindInFilesPanel::start_search() { _finder->start(); update_replace_buttons(); + _refresh_button->hide(); _cancel_button->show(); } @@ -691,6 +698,7 @@ void FindInFilesPanel::stop_search() { _status_label->set_text(""); update_replace_buttons(); set_progress_visible(false); + _refresh_button->show(); _cancel_button->hide(); } @@ -793,9 +801,14 @@ void FindInFilesPanel::_on_finished() { _status_label->set_text(TTR("Search complete")); update_replace_buttons(); set_progress_visible(false); + _refresh_button->show(); _cancel_button->hide(); } +void FindInFilesPanel::_on_refresh_button_clicked() { + start_search(); +} + void FindInFilesPanel::_on_cancel_button_clicked() { stop_search(); } @@ -970,6 +983,7 @@ void FindInFilesPanel::_bind_methods() { ClassDB::bind_method("_on_result_found", &FindInFilesPanel::_on_result_found); ClassDB::bind_method("_on_item_edited", &FindInFilesPanel::_on_item_edited); ClassDB::bind_method("_on_finished", &FindInFilesPanel::_on_finished); + ClassDB::bind_method("_on_refresh_button_clicked", &FindInFilesPanel::_on_refresh_button_clicked); ClassDB::bind_method("_on_cancel_button_clicked", &FindInFilesPanel::_on_cancel_button_clicked); ClassDB::bind_method("_on_result_selected", &FindInFilesPanel::_on_result_selected); ClassDB::bind_method("_on_replace_text_changed", &FindInFilesPanel::_on_replace_text_changed); diff --git a/editor/find_in_files.h b/editor/find_in_files.h index 5dc4ef5e19..7002f750b7 100644 --- a/editor/find_in_files.h +++ b/editor/find_in_files.h @@ -179,6 +179,7 @@ protected: private: void _on_result_found(String fpath, int line_number, int begin, int end, String text); void _on_finished(); + void _on_refresh_button_clicked(); void _on_cancel_button_clicked(); void _on_result_selected(); void _on_item_edited(); @@ -206,6 +207,7 @@ private: Label *_search_text_label; Tree *_results_display; Label *_status_label; + Button *_refresh_button; Button *_cancel_button; ProgressBar *_progress_bar; Map<String, TreeItem *> _file_items; diff --git a/editor/import/resource_importer_texture_atlas.cpp b/editor/import/resource_importer_texture_atlas.cpp index 4291d6f2d7..3172cc7279 100644 --- a/editor/import/resource_importer_texture_atlas.cpp +++ b/editor/import/resource_importer_texture_atlas.cpp @@ -143,8 +143,8 @@ static void _plot_triangle(Vector2 *vertices, const Vector2 &p_offset, bool p_tr int px = xi, py = yi; int sx = px, sy = py; - sx = CLAMP(sx, 0, src_width); - sy = CLAMP(sy, 0, src_height); + sx = CLAMP(sx, 0, src_width - 1); + sy = CLAMP(sy, 0, src_height - 1); Color color = p_src_image->get_pixel(sx, sy); if (p_transposed) { SWAP(px, py); @@ -165,8 +165,8 @@ static void _plot_triangle(Vector2 *vertices, const Vector2 &p_offset, bool p_tr for (int xi = (xf < width ? int(xf) : width - 1); xi >= (xt > 0 ? xt : 0); xi--) { int px = xi, py = yi; int sx = px, sy = py; - sx = CLAMP(sx, 0, src_width); - sy = CLAMP(sy, 0, src_height); + sx = CLAMP(sx, 0, src_width - 1); + sy = CLAMP(sy, 0, src_height - 1); Color color = p_src_image->get_pixel(sx, sy); if (p_transposed) { SWAP(px, py); diff --git a/editor/plugins/mesh_instance_editor_plugin.cpp b/editor/plugins/mesh_instance_editor_plugin.cpp index 182a8600e4..37cf16de58 100644 --- a/editor/plugins/mesh_instance_editor_plugin.cpp +++ b/editor/plugins/mesh_instance_editor_plugin.cpp @@ -455,7 +455,7 @@ MeshInstanceEditor::MeshInstanceEditor() { options->get_popup()->add_separator(); options->get_popup()->add_item(TTR("Create Trimesh Collision Sibling"), MENU_OPTION_CREATE_TRIMESH_COLLISION_SHAPE); options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is the most accurate (but slowest) option for collision detection.")); - options->get_popup()->add_item(TTR("Create Single Convex Collision Siblings"), MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE); + options->get_popup()->add_item(TTR("Create Single Convex Collision Sibling"), MENU_OPTION_CREATE_SINGLE_CONVEX_COLLISION_SHAPE); options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a single convex collision shape.\nThis is the fastest (but least accurate) option for collision detection.")); options->get_popup()->add_item(TTR("Create Multiple Convex Collision Siblings"), MENU_OPTION_CREATE_MULTIPLE_CONVEX_COLLISION_SHAPES); options->get_popup()->set_item_tooltip(options->get_popup()->get_item_count() - 1, TTR("Creates a polygon-based collision shape.\nThis is a performance middle-ground between the two above options.")); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 4e0787c805..f4ebd7c3cc 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -292,24 +292,29 @@ void ScriptTextEditor::_set_theme_for_script() { const Color basetype_color = colors_cache.basetype_color; text_edit->add_keyword_color("String", basetype_color); text_edit->add_keyword_color("Vector2", basetype_color); + text_edit->add_keyword_color("Vector2i", basetype_color); text_edit->add_keyword_color("Rect2", basetype_color); - text_edit->add_keyword_color("Transform2D", basetype_color); + text_edit->add_keyword_color("Rect2i", basetype_color); text_edit->add_keyword_color("Vector3", basetype_color); + text_edit->add_keyword_color("Vector3i", basetype_color); + text_edit->add_keyword_color("Transform2D", basetype_color); + text_edit->add_keyword_color("Plane", basetype_color); + text_edit->add_keyword_color("Quat", basetype_color); text_edit->add_keyword_color("AABB", basetype_color); text_edit->add_keyword_color("Basis", basetype_color); - text_edit->add_keyword_color("Plane", basetype_color); text_edit->add_keyword_color("Transform", basetype_color); - text_edit->add_keyword_color("Quat", basetype_color); text_edit->add_keyword_color("Color", basetype_color); - text_edit->add_keyword_color("Object", basetype_color); + text_edit->add_keyword_color("StringName", basetype_color); text_edit->add_keyword_color("NodePath", basetype_color); text_edit->add_keyword_color("RID", basetype_color); + text_edit->add_keyword_color("Object", basetype_color); + text_edit->add_keyword_color("Callable", basetype_color); text_edit->add_keyword_color("Dictionary", basetype_color); text_edit->add_keyword_color("Array", basetype_color); text_edit->add_keyword_color("PackedByteArray", basetype_color); text_edit->add_keyword_color("PackedInt32Array", basetype_color); - text_edit->add_keyword_color("PackedFloat32Array", basetype_color); text_edit->add_keyword_color("PackedInt64Array", basetype_color); + text_edit->add_keyword_color("PackedFloat32Array", basetype_color); text_edit->add_keyword_color("PackedFloat64Array", basetype_color); text_edit->add_keyword_color("PackedStringArray", basetype_color); text_edit->add_keyword_color("PackedVector2Array", basetype_color); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 653ab153a1..2fb23f6a84 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -438,14 +438,22 @@ void VisualShaderEditor::_update_created_node(GraphNode *node) { if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) { Ref<StyleBoxFlat> sb = node->get_stylebox("frame", "GraphNode"); Color c = sb->get_border_color(); - Color mono_color = ((c.r + c.g + c.b) / 3) < 0.7 ? Color(1.0, 1.0, 1.0) : Color(0.0, 0.0, 0.0); + Color ic; + Color mono_color; + if (((c.r + c.g + c.b) / 3) < 0.7) { + mono_color = Color(1.0, 1.0, 1.0); + ic = Color(0.0, 0.0, 0.0, 0.7); + } else { + mono_color = Color(0.0, 0.0, 0.0); + ic = Color(1.0, 1.0, 1.0, 0.7); + } mono_color.a = 0.85; c = mono_color; node->add_color_override("title_color", c); c.a = 0.7; node->add_color_override("close_color", c); - node->add_color_override("resizer_color", c); + node->add_color_override("resizer_color", ic); } } @@ -1601,8 +1609,29 @@ void VisualShaderEditor::_graph_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; - if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) - _show_members_dialog(true); + if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) { + List<int> to_change; + for (int i = 0; i < graph->get_child_count(); i++) { + GraphNode *gn = Object::cast_to<GraphNode>(graph->get_child(i)); + if (gn) { + if (gn->is_selected() && gn->is_close_button_visible()) { + to_change.push_back(gn->get_name().operator String().to_int()); + } + } + } + if (to_change.empty() && copy_nodes_buffer.empty()) { + _show_members_dialog(true); + } else { + popup_menu->set_item_disabled(NodeMenuOptions::COPY, to_change.empty()); + popup_menu->set_item_disabled(NodeMenuOptions::PASTE, copy_nodes_buffer.empty()); + popup_menu->set_item_disabled(NodeMenuOptions::DELETE, to_change.empty()); + popup_menu->set_item_disabled(NodeMenuOptions::DUPLICATE, to_change.empty()); + menu_point = graph->get_local_mouse_position(); + Point2 gpos = Input::get_singleton()->get_mouse_position(); + popup_menu->set_position(gpos); + popup_menu->popup(); + } + } } void VisualShaderEditor::_show_members_dialog(bool at_mouse_pos) { @@ -1900,7 +1929,7 @@ void VisualShaderEditor::_copy_nodes() { _dup_copy_nodes(copy_type, copy_nodes_buffer, copy_nodes_excluded_buffer); } -void VisualShaderEditor::_paste_nodes() { +void VisualShaderEditor::_paste_nodes(bool p_use_custom_position, const Vector2 &p_custom_position) { if (copy_nodes_buffer.empty()) return; @@ -1911,12 +1940,19 @@ void VisualShaderEditor::_paste_nodes() { float scale = graph->get_zoom(); - _dup_paste_nodes(type, copy_type, copy_nodes_buffer, copy_nodes_excluded_buffer, (graph->get_scroll_ofs() / scale + graph->get_local_mouse_position() / scale - selection_center), false); + Vector2 mpos; + if (p_use_custom_position) { + mpos = p_custom_position; + } else { + mpos = graph->get_local_mouse_position(); + } + + _dup_paste_nodes(type, copy_type, copy_nodes_buffer, copy_nodes_excluded_buffer, (graph->get_scroll_ofs() / scale + mpos / scale - selection_center), false); _dup_update_excluded(type, copy_nodes_excluded_buffer); // to prevent selection of previous copies at new paste } -void VisualShaderEditor::_on_nodes_delete() { +void VisualShaderEditor::_delete_nodes() { VisualShader::Type type = VisualShader::Type(edit_type->get_selected()); List<int> to_erase; @@ -2102,6 +2138,26 @@ void VisualShaderEditor::_tools_menu_option(int p_idx) { } } +void VisualShaderEditor::_node_menu_id_pressed(int p_idx) { + switch (p_idx) { + case NodeMenuOptions::ADD: + _show_members_dialog(true); + break; + case NodeMenuOptions::COPY: + _copy_nodes(); + break; + case NodeMenuOptions::PASTE: + _paste_nodes(true, menu_point); + break; + case NodeMenuOptions::DELETE: + _delete_nodes(); + break; + case NodeMenuOptions::DUPLICATE: + _duplicate_nodes(); + break; + } +} + Variant VisualShaderEditor::get_drag_data_fw(const Point2 &p_point, Control *p_from) { if (p_from == members) { @@ -2240,7 +2296,7 @@ void VisualShaderEditor::_bind_methods() { ClassDB::bind_method("_node_selected", &VisualShaderEditor::_node_selected); ClassDB::bind_method("_scroll_changed", &VisualShaderEditor::_scroll_changed); ClassDB::bind_method("_delete_request", &VisualShaderEditor::_delete_request); - ClassDB::bind_method("_on_nodes_delete", &VisualShaderEditor::_on_nodes_delete); + ClassDB::bind_method("_delete_nodes", &VisualShaderEditor::_delete_nodes); ClassDB::bind_method("_node_changed", &VisualShaderEditor::_node_changed); ClassDB::bind_method("_edit_port_default_input", &VisualShaderEditor::_edit_port_default_input); ClassDB::bind_method("_port_edited", &VisualShaderEditor::_port_edited); @@ -2283,6 +2339,8 @@ void VisualShaderEditor::_bind_methods() { ClassDB::bind_method("_member_unselected", &VisualShaderEditor::_member_unselected); ClassDB::bind_method("_member_create", &VisualShaderEditor::_member_create); ClassDB::bind_method("_member_cancel", &VisualShaderEditor::_member_cancel); + + ClassDB::bind_method("_node_menu_id_pressed", &VisualShaderEditor::_node_menu_id_pressed); } VisualShaderEditor *VisualShaderEditor::singleton = NULL; @@ -2330,7 +2388,7 @@ VisualShaderEditor::VisualShaderEditor() { graph->connect_compat("duplicate_nodes_request", this, "_duplicate_nodes"); graph->connect_compat("copy_nodes_request", this, "_copy_nodes"); graph->connect_compat("paste_nodes_request", this, "_paste_nodes"); - graph->connect_compat("delete_nodes_request", this, "_on_nodes_delete"); + graph->connect_compat("delete_nodes_request", this, "_delete_nodes"); graph->connect_compat("gui_input", this, "_graph_gui_input"); graph->connect_compat("connection_to_empty", this, "_connection_to_empty"); graph->connect_compat("connection_from_empty", this, "_connection_from_empty"); @@ -2399,6 +2457,20 @@ VisualShaderEditor::VisualShaderEditor() { error_text->set_visible(false); /////////////////////////////////////// + // POPUP MENU + /////////////////////////////////////// + + popup_menu = memnew(PopupMenu); + add_child(popup_menu); + popup_menu->add_item("Add Node", NodeMenuOptions::ADD); + popup_menu->add_separator(); + popup_menu->add_item("Copy", NodeMenuOptions::COPY); + popup_menu->add_item("Paste", NodeMenuOptions::PASTE); + popup_menu->add_item("Delete", NodeMenuOptions::DELETE); + popup_menu->add_item("Duplicate", NodeMenuOptions::DUPLICATE); + popup_menu->connect_compat("id_pressed", this, "_node_menu_id_pressed"); + + /////////////////////////////////////// // SHADER NODES TREE /////////////////////////////////////// @@ -2636,7 +2708,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("CustomAlpha", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "custom_alpha"), "custom_alpha", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES)); add_options.push_back(AddOption("Delta", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "delta"), "delta", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES)); add_options.push_back(AddOption("EmissionTransform", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "emission_transform"), "emission_transform", VisualShaderNode::PORT_TYPE_TRANSFORM, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES)); - add_options.push_back(AddOption("Index", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "index"), "index", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES)); + add_options.push_back(AddOption("Index", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "index"), "index", VisualShaderNode::PORT_TYPE_SCALAR_INT, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES)); add_options.push_back(AddOption("LifeTime", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "lifetime"), "lifetime", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES)); add_options.push_back(AddOption("Restart", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "restart"), "restart", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES)); add_options.push_back(AddOption("Time", "Input", "Vertex", "VisualShaderNodeInput", vformat(input_param_for_vertex_shader_mode, "time"), "time", VisualShaderNode::PORT_TYPE_SCALAR, VisualShader::TYPE_VERTEX, Shader::MODE_PARTICLES)); diff --git a/editor/plugins/visual_shader_editor_plugin.h b/editor/plugins/visual_shader_editor_plugin.h index 8919690ada..8756fe9fe9 100644 --- a/editor/plugins/visual_shader_editor_plugin.h +++ b/editor/plugins/visual_shader_editor_plugin.h @@ -81,6 +81,7 @@ class VisualShaderEditor : public VBoxContainer { bool saved_node_pos_dirty; ConfirmationDialog *members_dialog; + PopupMenu *popup_menu; MenuButton *tools; bool preview_showed; @@ -90,6 +91,15 @@ class VisualShaderEditor : public VBoxContainer { COLLAPSE_ALL }; + enum NodeMenuOptions { + ADD, + SEPARATOR, // ignore + COPY, + PASTE, + DELETE, + DUPLICATE, + }; + Tree *members; AcceptDialog *alert; LineEdit *node_filter; @@ -181,7 +191,7 @@ class VisualShaderEditor : public VBoxContainer { void _node_selected(Object *p_node); void _delete_request(int); - void _on_nodes_delete(); + void _delete_nodes(); void _removed_from_graph(); @@ -216,7 +226,7 @@ class VisualShaderEditor : public VBoxContainer { void _clear_buffer(); void _copy_nodes(); - void _paste_nodes(); + void _paste_nodes(bool p_use_custom_position = false, const Vector2 &p_custom_position = Vector2()); Vector<Ref<VisualShaderNodePlugin> > plugins; @@ -250,6 +260,9 @@ class VisualShaderEditor : public VBoxContainer { void _member_create(); void _member_cancel(); + Vector2 menu_point; + void _node_menu_id_pressed(int p_idx); + Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); diff --git a/methods.py b/methods.py index 2e858e3865..3f03e6bbd2 100644 --- a/methods.py +++ b/methods.py @@ -558,19 +558,18 @@ def is_vanilla_clang(env): def get_compiler_version(env): """ - Returns an array of version numbers as strings: [major, minor, patch]. + Returns an array of version numbers as ints: [major, minor, patch]. The return array should have at least two values (major, minor). """ - if using_gcc(env): - version = decode_utf8(subprocess.check_output([env['CXX'], '-dumpversion']).strip()) - elif using_clang(env): - # Not using -dumpversion as it used to return 4.2.1: https://reviews.llvm.org/D56803 + if not env.msvc: + # Not using -dumpversion as some GCC distros only return major, and + # Clang used to return hardcoded 4.2.1: # https://reviews.llvm.org/D56803 version = decode_utf8(subprocess.check_output([env['CXX'], '--version']).strip()) else: # TODO: Implement for MSVC return None - match = re.search('[0-9]+\.[0-9.]*', version) + match = re.search('[0-9]+\.[0-9.]+', version) if match is not None: - return match.group().split('.') + return list(map(int, match.group().split('.'))) else: return None diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index 0e4c4b4731..f6df97f11d 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -726,9 +726,6 @@ void SpaceBullet::check_ghost_overlaps() { other_body_shape = static_cast<btCollisionShape *>(otherObject->get_bt_shape(z)); - if (other_body_shape->isConcave()) - continue; - btTransform other_shape_transform(otherObject->get_bt_shape_transform(z)); other_shape_transform.getOrigin() *= other_body_scale; diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 85265a1fe5..1bc1aae0d2 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -2172,8 +2172,8 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p } static const char *_type_names[Variant::VARIANT_MAX] = { - "null", "bool", "int", "float", "String", "Vector2", "Rect2", "Vector3", "Transform2D", "Plane", "Quat", "AABB", "Basis", "Transform", - "Color", "NodePath", "RID", "Object", "Callable", "Signal", "Dictionary", "Array", "PackedByteArray", "PackedInt32Array", "PackedInt64Array", "PackedFloat32Array", "PackedFloat64Array", "PackedStringArray", + "null", "bool", "int", "float", "String", "Vector2", "Vector2i", "Rect2", "Rect2i", "Vector3", "Vector3i", "Transform2D", "Plane", "Quat", "AABB", "Basis", "Transform", + "Color", "StringName", "NodePath", "RID", "Object", "Callable", "Signal", "Dictionary", "Array", "PackedByteArray", "PackedInt32Array", "PackedInt64Array", "PackedFloat32Array", "PackedFloat64Array", "PackedStringArray", "PackedVector2Array", "PackedVector3Array", "PackedColorArray" }; diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs index c3db52aa9e..af8d070cbd 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/MsBuildFinder.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.IO; using Godot; +using GodotTools.Ides.Rider; using GodotTools.Internals; using Directory = System.IO.Directory; using Environment = System.Environment; @@ -54,6 +55,12 @@ namespace GodotTools.Build return msbuildPath; } + case BuildManager.BuildTool.JetBrainsMsBuild: + var editorPath = (string)editorSettings.GetSetting(RiderPathManager.EditorPathSettingName); + if (!File.Exists(editorPath)) + throw new FileNotFoundException($"Cannot find Rider executable. Tried with path: {editorPath}"); + var riderDir = new FileInfo(editorPath).Directory.Parent; + return Path.Combine(riderDir.FullName, @"tools\MSBuild\Current\Bin\MSBuild.exe"); default: throw new IndexOutOfRangeException("Invalid build tool in editor settings"); } diff --git a/modules/mono/editor/GodotTools/GodotTools/BuildManager.cs b/modules/mono/editor/GodotTools/GodotTools/BuildManager.cs index fa6bf4dafd..69a8c9cf4a 100644 --- a/modules/mono/editor/GodotTools/GodotTools/BuildManager.cs +++ b/modules/mono/editor/GodotTools/GodotTools/BuildManager.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using GodotTools.Build; +using GodotTools.Ides.Rider; using GodotTools.Internals; using GodotTools.Utils; using static GodotTools.Internals.Globals; @@ -16,6 +17,7 @@ namespace GodotTools public const string PropNameMsbuildMono = "MSBuild (Mono)"; public const string PropNameMsbuildVs = "MSBuild (VS Build Tools)"; + public const string PropNameMsbuildJetBrains = "MSBuild (JetBrains Rider)"; public const string MsBuildIssuesFileName = "msbuild_issues.csv"; public const string MsBuildLogFileName = "msbuild_log.txt"; @@ -23,7 +25,8 @@ namespace GodotTools public enum BuildTool { MsBuildMono, - MsBuildVs + MsBuildVs, + JetBrainsMsBuild } private static void RemoveOldIssuesFile(BuildInfo buildInfo) @@ -181,7 +184,7 @@ namespace GodotTools var buildInfo = new BuildInfo(GodotSharpDirs.ProjectSlnPath, config); // Add Godot defines - string constants = buildTool == BuildTool.MsBuildVs ? "GodotDefineConstants=\"" : "GodotDefineConstants=\\\""; + string constants = buildTool != BuildTool.MsBuildMono ? "GodotDefineConstants=\"" : "GodotDefineConstants=\\\""; foreach (var godotDefine in godotDefines) constants += $"GODOT_{godotDefine.ToUpper().Replace("-", "_").Replace(" ", "_").Replace(";", "_")};"; @@ -189,7 +192,7 @@ namespace GodotTools if (Internal.GodotIsRealTDouble()) constants += "GODOT_REAL_T_IS_DOUBLE;"; - constants += buildTool == BuildTool.MsBuildVs ? "\"" : "\\\""; + constants += buildTool != BuildTool.MsBuildMono ? "\"" : "\\\""; buildInfo.CustomProperties.Add(constants); @@ -245,18 +248,22 @@ namespace GodotTools public static void Initialize() { // Build tool settings - - EditorDef("mono/builds/build_tool", OS.IsWindows ? BuildTool.MsBuildVs : BuildTool.MsBuildMono); - var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings(); - + var msbuild = BuildTool.MsBuildMono; + if (OS.IsWindows) + msbuild = RiderPathManager.IsRider((string) editorSettings.GetSetting(RiderPathManager.EditorPathSettingName)) + ? BuildTool.JetBrainsMsBuild + : BuildTool.MsBuildVs; + + EditorDef("mono/builds/build_tool", msbuild); + editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary { ["type"] = Godot.Variant.Type.Int, ["name"] = "mono/builds/build_tool", ["hint"] = Godot.PropertyHint.Enum, ["hint_string"] = OS.IsWindows ? - $"{PropNameMsbuildMono},{PropNameMsbuildVs}" : + $"{PropNameMsbuildMono},{PropNameMsbuildVs},{PropNameMsbuildJetBrains}" : $"{PropNameMsbuildMono}" }); diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs index 9038333d38..5965e0fbcf 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathLocator.cs @@ -11,6 +11,10 @@ using Environment = System.Environment; using File = System.IO.File; using Path = System.IO.Path; using OS = GodotTools.Utils.OS; +// ReSharper disable UnassignedField.Local +// ReSharper disable InconsistentNaming +// ReSharper disable UnassignedField.Global +// ReSharper disable MemberHidesStaticFromOuterClass namespace GodotTools.Ides.Rider { @@ -131,28 +135,45 @@ namespace GodotTools.Ides.Rider if (OS.IsWindows) { var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); - return Path.Combine(localAppData, @"JetBrains\Toolbox\apps\Rider"); + return GetToolboxRiderRootPath(localAppData); } if (OS.IsOSX) { var home = Environment.GetEnvironmentVariable("HOME"); - if (!string.IsNullOrEmpty(home)) - { - return Path.Combine(home, @"Library/Application Support/JetBrains/Toolbox/apps/Rider"); - } + if (string.IsNullOrEmpty(home)) + return string.Empty; + var localAppData = Path.Combine(home, @"Library/Application Support"); + return GetToolboxRiderRootPath(localAppData); } if (OS.IsUnixLike()) { var home = Environment.GetEnvironmentVariable("HOME"); - if (!string.IsNullOrEmpty(home)) - { - return Path.Combine(home, @".local/share/JetBrains/Toolbox/apps/Rider"); - } + if (string.IsNullOrEmpty(home)) + return string.Empty; + var localAppData = Path.Combine(home, @".local/share"); + return GetToolboxRiderRootPath(localAppData); + } + + return string.Empty; + } + + + private static string GetToolboxRiderRootPath(string localAppData) + { + var toolboxPath = Path.Combine(localAppData, @"JetBrains\Toolbox"); + var settingsJson = Path.Combine(toolboxPath, ".settings.json"); + + if (File.Exists(settingsJson)) + { + var path = SettingsJson.GetInstallLocationFromJson(File.ReadAllText(settingsJson)); + if (!string.IsNullOrEmpty(path)) + toolboxPath = path; } - throw new Exception("Unexpected OS."); + var toolboxRiderRootPath = Path.Combine(toolboxPath, @"apps\Rider"); + return toolboxRiderRootPath; } internal static ProductInfo GetBuildVersion(string path) @@ -226,8 +247,8 @@ namespace GodotTools.Ides.Rider { try { - // use history.json - last entry stands for the active build https://jetbrains.slack.com/archives/C07KNP99D/p1547807024066500?thread_ts=1547731708.057700&cid=C07KNP99D - var historyFile = Path.Combine(channelDir, ".history.json"); + // use history.json - last entry stands for the active build https://jetbrains.slack.com/archives/C07KNP99D/p1547807024066500?thread_ts=1547731708.057700&cid=C07KNP99D + var historyFile = Path.Combine(channelDir, ".history.json"); if (File.Exists(historyFile)) { var json = File.ReadAllText(historyFile); @@ -255,14 +276,14 @@ namespace GodotTools.Ides.Rider } } - // changes in toolbox json files format may brake the logic above, so return all found Rider installations - return Directory.GetDirectories(channelDir) - .SelectMany(buildDir => GetExecutablePaths(dirName, searchPattern, isMac, buildDir)); + // changes in toolbox json files format may brake the logic above, so return all found Rider installations + return Directory.GetDirectories(channelDir) + .SelectMany(buildDir => GetExecutablePaths(dirName, searchPattern, isMac, buildDir)); } catch (Exception e) { - // do not write to Debug.Log, just log it. - Logger.Warn($"Failed to get RiderPath from {channelDir}", e); + // do not write to Debug.Log, just log it. + Logger.Warn($"Failed to get RiderPath from {channelDir}", e); } return new string[0]; @@ -289,6 +310,27 @@ namespace GodotTools.Ides.Rider #pragma warning disable 0649 [Serializable] + class SettingsJson + { + public string install_location; + + [CanBeNull] + public static string GetInstallLocationFromJson(string json) + { + try + { + return JsonConvert.DeserializeObject<SettingsJson>(json).install_location; + } + catch (Exception) + { + Logger.Warn($"Failed to get install_location from json {json}"); + } + + return null; + } + } + + [Serializable] class ToolboxHistory { public List<ItemNode> history; @@ -372,7 +414,6 @@ namespace GodotTools.Ides.Rider [Serializable] class ActiveApplication { - // ReSharper disable once InconsistentNaming public List<string> builds; } @@ -380,6 +421,7 @@ namespace GodotTools.Ides.Rider public struct RiderInfo { + // ReSharper disable once NotAccessedField.Global public bool IsToolbox; public string Presentation; public Version BuildNumber; diff --git a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs index 558a242bf9..ee5677a6a8 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Ides/Rider/RiderPathManager.cs @@ -9,13 +9,13 @@ namespace GodotTools.Ides.Rider { public static class RiderPathManager { - private static readonly string editorPathSettingName = "mono/editor/editor_path_optional"; + public static readonly string EditorPathSettingName = "mono/editor/editor_path_optional"; private static string GetRiderPathFromSettings() { var editorSettings = GodotSharpEditor.Instance.GetEditorInterface().GetEditorSettings(); - if (editorSettings.HasSetting(editorPathSettingName)) - return (string)editorSettings.GetSetting(editorPathSettingName); + if (editorSettings.HasSetting(EditorPathSettingName)) + return (string)editorSettings.GetSetting(EditorPathSettingName); return null; } @@ -25,22 +25,22 @@ namespace GodotTools.Ides.Rider var editor = (ExternalEditorId)editorSettings.GetSetting("mono/editor/external_editor"); if (editor == ExternalEditorId.Rider) { - if (!editorSettings.HasSetting(editorPathSettingName)) + if (!editorSettings.HasSetting(EditorPathSettingName)) { - Globals.EditorDef(editorPathSettingName, "Optional"); + Globals.EditorDef(EditorPathSettingName, "Optional"); editorSettings.AddPropertyInfo(new Godot.Collections.Dictionary { ["type"] = Variant.Type.String, - ["name"] = editorPathSettingName, + ["name"] = EditorPathSettingName, ["hint"] = PropertyHint.File, ["hint_string"] = "" }); } - var riderPath = (string)editorSettings.GetSetting(editorPathSettingName); + var riderPath = (string)editorSettings.GetSetting(EditorPathSettingName); if (IsRiderAndExists(riderPath)) { - Globals.EditorDef(editorPathSettingName, riderPath); + Globals.EditorDef(EditorPathSettingName, riderPath); return; } @@ -50,17 +50,15 @@ namespace GodotTools.Ides.Rider return; var newPath = paths.Last().Path; - Globals.EditorDef(editorPathSettingName, newPath); - editorSettings.SetSetting(editorPathSettingName, newPath); + Globals.EditorDef(EditorPathSettingName, newPath); + editorSettings.SetSetting(EditorPathSettingName, newPath); } } - private static bool IsRider(string path) + public static bool IsRider(string path) { if (string.IsNullOrEmpty(path)) - { return false; - } var fileInfo = new FileInfo(path); var filename = fileInfo.Name.ToLowerInvariant(); @@ -81,8 +79,8 @@ namespace GodotTools.Ides.Rider return null; var newPath = paths.Last().Path; - editorSettings.SetSetting(editorPathSettingName, newPath); - Globals.EditorDef(editorPathSettingName, newPath); + editorSettings.SetSetting(EditorPathSettingName, newPath); + Globals.EditorDef(EditorPathSettingName, newPath); return newPath; } diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 8d58cb9c4d..0bbef066a4 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -623,16 +623,24 @@ void VisualScriptEditor::_update_graph(int p_only_id) { sbf = EditorNode::get_singleton()->get_theme_base()->get_theme()->get_stylebox("comment", "GraphNode"); Color c = sbf->get_border_color(); + Color ic = c; c.a = 1; if (EditorSettings::get_singleton()->get("interface/theme/use_graph_node_headers")) { - Color mono_color = ((c.r + c.g + c.b) / 3) < 0.7 ? Color(1.0, 1.0, 1.0) : Color(0.0, 0.0, 0.0); + Color mono_color; + if (((c.r + c.g + c.b) / 3) < 0.7) { + mono_color = Color(1.0, 1.0, 1.0); + ic = Color(0.0, 0.0, 0.0, 0.7); + } else { + mono_color = Color(0.0, 0.0, 0.0); + ic = Color(1.0, 1.0, 1.0, 0.7); + } mono_color.a = 0.85; c = mono_color; } gnode->add_color_override("title_color", c); c.a = 0.7; gnode->add_color_override("close_color", c); - gnode->add_color_override("resizer_color", c); + gnode->add_color_override("resizer_color", ic); gnode->add_style_override("frame", sbf); } diff --git a/platform/server/detect.py b/platform/server/detect.py index d82df77957..ef94dc436c 100644 --- a/platform/server/detect.py +++ b/platform/server/detect.py @@ -32,6 +32,7 @@ def get_opts(): return [ BoolVariable('use_llvm', 'Use the LLVM compiler', False), BoolVariable('use_static_cpp', 'Link libgcc and libstdc++ statically for better portability', False), + BoolVariable('use_coverage', 'Test Godot coverage', False), BoolVariable('use_ubsan', 'Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)', False), BoolVariable('use_asan', 'Use LLVM/GCC compiler address sanitizer (ASAN))', False), BoolVariable('use_lsan', 'Use LLVM/GCC compiler leak sanitizer (LSAN))', False), @@ -99,6 +100,9 @@ def configure(env): env.Append(CPPDEFINES=['TYPED_METHOD_BIND']) env.extra_suffix = ".llvm" + env.extra_suffix + if env['use_coverage']: + env.Append(CCFLAGS=['-ftest-coverage', '-fprofile-arcs']) + env.Append(LINKFLAGS=['-ftest-coverage', '-fprofile-arcs']) if env['use_ubsan'] or env['use_asan'] or env['use_lsan'] or env['use_tsan']: env.extra_suffix += "s" diff --git a/platform/x11/detect.py b/platform/x11/detect.py index 9d5affcb3c..cd22ee9ff6 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -61,6 +61,7 @@ def get_opts(): BoolVariable('use_lld', 'Use the LLD linker', False), BoolVariable('use_thinlto', 'Use ThinLTO', False), BoolVariable('use_static_cpp', 'Link libgcc and libstdc++ statically for better portability', False), + BoolVariable('use_coverage', 'Test Godot coverage', False), BoolVariable('use_ubsan', 'Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)', False), BoolVariable('use_asan', 'Use LLVM/GCC compiler address sanitizer (ASAN))', False), BoolVariable('use_lsan', 'Use LLVM/GCC compiler leak sanitizer (LSAN))', False), @@ -141,6 +142,10 @@ def configure(env): print("Using LLD with GCC is not supported yet, try compiling with 'use_llvm=yes'.") sys.exit(255) + if env['use_coverage']: + env.Append(CCFLAGS=['-ftest-coverage', '-fprofile-arcs']) + env.Append(LINKFLAGS=['-ftest-coverage', '-fprofile-arcs']) + if env['use_ubsan'] or env['use_asan'] or env['use_lsan'] or env['use_tsan']: env.extra_suffix += "s" @@ -179,18 +184,10 @@ def configure(env): env.Append(CCFLAGS=['-pipe']) env.Append(LINKFLAGS=['-pipe']) - # Check for gcc version >= 6 before adding -no-pie - if using_gcc(env): - version = get_compiler_version(env) - if version != None and version[0] >= '6': - env.Append(CCFLAGS=['-fpie']) - env.Append(LINKFLAGS=['-no-pie']) - # Do the same for clang should be fine with Clang 4 and higher - if using_clang(env): - version = get_compiler_version(env) - if version != None and version[0] >= '4': - env.Append(CCFLAGS=['-fpie']) - env.Append(LINKFLAGS=['-no-pie']) + # -fpie and -no-pie is supported on GCC 6+ and Clang 4+, both below our + # minimal requirements. + env.Append(CCFLAGS=['-fpie']) + env.Append(LINKFLAGS=['-no-pie']) ## Dependencies diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 0d3ab36852..fb8396e4ff 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -358,11 +358,20 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { [[fallthrough]]; } case KEY_LEFT: { - #ifndef APPLE_STYLE_KEYS - if (!k->get_alt()) + if (!k->get_alt()) { #endif + if (selection.enabled && !k->get_shift()) { + set_cursor_position(selection.begin); + deselect(); + handled = true; + break; + } + shift_selection_check_pre(k->get_shift()); +#ifndef APPLE_STYLE_KEYS + } +#endif #ifdef APPLE_STYLE_KEYS if (k->get_command()) { @@ -405,8 +414,20 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { [[fallthrough]]; } case KEY_RIGHT: { +#ifndef APPLE_STYLE_KEYS + if (!k->get_alt()) { +#endif + if (selection.enabled && !k->get_shift()) { + set_cursor_position(selection.end); + deselect(); + handled = true; + break; + } - shift_selection_check_pre(k->get_shift()); + shift_selection_check_pre(k->get_shift()); +#ifndef APPLE_STYLE_KEYS + } +#endif #ifdef APPLE_STYLE_KEYS if (k->get_command()) { diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 5baa59fe7c..a0159c3858 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -2800,7 +2800,7 @@ void Node::_bind_methods() { GLOBAL_DEF("node/name_casing", NAME_CASING_PASCAL_CASE); ProjectSettings::get_singleton()->set_custom_property_info("node/name_casing", PropertyInfo(Variant::INT, "node/name_casing", PROPERTY_HINT_ENUM, "PascalCase,camelCase,snake_case")); - ClassDB::bind_method(D_METHOD("add_child_below_node", "node", "child_node", "legible_unique_name"), &Node::add_child_below_node, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("add_child_below_node", "preceding_node", "node", "legible_unique_name"), &Node::add_child_below_node, DEFVAL(false)); ClassDB::bind_method(D_METHOD("set_name", "name"), &Node::set_name); ClassDB::bind_method(D_METHOD("get_name"), &Node::get_name); diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index 86b2e78e8e..556d299198 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -1642,7 +1642,7 @@ const VisualShaderNodeInput::Port VisualShaderNodeInput::ports[] = { { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "delta", "DELTA" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "lifetime", "LIFETIME" }, - { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "index", "float(INDEX)" }, + { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR_INT, "index", "INDEX" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_TRANSFORM, "emission_transform", "EMISSION_TRANSFORM" }, { Shader::MODE_PARTICLES, VisualShader::TYPE_VERTEX, VisualShaderNode::PORT_TYPE_SCALAR, "time", "TIME" }, diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp index a33c94fbcd..dd6bece11d 100644 --- a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp +++ b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp @@ -1894,8 +1894,16 @@ void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transfor if (draw_sky) { RENDER_TIMESTAMP("Render Sky"); + + CameraMatrix projection = p_cam_projection; + if (p_reflection_probe.is_valid()) { + CameraMatrix correction; + correction.set_depth_correction(true); + projection = correction * p_cam_projection; + } + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); - _draw_sky(draw_list, RD::get_singleton()->framebuffer_get_format(opaque_framebuffer), p_environment, p_cam_projection, p_cam_transform, 1.0); + _draw_sky(draw_list, RD::get_singleton()->framebuffer_get_format(opaque_framebuffer), p_environment, projection, p_cam_transform, 1.0); RD::get_singleton()->draw_list_end(); if (using_separate_specular && !can_continue) { |