diff options
38 files changed, 613 insertions, 256 deletions
diff --git a/core/math/math_funcs.cpp b/core/math/math_funcs.cpp index 0c06d2a2b5..06355d15ed 100644 --- a/core/math/math_funcs.cpp +++ b/core/math/math_funcs.cpp @@ -30,30 +30,27 @@ #include "math_funcs.h" -#include "core/os/os.h" - -pcg32_random_t Math::default_pcg = { 12047754176567800795ULL, PCG_DEFAULT_INC_64 }; +RandomPCG Math::default_rand(RandomPCG::DEFAULT_SEED, RandomPCG::DEFAULT_INC); #define PHI 0x9e3779b9 -// TODO: we should eventually expose pcg.inc too uint32_t Math::rand_from_seed(uint64_t *seed) { - pcg32_random_t pcg = { *seed, PCG_DEFAULT_INC_64 }; - uint32_t r = pcg32_random_r(&pcg); - *seed = pcg.state; + RandomPCG rng = RandomPCG(*seed, RandomPCG::DEFAULT_INC); + uint32_t r = rng.rand(); + *seed = rng.get_seed(); return r; } void Math::seed(uint64_t x) { - default_pcg.state = x; + default_rand.seed(x); } void Math::randomize() { - seed(OS::get_singleton()->get_ticks_usec() * default_pcg.state + PCG_DEFAULT_INC_64); + default_rand.randomize(); } uint32_t Math::rand() { - return pcg32_random_r(&default_pcg); + return default_rand.rand(); } int Math::step_decimals(double p_step) { @@ -169,13 +166,9 @@ uint32_t Math::larger_prime(uint32_t p_val) { } double Math::random(double from, double to) { - unsigned int r = Math::rand(); - double ret = (double)r / (double)RANDOM_MAX; - return (ret) * (to - from) + from; + return default_rand.random(from, to); } float Math::random(float from, float to) { - unsigned int r = Math::rand(); - float ret = (float)r / (float)RANDOM_MAX; - return (ret) * (to - from) + from; + return default_rand.random(from, to); } diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 65c318448c..f9d89d5d5a 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -32,6 +32,7 @@ #define MATH_FUNCS_H #include "core/math/math_defs.h" +#include "core/math/random_pcg.h" #include "core/typedefs.h" #include "thirdparty/misc/pcg.h" @@ -41,7 +42,7 @@ class Math { - static pcg32_random_t default_pcg; + static RandomPCG default_rand; public: Math() {} // useless to instance diff --git a/core/math/random_number_generator.cpp b/core/math/random_number_generator.cpp new file mode 100644 index 0000000000..e4ec0dac99 --- /dev/null +++ b/core/math/random_number_generator.cpp @@ -0,0 +1,45 @@ +/*************************************************************************/ +/* random_number_generator.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "random_number_generator.h" + +RandomNumberGenerator::RandomNumberGenerator() : + randbase() {} + +void RandomNumberGenerator::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_seed", "seed"), &RandomNumberGenerator::set_seed); + ClassDB::bind_method(D_METHOD("get_seed"), &RandomNumberGenerator::get_seed); + ADD_PROPERTY(PropertyInfo(Variant::INT, "seed"), "set_seed", "get_seed"); + + ClassDB::bind_method(D_METHOD("randi"), &RandomNumberGenerator::randi); + ClassDB::bind_method(D_METHOD("randf"), &RandomNumberGenerator::randf); + ClassDB::bind_method(D_METHOD("rand_range", "from", "to"), &RandomNumberGenerator::rand_range); + ClassDB::bind_method(D_METHOD("randomize"), &RandomNumberGenerator::randomize); +} diff --git a/core/math/random_number_generator.h b/core/math/random_number_generator.h new file mode 100644 index 0000000000..557863fdbd --- /dev/null +++ b/core/math/random_number_generator.h @@ -0,0 +1,61 @@ +/*************************************************************************/ +/* random_number_generator.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RANDOM_NUMBER_GENERATOR_H +#define RANDOM_NUMBER_GENERATOR_H + +#include "core/math/random_pcg.h" +#include "core/reference.h" + +class RandomNumberGenerator : public Reference { + GDCLASS(RandomNumberGenerator, Reference); + + RandomPCG randbase; + +protected: + static void _bind_methods(); + +public: + _FORCE_INLINE_ void set_seed(uint64_t seed) { randbase.seed(seed); } + + _FORCE_INLINE_ uint64_t get_seed() { return randbase.get_seed(); } + + _FORCE_INLINE_ void randomize() { return randbase.randomize(); } + + _FORCE_INLINE_ uint32_t randi() { return randbase.rand(); } + + _FORCE_INLINE_ real_t randf() { return randbase.randf(); } + + _FORCE_INLINE_ real_t rand_range(real_t from, real_t to) { return randbase.random(from, to); } + + RandomNumberGenerator(); +}; + +#endif // RANDOM_NUMBER_GENERATOR_H diff --git a/core/math/random_pcg.cpp b/core/math/random_pcg.cpp new file mode 100644 index 0000000000..16899f79da --- /dev/null +++ b/core/math/random_pcg.cpp @@ -0,0 +1,55 @@ +/*************************************************************************/ +/* random_pcg.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "random_pcg.h" + +#include "core/os/os.h" + +RandomPCG::RandomPCG(uint64_t seed, uint64_t inc) : + pcg() { + pcg.state = seed; + pcg.inc = inc; +} + +void RandomPCG::randomize() { + seed(OS::get_singleton()->get_ticks_usec() * pcg.state + PCG_DEFAULT_INC_64); +} + +double RandomPCG::random(double from, double to) { + unsigned int r = rand(); + double ret = (double)r / (double)RANDOM_MAX; + return (ret) * (to - from) + from; +} + +float RandomPCG::random(float from, float to) { + unsigned int r = rand(); + float ret = (float)r / (float)RANDOM_MAX; + return (ret) * (to - from) + from; +} diff --git a/core/math/random_pcg.h b/core/math/random_pcg.h new file mode 100644 index 0000000000..4a43c36ede --- /dev/null +++ b/core/math/random_pcg.h @@ -0,0 +1,61 @@ +/*************************************************************************/ +/* random_pcg.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RANDOM_PCG_H +#define RANDOM_PCG_H + +#include "core/math/math_defs.h" + +#include "thirdparty/misc/pcg.h" + +class RandomPCG { + pcg32_random_t pcg; + +public: + static const uint64_t DEFAULT_SEED = 12047754176567800795ULL; + static const uint64_t DEFAULT_INC = PCG_DEFAULT_INC_64; + static const uint64_t RANDOM_MAX = 4294967295; + + RandomPCG(uint64_t seed = DEFAULT_SEED, uint64_t inc = PCG_DEFAULT_INC_64); + + _FORCE_INLINE_ void seed(uint64_t seed) { pcg.state = seed; } + _FORCE_INLINE_ uint64_t get_seed() { return pcg.state; } + + void randomize(); + _FORCE_INLINE_ uint32_t rand() { return pcg32_random_r(&pcg); } + _FORCE_INLINE_ double randf() { return (double)rand() / (double)RANDOM_MAX; } + _FORCE_INLINE_ float randd() { return (float)rand() / (float)RANDOM_MAX; } + + double random(double from, double to); + float random(float from, float to); + real_t random(int from, int to) { return (real_t)random((real_t)from, (real_t)to); } +}; + +#endif // RANDOM_PCG_H diff --git a/core/register_core_types.cpp b/core/register_core_types.cpp index 430004bb96..6b776cb0b1 100644 --- a/core/register_core_types.cpp +++ b/core/register_core_types.cpp @@ -55,6 +55,7 @@ #include "core/math/a_star.h" #include "core/math/expression.h" #include "core/math/geometry.h" +#include "core/math/random_number_generator.h" #include "core/math/triangle_mesh.h" #include "core/os/input.h" #include "core/os/main_loop.h" @@ -180,6 +181,7 @@ void register_core_types() { ClassDB::register_virtual_class<PackedDataContainerRef>(); ClassDB::register_class<AStar>(); ClassDB::register_class<EncodedObjectAsID>(); + ClassDB::register_class<RandomNumberGenerator>(); ClassDB::register_class<JSONParseResult>(); diff --git a/doc/classes/KinematicBody.xml b/doc/classes/KinematicBody.xml index 0656341ffa..df8fb251ba 100644 --- a/doc/classes/KinematicBody.xml +++ b/doc/classes/KinematicBody.xml @@ -106,13 +106,13 @@ </argument> <argument index="2" name="floor_normal" type="Vector3" default="Vector3( 0, 0, 0 )"> </argument> - <argument index="3" name="infinite_inertia" type="bool" default="true"> + <argument index="3" name="stop_on_slope" type="bool" default="false"> </argument> - <argument index="4" name="stop_on_slope" type="bool" default="false"> + <argument index="4" name="max_slides" type="int" default="4"> </argument> - <argument index="5" name="max_bounces" type="int" default="4"> + <argument index="5" name="floor_max_angle" type="float" default="0.785398"> </argument> - <argument index="6" name="floor_max_angle" type="float" default="0.785398"> + <argument index="6" name="infinite_inertia" type="bool" default="true"> </argument> <description> Moves the body while keeping it attached to slopes. Similar to [method move_and_slide]. @@ -126,7 +126,7 @@ </argument> <argument index="1" name="rel_vec" type="Vector3"> </argument> - <argument index="2" name="infinite_inertia" type="bool"> + <argument index="2" name="infinite_inertia" type="bool" default="true"> </argument> <description> Checks for collisions without moving the body. Virtually sets the node's position, scale and rotation to that of the given [Transform], then tries to move the body along the vector [code]rel_vec[/code]. Returns [code]true[/code] if a collision would occur. diff --git a/doc/classes/KinematicBody2D.xml b/doc/classes/KinematicBody2D.xml index 6511b2f182..8a644447ca 100644 --- a/doc/classes/KinematicBody2D.xml +++ b/doc/classes/KinematicBody2D.xml @@ -79,20 +79,20 @@ </argument> <argument index="1" name="floor_normal" type="Vector2" default="Vector2( 0, 0 )"> </argument> - <argument index="2" name="infinite_inertia" type="bool" default="true"> + <argument index="2" name="stop_on_slope" type="bool" default="false"> </argument> - <argument index="3" name="stop_on_slope" type="bool" default="false"> + <argument index="3" name="max_slides" type="int" default="4"> </argument> - <argument index="4" name="max_bounces" type="int" default="4"> + <argument index="4" name="floor_max_angle" type="float" default="0.785398"> </argument> - <argument index="5" name="floor_max_angle" type="float" default="0.785398"> + <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 [code]KinematicBody2D[/code] 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. [code]linear_velocity[/code] is a value in pixels per second. Unlike in for example [method move_and_collide], you should [i]not[/i] multiply it with [code]delta[/code] — this is done by the method. [code]floor_normal[/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. [i]TODO: Update for stop_on_slope argument.[/i] If the body is standing on a slope and the horizontal speed (relative to the floor's speed) goes below [code]slope_stop_min_velocity[/code], the body will stop completely. This prevents the body from sliding down slopes when you include gravity in [code]linear_velocity[/code]. When set to lower values, the body will not be able to stand still on steep slopes. - If the body collides, it will change direction a maximum of [code]max_bounces[/code] times before it stops. + If the body collides, it will change direction a maximum of [code]max_slides[/code] times before it stops. [code]floor_max_angle[/code] is the maximum angle (in radians) where a slope is still considered a floor (or a ceiling), rather than a wall. The default value equals 45 degrees. Returns the movement that remained when the body stopped. To get more detailed information about collisions that occurred, use [method get_slide_collision]. </description> @@ -106,13 +106,13 @@ </argument> <argument index="2" name="floor_normal" type="Vector2" default="Vector2( 0, 0 )"> </argument> - <argument index="3" name="infinite_inertia" type="bool" default="true"> + <argument index="3" name="stop_on_slope" type="bool" default="false"> </argument> - <argument index="4" name="stop_on_slope" type="bool" default="false"> + <argument index="4" name="max_slides" type="int" default="4"> </argument> - <argument index="5" name="max_bounces" type="int" default="4"> + <argument index="5" name="floor_max_angle" type="float" default="0.785398"> </argument> - <argument index="6" name="floor_max_angle" type="float" default="0.785398"> + <argument index="6" name="infinite_inertia" type="bool" default="true"> </argument> <description> Moves the body while keeping it attached to slopes. Similar to [method move_and_slide]. @@ -126,7 +126,7 @@ </argument> <argument index="1" name="rel_vec" type="Vector2"> </argument> - <argument index="2" name="infinite_inertia" type="bool"> + <argument index="2" name="infinite_inertia" type="bool" default="true"> </argument> <description> Checks for collisions without moving the body. Virtually sets the node's position, scale and rotation to that of the given [Transform2D], then tries to move the body along the vector [code]rel_vec[/code]. Returns [code]true[/code] if a collision would occur. diff --git a/doc/classes/RandomNumberGenerator.xml b/doc/classes/RandomNumberGenerator.xml new file mode 100644 index 0000000000..55ae356435 --- /dev/null +++ b/doc/classes/RandomNumberGenerator.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="RandomNumberGenerator" inherits="Reference" category="Core" version="3.1"> + <brief_description> + A class for generation pseudo-random numbers. + </brief_description> + <description> + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + <method name="randi"> + <return type="int"> + </return> + <description> + Generates pseudo-random 32-bit integer between '0' and '4294967295'. + </description> + </method> + <method name="randf"> + <return type="float"> + </return> + <description> + Generates pseudo-random float between '0.0' and '1.0'. + </description> + </method> + <method name="rand_range"> + <return type="float"> + </return> + <argument index="0" name="from" type="float"> + </argument> + <argument index="1" name="to" type="float"> + </argument> + <description> + Generates pseudo-random float between [code]from[/code] and [code]to[/code]. + </description> + </method> + <method name="randomize"> + <return type="void"> + </return> + <description> + Setups a time-based seed to generator. + </description> + </method> + </methods> + <members> + <member name="seed" type="int" setter="set_seed" getter="get_seed"> + </member> + </members> + <constants> + </constants> +</class> diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index c4b6c607a2..91280d966a 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -1209,6 +1209,8 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m state.scene_shader.set_uniform(SceneShaderGLES2::SKELETON_TEXTURE_SIZE, p_skeleton_tex_size); + state.current_main_tex = 0; + for (int i = 0; i < tc; i++) { glActiveTexture(GL_TEXTURE0 + i); @@ -1239,6 +1241,9 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m t = t->get_ptr(); glBindTexture(t->target, t->tex_id); + if (i == 0) { + state.current_main_tex = t->tex_id; + } } state.scene_shader.use_material((void *)p_material); diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 5011794735..ff6216cf7a 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -4458,6 +4458,7 @@ void RasterizerStorageGLES2::initialize() { } } + config.keep_original_textures = false; config.shrink_textures_x2 = false; config.float_texture_supported = config.extensions.has("GL_ARB_texture_float") || config.extensions.has("GL_OES_texture_float"); @@ -4605,6 +4606,7 @@ void RasterizerStorageGLES2::initialize() { #endif config.force_vertex_shading = GLOBAL_GET("rendering/quality/shading/force_vertex_shading"); + config.use_fast_texture_filter = GLOBAL_GET("rendering/quality/filters/use_nearest_mipmap_filter"); } void RasterizerStorageGLES2::finalize() { diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index 04a6f72710..c9731011fb 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -60,20 +60,12 @@ public: bool shrink_textures_x2; bool use_fast_texture_filter; - // bool use_anisotropic_filter; - - bool hdr_supported; - - bool use_rgba_2d_shadows; - - // float anisotropic_level; int max_texture_image_units; int max_texture_size; - bool generate_wireframes; - - bool use_texture_array_environment; + // TODO implement wireframe in GLES2 + // bool generate_wireframes; Set<String> extensions; @@ -83,7 +75,6 @@ public: bool keep_original_textures; - bool no_depth_prepass; bool force_vertex_shading; } config; @@ -272,31 +263,28 @@ public: void *detect_normal_ud; Texture() { - flags = 0; - width = 0; - height = 0; alloc_width = 0; alloc_height = 0; - format = Image::FORMAT_L8; - target = 0; - data_size = 0; - total_data_size = 0; + stored_cube_sides = 0; ignore_mipmaps = false; - - compressed = false; - - active = false; - + render_target = NULL; + flags = width = height = 0; tex_id = 0; - - stored_cube_sides = 0; - + data_size = 0; + format = Image::FORMAT_L8; + active = false; + compressed = false; + total_data_size = 0; + mipmaps = 0; + detect_3d = NULL; + detect_3d_ud = NULL; + detect_srgb = NULL; + detect_srgb_ud = NULL; + detect_normal = NULL; + detect_normal_ud = NULL; proxy = NULL; - - render_target = NULL; - redraw_if_visible = false; } diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl index 2a781605d1..c2a4a2d4b3 100644 --- a/drivers/gles2/shaders/scene.glsl +++ b/drivers/gles2/shaders/scene.glsl @@ -247,7 +247,7 @@ void light_compute( float cLdotH = max(dot(L, H), 0.0); float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; float blinn = pow(cNdotH, shininess); - blinn *= (shininess + 8.0) / (8.0 * 3.141592654); + blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); specular_brdf_NL = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75); #endif @@ -1012,9 +1012,7 @@ float G_GGX_2cos(float cos_theta_m, float alpha) { // This approximates G_GGX_2cos(cos_theta_l, alpha) * G_GGX_2cos(cos_theta_v, alpha) // See Filament docs, Specular G section. float V_GGX(float cos_theta_l, float cos_theta_v, float alpha) { - float v = cos_theta_l * (cos_theta_v * (1.0 - alpha) + alpha); - float l = cos_theta_v * (cos_theta_l * (1.0 - alpha) + alpha); - return 0.5 / (v + l); + return 0.5 / mix(2.0 * cos_theta_l * cos_theta_v, cos_theta_l + cos_theta_v, alpha); } float D_GGX(float cos_theta_m, float alpha) { @@ -1126,6 +1124,18 @@ LIGHT_SHADER_CODE float NdotV = dot(N, V); float cNdotV = max(NdotV, 0.0); +#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) + vec3 H = normalize(V + L); +#endif + +#if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) + float cNdotH = max(dot(N, H), 0.0); +#endif + +#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) + float cLdotH = max(dot(L, H), 0.0); +#endif + if (metallic < 1.0) { #if defined(DIFFUSE_OREN_NAYAR) vec3 diffuse_brdf_NL; @@ -1160,13 +1170,9 @@ LIGHT_SHADER_CODE #elif defined(DIFFUSE_BURLEY) { - - vec3 H = normalize(V + L); - float cLdotH = max(0.0, dot(L, H)); - - float FD90 = 0.5 + 2.0 * cLdotH * cLdotH * roughness; - float FdV = 1.0 + (FD90 - 1.0) * SchlickFresnel(cNdotV); - float FdL = 1.0 + (FD90 - 1.0) * SchlickFresnel(cNdotL); + float FD90_minus_1 = 2.0 * cLdotH * cLdotH * roughness - 0.5; + float FdV = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotV); + float FdL = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotL); diffuse_brdf_NL = (1.0 / M_PI) * FdV * FdL * cNdotL; /* float energyBias = mix(roughness, 0.0, 0.5); @@ -1209,13 +1215,9 @@ LIGHT_SHADER_CODE #if defined(SPECULAR_BLINN) //normalized blinn - vec3 H = normalize(V + L); - float cNdotH = max(dot(N, H), 0.0); - float cVdotH = max(dot(V, H), 0.0); - float cLdotH = max(dot(L, H), 0.0); float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; float blinn = pow(cNdotH, shininess); - blinn *= (shininess + 8.0) / (8.0 * 3.141592654); + blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); specular_brdf_NL = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75); #elif defined(SPECULAR_PHONG) @@ -1224,7 +1226,7 @@ LIGHT_SHADER_CODE float cRdotV = max(0.0, dot(R, V)); float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; float phong = pow(cRdotV, shininess); - phong *= (shininess + 8.0) / (8.0 * 3.141592654); + phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); specular_brdf_NL = (phong) / max(4.0 * cNdotV * cNdotL, 0.75); #elif defined(SPECULAR_TOON) @@ -1240,11 +1242,6 @@ LIGHT_SHADER_CODE #elif defined(SPECULAR_SCHLICK_GGX) // shlick+ggx as default - vec3 H = normalize(V + L); - - float cNdotH = max(dot(N, H), 0.0); - float cLdotH = max(dot(L, H), 0.0); - #if defined(LIGHT_USE_ANISOTROPY) float alpha = roughness * roughness; float aspect = sqrt(1.0 - anisotropy * 0.9); @@ -1275,24 +1272,18 @@ LIGHT_SHADER_CODE specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation; #if defined(LIGHT_USE_CLEARCOAT) - if (clearcoat_gloss > 0.0) { -#if !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_BLINN) - vec3 H = normalize(V + L); -#endif + #if !defined(SPECULAR_SCHLICK_GGX) - float cNdotH = max(dot(N, H), 0.0); - float cLdotH = max(dot(L, H), 0.0); - float cLdotH5 = SchlickFresnel(cLdotH); + float cLdotH5 = SchlickFresnel(cLdotH); #endif - float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss)); - float Fr = mix(.04, 1.0, cLdotH5); - //float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25); - float Gr = V_GGX(cNdotL, cNdotV, 0.25); + float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss)); + float Fr = mix(.04, 1.0, cLdotH5); + //float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25); + float Gr = V_GGX(cNdotL, cNdotV, 0.25); - float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL; + float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL; - specular_light += clearcoat_specular_brdf_NL * light_color * specular_blob_intensity * attenuation; - } + specular_light += clearcoat_specular_brdf_NL * light_color * specular_blob_intensity * attenuation; #endif } diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 2f6a556773..41ce5e7c47 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -432,7 +432,6 @@ void RasterizerGLES3::make_current() { void RasterizerGLES3::register_config() { - GLOBAL_DEF("rendering/quality/filters/use_nearest_mipmap_filter", false); GLOBAL_DEF("rendering/quality/filters/anisotropic_filter_level", 4); ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/anisotropic_filter_level", PropertyInfo(Variant::INT, "rendering/quality/filters/anisotropic_filter_level", PROPERTY_HINT_RANGE, "1,16,1")); GLOBAL_DEF("rendering/limits/time/time_rollover_secs", 3600); diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 91ab34f775..66c0631cef 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -949,6 +949,18 @@ LIGHT_SHADER_CODE float NdotV = dot(N, V); float cNdotV = max(NdotV, 0.0); +#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) + vec3 H = normalize(V + L); +#endif + +#if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) + float cNdotH = max(dot(N, H), 0.0); +#endif + +#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_USE_CLEARCOAT) + float cLdotH = max(dot(L, H), 0.0); +#endif + if (metallic < 1.0) { #if defined(DIFFUSE_OREN_NAYAR) vec3 diffuse_brdf_NL; @@ -983,13 +995,9 @@ LIGHT_SHADER_CODE #elif defined(DIFFUSE_BURLEY) { - - vec3 H = normalize(V + L); - float cLdotH = max(0.0, dot(L, H)); - - float FD90 = 0.5 + 2.0 * cLdotH * cLdotH * roughness; - float FdV = 1.0 + (FD90 - 1.0) * SchlickFresnel(cNdotV); - float FdL = 1.0 + (FD90 - 1.0) * SchlickFresnel(cNdotL); + float FD90_minus_1 = 2.0 * cLdotH * cLdotH * roughness - 0.5; + float FdV = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotV); + float FdL = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotL); diffuse_brdf_NL = (1.0 / M_PI) * FdV * FdL * cNdotL; /* float energyBias = mix(roughness, 0.0, 0.5); @@ -1026,13 +1034,9 @@ LIGHT_SHADER_CODE #if defined(SPECULAR_BLINN) //normalized blinn - vec3 H = normalize(V + L); - float cNdotH = max(dot(N, H), 0.0); - float cVdotH = max(dot(V, H), 0.0); - float cLdotH = max(dot(L, H), 0.0); float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; float blinn = pow(cNdotH, shininess); - blinn *= (shininess + 8.0) / (8.0 * 3.141592654); + blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); float intensity = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75); specular_light += light_color * intensity * specular_blob_intensity * attenuation; @@ -1043,7 +1047,7 @@ LIGHT_SHADER_CODE float cRdotV = max(0.0, dot(R, V)); float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; float phong = pow(cRdotV, shininess); - phong *= (shininess + 8.0) / (8.0 * 3.141592654); + phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); float intensity = (phong) / max(4.0 * cNdotV * cNdotL, 0.75); specular_light += light_color * intensity * specular_blob_intensity * attenuation; @@ -1063,11 +1067,6 @@ LIGHT_SHADER_CODE #elif defined(SPECULAR_SCHLICK_GGX) // shlick+ggx as default - vec3 H = normalize(V + L); - - float cNdotH = max(dot(N, H), 0.0); - float cLdotH = max(dot(L, H), 0.0); - #if defined(LIGHT_USE_ANISOTROPY) float alpha = roughness * roughness; @@ -1095,23 +1094,17 @@ LIGHT_SHADER_CODE #endif #if defined(LIGHT_USE_CLEARCOAT) - if (clearcoat_gloss > 0.0) { -#if !defined(SPECULAR_SCHLICK_GGX) && !defined(SPECULAR_BLINN) - vec3 H = normalize(V + L); -#endif + #if !defined(SPECULAR_SCHLICK_GGX) - float cNdotH = max(dot(N, H), 0.0); - float cLdotH = max(dot(L, H), 0.0); - float cLdotH5 = SchlickFresnel(cLdotH); + float cLdotH5 = SchlickFresnel(cLdotH); #endif - float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss)); - float Fr = mix(.04, 1.0, cLdotH5); - float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25); + float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss)); + float Fr = mix(.04, 1.0, cLdotH5); + float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25); - float specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL; + float specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL; - specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation; - } + specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation; #endif } diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index d8cb12543f..dbbf5d08b8 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -3150,34 +3150,33 @@ Ref<Texture> EditorNode::get_object_icon(const Object *p_object, const String &p script = p_object; } - StringName name; - String icon_path; if (script.is_valid()) { - name = EditorNode::get_editor_data().script_class_get_name(script->get_path()); - icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name); - name = script->get_instance_base_type(); + StringName name = EditorNode::get_editor_data().script_class_get_name(script->get_path()); + String icon_path = EditorNode::get_editor_data().script_class_get_icon_path(name); + if (icon_path.length()) + return ResourceLoader::load(icon_path); + + // should probably be deprecated in 4.x + StringName base = script->get_instance_base_type(); + if (base != StringName()) { + const Map<String, Vector<EditorData::CustomType> > &p_map = EditorNode::get_editor_data().get_custom_types(); + for (const Map<String, Vector<EditorData::CustomType> >::Element *E = p_map.front(); E; E = E->next()) { + const Vector<EditorData::CustomType> &ct = E->value(); + for (int i = 0; i < ct.size(); ++i) { + if (ct[i].name == base && ct[i].icon.is_valid()) { + return ct[i].icon; + } + } + } + } } - if (gui_base->has_icon(p_object->get_class(), "EditorIcons")) - return gui_base->get_icon(p_object->get_class(), "EditorIcons"); - - if (icon_path.length()) - return ResourceLoader::load(icon_path); - + // should probably be deprecated in 4.x if (p_object->has_meta("_editor_icon")) return p_object->get_meta("_editor_icon"); - if (name != StringName()) { - const Map<String, Vector<EditorData::CustomType> > &p_map = EditorNode::get_editor_data().get_custom_types(); - for (const Map<String, Vector<EditorData::CustomType> >::Element *E = p_map.front(); E; E = E->next()) { - const Vector<EditorData::CustomType> &ct = E->value(); - for (int i = 0; i < ct.size(); ++i) { - if (ct[i].name == name && ct[i].icon.is_valid()) { - return ct[i].icon; - } - } - } - } + if (gui_base->has_icon(p_object->get_class(), "EditorIcons")) + return gui_base->get_icon(p_object->get_class(), "EditorIcons"); if (p_fallback.length()) return gui_base->get_icon(p_fallback, "EditorIcons"); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index a0763e03f1..1add99bdcc 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -4504,6 +4504,46 @@ void CanvasItemEditor::focus_selection() { CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { + key_pos = true; + key_rot = true; + key_scale = false; + + show_grid = false; + show_origin = true; + show_viewport = true; + show_helpers = false; + show_rulers = true; + show_guides = true; + show_edit_locks = true; + zoom = 1; + view_offset = Point2(-150 - RULER_WIDTH, -95 - RULER_WIDTH); + previous_update_view_offset = view_offset; // Moves the view a little bit to the left so that (0,0) is visible. The values a relative to a 16/10 screen + grid_offset = Point2(); + grid_step = Point2(10, 10); + grid_step_multiplier = 0; + snap_rotation_offset = 0; + snap_rotation_step = 15 / (180 / Math_PI); + snap_active = false; + snap_node_parent = true; + snap_node_anchors = true; + snap_node_sides = true; + snap_node_center = true; + snap_other_nodes = true; + snap_grid = true; + snap_guides = true; + snap_rotation = false; + snap_pixel = false; + + skeleton_show_bones = true; + + drag_type = DRAG_NONE; + drag_from = Vector2(); + drag_to = Vector2(); + dragged_guide_pos = Point2(); + dragged_guide_index = -1; + + bone_last_frame = 0; + bone_list_dirty = false; tool = TOOL_SELECT; undo_redo = p_editor->get_undo_redo(); @@ -4826,49 +4866,11 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { multiply_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/multiply_grid_step", TTR("Multiply grid step by 2"), KEY_KP_MULTIPLY); divide_grid_step_shortcut = ED_SHORTCUT("canvas_item_editor/divide_grid_step", TTR("Divide grid step by 2"), KEY_KP_DIVIDE); - key_pos = true; - key_rot = true; - key_scale = false; - - show_grid = false; - show_origin = true; - show_viewport = true; - show_helpers = false; - show_rulers = true; - show_guides = true; - show_edit_locks = true; - zoom = 1; - view_offset = Point2(-150 - RULER_WIDTH, -95 - RULER_WIDTH); - previous_update_view_offset = view_offset; // Moves the view a little bit to the left so that (0,0) is visible. The values a relative to a 16/10 screen - grid_offset = Point2(); - grid_step = Point2(10, 10); - grid_step_multiplier = 0; - snap_rotation_offset = 0; - snap_rotation_step = 15 / (180 / Math_PI); - snap_active = false; - snap_node_parent = true; - snap_node_anchors = true; - snap_node_sides = true; - snap_node_center = true; - snap_other_nodes = true; - snap_grid = true; - snap_guides = true; - snap_rotation = false; - snap_pixel = false; - skeleton_show_bones = true; skeleton_menu->get_popup()->set_item_checked(skeleton_menu->get_popup()->get_item_index(SKELETON_SHOW_BONES), true); singleton = this; set_process_unhandled_key_input(true); - drag_type = DRAG_NONE; - drag_from = Vector2(); - drag_to = Vector2(); - dragged_guide_pos = Point2(); - dragged_guide_index = -1; - - bone_last_frame = 0; - // Update the menus' checkboxes call_deferred("set_state", get_state()); } diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 59777fb085..f71eb1b605 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -64,7 +64,10 @@ public: Dictionary undo_state; - CanvasItemEditorSelectedItem() { prev_rot = 0; } + CanvasItemEditorSelectedItem() : + prev_anchors() { + prev_rot = 0; + } }; class CanvasItemEditor : public VBoxContainer { diff --git a/editor/plugins/particles_editor_plugin.cpp b/editor/plugins/particles_editor_plugin.cpp index 6b41946918..f2dfae7a9f 100644 --- a/editor/plugins/particles_editor_plugin.cpp +++ b/editor/plugins/particles_editor_plugin.cpp @@ -453,6 +453,7 @@ void ParticlesEditor::_bind_methods() { ParticlesEditor::ParticlesEditor() { + node = NULL; particles_editor_hb = memnew(HBoxContainer); SpatialEditor::get_singleton()->add_control_to_menu_panel(particles_editor_hb); options = memnew(MenuButton); diff --git a/editor/plugins/skeleton_editor_plugin.cpp b/editor/plugins/skeleton_editor_plugin.cpp index e7d9f1b702..8b0beefb3e 100644 --- a/editor/plugins/skeleton_editor_plugin.cpp +++ b/editor/plugins/skeleton_editor_plugin.cpp @@ -151,6 +151,7 @@ void SkeletonEditor::_bind_methods() { } SkeletonEditor::SkeletonEditor() { + skeleton = NULL; options = memnew(MenuButton); SpatialEditor::get_singleton()->add_control_to_menu_panel(options); diff --git a/editor/project_export.cpp b/editor/project_export.cpp index 27d8bd97fb..f8ba6fd4e3 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -946,6 +946,7 @@ void ProjectExportDialog::_bind_methods() { ClassDB::bind_method("_export_pck_zip_selected", &ProjectExportDialog::_export_pck_zip_selected); ClassDB::bind_method("_open_export_template_manager", &ProjectExportDialog::_open_export_template_manager); ClassDB::bind_method("_validate_export_path", &ProjectExportDialog::_validate_export_path); + ClassDB::bind_method("_export_path_changed", &ProjectExportDialog::_export_path_changed); ClassDB::bind_method("_export_project", &ProjectExportDialog::_export_project); ClassDB::bind_method("_export_project_to_path", &ProjectExportDialog::_export_project_to_path); ClassDB::bind_method("_export_all", &ProjectExportDialog::_export_all); diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index ba9837ef6e..089ffa285d 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -467,7 +467,6 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da String type = p_data[1]; Array properties = p_data[2]; - bool is_new_object = false; if (remote_objects.has(id)) { debugObj = remote_objects[id]; } else { @@ -475,7 +474,6 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da debugObj->remote_object_id = id; debugObj->type_name = type; remote_objects[id] = debugObj; - is_new_object = true; debugObj->connect("value_edited", this, "_scene_tree_property_value_edited"); } diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 1d26700fa0..09b3a5631f 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -4840,6 +4840,21 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { tokenizer->advance(); if (tokenizer->is_token_literal(0, true)) { enum_name = tokenizer->get_token_literal(); + + if (current_class->constant_expressions.has(enum_name)) { + _set_error("A constant named '" + String(enum_name) + "' already exists in this class (at line: " + + itos(current_class->constant_expressions[enum_name].expression->line) + ")."); + return; + } + + for (int i = 0; i < current_class->variables.size(); i++) { + if (current_class->variables[i].identifier == enum_name) { + _set_error("A variable named '" + String(enum_name) + "' already exists in this class (at line: " + + itos(current_class->variables[i].line) + ")."); + return; + } + } + tokenizer->advance(); } if (tokenizer->get_token() != GDScriptTokenizer::TK_CURLY_BRACKET_OPEN) { @@ -4866,26 +4881,12 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { return; } else { // tokenizer->is_token_literal(0, true) - ClassNode::Constant constant; - StringName const_id = tokenizer->get_token_literal(); - if (current_class->constant_expressions.has(const_id)) { - _set_error("A constant named '" + String(const_id) + "' already exists in this class (at line: " + - itos(current_class->constant_expressions[const_id].expression->line) + ")."); - return; - } - - for (int i = 0; i < current_class->variables.size(); i++) { - if (current_class->variables[i].identifier == const_id) { - _set_error("A variable named '" + String(const_id) + "' already exists in this class (at line: " + - itos(current_class->variables[i].line) + ")."); - return; - } - } - tokenizer->advance(); + ConstantNode *enum_value_expr; + if (tokenizer->get_token() == GDScriptTokenizer::TK_OP_ASSIGN) { tokenizer->advance(); @@ -4902,23 +4903,20 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { return; } - ConstantNode *subexpr_const = static_cast<ConstantNode *>(subexpr); + enum_value_expr = static_cast<ConstantNode *>(subexpr); - if (subexpr_const->value.get_type() != Variant::INT) { + if (enum_value_expr->value.get_type() != Variant::INT) { _set_error("Expected an int value for enum"); return; } - last_assign = subexpr_const->value; - - constant.expression = subexpr_const; + last_assign = enum_value_expr->value; } else { last_assign = last_assign + 1; - ConstantNode *cn = alloc_node<ConstantNode>(); - cn->value = last_assign; - cn->datatype = _type_from_variant(cn->value); - constant.expression = cn; + enum_value_expr = alloc_node<ConstantNode>(); + enum_value_expr->value = last_assign; + enum_value_expr->datatype = _type_from_variant(enum_value_expr->value); } if (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) { @@ -4926,14 +4924,29 @@ void GDScriptParser::_parse_class(ClassNode *p_class) { } if (enum_name != "") { - const ConstantNode *cn = static_cast<const ConstantNode *>(constant.expression); - enum_dict[const_id] = cn->value; - } + enum_dict[const_id] = enum_value_expr->value; + } else { + if (current_class->constant_expressions.has(const_id)) { + _set_error("A constant named '" + String(const_id) + "' already exists in this class (at line: " + + itos(current_class->constant_expressions[const_id].expression->line) + ")."); + return; + } - constant.type.has_type = true; - constant.type.kind = DataType::BUILTIN; - constant.type.builtin_type = Variant::INT; - p_class->constant_expressions.insert(const_id, constant); + for (int i = 0; i < current_class->variables.size(); i++) { + if (current_class->variables[i].identifier == const_id) { + _set_error("A variable named '" + String(const_id) + "' already exists in this class (at line: " + + itos(current_class->variables[i].line) + ")."); + return; + } + } + + ClassNode::Constant constant; + constant.type.has_type = true; + constant.type.kind = DataType::BUILTIN; + constant.type.builtin_type = Variant::INT; + constant.expression = enum_value_expr; + p_class->constant_expressions.insert(const_id, constant); + } } } diff --git a/platform/x11/detect.py b/platform/x11/detect.py index dc5c22b4b3..e257a20bdd 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -149,7 +149,7 @@ def configure(env): env.Append(CCFLAGS=['-pipe']) env.Append(LINKFLAGS=['-pipe']) - # Check for gcc version > 4 before adding -no-pie + # Check for gcc version > 5 before adding -no-pie import re import subprocess proc = subprocess.Popen([env['CXX'], '--version'], stdout=subprocess.PIPE) @@ -157,7 +157,7 @@ def configure(env): match = re.search('[0-9][0-9.]*', stdout) if match is not None: version = match.group().split('.') - if (version[0] > '4'): + if (version[0] > '5'): env.Append(CCFLAGS=['-fpie']) env.Append(LINKFLAGS=['-no-pie']) diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 33c5fef151..929b4624ee 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -1226,7 +1226,7 @@ bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_ //so, if you pass 45 as limit, avoid numerical precision erros when angle is 45. #define FLOOR_ANGLE_THRESHOLD 0.01 -Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, bool p_infinite_inertia, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle) { +Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { Vector2 floor_motion = floor_velocity; if (on_floor && on_floor_body.is_valid()) { @@ -1237,7 +1237,8 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const } } - Vector2 motion = (floor_motion + p_linear_velocity) * get_physics_process_delta_time(); + // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky + Vector2 motion = (floor_motion + p_linear_velocity) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time()); Vector2 lv = p_linear_velocity; on_floor = false; @@ -1332,11 +1333,11 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const return lv; } -Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_floor_direction, bool p_infinite_inertia, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle) { +Vector2 KinematicBody2D::move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { bool was_on_floor = on_floor; - Vector2 ret = move_and_slide(p_linear_velocity, p_floor_direction, p_infinite_inertia, p_stop_on_slope, p_max_slides, p_floor_max_angle); + Vector2 ret = move_and_slide(p_linear_velocity, p_floor_direction, p_stop_on_slope, p_max_slides, p_floor_max_angle, p_infinite_inertia); if (!was_on_floor || p_snap == Vector2()) { return ret; } @@ -1470,10 +1471,10 @@ void KinematicBody2D::_notification(int p_what) { void KinematicBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "exclude_raycast_shapes", "test_only"), &KinematicBody2D::_move, DEFVAL(true), DEFVAL(true), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "infinite_inertia", "stop_on_slope", "max_bounces", "floor_max_angle"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(true), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45))); - ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "floor_normal", "infinite_inertia", "stop_on_slope", "max_bounces", "floor_max_angle"), &KinematicBody2D::move_and_slide_with_snap, DEFVAL(Vector2(0, 0)), DEFVAL(true), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45))); + ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody2D::move_and_slide, DEFVAL(Vector2(0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "floor_normal", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody2D::move_and_slide_with_snap, DEFVAL(Vector2(0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); - ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody2D::test_move); + ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody2D::test_move, DEFVAL(true)); ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody2D::is_on_floor); ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody2D::is_on_ceiling); diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index ddd55f7b7f..c7b42add84 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -332,15 +332,15 @@ protected: public: bool move_and_collide(const Vector2 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes = true, bool p_test_only = false); - bool test_move(const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia); + bool test_move(const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia = true); bool separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision); void set_safe_margin(float p_margin); float get_safe_margin() const; - Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction = Vector2(0, 0), bool p_infinite_inertia = true, bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45)); - Vector2 move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_floor_direction = Vector2(0, 0), bool p_infinite_inertia = true, bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45)); + Vector2 move_and_slide(const Vector2 &p_linear_velocity, const Vector2 &p_floor_direction = Vector2(0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); + Vector2 move_and_slide_with_snap(const Vector2 &p_linear_velocity, const Vector2 &p_snap, const Vector2 &p_floor_direction = Vector2(0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); bool is_on_floor() const; bool is_on_wall() const; bool is_on_ceiling() const; diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 038d816951..9148b436a0 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -1167,7 +1167,8 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve } } - Vector3 motion = (floor_velocity + lv) * get_physics_process_delta_time(); + // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky + Vector3 motion = (floor_velocity + lv) * (Engine::get_singleton()->is_in_physics_frame() ? get_physics_process_delta_time() : get_process_delta_time()); on_floor = false; on_ceiling = false; @@ -1266,7 +1267,7 @@ Vector3 KinematicBody::move_and_slide(const Vector3 &p_linear_velocity, const Ve return lv; } -Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_floor_direction, bool p_infinite_inertia, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle) { +Vector3 KinematicBody::move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_floor_direction, bool p_stop_on_slope, int p_max_slides, float p_floor_max_angle, bool p_infinite_inertia) { bool was_on_floor = on_floor; @@ -1402,9 +1403,9 @@ void KinematicBody::_bind_methods() { ClassDB::bind_method(D_METHOD("move_and_collide", "rel_vec", "infinite_inertia", "test_only"), &KinematicBody::_move, DEFVAL(true), DEFVAL(false)); ClassDB::bind_method(D_METHOD("move_and_slide", "linear_velocity", "floor_normal", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); - ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "floor_normal", "infinite_inertia", "stop_on_slope", "max_bounces", "floor_max_angle"), &KinematicBody::move_and_slide_with_snap, DEFVAL(Vector3(0, 0, 0)), DEFVAL(true), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45))); + ClassDB::bind_method(D_METHOD("move_and_slide_with_snap", "linear_velocity", "snap", "floor_normal", "stop_on_slope", "max_slides", "floor_max_angle", "infinite_inertia"), &KinematicBody::move_and_slide_with_snap, DEFVAL(Vector3(0, 0, 0)), DEFVAL(false), DEFVAL(4), DEFVAL(Math::deg2rad((float)45)), DEFVAL(true)); - ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody::test_move); + ClassDB::bind_method(D_METHOD("test_move", "from", "rel_vec", "infinite_inertia"), &KinematicBody::test_move, DEFVAL(true)); ClassDB::bind_method(D_METHOD("is_on_floor"), &KinematicBody::is_on_floor); ClassDB::bind_method(D_METHOD("is_on_ceiling"), &KinematicBody::is_on_ceiling); diff --git a/scene/3d/physics_body.h b/scene/3d/physics_body.h index fa319e6fbb..20d948b6eb 100644 --- a/scene/3d/physics_body.h +++ b/scene/3d/physics_body.h @@ -329,7 +329,7 @@ public: float get_safe_margin() const; Vector3 move_and_slide(const Vector3 &p_linear_velocity, const Vector3 &p_floor_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); - Vector3 move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_floor_direction = Vector3(0, 0, 0), bool p_infinite_inertia = true, bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45)); + Vector3 move_and_slide_with_snap(const Vector3 &p_linear_velocity, const Vector3 &p_snap, const Vector3 &p_floor_direction = Vector3(0, 0, 0), bool p_stop_on_slope = false, int p_max_slides = 4, float p_floor_max_angle = Math::deg2rad((float)45), bool p_infinite_inertia = true); bool is_on_floor() const; bool is_on_wall() const; bool is_on_ceiling() const; diff --git a/scene/audio/audio_player.cpp b/scene/audio/audio_player.cpp index 64af7efb16..1d9d048fe1 100644 --- a/scene/audio/audio_player.cpp +++ b/scene/audio/audio_player.cpp @@ -219,6 +219,7 @@ void AudioStreamPlayer::seek(float p_seconds) { void AudioStreamPlayer::stop() { if (stream_playback.is_valid()) { + stream_playback->stop(); active = false; set_process_internal(false); } diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 004455c6a9..f621522102 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -1425,6 +1425,7 @@ PopupMenu::PopupMenu() { set_hide_on_item_selection(true); set_hide_on_checkable_item_selection(true); set_hide_on_multistate_item_selection(false); + set_hide_on_window_lose_focus(true); submenu_timer = memnew(Timer); submenu_timer->set_wait_time(0.3); diff --git a/scene/resources/scene_format_text.cpp b/scene/resources/scene_format_text.cpp index f287b43fbe..5ae843f2bd 100644 --- a/scene/resources/scene_format_text.cpp +++ b/scene/resources/scene_format_text.cpp @@ -626,14 +626,14 @@ Error ResourceInteractiveLoaderText::poll() { if (!packed_scene.is_valid()) return error; - error = OK; + error = ERR_FILE_EOF; //get it here resource = packed_scene; if (!ResourceCache::has(res_path)) { packed_scene->set_path(res_path); } - return ERR_FILE_EOF; + return error; } else { error_text += "Unknown tag in file: " + next_tag.name; diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index b41fcac8fa..33d1e72669 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -1017,7 +1017,7 @@ void AudioServer::update() { void AudioServer::load_default_bus_layout() { - if (FileAccess::exists("res://default_bus_layout.tres")) { + if (ResourceLoader::exists("res://default_bus_layout.tres")) { Ref<AudioBusLayout> default_layout = ResourceLoader::load("res://default_bus_layout.tres"); if (default_layout.is_valid()) { set_bus_layout(default_layout); diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index e2db89e699..3fe661090c 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -691,6 +691,30 @@ String ShaderLanguage::token_debug(const String &p_code) { return output; } +bool ShaderLanguage::is_token_variable_datatype(TokenType p_type) { + return ( + p_type == TK_TYPE_VOID || + p_type == TK_TYPE_BOOL || + p_type == TK_TYPE_BVEC2 || + p_type == TK_TYPE_BVEC3 || + p_type == TK_TYPE_BVEC4 || + p_type == TK_TYPE_INT || + p_type == TK_TYPE_IVEC2 || + p_type == TK_TYPE_IVEC3 || + p_type == TK_TYPE_IVEC4 || + p_type == TK_TYPE_UINT || + p_type == TK_TYPE_UVEC2 || + p_type == TK_TYPE_UVEC3 || + p_type == TK_TYPE_UVEC4 || + p_type == TK_TYPE_FLOAT || + p_type == TK_TYPE_VEC2 || + p_type == TK_TYPE_VEC3 || + p_type == TK_TYPE_VEC4 || + p_type == TK_TYPE_MAT2 || + p_type == TK_TYPE_MAT3 || + p_type == TK_TYPE_MAT4); +} + bool ShaderLanguage::is_token_datatype(TokenType p_type) { return ( @@ -3563,6 +3587,11 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui } } + if (!is_token_variable_datatype(tk.type)) { + _set_error("Invalid data type for variable (samplers not allowed)"); + return ERR_PARSE_ERROR; + } + DataType type = get_token_datatype(tk.type); tk = _get_token(); @@ -4218,6 +4247,11 @@ Error ShaderLanguage::_parse_shader(const Map<StringName, FunctionInfo> &p_funct return ERR_PARSE_ERROR; } + if (!is_token_variable_datatype(tk.type)) { + _set_error("Invalid data type for function return (samplers not allowed)"); + return ERR_PARSE_ERROR; + } + type = get_token_datatype(tk.type); _get_completable_identifier(NULL, COMPLETION_MAIN_FUNCTION, name); diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index 08c4d06992..f07b1fade5 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -534,6 +534,7 @@ public: static String get_token_text(Token p_token); static bool is_token_datatype(TokenType p_type); + static bool is_token_variable_datatype(TokenType p_type); static DataType get_token_datatype(TokenType p_type); static bool is_token_interpolation(TokenType p_type); static DataInterpolation get_token_interpolation(TokenType p_type); diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp index 84b7504ad4..74a05ce4e4 100644 --- a/servers/visual/visual_server_canvas.cpp +++ b/servers/visual/visual_server_canvas.cpp @@ -51,6 +51,23 @@ void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Tra } } +void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item **r_items, Transform2D *r_extra_transforms, int &r_index) { + int child_item_count = p_canvas_item->child_items.size(); + VisualServerCanvas::Item **child_items = p_canvas_item->child_items.ptrw(); + for (int i = 0; i < child_item_count; i++) { + if (r_items) { + r_items[r_index] = child_items[i]; + child_items[i]->ysort_xform = p_transform; + child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]); + } + + r_index++; + + if (child_items[i]->sort_y) + _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, r_items, r_extra_transforms, r_index); + } +} + void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner) { Item *ci = p_canvas_item; @@ -58,10 +75,10 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor if (!ci->visible) return; - if (p_canvas_item->children_order_dirty) { + if (ci->children_order_dirty) { - p_canvas_item->child_items.sort_custom<ItemIndexSort>(); - p_canvas_item->children_order_dirty = false; + ci->child_items.sort_custom<ItemIndexSort>(); + ci->children_order_dirty = false; } Rect2 rect = ci->get_rect(); @@ -82,8 +99,8 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor return; int child_item_count = ci->child_items.size(); - Item **child_items = (Item **)alloca(child_item_count * sizeof(Item *)); - copymem(child_items, ci->child_items.ptr(), child_item_count * sizeof(Item *)); + Item **child_items = ci->child_items.ptrw(); + Transform2D *child_extra_transforms = NULL; if (ci->clip) { if (p_canvas_clip != NULL) { @@ -99,6 +116,17 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor if (ci->sort_y) { + if (ci->ysort_children_count == -1) { + ci->ysort_children_count = 0; + _collect_ysort_children(ci, Transform2D(), NULL, NULL, ci->ysort_children_count); + } + + child_item_count = ci->ysort_children_count; + child_items = (Item **)alloca(child_item_count * sizeof(Item *)); + + int i = 0; + _collect_ysort_children(ci, Transform2D(), child_items, child_extra_transforms, i); + SortArray<Item *, ItemPtrSort> sorter; sorter.sort(child_items, child_item_count); } @@ -110,9 +138,13 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor for (int i = 0; i < child_item_count; i++) { - if (!child_items[i]->behind) + if (!child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y)) continue; - _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); + if (ci->sort_y) { + _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); + } else { + _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); + } } if (ci->copy_back_buffer) { @@ -148,9 +180,13 @@ void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item, const Transfor for (int i = 0; i < child_item_count; i++) { - if (child_items[i]->behind) + if (child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y)) continue; - _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); + if (ci->sort_y) { + _render_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); + } else { + _render_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); + } } } @@ -300,6 +336,7 @@ void VisualServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) { Item *item_owner = canvas_item_owner.get(canvas_item->parent); item_owner->child_items.erase(canvas_item); + item_owner->ysort_children_count = -1; } canvas_item->parent = RID(); @@ -319,6 +356,12 @@ void VisualServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) { item_owner->child_items.push_back(canvas_item); item_owner->children_order_dirty = true; + Item *ysort_owner = item_owner; + while (ysort_owner && ysort_owner->sort_y) { + item_owner->ysort_children_count = -1; + ysort_owner = canvas_item_owner.getornull(ysort_owner->parent); + } + } else { ERR_EXPLAIN("Invalid parent"); @@ -826,6 +869,7 @@ void VisualServerCanvas::canvas_item_set_sort_children_by_y(RID p_item, bool p_e ERR_FAIL_COND(!canvas_item); canvas_item->sort_y = p_enable; + canvas_item->ysort_children_count = -1; } void VisualServerCanvas::canvas_item_set_z_index(RID p_item, int p_z) { diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h index d12bd520bf..4b7422b15a 100644 --- a/servers/visual/visual_server_canvas.h +++ b/servers/visual/visual_server_canvas.h @@ -48,6 +48,9 @@ public: bool use_parent_material; int index; bool children_order_dirty; + int ysort_children_count; + Transform2D ysort_xform; + Vector2 ysort_pos; Vector<Item *> child_items; @@ -61,6 +64,9 @@ public: use_parent_material = false; z_relative = true; index = 0; + ysort_children_count = -1; + ysort_xform = Transform2D(); + ysort_pos = Vector2(); } }; @@ -76,10 +82,10 @@ public: _FORCE_INLINE_ bool operator()(const Item *p_left, const Item *p_right) const { - if (Math::abs(p_left->xform.elements[2].y - p_right->xform.elements[2].y) < CMP_EPSILON) - return p_left->xform.elements[2].x < p_right->xform.elements[2].x; + if (Math::abs(p_left->ysort_pos.y - p_right->ysort_pos.y) < CMP_EPSILON) + return p_left->ysort_pos.x < p_right->ysort_pos.x; else - return p_left->xform.elements[2].y < p_right->xform.elements[2].y; + return p_left->ysort_pos.y < p_right->ysort_pos.y; } }; diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 4b0e5cd28d..c1460ea4a9 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -2401,6 +2401,8 @@ VisualServer::VisualServer() { GLOBAL_DEF("rendering/quality/depth_prepass/enable", true); GLOBAL_DEF("rendering/quality/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno"); + + GLOBAL_DEF("rendering/quality/filters/use_nearest_mipmap_filter", false); } VisualServer::~VisualServer() { |