Merge pull request #42406 from akien-mga/3.2-cherrypicks

Cherry-picks for the 3.2 branch (future 3.2.4) - 2nd batch
This commit is contained in:
Rémi Verschelde 2020-09-29 14:34:40 +02:00 committed by GitHub
commit 59d873258c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
51 changed files with 250 additions and 128 deletions

View file

@ -13,7 +13,7 @@ jobs:
run: |
sudo apt-get update -qq
sudo apt-get install -qq dos2unix recode clang-format
sudo pip3 install black pygments
sudo pip3 install black==20.8b1 pygments
- name: File formatting checks (file_format.sh)
run: |

View file

@ -316,31 +316,6 @@ if selected_platform in platform_list:
env["warnings"] = "extra"
env["werror"] = True
if env["vsproj"]:
env.vs_incs = []
env.vs_srcs = []
def AddToVSProject(sources):
for x in sources:
if type(x) == type(""):
fname = env.File(x).path
else:
fname = env.File(x)[0].path
pieces = fname.split(".")
if len(pieces) > 0:
basename = pieces[0]
basename = basename.replace("\\\\", "/")
if os.path.isfile(basename + ".h"):
env.vs_incs = env.vs_incs + [basename + ".h"]
elif os.path.isfile(basename + ".hpp"):
env.vs_incs = env.vs_incs + [basename + ".hpp"]
if os.path.isfile(basename + ".c"):
env.vs_srcs = env.vs_srcs + [basename + ".c"]
elif os.path.isfile(basename + ".cpp"):
env.vs_srcs = env.vs_srcs + [basename + ".cpp"]
env.AddToVSProject = AddToVSProject
env.extra_suffix = ""
if env["extra_suffix"] != "":
@ -604,6 +579,10 @@ if selected_platform in platform_list:
CacheDir(scons_cache_path)
print("Scons cache enabled... (path: '" + scons_cache_path + "')")
if env["vsproj"]:
env.vs_incs = []
env.vs_srcs = []
Export("env")
# build subdirs, the build order is dependent on link order.

View file

