diff options
26 files changed, 290 insertions, 90 deletions
diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 391c293810..483565648a 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -860,42 +860,42 @@ struct _VariantCall { VCALL_PTR1R(Transform2D, is_equal_approx); static void _call_Transform2D_xform(Variant &r_ret, Variant &p_self, const Variant **p_args) { - switch (p_args[0]->type) { - case Variant::VECTOR2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator Vector2()); return; case Variant::RECT2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator Rect2()); return; case Variant::PACKED_VECTOR2_ARRAY: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform(p_args[0]->operator PackedVector2Array()); return; - default: r_ret = Variant(); + default: + r_ret = Variant(); + ERR_PRINT("Invalid type in function 'xform' in base 'Transform2D'. Valid types are Vector2, Rect2, and PackedVector2Array."); } } static void _call_Transform2D_xform_inv(Variant &r_ret, Variant &p_self, const Variant **p_args) { - switch (p_args[0]->type) { - case Variant::VECTOR2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Vector2()); return; case Variant::RECT2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Rect2()); return; case Variant::PACKED_VECTOR2_ARRAY: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->xform_inv(p_args[0]->operator PackedVector2Array()); return; - default: r_ret = Variant(); + default: + r_ret = Variant(); + ERR_PRINT("Invalid type in function 'xform_inv' in base 'Transform2D'. Valid types are Vector2, Rect2, and PackedVector2Array."); } } static void _call_Transform2D_basis_xform(Variant &r_ret, Variant &p_self, const Variant **p_args) { - switch (p_args[0]->type) { - case Variant::VECTOR2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->basis_xform(p_args[0]->operator Vector2()); return; - default: r_ret = Variant(); + default: + r_ret = Variant(); + ERR_PRINT("Invalid type in function 'basis_xform' in base 'Transform2D'. Only Vector2 is valid."); } } static void _call_Transform2D_basis_xform_inv(Variant &r_ret, Variant &p_self, const Variant **p_args) { - switch (p_args[0]->type) { - case Variant::VECTOR2: r_ret = reinterpret_cast<Transform2D *>(p_self._data._ptr)->basis_xform_inv(p_args[0]->operator Vector2()); return; - default: r_ret = Variant(); + default: + r_ret = Variant(); + ERR_PRINT("Invalid type in function 'basis_xform_inv' in base 'Transform2D'. Only Vector2 is valid."); } } @@ -928,37 +928,29 @@ struct _VariantCall { VCALL_PTR1R(Transform, is_equal_approx); static void _call_Transform_xform(Variant &r_ret, Variant &p_self, const Variant **p_args) { - switch (p_args[0]->type) { - case Variant::VECTOR3: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator Vector3()); return; case Variant::PLANE: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator Plane()); return; case Variant::AABB: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator ::AABB()); return; case Variant::PACKED_VECTOR3_ARRAY: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform(p_args[0]->operator ::PackedVector3Array()); return; - default: r_ret = Variant(); + default: + r_ret = Variant(); + ERR_PRINT("Invalid type in function 'xform' in base 'Transform'. Valid types are Vector3, Plane, AABB, and PackedVector3Array."); } } static void _call_Transform_xform_inv(Variant &r_ret, Variant &p_self, const Variant **p_args) { - switch (p_args[0]->type) { - case Variant::VECTOR3: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Vector3()); return; case Variant::PLANE: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator Plane()); return; case Variant::AABB: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator ::AABB()); return; case Variant::PACKED_VECTOR3_ARRAY: r_ret = reinterpret_cast<Transform *>(p_self._data._ptr)->xform_inv(p_args[0]->operator ::PackedVector3Array()); return; - default: r_ret = Variant(); + default: + r_ret = Variant(); + ERR_PRINT("Invalid type in function 'xform_inv' in base 'Transform'. Valid types are Vector3, Plane, AABB, and PackedVector3Array."); } } - /* - VCALL_PTR0( Transform, invert ); - VCALL_PTR0( Transform, affine_invert ); - VCALL_PTR2( Transform, rotate ); - VCALL_PTR1( Transform, scale ); - VCALL_PTR1( Transform, translate ); - VCALL_PTR0( Transform, orthonormalize ); */ - struct ConstructData { int arg_count; diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index 47b9c80f3f..b3cd1c1af7 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -155,7 +155,7 @@ Tab key. </constant> <constant name="KEY_BACKTAB" value="16777219" enum="KeyList"> - Shift+Tab key. + Shift + Tab key. </constant> <constant name="KEY_BACKSPACE" value="16777220" enum="KeyList"> Backspace key. diff --git a/doc/classes/AnimatedTexture.xml b/doc/classes/AnimatedTexture.xml index 80b910aaa7..ddd51cc6b3 100644 --- a/doc/classes/AnimatedTexture.xml +++ b/doc/classes/AnimatedTexture.xml @@ -61,6 +61,9 @@ </method> </methods> <members> + <member name="current_frame" type="int" setter="set_current_frame" getter="get_current_frame"> + Sets the currently visible frame of the texture. + </member> <member name="fps" type="float" setter="set_fps" getter="get_fps" default="4.0"> Animation speed in frames per second. This value defines the default time interval between two frames of the animation, and thus the overall duration of the animation loop based on the [member frames] property. A value of 0 means no predefined number of frames per second, the animation will play according to each frame's frame delay (see [method set_frame_delay]). For example, an animation with 8 frames, no frame delay and a [code]fps[/code] value of 2 will run for 4 seconds, with each frame lasting 0.5 seconds. @@ -68,6 +71,12 @@ <member name="frames" type="int" setter="set_frames" getter="get_frames" default="1"> Number of frames to use in the animation. While you can create the frames independently with [method set_frame_texture], you need to set this value for the animation to take new frames into account. The maximum number of frames is [constant MAX_FRAMES]. </member> + <member name="oneshot" type="bool" setter="set_oneshot" getter="get_oneshot" default="false"> + If [code]true[/code], the animation will only play once and will not loop back to the first frame after reaching the end. Note that reaching the end will not set [member pause] to [code]true[/code]. + </member> + <member name="pause" type="bool" setter="set_pause" getter="get_pause" default="false"> + If [code]true[/code], the animation will pause where it currently is (i.e. at [member current_frame]). The animation will continue from where it was paused when changing this property to [code]false[/code]. + </member> </members> <constants> <constant name="MAX_FRAMES" value="256"> diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index 0c8d42021a..9dbb843902 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -798,11 +798,11 @@ Tells Godot which node it should give keyboard focus to if the user presses the top arrow on the keyboard or top on a gamepad by default. You can change the key by editing the [code]ui_top[/code] input action. The node must be a [Control]. If this property is not set, Godot will give focus to the closest [Control] to the bottom of this one. </member> <member name="focus_next" type="NodePath" setter="set_focus_next" getter="get_focus_next" default="NodePath("")"> - Tells Godot which node it should give keyboard focus to if the user presses Tab on a keyboard by default. You can change the key by editing the [code]ui_focus_next[/code] input action. + Tells Godot which node it should give keyboard focus to if the user presses [kbd]Tab[/kbd] on a keyboard by default. You can change the key by editing the [code]ui_focus_next[/code] input action. If this property is not set, Godot will select a "best guess" based on surrounding nodes in the scene tree. </member> <member name="focus_previous" type="NodePath" setter="set_focus_previous" getter="get_focus_previous" default="NodePath("")"> - Tells Godot which node it should give keyboard focus to if the user presses Shift+Tab on a keyboard by default. You can change the key by editing the [code]ui_focus_prev[/code] input action. + Tells Godot which node it should give keyboard focus to if the user presses [kbd]Shift + Tab[/kbd] on a keyboard by default. You can change the key by editing the [code]ui_focus_prev[/code] input action. If this property is not set, Godot will select a "best guess" based on surrounding nodes in the scene tree. </member> <member name="grow_horizontal" type="int" setter="set_h_grow_direction" getter="get_h_grow_direction" enum="Control.GrowDirection" default="1"> diff --git a/doc/classes/EditorScript.xml b/doc/classes/EditorScript.xml index 410301351f..e96044bf48 100644 --- a/doc/classes/EditorScript.xml +++ b/doc/classes/EditorScript.xml @@ -4,7 +4,7 @@ Base script that can be used to add extension functions to the editor. </brief_description> <description> - Scripts extending this class and implementing its [method _run] method can be executed from the Script Editor's [b]File > Run[/b] menu option (or by pressing [code]Ctrl+Shift+X[/code]) while the editor is running. This is useful for adding custom in-editor functionality to Godot. For more complex additions, consider using [EditorPlugin]s instead. + Scripts extending this class and implementing its [method _run] method can be executed from the Script Editor's [b]File > Run[/b] menu option (or by pressing [kbd]Ctrl + Shift + X[/kbd]) while the editor is running. This is useful for adding custom in-editor functionality to Godot. For more complex additions, consider using [EditorPlugin]s instead. [b]Note:[/b] Extending scripts need to have [code]tool[/code] mode enabled. [b]Example script:[/b] [codeblock] diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml index 750ac8085c..9d00ffe233 100644 --- a/doc/classes/GraphEdit.xml +++ b/doc/classes/GraphEdit.xml @@ -240,7 +240,7 @@ </signal> <signal name="copy_nodes_request"> <description> - Emitted when the user presses [code]Ctrl + C[/code]. + Emitted when the user presses [kbd]Ctrl + C[/kbd]. </description> </signal> <signal name="delete_nodes_request"> @@ -281,7 +281,7 @@ </signal> <signal name="paste_nodes_request"> <description> - Emitted when the user presses [code]Ctrl + V[/code]. + Emitted when the user presses [kbd]Ctrl + V[/kbd]. </description> </signal> <signal name="popup_request"> diff --git a/doc/classes/InputEventKey.xml b/doc/classes/InputEventKey.xml index 34afa90553..767e67c615 100644 --- a/doc/classes/InputEventKey.xml +++ b/doc/classes/InputEventKey.xml @@ -14,7 +14,7 @@ <return type="int"> </return> <description> - Returns the keycode combined with modifier keys such as [code]Shift[/code] or [code]Alt[/code]. See also [InputEventWithModifiers]. + Returns the keycode combined with modifier keys such as [kbd]Shift[/kbd] or [kbd]Alt[/kbd]. See also [InputEventWithModifiers]. To get a human-readable representation of the [InputEventKey] with modifiers, use [code]OS.get_keycode_string(event.get_keycode_with_modifiers())[/code] where [code]event[/code] is the [InputEventKey]. </description> </method> @@ -22,7 +22,7 @@ <return type="int"> </return> <description> - Returns the physical keycode combined with modifier keys such as [code]Shift[/code] or [code]Alt[/code]. See also [InputEventWithModifiers]. + Returns the physical keycode combined with modifier keys such as [kbd]Shift[/kbd] or [kbd]Alt[/kbd]. See also [InputEventWithModifiers]. To get a human-readable representation of the [InputEventKey] with modifiers, use [code]OS.get_keycode_string(event.get_physical_keycode_with_modifiers())[/code] where [code]event[/code] is the [InputEventKey]. </description> </method> diff --git a/doc/classes/InputEventWithModifiers.xml b/doc/classes/InputEventWithModifiers.xml index 34faf18e24..cc7de2ca32 100644 --- a/doc/classes/InputEventWithModifiers.xml +++ b/doc/classes/InputEventWithModifiers.xml @@ -4,7 +4,7 @@ Base class for keys events with modifiers. </brief_description> <description> - Contains keys events information with modifiers support like [code]Shift[/code] or [code]Alt[/code]. See [method Node._input]. + Contains keys events information with modifiers support like [kbd]Shift[/kbd] or [kbd]Alt[/kbd]. See [method Node._input]. </description> <tutorials> <link>https://docs.godotengine.org/en/latest/tutorials/inputs/inputevent.html</link> @@ -13,19 +13,19 @@ </methods> <members> <member name="alt" type="bool" setter="set_alt" getter="get_alt" default="false"> - State of the [code]Alt[/code] modifier. + State of the [kbd]Alt[/kbd] modifier. </member> <member name="command" type="bool" setter="set_command" getter="get_command" default="false"> - State of the [code]Command[/code] modifier. + State of the [kbd]Cmd[/kbd] modifier. </member> <member name="control" type="bool" setter="set_control" getter="get_control" default="false"> - State of the [code]Ctrl[/code] modifier. + State of the [kbd]Ctrl[/kbd] modifier. </member> <member name="meta" type="bool" setter="set_metakey" getter="get_metakey" default="false"> - State of the [code]Meta[/code] modifier. + State of the [kbd]Meta[/kbd] modifier. </member> <member name="shift" type="bool" setter="set_shift" getter="get_shift" default="false"> - State of the [code]Shift[/code] modifier. + State of the [kbd]Shift[/kbd] modifier. </member> </members> <constants> diff --git a/doc/classes/ItemList.xml b/doc/classes/ItemList.xml index c6ed1e22ed..25420bd77b 100644 --- a/doc/classes/ItemList.xml +++ b/doc/classes/ItemList.xml @@ -5,7 +5,7 @@ </brief_description> <description> This control provides a selectable list of items that may be in a single (or multiple columns) with option of text, icons, or both text and icon. Tooltips are supported and may be different for every item in the list. - Selectable items in the list may be selected or deselected and multiple selection may be enabled. Selection with right mouse button may also be enabled to allow use of popup context menus. Items may also be "activated" by double-clicking them or by pressing Enter. + Selectable items in the list may be selected or deselected and multiple selection may be enabled. Selection with right mouse button may also be enabled to allow use of popup context menus. Items may also be "activated" by double-clicking them or by pressing [kbd]Enter[/kbd]. Item text only supports single-line strings, newline characters (e.g. [code]\n[/code]) in the string won't produce a newline. Text wrapping is enabled in [constant ICON_MODE_TOP] mode, but column's width is adjusted to fully fit its content by default. You need to set [member fixed_column_width] greater than zero to wrap the text. </description> <tutorials> @@ -278,7 +278,7 @@ </argument> <description> Disables (or enables) the item at the specified index. - Disabled items cannot be selected and do not trigger activation signals (when double-clicking or pressing Enter). + Disabled items cannot be selected and do not trigger activation signals (when double-clicking or pressing [kbd]Enter[/kbd]). </description> </method> <method name="set_item_icon"> @@ -452,7 +452,7 @@ <argument index="0" name="index" type="int"> </argument> <description> - Triggered when specified list item is activated via double-clicking or by pressing Enter. + Triggered when specified list item is activated via double-clicking or by pressing [kbd]Enter[/kbd]. </description> </signal> <signal name="item_rmb_selected"> @@ -508,7 +508,7 @@ Only allow selecting a single item. </constant> <constant name="SELECT_MULTI" value="1" enum="SelectMode"> - Allows selecting multiple items by holding Ctrl or Shift. + Allows selecting multiple items by holding [kbd]Ctrl[/kbd] or [kbd]Shift[/kbd]. </constant> </constants> <theme_items> diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml index 447446ba10..3eeb892719 100644 --- a/doc/classes/LineEdit.xml +++ b/doc/classes/LineEdit.xml @@ -5,27 +5,27 @@ </brief_description> <description> LineEdit provides a single-line string editor, used for text fields. - It features many built-in shortcuts which will always be available ([code]Ctrl[/code] here maps to [code]Command[/code] on macOS): - - Ctrl + C: Copy - - Ctrl + X: Cut - - Ctrl + V or Ctrl + Y: Paste/"yank" - - Ctrl + Z: Undo - - Ctrl + Shift + Z: Redo - - Ctrl + U: Delete text from the cursor position to the beginning of the line - - Ctrl + K: Delete text from the cursor position to the end of the line - - Ctrl + A: Select all text - - Up/Down arrow: Move the cursor to the beginning/end of the line + It features many built-in shortcuts which will always be available ([kbd]Ctrl[/kbd] here maps to [kbd]Cmd[/kbd] on macOS): + - [kbd]Ctrl + C[/kbd]: Copy + - [kbd]Ctrl + X[/kbd]: Cut + - [kbd]Ctrl + V[/kbd] or [kbd]Ctrl + Y[/kbd]: Paste/"yank" + - [kbd]Ctrl + Z[/kbd]: Undo + - [kbd]Ctrl + Shift + Z[/kbd]: Redo + - [kbd]Ctrl + U[/kbd]: Delete text from the cursor position to the beginning of the line + - [kbd]Ctrl + K[/kbd]: Delete text from the cursor position to the end of the line + - [kbd]Ctrl + A[/kbd]: Select all text + - [kbd]Up Arrow[/kbd]/[kbd]Down Arrow[/kbd]: Move the cursor to the beginning/end of the line On macOS, some extra keyboard shortcuts are available: - - Ctrl + F: Like the right arrow key, move the cursor one character right - - Ctrl + B: Like the left arrow key, move the cursor one character left - - Ctrl + P: Like the up arrow key, move the cursor to the previous line - - Ctrl + N: Like the down arrow key, move the cursor to the next line - - Ctrl + D: Like the Delete key, delete the character on the right side of cursor - - Ctrl + H: Like the Backspace key, delete the character on the left side of the cursor - - Ctrl + A: Like the Home key, move the cursor to the beginning of the line - - Ctrl + E: Like the End key, move the cursor to the end of the line - - Command + Left arrow: Like the Home key, move the cursor to the beginning of the line - - Command + Right arrow: Like the End key, move the cursor to the end of the line + - [kbd]Ctrl + F[/kbd]: Same as [kbd]Right Arrow[/kbd], move the cursor one character right + - [kbd]Ctrl + B[/kbd]: Same as [kbd]Left Arrow[/kbd], move the cursor one character left + - [kbd]Ctrl + P[/kbd]: Same as [kbd]Up Arrow[/kbd], move the cursor to the previous line + - [kbd]Ctrl + N[/kbd]: Same as [kbd]Down Arrow[/kbd], move the cursor to the next line + - [kbd]Ctrl + D[/kbd]: Same as [kbd]Delete[/kbd], delete the character on the right side of cursor + - [kbd]Ctrl + H[/kbd]: Same as [kbd]Backspace[/kbd], delete the character on the left side of the cursor + - [kbd]Ctrl + A[/kbd]: Same as [kbd]Home[/kbd], move the cursor to the beginning of the line + - [kbd]Ctrl + E[/kbd]: Same as [kbd]End[/kbd], move the cursor to the end of the line + - [kbd]Cmd + Left Arrow[/kbd]: Same as [kbd]Home[/kbd], move the cursor to the beginning of the line + - [kbd]Cmd + Right Arrow[/kbd]: Same as [kbd]End[/kbd], move the cursor to the end of the line </description> <tutorials> </tutorials> diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml index 1c745de7f0..5ba3c6c56a 100644 --- a/doc/classes/Node.xml +++ b/doc/classes/Node.xml @@ -932,7 +932,7 @@ Implemented on all platforms. </constant> <constant name="NOTIFICATION_WM_CLOSE_REQUEST" value="1006"> - Notification received from the OS when a close request is sent (e.g. closing the window with a "Close" button or Alt+F4). + Notification received from the OS when a close request is sent (e.g. closing the window with a "Close" button or [kbd]Alt + F4[/kbd]). Implemented on desktop platforms. </constant> <constant name="NOTIFICATION_WM_GO_BACK_REQUEST" value="1007"> diff --git a/doc/classes/Transform.xml b/doc/classes/Transform.xml index e4d367c344..4175f01eb4 100644 --- a/doc/classes/Transform.xml +++ b/doc/classes/Transform.xml @@ -135,7 +135,7 @@ <argument index="0" name="scale" type="Vector3"> </argument> <description> - Scales the transform by the given scale factor, using matrix multiplication. + Scales basis and origin of the transform by the given scale factor, using matrix multiplication. </description> </method> <method name="translated"> diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py index 5ceab52523..a14ef7c665 100755 --- a/doc/tools/makerst.py +++ b/doc/tools/makerst.py @@ -901,6 +901,12 @@ def rstize_text(text, state): # type: (str, State) -> str tag_text = "``" tag_depth += 1 inside_code = True + elif cmd == "kbd": + tag_text = ":kbd:`" + tag_depth += 1 + elif cmd == "/kbd": + tag_text = "`" + tag_depth -= 1 elif cmd.startswith("enum "): tag_text = make_enum(cmd[5:], state) escape_post = True diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 699d6e1484..92c1ada850 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -404,18 +404,19 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener // constants - for (Map<StringName, SL::ShaderNode::Constant>::Element *E = snode->constants.front(); E; E = E->next()) { + for (int i = 0; i < snode->vconstants.size(); i++) { + const SL::ShaderNode::Constant &cnode = snode->vconstants[i]; String gcode; gcode += "const "; - gcode += _prestr(E->get().precision); - if (E->get().type == SL::TYPE_STRUCT) { - gcode += _mkid(E->get().type_str); + gcode += _prestr(cnode.precision); + if (cnode.type == SL::TYPE_STRUCT) { + gcode += _mkid(cnode.type_str); } else { - gcode += _typestr(E->get().type); + gcode += _typestr(cnode.type); } - gcode += " " + _mkid(E->key()); + gcode += " " + _mkid(String(cnode.name)); gcode += "="; - gcode += _dump_node_code(E->get().initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + gcode += _dump_node_code(cnode.initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); gcode += ";\n"; vertex_global += gcode; fragment_global += gcode; diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp index 8aadf02ea6..cf00c536a7 100644 --- a/editor/editor_fonts.cpp +++ b/editor/editor_fonts.cpp @@ -247,10 +247,12 @@ void editor_register_fonts(Ref<Theme> p_theme) { MAKE_BOLD_FONT(df_doc_bold, int(EDITOR_GET("text_editor/help/help_font_size")) * EDSCALE); MAKE_BOLD_FONT(df_doc_title, int(EDITOR_GET("text_editor/help/help_title_font_size")) * EDSCALE); MAKE_SOURCE_FONT(df_doc_code, int(EDITOR_GET("text_editor/help/help_source_font_size")) * EDSCALE); + MAKE_SOURCE_FONT(df_doc_kbd, (int(EDITOR_GET("text_editor/help/help_source_font_size")) - 1) * EDSCALE); p_theme->set_font("doc", "EditorFonts", df_doc); p_theme->set_font("doc_bold", "EditorFonts", df_doc_bold); p_theme->set_font("doc_title", "EditorFonts", df_doc_title); p_theme->set_font("doc_source", "EditorFonts", df_doc_code); + p_theme->set_font("doc_keyboard", "EditorFonts", df_doc_kbd); // Ruler font MAKE_DEFAULT_FONT(df_rulers, 8 * EDSCALE); diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 050b0a5f33..75d1b2595a 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -1222,11 +1222,14 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { Ref<Font> doc_font = p_rt->get_theme_font("doc", "EditorFonts"); Ref<Font> doc_bold_font = p_rt->get_theme_font("doc_bold", "EditorFonts"); Ref<Font> doc_code_font = p_rt->get_theme_font("doc_source", "EditorFonts"); + Ref<Font> doc_kbd_font = p_rt->get_theme_font("doc_keyboard", "EditorFonts"); Color font_color_hl = p_rt->get_theme_color("headline_color", "EditorHelp"); Color accent_color = p_rt->get_theme_color("accent_color", "Editor"); + Color property_color = p_rt->get_theme_color("property_color", "Editor"); Color link_color = accent_color.linear_interpolate(font_color_hl, 0.8); Color code_color = accent_color.linear_interpolate(font_color_hl, 0.6); + Color kbd_color = accent_color.linear_interpolate(property_color, 0.6); String bbcode = p_bbcode.dedent().replace("\t", "").replace("\r", "").strip_edges(); @@ -1337,6 +1340,14 @@ static void _add_text_to_rt(const String &p_bbcode, RichTextLabel *p_rt) { code_tag = true; pos = brk_end + 1; tag_stack.push_front(tag); + } else if (tag == "kbd") { + + //use keyboard font with custom color + p_rt->push_font(doc_kbd_font); + p_rt->push_color(kbd_color); + code_tag = true; // though not strictly a code tag, logic is similar + pos = brk_end + 1; + tag_stack.push_front(tag); } else if (tag == "center") { //align to center diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index fdd5bd8db6..49cffb015f 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -412,8 +412,104 @@ void EditorPropertyArray::_remove_pressed(int p_index) { update_property(); } +void EditorPropertyArray::_button_draw() { + if (dropping) { + Color color = get_theme_color("accent_color", "Editor"); + edit->draw_rect(Rect2(Point2(), edit->get_size()), color, false); + } +} + +bool EditorPropertyArray::_is_drop_valid(const Dictionary &p_drag_data) const { + String allowed_type = Variant::get_type_name(subtype); + + Dictionary drag_data = p_drag_data; + + if (drag_data.has("type") && String(drag_data["type"]) == "files") { + + Vector<String> files = drag_data["files"]; + + for (int i = 0; i < files.size(); i++) { + String file = files[i]; + String ftype = EditorFileSystem::get_singleton()->get_file_type(file); + + for (int j = 0; j < allowed_type.get_slice_count(","); j++) { + String at = allowed_type.get_slice(",", j).strip_edges(); + // Fail if one of the files is not of allowed type + if (!ClassDB::is_parent_class(ftype, at)) { + return false; + } + } + } + + // If no files fail, drop is valid + return true; + } + + return false; +} + +bool EditorPropertyArray::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { + + return _is_drop_valid(p_data); +} + +void EditorPropertyArray::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { + ERR_FAIL_COND(!_is_drop_valid(p_data)); + + Dictionary drag_data = p_data; + + if (drag_data.has("type") && String(drag_data["type"]) == "files") { + + Vector<String> files = drag_data["files"]; + + Variant array = object->get_array(); + + // Handle the case where array is not initialised yet + if (!array.is_array()) { + Callable::CallError ce; + array = Variant::construct(array_type, nullptr, 0, ce); + } + + // Loop the file array and add to existing array + for (int i = 0; i < files.size(); i++) { + String file = files[i]; + + RES res = ResourceLoader::load(file); + if (res.is_valid()) { + array.call("push_back", res); + } + } + + if (array.get_type() == Variant::ARRAY) { + array = array.call("duplicate"); + } + + emit_changed(get_edited_property(), array, "", false); + object->set_array(array); + + update_property(); + } +} + void EditorPropertyArray::_notification(int p_what) { + if (p_what == NOTIFICATION_DRAG_BEGIN) { + + if (is_visible_in_tree()) { + if (_is_drop_valid(get_viewport()->gui_get_drag_data())) { + dropping = true; + edit->update(); + } + } + } + + if (p_what == NOTIFICATION_DRAG_END) { + if (dropping) { + dropping = false; + edit->update(); + } + } } + void EditorPropertyArray::_edit_pressed() { Variant array = get_edited_object()->get(get_edited_property()); @@ -490,6 +586,8 @@ void EditorPropertyArray::setup(Variant::Type p_array_type, const String &p_hint } void EditorPropertyArray::_bind_methods() { + ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &EditorPropertyArray::can_drop_data_fw); + ClassDB::bind_method(D_METHOD("drop_data_fw"), &EditorPropertyArray::drop_data_fw); } EditorPropertyArray::EditorPropertyArray() { @@ -503,6 +601,8 @@ EditorPropertyArray::EditorPropertyArray() { edit->set_clip_text(true); edit->connect("pressed", callable_mp(this, &EditorPropertyArray::_edit_pressed)); edit->set_toggle_mode(true); + edit->set_drag_forwarding(this); + edit->connect("draw", callable_mp(this, &EditorPropertyArray::_button_draw)); add_child(edit); add_focusable(edit); vbox = nullptr; @@ -524,6 +624,8 @@ EditorPropertyArray::EditorPropertyArray() { subtype = Variant::NIL; subtype_hint = PROPERTY_HINT_NONE; subtype_hint_string = ""; + + dropping = false; } ///////////////////// DICTIONARY /////////////////////////// diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h index 51a4be1b3a..d6f3c976f9 100644 --- a/editor/editor_properties_array_dict.h +++ b/editor/editor_properties_array_dict.h @@ -33,6 +33,7 @@ #include "editor/editor_inspector.h" #include "editor/editor_spin_slider.h" +#include "editor/filesystem_dock.h" #include "scene/gui/button.h" class EditorPropertyArrayObject : public Reference { @@ -82,6 +83,7 @@ class EditorPropertyArray : public EditorProperty { PopupMenu *change_type; bool updating; + bool dropping; Ref<EditorPropertyArrayObject> object; int page_len; @@ -107,6 +109,11 @@ class EditorPropertyArray : public EditorProperty { void _object_id_selected(const StringName &p_property, ObjectID p_id); void _remove_pressed(int p_index); + void _button_draw(); + bool _is_drop_valid(const Dictionary &p_drag_data) const; + 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); + protected: static void _bind_methods(); void _notification(int p_what); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index db51c5c6ba..0a252cc0a3 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -433,7 +433,9 @@ void AnimationPlayerEditor::_animation_remove() { if (animation->get_item_count() == 0) return; - delete_dialog->set_text(TTR("Delete Animation?")); + String current = animation->get_item_text(animation->get_selected()); + + delete_dialog->set_text(TTR("Delete Animation '" + current + "'?")); delete_dialog->popup_centered(); } @@ -1135,7 +1137,9 @@ void AnimationPlayerEditor::_animation_tool_menu(int p_option) { case TOOL_DUPLICATE_ANIM: { _animation_duplicate(); - } break; + + [[fallthrough]]; // Allow immediate rename after animation is duplicated + } case TOOL_RENAME_ANIM: { _animation_rename(); diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index ee92a6234a..bdf9cf965f 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -566,8 +566,12 @@ String BindingsGenerator::bbcode_to_xml(const String &p_bbcode, const TypeInterf code_tag = true; pos = brk_end + 1; tag_stack.push_front(tag); + } else if (tag == "kbd") { + // keyboard combinations are not supported in xml comments + pos = brk_end + 1; + tag_stack.push_front(tag); } else if (tag == "center") { - // center is alignment not supported in xml comments + // center alignment is not supported in xml comments pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "br") { diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index f431a2ad48..d57af29599 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -1692,15 +1692,20 @@ void AnimatedTexture::_update_proxy() { } int iter_max = frame_count; - while (iter_max) { + while (iter_max && !pause) { float frame_limit = limit + frames[current_frame].delay_sec; if (time > frame_limit) { current_frame++; if (current_frame >= frame_count) { - current_frame = 0; + if (oneshot) { + current_frame = frame_count - 1; + } else { + current_frame = 0; + } } time -= frame_limit; + _change_notify("current_frame"); } else { break; } @@ -1723,6 +1728,33 @@ int AnimatedTexture::get_frames() const { return frame_count; } +void AnimatedTexture::set_current_frame(int p_frame) { + ERR_FAIL_COND(p_frame < 0 || p_frame >= frame_count); + + RWLockWrite r(rw_lock); + + current_frame = p_frame; +} +int AnimatedTexture::get_current_frame() const { + return current_frame; +} + +void AnimatedTexture::set_pause(bool p_pause) { + RWLockWrite r(rw_lock); + pause = p_pause; +} +bool AnimatedTexture::get_pause() const { + return pause; +} + +void AnimatedTexture::set_oneshot(bool p_oneshot) { + RWLockWrite r(rw_lock); + oneshot = p_oneshot; +} +bool AnimatedTexture::get_oneshot() const { + return oneshot; +} + void AnimatedTexture::set_frame_texture(int p_frame, const Ref<Texture2D> &p_texture) { ERR_FAIL_COND(p_texture == this); @@ -1833,6 +1865,15 @@ void AnimatedTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("set_frames", "frames"), &AnimatedTexture::set_frames); ClassDB::bind_method(D_METHOD("get_frames"), &AnimatedTexture::get_frames); + ClassDB::bind_method(D_METHOD("set_current_frame", "frame"), &AnimatedTexture::set_current_frame); + ClassDB::bind_method(D_METHOD("get_current_frame"), &AnimatedTexture::get_current_frame); + + ClassDB::bind_method(D_METHOD("set_pause", "pause"), &AnimatedTexture::set_pause); + ClassDB::bind_method(D_METHOD("get_pause"), &AnimatedTexture::get_pause); + + ClassDB::bind_method(D_METHOD("set_oneshot", "oneshot"), &AnimatedTexture::set_oneshot); + ClassDB::bind_method(D_METHOD("get_oneshot"), &AnimatedTexture::get_oneshot); + ClassDB::bind_method(D_METHOD("set_fps", "fps"), &AnimatedTexture::set_fps); ClassDB::bind_method(D_METHOD("get_fps"), &AnimatedTexture::get_fps); @@ -1843,6 +1884,9 @@ void AnimatedTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("get_frame_delay", "frame"), &AnimatedTexture::get_frame_delay); ADD_PROPERTY(PropertyInfo(Variant::INT, "frames", PROPERTY_HINT_RANGE, "1," + itos(MAX_FRAMES), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), "set_frames", "get_frames"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "current_frame", PROPERTY_HINT_NONE, "", 0), "set_current_frame", "get_current_frame"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pause"), "set_pause", "get_pause"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "oneshot"), "set_oneshot", "get_oneshot"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "fps", PROPERTY_HINT_RANGE, "0,1024,0.1"), "set_fps", "get_fps"); for (int i = 0; i < MAX_FRAMES; i++) { @@ -1864,6 +1908,8 @@ AnimatedTexture::AnimatedTexture() { fps = 4; prev_ticks = 0; current_frame = 0; + pause = false; + oneshot = false; RenderingServer::get_singleton()->connect("frame_pre_draw", callable_mp(this, &AnimatedTexture::_update_proxy)); #ifndef NO_THREADS diff --git a/scene/resources/texture.h b/scene/resources/texture.h index f4f00c2ca0..5d5f438eba 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -567,7 +567,8 @@ private: Frame frames[MAX_FRAMES]; int frame_count; int current_frame; - + bool pause; + bool oneshot; float fps; float time; @@ -584,6 +585,15 @@ public: void set_frames(int p_frames); int get_frames() const; + void set_current_frame(int p_frame); + int get_current_frame() const; + + void set_pause(bool p_pause); + bool get_pause() const; + + void set_oneshot(bool p_oneshot); + bool get_oneshot() const; + void set_frame_texture(int p_frame, const Ref<Texture2D> &p_texture); Ref<Texture2D> get_frame_texture(int p_frame) const; diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp index 0689429014..d32627a076 100644 --- a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp +++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp @@ -5063,10 +5063,10 @@ void RasterizerStorageRD::_global_variable_store_in_buffer(int32_t p_index, RS:: bv[2].z = v.basis.elements[2][2]; bv[2].w = 0; - bv[2].x = v.origin.x; - bv[2].y = v.origin.y; - bv[2].z = v.origin.z; - bv[2].w = 1; + bv[3].x = v.origin.x; + bv[3].y = v.origin.y; + bv[3].z = v.origin.z; + bv[3].w = 1; } break; default: { diff --git a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp index 9cbff2571a..d4e6576125 100644 --- a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp +++ b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp @@ -650,18 +650,19 @@ String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, Ge index++; } - for (Map<StringName, SL::ShaderNode::Constant>::Element *E = pnode->constants.front(); E; E = E->next()) { + for (int i = 0; i < pnode->vconstants.size(); i++) { + const SL::ShaderNode::Constant &cnode = pnode->vconstants[i]; String gcode; gcode += "const "; - gcode += _prestr(E->get().precision); - if (E->get().type == SL::TYPE_STRUCT) { - gcode += _mkid(E->get().type_str); + gcode += _prestr(cnode.precision); + if (cnode.type == SL::TYPE_STRUCT) { + gcode += _mkid(cnode.type_str); } else { - gcode += _typestr(E->get().type); + gcode += _typestr(cnode.type); } - gcode += " " + _mkid(E->key()); + gcode += " " + _mkid(String(cnode.name)); gcode += "="; - gcode += _dump_node_code(E->get().initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + gcode += _dump_node_code(cnode.initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); gcode += ";\n"; r_gen_code.vertex_global += gcode; r_gen_code.fragment_global += gcode; diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp index bec0958f71..93593effd4 100644 --- a/servers/rendering/shader_language.cpp +++ b/servers/rendering/shader_language.cpp @@ -6334,6 +6334,7 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct while (true) { ShaderNode::Constant constant; + constant.name = name; constant.type = is_struct ? TYPE_STRUCT : type; constant.type_str = struct_name; constant.precision = precision; @@ -6373,6 +6374,8 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct } shader->constants[name] = constant; + shader->vconstants.push_back(constant); + if (tk.type == TK_COMMA) { tk = _get_token(); if (tk.type != TK_IDENTIFIER) { diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h index 48f1d1440f..973e1c4937 100644 --- a/servers/rendering/shader_language.h +++ b/servers/rendering/shader_language.h @@ -607,6 +607,7 @@ public: struct ShaderNode : public Node { struct Constant { + StringName name; DataType type; StringName type_str; DataPrecision precision; @@ -698,6 +699,7 @@ public: Vector<StringName> render_modes; Vector<Function> functions; + Vector<Constant> vconstants; Vector<Struct> vstructs; ShaderNode() : |