Merge pull request #74866 from YuriSizov/4.0-cherrypicks
Cherry-picks for the 4.0 branch (future 4.0.1) - 1st batch
This commit is contained in:
commit
30e81fcc26
@ -1304,16 +1304,8 @@ ProjectSettings::ProjectSettings() {
|
||||
}
|
||||
extensions.push_back("gdshader");
|
||||
|
||||
GLOBAL_DEF("editor/run/main_run_args", "");
|
||||
|
||||
GLOBAL_DEF(PropertyInfo(Variant::PACKED_STRING_ARRAY, "editor/script/search_in_file_extensions"), extensions);
|
||||
|
||||
GLOBAL_DEF(PropertyInfo(Variant::STRING, "editor/script/templates_search_path", PROPERTY_HINT_DIR), "res://script_templates");
|
||||
|
||||
// For correct doc generation.
|
||||
GLOBAL_DEF("editor/naming/default_signal_callback_name", "_on_{node_name}_{signal_name}");
|
||||
GLOBAL_DEF("editor/naming/default_signal_callback_to_self_name", "_on_{signal_name}");
|
||||
|
||||
_add_builtin_input_map();
|
||||
|
||||
// Keep the enum values in sync with the `DisplayServer::ScreenOrientation` enum.
|
||||
|
@ -1052,6 +1052,7 @@ void GDExtensionAPIDump::generate_extension_json_file(const String &p_path) {
|
||||
|
||||
String text = json->stringify(api, "\t", false) + "\n";
|
||||
Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE);
|
||||
ERR_FAIL_COND_MSG(fa.is_null(), vformat("Cannot open file '%s' for writing.", p_path));
|
||||
fa->store_string(text);
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ class GDExtensionInterfaceDump {
|
||||
public:
|
||||
static void generate_gdextension_interface_file(const String &p_path) {
|
||||
Ref<FileAccess> fa = FileAccess::open(p_path, FileAccess::WRITE);
|
||||
ERR_FAIL_COND_MSG(fa.is_null(), vformat("Cannot open file '%s' for writing.", p_path));
|
||||
CharString cs(gdextension_interface_dump);
|
||||
fa->store_buffer((const uint8_t *)cs.ptr(), cs.length());
|
||||
};
|
||||
|
24
doc/Makefile
24
doc/Makefile
@ -1,28 +1,28 @@
|
||||
BASEDIR = .
|
||||
CLASSES = $(BASEDIR)/classes/ $(BASEDIR)/../modules/
|
||||
CLASSES = "$(BASEDIR)/classes/" "$(BASEDIR)/../modules/"
|
||||
OUTPUTDIR = $(BASEDIR)/_build
|
||||
TOOLSDIR = $(BASEDIR)/tools
|
||||
JSDIR = $(BASEDIR)/../platform/web
|
||||
JSDIR = "$(BASEDIR)/../platform/web"
|
||||
LANGARG ?= en
|
||||
LANGCMD = -l $(LANGARG)
|
||||
|
||||
.ONESHELL:
|
||||
|
||||
clean:
|
||||
rm -rf $(OUTPUTDIR)
|
||||
rm -rf "$(OUTPUTDIR)"
|
||||
|
||||
doxygen:
|
||||
rm -rf $(OUTPUTDIR)/doxygen
|
||||
mkdir -p $(OUTPUTDIR)/doxygen
|
||||
rm -rf "$(OUTPUTDIR)/doxygen"
|
||||
mkdir -p "$(OUTPUTDIR)/doxygen"
|
||||
doxygen Doxyfile
|
||||
|
||||
rst:
|
||||
rm -rf $(OUTPUTDIR)/rst
|
||||
mkdir -p $(OUTPUTDIR)/rst
|
||||
python3 $(TOOLSDIR)/make_rst.py -o $(OUTPUTDIR)/rst $(LANGCMD) $(CLASSES)
|
||||
rm -rf "$(OUTPUTDIR)/rst"
|
||||
mkdir -p "$(OUTPUTDIR)/rst"
|
||||
python3 "$(TOOLSDIR)/make_rst.py" -o "$(OUTPUTDIR)/rst" "$(LANGCMD)" $(CLASSES)
|
||||
|
||||
rstjs:
|
||||
rm -rf $(OUTPUTDIR)/rstjs
|
||||
mkdir -p $(OUTPUTDIR)/rstjs
|
||||
npm --prefix $(JSDIR) ci
|
||||
npm --prefix $(JSDIR) run docs -- --destination $(OUTPUTDIR)/rstjs/html5_shell_classref.rst
|
||||
rm -rf "$(OUTPUTDIR)/rstjs"
|
||||
mkdir -p "$(OUTPUTDIR)/rstjs"
|
||||
npm --prefix "$(JSDIR)" ci
|
||||
npm --prefix "$(JSDIR)" run docs -- --destination "$(OUTPUTDIR)/rstjs/html5_shell_classref.rst"
|
||||
|
@ -188,7 +188,7 @@
|
||||
<param index="0" name="from" type="Vector3" />
|
||||
<param index="1" name="dir" type="Vector3" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the given ray intersects with this [AABB]. Ray length is infinite.
|
||||
Returns the point of intersection of the given ray with this [AABB] or [code]null[/code] if there is no intersection. Ray length is infinite.
|
||||
</description>
|
||||
</method>
|
||||
<method name="intersects_segment" qualifiers="const">
|
||||
@ -196,7 +196,7 @@
|
||||
<param index="0" name="from" type="Vector3" />
|
||||
<param index="1" name="to" type="Vector3" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the [AABB] intersects the line segment between [param from] and [param to].
|
||||
Returns the point of intersection between [param from] and [param to] with this [AABB] or [code]null[/code] if there is no intersection.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_equal_approx" qualifiers="const">
|
||||
|
@ -41,7 +41,6 @@
|
||||
[b]Note:[/b] Concatenating with the [code]+=[/code] operator will create a new array, which has a cost. If you want to append another array to an existing array, [method append_array] is more efficient.
|
||||
[b]Note:[/b] Arrays are always passed by reference. To get a copy of an array that can be modified independently of the original array, use [method duplicate].
|
||||
[b]Note:[/b] Erasing elements while iterating over arrays is [b]not[/b] supported and will result in unpredictable behavior.
|
||||
[b]Note:[/b] When declaring an array with [code]const[/code], the array itself can still be mutated by defining the values at individual indices or pushing/removing elements. Using [code]const[/code] will only prevent assigning the constant with another value after it was initialized.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
|
@ -23,8 +23,8 @@
|
||||
|
||||
func _process(delta):
|
||||
while server.is_connection_available():
|
||||
var peer : PacketPeerUDP = server.take_connection()
|
||||
var dtls_peer : PacketPeerDTLS = dtls.take_connection(peer)
|
||||
var peer: PacketPeerUDP = server.take_connection()
|
||||
var dtls_peer: PacketPeerDTLS = dtls.take_connection(peer)
|
||||
if dtls_peer.get_status() != PacketPeerDTLS.STATUS_HANDSHAKING:
|
||||
continue # It is normal that 50% of the connections fails due to cookie exchange.
|
||||
print("Peer connected!")
|
||||
|
@ -135,7 +135,6 @@
|
||||
[/csharp]
|
||||
[/codeblocks]
|
||||
[b]Note:[/b] Erasing elements while iterating over dictionaries is [b]not[/b] supported and will result in unpredictable behavior.
|
||||
[b]Note:[/b] When declaring a dictionary with [code]const[/code], the dictionary becomes read-only. A read-only Dictionary's entries cannot be overridden at run-time. This does [i]not[/i] affect nested [Array] and [Dictionary] values.
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="GDScript basics: Dictionary">$DOCS_URL/tutorials/scripting/gdscript/gdscript_basics.html#dictionary</link>
|
||||
|
@ -290,7 +290,7 @@
|
||||
</methods>
|
||||
<members>
|
||||
<member name="include_hidden" type="bool" setter="set_include_hidden" getter="get_include_hidden">
|
||||
If [code]true[/code], hidden files are included when the navigating directory.
|
||||
If [code]true[/code], hidden files are included when navigating the directory.
|
||||
Affects [method list_dir_begin], [method get_directories] and [method get_files].
|
||||
</member>
|
||||
<member name="include_navigational" type="bool" setter="set_include_navigational" getter="get_include_navigational">
|
||||
|
@ -190,7 +190,7 @@
|
||||
<description>
|
||||
Adds a new checkable item with text [param label] to the global menu with ID [param menu_root].
|
||||
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
|
||||
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
|
||||
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using bitwise OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
|
||||
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
|
||||
[b]Note:[/b] This method is implemented on macOS.
|
||||
[b]Supported system menu IDs:[/b]
|
||||
@ -213,7 +213,7 @@
|
||||
<description>
|
||||
Adds a new checkable item with text [param label] and icon [param icon] to the global menu with ID [param menu_root].
|
||||
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
|
||||
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
|
||||
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using bitwise OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
|
||||
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
|
||||
[b]Note:[/b] This method is implemented on macOS.
|
||||
[b]Supported system menu IDs:[/b]
|
||||
@ -236,7 +236,7 @@
|
||||
<description>
|
||||
Adds a new item with text [param label] and icon [param icon] to the global menu with ID [param menu_root].
|
||||
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
|
||||
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
|
||||
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using bitwise OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
|
||||
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
|
||||
[b]Note:[/b] This method is implemented on macOS.
|
||||
[b]Supported system menu IDs:[/b]
|
||||
@ -259,7 +259,7 @@
|
||||
<description>
|
||||
Adds a new radio-checkable item with text [param label] and icon [param icon] to the global menu with ID [param menu_root].
|
||||
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
|
||||
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
|
||||
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using bitwise OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
|
||||
[b]Note:[/b] Radio-checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually. See [method global_menu_set_item_checked] for more info on how to control it.
|
||||
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
|
||||
[b]Note:[/b] This method is implemented on macOS.
|
||||
@ -282,7 +282,7 @@
|
||||
<description>
|
||||
Adds a new item with text [param label] to the global menu with ID [param menu_root].
|
||||
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
|
||||
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
|
||||
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using bitwise OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
|
||||
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
|
||||
[b]Note:[/b] This method is implemented on macOS.
|
||||
[b]Supported system menu IDs:[/b]
|
||||
@ -307,7 +307,7 @@
|
||||
Adds a new item with text [param label] to the global menu with ID [param menu_root].
|
||||
Contrarily to normal binary items, multistate items can have more than two states, as defined by [param max_states]. Each press or activate of the item will increase the state by one. The default value is defined by [param default_state].
|
||||
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
|
||||
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
|
||||
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using bitwise OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
|
||||
[b]Note:[/b] By default, there's no indication of the current item state, it should be changed manually.
|
||||
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
|
||||
[b]Note:[/b] This method is implemented on macOS.
|
||||
@ -330,7 +330,7 @@
|
||||
<description>
|
||||
Adds a new radio-checkable item with text [param label] to the global menu with ID [param menu_root].
|
||||
Returns index of the inserted item, it's not guaranteed to be the same as [param index] value.
|
||||
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
|
||||
An [param accelerator] can optionally be defined, which is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The [param accelerator] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using bitwise OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
|
||||
[b]Note:[/b] Radio-checkable items just display a checkmark, but don't have any built-in checking behavior and must be checked/unchecked manually. See [method global_menu_set_item_checked] for more info on how to control it.
|
||||
[b]Note:[/b] The [param callback] and [param key_callback] Callables need to accept exactly one Variant parameter, the parameter passed to the Callables will be the value passed to [param tag].
|
||||
[b]Note:[/b] This method is implemented on macOS.
|
||||
@ -507,7 +507,7 @@
|
||||
<param index="0" name="menu_root" type="String" />
|
||||
<param index="1" name="idx" type="int" />
|
||||
<description>
|
||||
Returns the tooltip associated with the specified index index [param idx].
|
||||
Returns the tooltip associated with the specified index [param idx].
|
||||
[b]Note:[/b] This method is implemented on macOS.
|
||||
</description>
|
||||
</method>
|
||||
@ -565,7 +565,7 @@
|
||||
<param index="1" name="idx" type="int" />
|
||||
<param index="2" name="keycode" type="int" enum="Key" />
|
||||
<description>
|
||||
Sets the accelerator of the item at index [param idx]. [param keycode] can be a single [enum Key], or a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
|
||||
Sets the accelerator of the item at index [param idx]. [param keycode] can be a single [enum Key], or a combination of [enum KeyModifierMask]s and [enum Key]s using bitwise OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
|
||||
[b]Note:[/b] This method is implemented on macOS.
|
||||
</description>
|
||||
</method>
|
||||
@ -576,7 +576,7 @@
|
||||
<param index="2" name="callback" type="Callable" />
|
||||
<description>
|
||||
Sets the callback of the item at index [param idx]. Callback is emitted when an item is pressed.
|
||||
[b]Note:[/b] The [param callback] Callable needs to accept exactly one Variant parameter, the parameter passed to the Callable will be the value passed to the tag parameter when the menu item was created.
|
||||
[b]Note:[/b] The [param callback] Callable needs to accept exactly one Variant parameter, the parameter passed to the Callable will be the value passed to the [code]tag[/code] parameter when the menu item was created.
|
||||
[b]Note:[/b] This method is implemented on macOS.
|
||||
</description>
|
||||
</method>
|
||||
@ -638,7 +638,7 @@
|
||||
<param index="2" name="key_callback" type="Callable" />
|
||||
<description>
|
||||
Sets the callback of the item at index [param idx]. Callback is emitted when its accelerator is activated.
|
||||
[b]Note:[/b] The [param key_callback] Callable needs to accept exactly one Variant parameter, the parameter passed to the Callable will be the value passed to the tag parameter when the menu item was created.
|
||||
[b]Note:[/b] The [param key_callback] Callable needs to accept exactly one Variant parameter, the parameter passed to the Callable will be the value passed to the [code]tag[/code] parameter when the menu item was created.
|
||||
[b]Note:[/b] This method is implemented on macOS.
|
||||
</description>
|
||||
</method>
|
||||
|
@ -67,7 +67,7 @@
|
||||
The view format in which the [EditorFileDialog] displays resources to the user.
|
||||
</member>
|
||||
<member name="file_mode" type="int" setter="set_file_mode" getter="get_file_mode" enum="EditorFileDialog.FileMode" default="4">
|
||||
The dialog's open or save mode, which affects the selection behavior. See [enum FileMode]
|
||||
The dialog's open or save mode, which affects the selection behavior. See [enum FileMode].
|
||||
</member>
|
||||
<member name="filters" type="PackedStringArray" setter="set_filters" getter="get_filters" default="PackedStringArray()">
|
||||
The available file type filters. For example, this shows only [code].png[/code] and [code].gd[/code] files: [code]set_filters(PackedStringArray(["*.png ; PNG Images","*.gd ; GDScript Files"]))[/code]. Multiple file types can also be specified in a single filter. [code]"*.png, *.jpg, *.jpeg ; Supported Images"[/code] will show both PNG and JPEG files when selected.
|
||||
|
@ -10,13 +10,13 @@
|
||||
[gdscript]
|
||||
extends EditorResourceConversionPlugin
|
||||
|
||||
func _handles(resource : Resource):
|
||||
func _handles(resource: Resource):
|
||||
return resource is ImageTexture
|
||||
|
||||
func _converts_to():
|
||||
return "PortableCompressedTexture2D"
|
||||
|
||||
func _convert(itex : Resource):
|
||||
func _convert(itex: Resource):
|
||||
var ptex = PortableCompressedTexture2D.new()
|
||||
ptex.create_from_image(itex.get_image(), PortableCompressedTexture2D.COMPRESSION_MODE_LOSSLESS)
|
||||
return ptex
|
||||
|
@ -87,7 +87,7 @@
|
||||
<method name="get_changed_settings" qualifiers="const">
|
||||
<return type="PackedStringArray" />
|
||||
<description>
|
||||
Gets an array of the settings which have been changed since the last save. Note that internally [code]changed_settings[/code] is cleared after a successful save, so generally the most appropriate place to use this method is when processing [constant NOTIFICATION_EDITOR_SETTINGS_CHANGED]
|
||||
Gets an array of the settings which have been changed since the last save. Note that internally [code]changed_settings[/code] is cleared after a successful save, so generally the most appropriate place to use this method is when processing [constant NOTIFICATION_EDITOR_SETTINGS_CHANGED].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_favorites" qualifiers="const">
|
||||
|
@ -277,7 +277,7 @@
|
||||
[b]Note:[/b] SSR is only supported in the Forward+ rendering method, not Mobile or Compatibility.
|
||||
</member>
|
||||
<member name="ssr_fade_in" type="float" setter="set_ssr_fade_in" getter="get_ssr_fade_in" default="0.15">
|
||||
The fade-in distance for screen-space reflections. Affects the area from the reflected material to the screen-space reflection). Only positive values are valid (negative values will be clamped to [code]0.0[/code]).
|
||||
The fade-in distance for screen-space reflections. Affects the area from the reflected material to the screen-space reflection. Only positive values are valid (negative values will be clamped to [code]0.0[/code]).
|
||||
</member>
|
||||
<member name="ssr_fade_out" type="float" setter="set_ssr_fade_out" getter="get_ssr_fade_out" default="2.0">
|
||||
The fade-out distance for screen-space reflections. Affects the area from the screen-space reflection to the "global" reflection. Only positive values are valid (negative values will be clamped to [code]0.0[/code]).
|
||||
|
@ -271,6 +271,17 @@
|
||||
<description>
|
||||
Returns list of supported [url=https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg]variation coordinates[/url], each coordinate is returned as [code]tag: Vector3i(min_value,max_value,default_value)[/code].
|
||||
Font variations allow for continuous change of glyph characteristics along some given design axis, such as weight, width or slant.
|
||||
To print available variation axes of a variable font:
|
||||
[codeblock]
|
||||
var fv = FontVariation.new()
|
||||
fv.set_base_font = load("res://RobotoFlex.ttf")
|
||||
var variation_list = fv.get_supported_variation_list()
|
||||
for tag in variation_list:
|
||||
var name = TextServerManager.get_primary_interface().tag_to_name(tag)
|
||||
var values = variation_list[tag]
|
||||
print("variation axis: %s (%d)\n\tmin, max, default: %s" % [name, tag, values])
|
||||
[/codeblock]
|
||||
[b]Note:[/b] To set and get variation coordinates of a [FontVariation], use [member FontVariation.variation_opentype].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_underline_position" qualifiers="const">
|
||||
|
@ -22,6 +22,13 @@
|
||||
GetNode("Label").AddThemeFontSizeOverride("font_size", 64);
|
||||
[/csharp]
|
||||
[/codeblocks]
|
||||
To set the coordinate of multiple variation axes:
|
||||
[codeblock]
|
||||
var fv = FontVariation.new();
|
||||
var ts = TextServerManager.get_primary_interface()
|
||||
fv.base_font = load("res://BarlowCondensed-Regular.ttf")
|
||||
fv.variation_opentype = { ts.name_to_tag("wght"): 900, ts.name_to_tag("custom_hght"): 900 }
|
||||
[/codeblock]
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
@ -40,7 +47,7 @@
|
||||
Base font used to create a variation. If not set, default [Theme] font is used.
|
||||
</member>
|
||||
<member name="fallbacks" type="Font[]" setter="set_fallbacks" getter="get_fallbacks" default="[]">
|
||||
Array of fallback [Font]s. If not set [member base_font] fallback are ussed.
|
||||
Array of fallback [Font]s to use as a substitute if a glyph is not found in this [FontVariation]. If not set, [member base_font]'s fallbacks are used instead.
|
||||
</member>
|
||||
<member name="opentype_features" type="Dictionary" setter="set_opentype_features" getter="get_opentype_features" default="{}">
|
||||
A set of OpenType feature tags. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/featuretags]OpenType feature tags[/url].
|
||||
@ -66,6 +73,8 @@
|
||||
</member>
|
||||
<member name="variation_opentype" type="Dictionary" setter="set_variation_opentype" getter="get_variation_opentype" default="{}">
|
||||
Font OpenType variation coordinates. More info: [url=https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxisreg]OpenType variation tags[/url].
|
||||
[b]Note:[/b] This [Dictionary] uses OpenType tags as keys. Variation axes can be identified both by tags([code]int[/code]) and names ([code]string[/code]). Some axes might be accessible by multiple names. For example, [code]wght[/code] refers to the same axis as [code]weight[/code]. Tags on the other hand are unique. To convert between names and tags, use [method TextServer.name_to_tag] and [method TextServer.tag_to_name].
|
||||
[b]Note:[/b] To get available variation axes of a font, use [method Font.get_supported_variation_list].
|
||||
</member>
|
||||
<member name="variation_transform" type="Transform2D" setter="set_variation_transform" getter="get_variation_transform" default="Transform2D(1, 0, 0, 1, 0, 0)">
|
||||
2D transform, applied to the font outlines, can be used for slanting, flipping and rotating glyphs.
|
||||
|
@ -31,8 +31,8 @@
|
||||
Below is a sample code to help get started:
|
||||
[codeblock]
|
||||
func _is_in_input_hotzone(in_node, in_port, mouse_position):
|
||||
var port_size : Vector2 = Vector2(get_theme_constant("port_grab_distance_horizontal"), get_theme_constant("port_grab_distance_vertical"))
|
||||
var port_pos : Vector2 = in_node.get_position() + in_node.get_connection_input_position(in_port) - port_size / 2
|
||||
var port_size: Vector2 = Vector2(get_theme_constant("port_grab_distance_horizontal"), get_theme_constant("port_grab_distance_vertical"))
|
||||
var port_pos: Vector2 = in_node.get_position() + in_node.get_connection_input_position(in_port) - port_size / 2
|
||||
var rect = Rect2(port_pos, port_size)
|
||||
|
||||
return rect.has_point(mouse_position)
|
||||
@ -49,8 +49,8 @@
|
||||
Below is a sample code to help get started:
|
||||
[codeblock]
|
||||
func _is_in_output_hotzone(in_node, in_port, mouse_position):
|
||||
var port_size : Vector2 = Vector2(get_theme_constant("port_grab_distance_horizontal"), get_theme_constant("port_grab_distance_vertical"))
|
||||
var port_pos : Vector2 = in_node.get_position() + in_node.get_connection_output_position(in_port) - port_size / 2
|
||||
var port_size: Vector2 = Vector2(get_theme_constant("port_grab_distance_horizontal"), get_theme_constant("port_grab_distance_vertical"))
|
||||
var port_pos: Vector2 = in_node.get_position() + in_node.get_connection_output_position(in_port) - port_size / 2
|
||||
var rect = Rect2(port_pos, port_size)
|
||||
|
||||
return rect.has_point(mouse_position)
|
||||
|
@ -342,7 +342,7 @@
|
||||
<theme_item name="title_color" data_type="color" type="Color" default="Color(0.875, 0.875, 0.875, 1)">
|
||||
Color of the title text.
|
||||
</theme_item>
|
||||
<theme_item name="close_h_offset" data_type="constant" type="int" default="22">
|
||||
<theme_item name="close_h_offset" data_type="constant" type="int" default="12">
|
||||
</theme_item>
|
||||
<theme_item name="close_offset" data_type="constant" type="int" default="22">
|
||||
The vertical offset of the close button.
|
||||
|
@ -20,7 +20,7 @@
|
||||
[b]Note:[/b] The image can be retrieved from an imported texture using the [method Texture2D.get_image] method, which returns a copy of the image:
|
||||
[codeblock]
|
||||
var texture = load("res://icon.svg")
|
||||
var image : Image = texture.get_image()
|
||||
var image: Image = texture.get_image()
|
||||
[/codeblock]
|
||||
An [ImageTexture] is not meant to be operated from within the editor interface directly, and is mostly useful for rendering images on screen dynamically via code. If you need to generate images procedurally from within the editor, consider saving and importing images as custom texture resources implementing a new [EditorImportPlugin].
|
||||
[b]Note:[/b] The maximum texture size is 16384×16384 pixels due to graphics hardware limitations.
|
||||
|
@ -188,6 +188,7 @@
|
||||
GetTree().CreateTween().BindNode(this);
|
||||
[/csharp]
|
||||
[/codeblocks]
|
||||
The Tween will start automatically on the next process frame or physics frame (depending on [enum Tween.TweenProcessMode]).
|
||||
</description>
|
||||
</method>
|
||||
<method name="duplicate" qualifiers="const">
|
||||
|
@ -285,11 +285,11 @@
|
||||
Enables and disables Turbulence for the particle system.
|
||||
</member>
|
||||
<member name="turbulence_influence_max" type="float" setter="set_param_max" getter="get_param_max" default="0.1">
|
||||
Minimum turbulence influence on each particle.
|
||||
The actual amount of turbulence influence on each particle is calculated as a random value between [member turbulence_influence_min] and [member turbulence_influence_max] and multiplied by the amount of turbulence influence from [member turbulence_influence_over_life].
|
||||
Maximum turbulence influence on each particle.
|
||||
The actual amount of turbulence influence on each particle is calculated as a random value between [member turbulence_influence_min] and [member turbulence_influence_max] and multiplied by the amount of turbulence influence from [member turbulence_influence_over_life].
|
||||
</member>
|
||||
<member name="turbulence_influence_min" type="float" setter="set_param_min" getter="get_param_min" default="0.1">
|
||||
Maximum turbulence influence on each particle.
|
||||
Minimum turbulence influence on each particle.
|
||||
The actual amount of turbulence influence on each particle is calculated as a random value between [member turbulence_influence_min] and [member turbulence_influence_max] and multiplied by the amount of turbulence influence from [member turbulence_influence_over_life].
|
||||
</member>
|
||||
<member name="turbulence_influence_over_life" type="Texture2D" setter="set_param_texture" getter="get_param_texture">
|
||||
|
@ -192,7 +192,7 @@
|
||||
<return type="int" enum="Key" />
|
||||
<param index="0" name="index" type="int" />
|
||||
<description>
|
||||
Returns the accelerator of the item at the given [param index]. An accelerator is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The return value is an integer which is generally a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]). If no accelerator is defined for the specified [param index], [method get_item_accelerator] returns [code]0[/code] (corresponding to [constant @GlobalScope.KEY_NONE]).
|
||||
Returns the accelerator of the item at the given [param index]. An accelerator is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. The return value is an integer which is generally a combination of [enum KeyModifierMask]s and [enum Key]s using bitwise OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]). If no accelerator is defined for the specified [param index], [method get_item_accelerator] returns [code]0[/code] (corresponding to [constant @GlobalScope.KEY_NONE]).
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_item_icon" qualifiers="const">
|
||||
@ -345,7 +345,7 @@
|
||||
<param index="0" name="index" type="int" />
|
||||
<param index="1" name="accel" type="int" enum="Key" />
|
||||
<description>
|
||||
Sets the accelerator of the item at the given [param index]. An accelerator is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. [param accel] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using boolean OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
|
||||
Sets the accelerator of the item at the given [param index]. An accelerator is a keyboard shortcut that can be pressed to trigger the menu button even if it's not currently open. [param accel] is generally a combination of [enum KeyModifierMask]s and [enum Key]s using bitwise OR such as [code]KEY_MASK_CTRL | KEY_A[/code] ([kbd]Ctrl + A[/kbd]).
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_item_as_checkable">
|
||||
|
@ -753,6 +753,9 @@
|
||||
<member name="editor/naming/node_name_num_separator" type="int" setter="" getter="" default="0">
|
||||
What to use to separate node name from number. This is mostly an editor setting.
|
||||
</member>
|
||||
<member name="editor/naming/scene_name_casing" type="int" setter="" getter="" default="2">
|
||||
When generating file names from scene root node, set the type of casing in this project. This is mostly an editor setting.
|
||||
</member>
|
||||
<member name="editor/run/main_run_args" type="String" setter="" getter="" default="""">
|
||||
The command-line arguments to append to Godot's own command line when running the project. This doesn't affect the editor itself.
|
||||
It is possible to make another executable run Godot by using the [code]%command%[/code] placeholder. The placeholder will be replaced with Godot's own command line. Program-specific arguments should be placed [i]before[/i] the placeholder, whereas Godot-specific arguments should be placed [i]after[/i] the placeholder.
|
||||
|
@ -88,7 +88,7 @@
|
||||
<method name="create_tween">
|
||||
<return type="Tween" />
|
||||
<description>
|
||||
Creates and returns a new [Tween].
|
||||
Creates and returns a new [Tween]. The Tween will start automatically on the next process frame or physics frame (depending on [enum Tween.TweenProcessMode]).
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_first_node_in_group">
|
||||
|
@ -240,7 +240,7 @@
|
||||
<param index="2" name="theme_type" type="StringName" />
|
||||
<description>
|
||||
Returns the theme property of [param data_type] defined by [param name] and [param theme_type], if it exists.
|
||||
Returns the engine fallback icon value if the property doesn't exist (see [ThemeDB]). Use [method has_theme_item] to check for existence.
|
||||
Returns the engine fallback value if the property doesn't exist (see [ThemeDB]). Use [method has_theme_item] to check for existence.
|
||||
[b]Note:[/b] This method is analogous to calling the corresponding data type specific method, but can be used for more generalized logic.
|
||||
</description>
|
||||
</method>
|
||||
|
@ -16,13 +16,13 @@
|
||||
<method name="get_id" qualifiers="const">
|
||||
<return type="String" />
|
||||
<description>
|
||||
Returns the current [Thread]'s ID, uniquely identifying it among all threads. If the [Thread] is not running this returns an empty string.
|
||||
Returns the current [Thread]'s ID, uniquely identifying it among all threads. If the [Thread] has not started running or if [method wait_to_finish] has been called, this returns an empty string.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_alive" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
Returns [code]true[/code] if this [Thread] is currently running. This is useful for determining if [method wait_to_finish] can be called without blocking the calling thread.
|
||||
Returns [code]true[/code] if this [Thread] is currently running the provided function. This is useful for determining if [method wait_to_finish] can be called without blocking the calling thread.
|
||||
To check if a [Thread] is joinable, use [method is_started].
|
||||
</description>
|
||||
</method>
|
||||
|
@ -120,7 +120,7 @@
|
||||
<return type="bool" />
|
||||
<param index="0" name="xform" type="Transform2D" />
|
||||
<description>
|
||||
Returns [code]true[/code] if this transform and [code]transform[/code] are approximately equal, by calling [code]is_equal_approx[/code] on each component.
|
||||
Returns [code]true[/code] if this transform and [param xform] are approximately equal, by calling [code]is_equal_approx[/code] on each component.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_finite" qualifiers="const">
|
||||
@ -133,7 +133,7 @@
|
||||
<return type="Transform2D" />
|
||||
<param index="0" name="target" type="Vector2" default="Vector2(0, 0)" />
|
||||
<description>
|
||||
Returns a copy of the transform rotated such that it's rotation on the X-axis points towards the [param target] position.
|
||||
Returns a copy of the transform rotated such that the rotated X-axis points towards the [param target] position.
|
||||
Operations take place in global space.
|
||||
</description>
|
||||
</method>
|
||||
|
@ -80,7 +80,7 @@
|
||||
<return type="bool" />
|
||||
<param index="0" name="xform" type="Transform3D" />
|
||||
<description>
|
||||
Returns [code]true[/code] if this transform and [code]transform[/code] are approximately equal, by calling [code]is_equal_approx[/code] on each component.
|
||||
Returns [code]true[/code] if this transform and [param xform] are approximately equal, by calling [code]is_equal_approx[/code] on each component.
|
||||
</description>
|
||||
</method>
|
||||
<method name="is_finite" qualifiers="const">
|
||||
|
@ -89,8 +89,8 @@
|
||||
[/codeblocks]
|
||||
Some [Tweener]s use transitions and eases. The first accepts a [enum TransitionType] constant, and refers to the way the timing of the animation is handled (see [url=https://easings.net/]easings.net[/url] for some examples). The second accepts an [enum EaseType] constant, and controls where the [code]trans_type[/code] is applied to the interpolation (in the beginning, the end, or both). If you don't know which transition and easing to pick, you can try different [enum TransitionType] constants with [constant EASE_IN_OUT], and use the one that looks best.
|
||||
[url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/tween_cheatsheet.png]Tween easing and transition types cheatsheet[/url]
|
||||
[b]Note:[/b] All [Tween]s will automatically start by default. To prevent a [Tween] from autostarting, you can call [method stop] immediately after it is created.
|
||||
[b]Note:[/b] [Tween]s are processing after all of nodes in the current frame, i.e. after [method Node._process] or [method Node._physics_process] (depending on [enum TweenProcessMode]).
|
||||
[b]Note:[/b] Tweens are not designed to be re-used and trying to do so results in an undefined behavior. Create a new Tween for each animation and every time you replay an animation from start. Keep in mind that Tweens start immediately, so only create a Tween when you want to start animating.
|
||||
[b]Note:[/b] Tweens are processing after all of nodes in the current frame, i.e. after [method Node._process] or [method Node._physics_process] (depending on [enum TweenProcessMode]).
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
@ -129,7 +129,6 @@
|
||||
<description>
|
||||
Processes the [Tween] by the given [param delta] value, in seconds. This is mostly useful for manual control when the [Tween] is paused. It can also be used to end the [Tween] animation immediately, by setting [param delta] longer than the whole duration of the [Tween] animation.
|
||||
Returns [code]true[/code] if the [Tween] still has [Tweener]s that haven't finished.
|
||||
[b]Note:[/b] The [Tween] will become invalid in the next processing frame after its animation finishes. Calling [method stop] after performing [method custom_step] instead keeps and resets the [Tween].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_total_elapsed_time" qualifiers="const">
|
||||
@ -432,7 +431,6 @@
|
||||
<signal name="finished">
|
||||
<description>
|
||||
Emitted when the [Tween] has finished all tweening. Never emitted when the [Tween] is set to infinite looping (see [method set_loops]).
|
||||
[b]Note:[/b] The [Tween] is removed (invalidated) in the next processing frame after this signal is emitted. Calling [method stop] inside the signal callback will prevent the [Tween] from being removed.
|
||||
</description>
|
||||
</signal>
|
||||
<signal name="loop_finished">
|
||||
|
@ -22,7 +22,7 @@
|
||||
func _process(delta):
|
||||
server.poll() # Important!
|
||||
if server.is_connection_available():
|
||||
var peer : PacketPeerUDP = server.take_connection()
|
||||
var peer: PacketPeerUDP = server.take_connection()
|
||||
var packet = peer.get_packet()
|
||||
print("Accepted peer: %s:%s" % [peer.get_packet_ip(), peer.get_packet_port()])
|
||||
print("Received data: %s" % [packet.get_string_from_utf8()])
|
||||
|
@ -582,7 +582,7 @@
|
||||
The window's title. If the [Window] is non-embedded, title styles set in [Theme] will have no effect.
|
||||
</member>
|
||||
<member name="transient" type="bool" setter="set_transient" getter="is_transient" default="false">
|
||||
If [code]true[/code], the [Window] is transient, i.e. it's considered a child of another [Window]. Transient window is will be destroyed with its transient parent and will return focus to their parent when closed. The transient window is displayed on top of a non-exclusive full-screen parent window. Transient windows can't enter full-screen mode.
|
||||
If [code]true[/code], the [Window] is transient, i.e. it's considered a child of another [Window]. The transient window will be destroyed with its transient parent and will return focus to their parent when closed. The transient window is displayed on top of a non-exclusive full-screen parent window. Transient windows can't enter full-screen mode.
|
||||
Note that behavior might be different depending on the platform.
|
||||
</member>
|
||||
<member name="transparent" type="bool" setter="set_flag" getter="get_flag" default="false">
|
||||
@ -764,7 +764,7 @@
|
||||
The content can be expanded horizontally. Scaling vertically will result in keeping the height ratio and then black bars on top and bottom sides.
|
||||
</constant>
|
||||
<constant name="CONTENT_SCALE_ASPECT_EXPAND" value="4" enum="ContentScaleAspect">
|
||||
The content's aspect will be preserved. If the target size has different aspect from the base one, the content will stay in the to-left corner and add an extra visible area in the stretched space.
|
||||
The content's aspect will be preserved. If the target size has different aspect from the base one, the content will stay in the top-left corner and add an extra visible area in the stretched space.
|
||||
</constant>
|
||||
<constant name="LAYOUT_DIRECTION_INHERITED" value="0" enum="LayoutDirection">
|
||||
Automatic layout direction, determined from the parent window layout direction.
|
||||
|
@ -116,9 +116,9 @@
|
||||
[b]Note:[/b] Not all runtimes support all environment blend modes, so it is important to check this at startup. For example:
|
||||
[codeblock]
|
||||
func _ready():
|
||||
var xr_interface : XRInterface = XRServer.find_interface("OpenXR")
|
||||
var xr_interface: XRInterface = XRServer.find_interface("OpenXR")
|
||||
if xr_interface and xr_interface.is_initialized():
|
||||
var vp : Viewport = get_viewport()
|
||||
var vp: Viewport = get_viewport()
|
||||
vp.use_xr = true
|
||||
var acceptable_modes = [ XRInterface.XR_ENV_BLEND_MODE_OPAQUE, XRInterface.XR_ENV_BLEND_MODE_ADDITIVE ]
|
||||
var modes = xr_interface.get_supported_environment_blend_modes()
|
||||
|
@ -832,6 +832,8 @@ void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) {
|
||||
tex->is_render_target = false;
|
||||
tex->is_proxy = true;
|
||||
tex->proxies.clear();
|
||||
tex->canvas_texture = nullptr;
|
||||
tex->tex_id = 0;
|
||||
proxy_to->proxies.push_back(p_texture);
|
||||
}
|
||||
|
||||
|
@ -257,7 +257,14 @@ void EditorAudioBus::update_bus() {
|
||||
}
|
||||
|
||||
void EditorAudioBus::_name_changed(const String &p_new_name) {
|
||||
if (updating_bus) {
|
||||
return;
|
||||
}
|
||||
updating_bus = true;
|
||||
track_name->release_focus();
|
||||
|
||||
if (p_new_name == AudioServer::get_singleton()->get_bus_name(get_index())) {
|
||||
updating_bus = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -280,12 +287,15 @@ void EditorAudioBus::_name_changed(const String &p_new_name) {
|
||||
attempts++;
|
||||
attempt = p_new_name + " " + itos(attempts);
|
||||
}
|
||||
updating_bus = true;
|
||||
|
||||
EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
|
||||
|
||||
StringName current = AudioServer::get_singleton()->get_bus_name(get_index());
|
||||
|
||||
ur->create_action(TTR("Rename Audio Bus"));
|
||||
ur->add_do_method(buses, "_set_renaming_buses", true);
|
||||
ur->add_undo_method(buses, "_set_renaming_buses", true);
|
||||
|
||||
ur->add_do_method(AudioServer::get_singleton(), "set_bus_name", get_index(), attempt);
|
||||
ur->add_undo_method(AudioServer::get_singleton(), "set_bus_name", get_index(), current);
|
||||
|
||||
@ -301,11 +311,12 @@ void EditorAudioBus::_name_changed(const String &p_new_name) {
|
||||
|
||||
ur->add_do_method(buses, "_update_sends");
|
||||
ur->add_undo_method(buses, "_update_sends");
|
||||
|
||||
ur->add_do_method(buses, "_set_renaming_buses", false);
|
||||
ur->add_undo_method(buses, "_set_renaming_buses", false);
|
||||
ur->commit_action();
|
||||
|
||||
updating_bus = false;
|
||||
|
||||
track_name->release_focus();
|
||||
}
|
||||
|
||||
void EditorAudioBus::_volume_changed(float p_normalized) {
|
||||
@ -995,12 +1006,31 @@ void EditorAudioBusDrop::_bind_methods() {
|
||||
EditorAudioBusDrop::EditorAudioBusDrop() {
|
||||
}
|
||||
|
||||
void EditorAudioBuses::_set_renaming_buses(bool p_renaming) {
|
||||
renaming_buses = p_renaming;
|
||||
}
|
||||
|
||||
void EditorAudioBuses::_update_buses() {
|
||||
while (bus_hb->get_child_count() > 0) {
|
||||
memdelete(bus_hb->get_child(0));
|
||||
if (renaming_buses) {
|
||||
// This case will be handled more gracefully, no need to trigger a full rebuild.
|
||||
// This is possibly a mistake in the AudioServer, which fires bus_layout_changed
|
||||
// on a rename. This may not be intended, but no way to tell at the moment.
|
||||
return;
|
||||
}
|
||||
|
||||
drop_end = nullptr;
|
||||
for (int i = bus_hb->get_child_count() - 1; i >= 0; i--) {
|
||||
EditorAudioBus *audio_bus = Object::cast_to<EditorAudioBus>(bus_hb->get_child(i));
|
||||
if (audio_bus) {
|
||||
bus_hb->remove_child(audio_bus);
|
||||
audio_bus->queue_free();
|
||||
}
|
||||
}
|
||||
|
||||
if (drop_end) {
|
||||
bus_hb->remove_child(drop_end);
|
||||
drop_end->queue_free();
|
||||
drop_end = nullptr;
|
||||
}
|
||||
|
||||
for (int i = 0; i < AudioServer::get_singleton()->get_bus_count(); i++) {
|
||||
bool is_master = (i == 0);
|
||||
@ -1033,6 +1063,7 @@ void EditorAudioBuses::_notification(int p_what) {
|
||||
|
||||
case NOTIFICATION_DRAG_END: {
|
||||
if (drop_end) {
|
||||
bus_hb->remove_child(drop_end);
|
||||
drop_end->queue_free();
|
||||
drop_end = nullptr;
|
||||
}
|
||||
@ -1259,6 +1290,7 @@ void EditorAudioBuses::_file_dialog_callback(const String &p_string) {
|
||||
}
|
||||
|
||||
void EditorAudioBuses::_bind_methods() {
|
||||
ClassDB::bind_method("_set_renaming_buses", &EditorAudioBuses::_set_renaming_buses);
|
||||
ClassDB::bind_method("_update_buses", &EditorAudioBuses::_update_buses);
|
||||
ClassDB::bind_method("_update_bus", &EditorAudioBuses::_update_bus);
|
||||
ClassDB::bind_method("_update_sends", &EditorAudioBuses::_update_sends);
|
||||
|
@ -172,6 +172,9 @@ class EditorAudioBuses : public VBoxContainer {
|
||||
Timer *save_timer = nullptr;
|
||||
String edited_path;
|
||||
|
||||
bool renaming_buses = false;
|
||||
void _set_renaming_buses(bool p_renaming);
|
||||
|
||||
void _add_bus();
|
||||
void _update_buses();
|
||||
void _update_bus(int p_index);
|
||||
|
@ -151,6 +151,51 @@ EditorNode *EditorNode::singleton = nullptr;
|
||||
// The metadata key used to store and retrieve the version text to copy to the clipboard.
|
||||
static const String META_TEXT_TO_COPY = "text_to_copy";
|
||||
|
||||
class AcceptDialogAutoReparent : public AcceptDialog {
|
||||
GDCLASS(AcceptDialogAutoReparent, AcceptDialog);
|
||||
|
||||
protected:
|
||||
void _notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
|
||||
if (!is_visible()) {
|
||||
Node *p = get_parent();
|
||||
if (p) {
|
||||
p->remove_child(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void attach_and_popup_centered() {
|
||||
EditorNode *ed = EditorNode::get_singleton();
|
||||
if (ed && !is_inside_tree()) {
|
||||
Window *w = ed->get_window();
|
||||
while (w && w->get_exclusive_child()) {
|
||||
w = w->get_exclusive_child();
|
||||
}
|
||||
if (w && w != this) {
|
||||
w->add_child(this);
|
||||
popup_centered();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void attach_and_popup_centered_ratio(float p_ratio = 0.8) {
|
||||
EditorNode *ed = EditorNode::get_singleton();
|
||||
if (ed && !is_inside_tree()) {
|
||||
Window *w = ed->get_window();
|
||||
while (w && w->get_exclusive_child()) {
|
||||
w = w->get_exclusive_child();
|
||||
}
|
||||
if (w && w != this) {
|
||||
w->add_child(this);
|
||||
popup_centered_ratio(p_ratio);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void EditorNode::disambiguate_filenames(const Vector<String> p_full_paths, Vector<String> &r_filenames) {
|
||||
ERR_FAIL_COND_MSG(p_full_paths.size() != r_filenames.size(), vformat("disambiguate_filenames requires two string vectors of same length (%d != %d).", p_full_paths.size(), r_filenames.size()));
|
||||
|
||||
@ -615,6 +660,21 @@ void EditorNode::_notification(int p_what) {
|
||||
if (progress_dialog) {
|
||||
progress_dialog->queue_free();
|
||||
}
|
||||
if (load_error_dialog) {
|
||||
load_error_dialog->queue_free();
|
||||
}
|
||||
if (execute_output_dialog) {
|
||||
execute_output_dialog->queue_free();
|
||||
}
|
||||
if (warning) {
|
||||
warning->queue_free();
|
||||
}
|
||||
if (accept) {
|
||||
accept->queue_free();
|
||||
}
|
||||
if (save_accept) {
|
||||
save_accept->queue_free();
|
||||
}
|
||||
editor_data.save_editor_external_data();
|
||||
FileAccess::set_file_close_fail_notify_callback(nullptr);
|
||||
log->deinit(); // Do not get messages anymore.
|
||||
@ -1233,6 +1293,12 @@ void EditorNode::edit_resource(const Ref<Resource> &p_resource) {
|
||||
|
||||
void EditorNode::save_resource_in_path(const Ref<Resource> &p_resource, const String &p_path) {
|
||||
editor_data.apply_changes_in_editors();
|
||||
|
||||
if (saving_resources_in_path.has(p_resource)) {
|
||||
return;
|
||||
}
|
||||
saving_resources_in_path.insert(p_resource);
|
||||
|
||||
int flg = 0;
|
||||
if (EDITOR_GET("filesystem/on_save/compress_binary_resources")) {
|
||||
flg |= ResourceSaver::FLAG_COMPRESS;
|
||||
@ -1247,10 +1313,16 @@ void EditorNode::save_resource_in_path(const Ref<Resource> &p_resource, const St
|
||||
} else {
|
||||
show_accept(TTR("Error saving resource!"), TTR("OK"));
|
||||
}
|
||||
|
||||
saving_resources_in_path.erase(p_resource);
|
||||
return;
|
||||
}
|
||||
|
||||
((Resource *)p_resource.ptr())->set_path(path);
|
||||
saving_resources_in_path.erase(p_resource);
|
||||
|
||||
_resource_saved(p_resource, path);
|
||||
|
||||
emit_signal(SNAME("resource_saved"), p_resource);
|
||||
editor_data.notify_resource_saved(p_resource);
|
||||
}
|
||||
@ -4266,9 +4338,11 @@ void EditorNode::add_io_error(const String &p_error) {
|
||||
|
||||
void EditorNode::_load_error_notify(void *p_ud, const String &p_text) {
|
||||
EditorNode *en = static_cast<EditorNode *>(p_ud);
|
||||
en->load_errors->add_image(en->gui_base->get_theme_icon(SNAME("Error"), SNAME("EditorIcons")));
|
||||
en->load_errors->add_text(p_text + "\n");
|
||||
en->load_error_dialog->popup_centered_ratio(0.5);
|
||||
if (en && en->load_error_dialog) {
|
||||
en->load_errors->add_image(en->gui_base->get_theme_icon(SNAME("Error"), SNAME("EditorIcons")));
|
||||
en->load_errors->add_text(p_text + "\n");
|
||||
en->load_error_dialog->attach_and_popup_centered_ratio(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
bool EditorNode::_find_scene_in_use(Node *p_node, const String &p_path) const {
|
||||
@ -4639,23 +4713,27 @@ Error EditorNode::export_preset(const String &p_preset, const String &p_path, bo
|
||||
|
||||
void EditorNode::show_accept(const String &p_text, const String &p_title) {
|
||||
current_menu_option = -1;
|
||||
accept->set_ok_button_text(p_title);
|
||||
accept->set_text(p_text);
|
||||
accept->popup_centered();
|
||||
if (accept) {
|
||||
accept->set_ok_button_text(p_title);
|
||||
accept->set_text(p_text);
|
||||
accept->attach_and_popup_centered();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorNode::show_save_accept(const String &p_text, const String &p_title) {
|
||||
current_menu_option = -1;
|
||||
save_accept->set_ok_button_text(p_title);
|
||||
save_accept->set_text(p_text);
|
||||
save_accept->popup_centered();
|
||||
if (save_accept) {
|
||||
save_accept->set_ok_button_text(p_title);
|
||||
save_accept->set_text(p_text);
|
||||
save_accept->attach_and_popup_centered();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorNode::show_warning(const String &p_text, const String &p_title) {
|
||||
if (warning->is_inside_tree()) {
|
||||
if (warning) {
|
||||
warning->set_text(p_text);
|
||||
warning->set_title(p_title);
|
||||
warning->popup_centered();
|
||||
warning->attach_and_popup_centered();
|
||||
} else {
|
||||
WARN_PRINT(p_title + " " + p_text);
|
||||
}
|
||||
@ -4795,6 +4873,7 @@ void EditorNode::_dock_select_input(const Ref<InputEvent> &p_input) {
|
||||
dock_slot[nrect]->add_child(dock);
|
||||
dock_popup_selected_idx = nrect;
|
||||
dock_slot[nrect]->set_current_tab(dock_slot[nrect]->get_tab_count() - 1);
|
||||
dock_slot[nrect]->set_tab_title(dock_slot[nrect]->get_tab_count() - 1, TTRGET(dock->get_name()));
|
||||
dock_slot[nrect]->show();
|
||||
dock_select->queue_redraw();
|
||||
|
||||
@ -5152,6 +5231,7 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String
|
||||
}
|
||||
dock_slot[i]->add_child(node);
|
||||
dock_slot[i]->move_child(node, 0);
|
||||
dock_slot[i]->set_tab_title(0, TTRGET(node->get_name()));
|
||||
dock_slot[i]->show();
|
||||
}
|
||||
}
|
||||
@ -6441,6 +6521,11 @@ void EditorNode::_renderer_selected(int p_which) {
|
||||
}
|
||||
|
||||
void EditorNode::_resource_saved(Ref<Resource> p_resource, const String &p_path) {
|
||||
if (singleton->saving_resources_in_path.has(p_resource)) {
|
||||
// This is going to be handled by save_resource_in_path when the time is right.
|
||||
return;
|
||||
}
|
||||
|
||||
if (EditorFileSystem::get_singleton()) {
|
||||
EditorFileSystem::get_singleton()->update_file(p_path);
|
||||
}
|
||||
@ -6492,7 +6577,6 @@ void EditorNode::_feature_profile_changed() {
|
||||
}
|
||||
|
||||
void EditorNode::_bind_methods() {
|
||||
GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/naming/scene_name_casing", PROPERTY_HINT_ENUM, "Auto,PascalCase,snake_case"), SCENE_NAME_CASING_SNAKE_CASE);
|
||||
ClassDB::bind_method("edit_current", &EditorNode::edit_current);
|
||||
ClassDB::bind_method("edit_node", &EditorNode::edit_node);
|
||||
|
||||
@ -6549,11 +6633,13 @@ static void _execute_thread(void *p_ud) {
|
||||
}
|
||||
|
||||
int EditorNode::execute_and_show_output(const String &p_title, const String &p_path, const List<String> &p_arguments, bool p_close_on_ok, bool p_close_on_errors) {
|
||||
execute_output_dialog->set_title(p_title);
|
||||
execute_output_dialog->get_ok_button()->set_disabled(true);
|
||||
execute_outputs->clear();
|
||||
execute_outputs->set_scroll_follow(true);
|
||||
execute_output_dialog->popup_centered_ratio();
|
||||
if (execute_output_dialog) {
|
||||
execute_output_dialog->set_title(p_title);
|
||||
execute_output_dialog->get_ok_button()->set_disabled(true);
|
||||
execute_outputs->clear();
|
||||
execute_outputs->set_scroll_follow(true);
|
||||
execute_output_dialog->attach_and_popup_centered_ratio();
|
||||
}
|
||||
|
||||
ExecuteThreadArgs eta;
|
||||
eta.path = p_path;
|
||||
@ -6571,6 +6657,7 @@ int EditorNode::execute_and_show_output(const String &p_title, const String &p_p
|
||||
String to_add = eta.output.substr(prev_len, eta.output.length());
|
||||
prev_len = eta.output.length();
|
||||
execute_outputs->add_text(to_add);
|
||||
DisplayServer::get_singleton()->process_events(); // Get rid of pending events.
|
||||
Main::iteration();
|
||||
}
|
||||
}
|
||||
@ -6580,14 +6667,16 @@ int EditorNode::execute_and_show_output(const String &p_title, const String &p_p
|
||||
eta.execute_output_thread.wait_to_finish();
|
||||
execute_outputs->add_text("\nExit Code: " + itos(eta.exitcode));
|
||||
|
||||
if (p_close_on_errors && eta.exitcode != 0) {
|
||||
execute_output_dialog->hide();
|
||||
}
|
||||
if (p_close_on_ok && eta.exitcode == 0) {
|
||||
execute_output_dialog->hide();
|
||||
}
|
||||
if (execute_output_dialog) {
|
||||
if (p_close_on_errors && eta.exitcode != 0) {
|
||||
execute_output_dialog->hide();
|
||||
}
|
||||
if (p_close_on_ok && eta.exitcode == 0) {
|
||||
execute_output_dialog->hide();
|
||||
}
|
||||
|
||||
execute_output_dialog->get_ok_button()->set_disabled(false);
|
||||
execute_output_dialog->get_ok_button()->set_disabled(false);
|
||||
}
|
||||
|
||||
return eta.exitcode;
|
||||
}
|
||||
@ -7158,12 +7247,10 @@ EditorNode::EditorNode() {
|
||||
prev_scene->set_position(Point2(3, 24));
|
||||
prev_scene->hide();
|
||||
|
||||
accept = memnew(AcceptDialog);
|
||||
gui_base->add_child(accept);
|
||||
accept = memnew(AcceptDialogAutoReparent);
|
||||
accept->connect("confirmed", callable_mp(this, &EditorNode::_menu_confirm_current));
|
||||
|
||||
save_accept = memnew(AcceptDialog);
|
||||
gui_base->add_child(save_accept);
|
||||
save_accept = memnew(AcceptDialogAutoReparent);
|
||||
save_accept->connect("confirmed", callable_mp(this, &EditorNode::_menu_option).bind((int)MenuOptions::FILE_SAVE_AS_SCENE));
|
||||
|
||||
project_export = memnew(ProjectExportDialog);
|
||||
@ -7208,9 +7295,8 @@ EditorNode::EditorNode() {
|
||||
gui_base->add_child(fbx_importer_manager);
|
||||
#endif
|
||||
|
||||
warning = memnew(AcceptDialog);
|
||||
warning = memnew(AcceptDialogAutoReparent);
|
||||
warning->add_button(TTR("Copy Text"), true, "copy");
|
||||
gui_base->add_child(warning);
|
||||
warning->connect("custom_action", callable_mp(this, &EditorNode::_copy_warning));
|
||||
|
||||
ED_SHORTCUT("editor/next_tab", TTR("Next Scene Tab"), KeyModifierMask::CMD_OR_CTRL + Key::TAB);
|
||||
@ -7978,17 +8064,15 @@ EditorNode::EditorNode() {
|
||||
set_process_shortcut_input(true);
|
||||
|
||||
load_errors = memnew(RichTextLabel);
|
||||
load_error_dialog = memnew(AcceptDialog);
|
||||
load_error_dialog = memnew(AcceptDialogAutoReparent);
|
||||
load_error_dialog->add_child(load_errors);
|
||||
load_error_dialog->set_title(TTR("Load Errors"));
|
||||
gui_base->add_child(load_error_dialog);
|
||||
|
||||
execute_outputs = memnew(RichTextLabel);
|
||||
execute_outputs->set_selection_enabled(true);
|
||||
execute_output_dialog = memnew(AcceptDialog);
|
||||
execute_output_dialog = memnew(AcceptDialogAutoReparent);
|
||||
execute_output_dialog->add_child(execute_outputs);
|
||||
execute_output_dialog->set_title("");
|
||||
gui_base->add_child(execute_output_dialog);
|
||||
|
||||
EditorFileSystem::get_singleton()->connect("sources_changed", callable_mp(this, &EditorNode::_sources_changed));
|
||||
EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &EditorNode::_fs_changed));
|
||||
|
@ -45,6 +45,7 @@ typedef void (*EditorPluginInitializeCallback)();
|
||||
typedef bool (*EditorBuildCallback)();
|
||||
|
||||
class AcceptDialog;
|
||||
class AcceptDialogAutoReparent;
|
||||
class AudioStreamPreviewGenerator;
|
||||
class BackgroundProgress;
|
||||
class CenterContainer;
|
||||
@ -370,10 +371,10 @@ private:
|
||||
PluginConfigDialog *plugin_config_dialog = nullptr;
|
||||
|
||||
RichTextLabel *load_errors = nullptr;
|
||||
AcceptDialog *load_error_dialog = nullptr;
|
||||
AcceptDialogAutoReparent *load_error_dialog = nullptr;
|
||||
|
||||
RichTextLabel *execute_outputs = nullptr;
|
||||
AcceptDialog *execute_output_dialog = nullptr;
|
||||
AcceptDialogAutoReparent *execute_output_dialog = nullptr;
|
||||
|
||||
Ref<Theme> theme;
|
||||
|
||||
@ -388,10 +389,10 @@ private:
|
||||
ConfirmationDialog *import_confirmation = nullptr;
|
||||
ConfirmationDialog *pick_main_scene = nullptr;
|
||||
Button *select_current_scene_button = nullptr;
|
||||
AcceptDialog *accept = nullptr;
|
||||
AcceptDialog *save_accept = nullptr;
|
||||
AcceptDialogAutoReparent *accept = nullptr;
|
||||
AcceptDialogAutoReparent *save_accept = nullptr;
|
||||
EditorAbout *about = nullptr;
|
||||
AcceptDialog *warning = nullptr;
|
||||
AcceptDialogAutoReparent *warning = nullptr;
|
||||
|
||||
int overridden_default_layout = -1;
|
||||
Ref<ConfigFile> default_layout;
|
||||
@ -485,6 +486,7 @@ private:
|
||||
Object *current = nullptr;
|
||||
|
||||
Ref<Resource> saving_resource;
|
||||
HashSet<Ref<Resource>> saving_resources_in_path;
|
||||
|
||||
uint64_t update_spinner_step_msec = 0;
|
||||
uint64_t update_spinner_step_frame = 0;
|
||||
|
@ -137,6 +137,7 @@ Vector<Ref<Texture2D>> EditorInterface::make_mesh_previews(const Vector<Ref<Mesh
|
||||
RS::get_singleton()->instance_set_transform(light_instance2, xform * Transform3D().looking_at(Vector3(+1, -1, -2), Vector3(0, 1, 0)));
|
||||
|
||||
ep.step(TTR("Thumbnail..."), i);
|
||||
DisplayServer::get_singleton()->process_events();
|
||||
Main::iteration();
|
||||
Main::iteration();
|
||||
Ref<Image> img = RS::get_singleton()->texture_2d_get(viewport_texture);
|
||||
|
@ -399,8 +399,12 @@ void EditorResourcePicker::_edit_menu_cbk(int p_which) {
|
||||
file_system_dock->navigate_to_path(edited_resource->get_path());
|
||||
|
||||
// Ensure that the FileSystem dock is visible.
|
||||
TabContainer *tab_container = (TabContainer *)file_system_dock->get_parent_control();
|
||||
tab_container->set_current_tab(tab_container->get_tab_idx_from_control(file_system_dock));
|
||||
if (file_system_dock->get_window() == get_tree()->get_root()) {
|
||||
TabContainer *tab_container = (TabContainer *)file_system_dock->get_parent_control();
|
||||
tab_container->set_current_tab(tab_container->get_tab_idx_from_control(file_system_dock));
|
||||
} else {
|
||||
file_system_dock->get_window()->grab_focus();
|
||||
}
|
||||
} break;
|
||||
|
||||
default: {
|
||||
|
@ -231,11 +231,11 @@ static Ref<StyleBoxLine> make_line_stylebox(Color p_color, int p_thickness = 1,
|
||||
return style;
|
||||
}
|
||||
|
||||
#ifdef MODULE_SVG_ENABLED
|
||||
// See also `generate_icon()` in `scene/resources/default_theme.cpp`.
|
||||
static Ref<ImageTexture> editor_generate_icon(int p_index, float p_scale, float p_saturation, const HashMap<Color, Color> &p_convert_colors = HashMap<Color, Color>()) {
|
||||
Ref<Image> img = memnew(Image);
|
||||
|
||||
#ifdef MODULE_SVG_ENABLED
|
||||
// Upsample icon generation only if the editor scale isn't an integer multiplier.
|
||||
// Generating upsampled icons is slower, and the benefit is hardly visible
|
||||
// with integer editor scales.
|
||||
@ -246,13 +246,16 @@ static Ref<ImageTexture> editor_generate_icon(int p_index, float p_scale, float
|
||||
if (p_saturation != 1.0) {
|
||||
img->adjust_bcs(1.0, 1.0, p_saturation);
|
||||
}
|
||||
#else
|
||||
// If the SVG module is disabled, we can't really display the UI well, but at least we won't crash.
|
||||
// 16 pixels is used as it's the most common base size for Godot icons.
|
||||
img = Image::create_empty(16 * p_scale, 16 * p_scale, false, Image::FORMAT_RGBA8);
|
||||
#endif
|
||||
|
||||
return ImageTexture::create_from_image(img);
|
||||
}
|
||||
#endif
|
||||
|
||||
void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme, float p_icon_saturation, int p_thumb_size, bool p_only_thumbs = false) {
|
||||
#ifdef MODULE_SVG_ENABLED
|
||||
// Before we register the icons, we adjust their colors and saturation.
|
||||
// Most icons follow the standard rules for color conversion to follow the editor
|
||||
// theme's polarity (dark/light). We also adjust the saturation for most icons,
|
||||
@ -379,9 +382,6 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme, f
|
||||
p_theme->set_icon(editor_icons_names[index], SNAME("EditorIcons"), icon);
|
||||
}
|
||||
}
|
||||
#else
|
||||
WARN_PRINT("SVG support disabled, editor icons won't be rendered.");
|
||||
#endif
|
||||
}
|
||||
|
||||
Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
|
||||
@ -618,6 +618,10 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
|
||||
regenerate_thumb_icons = !Math::is_equal_approx(prev_thumb_size, thumb_size);
|
||||
}
|
||||
|
||||
#ifndef MODULE_SVG_ENABLED
|
||||
WARN_PRINT("SVG support disabled, editor icons won't be rendered.");
|
||||
#endif
|
||||
|
||||
if (keep_old_icons) {
|
||||
for (int i = 0; i < editor_icons_count; i++) {
|
||||
theme->set_icon(editor_icons_names[i], SNAME("EditorIcons"), p_theme->get_icon(editor_icons_names[i], SNAME("EditorIcons")));
|
||||
|
@ -90,10 +90,10 @@ void EditorToaster::_notification(int p_what) {
|
||||
}
|
||||
|
||||
// Hide element if it is not visible anymore.
|
||||
if (modulate_fade.a <= 0 && element.key->is_visible()) {
|
||||
if (modulate_fade.a <= 0.0 && element.key->is_visible()) {
|
||||
element.key->hide();
|
||||
needs_update = true;
|
||||
} else if (modulate_fade.a >= 0 && !element.key->is_visible()) {
|
||||
} else if (modulate_fade.a > 0.0 && !element.key->is_visible()) {
|
||||
element.key->show();
|
||||
needs_update = true;
|
||||
}
|
||||
|
@ -943,8 +943,8 @@ void ProjectExportDialog::_export_pck_zip_selected(const String &p_path) {
|
||||
}
|
||||
|
||||
void ProjectExportDialog::_open_export_template_manager() {
|
||||
EditorNode::get_singleton()->open_export_template_manager();
|
||||
hide();
|
||||
EditorNode::get_singleton()->open_export_template_manager();
|
||||
}
|
||||
|
||||
void ProjectExportDialog::_validate_export_path(const String &p_path) {
|
||||
|
@ -648,7 +648,7 @@ void TileSetAtlasSourceEditor::_update_tile_data_editors() {
|
||||
if (!tile_data_editors.has("texture_origin")) {
|
||||
TileDataTextureOriginEditor *tile_data_texture_origin_editor = memnew(TileDataTextureOriginEditor);
|
||||
tile_data_texture_origin_editor->hide();
|
||||
tile_data_texture_origin_editor->setup_property_editor(Variant::VECTOR2, "texture_origin");
|
||||
tile_data_texture_origin_editor->setup_property_editor(Variant::VECTOR2I, "texture_origin");
|
||||
tile_data_texture_origin_editor->connect("needs_redraw", callable_mp((CanvasItem *)tile_atlas_control_unscaled, &Control::queue_redraw));
|
||||
tile_data_texture_origin_editor->connect("needs_redraw", callable_mp((CanvasItem *)alternative_tiles_control_unscaled, &Control::queue_redraw));
|
||||
tile_data_editors["texture_origin"] = tile_data_texture_origin_editor;
|
||||
|
@ -145,7 +145,10 @@ void TilesEditorPlugin::_tile_map_changed() {
|
||||
|
||||
void TilesEditorPlugin::_update_editors() {
|
||||
// If tile_map is not edited, we change the edited only if we are not editing a tile_set.
|
||||
tileset_editor->edit(tile_set);
|
||||
if (tile_set.is_valid()) {
|
||||
tileset_editor->edit(tile_set);
|
||||
}
|
||||
|
||||
TileMap *tile_map = Object::cast_to<TileMap>(ObjectDB::get_instance(tile_map_id));
|
||||
if (tile_map) {
|
||||
tilemap_editor->edit(tile_map);
|
||||
@ -158,6 +161,7 @@ void TilesEditorPlugin::_update_editors() {
|
||||
|
||||
// Make sure the tile set editor is visible if we have one assigned.
|
||||
tileset_editor_button->set_visible(is_visible && tile_set.is_valid());
|
||||
tilemap_editor_button->set_visible(is_visible && tile_map);
|
||||
|
||||
// Update visibility of bottom panel buttons.
|
||||
if (tileset_editor_button->is_pressed() && !tile_set.is_valid()) {
|
||||
|
@ -221,9 +221,7 @@ bool ProgressDialog::task_step(const String &p_task, const String &p_state, int
|
||||
|
||||
t.state->set_text(p_state);
|
||||
last_progress_tick = OS::get_singleton()->get_ticks_usec();
|
||||
if (cancel_hb->is_visible()) {
|
||||
DisplayServer::get_singleton()->process_events();
|
||||
}
|
||||
DisplayServer::get_singleton()->process_events();
|
||||
|
||||
#ifndef ANDROID_ENABLED
|
||||
Main::iteration(); // this will not work on a lot of platforms, so it's only meant for the editor
|
||||
|
@ -70,9 +70,9 @@ public:
|
||||
RegEx reg_json_print = RegEx("\\bJSON\\b\\.print\\(");
|
||||
RegEx reg_export = RegEx("export\\(([a-zA-Z0-9_]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)");
|
||||
RegEx reg_export_advanced = RegEx("export\\(([^)^\n]+)\\)[ ]+var[ ]+([a-zA-Z0-9_]+)([^\n]+)");
|
||||
RegEx reg_setget_setget = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+([a-zA-Z0-9_]+)[ \t]*,[ \t]*([a-zA-Z0-9_]+)");
|
||||
RegEx reg_setget_set = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+([a-zA-Z0-9_]+)[ \t]*[,]*[^a-z^A-Z^0-9^_]*$");
|
||||
RegEx reg_setget_get = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+)setget[ \t]+,[ \t]*([a-zA-Z0-9_]+)[ \t]*$");
|
||||
RegEx reg_setget_setget = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+?)[ \t]*setget[ \t]+([a-zA-Z0-9_]+)[ \t]*,[ \t]*([a-zA-Z0-9_]+)");
|
||||
RegEx reg_setget_set = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+?)[ \t]*setget[ \t]+([a-zA-Z0-9_]+)[ \t]*[,]*[^\n]*$");
|
||||
RegEx reg_setget_get = RegEx("var[ ]+([a-zA-Z0-9_]+)([^\n]+?)[ \t]*setget[ \t]+,[ \t]*([a-zA-Z0-9_]+)[ \t]*$");
|
||||
RegEx reg_join = RegEx("([\\(\\)a-zA-Z0-9_]+)\\.join\\(([^\n^\\)]+)\\)");
|
||||
RegEx reg_image_lock = RegEx("([a-zA-Z0-9_\\.]+)\\.lock\\(\\)");
|
||||
RegEx reg_image_unlock = RegEx("([a-zA-Z0-9_\\.]+)\\.unlock\\(\\)");
|
||||
@ -828,10 +828,10 @@ bool ProjectConverter3To4::test_conversion(RegExContainer ®_container) {
|
||||
valid = valid && test_conversion_with_regex("\n\nmaster func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
|
||||
valid = valid && test_conversion_with_regex("\n\nmastersync func", "\n\nThe master and mastersync rpc behavior is not officially supported anymore. Try using another keyword or making custom logic using get_multiplayer().get_remote_sender_id()\n@rpc(\"call_local\") func", &ProjectConverter3To4::rename_gdscript_keywords, "gdscript keyword", reg_container);
|
||||
|
||||
valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function , get_function", "var size : Vector2 = Vector2() : get = get_function, set = set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
|
||||
valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function , ", "var size : Vector2 = Vector2() : set = set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
|
||||
valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget set_function", "var size : Vector2 = Vector2() : set = set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
|
||||
valid = valid && test_conversion_gdscript_builtin("var size : Vector2 = Vector2() setget , get_function", "var size : Vector2 = Vector2() : get = get_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
|
||||
valid = valid && test_conversion_gdscript_builtin("var size: Vector2 = Vector2() setget set_function, get_function", "var size: Vector2 = Vector2(): get = get_function, set = set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
|
||||
valid = valid && test_conversion_gdscript_builtin("var size: Vector2 = Vector2() setget set_function, ", "var size: Vector2 = Vector2(): set = set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
|
||||
valid = valid && test_conversion_gdscript_builtin("var size: Vector2 = Vector2() setget set_function", "var size: Vector2 = Vector2(): set = set_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
|
||||
valid = valid && test_conversion_gdscript_builtin("var size: Vector2 = Vector2() setget , get_function", "var size: Vector2 = Vector2(): get = get_function", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
|
||||
|
||||
valid = valid && test_conversion_gdscript_builtin("get_node(@", "get_node(", &ProjectConverter3To4::rename_gdscript_functions, "custom rename", reg_container, false);
|
||||
|
||||
|
@ -212,6 +212,15 @@ void register_editor_types() {
|
||||
EditorPlugins::add_by_type<Skeleton2DEditorPlugin>();
|
||||
EditorPlugins::add_by_type<Sprite2DEditorPlugin>();
|
||||
EditorPlugins::add_by_type<TilesEditorPlugin>();
|
||||
|
||||
// For correct doc generation.
|
||||
GLOBAL_DEF("editor/run/main_run_args", "");
|
||||
|
||||
GLOBAL_DEF(PropertyInfo(Variant::STRING, "editor/script/templates_search_path", PROPERTY_HINT_DIR), "res://script_templates");
|
||||
|
||||
GLOBAL_DEF("editor/naming/default_signal_callback_name", "_on_{node_name}_{signal_name}");
|
||||
GLOBAL_DEF("editor/naming/default_signal_callback_to_self_name", "_on_{signal_name}");
|
||||
GLOBAL_DEF(PropertyInfo(Variant::INT, "editor/naming/scene_name_casing", PROPERTY_HINT_ENUM, "Auto,PascalCase,snake_case"), EditorNode::SCENE_NAME_CASING_SNAKE_CASE);
|
||||
}
|
||||
|
||||
void unregister_editor_types() {
|
||||
|
@ -108,6 +108,10 @@
|
||||
|
||||
#include "modules/modules_enabled.gen.h" // For mono.
|
||||
|
||||
#if defined(MODULE_MONO_ENABLED) && defined(TOOLS_ENABLED)
|
||||
#include "modules/mono/editor/bindings_generator.h"
|
||||
#endif
|
||||
|
||||
/* Static members */
|
||||
|
||||
// Singletons
|
||||
@ -312,7 +316,6 @@ void finalize_navigation_server() {
|
||||
|
||||
void initialize_theme_db() {
|
||||
theme_db = memnew(ThemeDB);
|
||||
theme_db->initialize_theme();
|
||||
}
|
||||
|
||||
void finalize_theme_db() {
|
||||
@ -532,6 +535,7 @@ Error Main::test_setup() {
|
||||
|
||||
// Theme needs modules to be initialized so that sub-resources can be loaded.
|
||||
initialize_theme_db();
|
||||
theme_db->initialize_theme();
|
||||
register_scene_singletons();
|
||||
|
||||
ERR_FAIL_COND_V(TextServerManager::get_singleton()->get_interface_count() == 0, ERR_CANT_CREATE);
|
||||
@ -2314,6 +2318,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
|
||||
register_platform_apis();
|
||||
|
||||
// Theme needs modules to be initialized so that sub-resources can be loaded.
|
||||
// Default theme is initialized later, after ScriptServer is ready.
|
||||
initialize_theme_db();
|
||||
register_scene_singletons();
|
||||
|
||||
@ -2341,8 +2346,18 @@ Error Main::setup2(Thread::ID p_main_tid_override) {
|
||||
// This loads global classes, so it must happen before custom loaders and savers are registered
|
||||
ScriptServer::init_languages();
|
||||
|
||||
theme_db->initialize_theme();
|
||||
audio_server->load_default_bus_layout();
|
||||
|
||||
#if defined(MODULE_MONO_ENABLED) && defined(TOOLS_ENABLED)
|
||||
// Hacky to have it here, but we don't have good facility yet to let modules
|
||||
// register command line options to call at the right time. This needs to happen
|
||||
// after init'ing the ScriptServer, but also after init'ing the ThemeDB,
|
||||
// for the C# docs generation in the bindings.
|
||||
List<String> cmdline_args = OS::get_singleton()->get_cmdline_args();
|
||||
BindingsGenerator::handle_cmdline_args(cmdline_args);
|
||||
#endif
|
||||
|
||||
if (use_debug_profiler && EngineDebugger::is_active()) {
|
||||
// Start the "scripts" profiler, used in local debugging.
|
||||
// We could add more, and make the CLI arg require a comma-separated list of profilers.
|
||||
|
@ -285,7 +285,7 @@
|
||||
@export var string = ""
|
||||
@export var int_number = 5
|
||||
@export var float_number: float = 5
|
||||
@export var image : Image
|
||||
@export var image: Image
|
||||
[/codeblock]
|
||||
</description>
|
||||
</annotation>
|
||||
@ -309,7 +309,7 @@
|
||||
Export a [Color] property without allowing its transparency ([member Color.a]) to be edited.
|
||||
See also [constant PROPERTY_HINT_COLOR_NO_ALPHA].
|
||||
[codeblock]
|
||||
@export_color_no_alpha var dye_color : Color
|
||||
@export_color_no_alpha var dye_color: Color
|
||||
[/codeblock]
|
||||
</description>
|
||||
</annotation>
|
||||
|
@ -1010,12 +1010,14 @@ void GDScript::_bind_methods() {
|
||||
}
|
||||
|
||||
void GDScript::set_path(const String &p_path, bool p_take_over) {
|
||||
String old_path = path;
|
||||
if (is_root_script()) {
|
||||
Script::set_path(p_path, p_take_over);
|
||||
}
|
||||
this->path = p_path;
|
||||
|
||||
String old_path = path;
|
||||
path = p_path;
|
||||
GDScriptCache::move_script(old_path, p_path);
|
||||
|
||||
for (KeyValue<StringName, Ref<GDScript>> &kv : subclasses) {
|
||||
kv.value->set_path(p_path, p_take_over);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
enum MyEnum { ENUM_VALUE_1, ENUM_VALUE_2 }
|
||||
enum MyOtherEnum { OTHER_ENUM_VALUE_1, OTHER_ENUM_VALUE_2 }
|
||||
|
||||
func enum_func(e : MyEnum) -> void:
|
||||
func enum_func(e: MyEnum) -> void:
|
||||
print(e)
|
||||
|
||||
func test():
|
||||
|
@ -4,4 +4,4 @@ func test():
|
||||
x.free()
|
||||
|
||||
var ok = x
|
||||
var bad : Node = x
|
||||
var bad: Node = x
|
||||
|
@ -2,5 +2,5 @@ enum LocalNamed { VALUE_A, VALUE_B, VALUE_C = 42 }
|
||||
|
||||
func test():
|
||||
const P = preload("../features/enum_from_outer.gd")
|
||||
var x : LocalNamed
|
||||
var x: LocalNamed
|
||||
x = P.Named.VALUE_A
|
||||
|
@ -1,7 +1,7 @@
|
||||
var _prop : int
|
||||
var _prop: int
|
||||
|
||||
# Getter function has wrong return type.
|
||||
var prop : String:
|
||||
var prop: String:
|
||||
get = get_prop
|
||||
|
||||
func get_prop():
|
||||
|
@ -1,10 +1,10 @@
|
||||
var _prop : int
|
||||
var _prop: int
|
||||
|
||||
# Setter function has wrong argument type.
|
||||
var prop : String:
|
||||
var prop: String:
|
||||
set = set_prop
|
||||
|
||||
func set_prop(value : int):
|
||||
func set_prop(value: int):
|
||||
_prop = value
|
||||
|
||||
func test():
|
||||
|
@ -1,7 +1,7 @@
|
||||
var _prop : int
|
||||
var _prop: int
|
||||
|
||||
# Inline getter returns int instead of String.
|
||||
var prop : String:
|
||||
var prop: String:
|
||||
get:
|
||||
return _prop
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
var _prop : int
|
||||
var _prop: int
|
||||
|
||||
# Inline setter assigns String to int.
|
||||
var prop : String:
|
||||
var prop: String:
|
||||
set(value):
|
||||
_prop = value
|
||||
|
||||
|
@ -7,4 +7,4 @@ func test():
|
||||
x.free()
|
||||
|
||||
var ok = x
|
||||
var bad : A = x
|
||||
var bad: A = x
|
||||
|
@ -1,7 +1,7 @@
|
||||
enum Enum {V1, V2}
|
||||
|
||||
func test():
|
||||
var enumAsDict : Dictionary = Enum.duplicate()
|
||||
var enumAsDict: Dictionary = Enum.duplicate()
|
||||
var enumAsVariant = Enum.duplicate()
|
||||
print(Enum.has("V1"))
|
||||
print(enumAsDict.has("V1"))
|
||||
|
@ -5,19 +5,19 @@ enum MyEnum { V0, V1, V2 }
|
||||
class InnerClass:
|
||||
enum MyEnum { V0, V2, V1 }
|
||||
|
||||
func inner_inner_no_class(e : MyEnum) -> MyEnum:
|
||||
func inner_inner_no_class(e: MyEnum) -> MyEnum:
|
||||
print(e)
|
||||
return e
|
||||
|
||||
func inner_inner_class(e : InnerClass.MyEnum) -> InnerClass.MyEnum:
|
||||
func inner_inner_class(e: InnerClass.MyEnum) -> InnerClass.MyEnum:
|
||||
print(e)
|
||||
return e
|
||||
|
||||
func inner_inner_class_class(e : EnumFunctionTypecheckOuterClass.InnerClass.MyEnum) -> EnumFunctionTypecheckOuterClass.InnerClass.MyEnum:
|
||||
func inner_inner_class_class(e: EnumFunctionTypecheckOuterClass.InnerClass.MyEnum) -> EnumFunctionTypecheckOuterClass.InnerClass.MyEnum:
|
||||
print(e)
|
||||
return e
|
||||
|
||||
func inner_outer(e : EnumFunctionTypecheckOuterClass.MyEnum) -> EnumFunctionTypecheckOuterClass.MyEnum:
|
||||
func inner_outer(e: EnumFunctionTypecheckOuterClass.MyEnum) -> EnumFunctionTypecheckOuterClass.MyEnum:
|
||||
print(e)
|
||||
return e
|
||||
|
||||
@ -59,19 +59,19 @@ class InnerClass:
|
||||
print()
|
||||
|
||||
|
||||
func outer_outer_no_class(e : MyEnum) -> MyEnum:
|
||||
func outer_outer_no_class(e: MyEnum) -> MyEnum:
|
||||
print(e)
|
||||
return e
|
||||
|
||||
func outer_outer_class(e : EnumFunctionTypecheckOuterClass.MyEnum) -> EnumFunctionTypecheckOuterClass.MyEnum:
|
||||
func outer_outer_class(e: EnumFunctionTypecheckOuterClass.MyEnum) -> EnumFunctionTypecheckOuterClass.MyEnum:
|
||||
print(e)
|
||||
return e
|
||||
|
||||
func outer_inner_class(e : InnerClass.MyEnum) -> InnerClass.MyEnum:
|
||||
func outer_inner_class(e: InnerClass.MyEnum) -> InnerClass.MyEnum:
|
||||
print(e)
|
||||
return e
|
||||
|
||||
func outer_inner_class_class(e : EnumFunctionTypecheckOuterClass.InnerClass.MyEnum) -> EnumFunctionTypecheckOuterClass.InnerClass.MyEnum:
|
||||
func outer_inner_class_class(e: EnumFunctionTypecheckOuterClass.InnerClass.MyEnum) -> EnumFunctionTypecheckOuterClass.InnerClass.MyEnum:
|
||||
print(e)
|
||||
return e
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
func print_enum(e : TileSet.TileShape) -> TileSet.TileShape:
|
||||
func print_enum(e: TileSet.TileShape) -> TileSet.TileShape:
|
||||
print(e)
|
||||
return e
|
||||
|
||||
func test():
|
||||
var v : TileSet.TileShape
|
||||
var v: TileSet.TileShape
|
||||
v = TileSet.TILE_SHAPE_SQUARE
|
||||
v = print_enum(v)
|
||||
v = print_enum(TileSet.TILE_SHAPE_SQUARE)
|
||||
|
@ -7,9 +7,9 @@ class InnerClass:
|
||||
|
||||
static func test_inner_from_inner():
|
||||
print("Inner - Inner")
|
||||
var e1 : MyEnum
|
||||
var e2 : InnerClass.MyEnum
|
||||
var e3 : EnumTypecheckOuterClass.InnerClass.MyEnum
|
||||
var e1: MyEnum
|
||||
var e2: InnerClass.MyEnum
|
||||
var e3: EnumTypecheckOuterClass.InnerClass.MyEnum
|
||||
|
||||
print("Self ", e1, e2, e3)
|
||||
e1 = MyEnum.V1
|
||||
@ -36,7 +36,7 @@ class InnerClass:
|
||||
|
||||
static func test_outer_from_inner():
|
||||
print("Inner - Outer")
|
||||
var e : EnumTypecheckOuterClass.MyEnum
|
||||
var e: EnumTypecheckOuterClass.MyEnum
|
||||
|
||||
e = EnumTypecheckOuterClass.MyEnum.V1
|
||||
print("Outer.MyEnum ", e)
|
||||
@ -45,8 +45,8 @@ class InnerClass:
|
||||
|
||||
func test_outer_from_outer():
|
||||
print("Outer - Outer")
|
||||
var e1 : MyEnum
|
||||
var e2 : EnumTypecheckOuterClass.MyEnum
|
||||
var e1: MyEnum
|
||||
var e2: EnumTypecheckOuterClass.MyEnum
|
||||
|
||||
print("Self ", e1, e2)
|
||||
e1 = MyEnum.V1
|
||||
@ -63,8 +63,8 @@ func test_outer_from_outer():
|
||||
|
||||
func test_inner_from_outer():
|
||||
print("Outer - Inner")
|
||||
var e1 : InnerClass.MyEnum
|
||||
var e2 : EnumTypecheckOuterClass.InnerClass.MyEnum
|
||||
var e1: InnerClass.MyEnum
|
||||
var e2: EnumTypecheckOuterClass.InnerClass.MyEnum
|
||||
|
||||
print("Inner ", e1, e2)
|
||||
e1 = InnerClass.MyEnum.V1
|
||||
|
@ -1,4 +1,4 @@
|
||||
var Value:int = 8 :
|
||||
var Value:int = 8:
|
||||
get:
|
||||
return Value
|
||||
set(v):
|
||||
|
@ -6,21 +6,21 @@ var prop1:
|
||||
prop1 = value
|
||||
|
||||
# Typed inline property
|
||||
var prop2 : int:
|
||||
var prop2: int:
|
||||
get:
|
||||
return prop2
|
||||
set(value):
|
||||
prop2 = value
|
||||
|
||||
# Typed inline property with default value
|
||||
var prop3 : int = 1:
|
||||
var prop3: int = 1:
|
||||
get:
|
||||
return prop3
|
||||
set(value):
|
||||
prop3 = value
|
||||
|
||||
# Typed inline property with backing variable
|
||||
var _prop4 : int = 2
|
||||
var _prop4: int = 2
|
||||
var prop4: int:
|
||||
get:
|
||||
return _prop4
|
||||
|
@ -1,4 +1,4 @@
|
||||
const preloaded : GDScript = preload("gdscript_to_preload.notest.gd")
|
||||
const preloaded: GDScript = preload("gdscript_to_preload.notest.gd")
|
||||
|
||||
func test():
|
||||
var preloaded_instance: preloaded = preloaded.new()
|
||||
|
@ -1,3 +1,5 @@
|
||||
# Do not fix code style here!
|
||||
|
||||
func test():
|
||||
# The following lines are equivalent:
|
||||
var _integer: int = 1
|
||||
|
@ -1,21 +1,21 @@
|
||||
GDTEST_OK
|
||||
>> WARNING
|
||||
>> Line: 9
|
||||
>> UNUSED_LOCAL_CONSTANT
|
||||
>> The local constant '_INTEGER' is declared but never used in the block. If this is intended, prefix it with an underscore: '__INTEGER'
|
||||
>> WARNING
|
||||
>> Line: 10
|
||||
>> UNUSED_LOCAL_CONSTANT
|
||||
>> The local constant '_INTEGER_REDUNDANT_TYPED' is declared but never used in the block. If this is intended, prefix it with an underscore: '__INTEGER_REDUNDANT_TYPED'
|
||||
>> WARNING
|
||||
>> Line: 11
|
||||
>> UNUSED_LOCAL_CONSTANT
|
||||
>> The local constant '_INTEGER_REDUNDANT_TYPED2' is declared but never used in the block. If this is intended, prefix it with an underscore: '__INTEGER_REDUNDANT_TYPED2'
|
||||
>> The local constant '_INTEGER' is declared but never used in the block. If this is intended, prefix it with an underscore: '__INTEGER'
|
||||
>> WARNING
|
||||
>> Line: 12
|
||||
>> UNUSED_LOCAL_CONSTANT
|
||||
>> The local constant '_INTEGER_REDUNDANT_INFERRED' is declared but never used in the block. If this is intended, prefix it with an underscore: '__INTEGER_REDUNDANT_INFERRED'
|
||||
>> The local constant '_INTEGER_REDUNDANT_TYPED' is declared but never used in the block. If this is intended, prefix it with an underscore: '__INTEGER_REDUNDANT_TYPED'
|
||||
>> WARNING
|
||||
>> Line: 13
|
||||
>> UNUSED_LOCAL_CONSTANT
|
||||
>> The local constant '_INTEGER_REDUNDANT_TYPED2' is declared but never used in the block. If this is intended, prefix it with an underscore: '__INTEGER_REDUNDANT_TYPED2'
|
||||
>> WARNING
|
||||
>> Line: 14
|
||||
>> UNUSED_LOCAL_CONSTANT
|
||||
>> The local constant '_INTEGER_REDUNDANT_INFERRED' is declared but never used in the block. If this is intended, prefix it with an underscore: '__INTEGER_REDUNDANT_INFERRED'
|
||||
>> WARNING
|
||||
>> Line: 15
|
||||
>> UNUSED_LOCAL_CONSTANT
|
||||
>> The local constant '_INTEGER_REDUNDANT_INFERRED2' is declared but never used in the block. If this is intended, prefix it with an underscore: '__INTEGER_REDUNDANT_INFERRED2'
|
||||
|
@ -1,8 +1,8 @@
|
||||
extends Node
|
||||
|
||||
@onready var later_inferred := [1]
|
||||
@onready var later_static : Array
|
||||
@onready var later_static_with_init : Array = [1]
|
||||
@onready var later_static: Array
|
||||
@onready var later_static_with_init: Array = [1]
|
||||
@onready var later_untyped = [1]
|
||||
|
||||
func test():
|
||||
|
@ -1,5 +1,5 @@
|
||||
#GDTEST_OK
|
||||
var prop : int = 0:
|
||||
var prop: int = 0:
|
||||
get:
|
||||
return prop
|
||||
set(value):
|
||||
|
@ -4,6 +4,6 @@ func test():
|
||||
@warning_ignore("narrowing_conversion")
|
||||
var foo: int = 0.0
|
||||
print(typeof(foo) == TYPE_INT)
|
||||
var dict : Dictionary = {"a":0.0}
|
||||
var dict: Dictionary = {"a": 0.0}
|
||||
foo = dict.get("a")
|
||||
print(typeof(foo) == TYPE_INT)
|
||||
|
@ -5,6 +5,7 @@
|
||||
</brief_description>
|
||||
<description>
|
||||
Represents a GLTF node. GLTF nodes may have names, transforms, children (other GLTF nodes), and more specialized properties (represented by their own classes).
|
||||
GLTF nodes generally exist inside of [GLTFState] which represents all data of a GLTF file. Most of GLTFNode's properties are indices of other data in the GLTF file. You can extend a GLTF node with additional properties by using [method get_additional_data] and [method set_additional_data].
|
||||
</description>
|
||||
<tutorials>
|
||||
<link title="GLTF scene and node spec">https://github.com/KhronosGroup/glTF-Tutorials/blob/master/gltfTutorial/gltfTutorial_004_ScenesNodes.md"</link>
|
||||
@ -30,28 +31,40 @@
|
||||
</methods>
|
||||
<members>
|
||||
<member name="camera" type="int" setter="set_camera" getter="get_camera" default="-1">
|
||||
If this GLTF node is a camera, the index of the [GLTFCamera] in the [GLTFState] that describes the camera's properties. If -1, this node is not a camera.
|
||||
</member>
|
||||
<member name="children" type="PackedInt32Array" setter="set_children" getter="get_children" default="PackedInt32Array()">
|
||||
The indices of the children nodes in the [GLTFState]. If this GLTF node has no children, this will be an empty array.
|
||||
</member>
|
||||
<member name="height" type="int" setter="set_height" getter="get_height" default="-1">
|
||||
How deep into the node hierarchy this node is. A root node will have a height of 0, its children will have a height of 1, and so on. If -1, the height has not been calculated.
|
||||
</member>
|
||||
<member name="light" type="int" setter="set_light" getter="get_light" default="-1">
|
||||
If this GLTF node is a light, the index of the [GLTFLight] in the [GLTFState] that describes the light's properties. If -1, this node is not a light.
|
||||
</member>
|
||||
<member name="mesh" type="int" setter="set_mesh" getter="get_mesh" default="-1">
|
||||
If this GLTF node is a mesh, the index of the [GLTFMesh] in the [GLTFState] that describes the mesh's properties. If -1, this node is not a mesh.
|
||||
</member>
|
||||
<member name="parent" type="int" setter="set_parent" getter="get_parent" default="-1">
|
||||
The index of the parent node in the [GLTFState]. If -1, this node is a root node.
|
||||
</member>
|
||||
<member name="position" type="Vector3" setter="set_position" getter="get_position" default="Vector3(0, 0, 0)">
|
||||
The position of the GLTF node relative to its parent.
|
||||
</member>
|
||||
<member name="rotation" type="Quaternion" setter="set_rotation" getter="get_rotation" default="Quaternion(0, 0, 0, 1)">
|
||||
The rotation of the GLTF node relative to its parent.
|
||||
</member>
|
||||
<member name="scale" type="Vector3" setter="set_scale" getter="get_scale" default="Vector3(1, 1, 1)">
|
||||
The scale of the GLTF node relative to its parent.
|
||||
</member>
|
||||
<member name="skeleton" type="int" setter="set_skeleton" getter="get_skeleton" default="-1">
|
||||
If this GLTF node has a skeleton, the index of the [GLTFSkeleton] in the [GLTFState] that describes the skeleton's properties. If -1, this node does not have a skeleton.
|
||||
</member>
|
||||
<member name="skin" type="int" setter="set_skin" getter="get_skin" default="-1">
|
||||
If this GLTF node has a skin, the index of the [GLTFSkin] in the [GLTFState] that describes the skin's properties. If -1, this node does not have a skin.
|
||||
</member>
|
||||
<member name="xform" type="Transform3D" setter="set_xform" getter="get_xform" default="Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0)">
|
||||
The transform of the GLTF node relative to its parent. This property is usually unused since the position, rotation, and scale properties are preferred.
|
||||
</member>
|
||||
</members>
|
||||
</class>
|
||||
|
@ -1,8 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<class name="GLTFState" inherits="Resource" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd">
|
||||
<brief_description>
|
||||
Represents all data of a GLTF file.
|
||||
</brief_description>
|
||||
<description>
|
||||
Contains all nodes and resources of a GLTF file. This is used by [GLTFDocument] as data storage, which allows [GLTFDocument] and all [GLTFDocumentExtension] classes to remain stateless.
|
||||
GLTFState can be populated by [GLTFDocument] reading a file or by converting a Godot scene. Then the data can either be used to create a Godot scene or save to a GLTF file. The code that converts to/from a Godot scene can be intercepted at arbitrary points by [GLTFDocumentExtension] classes. This allows for custom data to be stored in the GLTF file or for custom data to be converted to/from Godot nodes.
|
||||
</description>
|
||||
<tutorials>
|
||||
</tutorials>
|
||||
@ -32,17 +35,20 @@
|
||||
<return type="AnimationPlayer" />
|
||||
<param index="0" name="idx" type="int" />
|
||||
<description>
|
||||
Returns the [AnimationPlayer] node with the given index. These nodes are only used during the export process when converting Godot [AnimationPlayer] nodes to GLTF animations.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_animation_players_count">
|
||||
<return type="int" />
|
||||
<param index="0" name="idx" type="int" />
|
||||
<description>
|
||||
Returns the number of [AnimationPlayer] nodes in this [GLTFState]. These nodes are only used during the export process when converting Godot [AnimationPlayer] nodes to GLTF animations.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_animations">
|
||||
<return type="GLTFAnimation[]" />
|
||||
<description>
|
||||
Returns an array of all [GLTFAnimation]s in the GLTF file. When importing, these will be generated as animations in an [AnimationPlayer] node. When exporting, these will be generated from Godot [AnimationPlayer] nodes.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_buffer_views">
|
||||
@ -53,6 +59,7 @@
|
||||
<method name="get_cameras">
|
||||
<return type="GLTFCamera[]" />
|
||||
<description>
|
||||
Returns an array of all [GLTFCamera]s in the GLTF file. These are the cameras that the [member GLTFNode.camera] index refers to.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_handle_binary_image">
|
||||
@ -68,6 +75,7 @@
|
||||
<method name="get_lights">
|
||||
<return type="GLTFLight[]" />
|
||||
<description>
|
||||
Returns an array of all [GLTFLight]s in the GLTF file. These are the lights that the [member GLTFNode.light] index refers to.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_materials">
|
||||
@ -78,27 +86,32 @@
|
||||
<method name="get_meshes">
|
||||
<return type="GLTFMesh[]" />
|
||||
<description>
|
||||
Returns an array of all [GLTFMesh]es in the GLTF file. These are the meshes that the [member GLTFNode.mesh] index refers to.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_nodes">
|
||||
<return type="GLTFNode[]" />
|
||||
<description>
|
||||
Returns an array of all [GLTFNode]s in the GLTF file. These are the nodes that [member GLTFNode.children] and [member root_nodes] refer to. This includes nodes that may not be generated in the Godot scene, or nodes that may generate multiple Godot scene nodes.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_scene_node">
|
||||
<return type="Node" />
|
||||
<param index="0" name="idx" type="int" />
|
||||
<description>
|
||||
Returns the Godot scene node that corresponds to the same index as the [GLTFNode] it was generated from. Not every [GLTFNode] will have a scene node generated, and not every generated scene node will have a corresponding [GLTFNode].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_skeletons">
|
||||
<return type="GLTFSkeleton[]" />
|
||||
<description>
|
||||
Returns an array of all [GLTFSkeleton]s in the GLTF file. These are the skeletons that the [member GLTFNode.skeleton] index refers to.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_skins">
|
||||
<return type="GLTFSkin[]" />
|
||||
<description>
|
||||
Returns an array of all [GLTFSkin]s in the GLTF file. These are the skins that the [member GLTFNode.skin] index refers to.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_texture_samplers">
|
||||
@ -115,11 +128,13 @@
|
||||
<method name="get_unique_animation_names">
|
||||
<return type="String[]" />
|
||||
<description>
|
||||
Returns an array of unique animation names. This is only used during the import process.
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_unique_names">
|
||||
<return type="String[]" />
|
||||
<description>
|
||||
Returns an array of unique node names. This is used in both the import process and export process.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_accessors">
|
||||
@ -141,6 +156,7 @@
|
||||
<return type="void" />
|
||||
<param index="0" name="animations" type="GLTFAnimation[]" />
|
||||
<description>
|
||||
Sets the [GLTFAnimation]s in the state. When importing, these will be generated as animations in an [AnimationPlayer] node. When exporting, these will be generated from Godot [AnimationPlayer] nodes.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_buffer_views">
|
||||
@ -153,6 +169,7 @@
|
||||
<return type="void" />
|
||||
<param index="0" name="cameras" type="GLTFCamera[]" />
|
||||
<description>
|
||||
Sets the [GLTFCamera]s in the state. These are the cameras that the [member GLTFNode.camera] index refers to.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_handle_binary_image">
|
||||
@ -171,6 +188,7 @@
|
||||
<return type="void" />
|
||||
<param index="0" name="lights" type="GLTFLight[]" />
|
||||
<description>
|
||||
Sets the [GLTFLight]s in the state. These are the lights that the [member GLTFNode.light] index refers to.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_materials">
|
||||
@ -183,24 +201,28 @@
|
||||
<return type="void" />
|
||||
<param index="0" name="meshes" type="GLTFMesh[]" />
|
||||
<description>
|
||||
Sets the [GLTFMesh]es in the state. These are the meshes that the [member GLTFNode.mesh] index refers to.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_nodes">
|
||||
<return type="void" />
|
||||
<param index="0" name="nodes" type="GLTFNode[]" />
|
||||
<description>
|
||||
Sets the [GLTFNode]s in the state. These are the nodes that [member GLTFNode.children] and [member root_nodes] refer to. Some of the nodes set here may not be generated in the Godot scene, or may generate multiple Godot scene nodes.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_skeletons">
|
||||
<return type="void" />
|
||||
<param index="0" name="skeletons" type="GLTFSkeleton[]" />
|
||||
<description>
|
||||
Sets the [GLTFSkeleton]s in the state. These are the skeletons that the [member GLTFNode.skeleton] index refers to.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_skins">
|
||||
<return type="void" />
|
||||
<param index="0" name="skins" type="GLTFSkin[]" />
|
||||
<description>
|
||||
Sets the [GLTFSkin]s in the state. These are the skins that the [member GLTFNode.skin] index refers to.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_texture_samplers">
|
||||
@ -220,12 +242,14 @@
|
||||
<return type="void" />
|
||||
<param index="0" name="unique_animation_names" type="String[]" />
|
||||
<description>
|
||||
Sets the unique animation names in the state. This is only used during the import process.
|
||||
</description>
|
||||
</method>
|
||||
<method name="set_unique_names">
|
||||
<return type="void" />
|
||||
<param index="0" name="unique_names" type="String[]" />
|
||||
<description>
|
||||
Sets the unique node names in the state. This is used in both the import process and export process.
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
@ -245,8 +269,10 @@
|
||||
<member name="minor_version" type="int" setter="set_minor_version" getter="get_minor_version" default="0">
|
||||
</member>
|
||||
<member name="root_nodes" type="PackedInt32Array" setter="set_root_nodes" getter="get_root_nodes" default="PackedInt32Array()">
|
||||
The root nodes of the GLTF file. Typically, a GLTF file will only have one scene, and therefore one root node. However, a GLTF file may have multiple scenes and therefore multiple root nodes, which will be generated as siblings of each other and as children of the root node of the generated Godot scene.
|
||||
</member>
|
||||
<member name="scene_name" type="String" setter="set_scene_name" getter="get_scene_name" default="""">
|
||||
The name of the scene. When importing, if not specified, this will be the file name. When exporting, if specified, the scene name will be saved to the GLTF file.
|
||||
</member>
|
||||
<member name="use_named_skin_binds" type="bool" setter="set_use_named_skin_binds" getter="get_use_named_skin_binds" default="false">
|
||||
</member>
|
||||
|
@ -70,7 +70,7 @@ Error GLTFDocumentExtensionConvertImporterMesh::import_post(Ref<GLTFState> p_sta
|
||||
}
|
||||
queue.pop_front();
|
||||
}
|
||||
while (!queue.is_empty()) {
|
||||
while (!delete_queue.is_empty()) {
|
||||
List<Node *>::Element *E = delete_queue.front();
|
||||
Node *node = E->get();
|
||||
memdelete(node);
|
||||
|
@ -42,7 +42,6 @@
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
#include "core/os/keyboard.h"
|
||||
#include "editor/bindings_generator.h"
|
||||
#include "editor/editor_internal_calls.h"
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_settings.h"
|
||||
@ -102,13 +101,6 @@ void CSharpLanguage::init() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED)
|
||||
// Generate the bindings here, before loading assemblies. The Godot assemblies
|
||||
// may be missing if the glue wasn't generated yet in order to build them.
|
||||
List<String> cmdline_args = OS::get_singleton()->get_cmdline_args();
|
||||
BindingsGenerator::handle_cmdline_args(cmdline_args);
|
||||
#endif
|
||||
|
||||
GLOBAL_DEF("dotnet/project/assembly_name", "");
|
||||
#ifdef TOOLS_ENABLED
|
||||
GLOBAL_DEF("dotnet/project/solution_directory", "");
|
||||
@ -589,7 +581,7 @@ Vector<ScriptLanguage::StackInfo> CSharpLanguage::debug_get_current_stack_info()
|
||||
_recursion_flag_ = false;
|
||||
};
|
||||
|
||||
if (!gdmono->is_runtime_initialized()) {
|
||||
if (!gdmono || !gdmono->is_runtime_initialized()) {
|
||||
return Vector<StackInfo>();
|
||||
}
|
||||
|
||||
@ -679,6 +671,7 @@ void CSharpLanguage::reload_tool_script(const Ref<Script> &p_script, bool p_soft
|
||||
|
||||
#ifdef GD_MONO_HOT_RELOAD
|
||||
bool CSharpLanguage::is_assembly_reloading_needed() {
|
||||
ERR_FAIL_NULL_V(gdmono, false);
|
||||
if (!gdmono->is_runtime_initialized()) {
|
||||
return false;
|
||||
}
|
||||
@ -713,6 +706,7 @@ bool CSharpLanguage::is_assembly_reloading_needed() {
|
||||
}
|
||||
|
||||
void CSharpLanguage::reload_assemblies(bool p_soft_reload) {
|
||||
ERR_FAIL_NULL(gdmono);
|
||||
if (!gdmono->is_runtime_initialized()) {
|
||||
return;
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ namespace GodotTools
|
||||
private PopupMenu _menuPopup;
|
||||
|
||||
private AcceptDialog _errorDialog;
|
||||
private ConfirmationDialog _confirmCreateSlnDialog;
|
||||
|
||||
private Button _bottomPanelBtn;
|
||||
private Button _toolBarBuildButton;
|
||||
@ -99,7 +100,7 @@ namespace GodotTools
|
||||
pr.Step("Done".TTR());
|
||||
|
||||
// Here, after all calls to progress_task_step
|
||||
CallDeferred(nameof(_RemoveCreateSlnMenuOption));
|
||||
CallDeferred(nameof(_ShowDotnetFeatures));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -110,9 +111,8 @@ namespace GodotTools
|
||||
}
|
||||
}
|
||||
|
||||
private void _RemoveCreateSlnMenuOption()
|
||||
private void _ShowDotnetFeatures()
|
||||
{
|
||||
_menuPopup.RemoveItem(_menuPopup.GetItemIndex((int)MenuOptions.CreateSln));
|
||||
_bottomPanelBtn.Show();
|
||||
_toolBarBuildButton.Show();
|
||||
}
|
||||
@ -122,8 +122,17 @@ namespace GodotTools
|
||||
switch ((MenuOptions)id)
|
||||
{
|
||||
case MenuOptions.CreateSln:
|
||||
CreateProjectSolution();
|
||||
{
|
||||
if (File.Exists(GodotSharpDirs.ProjectSlnPath) || File.Exists(GodotSharpDirs.ProjectCsProjPath))
|
||||
{
|
||||
ShowConfirmCreateSlnDialog();
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateProjectSolution();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MenuOptions.SetupGodotNugetFallbackFolder:
|
||||
{
|
||||
try
|
||||
@ -169,6 +178,13 @@ namespace GodotTools
|
||||
_errorDialog.PopupCentered();
|
||||
}
|
||||
|
||||
public void ShowConfirmCreateSlnDialog()
|
||||
{
|
||||
_confirmCreateSlnDialog.Title = "C# solution already exists. This will override the existing C# project file, any manual changes will be lost.".TTR();
|
||||
_confirmCreateSlnDialog.DialogText = "Create C# solution".TTR();
|
||||
_confirmCreateSlnDialog.PopupCentered();
|
||||
}
|
||||
|
||||
private static string _vsCodePath = string.Empty;
|
||||
|
||||
private static readonly string[] VsCodeNames =
|
||||
@ -420,6 +436,10 @@ namespace GodotTools
|
||||
_errorDialog = new AcceptDialog();
|
||||
editorBaseControl.AddChild(_errorDialog);
|
||||
|
||||
_confirmCreateSlnDialog = new ConfirmationDialog();
|
||||
_confirmCreateSlnDialog.Confirmed += () => CreateProjectSolution();
|
||||
editorBaseControl.AddChild(_confirmCreateSlnDialog);
|
||||
|
||||
MSBuildPanel = new MSBuildPanel();
|
||||
MSBuildPanel.Ready += () =>
|
||||
MSBuildPanel.BuildOutputView.BuildStateChanged += BuildStateChanged;
|
||||
@ -453,8 +473,8 @@ namespace GodotTools
|
||||
{
|
||||
_bottomPanelBtn.Hide();
|
||||
_toolBarBuildButton.Hide();
|
||||
_menuPopup.AddItem("Create C# solution".TTR(), (int)MenuOptions.CreateSln);
|
||||
}
|
||||
_menuPopup.AddItem("Create C# solution".TTR(), (int)MenuOptions.CreateSln);
|
||||
|
||||
_menuPopup.IdPressed += _MenuOptionPressed;
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
This action provides a float value between [code]0.0[/code] and [code]1.0[/code] for any analog input such as triggers.
|
||||
</constant>
|
||||
<constant name="OPENXR_ACTION_VECTOR2" value="2" enum="ActionType">
|
||||
This action provides a vector2 value and can be bound to embedded trackpads and joysticks
|
||||
This action provides a [Vector2] value and can be bound to embedded trackpads and joysticks.
|
||||
</constant>
|
||||
<constant name="OPENXR_ACTION_POSE" value="3" enum="ActionType">
|
||||
</constant>
|
||||
|
@ -334,6 +334,8 @@ _FORCE_INLINE_ bool is_connected_to_prev(char32_t p_chr, char32_t p_pchr) {
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
bool TextServerAdvanced::icu_data_loaded = false;
|
||||
|
||||
bool TextServerAdvanced::_has_feature(Feature p_feature) const {
|
||||
switch (p_feature) {
|
||||
case FEATURE_SIMPLE_LAYOUT:
|
||||
@ -1384,7 +1386,9 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_cache_for_size(FontAdvanced *p_f
|
||||
FT_Select_Size(fd->face, best_match);
|
||||
} else {
|
||||
FT_Set_Pixel_Sizes(fd->face, 0, double(fd->size.x * fd->oversampling));
|
||||
fd->scale = ((double)fd->size.x * fd->oversampling) / (double)fd->face->size->metrics.y_ppem;
|
||||
if (fd->face->size->metrics.y_ppem != 0) {
|
||||
fd->scale = ((double)fd->size.x * fd->oversampling) / (double)fd->face->size->metrics.y_ppem;
|
||||
}
|
||||
}
|
||||
|
||||
fd->hb_handle = hb_ft_font_create(fd->face, nullptr);
|
||||
@ -6599,5 +6603,6 @@ TextServerAdvanced::~TextServerAdvanced() {
|
||||
uset_close(allowed);
|
||||
allowed = nullptr;
|
||||
}
|
||||
u_cleanup();
|
||||
|
||||
std::atexit(u_cleanup);
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ class TextServerAdvanced : public TextServerExtension {
|
||||
|
||||
// ICU support data.
|
||||
|
||||
bool icu_data_loaded = false;
|
||||
static bool icu_data_loaded;
|
||||
mutable USet *allowed = nullptr;
|
||||
mutable USpoofChecker *sc_spoof = nullptr;
|
||||
mutable USpoofChecker *sc_conf = nullptr;
|
||||
|
@ -825,7 +825,9 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_cache_for_size(FontFallback *p_f
|
||||
FT_Select_Size(fd->face, best_match);
|
||||
} else {
|
||||
FT_Set_Pixel_Sizes(fd->face, 0, Math::round(fd->size.x * fd->oversampling));
|
||||
fd->scale = ((double)fd->size.x * fd->oversampling) / (double)fd->face->size->metrics.y_ppem;
|
||||
if (fd->face->size->metrics.y_ppem != 0) {
|
||||
fd->scale = ((double)fd->size.x * fd->oversampling) / (double)fd->face->size->metrics.y_ppem;
|
||||
}
|
||||
}
|
||||
|
||||
fd->ascent = (fd->face->size->metrics.ascender / 64.0) / fd->oversampling * fd->scale;
|
||||
|
@ -676,16 +676,19 @@ void DisplayServerAndroid::cursor_set_custom_image(const Ref<Resource> &p_cursor
|
||||
|
||||
void DisplayServerAndroid::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
|
||||
#if defined(VULKAN_ENABLED)
|
||||
context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
|
||||
if (context_vulkan) {
|
||||
context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
DisplayServer::VSyncMode DisplayServerAndroid::window_get_vsync_mode(WindowID p_window) const {
|
||||
#if defined(VULKAN_ENABLED)
|
||||
return context_vulkan->get_vsync_mode(p_window);
|
||||
#else
|
||||
return DisplayServer::VSYNC_ENABLED;
|
||||
if (context_vulkan) {
|
||||
return context_vulkan->get_vsync_mode(p_window);
|
||||
}
|
||||
#endif
|
||||
return DisplayServer::VSYNC_ENABLED;
|
||||
}
|
||||
|
||||
void DisplayServerAndroid::reset_swap_buffers_flag() {
|
||||
|
@ -677,40 +677,45 @@ Vector<String> OS_LinuxBSD::get_system_font_path_for_text(const String &p_font_n
|
||||
}
|
||||
|
||||
Vector<String> ret;
|
||||
FcPattern *pattern = FcPatternCreate();
|
||||
if (pattern) {
|
||||
FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8 *>(p_font_name.utf8().get_data()));
|
||||
FcPatternAddInteger(pattern, FC_WEIGHT, _weight_to_fc(p_weight));
|
||||
FcPatternAddInteger(pattern, FC_WIDTH, _stretch_to_fc(p_stretch));
|
||||
FcPatternAddInteger(pattern, FC_SLANT, p_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN);
|
||||
static const char *allowed_formats[] = { "TrueType", "CFF" };
|
||||
for (size_t i = 0; i < sizeof(allowed_formats) / sizeof(const char *); i++) {
|
||||
FcPattern *pattern = FcPatternCreate();
|
||||
if (pattern) {
|
||||
FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
|
||||
FcPatternAddString(pattern, FC_FONTFORMAT, reinterpret_cast<const FcChar8 *>(allowed_formats[i]));
|
||||
FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8 *>(p_font_name.utf8().get_data()));
|
||||
FcPatternAddInteger(pattern, FC_WEIGHT, _weight_to_fc(p_weight));
|
||||
FcPatternAddInteger(pattern, FC_WIDTH, _stretch_to_fc(p_stretch));
|
||||
FcPatternAddInteger(pattern, FC_SLANT, p_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN);
|
||||
|
||||
FcCharSet *char_set = FcCharSetCreate();
|
||||
for (int i = 0; i < p_text.size(); i++) {
|
||||
FcCharSetAddChar(char_set, p_text[i]);
|
||||
}
|
||||
FcPatternAddCharSet(pattern, FC_CHARSET, char_set);
|
||||
|
||||
FcLangSet *lang_set = FcLangSetCreate();
|
||||
FcLangSetAdd(lang_set, reinterpret_cast<const FcChar8 *>(p_locale.utf8().get_data()));
|
||||
FcPatternAddLangSet(pattern, FC_LANG, lang_set);
|
||||
|
||||
FcConfigSubstitute(0, pattern, FcMatchPattern);
|
||||
FcDefaultSubstitute(pattern);
|
||||
|
||||
FcResult result;
|
||||
FcPattern *match = FcFontMatch(0, pattern, &result);
|
||||
if (match) {
|
||||
char *file_name = nullptr;
|
||||
if (FcPatternGetString(match, FC_FILE, 0, reinterpret_cast<FcChar8 **>(&file_name)) == FcResultMatch) {
|
||||
if (file_name) {
|
||||
ret.push_back(String::utf8(file_name));
|
||||
}
|
||||
FcCharSet *char_set = FcCharSetCreate();
|
||||
for (int j = 0; j < p_text.size(); j++) {
|
||||
FcCharSetAddChar(char_set, p_text[j]);
|
||||
}
|
||||
FcPatternDestroy(match);
|
||||
FcPatternAddCharSet(pattern, FC_CHARSET, char_set);
|
||||
|
||||
FcLangSet *lang_set = FcLangSetCreate();
|
||||
FcLangSetAdd(lang_set, reinterpret_cast<const FcChar8 *>(p_locale.utf8().get_data()));
|
||||
FcPatternAddLangSet(pattern, FC_LANG, lang_set);
|
||||
|
||||
FcConfigSubstitute(0, pattern, FcMatchPattern);
|
||||
FcDefaultSubstitute(pattern);
|
||||
|
||||
FcResult result;
|
||||
FcPattern *match = FcFontMatch(0, pattern, &result);
|
||||
if (match) {
|
||||
char *file_name = nullptr;
|
||||
if (FcPatternGetString(match, FC_FILE, 0, reinterpret_cast<FcChar8 **>(&file_name)) == FcResultMatch) {
|
||||
if (file_name) {
|
||||
ret.push_back(String::utf8(file_name));
|
||||
}
|
||||
}
|
||||
FcPatternDestroy(match);
|
||||
}
|
||||
FcPatternDestroy(pattern);
|
||||
FcCharSetDestroy(char_set);
|
||||
FcLangSetDestroy(lang_set);
|
||||
}
|
||||
FcPatternDestroy(pattern);
|
||||
FcCharSetDestroy(char_set);
|
||||
FcLangSetDestroy(lang_set);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -725,47 +730,51 @@ String OS_LinuxBSD::get_system_font_path(const String &p_font_name, int p_weight
|
||||
ERR_FAIL_V_MSG(String(), "Unable to load fontconfig, system font support is disabled.");
|
||||
}
|
||||
|
||||
String ret;
|
||||
FcPattern *pattern = FcPatternCreate();
|
||||
if (pattern) {
|
||||
bool allow_substitutes = (p_font_name.to_lower() == "sans-serif") || (p_font_name.to_lower() == "serif") || (p_font_name.to_lower() == "monospace") || (p_font_name.to_lower() == "cursive") || (p_font_name.to_lower() == "fantasy");
|
||||
static const char *allowed_formats[] = { "TrueType", "CFF" };
|
||||
for (size_t i = 0; i < sizeof(allowed_formats) / sizeof(const char *); i++) {
|
||||
FcPattern *pattern = FcPatternCreate();
|
||||
if (pattern) {
|
||||
bool allow_substitutes = (p_font_name.to_lower() == "sans-serif") || (p_font_name.to_lower() == "serif") || (p_font_name.to_lower() == "monospace") || (p_font_name.to_lower() == "cursive") || (p_font_name.to_lower() == "fantasy");
|
||||
|
||||
FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
|
||||
FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8 *>(p_font_name.utf8().get_data()));
|
||||
FcPatternAddInteger(pattern, FC_WEIGHT, _weight_to_fc(p_weight));
|
||||
FcPatternAddInteger(pattern, FC_WIDTH, _stretch_to_fc(p_stretch));
|
||||
FcPatternAddInteger(pattern, FC_SLANT, p_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN);
|
||||
FcPatternAddBool(pattern, FC_SCALABLE, FcTrue);
|
||||
FcPatternAddString(pattern, FC_FONTFORMAT, reinterpret_cast<const FcChar8 *>(allowed_formats[i]));
|
||||
FcPatternAddString(pattern, FC_FAMILY, reinterpret_cast<const FcChar8 *>(p_font_name.utf8().get_data()));
|
||||
FcPatternAddInteger(pattern, FC_WEIGHT, _weight_to_fc(p_weight));
|
||||
FcPatternAddInteger(pattern, FC_WIDTH, _stretch_to_fc(p_stretch));
|
||||
FcPatternAddInteger(pattern, FC_SLANT, p_italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN);
|
||||
|
||||
FcConfigSubstitute(0, pattern, FcMatchPattern);
|
||||
FcDefaultSubstitute(pattern);
|
||||
FcConfigSubstitute(0, pattern, FcMatchPattern);
|
||||
FcDefaultSubstitute(pattern);
|
||||
|
||||
FcResult result;
|
||||
FcPattern *match = FcFontMatch(0, pattern, &result);
|
||||
if (match) {
|
||||
if (!allow_substitutes) {
|
||||
char *family_name = nullptr;
|
||||
if (FcPatternGetString(match, FC_FAMILY, 0, reinterpret_cast<FcChar8 **>(&family_name)) == FcResultMatch) {
|
||||
if (family_name && String::utf8(family_name).to_lower() != p_font_name.to_lower()) {
|
||||
FcPatternDestroy(match);
|
||||
FcPatternDestroy(pattern);
|
||||
|
||||
return String();
|
||||
FcResult result;
|
||||
FcPattern *match = FcFontMatch(0, pattern, &result);
|
||||
if (match) {
|
||||
if (!allow_substitutes) {
|
||||
char *family_name = nullptr;
|
||||
if (FcPatternGetString(match, FC_FAMILY, 0, reinterpret_cast<FcChar8 **>(&family_name)) == FcResultMatch) {
|
||||
if (family_name && String::utf8(family_name).to_lower() != p_font_name.to_lower()) {
|
||||
FcPatternDestroy(match);
|
||||
FcPatternDestroy(pattern);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
char *file_name = nullptr;
|
||||
if (FcPatternGetString(match, FC_FILE, 0, reinterpret_cast<FcChar8 **>(&file_name)) == FcResultMatch) {
|
||||
if (file_name) {
|
||||
ret = String::utf8(file_name);
|
||||
char *file_name = nullptr;
|
||||
if (FcPatternGetString(match, FC_FILE, 0, reinterpret_cast<FcChar8 **>(&file_name)) == FcResultMatch) {
|
||||
if (file_name) {
|
||||
String ret = String::utf8(file_name);
|
||||
FcPatternDestroy(match);
|
||||
FcPatternDestroy(pattern);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
FcPatternDestroy(match);
|
||||
}
|
||||
|
||||
FcPatternDestroy(match);
|
||||
FcPatternDestroy(pattern);
|
||||
}
|
||||
FcPatternDestroy(pattern);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return String();
|
||||
#else
|
||||
ERR_FAIL_V_MSG(String(), "Godot was compiled without fontconfig, system font support is disabled.");
|
||||
#endif
|
||||
|
@ -5258,6 +5258,9 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
|
||||
}
|
||||
#ifdef XKB_ENABLED
|
||||
xkb_loaded = (initialize_xkbcommon(dylibloader_verbose) == 0);
|
||||
if (!xkb_context_new || !xkb_compose_table_new_from_locale || !xkb_compose_table_unref || !xkb_context_unref || !xkb_compose_state_feed || !xkb_compose_state_unref || !xkb_compose_state_new || !xkb_compose_state_get_status || !xkb_compose_state_get_utf8 || !xkb_keysym_to_utf32 || !xkb_keysym_to_upper) {
|
||||
xkb_loaded = false;
|
||||
}
|
||||
#endif
|
||||
if (initialize_xext(dylibloader_verbose) != 0) {
|
||||
r_error = ERR_UNAVAILABLE;
|
||||
|
@ -2375,7 +2375,7 @@ int RichTextLabel::_find_list(Item *p_item, Vector<int> &r_index, Vector<ItemLis
|
||||
|
||||
int index = 1;
|
||||
if (frame != nullptr) {
|
||||
for (int i = list->line + 1; i <= prev_item->line; i++) {
|
||||
for (int i = list->line + 1; i <= prev_item->line && i < (int)frame->lines.size(); i++) {
|
||||
if (_find_list_item(frame->lines[i].from) == list) {
|
||||
index++;
|
||||
}
|
||||
|
@ -1365,8 +1365,11 @@ void Window::_window_input(const Ref<InputEvent> &p_ev) {
|
||||
|
||||
emit_signal(SceneStringNames::get_singleton()->window_input, p_ev);
|
||||
|
||||
push_input(p_ev);
|
||||
if (!is_input_handled()) {
|
||||
if (is_inside_tree()) {
|
||||
push_input(p_ev);
|
||||
}
|
||||
|
||||
if (!is_input_handled() && is_inside_tree()) {
|
||||
push_unhandled_input(p_ev);
|
||||
}
|
||||
}
|
||||
|
@ -86,6 +86,10 @@ static Ref<ImageTexture> generate_icon(int p_index) {
|
||||
ImageLoaderSVG img_loader;
|
||||
Error err = img_loader.create_image_from_string(img, default_theme_icons_sources[p_index], scale, upsample, HashMap<Color, Color>());
|
||||
ERR_FAIL_COND_V_MSG(err != OK, Ref<ImageTexture>(), "Failed generating icon, unsupported or invalid SVG data in default theme.");
|
||||
#else
|
||||
// If the SVG module is disabled, we can't really display the UI well, but at least we won't crash.
|
||||
// 16 pixels is used as it's the most common base size for Godot icons.
|
||||
img = Image::create_empty(16 * scale, 16 * scale, false, Image::FORMAT_RGBA8);
|
||||
#endif
|
||||
|
||||
return ImageTexture::create_from_image(img);
|
||||
@ -720,7 +724,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
|
||||
theme->set_constant("title_offset", "GraphNode", 26 * scale);
|
||||
theme->set_constant("title_h_offset", "GraphNode", 0);
|
||||
theme->set_constant("close_offset", "GraphNode", 22 * scale);
|
||||
theme->set_constant("close_h_offset", "GraphNode", 22 * scale);
|
||||
theme->set_constant("close_h_offset", "GraphNode", 12 * scale);
|
||||
theme->set_constant("port_offset", "GraphNode", 0);
|
||||
|
||||
// Tree
|
||||
|
@ -1193,6 +1193,9 @@ void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) {
|
||||
prev_tex->proxies.erase(p_texture);
|
||||
}
|
||||
|
||||
// Copy canvas_texture so it doesn't leak.
|
||||
CanvasTexture *canvas_texture = tex->canvas_texture;
|
||||
|
||||
*tex = *proxy_to;
|
||||
|
||||
tex->proxy_to = p_proxy_to;
|
||||
@ -1200,6 +1203,7 @@ void TextureStorage::texture_proxy_update(RID p_texture, RID p_proxy_to) {
|
||||
tex->is_proxy = true;
|
||||
tex->proxies.clear();
|
||||
proxy_to->proxies.push_back(p_texture);
|
||||
tex->canvas_texture = canvas_texture;
|
||||
|
||||
tex->rd_view.format_override = tex->rd_format;
|
||||
tex->rd_texture = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture);
|
||||
|
Loading…
Reference in New Issue
Block a user