@ -39,8 +39,7 @@ class MessageQueue {
_THREAD_SAFE_CLASS_
enum {
DEFAULT_QUEUE_SIZE_KB = 1024
DEFAULT_QUEUE_SIZE_KB = 4096
};
enum {

View file

@ -1750,11 +1750,14 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str
write(E->get(), p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud);
p_store_string_func(p_store_string_ud, ": ");
write(dict[E->get()], p_store_string_func, p_store_string_ud, p_encode_res_func, p_encode_res_ud);
if (E->next())
if (E->next()) {
p_store_string_func(p_store_string_ud, ",\n");
} else {
p_store_string_func(p_store_string_ud, "\n");
}
}
p_store_string_func(p_store_string_ud, "\n}");
p_store_string_func(p_store_string_ud, "}");
} break;
case Variant::ARRAY: {

View file

@ -1,10 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectHighShelfFilter" inherits="AudioEffectFilter" version="3.2">
<brief_description>
Reduces all frequencies above the [member AudioEffectFilter.cutoff_hz].
</brief_description>
<description>
</description>
<tutorials>
<link title="Audio buses">https://docs.godotengine.org/en/latest/tutorials/audio/audio_buses.html</link>
</tutorials>
<methods>
</methods>

View file

@ -1,10 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="AudioEffectLowShelfFilter" inherits="AudioEffectFilter" version="3.2">
<brief_description>
Reduces all frequencies below the [member AudioEffectFilter.cutoff_hz].
</brief_description>
<description>
</description>
<tutorials>
<link title="Audio buses">https://docs.godotengine.org/en/latest/tutorials/audio/audio_buses.html</link>
</tutorials>
<methods>
</methods>

View file

@ -8,6 +8,7 @@
You can also create a color from standardized color names by using [method @GDScript.ColorN] or directly using the color constants defined here. The standardized color set is based on the [url=https://en.wikipedia.org/wiki/X11_color_names]X11 color names[/url].
If you want to supply values in a range of 0 to 255, you should use [method @GDScript.Color8].
[b]Note:[/b] In a boolean context, a Color will evaluate to [code]false[/code] if it's equal to [code]Color(0, 0, 0, 1)[/code] (opaque black). Otherwise, a Color will always evaluate to [code]true[/code].
[url=https://raw.githubusercontent.com/godotengine/godot-docs/master/img/color_constants.png]Color constants cheatsheet[/url]
</description>
<tutorials>
</tutorials>

View file

@ -96,10 +96,12 @@
Extra spacing at the bottom in pixels.
</member>
<member name="extra_spacing_char" type="int" setter="set_spacing" getter="get_spacing" default="0">
Extra character spacing in pixels.
Extra spacing for each character in pixels.
This can be a negative number to make the distance between characters smaller.
</member>
<member name="extra_spacing_space" type="int" setter="set_spacing" getter="get_spacing" default="0">
Extra space spacing in pixels.
Extra spacing for the space character (in addition to [member extra_spacing_char]) in pixels.
This can be a negative number to make the distance between words smaller.
</member>
<member name="extra_spacing_top" type="int" setter="set_spacing" getter="get_spacing" default="0">
Extra spacing at the top in pixels.
@ -132,10 +134,10 @@
Spacing at the bottom.
</constant>
<constant name="SPACING_CHAR" value="2" enum="SpacingType">
Character spacing.
Spacing for each character.
</constant>
<constant name="SPACING_SPACE" value="3" enum="SpacingType">
Space spacing.
Spacing for the space character.
</constant>
</constants>
</class>

View file

@ -125,8 +125,10 @@
</argument>
<argument index="1" name="for_property" type="String" default="&quot;&quot;">
</argument>
<argument index="2" name="inspector_only" type="bool" default="false">
</argument>
<description>
Shows the given property on the given [code]object[/code] in the editor's Inspector dock.
Shows the given property on the given [code]object[/code] in the editor's Inspector dock. If [code]inspector_only[/code] is [code]true[/code], plugins will not attempt to edit [code]object[/code].
</description>
</method>
<method name="is_playing_scene" qualifiers="const">

View file

@ -21,6 +21,7 @@
return content
[/codeblock]
In the example above, the file will be saved in the user data folder as specified in the [url=https://docs.godotengine.org/en/latest/tutorials/io/data_paths.html]Data paths[/url] documentation.
[b]Note:[/b] To access project resources once exported, it is recommended to use [ResourceLoader] instead of the [File] API, as some files are converted to engine-specific formats and their original source files might not be present in the exported PCK package.
</description>
<tutorials>
<link>https://docs.godotengine.org/en/latest/getting_started/step_by_step/filesystem.html</link>
@ -48,7 +49,7 @@
</argument>
<description>
Returns [code]true[/code] if the file exists in the given path.
[b]Note:[/b] Many resources types are imported (e.g. textures or sound files), and that their source asset will not be included in the exported game, as only the imported version is used (in the [code]res://.import[/code] folder). To check for the existence of such resources while taking into account the remapping to their imported location, use [method ResourceLoader.exists]. Typically, using [code]File.file_exists[/code] on an imported resource would work while you are developing in the editor (the source asset is present in [code]res://[/code], but fail when exported).
[b]Note:[/b] Many resources types are imported (e.g. textures or sound files), and their source asset will not be included in the exported game, as only the imported version is used. See [method ResourceLoader.exists] for an alternative approach that takes resource remapping into account.
</description>
</method>
<method name="get_16" qualifiers="const">

View file

@ -6,7 +6,7 @@
<description>
Kinematic bodies are special types of bodies that are meant to be user-controlled. They are not affected by physics at all; to other types of bodies, such as a character or a rigid body, these are the same as a static body. However, they have two main uses:
[b]Simulated motion:[/b] When these bodies are moved manually, either from code or from an [AnimationPlayer] (with [member AnimationPlayer.playback_process_mode] set to "physics"), the physics will automatically compute an estimate of their linear and angular velocity. This makes them very useful for moving platforms or other AnimationPlayer-controlled objects (like a door, a bridge that opens, etc).
[b]Kinematic characters:[/b] KinematicBody also has an API for moving objects (the [method move_and_collide] and [method move_and_slide] methods) while performing collision tests. This makes them really useful to implement characters that collide against a world, but that don't require advanced physics.
[b]Kinematic characters:[/b] KinematicBody also has an API for moving objects (the [method move_and_collide] and [method move_and_slide] methods) while performing collision tests. This makes them really useful to implement characters that collide against a world, but don't require advanced physics.
</description>
<tutorials>
<link>https://docs.godotengine.org/en/latest/tutorials/physics/kinematic_character_2d.html</link>
@ -41,35 +41,35 @@
<argument index="0" name="slide_idx" type="int">
</argument>
<description>
Returns a [KinematicCollision], which contains information about a collision that occurred during the last [method move_and_slide] call. Since the body can collide several times in a single call to [method move_and_slide], you must specify the index of the collision in the range 0 to ([method get_slide_count] - 1).
Returns a [KinematicCollision], which contains information about a collision that occurred during the last call to [method move_and_slide] or [method move_and_slide_with_snap]. Since the body can collide several times in a single call to [method move_and_slide], you must specify the index of the collision in the range 0 to ([method get_slide_count] - 1).
</description>
</method>
<method name="get_slide_count" qualifiers="const">
<return type="int">
</return>
<description>
Returns the number of times the body collided and changed direction during the last call to [method move_and_slide].
Returns the number of times the body collided and changed direction during the last call to [method move_and_slide] or [method move_and_slide_with_snap].
</description>
</method>
<method name="is_on_ceiling" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the body is on the ceiling. Only updates when calling [method move_and_slide].
Returns [code]true[/code] if the body is on the ceiling. Only updates when calling [method move_and_slide] or [method move_and_slide_with_snap].
</description>
</method>
<method name="is_on_floor" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the body is on the floor. Only updates when calling [method move_and_slide].
Returns [code]true[/code] if the body is on the floor. Only updates when calling [method move_and_slide] or [method move_and_slide_with_snap].
</description>
</method>
<method name="is_on_wall" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the body is on a wall. Only updates when calling [method move_and_slide].
Returns [code]true[/code] if the body is on a wall. Only updates when calling [method move_and_slide] or [method move_and_slide_with_snap].
</description>
</method>
<method name="move_and_collide">
@ -104,7 +104,7 @@
<argument index="5" name="infinite_inertia" type="bool" default="true">
</argument>
<description>
Moves the body along a vector. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [KinematicBody] or [RigidBody], it will also be affected by the motion of the other body. You can use this to make moving or rotating platforms, or to make nodes push other nodes.
Moves the body along a vector. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [KinematicBody] or [RigidBody], it will also be affected by the motion of the other body. You can use this to make moving and rotating platforms, or to make nodes push other nodes.
This method should be used in [method Node._physics_process] (or in a method called by [method Node._physics_process]), as it uses the physics step's [code]delta[/code] value automatically in calculations. Otherwise, the simulation will run at an incorrect speed.
[code]linear_velocity[/code] is the velocity vector (typically meters per second). Unlike in [method move_and_collide], you should [i]not[/i] multiply it by [code]delta[/code] — the physics engine handles applying the velocity.
[code]up_direction[/code] is the up direction, used to determine what is a wall and what is a floor or a ceiling. If set to the default value of [code]Vector3(0, 0, 0)[/code], everything is considered a wall.

View file

@ -6,7 +6,7 @@
<description>
Kinematic bodies are special types of bodies that are meant to be user-controlled. They are not affected by physics at all; to other types of bodies, such as a character or a rigid body, these are the same as a static body. However, they have two main uses:
[b]Simulated motion:[/b] When these bodies are moved manually, either from code or from an [AnimationPlayer] (with [member AnimationPlayer.playback_process_mode] set to "physics"), the physics will automatically compute an estimate of their linear and angular velocity. This makes them very useful for moving platforms or other AnimationPlayer-controlled objects (like a door, a bridge that opens, etc).
[b]Kinematic characters:[/b] KinematicBody2D also has an API for moving objects (the [method move_and_collide] and [method move_and_slide] methods) while performing collision tests. This makes them really useful to implement characters that collide against a world, but that don't require advanced physics.
[b]Kinematic characters:[/b] KinematicBody2D also has an API for moving objects (the [method move_and_collide] and [method move_and_slide] methods) while performing collision tests. This makes them really useful to implement characters that collide against a world, but don't require advanced physics.
</description>
<tutorials>
<link title="Kinematic character (2D)">https://docs.godotengine.org/en/latest/tutorials/physics/kinematic_character_2d.html</link>
@ -33,7 +33,7 @@
<argument index="0" name="slide_idx" type="int">
</argument>
<description>
Returns a [KinematicCollision2D], which contains information about a collision that occurred during the last [method move_and_slide] call. Since the body can collide several times in a single call to [method move_and_slide], you must specify the index of the collision in the range 0 to ([method get_slide_count] - 1).
Returns a [KinematicCollision2D], which contains information about a collision that occurred during the last call to [method move_and_slide] or [method move_and_slide_with_snap]. Since the body can collide several times in a single call to [method move_and_slide], you must specify the index of the collision in the range 0 to ([method get_slide_count] - 1).
[b]Example usage:[/b]
[codeblock]
for i in get_slide_count():
@ -46,28 +46,28 @@
<return type="int">
</return>
<description>
Returns the number of times the body collided and changed direction during the last call to [method move_and_slide].
Returns the number of times the body collided and changed direction during the last call to [method move_and_slide] or [method move_and_slide_with_snap].
</description>
</method>
<method name="is_on_ceiling" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the body is on the ceiling. Only updates when calling [method move_and_slide].
Returns [code]true[/code] if the body is on the ceiling. Only updates when calling [method move_and_slide] or [method move_and_slide_with_snap].
</description>
</method>
<method name="is_on_floor" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the body is on the floor. Only updates when calling [method move_and_slide].
Returns [code]true[/code] if the body is on the floor. Only updates when calling [method move_and_slide] or [method move_and_slide_with_snap].
</description>
</method>
<method name="is_on_wall" qualifiers="const">
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the body is on a wall. Only updates when calling [method move_and_slide].
Returns [code]true[/code] if the body is on a wall. Only updates when calling [method move_and_slide] or [method move_and_slide_with_snap].
</description>
</method>
<method name="move_and_collide">
@ -102,7 +102,7 @@
<argument index="5" name="infinite_inertia" type="bool" default="true">
</argument>
<description>
Moves the body along a vector. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [KinematicBody2D] or [RigidBody2D], it will also be affected by the motion of the other body. You can use this to make moving or rotating platforms, or to make nodes push other nodes.
Moves the body along a vector. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [KinematicBody2D] or [RigidBody2D], it will also be affected by the motion of the other body. You can use this to make moving and rotating platforms, or to make nodes push other nodes.
This method should be used in [method Node._physics_process] (or in a method called by [method Node._physics_process]), as it uses the physics step's [code]delta[/code] value automatically in calculations. Otherwise, the simulation will run at an incorrect speed.
[code]linear_velocity[/code] is the velocity vector in pixels per second. Unlike in [method move_and_collide], you should [i]not[/i] multiply it by [code]delta[/code] — the physics engine handles applying the velocity.
[code]up_direction[/code] is the up direction, used to determine what is a wall and what is a floor or a ceiling. If set to the default value of [code]Vector2(0, 0)[/code], everything is considered a wall. This is useful for topdown games.

View file

@ -824,7 +824,7 @@
<member name="logging/file_logging/max_log_files" type="int" setter="" getter="" default="5">
Specifies the maximum amount of log files allowed (used for rotation).
</member>
<member name="memory/limits/message_queue/max_size_kb" type="int" setter="" getter="" default="1024">
<member name="memory/limits/message_queue/max_size_kb" type="int" setter="" getter="" default="4096">
Godot uses a message queue to defer some function calls. If you run out of space on it (you will see an error), you can increase the size here.
</member>
<member name="memory/limits/multithreaded_server/rid_pool_prealloc" type="int" setter="" getter="" default="60">

View file

@ -158,10 +158,12 @@
Specifies whether to use [code]UV[/code] or [code]UV2[/code] for the detail layer. See [enum DetailUV] for options.
</member>
<member name="distance_fade_max_distance" type="float" setter="set_distance_fade_max_distance" getter="get_distance_fade_max_distance">
Distance at which the object fades fully and is no longer visible.
Distance at which the object appears fully opaque.
[b]Note:[/b] If [code]distance_fade_max_distance[/code] is less than [code]distance_fade_min_distance[/code], the behavior will be reversed. The object will start to fade away at [code]distance_fade_max_distance[/code] and will fully disappear once it reaches [code]distance_fade_min_distance[/code].
</member>
<member name="distance_fade_min_distance" type="float" setter="set_distance_fade_min_distance" getter="get_distance_fade_min_distance">
Distance at which the object starts to fade. If the object is less than this distance away it will appear normal.
Distance at which the object starts to become visible. If the object is less than this distance away, it will be invisible.
[b]Note:[/b] If [code]distance_fade_min_distance[/code] is greater than [code]distance_fade_max_distance[/code], the behavior will be reversed. The object will start to fade away at [code]distance_fade_max_distance[/code] and will fully disappear once it reaches [code]distance_fade_min_distance[/code].
</member>
<member name="distance_fade_mode" type="int" setter="set_distance_fade" getter="get_distance_fade" enum="SpatialMaterial.DistanceFadeMode" default="0">
Specifies which type of fade to use. Can be any of the [enum DistanceFadeMode]s.
@ -252,6 +254,7 @@
</member>
<member name="params_billboard_mode" type="int" setter="set_billboard_mode" getter="get_billboard_mode" enum="SpatialMaterial.BillboardMode" default="0">
Controls how the object faces the camera. See [enum BillboardMode].
[b]Note:[/b] Billboard mode is not suitable for VR because the left-right vector of the camera is not horizontal when the screen is attached to your head instead of on the table. See [url=https://github.com/godotengine/godot/issues/41567]GitHub issue #41567[/url] for details.
</member>
<member name="params_blend_mode" type="int" setter="set_blend_mode" getter="get_blend_mode" enum="SpatialMaterial.BlendMode" default="0">
The material's blend mode.

View file

@ -172,7 +172,7 @@
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the vector is normalized, and false otherwise.
Returns [code]true[/code] if the vector is normalized, [code]false[/code] otherwise.
</description>
</method>
<method name="length">

View file

@ -147,7 +147,7 @@
<return type="bool">
</return>
<description>
Returns [code]true[/code] if the vector is normalized, and false otherwise.
Returns [code]true[/code] if the vector is normalized, [code]false[/code] otherwise.
</description>
</method>
<method name="length">

View file

@ -33,15 +33,6 @@ else:
# Core dependencies
SConscript("png/SCsub")
if env["vsproj"]:
import os
path = os.getcwd()
# Change directory so the path resolves correctly in the function call.
os.chdir("..")
env.AddToVSProject(env.drivers_sources)
os.chdir(path)
env.add_source_files(env.drivers_sources, "*.cpp")
lib = env.add_library("drivers", env.drivers_sources)

View file

@ -154,7 +154,7 @@ String DirAccessUnix::get_next() {
_cisdir = (entry->d_type == DT_DIR);
}
_cishidden = (fname != "." && fname != ".." && fname.begins_with("."));
_cishidden = is_hidden(fname);
return fname;
}
@ -408,6 +408,10 @@ String DirAccessUnix::get_filesystem_type() const {
return ""; //TODO this should be implemented
}
bool DirAccessUnix::is_hidden(const String &p_name) {
return p_name != "." && p_name != ".." && p_name.begins_with(".");
}
DirAccessUnix::DirAccessUnix() {
dir_stream = 0;

View file

@ -52,6 +52,7 @@ class DirAccessUnix : public DirAccess {
protected:
virtual String fix_unicode_name(const char *p_name) const { return String::utf8(p_name); }
virtual bool is_hidden(const String &p_name);
public:
virtual Error list_dir_begin(); ///< This starts dir listing

View file

@ -82,8 +82,15 @@ void EditorLog::_clear_request() {
}
void EditorLog::_copy_request() {
String text = log->get_selected_text();
log->selection_copy();
if (text == "") {
text = log->get_text();
}
if (text != "") {
OS::get_singleton()->set_clipboard(text);
}
}
void EditorLog::clear() {

View file

@ -242,9 +242,9 @@ String EditorInterface::get_current_path() const {
return EditorNode::get_singleton()->get_filesystem_dock()->get_current_path();
}
void EditorInterface::inspect_object(Object *p_obj, const String &p_for_property) {
void EditorInterface::inspect_object(Object *p_obj, const String &p_for_property, bool p_inspector_only) {
EditorNode::get_singleton()->push_item(p_obj, p_for_property);
EditorNode::get_singleton()->push_item(p_obj, p_for_property, p_inspector_only);
}
EditorFileSystem *EditorInterface::get_resource_file_system() {
@ -311,7 +311,7 @@ bool EditorInterface::is_distraction_free_mode_enabled() const {
void EditorInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("inspect_object", "object", "for_property"), &EditorInterface::inspect_object, DEFVAL(String()));
ClassDB::bind_method(D_METHOD("inspect_object", "object", "for_property", "inspector_only"), &EditorInterface::inspect_object, DEFVAL(String()), DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_selection"), &EditorInterface::get_selection);
ClassDB::bind_method(D_METHOD("get_editor_settings"), &EditorInterface::get_editor_settings);
ClassDB::bind_method(D_METHOD("get_script_editor"), &EditorInterface::get_script_editor);

View file

@ -88,7 +88,7 @@ public:
String get_selected_path() const;
String get_current_path() const;
void inspect_object(Object *p_obj, const String &p_for_property = String());
void inspect_object(Object *p_obj, const String &p_for_property = String(), bool p_inspector_only = false);
EditorSelection *get_selection();
//EditorImportExport *get_import_export();

View file

@ -987,19 +987,27 @@ void EditorPropertyEasing::_drag_easing(const Ref<InputEvent> &p_ev) {
rel = -rel;
float val = get_edited_object()->get(get_edited_property());
if (val == 0)
return;
bool sg = val < 0;
val = Math::absf(val);
val = Math::log(val) / Math::log((float)2.0);
//logspace
// Logarithmic space.
val += rel * 0.05;
val = Math::pow(2.0f, val);
if (sg)
val = -val;
// 0 is a singularity, but both positive and negative values
// are otherwise allowed. Enforce 0+ as workaround.
if (Math::is_zero_approx(val)) {
val = 0.00001;
}
// Limit to a reasonable value to prevent the curve going into infinity,
// which can cause crashes and other issues.
val = CLAMP(val, -1000000, 1000000);
emit_changed(get_edited_property(), val);
easing_draw->update();
}
@ -1044,7 +1052,18 @@ void EditorPropertyEasing::_draw_easing() {
}
easing_draw->draw_multiline(lines, line_color, 1.0, true);
f->draw(ci, Point2(10, 10 + f->get_ascent()), String::num(exp, 2), font_color);
// 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) {
decimals = 4;
} else if (Math::abs(exp) < 1 - CMP_EPSILON) {
decimals = 3;
} else if (Math::abs(exp) < 10 - CMP_EPSILON) {
decimals = 2;
} else {
decimals = 1;
}
f->draw(ci, Point2(10, 10 + f->get_ascent()), rtos(exp).pad_decimals(decimals), font_color);
}
void EditorPropertyEasing::update_property() {
@ -1075,6 +1094,11 @@ void EditorPropertyEasing::_spin_value_changed(double p_value) {
if (Math::is_zero_approx(p_value)) {
p_value = 0.00001;
}
// Limit to a reasonable value to prevent the curve going into infinity,
// which can cause crashes and other issues.
p_value = CLAMP(p_value, -1000000, 1000000);
emit_changed(get_edited_property(), p_value);
_spin_focus_exited();
}

View file

@ -376,7 +376,12 @@ String EditorSpinSlider::get_label() const {
}
void EditorSpinSlider::_evaluate_input_text() {
String text = value_input->get_text();
// Replace comma with dot to support it as decimal separator (GH-6028).
// This prevents using functions like `pow()`, but using functions
// in EditorSpinSlider is a barely known (and barely used) feature.
// Instead, we'd rather support German/French keyboard layouts out of the box.
const String text = value_input->get_text().replace(",", ".");
Ref<Expression> expr;
expr.instance();
Error err = expr->parse(text);

View file

@ -1 +1 @@
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><path d="m5 3-3 5h-1v4h1.0507812a2.5 2.5 0 0 1 2.4492188-2 2.5 2.5 0 0 1 2.4453125 2h2.1054687a2.5 2.5 0 0 1 2.4492188-2 2.5 2.5 0 0 1 2.445312 2h1.054688v-4h-1l-4-5zm1 1h3l3 4h-8z" stroke-width=".033311"/><circle cx="4.5" cy="12.5" r="1.5"/><circle cx="11.5" cy="12.5" r="1.5"/></g></svg>
<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="#e0e0e0"><circle cx="8" cy="5" r="4"/><path d="m11 13c0 1.6569 1.3431 3 3 3h1v-2h-1c-.55228-.00001-.99999-.44772-1-1 .00001-.55228.44772-.99999 1-1h1v-2h-1c-1.6569 0-3 1.3431-3 3z" fill-opacity=".99608"/><path d="m4 10c-1.6569 0-3 1.3431-3 3v3h2v-3c.0000096-.5523.44772-1 1-1h1v-2z" fill-opacity=".99608"/><path d="m8 10c-3 0-3 3-3 3s0 3 3 3h1v-2h-1s-1 0-1-1h3 1s0-3-3-3zm-1 1h2v1h-2z"/></g></svg>

Before

Width:  |  Height:  |  Size: 391 B

After

Width:  |  Height:  |  Size: 490 B

View file

@ -1226,6 +1226,12 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
ERR_FAIL_INDEX_V(material, state.materials.size(), ERR_FILE_CORRUPT);
const Ref<Material> &mat = state.materials[material];
mesh.mesh->surface_set_material(mesh.mesh->get_surface_count() - 1, mat);
} else {
Ref<SpatialMaterial> mat;
mat.instance();
mat->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
mesh.mesh->surface_set_material(mesh.mesh->get_surface_count() - 1, mat);
}
}
@ -1391,6 +1397,7 @@ Error EditorSceneImporterGLTF::_parse_materials(GLTFState &state) {
if (d.has("name")) {
material->set_name(d["name"]);
}
material->set_flag(SpatialMaterial::FLAG_ALBEDO_FROM_VERTEX_COLOR, true);
if (d.has("pbrMetallicRoughness")) {

View file

@ -951,8 +951,11 @@ void EditorAssetLibrary::_search(int p_page) {
_api_request("asset", REQUESTING_SEARCH, args);
}
void EditorAssetLibrary::_search_text_entered(const String &p_text) {
void EditorAssetLibrary::_search_text_changed(const String &p_text) {
filter_debounce_timer->start();
}
void EditorAssetLibrary::_filter_debounce_timer_timeout() {
_search();
}
@ -1328,7 +1331,8 @@ void EditorAssetLibrary::_bind_methods() {
ClassDB::bind_method("_select_category", &EditorAssetLibrary::_select_category);
ClassDB::bind_method("_image_request_completed", &EditorAssetLibrary::_image_request_completed);
ClassDB::bind_method("_search", &EditorAssetLibrary::_search, DEFVAL(0));
ClassDB::bind_method("_search_text_entered", &EditorAssetLibrary::_search_text_entered);
ClassDB::bind_method("_search_text_changed", &EditorAssetLibrary::_search_text_changed);
ClassDB::bind_method("_filter_debounce_timer_timeout", &EditorAssetLibrary::_filter_debounce_timer_timeout);
ClassDB::bind_method("_install_asset", &EditorAssetLibrary::_install_asset);
ClassDB::bind_method("_manage_plugins", &EditorAssetLibrary::_manage_plugins);
ClassDB::bind_method("_asset_open", &EditorAssetLibrary::_asset_open);
@ -1359,10 +1363,15 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
filter = memnew(LineEdit);
search_hb->add_child(filter);
filter->set_h_size_flags(SIZE_EXPAND_FILL);
filter->connect("text_entered", this, "_search_text_entered");
search = memnew(Button(TTR("Search")));
search->connect("pressed", this, "_search");
search_hb->add_child(search);
filter->connect("text_changed", this, "_search_text_changed");
// Perform a search automatically if the user hasn't entered any text for a certain duration.
// This way, the user doesn't need to press Enter to initiate their search.
filter_debounce_timer = memnew(Timer);
filter_debounce_timer->set_one_shot(true);
filter_debounce_timer->set_wait_time(0.25);
filter_debounce_timer->connect("timeout", this, "_filter_debounce_timer_timeout");
search_hb->add_child(filter_debounce_timer);
if (!p_templates_only)
search_hb->add_child(memnew(VSeparator));

View file

@ -186,10 +186,10 @@ class EditorAssetLibrary : public PanelContainer {
Label *library_loading;
Label *library_error;
LineEdit *filter;
Timer *filter_debounce_timer;
OptionButton *categories;
OptionButton *repository;
OptionButton *sort;
Button *search;
HBoxContainer *error_hb;
TextureRect *error_tr;
Label *error_label;
@ -284,10 +284,12 @@ class EditorAssetLibrary : public PanelContainer {
void _search(int p_page = 0);
void _rerun_search(int p_ignore);
void _search_text_changed(const String &p_text = "");
void _search_text_entered(const String &p_text = "");
void _api_request(const String &p_request, RequestType p_request_type, const String &p_arguments = "");
void _http_request_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data);
void _http_download_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data);
void _filter_debounce_timer_timeout();
void _repository_changed(int p_repository_id);
void _support_toggled(int p_support);

View file

@ -844,10 +844,11 @@ Vector2 CanvasItemEditor::_position_to_anchor(const Control *p_control, Vector2
ERR_FAIL_COND_V(!p_control, Vector2());
Rect2 parent_rect = p_control->get_parent_anchorable_rect();
ERR_FAIL_COND_V(parent_rect.size.x == 0, Vector2());
ERR_FAIL_COND_V(parent_rect.size.y == 0, Vector2());
return (p_control->get_transform().xform(position) - parent_rect.position) / parent_rect.size;
Vector2 output = Vector2();
output.x = (parent_rect.size.x == 0) ? 0.0 : (p_control->get_transform().xform(position).x - parent_rect.position.x) / parent_rect.size.x;
output.y = (parent_rect.size.y == 0) ? 0.0 : (p_control->get_transform().xform(position).y - parent_rect.position.y) / parent_rect.size.y;
return output;
}
void CanvasItemEditor::_save_canvas_item_ik_chain(const CanvasItem *p_canvas_item, List<float> *p_bones_length, List<Dictionary> *p_bones_state) {
@ -3694,12 +3695,12 @@ void CanvasItemEditor::_draw_viewport() {
_draw_grid();
_draw_ruler_tool();
_draw_selection();
_draw_axis();
if (editor->get_edited_scene()) {
_draw_locks_and_groups(editor->get_edited_scene());
_draw_invisible_nodes_positions(editor->get_edited_scene());
}
_draw_selection();
RID ci = viewport->get_canvas_item();
VisualServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D());

View file

@ -1856,7 +1856,7 @@ void ProjectManager::_update_project_buttons() {
rename_btn->set_disabled(empty_selection || is_missing_project_selected);
run_btn->set_disabled(empty_selection || is_missing_project_selected);
erase_missing_btn->set_visible(_project_list->is_any_project_missing());
erase_missing_btn->set_disabled(!_project_list->is_any_project_missing());
}
void ProjectManager::_unhandled_input(const Ref<InputEvent> &p_ev) {
@ -2525,6 +2525,7 @@ ProjectManager::ProjectManager() {
_project_list->set_enable_h_scroll(false);
VBoxContainer *tree_vb = memnew(VBoxContainer);
tree_vb->set_custom_minimum_size(Size2(120, 120));
tree_hb->add_child(tree_vb);
Button *open = memnew(Button);

View file

@ -1229,8 +1229,6 @@ void SceneTreeDock::_node_selected() {
Node *node = scene_tree->get_selected();
if (!node) {
editor->push_item(NULL);
return;
}
@ -1933,11 +1931,10 @@ void SceneTreeDock::_selection_changed() {
if (selection_size > 1) {
//automatically turn on multi-edit
_tool_selected(TOOL_MULTI_EDIT);
} else if (selection_size == 1) {
editor->push_item(EditorNode::get_singleton()->get_editor_selection()->get_selected_node_list()[0]);
} else {
} else if (selection_size == 0) {
editor->push_item(NULL);
}
_update_script_button();
}

View file

@ -794,6 +794,9 @@ void SceneTreeEditor::_renamed() {
if (new_name == n->get_name())
return;
// Trim leading/trailing whitespace to prevent node names from containing accidental whitespace, which would make it more difficult to get the node via `get_node()`.
new_name = new_name.strip_edges();
if (!undo_redo) {
n->set_name(new_name);
which->set_metadata(0, n->get_path());

View file

@ -1,4 +1,4 @@
# Portuguese (Portugal) translation of the Godot Engine editor
# Portuguese translation of the Godot Engine editor
# Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.
# Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).
# This file is distributed under the same license as the Godot source code.
@ -22,9 +22,9 @@ msgstr ""
"POT-Creation-Date: \n"
"PO-Revision-Date: 2020-09-24 12:43+0000\n"
"Last-Translator: ssantos <ssantos@web.de>\n"
"Language-Team: Portuguese (Portugal) <https://hosted.weblate.org/projects/"
"godot-engine/godot/pt_PT/>\n"
"Language: pt_PT\n"
"Language-Team: Portuguese <https://hosted.weblate.org/projects/"
"godot-engine/godot/pt/>\n"
"Language: pt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

View file

@ -5,6 +5,9 @@ import subprocess
from collections import OrderedDict
from compat import iteritems, isbasestring, open_utf8, decode_utf8, qualname
from SCons import Node
from SCons.Script import Glob
def add_source_files(self, sources, files, warn_duplicates=True):
# Convert string to list of absolute paths (including expanding wildcard)
@ -564,6 +567,35 @@ def generate_cpp_hint_file(filename):
print("Could not write cpp.hint file.")
def glob_recursive(pattern, node="."):
results = []
for f in Glob(str(node) + "/*", source=True):
if type(f) is Node.FS.Dir:
results += glob_recursive(pattern, f)
results += Glob(str(node) + "/" + pattern, source=True)
return results
def add_to_vs_project(env, sources):
for x in sources:
if type(x) == type(""):
fname = env.File(x).path
else:
fname = env.File(x)[0].path
pieces = fname.split(".")
if len(pieces) > 0:
basename = pieces[0]
basename = basename.replace("\\\\", "/")
if os.path.isfile(basename + ".h"):
env.vs_incs += [basename + ".h"]
elif os.path.isfile(basename + ".hpp"):
env.vs_incs += [basename + ".hpp"]
if os.path.isfile(basename + ".c"):
env.vs_srcs += [basename + ".c"]
elif os.path.isfile(basename + ".cpp"):
env.vs_srcs += [basename + ".cpp"]
def generate_vs_project(env, num_jobs):
batch_file = find_visual_c_batch_file(env)
if batch_file:
@ -596,12 +628,16 @@ def generate_vs_project(env, num_jobs):
result = " ^& ".join(common_build_prefix + [" ".join([commands] + common_build_postfix)])
return result
env.AddToVSProject(env.core_sources)
env.AddToVSProject(env.main_sources)
env.AddToVSProject(env.modules_sources)
env.AddToVSProject(env.scene_sources)
env.AddToVSProject(env.servers_sources)
env.AddToVSProject(env.editor_sources)
add_to_vs_project(env, env.core_sources)
add_to_vs_project(env, env.drivers_sources)
add_to_vs_project(env, env.main_sources)
add_to_vs_project(env, env.modules_sources)
add_to_vs_project(env, env.scene_sources)
add_to_vs_project(env, env.servers_sources)
add_to_vs_project(env, env.editor_sources)
for header in glob_recursive("**/*.h"):
env.vs_incs.append(str(header))
env["MSVSBUILDCOM"] = build_commandline("scons")
env["MSVSREBUILDCOM"] = build_commandline("scons vsproj=yes")

View file

@ -817,6 +817,7 @@
a = [1, 2, 3]
print("a", "b", a) # Prints ab[1, 2, 3]
[/codeblock]
[b]Note:[/b] Consider using [method push_error] and [method push_warning] to print error and warning messages instead of [method print]. This distinguishes them from print messages used for debugging purposes, while also displaying a stack trace when an error or warning is printed.
</description>
</method>
<method name="print_debug" qualifiers="vararg">
@ -890,6 +891,7 @@
[codeblock]
push_error("test error") # Prints "test error" to debugger and terminal as error call
[/codeblock]
[b]Note:[/b] Errors printed this way will not pause project execution. To print an error message and pause project execution in debug builds, use [code]assert(false, "test error")[/code] instead.
</description>
</method>
<method name="push_warning">

View file

@ -2246,8 +2246,15 @@ GDScriptLanguage::~GDScriptLanguage() {
}
// Clear dependencies between scripts, to ensure cyclic references are broken (to avoid leaks at exit).
while (script_list.first()) {
GDScript *script = script_list.first()->self();
SelfList<GDScript> *s = script_list.first();
while (s) {
GDScript *script = s->self();
// This ensures the current script is not released before we can check what's the next one
// in the list (we can't get the next upfront because we don't know if the reference breaking
// will cause it -or any other after it, for that matter- to be released so the next one
// is not the same as before).
script->reference();
for (Map<StringName, GDScriptFunction *>::Element *E = script->member_functions.front(); E; E = E->next()) {
GDScriptFunction *func = E->get();
for (int i = 0; i < func->argument_types.size(); i++) {
@ -2258,6 +2265,9 @@ GDScriptLanguage::~GDScriptLanguage() {
for (Map<StringName, GDScript::MemberInfo>::Element *E = script->member_indices.front(); E; E = E->next()) {
E->get().data_type.script_type_ref = Ref<Script>();
}
s = s->next();
script->unreference();
}
singleton = NULL;

View file

@ -98,6 +98,10 @@ Variant JSONRPC::process_action(const Variant &p_action, bool p_process_arr_elem
if (p_action.get_type() == Variant::DICTIONARY) {
Dictionary dict = p_action;
String method = dict.get("method", "");
if (method.begins_with("$/")) {
return ret;
}
Array args;
if (dict.has("params")) {
Variant params = dict.get("params", Variant());

View file

@ -392,9 +392,8 @@ def configure(env, env_mono):
mono_root = subprocess.check_output(["pkg-config", "mono-2", "--variable=prefix"]).decode("utf8").strip()
if tools_enabled:
# Only supported for editor builds.
copy_mono_root_files(env, mono_root)
else:
print("Ignoring option: 'copy_mono_root'; only available for builds with 'tools' enabled.")
def make_template_dir(env, mono_root):

View file

@ -23,18 +23,16 @@ def configure(env):
envvars.Add(
PathVariable(
"mono_prefix",
"Path to the mono installation directory for the target platform and architecture",
"Path to the Mono installation directory for the target platform and architecture",
"",
PathVariable.PathAccept,
)
)
envvars.Add(BoolVariable("mono_static", "Statically link mono", default_mono_static))
envvars.Add(BoolVariable("mono_glue", "Build with the mono glue sources", True))
envvars.Add(BoolVariable("mono_static", "Statically link Mono", default_mono_static))
envvars.Add(BoolVariable("mono_glue", "Build with the Mono glue sources", True))
envvars.Add(BoolVariable("build_cil", "Build C# solutions", True))
envvars.Add(
BoolVariable(
"copy_mono_root", "Make a copy of the mono installation directory to bundle with the editor", False
)
BoolVariable("copy_mono_root", "Make a copy of the Mono installation directory to bundle with the editor", True)
)
# TODO: It would be great if this could be detected automatically instead

View file

@ -40,7 +40,6 @@
<argument index="0" name="label" type="String">
</argument>
<argument index="1" name="options" type="Dictionary" default="{
}">
</argument>
<description>
@ -82,7 +81,6 @@
<return type="int" enum="Error">
</return>
<argument index="0" name="configuration" type="Dictionary" default="{
}">
</argument>
<description>

View file

@ -47,6 +47,8 @@ protected:
virtual int get_drive_count();
virtual String get_drive(int p_drive);
virtual bool is_hidden(const String &p_name);
};
#endif //UNIX ENABLED

View file

@ -69,4 +69,14 @@ String DirAccessOSX::get_drive(int p_drive) {
return volname;
}
bool DirAccessOSX::is_hidden(const String &p_name) {
String f = get_current_dir().plus_file(p_name);
NSURL *url = [NSURL fileURLWithPath:@(f.utf8().get_data())];
NSNumber *hidden = nil;
if (![url getResourceValue:&hidden forKey:NSURLIsHiddenKey error:nil]) {
return DirAccessUnix::is_hidden(p_name);
}
return [hidden boolValue];
}
#endif //posix_enabled

View file

@ -25,10 +25,10 @@ prog = env.add_program("#bin/godot", common_win + res_obj, PROGSUFFIX=env["PROGS
# Microsoft Visual Studio Project Generation
if env["vsproj"]:
env.vs_srcs = env.vs_srcs + ["platform/windows/" + res_file]
env.vs_srcs = env.vs_srcs + ["platform/windows/godot.natvis"]
env.vs_srcs += ["platform/windows/" + res_file]
env.vs_srcs += ["platform/windows/godot.natvis"]
for x in common_win:
env.vs_srcs = env.vs_srcs + ["platform/windows/" + str(x)]
env.vs_srcs += ["platform/windows/" + str(x)]
if not os.getenv("VCINSTALLDIR"):
if (env["debug_symbols"] == "full" or env["debug_symbols"] == "yes") and env["separate_debug_symbols"]:

View file

@ -109,7 +109,7 @@ void ParallaxBackground::_update_scroll() {
continue;
if (ignore_camera_zoom)
l->set_base_offset_and_scale(ofs, 1.0, screen_offset);
l->set_base_offset_and_scale((ofs + screen_offset * (scale - 1)) / scale, 1.0, screen_offset);
else
l->set_base_offset_and_scale(ofs, scale, screen_offset);
}

View file

@ -2578,10 +2578,10 @@ bool RichTextLabel::search(const String &p_string, bool p_from_selection, bool p
return false;
}
void RichTextLabel::selection_copy() {
if (!selection.active || !selection.enabled)
return;
String RichTextLabel::get_selected_text() {
if (!selection.active || !selection.enabled) {
return "";
}
String text;
@ -2611,6 +2611,12 @@ void RichTextLabel::selection_copy() {
item = _get_next_item(item, true);
}
return text;
}
void RichTextLabel::selection_copy() {
String text = get_selected_text();
if (text != "") {
OS::get_singleton()->set_clipboard(text);
}

View file

@ -473,6 +473,7 @@ public:
void set_selection_enabled(bool p_enabled);
bool is_selection_enabled() const;
String get_selected_text();
void selection_copy();
Error parse_bbcode(const String &p_bbcode);

View file

@ -131,7 +131,7 @@ void Gradient::add_point(float p_offset, const Color &p_color) {
void Gradient::remove_point(int p_index) {
ERR_FAIL_INDEX(p_index, points.size());
ERR_FAIL_COND(points.size() <= 2);
ERR_FAIL_COND(points.size() <= 1);
points.remove(p_index);
emit_signal(CoreStringNames::get_singleton()->changed);
}

View file

@ -1741,6 +1741,9 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
}
for (int i = 0; i < state->get_connection_count(); i++) {
if (i == 0) {
f->store_line("");
}
String connstr = "[connection";
connstr += " signal=\"" + String(state->get_connection_signal(i)) + "\"";
@ -1765,7 +1768,10 @@ Error ResourceFormatSaverTextInstance::save(const String &p_path, const RES &p_r
Vector<NodePath> editable_instances = state->get_editable_instances();
for (int i = 0; i < editable_instances.size(); i++) {
f->store_line("\n[editable path=\"" + editable_instances[i].operator String() + "\"]");
if (i == 0) {
f->store_line("");
}
f->store_line("[editable path=\"" + editable_instances[i].operator String() + "\"]");
}
}

View file

@ -941,7 +941,7 @@ void StyleBoxFlat::_bind_methods() {
ADD_GROUP("Shadow", "shadow_");
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color"), "set_shadow_color", "get_shadow_color");
ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_size"), "set_shadow_size", "get_shadow_size");
ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_size", PROPERTY_HINT_RANGE, "0,100,1,or_greater"), "set_shadow_size", "get_shadow_size");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "shadow_offset"), "set_shadow_offset", "get_shadow_offset");
ADD_GROUP("Anti Aliasing", "anti_aliasing_");

View file

@ -62,6 +62,7 @@ void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2
child_items[i]->ysort_xform = p_transform;
child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]);
child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : NULL;
child_items[i]->ysort_index = r_index;
}
r_index++;

View file

@ -52,6 +52,7 @@ public:
Color ysort_modulate;
Transform2D ysort_xform;
Vector2 ysort_pos;
int ysort_index;
Vector<Item *> child_items;
@ -68,6 +69,7 @@ public:
ysort_children_count = -1;
ysort_xform = Transform2D();
ysort_pos = Vector2();
ysort_index = 0;
}
};
@ -83,8 +85,9 @@ public:
_FORCE_INLINE_ bool operator()(const Item *p_left, const Item *p_right) const {
if (Math::is_equal_approx(p_left->ysort_pos.y, p_right->ysort_pos.y))
return p_left->ysort_pos.x < p_right->ysort_pos.x;
if (Math::is_equal_approx(p_left->ysort_pos.y, p_right->ysort_pos.y)) {
return p_left->ysort_index < p_right->ysort_index;
}
return p_left->ysort_pos.y < p_right->ysort_pos.y;
}