summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/classes/ARVRAnchor.xml6
-rw-r--r--doc/classes/ARVRCamera.xml6
-rw-r--r--doc/classes/ARVRController.xml6
-rw-r--r--doc/classes/ARVROrigin.xml2
-rw-r--r--doc/classes/Curve3D.xml4
-rw-r--r--doc/classes/KinematicBody2D.xml2
-rw-r--r--doc/classes/OrientedPathFollow.xml40
-rw-r--r--doc/classes/PathFollow.xml3
-rw-r--r--drivers/gles2/rasterizer_canvas_gles2.cpp32
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.cpp18
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.cpp1
-rw-r--r--drivers/gles3/rasterizer_canvas_gles3.cpp18
-rw-r--r--editor/editor_node.cpp17
-rw-r--r--editor/editor_node.h2
-rw-r--r--editor/editor_properties.cpp2
-rw-r--r--editor/editor_resource_preview.cpp15
-rw-r--r--editor/editor_resource_preview.h2
-rw-r--r--editor/icons/icon_oriented_path_follow.svg5
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp4
-rw-r--r--editor/plugins/item_list_editor_plugin.cpp2
-rw-r--r--editor/scene_tree_dock.cpp14
-rw-r--r--main/splash_editor.pngbin37619 -> 39571 bytes
-rw-r--r--main/tests/test_math.cpp23
-rw-r--r--modules/csg/csg_shape.cpp4
-rw-r--r--modules/gdscript/gdscript_compiler.cpp4
-rw-r--r--modules/gdscript/gdscript_editor.cpp6
-rw-r--r--modules/gdscript/gdscript_function.h10
-rw-r--r--modules/gdscript/gdscript_parser.cpp65
-rw-r--r--modules/gdscript/gdscript_parser.h2
-rw-r--r--modules/webm/libvpx/SCsub4
-rw-r--r--platform/android/SCsub2
-rw-r--r--platform/android/detect.py19
-rw-r--r--platform/android/export/export.cpp7
-rw-r--r--platform/iphone/detect.py2
-rw-r--r--scene/2d/canvas_item.cpp1
-rw-r--r--scene/2d/light_2d.cpp2
-rw-r--r--scene/2d/polygon_2d.cpp3
-rw-r--r--scene/2d/tile_map.cpp5
-rw-r--r--scene/3d/audio_stream_player_3d.cpp7
-rw-r--r--scene/3d/cpu_particles.cpp11
-rw-r--r--scene/3d/path.cpp300
-rw-r--r--scene/3d/path.h48
-rw-r--r--scene/3d/voxel_light_baker.cpp5
-rw-r--r--scene/animation/animation_blend_space_1d.cpp2
-rw-r--r--scene/gui/line_edit.cpp4
-rw-r--r--scene/gui/scroll_container.cpp1
-rw-r--r--scene/gui/text_edit.cpp1
-rw-r--r--scene/gui/tree.cpp3
-rw-r--r--scene/main/http_request.cpp3
-rw-r--r--scene/register_scene_types.cpp1
-rw-r--r--scene/resources/animation.cpp2
-rw-r--r--scene/resources/curve.cpp32
-rw-r--r--scene/resources/shape_2d.cpp16
-rw-r--r--scene/resources/shape_2d.h4
-rw-r--r--servers/visual/rasterizer.h2
-rw-r--r--servers/visual/visual_server_canvas.cpp1
56 files changed, 289 insertions, 514 deletions
diff --git a/doc/classes/ARVRAnchor.xml b/doc/classes/ARVRAnchor.xml
index fa93d9668c..5b9188b171 100644
--- a/doc/classes/ARVRAnchor.xml
+++ b/doc/classes/ARVRAnchor.xml
@@ -5,8 +5,8 @@
</brief_description>
<description>
The ARVR Anchor point is a spatial node that maps a real world location identified by the AR platform to a position within the game world. For example, as long as plane detection in ARKit is on, ARKit will identify and update the position of planes (tables, floors, etc) and create anchors for them.
- This node is mapped to one of the anchors through its unique id. When you receive a signal that a new anchor is available you should add this node to your scene for that anchor. You can predefine nodes and set the id and the nodes will simply remain on 0,0,0 until a plane is recognised.
- Keep in mind that as long as plane detection is enable the size, placing and orientation of an anchor will be updates as the detection logic learns more about the real world out there especially if only part of the surface is in view.
+ This node is mapped to one of the anchors through its unique id. When you receive a signal that a new anchor is available, you should add this node to your scene for that anchor. You can predefine nodes and set the id and the nodes will simply remain on 0,0,0 until a plane is recognised.
+ Keep in mind that, as long as plane detection is enabled, the size, placing and orientation of an anchor will be updated as the detection logic learns more about the real world out there especially if only part of the surface is in view.
</description>
<tutorials>
</tutorials>
@@ -31,7 +31,7 @@
<return type="Plane">
</return>
<description>
- Returns a plane aligned with our anchor, handy for intersection testing
+ Returns a plane aligned with our anchor; handy for intersection testing.
</description>
</method>
<method name="get_size" qualifiers="const">
diff --git a/doc/classes/ARVRCamera.xml b/doc/classes/ARVRCamera.xml
index e74b435e11..aca8282a7c 100644
--- a/doc/classes/ARVRCamera.xml
+++ b/doc/classes/ARVRCamera.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8" ?>
<class name="ARVRCamera" inherits="Camera" category="Core" version="3.1">
<brief_description>
- A camera node with a few overrules for AR/VR applied such as location tracking.
+ A camera node with a few overrules for AR/VR applied, such as location tracking.
</brief_description>
<description>
- This is a helper spatial node for our camera, note that if stereoscopic rendering is applicable (VR-HMD) most of the camera properties are ignored as the HMD information overrides them. The only properties that can be trusted are the near and far planes.
- The position and orientation of this node is automatically updated by the ARVR Server to represent the location of the HMD if such tracking is available and can thus be used by game logic. Note that in contrast to the ARVR Controller the render thread has access to the most up to date tracking data of the HMD and the location of the ARVRCamera can lag a few milliseconds behind what is used for rendering as a result.
+ This is a helper spatial node for our camera; note that, if stereoscopic rendering is applicable (VR-HMD), most of the camera properties are ignored, as the HMD information overrides them. The only properties that can be trusted are the near and far planes.
+ The position and orientation of this node is automatically updated by the ARVR Server to represent the location of the HMD if such tracking is available and can thus be used by game logic. Note that, in contrast to the ARVR Controller, the render thread has access to the most up-to-date tracking data of the HMD and the location of the ARVRCamera can lag a few milliseconds behind what is used for rendering as a result.
</description>
<tutorials>
</tutorials>
diff --git a/doc/classes/ARVRController.xml b/doc/classes/ARVRController.xml
index d3d6fce537..ccb55375d2 100644
--- a/doc/classes/ARVRController.xml
+++ b/doc/classes/ARVRController.xml
@@ -4,8 +4,8 @@
A spatial node representing a spatially tracked controller.
</brief_description>
<description>
- This is a helper spatial node that is linked to the tracking of controllers. It also offers several handy pass throughs to the state of buttons and such on the controllers.
- Controllers are linked by their id. You can create controller nodes before the controllers are available. Say your game always uses two controllers (one for each hand) you can predefine the controllers with id 1 and 2 and they will become active as soon as the controllers are identified. If you expect additional controllers to be used you should react to the signals and add ARVRController nodes to your scene.
+ This is a helper spatial node that is linked to the tracking of controllers. It also offers several handy passthroughs to the state of buttons and such on the controllers.
+ Controllers are linked by their id. You can create controller nodes before the controllers are available. Say your game always uses two controllers (one for each hand) you can predefine the controllers with id 1 and 2 and they will become active as soon as the controllers are identified. If you expect additional controllers to be used, you should react to the signals and add ARVRController nodes to your scene.
The position of the controller node is automatically updated by the ARVR Server. This makes this node ideal to add child nodes to visualise the controller.
</description>
<tutorials>
@@ -64,7 +64,7 @@
<member name="controller_id" type="int" setter="set_controller_id" getter="get_controller_id">
The controller's id.
A controller id of 0 is unbound and will always result in an inactive node. Controller id 1 is reserved for the first controller that identifies itself as the left hand controller and id 2 is reserved for the first controller that identifies itself as the right hand controller.
- For any other controller that the [ARVRServer] detects we continue with controller id 3.
+ For any other controller that the [ARVRServer] detects, we continue with controller id 3.
When a controller is turned off, its slot is freed. This ensures controllers will keep the same id even when controllers with lower ids are turned off.
</member>
<member name="rumble" type="float" setter="set_rumble" getter="get_rumble">
diff --git a/doc/classes/ARVROrigin.xml b/doc/classes/ARVROrigin.xml
index 80626338f2..55062ba3ae 100644
--- a/doc/classes/ARVROrigin.xml
+++ b/doc/classes/ARVROrigin.xml
@@ -6,7 +6,7 @@
<description>
This is a special node within the AR/VR system that maps the physical location of the center of our tracking space to the virtual location within our game world.
There should be only one of these nodes in your scene and you must have one. All the ARVRCamera, ARVRController and ARVRAnchor nodes should be direct children of this node for spatial tracking to work correctly.
- It is the position of this node that you update when you're character needs to move through your game world while we're not moving in the real world. Movement in the real world is always in relation to this origin point.
+ It is the position of this node that you update when your character needs to move through your game world while we're not moving in the real world. Movement in the real world is always in relation to this origin point.
So say that your character is driving a car, the ARVROrigin node should be a child node of this car. If you implement a teleport system to move your character, you change the position of this node. Etc.
</description>
<tutorials>
diff --git a/doc/classes/Curve3D.xml b/doc/classes/Curve3D.xml
index b2e64f96a6..e9ee1c6974 100644
--- a/doc/classes/Curve3D.xml
+++ b/doc/classes/Curve3D.xml
@@ -225,7 +225,7 @@
</argument>
<description>
Sets the tilt angle in radians for the point [code]idx[/code]. If the index is out of bounds, the function sends an error to the console.
- The tilt controls the rotation along the look-at axis an object traveling the path would have. In the case of a curve controlling a [PathFollow] or [OrientedPathFollow], this tilt is an offset over the natural tilt the [PathFollow] or [OrientedPathFollow] calculates.
+ The tilt controls the rotation along the look-at axis an object traveling the path would have. In the case of a curve controlling a [PathFollow], this tilt is an offset over the natural tilt the [PathFollow] calculates.
</description>
</method>
<method name="tessellate" qualifiers="const">
@@ -248,7 +248,7 @@
The distance in meters between two adjacent cached points. Changing it forces the cache to be recomputed the next time the [method get_baked_points] or [method get_baked_length] function is called. The smaller the distance, the more points in the cache and the more memory it will consume, so use with care.
</member>
<member name="up_vector_enabled" type="bool" setter="set_up_vector_enabled" getter="is_up_vector_enabled">
- If [code]true[/code], the curve will bake up vectors used for orientation. See [OrientedPathFollow]. Changing it forces the cache to be recomputed.
+ If [code]true[/code], the curve will bake up vectors used for orientation. This is used when a [member PathFollow.rotation_mode] is set to [code]ROTATION_ORIENTED[/code], see [PathFollow] for details. Changing it forces the cache to be recomputed.
</member>
</members>
<constants>
diff --git a/doc/classes/KinematicBody2D.xml b/doc/classes/KinematicBody2D.xml
index 12d2bcec77..986010f832 100644
--- a/doc/classes/KinematicBody2D.xml
+++ b/doc/classes/KinematicBody2D.xml
@@ -94,7 +94,7 @@
[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_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].
+ Returns the [code]linear_velocity[/code] vector, rotated and/or scaled if a slide collision occurred. To get more detailed information about collisions that occurred, use [method get_slide_collision].
</description>
</method>
<method name="move_and_slide_with_snap">
diff --git a/doc/classes/OrientedPathFollow.xml b/doc/classes/OrientedPathFollow.xml
deleted file mode 100644
index 665e3af6b2..0000000000
--- a/doc/classes/OrientedPathFollow.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<class name="OrientedPathFollow" inherits="Spatial" category="Core" version="3.1">
- <brief_description>
- Oriented point sampler for a [Path].
- </brief_description>
- <description>
- This node behaves like [PathFollow], except it uses its parent [Path] up vector information to enforce orientation.
- Make sure to check if the curve of this node's parent [Path] has up vectors enabled. See [PathFollow] and [Curve3D] for further information.
- </description>
- <tutorials>
- </tutorials>
- <demos>
- </demos>
- <methods>
- </methods>
- <members>
- <member name="cubic_interp" type="bool" setter="set_cubic_interpolation" getter="get_cubic_interpolation">
- If [code]true[/code], the position between two cached points is interpolated cubically, and linearly otherwise.
- The points along the [Curve3D] of the [Path] are precomputed before use, for faster calculations. The point at the requested offset is then calculated interpolating between two adjacent cached points. This may present a problem if the curve makes sharp turns, as the cached points may not follow the curve closely enough.
- There are two answers to this problem: Either increase the number of cached points and increase memory consumption, or make a cubic interpolation between two points at the cost of (slightly) slower calculations.
- </member>
- <member name="h_offset" type="float" setter="set_h_offset" getter="get_h_offset">
- The node's offset along the curve.
- </member>
- <member name="loop" type="bool" setter="set_loop" getter="has_loop">
- If [code]true[/code], any offset outside the path's length will wrap around, instead of stopping at the ends. Use it for cyclic paths.
- </member>
- <member name="offset" type="float" setter="set_offset" getter="get_offset">
- The distance from the first vertex, measured in 3D units along the path. This sets this node's position to a point within the path.
- </member>
- <member name="unit_offset" type="float" setter="set_unit_offset" getter="get_unit_offset">
- The distance from the first vertex, considering 0.0 as the first vertex and 1.0 as the last. This is just another way of expressing the offset within the path, as the offset supplied is multiplied internally by the path's length.
- </member>
- <member name="v_offset" type="float" setter="set_v_offset" getter="get_v_offset">
- The node's offset perpendicular to the curve.
- </member>
- </members>
- <constants>
- </constants>
-</class>
diff --git a/doc/classes/PathFollow.xml b/doc/classes/PathFollow.xml
index ed4a805a00..da4782a7c3 100644
--- a/doc/classes/PathFollow.xml
+++ b/doc/classes/PathFollow.xml
@@ -51,5 +51,8 @@
<constant name="ROTATION_XYZ" value="3" enum="RotationMode">
Allows the PathFollow to rotate in any axis.
</constant>
+ <constant name="ROTATION_ORIENTED" value="4" enum="RotationMode">
+ Uses the up vector information in a [Curve3D] to enforce orientation. This rotation mode requires the [Path]'s [member Curve3D.up_vector_enabled] property to be set to [code]true[/code].
+ </constant>
</constants>
</class>
diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp
index 14bd71c6eb..e6ec6fb4fd 100644
--- a/drivers/gles2/rasterizer_canvas_gles2.cpp
+++ b/drivers/gles2/rasterizer_canvas_gles2.cpp
@@ -93,6 +93,7 @@ void RasterizerCanvasGLES2::_set_uniforms() {
glBindTexture(GL_TEXTURE_2D, cls->distance);
state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_MATRIX, light->shadow_matrix_cache);
state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_SHADOW_COLOR, light->shadow_color);
+
state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOWPIXEL_SIZE, (1.0 / light->shadow_buffer_size) * (1.0 + light->shadow_smooth));
if (light->radius_cache == 0) {
state.canvas_shader.set_uniform(CanvasShaderGLES2::SHADOW_GRADIENT, 0.0);
@@ -1303,6 +1304,14 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
t = t->get_ptr();
+#ifdef TOOLS_ENABLED
+ if (t->detect_normal && texture_hints[i] == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL) {
+ t->detect_normal(t->detect_normal_ud);
+ }
+#endif
+ if (t->render_target)
+ t->render_target->used_in_frame = true;
+
if (t->redraw_if_visible) {
VisualServerRaster::redraw_request();
}
@@ -1438,25 +1447,20 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons
state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS, has_shadow);
if (has_shadow) {
state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_USE_GRADIENT, light->shadow_gradient_length > 0);
- switch (light->shadow_filter) {
-
- case VS::CANVAS_LIGHT_FILTER_NONE: state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_NEAREST, true); break;
- case VS::CANVAS_LIGHT_FILTER_PCF3: state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF3, true); break;
- case VS::CANVAS_LIGHT_FILTER_PCF5: state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF5, true); break;
- case VS::CANVAS_LIGHT_FILTER_PCF7: state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF7, true); break;
- case VS::CANVAS_LIGHT_FILTER_PCF9: state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF9, true); break;
- case VS::CANVAS_LIGHT_FILTER_PCF13: state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF13, true); break;
- }
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_NEAREST, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_NONE);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF3, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF3);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF5, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF5);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF7, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF7);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF9, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF9);
+ state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF13, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF13);
}
- bool light_rebind = state.canvas_shader.bind();
+ state.canvas_shader.bind();
state.using_light = light;
state.using_shadow = has_shadow;
- if (light_rebind) {
-
- _set_uniforms();
- }
+ //always re-set uniforms, since light parameters changed
+ _set_uniforms();
glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4);
RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(light->texture);
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp
index d9f1fe1212..e4783e907b 100644
--- a/drivers/gles2/rasterizer_scene_gles2.cpp
+++ b/drivers/gles2/rasterizer_scene_gles2.cpp
@@ -1245,6 +1245,24 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m
t = t->get_ptr();
+ if (t->redraw_if_visible) { //must check before proxy because this is often used with proxies
+ VisualServerRaster::redraw_request();
+ }
+
+#ifdef TOOLS_ENABLED
+ if (t->detect_3d) {
+ t->detect_3d(t->detect_3d_ud);
+ }
+#endif
+
+#ifdef TOOLS_ENABLED
+ if (t->detect_normal && texture_hints[i] == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL) {
+ t->detect_normal(t->detect_normal_ud);
+ }
+#endif
+ if (t->render_target)
+ t->render_target->used_in_frame = true;
+
glBindTexture(t->target, t->tex_id);
if (i == 0) {
state.current_main_tex = t->tex_id;
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index aef12b58d2..af698f3988 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -4204,6 +4204,7 @@ void RasterizerStorageGLES2::render_target_set_msaa(RID p_render_target, VS::Vie
RID RasterizerStorageGLES2::canvas_light_shadow_buffer_create(int p_width) {
CanvasLightShadow *cls = memnew(CanvasLightShadow);
+
if (p_width > config.max_texture_size)
p_width = config.max_texture_size;
diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp
index 06b84aeab4..79fec63db0 100644
--- a/drivers/gles3/rasterizer_canvas_gles3.cpp
+++ b/drivers/gles3/rasterizer_canvas_gles3.cpp
@@ -158,7 +158,10 @@ void RasterizerCanvasGLES3::canvas_begin() {
state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_LIGHTING, false);
state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SHADOWS, false);
state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_NEAREST, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF3, false);
state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF5, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF7, false);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF9, false);
state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13, false);
state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD, false);
state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_NINEPATCH, false);
@@ -1558,15 +1561,12 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons
state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SHADOWS, has_shadow);
if (has_shadow) {
state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_USE_GRADIENT, light->shadow_gradient_length > 0);
- switch (light->shadow_filter) {
-
- case VS::CANVAS_LIGHT_FILTER_NONE: state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_NEAREST, true); break;
- case VS::CANVAS_LIGHT_FILTER_PCF3: state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF3, true); break;
- case VS::CANVAS_LIGHT_FILTER_PCF5: state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF5, true); break;
- case VS::CANVAS_LIGHT_FILTER_PCF7: state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF7, true); break;
- case VS::CANVAS_LIGHT_FILTER_PCF9: state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF9, true); break;
- case VS::CANVAS_LIGHT_FILTER_PCF13: state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13, true); break;
- }
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_NEAREST, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_NONE);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF3, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF3);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF5, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF5);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF7, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF7);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF9, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF9);
+ state.canvas_shader.set_conditional(CanvasShaderGLES3::SHADOW_FILTER_PCF13, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF13);
}
bool light_rebind = state.canvas_shader.bind();
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 9169227e8a..719130621e 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -494,7 +494,7 @@ void EditorNode::_fs_changed() {
}
}
- get_tree()->quit();
+ _exit_editor();
}
}
@@ -1120,7 +1120,7 @@ void EditorNode::save_all_scenes_and_restart() {
to_reopen = get_tree()->get_edited_scene_root()->get_filename();
}
- get_tree()->quit();
+ _exit_editor();
String exec = OS::get_singleton()->get_executable_path();
List<String> args;
@@ -2356,6 +2356,12 @@ int EditorNode::_next_unsaved_scene(bool p_valid_filename, int p_start) {
return -1;
}
+void EditorNode::_exit_editor() {
+ exiting = true;
+ resource_preview->stop(); //stop early to avoid crashes
+ get_tree()->quit();
+}
+
void EditorNode::_discard_changes(const String &p_str) {
switch (current_option) {
@@ -2383,14 +2389,13 @@ void EditorNode::_discard_changes(const String &p_str) {
case FILE_QUIT: {
_menu_option_confirm(RUN_STOP, true);
- exiting = true;
- get_tree()->quit();
+ _exit_editor();
+
} break;
case RUN_PROJECT_MANAGER: {
_menu_option_confirm(RUN_STOP, true);
- exiting = true;
- get_tree()->quit();
+ _exit_editor();
String exec = OS::get_singleton()->get_executable_path();
List<String> args;
diff --git a/editor/editor_node.h b/editor/editor_node.h
index d7d969fb16..13bebea5f0 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -470,6 +470,8 @@ private:
void _dropped_files(const Vector<String> &p_files, int p_screen);
String _recent_scene;
+ void _exit_editor();
+
bool convert_old;
void _unhandled_input(const Ref<InputEvent> &p_event);
diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp
index 72545f6b19..e33b26d9cb 100644
--- a/editor/editor_properties.cpp
+++ b/editor/editor_properties.cpp
@@ -2397,7 +2397,7 @@ void EditorPropertyResource::_update_menu() {
void EditorPropertyResource::_sub_inspector_property_keyed(const String &p_property, const Variant &p_value, bool) {
- emit_signal("property_keyed_with_value", String(get_edited_property()) + ":" + p_property, p_value);
+ emit_signal("property_keyed_with_value", String(get_edited_property()) + ":" + p_property, p_value, false);
}
void EditorPropertyResource::_sub_inspector_resource_selected(const RES &p_resource, const String &p_property) {
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index 25139b0163..368efbc48f 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -416,6 +416,16 @@ void EditorResourcePreview::check_for_invalidation(const String &p_path) {
}
}
+void EditorResourcePreview::stop() {
+ if (thread) {
+ exit = true;
+ preview_sem->post();
+ Thread::wait_to_finish(thread);
+ memdelete(thread);
+ thread = NULL;
+ }
+}
+
EditorResourcePreview::EditorResourcePreview() {
singleton = this;
preview_mutex = Mutex::create();
@@ -428,10 +438,7 @@ EditorResourcePreview::EditorResourcePreview() {
EditorResourcePreview::~EditorResourcePreview() {
- exit = true;
- preview_sem->post();
- Thread::wait_to_finish(thread);
- memdelete(thread);
+ stop();
memdelete(preview_mutex);
memdelete(preview_sem);
}
diff --git a/editor/editor_resource_preview.h b/editor/editor_resource_preview.h
index 055ecc6bbf..85ac78d58f 100644
--- a/editor/editor_resource_preview.h
+++ b/editor/editor_resource_preview.h
@@ -126,6 +126,8 @@ public:
void remove_preview_generator(const Ref<EditorResourcePreviewGenerator> &p_generator);
void check_for_invalidation(const String &p_path);
+ void stop();
+
EditorResourcePreview();
~EditorResourcePreview();
};
diff --git a/editor/icons/icon_oriented_path_follow.svg b/editor/icons/icon_oriented_path_follow.svg
deleted file mode 100644
index bd3f585e54..0000000000
--- a/editor/icons/icon_oriented_path_follow.svg
+++ /dev/null
@@ -1,5 +0,0 @@
-<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
-<g transform="translate(0 -1036.4)">
-<path transform="translate(0 1036.4)" d="m13 0l-3 4h1.9473c-0.1385 1.3203-0.5583 1.9074-1.084 2.2754-0.64426 0.451-1.7129 0.60547-2.9629 0.73047s-2.6814 0.22053-3.9121 1.082c-0.89278 0.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -0.84961 -1.6328c0.19235-0.88496 0.55306-1.3373 0.98633-1.6406 0.64426-0.451 1.7129-0.60547 2.9629-0.73047s2.6814-0.22053 3.9121-1.082c1.0528-0.73697 1.7552-2.032 1.9375-3.9141h2.0508l-3-4z" fill="#fc9c9c" fill-opacity=".99608"/>
-</g>
-</svg>
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index b0e812a130..86d6799b19 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -573,10 +573,10 @@ bool CanvasItemEditor::_get_bone_shape(Vector<Vector2> *shape, Vector<Vector2> *
Node2D *from_node = Object::cast_to<Node2D>(ObjectDB::get_instance(bone->key().from));
Node2D *to_node = Object::cast_to<Node2D>(ObjectDB::get_instance(bone->key().to));
- if (!from_node->is_inside_tree())
- return false; //may have been removed
if (!from_node)
return false;
+ if (!from_node->is_inside_tree())
+ return false; //may have been removed
if (!to_node && bone->get().length == 0)
return false;
diff --git a/editor/plugins/item_list_editor_plugin.cpp b/editor/plugins/item_list_editor_plugin.cpp
index d9861c91e0..db0816064c 100644
--- a/editor/plugins/item_list_editor_plugin.cpp
+++ b/editor/plugins/item_list_editor_plugin.cpp
@@ -109,7 +109,7 @@ void ItemListPlugin::_get_property_list(List<PropertyInfo> *p_list) const {
int flags = get_flags();
if (flags & FLAG_CHECKABLE) {
- p_list->push_back(PropertyInfo(Variant::BOOL, base + "checkable", PROPERTY_HINT_ENUM, "No,As checkbox,As radio button"));
+ p_list->push_back(PropertyInfo(Variant::INT, base + "checkable", PROPERTY_HINT_ENUM, "No,As checkbox,As radio button"));
p_list->push_back(PropertyInfo(Variant::BOOL, base + "checked"));
}
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index daa7f92dcf..be1c4a36bd 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -563,6 +563,20 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) {
if (node == root)
return;
+ //check that from node to root, all owners are right
+
+ if (node->get_owner() != root) {
+ accept->set_text(TTR("Node must belong to the edited scene to become root."));
+ accept->popup_centered_minsize();
+ return;
+ }
+
+ if (node->get_filename() != String()) {
+ accept->set_text(TTR("Instantiated scenes can't become root"));
+ accept->popup_centered_minsize();
+ return;
+ }
+
editor_data->get_undo_redo().create_action("Make node as Root");
editor_data->get_undo_redo().add_do_method(node->get_parent(), "remove_child", node);
editor_data->get_undo_redo().add_do_method(root->get_parent(), "remove_child", root);
diff --git a/main/splash_editor.png b/main/splash_editor.png
index d5bc2f1ce6..d8677f1749 100644
--- a/main/splash_editor.png
+++ b/main/splash_editor.png
Binary files differ
diff --git a/main/tests/test_math.cpp b/main/tests/test_math.cpp
index c833bac4ab..a082abcaba 100644
--- a/main/tests/test_math.cpp
+++ b/main/tests/test_math.cpp
@@ -444,14 +444,11 @@ MainLoop *test() {
float bb = (rgbe >> 18) & 0x1ff;
float eb = (rgbe >> 27);
float mb = Math::pow(2, eb - 15.0 - 9.0);
- ;
float rd = rb * mb;
float gd = gb * mb;
float bd = bb * mb;
print_line("RGBE: " + Color(rd, gd, bd));
-
- return NULL;
}
print_line("Dvectors: " + itos(MemoryPool::allocs_used));
@@ -482,8 +479,6 @@ MainLoop *test() {
print_line("later Mem used: " + itos(MemoryPool::total_memory));
print_line("Mlater Ax mem used: " + itos(MemoryPool::max_memory));
- return NULL;
-
List<String> cmdlargs = OS::get_singleton()->get_cmdline_args();
if (cmdlargs.empty()) {
@@ -492,6 +487,11 @@ MainLoop *test() {
}
String test = cmdlargs.back()->get();
+ if (test == "math") {
+ // Not a file name but the test name, abort.
+ // FIXME: This test is ugly as heck, needs fixing :)
+ return NULL;
+ }
FileAccess *fa = FileAccess::open(test, FileAccess::READ);
@@ -516,8 +516,6 @@ MainLoop *test() {
print_line("Found class: " + getclass.get_class());
}
- return NULL;
-
{
Vector<int> hashes;
@@ -557,13 +555,10 @@ MainLoop *test() {
}
print_line("DONE");
-
- return NULL;
}
- {
+ {
print_line("NUM: " + itos(-128));
- return NULL;
}
{
@@ -593,7 +588,6 @@ MainLoop *test() {
print_line("after v: " + v + " a: " + rtos(a));
}
- return NULL;
String ret;
List<String> args;
@@ -602,7 +596,6 @@ MainLoop *test() {
print_line("error: " + itos(err));
print_line(ret);
- return NULL;
Basis m3;
m3.rotate(Vector3(1, 0, 0), 0.2);
m3.rotate(Vector3(0, 1, 0), 1.77);
@@ -611,17 +604,13 @@ MainLoop *test() {
m32.set_euler(m3.get_euler());
print_line("ELEULEEEEEEEEEEEEEEEEEER: " + m3.get_euler() + " vs " + m32.get_euler());
- return NULL;
-
{
-
Dictionary d;
d["momo"] = 1;
Dictionary b = d;
b["44"] = 4;
}
- return NULL;
print_line("inters: " + rtos(Geometry::segment_intersects_circle(Vector2(-5, 0), Vector2(-2, 0), Vector2(), 1.0)));
print_line("cross: " + Vector3(1, 2, 3).cross(Vector3(4, 5, 7)));
diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp
index 809fd841c1..a13f731c11 100644
--- a/modules/csg/csg_shape.cpp
+++ b/modules/csg/csg_shape.cpp
@@ -1132,9 +1132,9 @@ CSGBrush *CSGBox::_build_brush() {
for (int k = 0; k < 3; k++) {
if (i < 3)
- face_points[j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1);
+ face_points[j][(i + k) % 3] = v[k];
else
- face_points[3 - j][(i + k) % 3] = v[k] * (i >= 3 ? -1 : 1);
+ face_points[3 - j][(i + k) % 3] = -v[k];
}
}
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 2b6b66d7b6..e59b57b39a 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -486,7 +486,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
script = codegen.script;
} else {
StringName name = cn->cast_type.class_type->name;
- if (class_map[name] == codegen.script->subclasses[name]) {
+ if (codegen.script->subclasses.has(name) && class_map[name] == codegen.script->subclasses[name]) {
idx = codegen.get_name_map_pos(name);
idx |= GDScriptFunction::ADDR_TYPE_CLASS_CONSTANT << GDScriptFunction::ADDR_BITS;
} else {
@@ -1183,7 +1183,7 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser::
script = codegen.script;
} else {
StringName name = assign_type.class_type->name;
- if (class_map[name] == codegen.script->subclasses[name]) {
+ if (codegen.script->subclasses.has(name) && class_map[name] == codegen.script->subclasses[name]) {
idx = codegen.get_name_map_pos(name);
idx |= GDScriptFunction::ADDR_TYPE_CLASS_CONSTANT << GDScriptFunction::ADDR_BITS;
} else {
diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp
index 64678c7240..08ad101967 100644
--- a/modules/gdscript/gdscript_editor.cpp
+++ b/modules/gdscript/gdscript_editor.cpp
@@ -1181,7 +1181,11 @@ static bool _guess_identifier_type(const GDScriptCompletionContext &p_context, c
c.line = op->line;
c.block = blk;
if (_guess_expression_type(p_context, op->arguments[1], r_type)) {
- r_type.type.is_meta_type = false;
+ r_type.type.is_meta_type = false; // Right-hand of `is` will be a meta type, but the left-hand value is not
+ // Not an assignment, it shouldn't carry any value
+ r_type.value = Variant();
+ r_type.assigned_expression = NULL;
+
return true;
}
}
diff --git a/modules/gdscript/gdscript_function.h b/modules/gdscript/gdscript_function.h
index aab1af1250..f4058664ff 100644
--- a/modules/gdscript/gdscript_function.h
+++ b/modules/gdscript/gdscript_function.h
@@ -74,8 +74,14 @@ struct GDScriptDataType {
return false;
}
Object *obj = p_variant.operator Object *();
- if (obj && !ClassDB::is_parent_class(obj->get_class_name(), native_type)) {
- return false;
+ if (obj) {
+ if (!ClassDB::is_parent_class(obj->get_class_name(), native_type)) {
+ // Try with underscore prefix
+ StringName underscore_native_type = "_" + native_type;
+ if (!ClassDB::is_parent_class(obj->get_class_name(), underscore_native_type)) {
+ return false;
+ }
+ }
}
return true;
} break;
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp
index b0743af1b4..a012ccad30 100644
--- a/modules/gdscript/gdscript_parser.cpp
+++ b/modules/gdscript/gdscript_parser.cpp
@@ -4559,6 +4559,10 @@ void GDScriptParser::_parse_class(ClassNode *p_class) {
member.line = tokenizer->get_token_line();
member.usages = 0;
member.rpc_mode = rpc_mode;
+#ifdef TOOLS_ENABLED
+ Variant::CallError ce;
+ member.default_value = Variant::construct(member._export.type, NULL, 0, ce);
+#endif
if (current_class->constant_expressions.has(member.identifier)) {
_set_error("A constant named '" + String(member.identifier) + "' already exists in this class (at line: " +
@@ -5058,7 +5062,7 @@ void GDScriptParser::_determine_inheritance(ClassNode *p_class) {
if (ScriptServer::is_global_class(base)) {
base_script = ResourceLoader::load(ScriptServer::get_global_class_path(base));
if (!base_script.is_valid()) {
- _set_error("Class '" + base + "' could not be fully loaded (script error or cyclic inheritance).", p_class->line);
+ _set_error("Class '" + base + "' could not be fully loaded (script error or cyclic dependency).", p_class->line);
return;
}
p = NULL;
@@ -5387,7 +5391,7 @@ GDScriptParser::DataType GDScriptParser::_resolve_type(const DataType &p_source,
Ref<GDScript> gds = script;
if (gds.is_valid()) {
if (!gds->is_valid()) {
- _set_error("Class '" + id + "' could not be fully loaded (script error or cyclic inheritance).", p_line);
+ _set_error("Class '" + id + "' could not be fully loaded (script error or cyclic dependency).", p_line);
return DataType();
}
result.kind = DataType::GDSCRIPT;
@@ -5932,7 +5936,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
int idx = current_function->arguments.find(id->name);
node_type = current_function->argument_types[idx];
} else {
- node_type = _reduce_identifier_type(NULL, id->name, id->line);
+ node_type = _reduce_identifier_type(NULL, id->name, id->line, false);
}
} break;
case Node::TYPE_CAST: {
@@ -6182,7 +6186,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
result.is_constant = false;
node_type = result;
} else {
- node_type = _reduce_identifier_type(&base_type, member_id->name, op->line);
+ node_type = _reduce_identifier_type(&base_type, member_id->name, op->line, true);
#ifdef DEBUG_ENABLED
if (!node_type.has_type) {
_add_warning(GDScriptWarning::UNSAFE_PROPERTY_ACCESS, op->line, member_id->name.operator String(), base_type.to_string());
@@ -6224,7 +6228,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_node_type(Node *p_node) {
if (check_types && index_type.has_type) {
if (base_type.kind == DataType::BUILTIN) {
// Check if indexing is valid
- bool error = index_type.kind != DataType::BUILTIN;
+ bool error = index_type.kind != DataType::BUILTIN && base_type.builtin_type != Variant::DICTIONARY;
if (!error) {
switch (base_type.builtin_type) {
// Expect int or real as index
@@ -6767,10 +6771,10 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
valid = _get_function_signature(base_type, callee_name, return_type, arg_types,
default_args_count, is_static, is_vararg);
- if (valid) {
- return_type = original_type;
- return_type.is_meta_type = false;
- }
+ return_type = original_type;
+ return_type.is_meta_type = false;
+
+ valid = true; // There's always an initializer, we can asume this is true
}
if (!valid) {
@@ -6829,6 +6833,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
} break;
}
+#ifdef DEBUG_ENABLED
if (!check_types) {
return return_type;
}
@@ -6854,11 +6859,9 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
if (!par_type.has_type) {
_mark_line_as_unsafe(p_call->line);
-#ifdef DEBUG_ENABLED
if (par_type.may_yield && p_call->arguments[i]->type == Node::TYPE_OPERATOR) {
_add_warning(GDScriptWarning::FUNCTION_MAY_YIELD, p_call->line, _find_function_name(static_cast<OperatorNode *>(p_call->arguments[i])));
}
-#endif // DEBUG_ENABLED
} else if (!_is_type_compatible(arg_types[i - arg_diff], par_type, true)) {
// Supertypes are acceptable for dynamic compliance
if (!_is_type_compatible(par_type, arg_types[i - arg_diff])) {
@@ -6871,14 +6874,14 @@ GDScriptParser::DataType GDScriptParser::_reduce_function_call_type(const Operat
_mark_line_as_unsafe(p_call->line);
}
} else {
-#ifdef DEBUG_ENABLED
if (arg_type.kind == DataType::BUILTIN && arg_type.builtin_type == Variant::INT && par_type.kind == DataType::BUILTIN && par_type.builtin_type == Variant::REAL) {
_add_warning(GDScriptWarning::NARROWING_CONVERSION, p_call->line, callee_name);
}
-#endif // DEBUG_ENABLED
}
}
+#endif // DEBUG_ENABLED
+
return return_type;
}
@@ -6899,9 +6902,9 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN
if (!base_type.is_meta_type) {
for (int i = 0; i < base->variables.size(); i++) {
- ClassNode::Member m = base->variables[i];
- if (m.identifier == p_member) {
- r_member_type = m.data_type;
+ if (base->variables[i].identifier == p_member) {
+ r_member_type = base->variables[i].data_type;
+ base->variables.write[i].usages += 1;
return true;
}
}
@@ -7096,43 +7099,33 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN
return false;
}
-GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType *p_base_type, const StringName &p_identifier, int p_line) {
+GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType *p_base_type, const StringName &p_identifier, int p_line, bool p_is_indexing) {
if (p_base_type && !p_base_type->has_type) {
return DataType();
}
DataType base_type;
+ DataType member_type;
- // Check classes in current file
- ClassNode *base = NULL;
if (!p_base_type) {
- base = current_class;
base_type.has_type = true;
base_type.is_constant = true;
base_type.kind = DataType::CLASS;
- base_type.class_type = base;
+ base_type.class_type = current_class;
} else {
base_type = DataType(*p_base_type);
- if (base_type.kind == DataType::CLASS) {
- base = base_type.class_type;
- }
- }
-
- DataType member_type;
-
- for (int i = 0; i < current_class->variables.size(); i++) {
- if (current_class->variables[i].identifier == p_identifier) {
- member_type = current_class->variables[i].data_type;
- current_class->variables.write[i].usages += 1;
- return member_type;
- }
}
if (_get_member_type(base_type, p_identifier, member_type)) {
return member_type;
}
+ if (p_is_indexing) {
+ // Don't look for globals since this is an indexed identifier
+ return DataType();
+ }
+
if (!p_base_type) {
// Possibly this is a global, check before failing
@@ -7190,7 +7183,7 @@ GDScriptParser::DataType GDScriptParser::_reduce_identifier_type(const DataType
Ref<GDScript> gds = scr;
if (gds.is_valid()) {
if (!gds->is_valid()) {
- _set_error("Class '" + p_identifier + "' could not be fully loaded (script error or cyclic inheritance).");
+ _set_error("Class '" + p_identifier + "' could not be fully loaded (script error or cyclic dependency).");
return DataType();
}
result.kind = DataType::GDSCRIPT;
@@ -8110,6 +8103,7 @@ Error GDScriptParser::_parse(const String &p_base_path) {
check_types = false;
#endif
+#ifdef DEBUG_ENABLED
// Resolve all class-level stuff before getting into function blocks
_check_class_level_types(main_class);
@@ -8124,7 +8118,6 @@ Error GDScriptParser::_parse(const String &p_base_path) {
return ERR_PARSE_ERROR;
}
-#ifdef DEBUG_ENABLED
// Resolve warning ignores
Vector<Pair<int, String> > warning_skips = tokenizer->get_warning_skips();
bool warning_is_error = GLOBAL_GET("debug/gdscript/warnings/treat_warnings_as_errors").booleanize();
diff --git a/modules/gdscript/gdscript_parser.h b/modules/gdscript/gdscript_parser.h
index 63e02ddc6a..b4a705c9e7 100644
--- a/modules/gdscript/gdscript_parser.h
+++ b/modules/gdscript/gdscript_parser.h
@@ -607,7 +607,7 @@ private:
DataType _reduce_node_type(Node *p_node);
DataType _reduce_function_call_type(const OperatorNode *p_call);
- DataType _reduce_identifier_type(const DataType *p_base_type, const StringName &p_identifier, int p_line);
+ DataType _reduce_identifier_type(const DataType *p_base_type, const StringName &p_identifier, int p_line, bool p_is_indexing);
void _check_class_level_types(ClassNode *p_class);
void _check_class_blocks_types(ClassNode *p_class);
void _check_function_types(FunctionNode *p_function);
diff --git a/modules/webm/libvpx/SCsub b/modules/webm/libvpx/SCsub
index df75dca310..2639d20620 100644
--- a/modules/webm/libvpx/SCsub
+++ b/modules/webm/libvpx/SCsub
@@ -272,9 +272,9 @@ else:
import platform
is_x11_or_server_arm = ((env["platform"] == 'x11' or env["platform"] == 'server') and (platform.machine().startswith('arm') or platform.machine().startswith('aarch')))
is_ios_x86 = (env["platform"] == 'iphone' and ("arch" in env and env["arch"].startswith('x86')))
- is_android_x86 = (env["platform"] == 'android' and env["android_arch"] == 'x86')
+ is_android_x86 = (env["platform"] == 'android' and env["android_arch"].startswith('x86'))
if is_android_x86:
- cpu_bits = '32'
+ cpu_bits = '32' if env["android_arch"] == 'x86' else '64'
webm_cpu_x86 = not is_x11_or_server_arm and (cpu_bits == '32' or cpu_bits == '64') and (env["platform"] == 'windows' or env["platform"] == 'x11' or env["platform"] == 'osx' or env["platform"] == 'haiku' or is_android_x86 or is_ios_x86)
webm_cpu_arm = is_x11_or_server_arm or (not is_ios_x86 and env["platform"] == 'iphone') or (not is_android_x86 and env["platform"] == 'android')
diff --git a/platform/android/SCsub b/platform/android/SCsub
index ad682b9324..47d5035224 100644
--- a/platform/android/SCsub
+++ b/platform/android/SCsub
@@ -152,6 +152,8 @@ elif env['android_arch'] == 'arm64v8':
lib_arch_dir = 'arm64-v8a'
elif env['android_arch'] == 'x86':
lib_arch_dir = 'x86'
+elif env['android_arch'] == 'x86_64':
+ lib_arch_dir = 'x86_64'
else:
print('WARN: Architecture not suitable for embedding into APK; keeping .so at \\bin')
diff --git a/platform/android/detect.py b/platform/android/detect.py
index b031e51d8c..aa48252435 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -27,7 +27,7 @@ def get_opts():
return [
('ANDROID_NDK_ROOT', 'Path to the Android NDK', os.environ.get("ANDROID_NDK_ROOT", 0)),
('ndk_platform', 'Target platform (android-<api>, e.g. "android-18")', "android-18"),
- EnumVariable('android_arch', 'Target architecture', "armv7", ('armv7', 'armv6', 'arm64v8', 'x86')),
+ EnumVariable('android_arch', 'Target architecture', "armv7", ('armv7', 'armv6', 'arm64v8', 'x86', 'x86_64')),
BoolVariable('android_neon', 'Enable NEON support (armv7 only)', True),
BoolVariable('android_stl', 'Enable Android STL support (for modules)', True)
]
@@ -94,7 +94,7 @@ def configure(env):
## Architecture
- if env['android_arch'] not in ['armv7', 'armv6', 'arm64v8', 'x86']:
+ if env['android_arch'] not in ['armv7', 'armv6', 'arm64v8', 'x86', 'x86_64']:
env['android_arch'] = 'armv7'
neon_text = ""
@@ -110,6 +110,16 @@ def configure(env):
abi_subpath = "i686-linux-android"
arch_subpath = "x86"
env["x86_libtheora_opt_gcc"] = True
+ if env['android_arch'] == 'x86_64':
+ if get_platform(env["ndk_platform"]) < 21:
+ print("WARNING: android_arch=x86_64 is not supported by ndk_platform lower than android-21; setting ndk_platform=android-21")
+ env["ndk_platform"] = "android-21"
+ env['ARCH'] = 'arch-x86_64'
+ env.extra_suffix = ".x86_64" + env.extra_suffix
+ target_subpath = "x86_64-4.9"
+ abi_subpath = "x86_64-linux-android"
+ arch_subpath = "x86_64"
+ env["x86_libtheora_opt_gcc"] = True
elif env['android_arch'] == 'armv6':
env['ARCH'] = 'arch-arm'
env.extra_suffix = ".armv6" + env.extra_suffix
@@ -233,6 +243,9 @@ def configure(env):
# The NDK adds this if targeting API < 21, so we can drop it when Godot targets it at least
env.Append(CPPFLAGS=['-mstackrealign'])
+ elif env['android_arch'] == 'x86_64':
+ target_opts = ['-target', 'x86_64-none-linux-android']
+
elif env["android_arch"] == "armv6":
target_opts = ['-target', 'armv6-none-linux-androideabi']
env.Append(CPPFLAGS='-D__ARM_ARCH_6__ -march=armv6 -mfpu=vfp -mfloat-abi=softfp'.split())
@@ -282,7 +295,7 @@ def configure(env):
'/toolchains/' + target_subpath + '/prebuilt/' + host_subpath + '/' + abi_subpath + '/lib'])
env.Append(CPPPATH=['#platform/android'])
- env.Append(CPPFLAGS=['-DANDROID_ENABLED', '-DUNIX_ENABLED', '-DNO_FCNTL', '-DMPC_FIXED_POINT'])
+ env.Append(CPPFLAGS=['-DANDROID_ENABLED', '-DUNIX_ENABLED', '-DNO_FCNTL'])
env.Append(LIBS=['OpenSLES', 'EGL', 'GLESv3', 'android', 'log', 'z', 'dl'])
# TODO: Move that to opus module's config
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index f4a2a1020f..405fe0b294 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -552,14 +552,13 @@ class EditorExportAndroid : public EditorExportPlatform {
static Vector<String> get_abis() {
Vector<String> abis;
- // We can still build armv7 in theory, but it doesn't make much
+ // We can still build armv6 in theory, but it doesn't make much
// sense for games, so disabling for now.
//abis.push_back("armeabi");
abis.push_back("armeabi-v7a");
abis.push_back("arm64-v8a");
abis.push_back("x86");
- // Don't expose x86_64 for now, we don't support it in detect.py
- //abis.push_back("x86_64");
+ abis.push_back("x86_64");
return abis;
}
@@ -1171,7 +1170,7 @@ public:
Vector<String> abis = get_abis();
for (int i = 0; i < abis.size(); ++i) {
String abi = abis[i];
- bool is_default = (abi == "armeabi-v7a");
+ bool is_default = (abi == "armeabi-v7a" || abi == "arm64-v8a");
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "architectures/" + abi), is_default));
}
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index 797a7d31aa..d0e6a4cefe 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -173,7 +173,7 @@ def configure(env):
env['ENV']['CODESIGN_ALLOCATE'] = '/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate'
env.Append(CPPPATH=['#platform/iphone'])
- env.Append(CPPFLAGS=['-DIPHONE_ENABLED', '-DUNIX_ENABLED', '-DGLES_ENABLED', '-DMPC_FIXED_POINT', '-DCOREAUDIO_ENABLED'])
+ env.Append(CPPFLAGS=['-DIPHONE_ENABLED', '-DUNIX_ENABLED', '-DGLES_ENABLED', '-DCOREAUDIO_ENABLED'])
# TODO: Move that to opus module's config
if 'module_opus_enabled' in env and env['module_opus_enabled']:
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index 3aaed4fb27..6ed008cf9c 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -64,6 +64,7 @@ void CanvasItemMaterial::init_shaders() {
void CanvasItemMaterial::finish_shaders() {
memdelete(dirty_materials);
+ memdelete(shader_names);
dirty_materials = NULL;
#ifndef NO_THREADS
diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp
index 240dbe1a89..d7ed6f8f49 100644
--- a/scene/2d/light_2d.cpp
+++ b/scene/2d/light_2d.cpp
@@ -450,7 +450,7 @@ void Light2D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color"), "set_shadow_color", "get_shadow_color");
ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_buffer_size", PROPERTY_HINT_RANGE, "32,16384,1"), "set_shadow_buffer_size", "get_shadow_buffer_size");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_gradient_length", PROPERTY_HINT_RANGE, "0,4096,0.1"), "set_shadow_gradient_length", "get_shadow_gradient_length");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_filter", PROPERTY_HINT_ENUM, "None,PCF3,PCF5,PCF7,PCF9,PCF13"), "set_shadow_filter", "get_shadow_filter");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_filter", PROPERTY_HINT_ENUM, "None,PCF3,PCF5,PCF7,PCF9,PCF13"), "set_shadow_filter", "get_shadow_filter");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "shadow_filter_smooth", PROPERTY_HINT_RANGE, "0,64,0.1"), "set_shadow_smooth", "get_shadow_smooth");
ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_item_cull_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_item_shadow_cull_mask", "get_item_shadow_cull_mask");
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index bfa82fa12e..54b304f851 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -224,15 +224,12 @@ void Polygon2D::_notification(int p_what) {
for (int i = 0; i < bone_weights.size(); i++) {
if (bone_weights[i].weights.size() != points.size()) {
continue; //different number of vertices, sorry not using.
- print_line("wrong weight size");
}
if (!skeleton_node->has_node(bone_weights[i].path)) {
- print_line("no node");
continue; //node does not exist
}
Bone2D *bone = Object::cast_to<Bone2D>(skeleton_node->get_node(bone_weights[i].path));
if (!bone) {
- print_line("no bone");
continue;
}
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index cac59bddff..d61296b13f 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -377,13 +377,12 @@ void TileMap::update_dirty_quadrants() {
r.size = tile_set->autotile_get_size(c.id);
r.position += (r.size + Vector2(spacing, spacing)) * Vector2(c.autotile_coord_x, c.autotile_coord_y);
}
- Size2 s = tex->get_size();
+ Size2 s;
if (r == Rect2())
s = tex->get_size();
- else {
+ else
s = r.size;
- }
Rect2 rect;
rect.position = offset.floor();
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index cad7ff47c1..0f4d0383a4 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -33,6 +33,7 @@
#include "scene/3d/area.h"
#include "scene/3d/camera.h"
#include "scene/main/viewport.h"
+
void AudioStreamPlayer3D::_mix_audio() {
if (!stream_playback.is_valid() || !active ||
@@ -206,15 +207,15 @@ float AudioStreamPlayer3D::_get_attenuation_db(float p_distance) const {
float att = 0;
switch (attenuation_model) {
case ATTENUATION_INVERSE_DISTANCE: {
- att = Math::linear2db(1.0 / ((p_distance / unit_size) + 000001));
+ att = Math::linear2db(1.0 / ((p_distance / unit_size) + CMP_EPSILON));
} break;
case ATTENUATION_INVERSE_SQUARE_DISTANCE: {
float d = (p_distance / unit_size);
d *= d;
- att = Math::linear2db(1.0 / (d + 0.00001));
+ att = Math::linear2db(1.0 / (d + CMP_EPSILON));
} break;
case ATTENUATION_LOGARITHMIC: {
- att = -20 * Math::log(p_distance / unit_size + 000001);
+ att = -20 * Math::log(p_distance / unit_size + CMP_EPSILON);
} break;
default: {
ERR_PRINT("Unknown attenuation type");
diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp
index 0bf5983dd1..29610cb0bf 100644
--- a/scene/3d/cpu_particles.cpp
+++ b/scene/3d/cpu_particles.cpp
@@ -605,19 +605,14 @@ void CPUParticles::_particles_process(float p_delta) {
p.hue_rot_rand = Math::randf();
p.anim_offset_rand = Math::randf();
- float angle1_rad;
- float angle2_rad;
-
if (flags[FLAG_DISABLE_Z]) {
-
- angle1_rad = (Math::randf() * 2.0 - 1.0) * Math_PI * spread / 180.0;
+ float angle1_rad = (Math::randf() * 2.0 - 1.0) * Math_PI * spread / 180.0;
Vector3 rot = Vector3(Math::cos(angle1_rad), Math::sin(angle1_rad), 0.0);
p.velocity = rot * parameters[PARAM_INITIAL_LINEAR_VELOCITY] * Math::lerp(1.0f, float(Math::randf()), randomness[PARAM_INITIAL_LINEAR_VELOCITY]);
-
} else {
//initiate velocity spread in 3D
- angle1_rad = (Math::randf() * 2.0 - 1.0) * Math_PI * spread / 180.0;
- angle2_rad = (Math::randf() * 2.0 - 1.0) * (1.0 - flatness) * Math_PI * spread / 180.0;
+ float angle1_rad = (Math::randf() * 2.0 - 1.0) * Math_PI * spread / 180.0;
+ float angle2_rad = (Math::randf() * 2.0 - 1.0) * (1.0 - flatness) * Math_PI * spread / 180.0;
Vector3 direction_xz = Vector3(Math::sin(angle1_rad), 0, Math::cos(angle1_rad));
Vector3 direction_yz = Vector3(0, Math::sin(angle2_rad), Math::cos(angle2_rad));
diff --git a/scene/3d/path.cpp b/scene/3d/path.cpp
index 4e027f43f6..9fae5a9a54 100644
--- a/scene/3d/path.cpp
+++ b/scene/3d/path.cpp
@@ -44,10 +44,11 @@ void Path::_curve_changed() {
emit_signal("curve_changed");
}
- // update the configuration warnings of all children of type OrientedPathFollows
+ // update the configuration warnings of all children of type PathFollow
+ // previously used for PathFollowOriented (now enforced orientation is done in PathFollow)
if (is_inside_tree()) {
for (int i = 0; i < get_child_count(); i++) {
- OrientedPathFollow *child = Object::cast_to<OrientedPathFollow>(get_child(i));
+ PathFollow *child = Object::cast_to<PathFollow>(get_child(i));
if (child) {
child->update_configuration_warning();
}
@@ -105,24 +106,64 @@ void PathFollow::_update_transform() {
return;
}
+ float bl = c->get_baked_length();
+ float bi = c->get_bake_interval();
float o = offset;
+ float o_next = offset + bi;
if (loop) {
- o = Math::fposmod(o, c->get_baked_length());
+ o = Math::fposmod(o, bl);
+ o_next = Math::fposmod(o_next, bl);
+ } else if (rotation_mode == ROTATION_ORIENTED && o_next >= bl) {
+ o = bl - bi;
+ o_next = bl;
}
Vector3 pos = c->interpolate_baked(o, cubic);
Transform t = get_transform();
+ // Vector3 pos_offset = Vector3(h_offset, v_offset, 0); not used in all cases
+ // will be replaced by "Vector3(h_offset, v_offset, 0)" where it was formely used
+
+ if (rotation_mode == ROTATION_ORIENTED) {
+
+ Vector3 pos = c->interpolate_baked(o, cubic);
+ Vector3 forward = c->interpolate_baked(o_next, cubic) - pos;
+
+ if (forward.length_squared() < CMP_EPSILON2)
+ forward = Vector3(0, 0, 1);
+ else
+ forward.normalize();
+
+ Vector3 up = c->interpolate_baked_up_vector(o, true);
+
+ if (o_next < o) {
+ Vector3 up1 = c->interpolate_baked_up_vector(o_next, true);
+ Vector3 axis = up.cross(up1);
- t.origin = pos;
- Vector3 pos_offset = Vector3(h_offset, v_offset, 0);
+ if (axis.length_squared() < CMP_EPSILON2)
+ axis = forward;
+ else
+ axis.normalize();
- if (rotation_mode != ROTATION_NONE) {
+ up.rotate(axis, up.angle_to(up1) * 0.5f);
+ }
+
+ Vector3 scale = t.basis.get_scale();
+ Vector3 sideways = up.cross(forward).normalized();
+ up = forward.cross(sideways).normalized();
+
+ t.basis.set(sideways, up, forward);
+ t.basis.scale_local(scale);
+
+ t.origin = pos + sideways * h_offset + up * v_offset;
+ } else if (rotation_mode != ROTATION_NONE) {
// perform parallel transport
//
// see C. Dougan, The Parallel Transport Frame, Game Programming Gems 2 for example
// for a discussion about why not Frenet frame.
+ t.origin = pos;
+
Vector3 t_prev = (pos - c->interpolate_baked(o - delta_offset, cubic)).normalized();
Vector3 t_cur = (c->interpolate_baked(o + delta_offset, cubic) - pos).normalized();
@@ -165,9 +206,9 @@ void PathFollow::_update_transform() {
}
}
- t.translate(pos_offset);
+ t.translate(Vector3(h_offset, v_offset, 0));
} else {
- t.origin += pos_offset;
+ t.origin = pos + Vector3(h_offset, v_offset, 0);
}
set_transform(t);
@@ -224,6 +265,11 @@ String PathFollow::get_configuration_warning() const {
if (!Object::cast_to<Path>(get_parent())) {
return TTR("PathFollow only works when set as a child of a Path node.");
+ } else {
+ Path *path = Object::cast_to<Path>(get_parent());
+ if (path->get_curve().is_valid() && !path->get_curve()->is_up_vector_enabled() && rotation_mode == ROTATION_ORIENTED) {
+ return TTR("PathFollow ROTATION_ORIENTED requires \"Up Vector\" enabled in its parent Path's Curve resource.");
+ }
}
return String();
@@ -256,7 +302,7 @@ void PathFollow::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_offset", PROPERTY_HINT_RANGE, "0,1,0.0001,or_greater", PROPERTY_USAGE_EDITOR), "set_unit_offset", "get_unit_offset");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "h_offset"), "set_h_offset", "get_h_offset");
ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_offset"), "set_v_offset", "get_v_offset");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM, "None,Y,XY,XYZ"), "set_rotation_mode", "get_rotation_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "rotation_mode", PROPERTY_HINT_ENUM, "None,Y,XY,XYZ,Oriented"), "set_rotation_mode", "get_rotation_mode");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cubic_interp"), "set_cubic_interpolation", "get_cubic_interpolation");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop");
@@ -264,6 +310,7 @@ void PathFollow::_bind_methods() {
BIND_ENUM_CONSTANT(ROTATION_Y);
BIND_ENUM_CONSTANT(ROTATION_XY);
BIND_ENUM_CONSTANT(ROTATION_XYZ);
+ BIND_ENUM_CONSTANT(ROTATION_ORIENTED);
}
void PathFollow::set_offset(float p_offset) {
@@ -322,6 +369,8 @@ float PathFollow::get_unit_offset() const {
void PathFollow::set_rotation_mode(RotationMode p_rotation_mode) {
rotation_mode = p_rotation_mode;
+
+ update_configuration_warning();
_update_transform();
}
@@ -351,236 +400,3 @@ PathFollow::PathFollow() {
cubic = true;
loop = true;
}
-
-//////////////
-
-void OrientedPathFollow::_update_transform() {
-
- if (!path)
- return;
-
- Ref<Curve3D> c = path->get_curve();
- if (!c.is_valid())
- return;
-
- int count = c->get_point_count();
- if (count < 2)
- return;
-
- if (delta_offset == 0) {
- return;
- }
-
- float offset = get_offset();
- float bl = c->get_baked_length();
- float bi = c->get_bake_interval();
- float o = offset;
- float o_next = offset + bi;
-
- if (has_loop()) {
- o = Math::fposmod(o, bl);
- o_next = Math::fposmod(o_next, bl);
- } else if (o_next >= bl) {
- o = bl - bi;
- o_next = bl;
- }
-
- bool cubic = get_cubic_interpolation();
- Vector3 pos = c->interpolate_baked(o, cubic);
- Vector3 forward = c->interpolate_baked(o_next, cubic) - pos;
-
- if (forward.length_squared() < CMP_EPSILON2)
- forward = Vector3(0, 0, 1);
- else
- forward.normalize();
-
- Vector3 up = c->interpolate_baked_up_vector(o, true);
-
- if (o_next < o) {
- Vector3 up1 = c->interpolate_baked_up_vector(o_next, true);
- Vector3 axis = up.cross(up1);
-
- if (axis.length_squared() < CMP_EPSILON2)
- axis = forward;
- else
- axis.normalize();
-
- up.rotate(axis, up.angle_to(up1) * 0.5f);
- }
-
- Transform t = get_transform();
- Vector3 scale = t.basis.get_scale();
-
- Vector3 sideways = up.cross(forward).normalized();
- up = forward.cross(sideways).normalized();
-
- t.basis.set(sideways, up, forward);
- t.basis.scale_local(scale);
-
- t.origin = pos + sideways * get_h_offset() + up * get_v_offset();
-
- set_transform(t);
-}
-
-void OrientedPathFollow::_notification(int p_what) {
-
- switch (p_what) {
-
- case NOTIFICATION_ENTER_TREE: {
-
- Node *parent = get_parent();
- if (parent) {
- path = Object::cast_to<Path>(parent);
- if (path) {
- _update_transform();
- }
- }
-
- } break;
- case NOTIFICATION_EXIT_TREE: {
-
- path = NULL;
- } break;
- }
-}
-
-void OrientedPathFollow::set_cubic_interpolation(bool p_enable) {
-
- cubic = p_enable;
-}
-
-bool OrientedPathFollow::get_cubic_interpolation() const {
-
- return cubic;
-}
-
-void OrientedPathFollow::_validate_property(PropertyInfo &property) const {
-
- if (property.name == "offset") {
-
- float max = 10000;
- if (path && path->get_curve().is_valid())
- max = path->get_curve()->get_baked_length();
-
- property.hint_string = "0," + rtos(max) + ",0.01";
- }
-}
-
-String OrientedPathFollow::get_configuration_warning() const {
-
- if (!is_visible_in_tree() || !is_inside_tree())
- return String();
-
- if (!Object::cast_to<Path>(get_parent())) {
- return TTR("OrientedPathFollow only works when set as a child of a Path node.");
- } else {
- Path *path = Object::cast_to<Path>(get_parent());
- if (path->get_curve().is_valid() && !path->get_curve()->is_up_vector_enabled()) {
- return TTR("OrientedPathFollow requires \"Up Vector\" enabled in its parent Path's Curve resource.");
- }
- }
-
- return String();
-}
-
-void OrientedPathFollow::_bind_methods() {
-
- ClassDB::bind_method(D_METHOD("set_offset", "offset"), &OrientedPathFollow::set_offset);
- ClassDB::bind_method(D_METHOD("get_offset"), &OrientedPathFollow::get_offset);
-
- ClassDB::bind_method(D_METHOD("set_h_offset", "h_offset"), &OrientedPathFollow::set_h_offset);
- ClassDB::bind_method(D_METHOD("get_h_offset"), &OrientedPathFollow::get_h_offset);
-
- ClassDB::bind_method(D_METHOD("set_v_offset", "v_offset"), &OrientedPathFollow::set_v_offset);
- ClassDB::bind_method(D_METHOD("get_v_offset"), &OrientedPathFollow::get_v_offset);
-
- ClassDB::bind_method(D_METHOD("set_unit_offset", "unit_offset"), &OrientedPathFollow::set_unit_offset);
- ClassDB::bind_method(D_METHOD("get_unit_offset"), &OrientedPathFollow::get_unit_offset);
-
- ClassDB::bind_method(D_METHOD("set_cubic_interpolation", "enable"), &OrientedPathFollow::set_cubic_interpolation);
- ClassDB::bind_method(D_METHOD("get_cubic_interpolation"), &OrientedPathFollow::get_cubic_interpolation);
-
- ClassDB::bind_method(D_METHOD("set_loop", "loop"), &OrientedPathFollow::set_loop);
- ClassDB::bind_method(D_METHOD("has_loop"), &OrientedPathFollow::has_loop);
-
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "offset", PROPERTY_HINT_RANGE, "0,10000,0.01"), "set_offset", "get_offset");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_offset", PROPERTY_HINT_RANGE, "0,1,0.0001", PROPERTY_USAGE_EDITOR), "set_unit_offset", "get_unit_offset");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "h_offset"), "set_h_offset", "get_h_offset");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_offset"), "set_v_offset", "get_v_offset");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cubic_interp"), "set_cubic_interpolation", "get_cubic_interpolation");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop");
-}
-
-void OrientedPathFollow::set_offset(float p_offset) {
- delta_offset = p_offset - offset;
- offset = p_offset;
-
- if (path)
- _update_transform();
- _change_notify("offset");
- _change_notify("unit_offset");
-}
-
-void OrientedPathFollow::set_h_offset(float p_h_offset) {
-
- h_offset = p_h_offset;
- if (path)
- _update_transform();
-}
-
-float OrientedPathFollow::get_h_offset() const {
-
- return h_offset;
-}
-
-void OrientedPathFollow::set_v_offset(float p_v_offset) {
-
- v_offset = p_v_offset;
- if (path)
- _update_transform();
-}
-
-float OrientedPathFollow::get_v_offset() const {
-
- return v_offset;
-}
-
-float OrientedPathFollow::get_offset() const {
-
- return offset;
-}
-
-void OrientedPathFollow::set_unit_offset(float p_unit_offset) {
-
- if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length())
- set_offset(p_unit_offset * path->get_curve()->get_baked_length());
-}
-
-float OrientedPathFollow::get_unit_offset() const {
-
- if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length())
- return get_offset() / path->get_curve()->get_baked_length();
- else
- return 0;
-}
-
-void OrientedPathFollow::set_loop(bool p_loop) {
-
- loop = p_loop;
-}
-
-bool OrientedPathFollow::has_loop() const {
-
- return loop;
-}
-
-OrientedPathFollow::OrientedPathFollow() {
-
- offset = 0;
- delta_offset = 0;
- h_offset = 0;
- v_offset = 0;
- path = NULL;
- cubic = true;
- loop = true;
-}
diff --git a/scene/3d/path.h b/scene/3d/path.h
index c514811c62..2a12c4a826 100644
--- a/scene/3d/path.h
+++ b/scene/3d/path.h
@@ -63,7 +63,8 @@ public:
ROTATION_NONE,
ROTATION_Y,
ROTATION_XY,
- ROTATION_XYZ
+ ROTATION_XYZ,
+ ROTATION_ORIENTED
};
private:
@@ -113,49 +114,4 @@ public:
VARIANT_ENUM_CAST(PathFollow::RotationMode);
-class OrientedPathFollow : public Spatial {
-
- GDCLASS(OrientedPathFollow, Spatial);
-
-private:
- Path *path;
- real_t delta_offset; // change in offset since last _update_transform
- real_t offset;
- real_t h_offset;
- real_t v_offset;
- bool cubic;
- bool loop;
-
- void _update_transform();
-
-protected:
- virtual void _validate_property(PropertyInfo &property) const;
-
- void _notification(int p_what);
- static void _bind_methods();
-
-public:
- void set_offset(float p_offset);
- float get_offset() const;
-
- void set_h_offset(float p_h_offset);
- float get_h_offset() const;
-
- void set_v_offset(float p_v_offset);
- float get_v_offset() const;
-
- void set_unit_offset(float p_unit_offset);
- float get_unit_offset() const;
-
- void set_loop(bool p_loop);
- bool has_loop() const;
-
- void set_cubic_interpolation(bool p_enable);
- bool get_cubic_interpolation() const;
-
- String get_configuration_warning() const;
-
- OrientedPathFollow();
-};
-
#endif // PATH_H
diff --git a/scene/3d/voxel_light_baker.cpp b/scene/3d/voxel_light_baker.cpp
index 4b910e4463..30e38c8ee2 100644
--- a/scene/3d/voxel_light_baker.cpp
+++ b/scene/3d/voxel_light_baker.cpp
@@ -342,8 +342,8 @@ void VoxelLightBaker::_plot_face(int p_idx, int p_level, int p_x, int p_y, int p
if (lnormal == Vector3()) //just in case normal as nor provided
lnormal = normal;
- int uv_x = CLAMP(Math::fposmod(uv.x, 1.0f) * bake_texture_size, 0, bake_texture_size - 1);
- int uv_y = CLAMP(Math::fposmod(uv.y, 1.0f) * bake_texture_size, 0, bake_texture_size - 1);
+ int uv_x = CLAMP(int(Math::fposmod(uv.x, 1.0f) * bake_texture_size), 0, bake_texture_size - 1);
+ int uv_y = CLAMP(int(Math::fposmod(uv.y, 1.0f) * bake_texture_size), 0, bake_texture_size - 1);
int ofs = uv_y * bake_texture_size + uv_x;
albedo_accum.r += p_material.albedo[ofs].r;
@@ -1931,7 +1931,6 @@ Error VoxelLightBaker::make_lightmap(const Transform &p_xform, Ref<Mesh> &p_mesh
//add directional light (do this after blur)
{
- LightMap *lightmap_ptr = lightmap.ptrw();
const Cell *cells = bake_cells.ptr();
const Light *light = bake_light.ptr();
#ifdef _OPENMP
diff --git a/scene/animation/animation_blend_space_1d.cpp b/scene/animation/animation_blend_space_1d.cpp
index 360ba84374..dded44b990 100644
--- a/scene/animation/animation_blend_space_1d.cpp
+++ b/scene/animation/animation_blend_space_1d.cpp
@@ -110,7 +110,7 @@ void AnimationNodeBlendSpace1D::add_blend_point(const Ref<AnimationRootNode> &p_
if (p_at_index == -1 || p_at_index == blend_points_used) {
p_at_index = blend_points_used;
} else {
- for (int i = blend_points_used - 1; i > p_at_index; i++) {
+ for (int i = blend_points_used - 1; i > p_at_index; i--) {
blend_points[i] = blend_points[i - 1];
}
}
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 4d638b50c6..4a2bb3dad1 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -1290,13 +1290,11 @@ int LineEdit::get_max_length() const {
void LineEdit::selection_fill_at_cursor() {
- int aux;
-
selection.begin = cursor_pos;
selection.end = selection.cursor_start;
if (selection.end < selection.begin) {
- aux = selection.end;
+ int aux = selection.end;
selection.end = selection.begin;
selection.begin = aux;
}
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index f99f5e4d4b..28292309b9 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -271,7 +271,6 @@ void ScrollContainer::_notification(int p_what) {
}
if (!scroll_v || (!v_scroll->is_visible_in_tree() && c->get_v_size_flags() & SIZE_EXPAND)) {
r.position.y = 0;
- r.size.height = size.height;
if (c->get_v_size_flags() & SIZE_EXPAND)
r.size.height = MAX(size.height, minsize.height);
else
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 19c054fa43..09fbb39866 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -3811,7 +3811,6 @@ Vector<String> TextEdit::get_wrap_rows_text(int p_line) const {
if (indent_ofs + word_px > wrap_at) {
// not enough space; add it anyway
wrap_substring += word_str;
- px += word_px;
word_str = "";
word_px = 0;
}
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index d2411d97e3..514be00227 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -1158,10 +1158,9 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
r.position.x += icon_width;
r.size.x -= icon_width;
}
- //r.grow(cache.selected->get_margin(MARGIN_LEFT));
+ p_item->set_meta("__focus_rect", Rect2(r.position, r.size));
if (has_focus()) {
cache.selected_focus->draw(ci, r);
- p_item->set_meta("__focus_rect", Rect2(r.position, r.size));
} else {
cache.selected->draw(ci, r);
}
diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp
index 8e96873672..8b68b3215c 100644
--- a/scene/main/http_request.cpp
+++ b/scene/main/http_request.cpp
@@ -220,13 +220,12 @@ bool HTTPRequest::_handle_response(bool *ret_value) {
Error err;
if (new_request.begins_with("http")) {
// New url, request all again
- err = _parse_url(new_request);
+ _parse_url(new_request);
} else {
request_string = new_request;
}
err = _request();
-
if (err == OK) {
request_sent = false;
got_response = false;
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index 3281081897..a50a09f095 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -452,7 +452,6 @@ void register_scene_types() {
ClassDB::register_class<Curve3D>();
ClassDB::register_class<Path>();
ClassDB::register_class<PathFollow>();
- ClassDB::register_class<OrientedPathFollow>();
ClassDB::register_class<VisibilityNotifier>();
ClassDB::register_class<VisibilityEnabler>();
ClassDB::register_class<WorldEnvironment>();
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 5c6b0ac91a..383f3f5d4e 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -2332,7 +2332,7 @@ float Animation::bezier_track_interpolate(int p_track, float p_time) const {
float duration = bt->values[idx + 1].time - bt->values[idx].time; // time duration between our two keyframes
float low = 0; // 0% of the current animation segment
float high = 1; // 100% of the current animation segment
- float middle = 0;
+ float middle;
Vector2 start(0, bt->values[idx].value.value);
Vector2 start_out = start + bt->values[idx].value.out_handle;
diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp
index e136181136..464ca60d31 100644
--- a/scene/resources/curve.cpp
+++ b/scene/resources/curve.cpp
@@ -761,8 +761,8 @@ Vector2 Curve2D::interpolate_baked(float p_offset, bool p_cubic) const {
//validate//
int pc = baked_point_cache.size();
if (pc == 0) {
- ERR_EXPLAIN("No points in Curve2D");
- ERR_FAIL_COND_V(pc == 0, Vector2());
+ ERR_EXPLAIN("No points in Curve2D.");
+ ERR_FAIL_V(Vector2());
}
if (pc == 1)
@@ -826,8 +826,8 @@ Vector2 Curve2D::get_closest_point(const Vector2 &p_to_point) const {
//validate//
int pc = baked_point_cache.size();
if (pc == 0) {
- ERR_EXPLAIN("No points in Curve2D");
- ERR_FAIL_COND_V(pc == 0, Vector2());
+ ERR_EXPLAIN("No points in Curve2D.");
+ ERR_FAIL_V(Vector2());
}
if (pc == 1)
@@ -865,8 +865,8 @@ float Curve2D::get_closest_offset(const Vector2 &p_to_point) const {
//validate//
int pc = baked_point_cache.size();
if (pc == 0) {
- ERR_EXPLAIN("No points in Curve2D");
- ERR_FAIL_COND_V(pc == 0, 0.0f);
+ ERR_EXPLAIN("No points in Curve2D.");
+ ERR_FAIL_V(0.0f);
}
if (pc == 1)
@@ -1331,8 +1331,8 @@ Vector3 Curve3D::interpolate_baked(float p_offset, bool p_cubic) const {
//validate//
int pc = baked_point_cache.size();
if (pc == 0) {
- ERR_EXPLAIN("No points in Curve3D");
- ERR_FAIL_COND_V(pc == 0, Vector3());
+ ERR_EXPLAIN("No points in Curve3D.");
+ ERR_FAIL_V(Vector3());
}
if (pc == 1)
@@ -1375,8 +1375,8 @@ float Curve3D::interpolate_baked_tilt(float p_offset) const {
//validate//
int pc = baked_tilt_cache.size();
if (pc == 0) {
- ERR_EXPLAIN("No tilts in Curve3D");
- ERR_FAIL_COND_V(pc == 0, 0);
+ ERR_EXPLAIN("No tilts in Curve3D.");
+ ERR_FAIL_V(0);
}
if (pc == 1)
@@ -1413,8 +1413,8 @@ Vector3 Curve3D::interpolate_baked_up_vector(float p_offset, bool p_apply_tilt)
// curve may not have baked up vectors
int count = baked_up_vector_cache.size();
if (count == 0) {
- ERR_EXPLAIN("No up vectors in Curve3D");
- ERR_FAIL_COND_V(count == 0, Vector3(0, 1, 0));
+ ERR_EXPLAIN("No up vectors in Curve3D.");
+ ERR_FAIL_V(Vector3(0, 1, 0));
}
if (count == 1)
@@ -1484,8 +1484,8 @@ Vector3 Curve3D::get_closest_point(const Vector3 &p_to_point) const {
//validate//
int pc = baked_point_cache.size();
if (pc == 0) {
- ERR_EXPLAIN("No points in Curve3D");
- ERR_FAIL_COND_V(pc == 0, Vector3());
+ ERR_EXPLAIN("No points in Curve3D.");
+ ERR_FAIL_V(Vector3());
}
if (pc == 1)
@@ -1523,8 +1523,8 @@ float Curve3D::get_closest_offset(const Vector3 &p_to_point) const {
//validate//
int pc = baked_point_cache.size();
if (pc == 0) {
- ERR_EXPLAIN("No points in Curve3D");
- ERR_FAIL_COND_V(pc == 0, 0.0f);
+ ERR_EXPLAIN("No points in Curve3D.");
+ ERR_FAIL_V(0.0f);
}
if (pc == 1)
diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp
index 0254945c00..e2407e4423 100644
--- a/scene/resources/shape_2d.cpp
+++ b/scene/resources/shape_2d.cpp
@@ -59,37 +59,37 @@ bool Shape2D::collide(const Transform2D &p_local_xform, const Ref<Shape2D> &p_sh
return Physics2DServer::get_singleton()->shape_collide(get_rid(), p_local_xform, Vector2(), p_shape->get_rid(), p_shape_xform, Vector2(), NULL, 0, r);
}
-Variant Shape2D::collide_with_motion_and_get_contacts(const Transform2D &p_local_xform, const Vector2 &p_local_motion, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform, const Vector2 &p_shape_motion) {
+Array Shape2D::collide_with_motion_and_get_contacts(const Transform2D &p_local_xform, const Vector2 &p_local_motion, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform, const Vector2 &p_shape_motion) {
- ERR_FAIL_COND_V(p_shape.is_null(), Variant());
+ ERR_FAIL_COND_V(p_shape.is_null(), Array());
const int max_contacts = 16;
Vector2 result[max_contacts * 2];
int contacts = 0;
if (!Physics2DServer::get_singleton()->shape_collide(get_rid(), p_local_xform, p_local_motion, p_shape->get_rid(), p_shape_xform, p_shape_motion, result, max_contacts, contacts))
- return Variant();
+ return Array();
Array results;
results.resize(contacts * 2);
- for (int i = 0; i < contacts; i++) {
+ for (int i = 0; i < contacts * 2; i++) {
results[i] = result[i];
}
return results;
}
-Variant Shape2D::collide_and_get_contacts(const Transform2D &p_local_xform, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform) {
+Array Shape2D::collide_and_get_contacts(const Transform2D &p_local_xform, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform) {
- ERR_FAIL_COND_V(p_shape.is_null(), Variant());
+ ERR_FAIL_COND_V(p_shape.is_null(), Array());
const int max_contacts = 16;
Vector2 result[max_contacts * 2];
int contacts = 0;
if (!Physics2DServer::get_singleton()->shape_collide(get_rid(), p_local_xform, Vector2(), p_shape->get_rid(), p_shape_xform, Vector2(), result, max_contacts, contacts))
- return Variant();
+ return Array();
Array results;
results.resize(contacts * 2);
- for (int i = 0; i < contacts; i++) {
+ for (int i = 0; i < contacts * 2; i++) {
results[i] = result[i];
}
diff --git a/scene/resources/shape_2d.h b/scene/resources/shape_2d.h
index cf6b38ddda..da9b80477c 100644
--- a/scene/resources/shape_2d.h
+++ b/scene/resources/shape_2d.h
@@ -53,8 +53,8 @@ public:
bool collide_with_motion(const Transform2D &p_local_xform, const Vector2 &p_local_motion, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform, const Vector2 &p_shape_motion);
bool collide(const Transform2D &p_local_xform, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform);
- Variant collide_with_motion_and_get_contacts(const Transform2D &p_local_xform, const Vector2 &p_local_motion, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform, const Vector2 &p_shape_motion);
- Variant collide_and_get_contacts(const Transform2D &p_local_xform, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform);
+ Array collide_with_motion_and_get_contacts(const Transform2D &p_local_xform, const Vector2 &p_local_motion, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform, const Vector2 &p_shape_motion);
+ Array collide_and_get_contacts(const Transform2D &p_local_xform, const Ref<Shape2D> &p_shape, const Transform2D &p_shape_xform);
virtual void draw(const RID &p_to_rid, const Color &p_color) {}
virtual Rect2 get_rect() const { return Rect2(); }
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 773c1d1ad9..394592ec64 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -656,7 +656,7 @@ public:
next_ptr = NULL;
mask_next_ptr = NULL;
filter_next_ptr = NULL;
- shadow_buffer_size = 256;
+ shadow_buffer_size = 2048;
shadow_gradient_length = 0;
shadow_filter = VS::CANVAS_LIGHT_FILTER_NONE;
shadow_smooth = 0.0;
diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp
index bb02027479..84338bccca 100644
--- a/servers/visual/visual_server_canvas.cpp
+++ b/servers/visual/visual_server_canvas.cpp
@@ -1110,6 +1110,7 @@ void VisualServerCanvas::canvas_light_set_shadow_buffer_size(RID p_light, int p_
if (new_size == clight->shadow_buffer_size)
return;
+ print_line("create shadow buffer: " + itos(p_size));
clight->shadow_buffer_size = next_power_of_2(p_size);
if (clight->shadow_buffer.is_valid()) {