Merge pull request #49679 from akien-mga/3.x-cherrypicks

This commit is contained in:
Rémi Verschelde 2021-06-17 13:25:41 +02:00 committed by GitHub
commit 2f08881347
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 758 additions and 665 deletions

View File

@ -55,7 +55,7 @@ static String _make_indent(const String &p_indent, int p_size) {
return indent_text;
}
String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys) {
String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys, Set<const void *> &p_markers) {
String colon = ":";
String end_statement = "";
@ -80,20 +80,29 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_
String s = "[";
s += end_statement;
Array a = p_var;
ERR_FAIL_COND_V_MSG(p_markers.has(a.id()), "\"[...]\"", "Converting circular structure to JSON.");
p_markers.insert(a.id());
for (int i = 0; i < a.size(); i++) {
if (i > 0) {
s += ",";
s += end_statement;
}
s += _make_indent(p_indent, p_cur_indent + 1) + _print_var(a[i], p_indent, p_cur_indent + 1, p_sort_keys);
s += _make_indent(p_indent, p_cur_indent + 1) + _print_var(a[i], p_indent, p_cur_indent + 1, p_sort_keys, p_markers);
}
s += end_statement + _make_indent(p_indent, p_cur_indent) + "]";
p_markers.erase(a.id());
return s;
};
case Variant::DICTIONARY: {
String s = "{";
s += end_statement;
Dictionary d = p_var;
ERR_FAIL_COND_V_MSG(p_markers.has(d.id()), "\"{...}\"", "Converting circular structure to JSON.");
p_markers.insert(d.id());
List<Variant> keys;
d.get_key_list(&keys);
@ -106,12 +115,13 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_
s += ",";
s += end_statement;
}
s += _make_indent(p_indent, p_cur_indent + 1) + _print_var(String(E->get()), p_indent, p_cur_indent + 1, p_sort_keys);
s += _make_indent(p_indent, p_cur_indent + 1) + _print_var(String(E->get()), p_indent, p_cur_indent + 1, p_sort_keys, p_markers);
s += colon;
s += _print_var(d[E->get()], p_indent, p_cur_indent + 1, p_sort_keys);
s += _print_var(d[E->get()], p_indent, p_cur_indent + 1, p_sort_keys, p_markers);
}
s += end_statement + _make_indent(p_indent, p_cur_indent) + "}";
p_markers.erase(d.id());
return s;
};
default:
@ -120,7 +130,8 @@ String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_
}
String JSON::print(const Variant &p_var, const String &p_indent, bool p_sort_keys) {
return _print_var(p_var, p_indent, 0, p_sort_keys);
Set<const void *> markers;
return _print_var(p_var, p_indent, 0, p_sort_keys, markers);
}
Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str) {

View File

@ -63,7 +63,7 @@ class JSON {
static const char *tk_name[TK_MAX];
static String _print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys);
static String _print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys, Set<const void *> &p_markers);
static Error _get_token(const CharType *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str);
static Error _parse_value(Variant &value, Token &token, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str);

View File

@ -661,8 +661,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str
file->store_32(count + 1);
//store how many properties are saved, add one for custom featuers, which must always go first
String key = CoreStringNames::get_singleton()->_custom_features;
file->store_32(key.length());
file->store_string(key);
file->store_pascal_string(key);
int len;
err = encode_variant(p_custom_features, nullptr, len, false);
@ -699,8 +698,7 @@ Error ProjectSettings::_save_settings_binary(const String &p_file, const Map<Str
value = get(key);
}
file->store_32(key.length());
file->store_string(key);
file->store_pascal_string(key);
int len;
err = encode_variant(value, nullptr, len, true);

View File

@ -180,7 +180,7 @@ Error String::parse_url(String &r_scheme, String &r_host, int &r_port, String &r
base = base.substr(pos + 1, base.length() - pos - 1);
} else {
// Anything else
if (base.get_slice_count(":") > 1) {
if (base.get_slice_count(":") > 2) {
return ERR_INVALID_PARAMETER;
}
pos = base.rfind(":");

View File

@ -1406,6 +1406,7 @@ String Variant::stringify(List<const void *> &stack) const {
}
str += "}";
stack.erase(d.id());
return str;
} break;
case POOL_VECTOR2_ARRAY: {
@ -1485,6 +1486,7 @@ String Variant::stringify(List<const void *> &stack) const {
}
str += "]";
stack.erase(arr.id());
return str;
} break;

View File

@ -275,7 +275,8 @@
<argument index="1" name="new_name" type="String">
</argument>
<description>
If the currently being played animation changes, this signal will notify of such change.
Emitted when a queued animation plays after the previous animation was finished. See [method queue].
[b]Note:[/b] The signal is not emitted when the animation is changed via [method play] or from [AnimationTree].
</description>
</signal>
<signal name="animation_finished">

View File

@ -53,7 +53,6 @@
Creates a new surface.
Surfaces are created to be rendered using a [code]primitive[/code], which may be any of the types defined in [enum Mesh.PrimitiveType]. (As a note, when using indices, it is recommended to only use points, lines or triangles.) [method Mesh.get_surface_count] will become the [code]surf_idx[/code] for this new surface.
The [code]arrays[/code] argument is an array of arrays. See [enum ArrayType] for the values used in this array. For example, [code]arrays[0][/code] is the array of vertices. That first vertex sub-array is always required; the others are optional. Adding an index array puts this function into "index mode" where the vertex and other arrays become the sources of data and the index array defines the vertex order. All sub-arrays must have the same length as the vertex array or be empty, except for [constant ARRAY_INDEX] if it is used.
Adding an index array puts this function into "index mode" where the vertex and other arrays become the sources of data, and the index array defines the order of the vertices.
</description>
</method>
<method name="clear_blend_shapes">

View File

@ -13,23 +13,30 @@
</methods>
<members>
<member name="fft_size" type="int" setter="set_fft_size" getter="get_fft_size" enum="AudioEffectPitchShift.FFT_Size" default="3">
The size of the [url=https://en.wikipedia.org/wiki/Fast_Fourier_transform]Fast Fourier transform[/url] buffer. Higher values smooth out the effect over time, but have greater latency. The effects of this higher latency are especially noticeable on sounds that have sudden amplitude changes.
</member>
<member name="oversampling" type="int" setter="set_oversampling" getter="get_oversampling" default="4">
The oversampling factor to use. Higher values result in better quality, but are more demanding on the CPU and may cause audio cracking if the CPU can't keep up.
</member>
<member name="pitch_scale" type="float" setter="set_pitch_scale" getter="get_pitch_scale" default="1.0">
Pitch value. Can range from 0 (-1 octave) to 16 (+16 octaves).
The pitch scale to use. [code]1.0[/code] is the default pitch and plays sounds unaltered. [member pitch_scale] can range from [code]0.0[/code] (infinitely low pitch, inaudible) to [code]16[/code] (16 times higher than the initial pitch).
</member>
</members>
<constants>
<constant name="FFT_SIZE_256" value="0" enum="FFT_Size">
Use a buffer of 256 samples for the Fast Fourier transform. Lowest latency, but least stable over time.
</constant>
<constant name="FFT_SIZE_512" value="1" enum="FFT_Size">
Use a buffer of 512 samples for the Fast Fourier transform. Low latency, but less stable over time.
</constant>
<constant name="FFT_SIZE_1024" value="2" enum="FFT_Size">
Use a buffer of 1024 samples for the Fast Fourier transform. This is a compromise between latency and stability over time.
</constant>
<constant name="FFT_SIZE_2048" value="3" enum="FFT_Size">
Use a buffer of 2048 samples for the Fast Fourier transform. High latency, but stable over time.
</constant>
<constant name="FFT_SIZE_4096" value="4" enum="FFT_Size">
Use a buffer of 4096 samples for the Fast Fourier transform. Highest latency, but most stable over time.
</constant>
<constant name="FFT_SIZE_MAX" value="5" enum="FFT_Size">
Represents the size of the [enum FFT_Size] enum.

View File

@ -1,31 +1,43 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectSpectrumAnalyzer" inherits="AudioEffect" version="3.4">
<brief_description>
Audio effect that can be used for real-time audio visualizations.
</brief_description>
<description>
This audio effect does not affect sound output, but can be used for real-time audio visualizations.
See also [AudioStreamGenerator] for procedurally generating sounds.
</description>
<tutorials>
<link title="https://godotengine.org/asset-library/asset/528">Audio Spectrum Demo</link>
<link title="https://godotengine.org/article/godot-32-will-get-new-audio-features">Godot 3.2 will get new audio features</link>
</tutorials>
<methods>
</methods>
<members>
<member name="buffer_length" type="float" setter="set_buffer_length" getter="get_buffer_length" default="2.0">
The length of the buffer to keep (in seconds). Higher values keep data around for longer, but require more memory.
</member>
<member name="fft_size" type="int" setter="set_fft_size" getter="get_fft_size" enum="AudioEffectSpectrumAnalyzer.FFT_Size" default="2">
The size of the [url=https://en.wikipedia.org/wiki/Fast_Fourier_transform]Fast Fourier transform[/url] buffer. Higher values smooth out the spectrum analysis over time, but have greater latency. The effects of this higher latency are especially noticeable with sudden amplitude changes.
</member>
<member name="tap_back_pos" type="float" setter="set_tap_back_pos" getter="get_tap_back_pos" default="0.01">
</member>
</members>
<constants>
<constant name="FFT_SIZE_256" value="0" enum="FFT_Size">
Use a buffer of 256 samples for the Fast Fourier transform. Lowest latency, but least stable over time.
</constant>
<constant name="FFT_SIZE_512" value="1" enum="FFT_Size">
Use a buffer of 512 samples for the Fast Fourier transform. Low latency, but less stable over time.
</constant>
<constant name="FFT_SIZE_1024" value="2" enum="FFT_Size">
Use a buffer of 1024 samples for the Fast Fourier transform. This is a compromise between latency and stability over time.
</constant>
<constant name="FFT_SIZE_2048" value="3" enum="FFT_Size">
Use a buffer of 2048 samples for the Fast Fourier transform. High latency, but stable over time.
</constant>
<constant name="FFT_SIZE_4096" value="4" enum="FFT_Size">
Use a buffer of 4096 samples for the Fast Fourier transform. Highest latency, but most stable over time.
</constant>
<constant name="FFT_SIZE_MAX" value="5" enum="FFT_Size">
Represents the size of the [enum FFT_Size] enum.

View File

@ -1,18 +1,27 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioStreamGenerator" inherits="AudioStream" version="3.4">
<brief_description>
Audio stream that generates sounds procedurally.
</brief_description>
<description>
This audio stream does not play back sounds, but expects a script to generate audio data for it instead. See also [AudioStreamGeneratorPlayback].
See also [AudioEffectSpectrumAnalyzer] for performing real-time audio spectrum analysis.
[b]Note:[/b] Due to performance constraints, this class is best used from C# or from a compiled language via GDNative. If you still want to use this class from GDScript, consider using a lower [member mix_rate] such as 11,025 Hz or 22,050 Hz.
</description>
<tutorials>
<link title="Audio Generator Demo">https://godotengine.org/asset-library/asset/526</link>
<link title="https://godotengine.org/article/godot-32-will-get-new-audio-features">Godot 3.2 will get new audio features</link>
</tutorials>
<methods>
</methods>
<members>
<member name="buffer_length" type="float" setter="set_buffer_length" getter="get_buffer_length" default="0.5">
The length of the buffer to generate (in seconds). Lower values result in less latency, but require the script to generate audio data faster, resulting in increased CPU usage and more risk for audio cracking if the CPU can't keep up.
</member>
<member name="mix_rate" type="float" setter="set_mix_rate" getter="get_mix_rate" default="44100.0">
The sample rate to use (in Hz). Higher values are more demanding for the CPU to generate, but result in better quality.
In games, common sample rates in use are [code]11025[/code], [code]16000[/code], [code]22050[/code], [code]32000[/code], [code]44100[/code], and [code]48000[/code].
According to the [url=https://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampling_theorem]Nyquist-Shannon sampling theorem[/url], there is no quality difference to human hearing when going past 40,000 Hz (since most humans can only hear up to ~20,000 Hz, often less). If you are generating lower-pitched sounds such as voices, lower sample rates such as [code]32000[/code] or [code]22050[/code] may be usable with no loss in quality.
</member>
</members>
<constants>

View File

@ -1,11 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioStreamGeneratorPlayback" inherits="AudioStreamPlaybackResampled" version="3.4">
<brief_description>
Plays back audio generated using [AudioStreamGenerator].
</brief_description>
<description>
This class is meant to be used with [AudioStreamGenerator] to play back the generated audio in real-time.
</description>
<tutorials>
<link>https://github.com/godotengine/godot-demo-projects/tree/master/audio/generator</link>
<link title="Audio Generator Demo">https://godotengine.org/asset-library/asset/526</link>
<link title="https://godotengine.org/article/godot-32-will-get-new-audio-features">Godot 3.2 will get new audio features</link>
</tutorials>
<methods>
<method name="can_push_buffer" qualifiers="const">
@ -14,18 +17,21 @@
<argument index="0" name="amount" type="int">
</argument>
<description>
Returns [code]true[/code] if a buffer of the size [code]amount[/code] can be pushed to the audio sample data buffer without overflowing it, [code]false[/code] otherwise.
</description>
</method>
<method name="clear_buffer">
<return type="void">
</return>
<description>
Clears the audio sample data buffer.
</description>
</method>
<method name="get_frames_available" qualifiers="const">
<return type="int">
</return>
<description>
Returns the number of audio data frames left to play. If this returned number reaches [code]0[/code], the audio will stop playing until frames are added again. Therefore, make sure your script can always generate and push new audio frames fast enough to avoid audio cracking.
</description>
</method>
<method name="get_skips" qualifiers="const">
@ -40,6 +46,7 @@
<argument index="0" name="frames" type="PoolVector2Array">
</argument>
<description>
Pushes several audio data frames to the buffer. This is usually more efficient than [method push_frame] in C# and compiled languages via GDNative, but [method push_buffer] may be [i]less[/i] efficient in GDScript.
</description>
</method>
<method name="push_frame">
@ -48,6 +55,7 @@
<argument index="0" name="frame" type="Vector2">
</argument>
<description>
Pushes a single audio data frame to the buffer. This is usually less efficient than [method push_buffer] in C# and compiled languages via GDNative, but [method push_frame] may be [i]more[/i] efficient in GDScript.
</description>
</method>
</methods>

View File

@ -5,7 +5,7 @@
</brief_description>
<description>
AudioStreamSample stores sound samples loaded from WAV files. To play the stored sound, use an [AudioStreamPlayer] (for non-positional audio) or [AudioStreamPlayer2D]/[AudioStreamPlayer3D] (for positional audio). The sound can be looped.
This class can also be used to store dynamically-generated PCM audio data.
This class can also be used to store dynamically-generated PCM audio data. See also [AudioStreamGenerator] for procedural audio generation.
</description>
<tutorials>
</tutorials>
@ -39,7 +39,9 @@
The loop mode. This information will be imported automatically from the WAV file if present. See [enum LoopMode] constants for values.
</member>
<member name="mix_rate" type="int" setter="set_mix_rate" getter="get_mix_rate" default="44100">
The sample rate for mixing this audio.
The sample rate for mixing this audio. Higher values require more storage space, but result in better quality.
In games, common sample rates in use are [code]11025[/code], [code]16000[/code], [code]22050[/code], [code]32000[/code], [code]44100[/code], and [code]48000[/code].
According to the [url=https://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampling_theorem]Nyquist-Shannon sampling theorem[/url], there is no quality difference to human hearing when going past 40,000 Hz (since most humans can only hear up to ~20,000 Hz, often less). If you are using lower-pitched sounds such as voices, lower sample rates such as [code]32000[/code] or [code]22050[/code] may be usable with no loss in quality.
</member>
<member name="stereo" type="bool" setter="set_stereo" getter="is_stereo" default="false">
If [code]true[/code], audio is stereo.

View File

@ -159,6 +159,7 @@
</member>
<member name="physics_jitter_fix" type="float" setter="set_physics_jitter_fix" getter="get_physics_jitter_fix" default="0.5">
Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of in-game clock and real clock, but allows smoothing out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended.
[b]Note:[/b] For best results, when using a custom physics interpolation solution, the physics jitter fix should be disabled by setting [member physics_jitter_fix] to [code]0[/code].
</member>
<member name="target_fps" type="int" setter="set_target_fps" getter="get_target_fps" default="0">
The desired frames per second. If the hardware cannot keep up, this setting may not be respected. A value of 0 means no limit.

View File

@ -288,7 +288,7 @@
If [code]true[/code], microphone input will be allowed. This requires appropriate permissions to be set when exporting to Android or iOS.
</member>
<member name="audio/mix_rate" type="int" setter="" getter="" default="44100">
Mixing rate used for audio. In general, it's better to not touch this and leave it to the host operating system.
The mixing rate used for audio (in Hz). In general, it's better to not touch this and leave it to the host operating system.
</member>
<member name="audio/output_latency" type="int" setter="" getter="" default="15">
Output latency in milliseconds for audio. Lower values will result in lower audio latency at the cost of increased CPU usage. Low values may result in audible cracking on slower hardware.
@ -1047,7 +1047,8 @@
[b]Note:[/b] This property is only read when the project starts. To change the physics FPS at runtime, set [member Engine.iterations_per_second] instead.
</member>
<member name="physics/common/physics_jitter_fix" type="float" setter="" getter="" default="0.5">
Fix to improve physics jitter, specially on monitors where refresh rate is different than the physics FPS.
Controls how much physics ticks are synchronized with real time. For 0 or less, the ticks are synchronized. Such values are recommended for network games, where clock synchronization matters. Higher values cause higher deviation of in-game clock and real clock, but allows smoothing out framerate jitters. The default value of 0.5 should be fine for most; values above 2 could cause the game to react to dropped frames with a noticeable delay and are not recommended.
[b]Note:[/b] For best results, when using a custom physics interpolation solution, the physics jitter fix should be disabled by setting [member physics/common/physics_jitter_fix] to [code]0[/code].
[b]Note:[/b] This property is only read when the project starts. To change the physics FPS at runtime, set [member Engine.physics_jitter_fix] instead.
</member>
<member name="rendering/2d/opengl/batching_send_null" type="int" setter="" getter="" default="0">

View File

@ -136,7 +136,7 @@ EditorAbout::EditorAbout() {
version_btn = memnew(LinkButton);
String hash = String(VERSION_HASH);
if (hash.length() != 0) {
hash = "." + hash.left(9);
hash = " " + vformat("[%s]", hash.left(9));
}
version_btn->set_text(VERSION_FULL_NAME + hash);
// Set the text to copy in metadata as it slightly differs from the button's text.

View File

@ -871,15 +871,16 @@ EditorAutoloadSettings::EditorAutoloadSettings() {
tree->set_column_title(0, TTR("Name"));
tree->set_column_expand(0, true);
tree->set_column_min_width(0, 100);
tree->set_column_min_width(0, 100 * EDSCALE);
tree->set_column_title(1, TTR("Path"));
tree->set_column_expand(1, true);
tree->set_column_min_width(1, 100);
tree->set_column_min_width(1, 100 * EDSCALE);
tree->set_column_title(2, TTR("Singleton"));
tree->set_column_title(2, TTR("Global Variable"));
tree->set_column_expand(2, false);
tree->set_column_min_width(2, 80 * EDSCALE);
// Reserve enough space for translations of "Global Variable" which may be longer.
tree->set_column_min_width(2, 150 * EDSCALE);
tree->set_column_expand(3, false);
tree->set_column_min_width(3, 120 * EDSCALE);

View File

@ -275,6 +275,9 @@ void EditorFileDialog::_post_popup() {
if (res && name == "res://") {
name = "/";
} else {
if (name.ends_with("/")) {
name = name.substr(0, name.length() - 1);
}
name = name.get_file() + "/";
}
bool exists = dir_access->dir_exists(recentd[i]);

View File

@ -515,7 +515,7 @@ void EditorNode::_notification(int p_what) {
} break;
case MainLoop::NOTIFICATION_WM_FOCUS_IN: {
// Restore the original FPS cap after focusing back on the editor
// Restore the original FPS cap after focusing back on the editor.
OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/low_processor_mode_sleep_usec")));
EditorFileSystem::get_singleton()->scan_changes();
@ -523,7 +523,12 @@ void EditorNode::_notification(int p_what) {
} break;
case MainLoop::NOTIFICATION_WM_FOCUS_OUT: {
// Set a low FPS cap to decrease CPU/GPU usage while the editor is unfocused
// Save on focus loss before applying the FPS limit to avoid slowing down the saving process.
if (EDITOR_GET("interface/editor/save_on_focus_loss")) {
_menu_option_confirm(FILE_SAVE_SCENE, false);
}
// Set a low FPS cap to decrease CPU/GPU usage while the editor is unfocused.
OS::get_singleton()->set_low_processor_usage_mode_sleep_usec(int(EDITOR_GET("interface/editor/unfocused_low_processor_mode_sleep_usec")));
} break;
@ -2073,9 +2078,14 @@ void EditorNode::_edit_current() {
if (!inspector_only) {
EditorPlugin *main_plugin = editor_data.get_editor(current_obj);
for (int i = 0; i < editor_table.size(); i++) {
if (editor_table[i] == main_plugin && !main_editor_buttons[i]->is_visible()) {
main_plugin = nullptr; //if button is not visible, then no plugin active
int plugin_index = 0;
for (; plugin_index < editor_table.size(); plugin_index++) {
if (editor_table[plugin_index] == main_plugin) {
if (!main_editor_buttons[plugin_index]->is_visible()) {
main_plugin = nullptr; //if button is not visible, then no plugin active
}
break;
}
}
@ -2089,26 +2099,8 @@ void EditorNode::_edit_current() {
else if (main_plugin != editor_plugin_screen && (!ScriptEditor::get_singleton() || !ScriptEditor::get_singleton()->is_visible_in_tree() || ScriptEditor::get_singleton()->can_take_away_focus())) {
// update screen main_plugin
if (!changing_scene) {
if (editor_plugin_screen) {
editor_plugin_screen->make_visible(false);
}
editor_plugin_screen = main_plugin;
editor_plugin_screen->edit(current_obj);
editor_plugin_screen->make_visible(true);
int plugin_count = editor_data.get_editor_plugin_count();
for (int i = 0; i < plugin_count; i++) {
editor_data.get_editor_plugin(i)->notify_main_screen_changed(editor_plugin_screen->get_name());
}
for (int i = 0; i < editor_table.size(); i++) {
main_editor_buttons[i]->set_pressed(editor_table[i] == main_plugin);
}
}
_editor_select(plugin_index);
main_plugin->edit(current_obj);
} else {
editor_plugin_screen->edit(current_obj);
}
@ -2645,6 +2637,9 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
case FILE_EXPLORE_ANDROID_BUILD_TEMPLATES: {
OS::get_singleton()->shell_open("file://" + ProjectSettings::get_singleton()->get_resource_path().plus_file("android"));
} break;
case RUN_RELOAD_CURRENT_PROJECT: {
restart_editor();
} break;
case FILE_QUIT:
case RUN_PROJECT_MANAGER: {
if (!p_confirmed) {
@ -5701,34 +5696,10 @@ EditorNode::EditorNode() {
int display_scale = EditorSettings::get_singleton()->get("interface/editor/display_scale");
switch (display_scale) {
case 0: {
case 0:
// Try applying a suitable display scale automatically.
// The code below is adapted in `editor/editor_settings.cpp` and `editor/project_manager.cpp`.
// Make sure to update those when modifying the code below.
#ifdef OSX_ENABLED
editor_set_scale(OS::get_singleton()->get_screen_max_scale());
#else
const int screen = OS::get_singleton()->get_current_screen();
float scale;
if (OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).y >= 1400) {
// hiDPI display.
scale = 2.0;
} else if (OS::get_singleton()->get_screen_size(screen).y >= 1700) {
// Likely a hiDPI display, but we aren't certain due to the returned DPI.
// Use an intermediate scale to handle this situation.
scale = 1.5;
} else if (OS::get_singleton()->get_screen_size(screen).y <= 800) {
// Small loDPI display. Use a smaller display scale so that editor elements fit more easily.
// Icons won't look great, but this is better than having editor elements overflow from its window.
scale = 0.75;
} else {
scale = 1.0;
}
editor_set_scale(scale);
#endif
} break;
editor_set_scale(EditorSettings::get_singleton()->get_auto_display_scale());
break;
case 1:
editor_set_scale(0.75);
break;
@ -5867,6 +5838,7 @@ EditorNode::EditorNode() {
EDITOR_DEF("run/output/always_open_output_on_play", true);
EDITOR_DEF("run/output/always_close_output_on_stop", true);
EDITOR_DEF("run/auto_save/save_before_running", true);
EDITOR_DEF("interface/editor/save_on_focus_loss", false);
EDITOR_DEF_RST("interface/editor/save_each_scene_on_quit", true);
EDITOR_DEF("interface/editor/quit_confirmation", true);
EDITOR_DEF("interface/editor/show_update_spinner", false);
@ -6269,6 +6241,7 @@ EditorNode::EditorNode() {
tool_menu->add_item(TTR("Orphan Resource Explorer..."), TOOLS_ORPHAN_RESOURCES);
p->add_separator();
p->add_item(TTR("Reload Current Project"), RUN_RELOAD_CURRENT_PROJECT);
#ifdef OSX_ENABLED
p->add_shortcut(ED_SHORTCUT("editor/quit_to_project_list", TTR("Quit to Project List"), KEY_MASK_SHIFT + KEY_MASK_ALT + KEY_Q), RUN_PROJECT_MANAGER, true);
#else
@ -6616,7 +6589,7 @@ EditorNode::EditorNode() {
version_btn->set_text(VERSION_FULL_CONFIG);
String hash = String(VERSION_HASH);
if (hash.length() != 0) {
hash = "." + hash.left(9);
hash = " " + vformat("[%s]", hash.left(9));
}
// Set the text to copy in metadata as it slightly differs from the button's text.
version_btn->set_meta(META_TEXT_TO_COPY, "v" VERSION_FULL_BUILD + hash);

View File

@ -164,6 +164,7 @@ private:
RUN_SCENE_SETTINGS,
RUN_SETTINGS,
RUN_PROJECT_DATA_FOLDER,
RUN_RELOAD_CURRENT_PROJECT,
RUN_PROJECT_MANAGER,
RUN_FILE_SERVER,
RUN_LIVE_DEBUG,

View File

@ -699,44 +699,54 @@ void EditorPlugin::restore_global_state() {}
void EditorPlugin::save_global_state() {}
void EditorPlugin::add_import_plugin(const Ref<EditorImportPlugin> &p_importer) {
ERR_FAIL_COND(!p_importer.is_valid());
ResourceFormatImporter::get_singleton()->add_importer(p_importer);
EditorFileSystem::get_singleton()->call_deferred("scan");
}
void EditorPlugin::remove_import_plugin(const Ref<EditorImportPlugin> &p_importer) {
ERR_FAIL_COND(!p_importer.is_valid());
ResourceFormatImporter::get_singleton()->remove_importer(p_importer);
EditorFileSystem::get_singleton()->call_deferred("scan");
}
void EditorPlugin::add_export_plugin(const Ref<EditorExportPlugin> &p_exporter) {
ERR_FAIL_COND(!p_exporter.is_valid());
EditorExport::get_singleton()->add_export_plugin(p_exporter);
}
void EditorPlugin::remove_export_plugin(const Ref<EditorExportPlugin> &p_exporter) {
ERR_FAIL_COND(!p_exporter.is_valid());
EditorExport::get_singleton()->remove_export_plugin(p_exporter);
}
void EditorPlugin::add_spatial_gizmo_plugin(const Ref<EditorSpatialGizmoPlugin> &p_gizmo_plugin) {
ERR_FAIL_COND(!p_gizmo_plugin.is_valid());
SpatialEditor::get_singleton()->add_gizmo_plugin(p_gizmo_plugin);
}
void EditorPlugin::remove_spatial_gizmo_plugin(const Ref<EditorSpatialGizmoPlugin> &p_gizmo_plugin) {
ERR_FAIL_COND(!p_gizmo_plugin.is_valid());
SpatialEditor::get_singleton()->remove_gizmo_plugin(p_gizmo_plugin);
}
void EditorPlugin::add_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin) {
ERR_FAIL_COND(!p_plugin.is_valid());
EditorInspector::add_inspector_plugin(p_plugin);
}
void EditorPlugin::remove_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin) {
ERR_FAIL_COND(!p_plugin.is_valid());
EditorInspector::remove_inspector_plugin(p_plugin);
}
void EditorPlugin::add_scene_import_plugin(const Ref<EditorSceneImporter> &p_importer) {
ERR_FAIL_COND(!p_importer.is_valid());
ResourceImporterScene::get_singleton()->add_importer(p_importer);
}
void EditorPlugin::remove_scene_import_plugin(const Ref<EditorSceneImporter> &p_importer) {
ERR_FAIL_COND(!p_importer.is_valid());
ResourceImporterScene::get_singleton()->remove_importer(p_importer);
}

View File

@ -988,9 +988,8 @@ void EditorPropertyEasing::_draw_easing() {
Size2 s = easing_draw->get_size();
const int points = 48;
const int point_count = 48;
float prev = 1.0;
const float exp = get_edited_object()->get(get_edited_property());
const Ref<Font> f = get_font("font", "Label");
@ -1002,24 +1001,20 @@ void EditorPropertyEasing::_draw_easing() {
line_color = get_color("font_color", "Label") * Color(1, 1, 1, 0.9);
}
Vector<Point2> lines;
for (int i = 1; i <= points; i++) {
float ifl = i / float(points);
float iflp = (i - 1) / float(points);
Vector<Point2> points;
for (int i = 0; i <= point_count; i++) {
float ifl = i / float(point_count);
const float h = 1.0 - Math::ease(ifl, exp);
if (flip) {
ifl = 1.0 - ifl;
iflp = 1.0 - iflp;
}
lines.push_back(Point2(ifl * s.width, h * s.height));
lines.push_back(Point2(iflp * s.width, prev * s.height));
prev = h;
points.push_back(Point2(ifl * s.width, h * s.height));
}
easing_draw->draw_multiline(lines, line_color, 1.0, true);
easing_draw->draw_polyline(points, line_color, 1.0, true);
// Draw more decimals for small numbers since higher precision is usually required for fine adjustments.
int decimals;
if (Math::abs(exp) < 0.1 - CMP_EPSILON) {

View File

@ -309,28 +309,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
// Editor
_initial_set("interface/editor/display_scale", 0);
// Display what the Auto display scale setting effectively corresponds to.
// The code below is adapted in `editor/editor_node.cpp` and `editor/project_manager.cpp`.
// Make sure to update those when modifying the code below.
#ifdef OSX_ENABLED
float scale = OS::get_singleton()->get_screen_max_scale();
#else
const int screen = OS::get_singleton()->get_current_screen();
float scale;
if (OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).y >= 1400) {
// hiDPI display.
scale = 2.0;
} else if (OS::get_singleton()->get_screen_size(screen).y >= 1700) {
// Likely a hiDPI display, but we aren't certain due to the returned DPI.
// Use an intermediate scale to handle this situation.
scale = 1.5;
} else if (OS::get_singleton()->get_screen_size(screen).y <= 800) {
// Small loDPI display. Use a smaller display scale so that editor elements fit more easily.
// Icons won't look great, but this is better than having editor elements overflow from its window.
scale = 0.75;
} else {
scale = 1.0;
}
#endif
float scale = get_auto_display_scale();
hints["interface/editor/display_scale"] = PropertyInfo(Variant::INT, "interface/editor/display_scale", PROPERTY_HINT_ENUM, vformat("Auto (%d%%),75%%,100%%,125%%,150%%,175%%,200%%,Custom", Math::round(scale * 100)), PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/editor/custom_display_scale", 1.0f);
hints["interface/editor/custom_display_scale"] = PropertyInfo(Variant::REAL, "interface/editor/custom_display_scale", PROPERTY_HINT_RANGE, "0.5,3,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
@ -354,8 +333,12 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
_initial_set("interface/editor/dim_editor_on_dialog_popup", true);
_initial_set("interface/editor/low_processor_mode_sleep_usec", 6900); // ~144 FPS
hints["interface/editor/low_processor_mode_sleep_usec"] = PropertyInfo(Variant::REAL, "interface/editor/low_processor_mode_sleep_usec", PROPERTY_HINT_RANGE, "1,100000,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/editor/unfocused_low_processor_mode_sleep_usec", 50000); // 20 FPS
hints["interface/editor/unfocused_low_processor_mode_sleep_usec"] = PropertyInfo(Variant::REAL, "interface/editor/unfocused_low_processor_mode_sleep_usec", PROPERTY_HINT_RANGE, "1,100000,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/editor/unfocused_low_processor_mode_sleep_usec", 100000); // 10 FPS
// Allow an unfocused FPS limit as low as 1 FPS for those who really need low power usage
// (but don't need to preview particles or shaders while the editor is unfocused).
// With very low FPS limits, the editor can take a small while to become usable after being focused again,
// so this should be used at the user's discretion.
hints["interface/editor/unfocused_low_processor_mode_sleep_usec"] = PropertyInfo(Variant::REAL, "interface/editor/unfocused_low_processor_mode_sleep_usec", PROPERTY_HINT_RANGE, "1,1000000,1", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED);
_initial_set("interface/editor/separate_distraction_mode", false);
_initial_set("interface/editor/automatically_open_screenshots", true);
_initial_set("interface/editor/hide_console_window", false);
@ -1482,6 +1465,29 @@ String EditorSettings::get_editor_layouts_config() const {
return get_settings_dir().plus_file("editor_layouts.cfg");
}
float EditorSettings::get_auto_display_scale() const {
#ifdef OSX_ENABLED
return OS::get_singleton()->get_screen_max_scale();
#else
const int screen = OS::get_singleton()->get_current_screen();
// Use the smallest dimension to use a correct display scale on portait displays.
const int smallest_dimension = MIN(OS::get_singleton()->get_screen_size(screen).x, OS::get_singleton()->get_screen_size(screen).y);
if (OS::get_singleton()->get_screen_dpi(screen) >= 192 && smallest_dimension >= 1400) {
// hiDPI display.
return 2.0;
} else if (smallest_dimension >= 1700) {
// Likely a hiDPI display, but we aren't certain due to the returned DPI.
// Use an intermediate scale to handle this situation.
return 1.5;
} else if (smallest_dimension <= 800) {
// Small loDPI display. Use a smaller display scale so that editor elements fit more easily.
// Icons won't look great, but this is better than having editor elements overflow from its window.
return 0.75;
}
return 1.0;
#endif
}
// Shortcuts
void EditorSettings::add_shortcut(const String &p_name, Ref<ShortCut> &p_shortcut) {

View File

@ -189,6 +189,7 @@ public:
Vector<String> get_script_templates(const String &p_extension, const String &p_custom_path = String());
String get_editor_layouts_config() const;
float get_auto_display_scale() const;
void add_shortcut(const String &p_name, Ref<ShortCut> &p_shortcut);
bool is_shortcut(const String &p_name, const Ref<InputEvent> &p_event) const;

View File

@ -218,6 +218,7 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme =
exceptions.insert("EditorControlAnchor");
exceptions.insert("DefaultProjectIcon");
exceptions.insert("GuiChecked");
exceptions.insert("GuiRadioChecked");
exceptions.insert("GuiCloseCustomizable");
exceptions.insert("GuiGraphNodePort");
exceptions.insert("GuiResizer");

View File

@ -2656,7 +2656,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
// `KEY_MASK_CMD | KEY_C` conflicts with other editor shortcuts.
ED_SHORTCUT("filesystem_dock/copy_path", TTR("Copy Path"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_C);
ED_SHORTCUT("filesystem_dock/duplicate", TTR("Duplicate..."), KEY_MASK_CMD | KEY_D);
ED_SHORTCUT("filesystem_dock/delete", TTR("Move to Trash"), KEY_DELETE);
ED_SHORTCUT("filesystem_dock/delete", TTR("Delete"), KEY_DELETE);
ED_SHORTCUT("filesystem_dock/rename", TTR("Rename..."), KEY_F2);
ED_SHORTCUT("filesystem_dock/open_search", TTR("Focus the search box"), KEY_MASK_CMD | KEY_F);

View File

@ -1 +1 @@
<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m15 8a7 7 0 0 1 -7 7 7 7 0 0 1 -7-7 7 7 0 0 1 7-7 7 7 0 0 1 7 7" fill-opacity=".188235" stroke-width="2.333333"/><path d="m12 8a4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4 4 4 0 0 1 4 4" stroke-width="1.333333"/></g></svg>
<svg height="16" viewBox="0 0 16 15.999999" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m15 8a7 7 0 0 1 -7 7 7 7 0 0 1 -7-7 7 7 0 0 1 7-7 7 7 0 0 1 7 7" fill="#699ce8" stroke-width="2.33333"/><path d="m12 8a4 4 0 0 1 -4 4 4 4 0 0 1 -4-4 4 4 0 0 1 4-4 4 4 0 0 1 4 4" fill="#fff" stroke-width="1.33333"/></svg>

Before

Width:  |  Height:  |  Size: 340 B

After

Width:  |  Height:  |  Size: 320 B

View File

@ -210,6 +210,7 @@ void ResourceImporterTexture::get_import_options(List<ImportOption> *r_options,
void ResourceImporterTexture::_save_stex(const Ref<Image> &p_image, const String &p_to_path, int p_compress_mode, float p_lossy_quality, Image::CompressMode p_vram_compression, bool p_mipmaps, int p_texture_flags, bool p_streamable, bool p_detect_3d, bool p_detect_srgb, bool p_force_rgbe, bool p_detect_normal, bool p_force_normal, bool p_force_po2_for_compressed) {
FileAccess *f = FileAccess::open(p_to_path, FileAccess::WRITE);
ERR_FAIL_NULL(f);
f->store_8('G');
f->store_8('D');
f->store_8('S');

View File

@ -336,7 +336,7 @@ void SpatialEditorViewport::_update_camera(float p_interp_delta) {
equal = false;
}
if (!equal || p_interp_delta == 0 || is_freelook_active() || is_orthogonal != orthogonal) {
if (!equal || p_interp_delta == 0 || is_orthogonal != orthogonal) {
camera->set_global_transform(to_camera_transform(camera_cursor));
if (orthogonal) {
@ -4766,11 +4766,11 @@ void SpatialEditor::_update_camera_override_button(bool p_game_running) {
if (p_game_running) {
button->set_disabled(false);
button->set_tooltip(TTR("Game Camera Override\nNo game instance running."));
button->set_tooltip(TTR("Project Camera Override\nOverrides the running project's camera with the editor viewport camera."));
} else {
button->set_disabled(true);
button->set_pressed(false);
button->set_tooltip(TTR("Game Camera Override\nOverrides game camera with editor viewport camera."));
button->set_tooltip(TTR("Project Camera Override\nNo project instance running. Run the project from the editor to use this feature."));
}
}

View File

@ -1047,7 +1047,7 @@ TextureRegionEditor::TextureRegionEditor(EditorNode *p_editor) {
hb_grid->add_child(sb_step_y);
hb_grid->add_child(memnew(VSeparator));
hb_grid->add_child(memnew(Label(TTR("Sep.:"))));
hb_grid->add_child(memnew(Label(TTR("Separation:"))));
sb_sep_x = memnew(SpinBox);
sb_sep_x->set_min(0);

View File

@ -702,7 +702,7 @@ ThemeEditor::ThemeEditor() {
test_menu_button->get_popup()->add_radio_check_item(TTR("Radio Item"));
test_menu_button->get_popup()->add_radio_check_item(TTR("Checked Radio Item"));
test_menu_button->get_popup()->set_item_checked(7, true);
test_menu_button->get_popup()->add_separator(TTR("Named Sep."));
test_menu_button->get_popup()->add_separator(TTR("Named Separator"));
PopupMenu *test_submenu = memnew(PopupMenu);
test_menu_button->get_popup()->add_child(test_submenu);

View File

@ -2363,34 +2363,10 @@ ProjectManager::ProjectManager() {
float custom_display_scale = EditorSettings::get_singleton()->get("interface/editor/custom_display_scale");
switch (display_scale) {
case 0: {
case 0:
// Try applying a suitable display scale automatically.
// The code below is adapted in `editor/editor_settings.cpp` and `editor/editor_node.cpp`.
// Make sure to update those when modifying the code below.
#ifdef OSX_ENABLED
editor_set_scale(OS::get_singleton()->get_screen_max_scale());
#else
const int screen = OS::get_singleton()->get_current_screen();
float scale;
if (OS::get_singleton()->get_screen_dpi(screen) >= 192 && OS::get_singleton()->get_screen_size(screen).y >= 1400) {
// hiDPI display.
scale = 2.0;
} else if (OS::get_singleton()->get_screen_size(screen).y >= 1700) {
// Likely a hiDPI display, but we aren't certain due to the returned DPI.
// Use an intermediate scale to handle this situation.
scale = 1.5;
} else if (OS::get_singleton()->get_screen_size(screen).y <= 800) {
// Small loDPI display. Use a smaller display scale so that editor elements fit more easily.
// Icons won't look great, but this is better than having editor elements overflow from its window.
scale = 0.75;
} else {
scale = 1.0;
}
editor_set_scale(scale);
#endif
} break;
editor_set_scale(EditorSettings::get_singleton()->get_auto_display_scale());
break;
case 1:
editor_set_scale(0.75);
break;
@ -2600,7 +2576,7 @@ ProjectManager::ProjectManager() {
version_btn = memnew(LinkButton);
String hash = String(VERSION_HASH);
if (hash.length() != 0) {
hash = "." + hash.left(9);
hash = " " + vformat("[%s]", hash.left(9));
}
version_btn->set_text("v" VERSION_FULL_BUILD + hash);
// Fade the version label to be less prominent, but still readable.

View File

@ -1169,10 +1169,10 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
}
Engine::get_singleton()->set_iterations_per_second(GLOBAL_DEF("physics/common/physics_fps", 60));
ProjectSettings::get_singleton()->set_custom_property_info("physics/common/physics_fps", PropertyInfo(Variant::INT, "physics/common/physics_fps", PROPERTY_HINT_RANGE, "1,120,1,or_greater"));
ProjectSettings::get_singleton()->set_custom_property_info("physics/common/physics_fps", PropertyInfo(Variant::INT, "physics/common/physics_fps", PROPERTY_HINT_RANGE, "1,1000,1"));
Engine::get_singleton()->set_physics_jitter_fix(GLOBAL_DEF("physics/common/physics_jitter_fix", 0.5));
Engine::get_singleton()->set_target_fps(GLOBAL_DEF("debug/settings/fps/force_fps", 0));
ProjectSettings::get_singleton()->set_custom_property_info("debug/settings/fps/force_fps", PropertyInfo(Variant::INT, "debug/settings/fps/force_fps", PROPERTY_HINT_RANGE, "0,120,1,or_greater"));
ProjectSettings::get_singleton()->set_custom_property_info("debug/settings/fps/force_fps", PropertyInfo(Variant::INT, "debug/settings/fps/force_fps", PROPERTY_HINT_RANGE, "0,1000,1"));
GLOBAL_DEF("physics/common/enable_pause_aware_picking", false);
GLOBAL_DEF("debug/settings/stdout/print_fps", false);

View File

@ -36,6 +36,8 @@
</array>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.$app_category</string>
<key>LSMinimumSystemVersion</key>
<string>10.12</string>
<key>LSMinimumSystemVersionByArchitecture</key>

View File

@ -38,6 +38,8 @@
</array>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>LSMinimumSystemVersion</key>
<string>10.12</string>
<key>LSMinimumSystemVersionByArchitecture</key>

View File

@ -369,7 +369,10 @@ void NetworkedMultiplayerENet::poll() {
// To myself and only myself
incoming_packets.push_back(packet);
} else if (!server_relay) {
// No other destination is allowed when server is not relaying
// When relaying is disabled, other destinations will only be processed by the server.
if (target == 0 || target < -1) {
incoming_packets.push_back(packet);
}
continue;
} else if (target == 0) {
// Re-send to everyone but sender :|

View File

@ -310,7 +310,7 @@ PlaceHolderScriptInstance *GDScript::placeholder_instance_create(Object *p_this)
#ifdef TOOLS_ENABLED
PlaceHolderScriptInstance *si = memnew(PlaceHolderScriptInstance(GDScriptLanguage::get_singleton(), Ref<Script>(this), p_this));
placeholders.insert(si);
_update_exports();
_update_exports(nullptr, false, si);
return si;
#else
return NULL;
@ -357,7 +357,7 @@ void GDScript::_update_exports_values(Map<StringName, Variant> &values, List<Pro
}
#endif
bool GDScript::_update_exports(bool *r_err, bool p_recursive_call) {
bool GDScript::_update_exports(bool *r_err, bool p_recursive_call, PlaceHolderScriptInstance *p_instance_to_update) {
#ifdef TOOLS_ENABLED
static Vector<GDScript *> base_caches;
@ -480,15 +480,19 @@ bool GDScript::_update_exports(bool *r_err, bool p_recursive_call) {
}
}
if (placeholders.size()) { //hm :(
if ((changed || p_instance_to_update) && placeholders.size()) { //hm :(
// update placeholders if any
Map<StringName, Variant> values;
List<PropertyInfo> propnames;
_update_exports_values(values, propnames);
for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
E->get()->update(propnames, values);
if (changed) {
for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
E->get()->update(propnames, values);
}
} else {
p_instance_to_update->update(propnames, values);
}
}

View File

@ -129,7 +129,7 @@ class GDScript : public Script {
#endif
bool _update_exports(bool *r_err = nullptr, bool p_recursive_call = false);
bool _update_exports(bool *r_err = nullptr, bool p_recursive_call = false, PlaceHolderScriptInstance *p_instance_to_update = nullptr);
void _save_orphaned_subclasses();

View File

@ -1098,6 +1098,16 @@ void GridMapEditor::_notification(int p_what) {
options->set_icon(get_icon("GridMap", "EditorIcons"));
search_box->set_right_icon(get_icon("Search", "EditorIcons"));
} break;
case NOTIFICATION_WM_FOCUS_OUT: {
if (input_action == INPUT_PAINT) {
// Simulate mouse released event to stop drawing when editor focus exists.
Ref<InputEventMouseButton> release;
release.instance();
release->set_button_index(BUTTON_LEFT);
forward_spatial_input_event(nullptr, release);
}
} break;
}
}

View File

@ -2214,7 +2214,7 @@ void CSharpScript::_update_member_info_no_exports() {
}
#endif
bool CSharpScript::_update_exports() {
bool CSharpScript::_update_exports(PlaceHolderScriptInstance *p_instance_to_update) {
#ifdef TOOLS_ENABLED
bool is_editor = Engine::get_singleton()->is_editor_hint();
if (is_editor)
@ -2385,14 +2385,18 @@ bool CSharpScript::_update_exports() {
if (is_editor) {
placeholder_fallback_enabled = false;
if (placeholders.size()) {
if ((changed || p_instance_to_update) && placeholders.size()) {
// Update placeholders if any
Map<StringName, Variant> values;
List<PropertyInfo> propnames;
_update_exports_values(values, propnames);
for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
E->get()->update(propnames, values);
if (changed) {
for (Set<PlaceHolderScriptInstance *>::Element *E = placeholders.front(); E; E = E->next()) {
E->get()->update(propnames, values);
}
} else {
p_instance_to_update->update(propnames, values);
}
}
}
@ -2989,7 +2993,7 @@ PlaceHolderScriptInstance *CSharpScript::placeholder_instance_create(Object *p_t
#ifdef TOOLS_ENABLED
PlaceHolderScriptInstance *si = memnew(PlaceHolderScriptInstance(CSharpLanguage::get_singleton(), Ref<Script>(this), p_this));
placeholders.insert(si);
_update_exports();
_update_exports(si);
return si;
#else
return NULL;

View File

@ -135,7 +135,8 @@ class CSharpScript : public Script {
void load_script_signals(GDMonoClass *p_class, GDMonoClass *p_native_class);
bool _get_signal(GDMonoClass *p_class, GDMonoClass *p_delegate, Vector<Argument> &params);
bool _update_exports();
bool _update_exports(PlaceHolderScriptInstance *p_instance_to_update = nullptr);
bool _get_member_export(IMonoClassMember *p_member, bool p_inspect_export, PropertyInfo &r_prop_info, bool &r_exported);
#ifdef TOOLS_ENABLED
static int _try_get_member_export_hint(IMonoClassMember *p_member, ManagedType p_type, Variant::Type p_variant_type, bool p_allow_generics, PropertyHint &r_hint, String &r_hint_string);

View File

@ -41,7 +41,7 @@
// JavaScript functions defined in library_godot_editor_tools.js
extern "C" {
extern int godot_js_os_download_buffer(const uint8_t *p_buf, int p_buf_size, const char *p_name, const char *p_mime);
extern void godot_js_os_download_buffer(const uint8_t *p_buf, int p_buf_size, const char *p_name, const char *p_mime);
}
static void _javascript_editor_init_callback() {

View File

@ -84,7 +84,7 @@ extern void godot_js_display_cursor_set_custom_shape(const char *p_shape, const
extern void godot_js_display_cursor_set_visible(int p_visible);
// Display gamepad
extern char *godot_js_display_gamepad_cb(void (*p_on_change)(int p_index, int p_connected, const char *p_id, const char *p_guid));
extern void godot_js_display_gamepad_cb(void (*p_on_change)(int p_index, int p_connected, const char *p_id, const char *p_guid));
extern int godot_js_display_gamepad_sample();
extern int godot_js_display_gamepad_sample_count();
extern int godot_js_display_gamepad_sample_get(int p_idx, float r_btns[16], int32_t *r_btns_num, float r_axes[10], int32_t *r_axes_num, int32_t *r_standard);

View File

@ -28,11 +28,15 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifdef JAVASCRIPT_EVAL_ENABLED
#include "api/javascript_singleton.h"
#include "emscripten.h"
extern "C" {
extern void godot_js_os_download_buffer(const uint8_t *p_buf, int p_buf_size, const char *p_name, const char *p_mime);
}
#ifdef JAVASCRIPT_EVAL_ENABLED
extern "C" {
typedef union {
int64_t i;
@ -302,7 +306,6 @@ union js_eval_ret {
};
extern int godot_js_eval(const char *p_js, int p_use_global_ctx, union js_eval_ret *p_union_ptr, void *p_byte_arr, void *p_byte_arr_write, void *(*p_callback)(void *p_ptr, void *p_ptr2, int p_len));
extern int godot_js_os_download_buffer(const uint8_t *p_buf, int p_buf_size, const char *p_name, const char *p_mime);
}
void *resize_poolbytearray_and_open_write(void *p_arr, void *r_write, int p_len) {

View File

@ -683,7 +683,7 @@ const GodotDisplay = {
return GodotDisplayScreen.exitFullscreen();
},
godot_js_display_desired_size_set__sig: 'v',
godot_js_display_desired_size_set__sig: 'vii',
godot_js_display_desired_size_set: function (width, height) {
GodotDisplayScreen.desired_size = [width, height];
GodotDisplayScreen.updateSize();

View File

@ -126,7 +126,7 @@ const GodotFetch = {
},
},
godot_js_fetch_create__sig: 'iii',
godot_js_fetch_create__sig: 'iiiiiii',
godot_js_fetch_create: function (p_method, p_url, p_headers, p_headers_size, p_body, p_body_size) {
const method = GodotRuntime.parseString(p_method);
const url = GodotRuntime.parseString(p_url);
@ -176,7 +176,7 @@ const GodotFetch = {
return obj.status;
},
godot_js_fetch_read_headers__sig: 'iii',
godot_js_fetch_read_headers__sig: 'iiii',
godot_js_fetch_read_headers: function (p_id, p_parse_cb, p_ref) {
const obj = IDHandler.get(p_id);
if (!obj || !obj.response) {
@ -193,7 +193,7 @@ const GodotFetch = {
return 0;
},
godot_js_fetch_read_chunk__sig: 'ii',
godot_js_fetch_read_chunk__sig: 'iiii',
godot_js_fetch_read_chunk: function (p_id, p_buf, p_buf_size) {
const obj = IDHandler.get(p_id);
if (!obj || !obj.response) {

View File

@ -196,7 +196,7 @@ const GodotJSWrapper = {
}
},
godot_js_wrapper_create_cb__sig: 'vii',
godot_js_wrapper_create_cb__sig: 'iii',
godot_js_wrapper_create_cb: function (p_ref, p_func) {
const func = GodotRuntime.get_func(p_func);
let id = 0;

File diff suppressed because it is too large Load Diff

View File

@ -20,9 +20,9 @@
"author": "Godot Engine contributors",
"license": "MIT",
"devDependencies": {
"eslint": "^7.9.0",
"eslint-config-airbnb-base": "^14.2.0",
"eslint-plugin-import": "^2.22.0",
"jsdoc": "github:jsdoc/jsdoc#544a992824631fc652183d8b0b4b1281dc961560"
"eslint": "^7.28.0",
"eslint-config-airbnb-base": "^14.2.1",
"eslint-plugin-import": "^2.23.4",
"jsdoc": "^3.6.7"
}
}

View File

@ -147,6 +147,7 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.png,*.icns"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/app_category", PROPERTY_HINT_ENUM, "Business,Developer-tools,Education,Entertainment,Finance,Games,Action-games,Adventure-games,Arcade-games,Board-games,Card-games,Casino-games,Dice-games,Educational-games,Family-games,Kids-games,Music-games,Puzzle-games,Racing-games,Role-playing-games,Simulation-games,Sports-games,Strategy-games,Trivia-games,Word-games,Graphics-design,Healthcare-fitness,Lifestyle,Medical,Music,News,Photography,Productivity,Reference,Social-networking,Sports,Travel,Utilities,Video,Weather"), "Games"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), ""));
@ -386,6 +387,9 @@ void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset
strnew += lines[i].replace("$version", p_preset->get("application/version")) + "\n";
} else if (lines[i].find("$signature") != -1) {
strnew += lines[i].replace("$signature", p_preset->get("application/signature")) + "\n";
} else if (lines[i].find("$app_category") != -1) {
String cat = p_preset->get("application/app_category");
strnew += lines[i].replace("$app_category", cat.to_lower()) + "\n";
} else if (lines[i].find("$copyright") != -1) {
strnew += lines[i].replace("$copyright", p_preset->get("application/copyright")) + "\n";
} else if (lines[i].find("$highres") != -1) {

View File

@ -175,10 +175,9 @@ void BaseButton::on_action_event(Ref<InputEvent> p_event) {
status.hovering = false;
}
}
// pressed state should be correct with button_up signal
emit_signal("button_up");
status.press_attempt = false;
status.pressing_inside = false;
emit_signal("button_up");
}
update();

View File

@ -41,8 +41,13 @@
#define ZOOM_SCALE 1.2
#define MIN_ZOOM (((1 / ZOOM_SCALE) / ZOOM_SCALE) / ZOOM_SCALE)
#define MAX_ZOOM (1 * ZOOM_SCALE * ZOOM_SCALE * ZOOM_SCALE)
// Allow dezooming 8 times from the default zoom level.
// At low zoom levels, text is unreadable due to its small size and poor filtering,
// but this is still useful for previewing purposes.
#define MIN_ZOOM (1 / Math::pow(ZOOM_SCALE, 8))
// Allow zooming 4 times from the default zoom level.
#define MAX_ZOOM (1 * Math::pow(ZOOM_SCALE, 4))
#define MINIMAP_OFFSET 12
#define MINIMAP_PADDING 5

View File

@ -293,10 +293,12 @@ void TextureButton::set_normal_texture(const Ref<Texture> &p_normal) {
void TextureButton::set_pressed_texture(const Ref<Texture> &p_pressed) {
pressed = p_pressed;
update();
minimum_size_changed();
}
void TextureButton::set_hover_texture(const Ref<Texture> &p_hover) {
hover = p_hover;
update();
minimum_size_changed();
}
void TextureButton::set_disabled_texture(const Ref<Texture> &p_disabled) {
disabled = p_disabled;
@ -305,6 +307,7 @@ void TextureButton::set_disabled_texture(const Ref<Texture> &p_disabled) {
void TextureButton::set_click_mask(const Ref<BitMap> &p_click_mask) {
click_mask = p_click_mask;
update();
minimum_size_changed();
}
Ref<Texture> TextureButton::get_normal_texture() const {