summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/error_macros.h20
-rw-r--r--core/math/quick_hull.cpp4
-rw-r--r--core/math/quick_hull.h2
-rw-r--r--core/variant_op.cpp70
-rw-r--r--doc/classes/Tween.xml2
-rw-r--r--drivers/gles2/rasterizer_canvas_gles2.cpp1
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.cpp84
-rw-r--r--drivers/gles2/rasterizer_scene_gles2.h2
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.cpp389
-rw-r--r--drivers/gles2/rasterizer_storage_gles2.h7
-rw-r--r--drivers/gles2/shader_gles2.cpp123
-rw-r--r--drivers/gles3/rasterizer_storage_gles3.cpp1
-rw-r--r--drivers/windows/dir_access_windows.cpp3
-rw-r--r--editor/editor_file_dialog.cpp5
-rw-r--r--editor/editor_node.cpp2
-rw-r--r--editor/editor_resource_preview.cpp8
-rw-r--r--editor/editor_resource_preview.h3
-rw-r--r--editor/import/editor_scene_importer_gltf.cpp2
-rw-r--r--editor/plugins/tile_set_editor_plugin.cpp503
-rw-r--r--editor/plugins/tile_set_editor_plugin.h28
-rw-r--r--modules/csg/csg.cpp6
-rw-r--r--modules/opus/SCsub8
-rw-r--r--platform/android/detect.py6
-rw-r--r--platform/android/java/src/org/godotengine/godot/GodotIO.java8
-rw-r--r--platform/iphone/detect.py8
-rw-r--r--platform/javascript/detect.py4
-rw-r--r--platform/x11/detect.py2
-rw-r--r--scene/2d/area_2d.cpp2
-rw-r--r--scene/2d/polygon_2d.cpp4
-rw-r--r--scene/3d/area.cpp2
-rw-r--r--scene/3d/light.cpp7
-rw-r--r--scene/3d/light.h1
-rw-r--r--scene/animation/animation_player.cpp3
-rw-r--r--scene/gui/control.cpp2
-rw-r--r--scene/gui/graph_edit.cpp5
-rw-r--r--scene/gui/rich_text_label.cpp11
-rw-r--r--scene/gui/rich_text_label.h2
-rw-r--r--scene/main/viewport.cpp7
-rw-r--r--scene/main/viewport.h1
-rw-r--r--scene/resources/animation.cpp9
-rw-r--r--scene/resources/mesh.cpp30
-rw-r--r--scene/resources/mesh.h1
-rw-r--r--scene/resources/packed_scene.cpp2
-rw-r--r--servers/audio/audio_stream.cpp20
-rw-r--r--servers/audio_server.cpp18
-rw-r--r--servers/physics/physics_server_sw.cpp18
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp21
-rw-r--r--servers/visual/visual_server_canvas.cpp15
-rw-r--r--servers/visual/visual_server_scene.cpp3
49 files changed, 1236 insertions, 249 deletions
diff --git a/core/error_macros.h b/core/error_macros.h
index 3aa8ed4596..ca5ccd24cf 100644
--- a/core/error_macros.h
+++ b/core/error_macros.h
@@ -310,6 +310,16 @@ extern bool _err_error_exists;
_err_error_exists = false; \
}
+#define ERR_PRINT_ONCE(m_string) \
+ { \
+ static bool first_print = true; \
+ if (first_print) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string); \
+ _err_error_exists = false; \
+ first_print = false; \
+ } \
+ }
+
/** Print a warning string.
*/
@@ -325,6 +335,16 @@ extern bool _err_error_exists;
_err_error_exists = false; \
}
+#define WARN_PRINT_ONCE(m_string) \
+ { \
+ static bool first_print = true; \
+ if (first_print) { \
+ _err_print_error(FUNCTION_STR, __FILE__, __LINE__, m_string, ERR_HANDLER_WARNING); \
+ _err_error_exists = false; \
+ first_print = false; \
+ } \
+ }
+
#define WARN_DEPRECATED \
{ \
static volatile bool warning_shown = false; \
diff --git a/core/math/quick_hull.cpp b/core/math/quick_hull.cpp
index bc2b4e6fe0..fc2eb1454d 100644
--- a/core/math/quick_hull.cpp
+++ b/core/math/quick_hull.cpp
@@ -36,8 +36,6 @@ uint32_t QuickHull::debug_stop_after = 0xFFFFFFFF;
Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_mesh) {
- static const real_t over_tolerance = 0.0001;
-
/* CREATE AABB VOLUME */
AABB aabb;
@@ -180,6 +178,8 @@ Error QuickHull::build(const Vector<Vector3> &p_points, Geometry::MeshData &r_me
faces.push_back(f);
}
+ real_t over_tolerance = 3 * UNIT_EPSILON * (aabb.size.x + aabb.size.y + aabb.size.z);
+
/* COMPUTE AVAILABLE VERTICES */
for (int i = 0; i < p_points.size(); i++) {
diff --git a/core/math/quick_hull.h b/core/math/quick_hull.h
index 2e659cab6e..a445a47cbe 100644
--- a/core/math/quick_hull.h
+++ b/core/math/quick_hull.h
@@ -64,7 +64,7 @@ public:
struct Face {
Plane plane;
- int vertices[3];
+ uint32_t vertices[3];
Vector<int> points_over;
bool operator<(const Face &p_face) const {
diff --git a/core/variant_op.cpp b/core/variant_op.cpp
index 26851e4c23..b40b6ce4a6 100644
--- a/core/variant_op.cpp
+++ b/core/variant_op.cpp
@@ -3656,11 +3656,55 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
}
return;
case POOL_INT_ARRAY: {
- r_dst = a;
+ const PoolVector<int> *arr_a = reinterpret_cast<const PoolVector<int> *>(a._data._mem);
+ const PoolVector<int> *arr_b = reinterpret_cast<const PoolVector<int> *>(b._data._mem);
+ int sz = arr_a->size();
+ if (sz == 0 || arr_b->size() != sz) {
+
+ r_dst = a;
+ } else {
+
+ PoolVector<int> v;
+ v.resize(sz);
+ {
+ PoolVector<int>::Write vw = v.write();
+ PoolVector<int>::Read ar = arr_a->read();
+ PoolVector<int>::Read br = arr_b->read();
+
+ Variant va;
+ for (int i = 0; i < sz; i++) {
+ Variant::interpolate(ar[i], br[i], c, va);
+ vw[i] = va;
+ }
+ }
+ r_dst = v;
+ }
}
return;
case POOL_REAL_ARRAY: {
- r_dst = a;
+ const PoolVector<real_t> *arr_a = reinterpret_cast<const PoolVector<real_t> *>(a._data._mem);
+ const PoolVector<real_t> *arr_b = reinterpret_cast<const PoolVector<real_t> *>(b._data._mem);
+ int sz = arr_a->size();
+ if (sz == 0 || arr_b->size() != sz) {
+
+ r_dst = a;
+ } else {
+
+ PoolVector<real_t> v;
+ v.resize(sz);
+ {
+ PoolVector<real_t>::Write vw = v.write();
+ PoolVector<real_t>::Read ar = arr_a->read();
+ PoolVector<real_t>::Read br = arr_b->read();
+
+ Variant va;
+ for (int i = 0; i < sz; i++) {
+ Variant::interpolate(ar[i], br[i], c, va);
+ vw[i] = va;
+ }
+ }
+ r_dst = v;
+ }
}
return;
case POOL_STRING_ARRAY: {
@@ -3717,7 +3761,27 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant &
}
return;
case POOL_COLOR_ARRAY: {
- r_dst = a;
+ const PoolVector<Color> *arr_a = reinterpret_cast<const PoolVector<Color> *>(a._data._mem);
+ const PoolVector<Color> *arr_b = reinterpret_cast<const PoolVector<Color> *>(b._data._mem);
+ int sz = arr_a->size();
+ if (sz == 0 || arr_b->size() != sz) {
+
+ r_dst = a;
+ } else {
+
+ PoolVector<Color> v;
+ v.resize(sz);
+ {
+ PoolVector<Color>::Write vw = v.write();
+ PoolVector<Color>::Read ar = arr_a->read();
+ PoolVector<Color>::Read br = arr_b->read();
+
+ for (int i = 0; i < sz; i++) {
+ vw[i] = ar[i].linear_interpolate(br[i], c);
+ }
+ }
+ r_dst = v;
+ }
}
return;
default: {
diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml
index c3af586b21..f5f50a75b1 100644
--- a/doc/classes/Tween.xml
+++ b/doc/classes/Tween.xml
@@ -13,7 +13,7 @@
Tween.TRANS_LINEAR, Tween.EASE_IN_OUT)
tween.start()
[/codeblock]
- Many methods require a property name, such as "position" above. You can find the correct property name by hovering over the property in the Inspector.
+ Many methods require a property name, such as "position" above. You can find the correct property name by hovering over the property in the Inspector. You can also provide the components of a property directly by using "property:component" (eg. [code]position:x[/code]), where it would only apply to that particular component.
Many of the methods accept [code]trans_type[/code] and [code]ease_type[/code]. The first accepts an [enum TransitionType] constant, and refers to the way the timing of the animation is handled (see [code]http://easings.net/[/code] for some examples). The second accepts an [enum EaseType] constant, and controls the where [code]trans_type[/code] is applied to the interpolation (in the beginning, the end, or both). If you don't know which transition and easing to pick, you can try different [enum TransitionType] constants with [code]EASE_IN_OUT[/code], and use the one that looks best.
</description>
<tutorials>
diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp
index 5d336d2a25..bf0da5feb1 100644
--- a/drivers/gles2/rasterizer_canvas_gles2.cpp
+++ b/drivers/gles2/rasterizer_canvas_gles2.cpp
@@ -2029,6 +2029,7 @@ void RasterizerCanvasGLES2::initialize() {
state.using_light = NULL;
state.using_transparent_rt = false;
+ state.using_skeleton = false;
}
void RasterizerCanvasGLES2::finalize() {
diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp
index ebaa66824a..e0eec74700 100644
--- a/drivers/gles2/rasterizer_scene_gles2.cpp
+++ b/drivers/gles2/rasterizer_scene_gles2.cpp
@@ -83,7 +83,11 @@ void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) {
// erase the old atlast
if (shadow_atlas->fbo) {
- glDeleteTextures(1, &shadow_atlas->depth);
+ if (storage->config.use_rgba_3d_shadows) {
+ glDeleteRenderbuffers(1, &shadow_atlas->depth);
+ } else {
+ glDeleteTextures(1, &shadow_atlas->depth);
+ }
glDeleteFramebuffers(1, &shadow_atlas->fbo);
if (shadow_atlas->color) {
glDeleteTextures(1, &shadow_atlas->color);
@@ -111,18 +115,15 @@ void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) {
// create a depth texture
glActiveTexture(GL_TEXTURE0);
- glGenTextures(1, &shadow_atlas->depth);
- glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
- glTexImage2D(GL_TEXTURE_2D, 0, storage->config.depth_internalformat, shadow_atlas->size, shadow_atlas->size, 0, GL_DEPTH_COMPONENT, storage->config.depth_type, NULL);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ if (storage->config.use_rgba_3d_shadows) {
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadow_atlas->depth, 0);
+ //maximum compatibility, renderbuffer and RGBA shadow
+ glGenRenderbuffers(1, &shadow_atlas->depth);
+ glBindRenderbuffer(GL_RENDERBUFFER, directional_shadow.depth);
+ glRenderbufferStorage(GL_RENDERBUFFER, storage->config.depth_internalformat, shadow_atlas->size, shadow_atlas->size);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, shadow_atlas->depth);
- if (storage->config.use_rgba_3d_shadows) {
glGenTextures(1, &shadow_atlas->color);
glBindTexture(GL_TEXTURE_2D, shadow_atlas->color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, shadow_atlas->size, shadow_atlas->size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
@@ -131,6 +132,18 @@ void RasterizerSceneGLES2::shadow_atlas_set_size(RID p_atlas, int p_size) {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, shadow_atlas->color, 0);
+ } else {
+ //just depth texture
+ glGenTextures(1, &shadow_atlas->depth);
+ glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth);
+ glTexImage2D(GL_TEXTURE_2D, 0, storage->config.depth_internalformat, shadow_atlas->size, shadow_atlas->size, 0, GL_DEPTH_COMPONENT, storage->config.depth_type, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadow_atlas->depth, 0);
}
glViewport(0, 0, shadow_atlas->size, shadow_atlas->size);
@@ -475,7 +488,8 @@ RID RasterizerSceneGLES2::reflection_probe_instance_create(RID p_probe) {
glGenTextures(1, &rpi->color[i]);
}
- glGenTextures(1, &rpi->depth);
+ glGenRenderbuffers(1, &rpi->depth);
+
rpi->cubemap = 0;
//glGenTextures(1, &rpi->cubemap);
@@ -524,8 +538,8 @@ bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance
glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, rpi->depth);
- glTexImage2D(GL_TEXTURE_2D, 0, storage->config.depth_internalformat, size, size, 0, GL_DEPTH_COMPONENT, storage->config.depth_type, NULL);
+ glBindRenderbuffer(GL_RENDERBUFFER, rpi->depth);
+ glRenderbufferStorage(GL_RENDERBUFFER, storage->config.depth_internalformat, size, size);
if (rpi->cubemap != 0) {
glDeleteTextures(1, &rpi->cubemap);
@@ -547,7 +561,7 @@ bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance
glBindTexture(GL_TEXTURE_2D, rpi->color[i]);
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, size, size, 0, format, type, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rpi->color[i], 0);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rpi->depth, 0);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rpi->depth);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
ERR_CONTINUE(status != GL_FRAMEBUFFER_COMPLETE);
}
@@ -566,8 +580,6 @@ bool RasterizerSceneGLES2::reflection_probe_instance_begin_render(RID p_instance
//adjust framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, rpi->fbo[i]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, _cube_side_enum[i], rpi->cubemap, 0);
- glBindRenderbuffer(GL_RENDERBUFFER, rpi->depth);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size, size); // Note: used to be _DEPTH_COMPONENT24_OES. GL_DEPTH_COMPONENT untested.
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rpi->depth);
#ifdef DEBUG_ENABLED
@@ -2511,6 +2523,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements,
state.scene_shader.set_conditional(SceneShaderGLES2::FOG_DEPTH_ENABLED, false);
state.scene_shader.set_conditional(SceneShaderGLES2::FOG_HEIGHT_ENABLED, false);
state.scene_shader.set_conditional(SceneShaderGLES2::USE_RADIANCE_MAP, false);
+ state.scene_shader.set_conditional(SceneShaderGLES2::USE_DEPTH_PREPASS, false);
}
void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy, const Basis &p_sky_orientation) {
@@ -2977,7 +2990,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
if (light->type == VS::LIGHT_OMNI) {
// cubemap only
- if (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_write_depth) {
+ if (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_shadow_cubemaps) {
int cubemap_index = shadow_cubemaps.size() - 1;
// find an appropriate cubemap to render to
@@ -3075,7 +3088,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_
state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH_DUAL_PARABOLOID, false);
// convert cubemap to dual paraboloid if needed
- if (light->type == VS::LIGHT_OMNI && (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_write_depth) && p_pass == 5) {
+ if (light->type == VS::LIGHT_OMNI && (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_shadow_cubemaps) && p_pass == 5) {
ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas);
glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas->fbo);
@@ -3172,7 +3185,7 @@ bool RasterizerSceneGLES2::free(RID p_rid) {
if (reflection_instance->cubemap != 0) {
glDeleteTextures(1, &reflection_instance->cubemap);
}
- glDeleteTextures(1, &reflection_instance->depth);
+ glDeleteRenderbuffers(1, &reflection_instance->depth);
reflection_probe_release_atlas_index(p_rid);
reflection_probe_instance_owner.free(p_rid);
@@ -3253,7 +3266,7 @@ void RasterizerSceneGLES2::initialize() {
}
// cubemaps for shadows
- if (storage->config.support_write_depth) { //not going to be used
+ if (storage->config.support_shadow_cubemaps) { //not going to be used
int max_shadow_cubemap_sampler_size = 512;
int cube_size = max_shadow_cubemap_sampler_size;
@@ -3302,19 +3315,13 @@ void RasterizerSceneGLES2::initialize() {
glGenFramebuffers(1, &directional_shadow.fbo);
glBindFramebuffer(GL_FRAMEBUFFER, directional_shadow.fbo);
- glGenTextures(1, &directional_shadow.depth);
- glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
-
- glTexImage2D(GL_TEXTURE_2D, 0, storage->config.depth_internalformat, directional_shadow.size, directional_shadow.size, 0, GL_DEPTH_COMPONENT, storage->config.depth_type, NULL);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, directional_shadow.depth, 0);
-
if (storage->config.use_rgba_3d_shadows) {
+ //maximum compatibility, renderbuffer and RGBA shadow
+ glGenRenderbuffers(1, &directional_shadow.depth);
+ glBindRenderbuffer(GL_RENDERBUFFER, directional_shadow.depth);
+ glRenderbufferStorage(GL_RENDERBUFFER, storage->config.depth_internalformat, directional_shadow.size, directional_shadow.size);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, directional_shadow.depth);
+
glGenTextures(1, &directional_shadow.color);
glBindTexture(GL_TEXTURE_2D, directional_shadow.color);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, directional_shadow.size, directional_shadow.size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
@@ -3323,6 +3330,19 @@ void RasterizerSceneGLES2::initialize() {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, directional_shadow.color, 0);
+ } else {
+ //just a depth buffer
+ glGenTextures(1, &directional_shadow.depth);
+ glBindTexture(GL_TEXTURE_2D, directional_shadow.depth);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, storage->config.depth_internalformat, directional_shadow.size, directional_shadow.size, 0, GL_DEPTH_COMPONENT, storage->config.depth_type, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, directional_shadow.depth, 0);
}
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h
index fbb8b7e9e5..f23e45b52f 100644
--- a/drivers/gles2/rasterizer_scene_gles2.h
+++ b/drivers/gles2/rasterizer_scene_gles2.h
@@ -475,7 +475,7 @@ public:
virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform);
virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0);
virtual void light_instance_mark_visible(RID p_light_instance);
- virtual bool light_instances_can_render_shadow_cube() const { return storage->config.support_write_depth; }
+ virtual bool light_instances_can_render_shadow_cube() const { return storage->config.support_shadow_cubemaps; }
LightInstance **render_light_instances;
int render_directional_lights;
diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp
index c8650462aa..d5965bba4f 100644
--- a/drivers/gles2/rasterizer_storage_gles2.cpp
+++ b/drivers/gles2/rasterizer_storage_gles2.cpp
@@ -44,8 +44,31 @@ GLuint RasterizerStorageGLES2::system_fbo = 0;
#define _EXT_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
#define _EXT_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
+#define _EXT_COMPRESSED_RED_RGTC1_EXT 0x8DBB
+#define _EXT_COMPRESSED_RED_RGTC1 0x8DBB
+#define _EXT_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC
+#define _EXT_COMPRESSED_RG_RGTC2 0x8DBD
+#define _EXT_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE
+#define _EXT_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC
+#define _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD
+#define _EXT_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE
#define _EXT_ETC1_RGB8_OES 0x8D64
+#define _EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
+#define _EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
+#define _EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
+#define _EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
+
+#define _EXT_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54
+#define _EXT_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT 0x8A55
+#define _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56
+#define _EXT_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57
+
+#define _EXT_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C
+#define _EXT_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D
+#define _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E
+#define _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F
+
#ifdef GLES_OVER_GL
#define _GL_HALF_FLOAT_OES 0x140B
#else
@@ -231,41 +254,130 @@ Ref<Image> RasterizerStorageGLES2::_get_gl_image_and_format(const Ref<Image> &p_
} break;
case Image::FORMAT_RGTC_R: {
- need_decompress = true;
+ if (config.rgtc_supported) {
+
+ r_gl_internal_format = _EXT_COMPRESSED_RED_RGTC1_EXT;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+
+ } else {
+
+ need_decompress = true;
+ }
} break;
case Image::FORMAT_RGTC_RG: {
- need_decompress = true;
+ if (config.rgtc_supported) {
+
+ r_gl_internal_format = _EXT_COMPRESSED_RED_GREEN_RGTC2_EXT;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+ } else {
+
+ need_decompress = true;
+ }
} break;
case Image::FORMAT_BPTC_RGBA: {
- need_decompress = true;
+ if (config.bptc_supported) {
+
+ r_gl_internal_format = _EXT_COMPRESSED_RGBA_BPTC_UNORM;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+
+ } else {
+
+ need_decompress = true;
+ }
} break;
case Image::FORMAT_BPTC_RGBF: {
- need_decompress = true;
+ if (config.bptc_supported) {
+
+ r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_SIGNED_FLOAT;
+ r_gl_format = GL_RGB;
+ r_gl_type = GL_FLOAT;
+ r_compressed = true;
+ } else {
+
+ need_decompress = true;
+ }
} break;
case Image::FORMAT_BPTC_RGBFU: {
+ if (config.bptc_supported) {
- need_decompress = true;
+ r_gl_internal_format = _EXT_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT;
+ r_gl_format = GL_RGB;
+ r_gl_type = GL_FLOAT;
+ r_compressed = true;
+ } else {
+
+ need_decompress = true;
+ }
} break;
case Image::FORMAT_PVRTC2: {
- need_decompress = true;
+ if (config.pvrtc_supported) {
+
+ r_gl_internal_format = _EXT_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+
+ } else {
+
+ need_decompress = true;
+ }
} break;
case Image::FORMAT_PVRTC2A: {
- need_decompress = true;
+ if (config.pvrtc_supported) {
+
+ r_gl_internal_format = _EXT_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+
+ } else {
+
+ need_decompress = true;
+ }
+
} break;
case Image::FORMAT_PVRTC4: {
- need_decompress = true;
+ if (config.pvrtc_supported) {
+
+ r_gl_internal_format = _EXT_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+
+ } else {
+
+ need_decompress = true;
+ }
+
} break;
case Image::FORMAT_PVRTC4A: {
- need_decompress = true;
+ if (config.pvrtc_supported) {
+
+ r_gl_internal_format = _EXT_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
+ r_gl_format = GL_RGBA;
+ r_gl_type = GL_UNSIGNED_BYTE;
+ r_compressed = true;
+
+ } else {
+
+ need_decompress = true;
+ }
+
} break;
case Image::FORMAT_ETC: {
@@ -1223,8 +1335,6 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const {
switch (p_shader->mode) {
- // TODO
-
case VS::SHADER_CANVAS_ITEM: {
p_shader->canvas_item.light_mode = Shader::CanvasItem::LIGHT_MODE_NORMAL;
@@ -1308,7 +1418,11 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const {
actions->uniforms = &p_shader->uniforms;
if (p_shader->spatial.uses_screen_texture && p_shader->spatial.uses_depth_texture) {
- WARN_PRINT("Using both SCREEN_TEXTURE and DEPTH_TEXTURE is not supported in GLES2");
+ ERR_PRINT_ONCE("Using both SCREEN_TEXTURE and DEPTH_TEXTURE is not supported in GLES2");
+ }
+
+ if (p_shader->spatial.uses_depth_texture && !config.support_depth_texture) {
+ ERR_PRINT_ONCE("Using DEPTH_TEXTURE is not permitted on this hardware, operation will fail.");
}
} break;
@@ -2254,9 +2368,14 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS:
surface->aabb = p_aabb;
surface->max_bone = p_bone_aabbs.size();
-
+#ifdef TOOLS_ENABLED
+ surface->blend_shape_data = p_blend_shapes;
+ if (surface->blend_shape_data.size()) {
+ ERR_PRINT_ONCE("Blend shapes are not supported in OpenGL ES 2.0");
+ }
surface->data = array;
surface->index_data = p_index_array;
+#endif
surface->total_data_size += surface->array_byte_size + surface->index_array_byte_size;
@@ -2326,12 +2445,12 @@ void RasterizerStorageGLES2::mesh_set_blend_shape_count(RID p_mesh, int p_amount
ERR_FAIL_COND(p_amount < 0);
mesh->blend_shape_count = p_amount;
+ mesh->instance_change_notify(true, false);
}
int RasterizerStorageGLES2::mesh_get_blend_shape_count(RID p_mesh) const {
const Mesh *mesh = mesh_owner.getornull(p_mesh);
ERR_FAIL_COND_V(!mesh, 0);
-
return mesh->blend_shape_count;
}
@@ -2417,7 +2536,9 @@ PoolVector<uint8_t> RasterizerStorageGLES2::mesh_surface_get_array(RID p_mesh, i
ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), PoolVector<uint8_t>());
Surface *surface = mesh->surfaces[p_surface];
-
+#ifndef TOOLS_ENABLED
+ ERR_PRINT("OpenGL ES 2.0 does not allow retrieving mesh array data");
+#endif
return surface->data;
}
@@ -2457,7 +2578,14 @@ AABB RasterizerStorageGLES2::mesh_surface_get_aabb(RID p_mesh, int p_surface) co
}
Vector<PoolVector<uint8_t> > RasterizerStorageGLES2::mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const {
- return Vector<PoolVector<uint8_t> >();
+ const Mesh *mesh = mesh_owner.getornull(p_mesh);
+ ERR_FAIL_COND_V(!mesh, Vector<PoolVector<uint8_t> >());
+ ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Vector<PoolVector<uint8_t> >());
+#ifndef TOOLS_ENABLED
+ ERR_PRINT("OpenGL ES 2.0 does not allow retrieving mesh array data");
+#endif
+
+ return mesh->surfaces[p_surface]->blend_shape_data;
}
Vector<AABB> RasterizerStorageGLES2::mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const {
const Mesh *mesh = mesh_owner.getornull(p_mesh);
@@ -2476,7 +2604,7 @@ void RasterizerStorageGLES2::mesh_remove_surface(RID p_mesh, int p_surface) {
Surface *surface = mesh->surfaces[p_surface];
if (surface->material.is_valid()) {
- // TODO _material_remove_geometry(surface->material, mesh->surfaces[p_surface]);
+ _material_remove_geometry(surface->material, mesh->surfaces[p_surface]);
}
glDeleteBuffers(1, &surface->vertex_id);
@@ -2524,16 +2652,110 @@ AABB RasterizerStorageGLES2::mesh_get_aabb(RID p_mesh, RID p_skeleton) const {
if (mesh->custom_aabb != AABB())
return mesh->custom_aabb;
- // TODO handle skeletons
+ Skeleton *sk = NULL;
+ if (p_skeleton.is_valid()) {
+ sk = skeleton_owner.get(p_skeleton);
+ }
AABB aabb;
- if (mesh->surfaces.size() >= 1) {
- aabb = mesh->surfaces[0]->aabb;
- }
+ if (sk && sk->size != 0) {
+
+ for (int i = 0; i < mesh->surfaces.size(); i++) {
+
+ AABB laabb;
+ if ((mesh->surfaces[i]->format & VS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->skeleton_bone_aabb.size()) {
+
+ int bs = mesh->surfaces[i]->skeleton_bone_aabb.size();
+ const AABB *skbones = mesh->surfaces[i]->skeleton_bone_aabb.ptr();
+ const bool *skused = mesh->surfaces[i]->skeleton_bone_used.ptr();
- for (int i = 0; i < mesh->surfaces.size(); i++) {
- aabb.merge_with(mesh->surfaces[i]->aabb);
+ int sbs = sk->size;
+ ERR_CONTINUE(bs > sbs);
+ const float *texture = sk->bone_data.ptr();
+
+ bool first = true;
+ if (sk->use_2d) {
+ for (int j = 0; j < bs; j++) {
+
+ if (!skused[j])
+ continue;
+
+ int base_ofs = j * 2 * 4;
+
+ Transform mtx;
+
+ mtx.basis[0].x = texture[base_ofs + 0];
+ mtx.basis[0].y = texture[base_ofs + 1];
+ mtx.origin.x = texture[base_ofs + 3];
+ base_ofs += 256 * 4;
+ mtx.basis[1].x = texture[base_ofs + 0];
+ mtx.basis[1].y = texture[base_ofs + 1];
+ mtx.origin.y = texture[base_ofs + 3];
+
+ AABB baabb = mtx.xform(skbones[j]);
+
+ if (first) {
+ laabb = baabb;
+ first = false;
+ } else {
+ laabb.merge_with(baabb);
+ }
+ }
+ } else {
+ for (int j = 0; j < bs; j++) {
+
+ if (!skused[j])
+ continue;
+
+ int base_ofs = j * 3 * 4;
+
+ Transform mtx;
+
+ mtx.basis[0].x = texture[base_ofs + 0];
+ mtx.basis[0].y = texture[base_ofs + 1];
+ mtx.basis[0].z = texture[base_ofs + 2];
+ mtx.origin.x = texture[base_ofs + 3];
+ base_ofs += 256 * 4;
+ mtx.basis[1].x = texture[base_ofs + 0];
+ mtx.basis[1].y = texture[base_ofs + 1];
+ mtx.basis[1].z = texture[base_ofs + 2];
+ mtx.origin.y = texture[base_ofs + 3];
+ base_ofs += 256 * 4;
+ mtx.basis[2].x = texture[base_ofs + 0];
+ mtx.basis[2].y = texture[base_ofs + 1];
+ mtx.basis[2].z = texture[base_ofs + 2];
+ mtx.origin.z = texture[base_ofs + 3];
+
+ AABB baabb = mtx.xform(skbones[j]);
+ if (first) {
+ laabb = baabb;
+ first = false;
+ } else {
+ laabb.merge_with(baabb);
+ }
+ }
+ }
+
+ } else {
+
+ laabb = mesh->surfaces[i]->aabb;
+ }
+
+ if (i == 0)
+ aabb = laabb;
+ else
+ aabb.merge_with(laabb);
+ }
+ } else {
+
+ for (int i = 0; i < mesh->surfaces.size(); i++) {
+
+ if (i == 0)
+ aabb = mesh->surfaces[i]->aabb;
+ else
+ aabb.merge_with(mesh->surfaces[i]->aabb);
+ }
}
return aabb;
@@ -3227,7 +3449,6 @@ void RasterizerStorageGLES2::skeleton_allocate(RID p_skeleton, int p_bones, bool
skeleton->size = p_bones;
skeleton->use_2d = p_2d_skeleton;
- // TODO use float texture for vertex shader
if (config.float_texture_supported) {
glGenTextures(1, &skeleton->tex_id);
@@ -4306,24 +4527,36 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) {
// depth
- glGenTextures(1, &rt->depth);
- glBindTexture(GL_TEXTURE_2D, rt->depth);
+ if (config.support_depth_texture) {
+ glGenTextures(1, &rt->depth);
+ glBindTexture(GL_TEXTURE_2D, rt->depth);
+ glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, rt->width, rt->height, 0, GL_DEPTH_COMPONENT, config.depth_type, NULL);
- glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, rt->width, rt->height, 0, GL_DEPTH_COMPONENT, config.depth_type, NULL);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
+ } else {
+ glGenRenderbuffers(1, &rt->depth);
+ glBindRenderbuffer(GL_RENDERBUFFER, rt->depth);
+
+ glRenderbufferStorage(GL_RENDERBUFFER, config.depth_internalformat, rt->width, rt->height);
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth);
+ }
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
glDeleteFramebuffers(1, &rt->fbo);
- glDeleteTextures(1, &rt->depth);
+ if (config.support_depth_texture) {
+ glDeleteTextures(1, &rt->depth);
+ } else {
+ glDeleteRenderbuffers(1, &rt->depth);
+ }
glDeleteTextures(1, &rt->color);
rt->fbo = 0;
rt->width = 0;
@@ -4395,7 +4628,12 @@ void RasterizerStorageGLES2::_render_target_clear(RenderTarget *rt) {
}
if (rt->depth) {
- glDeleteTextures(1, &rt->depth);
+ if (config.support_depth_texture) {
+ glDeleteTextures(1, &rt->depth);
+ } else {
+ glDeleteRenderbuffers(1, &rt->depth);
+ }
+
rt->depth = 0;
}
@@ -4533,17 +4771,10 @@ RID RasterizerStorageGLES2::canvas_light_shadow_buffer_create(int p_width) {
glGenFramebuffers(1, &cls->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, cls->fbo);
- glGenTextures(1, &cls->depth);
- glBindTexture(GL_TEXTURE_2D, cls->depth);
-
- glTexImage2D(GL_TEXTURE_2D, 0, config.depth_internalformat, cls->size, cls->height, 0, GL_DEPTH_COMPONENT, config.depth_type, NULL);
-
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
- glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, cls->depth, 0);
+ glGenRenderbuffers(1, &cls->depth);
+ glBindRenderbuffer(GL_RENDERBUFFER, cls->depth);
+ glRenderbufferStorage(GL_RENDERBUFFER, config.depth_internalformat, cls->size, cls->height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, cls->depth);
glGenTextures(1, &cls->distance);
glBindTexture(GL_TEXTURE_2D, cls->distance);
@@ -4908,7 +5139,7 @@ bool RasterizerStorageGLES2::free(RID p_rid) {
CanvasLightShadow *cls = canvas_light_shadow_owner.get(p_rid);
glDeleteFramebuffers(1, &cls->fbo);
- glDeleteTextures(1, &cls->depth);
+ glDeleteRenderbuffers(1, &cls->depth);
glDeleteTextures(1, &cls->distance);
canvas_light_shadow_owner.free(p_rid);
memdelete(cls);
@@ -4986,21 +5217,17 @@ void RasterizerStorageGLES2::initialize() {
config.pvrtc_supported = config.extensions.has("IMG_texture_compression_pvrtc");
config.support_npot_repeat_mipmap = config.extensions.has("GL_OES_texture_npot");
- if (config.extensions.has("GL_OES_depth24")) {
- config.depth_internalformat = _DEPTH_COMPONENT24_OES;
- config.depth_type = GL_UNSIGNED_INT;
- } else {
- config.depth_internalformat = GL_DEPTH_COMPONENT16;
- config.depth_type = GL_UNSIGNED_SHORT;
- }
-
#endif
#ifdef GLES_OVER_GL
config.use_rgba_2d_shadows = false;
+ config.support_depth_texture = true;
config.use_rgba_3d_shadows = false;
+ config.support_depth_cubemaps = true;
#else
config.use_rgba_2d_shadows = !(config.float_texture_supported && config.extensions.has("GL_EXT_texture_rg"));
- config.use_rgba_3d_shadows = config.extensions.has("GL_OES_depth_texture");
+ config.support_depth_texture = config.extensions.has("GL_OES_depth_texture");
+ config.use_rgba_3d_shadows = !config.support_depth_texture;
+ config.support_depth_cubemaps = config.extensions.has("GL_OES_depth_texture_cube_map");
#endif
#ifdef GLES_OVER_GL
@@ -5024,6 +5251,58 @@ void RasterizerStorageGLES2::initialize() {
config.support_half_float_vertices = true;
#endif
+ config.rgtc_supported = config.extensions.has("GL_EXT_texture_compression_rgtc") || config.extensions.has("GL_ARB_texture_compression_rgtc") || config.extensions.has("EXT_texture_compression_rgtc");
+ config.bptc_supported = config.extensions.has("GL_ARB_texture_compression_bptc");
+
+ //determine formats for depth textures (or renderbuffers)
+ if (config.support_depth_texture) {
+ // Will use texture for depth
+ // have to manually see if we can create a valid framebuffer texture using UNSIGNED_INT,
+ // as there is no extension to test for this.
+ GLuint fbo;
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ GLuint depth;
+ glGenTextures(1, &depth);
+ glBindTexture(GL_TEXTURE_2D, depth);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, 32, 32, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, 0);
+
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+
+ if (status == GL_FRAMEBUFFER_COMPLETE) {
+ config.depth_internalformat = GL_DEPTH_COMPONENT;
+ config.depth_type = GL_UNSIGNED_INT;
+ } else {
+ config.depth_internalformat = GL_DEPTH_COMPONENT16;
+ config.depth_type = GL_UNSIGNED_SHORT;
+ }
+
+ glBindFramebuffer(GL_FRAMEBUFFER, system_fbo);
+ glDeleteFramebuffers(1, &fbo);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glDeleteTextures(1, &depth);
+
+ } else {
+ // Will use renderbuffer for depth
+ if (config.extensions.has("GL_OES_depth24")) {
+ config.depth_internalformat = _DEPTH_COMPONENT24_OES;
+ config.depth_type = GL_UNSIGNED_INT;
+ } else {
+ config.depth_internalformat = GL_DEPTH_COMPONENT16;
+ config.depth_type = GL_UNSIGNED_SHORT;
+ }
+ }
+
+ //picky requirements for these
+ config.support_shadow_cubemaps = config.support_depth_texture && config.support_write_depth && config.support_depth_cubemaps;
+
frame.count = 0;
frame.delta = 0;
frame.current_rt = NULL;
diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h
index 89f4381bed..e6c23716a5 100644
--- a/drivers/gles2/rasterizer_storage_gles2.h
+++ b/drivers/gles2/rasterizer_storage_gles2.h
@@ -73,6 +73,8 @@ public:
bool s3tc_supported;
bool etc1_supported;
bool pvrtc_supported;
+ bool rgtc_supported;
+ bool bptc_supported;
bool keep_original_textures;
@@ -85,6 +87,10 @@ public:
bool support_write_depth;
bool support_half_float_vertices;
bool support_npot_repeat_mipmap;
+ bool support_depth_texture;
+ bool support_depth_cubemaps;
+
+ bool support_shadow_cubemaps;
GLuint depth_internalformat;
GLuint depth_type;
@@ -631,6 +637,7 @@ public:
PoolVector<uint8_t> data;
PoolVector<uint8_t> index_data;
+ Vector<PoolVector<uint8_t> > blend_shape_data;
int total_data_size;
diff --git a/drivers/gles2/shader_gles2.cpp b/drivers/gles2/shader_gles2.cpp
index 6856035470..df7b170bf4 100644
--- a/drivers/gles2/shader_gles2.cpp
+++ b/drivers/gles2/shader_gles2.cpp
@@ -839,7 +839,7 @@ void ShaderGLES2::use_material(void *p_material) {
} break;
default: {
- ERR_PRINT("type missing, bug?");
+ ERR_PRINT("ShaderNode type missing, bug?");
} break;
}
} else if (E->get().default_value.size()) {
@@ -970,7 +970,126 @@ void ShaderGLES2::use_material(void *p_material) {
// Nothing to do?
} break;
default: {
- ERR_PRINT("type missing, bug?");
+ ERR_PRINT("ShaderNode type missing, bug?");
+ } break;
+ }
+ } else { //zero
+
+ switch (E->get().type) {
+ case ShaderLanguage::TYPE_BOOL: {
+ glUniform1i(location, GL_FALSE);
+ } break;
+
+ case ShaderLanguage::TYPE_BVEC2: {
+ glUniform2i(location, GL_FALSE, GL_FALSE);
+ } break;
+
+ case ShaderLanguage::TYPE_BVEC3: {
+ glUniform3i(location, GL_FALSE, GL_FALSE, GL_FALSE);
+ } break;
+
+ case ShaderLanguage::TYPE_BVEC4: {
+ glUniform4i(location, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ } break;
+
+ case ShaderLanguage::TYPE_INT: {
+ glUniform1i(location, 0);
+ } break;
+
+ case ShaderLanguage::TYPE_IVEC2: {
+ glUniform2i(location, 0, 0);
+ } break;
+
+ case ShaderLanguage::TYPE_IVEC3: {
+ glUniform3i(location, 0, 0, 0);
+ } break;
+
+ case ShaderLanguage::TYPE_IVEC4: {
+ glUniform4i(location, 0, 0, 0, 0);
+ } break;
+
+ case ShaderLanguage::TYPE_UINT: {
+ glUniform1i(location, 0);
+ } break;
+
+ case ShaderLanguage::TYPE_UVEC2: {
+ glUniform2i(location, 0, 0);
+ } break;
+
+ case ShaderLanguage::TYPE_UVEC3: {
+ glUniform3i(location, 0, 0, 0);
+ } break;
+
+ case ShaderLanguage::TYPE_UVEC4: {
+ glUniform4i(location, 0, 0, 0, 0);
+ } break;
+
+ case ShaderLanguage::TYPE_FLOAT: {
+ glUniform1f(location, 0);
+ } break;
+
+ case ShaderLanguage::TYPE_VEC2: {
+ glUniform2f(location, 0, 0);
+ } break;
+
+ case ShaderLanguage::TYPE_VEC3: {
+ glUniform3f(location, 0, 0, 0);
+ } break;
+
+ case ShaderLanguage::TYPE_VEC4: {
+ glUniform4f(location, 0, 0, 0, 0);
+ } break;
+
+ case ShaderLanguage::TYPE_MAT2: {
+ GLfloat mat[4] = { 0, 0, 0, 0 };
+
+ glUniformMatrix2fv(location, 1, GL_FALSE, mat);
+ } break;
+
+ case ShaderLanguage::TYPE_MAT3: {
+ GLfloat mat[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ glUniformMatrix3fv(location, 1, GL_FALSE, mat);
+
+ } break;
+
+ case ShaderLanguage::TYPE_MAT4: {
+ GLfloat mat[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+ glUniformMatrix4fv(location, 1, GL_FALSE, mat);
+
+ } break;
+
+ case ShaderLanguage::TYPE_SAMPLER2D: {
+
+ } break;
+
+ case ShaderLanguage::TYPE_ISAMPLER2D: {
+
+ } break;
+
+ case ShaderLanguage::TYPE_USAMPLER2D: {
+
+ } break;
+
+ case ShaderLanguage::TYPE_SAMPLERCUBE: {
+
+ } break;
+
+ case ShaderLanguage::TYPE_SAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_ISAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_USAMPLER2DARRAY:
+ case ShaderLanguage::TYPE_SAMPLER3D:
+ case ShaderLanguage::TYPE_ISAMPLER3D:
+ case ShaderLanguage::TYPE_USAMPLER3D: {
+ // Not implemented in GLES2
+ } break;
+
+ case ShaderLanguage::TYPE_VOID: {
+ // Nothing to do?
+ } break;
+ default: {
+ ERR_PRINT("ShaderNode type missing, bug?");
} break;
}
}
diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp
index ccd5fff99f..fdfa4a72e4 100644
--- a/drivers/gles3/rasterizer_storage_gles3.cpp
+++ b/drivers/gles3/rasterizer_storage_gles3.cpp
@@ -3634,6 +3634,7 @@ void RasterizerStorageGLES3::mesh_set_blend_shape_count(RID p_mesh, int p_amount
ERR_FAIL_COND(p_amount < 0);
mesh->blend_shape_count = p_amount;
+ mesh->instance_change_notify(true, false);
}
int RasterizerStorageGLES3::mesh_get_blend_shape_count(RID p_mesh) const {
diff --git a/drivers/windows/dir_access_windows.cpp b/drivers/windows/dir_access_windows.cpp
index 499bb4f34b..2f705ec87d 100644
--- a/drivers/windows/dir_access_windows.cpp
+++ b/drivers/windows/dir_access_windows.cpp
@@ -348,11 +348,10 @@ size_t DirAccessWindows::get_space_left() {
String DirAccessWindows::get_filesystem_type() const {
String path = fix_path(const_cast<DirAccessWindows *>(this)->get_current_dir());
- print_line("fixed path: " + path);
+
int unit_end = path.find(":");
ERR_FAIL_COND_V(unit_end == -1, String());
String unit = path.substr(0, unit_end + 1) + "\\";
- print_line("unit: " + unit);
WCHAR szVolumeName[100];
WCHAR szFileSystemName[10];
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index 765a330aaf..cdc06503e9 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -75,7 +75,7 @@ void EditorFileDialog::_notification(int p_what) {
preview_wheel_index++;
if (preview_wheel_index >= 8)
preview_wheel_index = 0;
- Ref<Texture> frame = get_icon("WaitPreview" + itos(preview_wheel_index + 1), "EditorIcons");
+ Ref<Texture> frame = get_icon("Progress" + itos(preview_wheel_index + 1), "EditorIcons");
preview->set_texture(frame);
preview_wheel_timeout = 0.1;
}
@@ -323,11 +323,10 @@ void EditorFileDialog::_request_single_thumbnail(const String &p_path) {
if (!FileAccess::exists(p_path))
return;
- EditorResourcePreview::get_singleton()->queue_resource_preview(p_path, this, "_thumbnail_done", p_path);
-
set_process(true);
preview_waiting = true;
preview_wheel_timeout = 0;
+ EditorResourcePreview::get_singleton()->queue_resource_preview(p_path, this, "_thumbnail_done", p_path);
}
void EditorFileDialog::_action_pressed() {
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 8a9835c977..b36afaef88 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -2852,7 +2852,7 @@ bool EditorNode::is_changing_scene() const {
void EditorNode::_clear_undo_history() {
- get_undo_redo()->clear_history();
+ get_undo_redo()->clear_history(false);
}
void EditorNode::set_current_scene(int p_idx) {
diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp
index e0c292dc87..9345ea6b6f 100644
--- a/editor/editor_resource_preview.cpp
+++ b/editor/editor_resource_preview.cpp
@@ -313,6 +313,8 @@ void EditorResourcePreview::_thread() {
preview_mutex->unlock();
}
}
+
+ exited = true;
}
void EditorResourcePreview::queue_edited_resource_preview(const Ref<Resource> &p_res, Object *p_receiver, const StringName &p_receiver_func, const Variant &p_userdata) {
@@ -420,11 +422,16 @@ void EditorResourcePreview::check_for_invalidation(const String &p_path) {
void EditorResourcePreview::start() {
ERR_FAIL_COND(thread);
thread = Thread::create(_thread_func, this);
+ exited = false;
}
void EditorResourcePreview::stop() {
if (thread) {
exit = true;
preview_sem->post();
+ while (!exited) {
+ OS::get_singleton()->delay_usec(10000);
+ VisualServer::get_singleton()->sync(); //sync pending stuff, as thread may be blocked on visual server
+ }
Thread::wait_to_finish(thread);
memdelete(thread);
thread = NULL;
@@ -438,6 +445,7 @@ EditorResourcePreview::EditorResourcePreview() {
preview_sem = Semaphore::create();
order = 0;
exit = false;
+ exited = false;
}
EditorResourcePreview::~EditorResourcePreview() {
diff --git a/editor/editor_resource_preview.h b/editor/editor_resource_preview.h
index c958bfbb74..703ba34e43 100644
--- a/editor/editor_resource_preview.h
+++ b/editor/editor_resource_preview.h
@@ -90,7 +90,8 @@ class EditorResourcePreview : public Node {
Mutex *preview_mutex;
Semaphore *preview_sem;
Thread *thread;
- bool exit;
+ volatile bool exit;
+ volatile bool exited;
struct Item {
Ref<Texture> preview;
diff --git a/editor/import/editor_scene_importer_gltf.cpp b/editor/import/editor_scene_importer_gltf.cpp
index ff2f68ffd3..3909d437e5 100644
--- a/editor/import/editor_scene_importer_gltf.cpp
+++ b/editor/import/editor_scene_importer_gltf.cpp
@@ -892,9 +892,11 @@ Error EditorSceneImporterGLTF::_parse_meshes(GLTFState &state) {
primitive = primitives2[mode];
}
+ ERR_FAIL_COND_V(!a.has("POSITION"), ERR_PARSE_ERROR);
if (a.has("POSITION")) {
array[Mesh::ARRAY_VERTEX] = _decode_accessor_as_vec3(state, a["POSITION"], true);
}
+
if (a.has("NORMAL")) {
array[Mesh::ARRAY_NORMAL] = _decode_accessor_as_vec3(state, a["NORMAL"], true);
}
diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp
index 5b34aaa92a..75417d986c 100644
--- a/editor/plugins/tile_set_editor_plugin.cpp
+++ b/editor/plugins/tile_set_editor_plugin.cpp
@@ -201,6 +201,7 @@ void TileSetEditor::_bind_methods() {
ClassDB::bind_method("_zoom_out", &TileSetEditor::_zoom_out);
ClassDB::bind_method("_zoom_reset", &TileSetEditor::_zoom_reset);
ClassDB::bind_method("_select_edited_shape_coord", &TileSetEditor::_select_edited_shape_coord);
+ ClassDB::bind_method("_sort_tiles", &TileSetEditor::_sort_tiles);
ClassDB::bind_method("edit", &TileSetEditor::edit);
ClassDB::bind_method("add_texture", &TileSetEditor::add_texture);
@@ -234,6 +235,8 @@ void TileSetEditor::_notification(int p_what) {
tools[BITMASK_CLEAR]->set_icon(get_icon("Clear", "EditorIcons"));
tools[SHAPE_NEW_POLYGON]->set_icon(get_icon("CollisionPolygon2D", "EditorIcons"));
tools[SHAPE_NEW_RECTANGLE]->set_icon(get_icon("CollisionShape2D", "EditorIcons"));
+ tools[SELECT_PREVIOUS]->set_icon(get_icon("ArrowLeft", "EditorIcons"));
+ tools[SELECT_NEXT]->set_icon(get_icon("ArrowRight", "EditorIcons"));
tools[SHAPE_DELETE]->set_icon(get_icon("Remove", "EditorIcons"));
tools[SHAPE_KEEP_INSIDE_TILE]->set_icon(get_icon("Snap", "EditorIcons"));
tools[TOOL_GRID_SNAP]->set_icon(get_icon("SnapGrid", "EditorIcons"));
@@ -241,6 +244,7 @@ void TileSetEditor::_notification(int p_what) {
tools[ZOOM_1]->set_icon(get_icon("ZoomReset", "EditorIcons"));
tools[ZOOM_IN]->set_icon(get_icon("ZoomMore", "EditorIcons"));
tools[VISIBLE_INFO]->set_icon(get_icon("InformationSign", "EditorIcons"));
+ _update_toggle_shape_button();
tool_editmode[EDITMODE_REGION]->set_icon(get_icon("RegionEdit", "EditorIcons"));
tool_editmode[EDITMODE_COLLISION]->set_icon(get_icon("StaticBody2D", "EditorIcons"));
@@ -324,11 +328,29 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) {
tool_workspacemode[i]->connect("pressed", this, "_on_workspace_mode_changed", varray(i));
tool_hb->add_child(tool_workspacemode[i]);
}
+
Control *spacer = memnew(Control);
spacer->set_h_size_flags(Control::SIZE_EXPAND_FILL);
tool_hb->add_child(spacer);
tool_hb->move_child(spacer, WORKSPACE_CREATE_SINGLE);
+ tools[SELECT_NEXT] = memnew(ToolButton);
+ tool_hb->add_child(tools[SELECT_NEXT]);
+ tool_hb->move_child(tools[SELECT_NEXT], WORKSPACE_CREATE_SINGLE);
+ tools[SELECT_NEXT]->set_shortcut(ED_SHORTCUT("tileset_editor/next_shape", TTR("Select next coordinate"), KEY_PAGEDOWN));
+ tools[SELECT_NEXT]->connect("pressed", this, "_on_tool_clicked", varray(SELECT_NEXT));
+ tools[SELECT_NEXT]->set_tooltip(TTR("Select the next shape, subtile, or Tile."));
+ tools[SELECT_PREVIOUS] = memnew(ToolButton);
+ tool_hb->add_child(tools[SELECT_PREVIOUS]);
+ tool_hb->move_child(tools[SELECT_PREVIOUS], WORKSPACE_CREATE_SINGLE);
+ tools[SELECT_PREVIOUS]->set_shortcut(ED_SHORTCUT("tileset_editor/previous_shape", TTR("Select previous coordinate"), KEY_PAGEUP));
+ tools[SELECT_PREVIOUS]->set_tooltip(TTR("Select the previous shape, subtile, or Tile."));
+ tools[SELECT_PREVIOUS]->connect("pressed", this, "_on_tool_clicked", varray(SELECT_PREVIOUS));
+
+ VSeparator *separator_shape_selection = memnew(VSeparator);
+ tool_hb->add_child(separator_shape_selection);
+ tool_hb->move_child(separator_shape_selection, WORKSPACE_CREATE_SINGLE);
+
tool_workspacemode[WORKSPACE_EDIT]->set_pressed(true);
workspace_mode = WORKSPACE_EDIT;
@@ -391,6 +413,12 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) {
tools[SHAPE_NEW_POLYGON]->set_button_group(tg);
tools[SHAPE_NEW_POLYGON]->set_tooltip(TTR("Create a new polygon."));
+ separator_shape_toggle = memnew(VSeparator);
+ toolbar->add_child(separator_shape_toggle);
+ tools[SHAPE_TOGGLE_TYPE] = memnew(ToolButton);
+ tools[SHAPE_TOGGLE_TYPE]->connect("pressed", this, "_on_tool_clicked", varray(SHAPE_TOGGLE_TYPE));
+ toolbar->add_child(tools[SHAPE_TOGGLE_TYPE]);
+
separator_delete = memnew(VSeparator);
toolbar->add_child(separator_delete);
tools[SHAPE_DELETE] = memnew(ToolButton);
@@ -744,6 +772,7 @@ void TileSetEditor::_on_edit_mode_changed(int p_edit_mode) {
} break;
default: {}
}
+ _update_toggle_shape_button();
workspace->update();
}
@@ -1375,8 +1404,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
}
undo_redo->create_action(TTR("Edit Collision Polygon"));
- undo_redo->add_do_method(edited_collision_shape.ptr(), "set_points", points);
- undo_redo->add_undo_method(edited_collision_shape.ptr(), "set_points", edited_collision_shape->get_points());
+ _set_edited_shape_points(points);
undo_redo->add_do_method(this, "_select_edited_shape_coord");
undo_redo->add_undo_method(this, "_select_edited_shape_coord");
undo_redo->commit_action();
@@ -1454,7 +1482,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
workspace->update();
} else {
creating_shape = true;
- edited_collision_shape = Ref<ConvexPolygonShape2D>();
+ _set_edited_collision_shape(Ref<ConvexPolygonShape2D>());
current_shape.resize(0);
current_shape.push_back(snap_point(pos));
workspace->update();
@@ -1474,7 +1502,7 @@ void TileSetEditor::_on_workspace_input(const Ref<InputEvent> &p_ie) {
} else if (tools[SHAPE_NEW_RECTANGLE]->is_pressed()) {
if (mb.is_valid()) {
if (mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
- edited_collision_shape = Ref<ConvexPolygonShape2D>();
+ _set_edited_collision_shape(Ref<ConvexPolygonShape2D>());
current_shape.resize(0);
current_shape.push_back(snap_point(shape_anchor));
current_shape.push_back(snap_point(shape_anchor + Vector2(current_tile_region.size.x, 0)));
@@ -1519,6 +1547,49 @@ void TileSetEditor::_on_tool_clicked(int p_tool) {
undo_redo->add_do_method(workspace, "update");
undo_redo->add_undo_method(workspace, "update");
undo_redo->commit_action();
+ } else if (p_tool == SHAPE_TOGGLE_TYPE) {
+ if (edited_collision_shape.is_valid()) {
+ Ref<ConvexPolygonShape2D> convex = edited_collision_shape;
+ Ref<ConcavePolygonShape2D> concave = edited_collision_shape;
+ Ref<Shape2D> previous_shape = edited_collision_shape;
+ Array sd = tileset->call("tile_get_shapes", get_current_tile());
+
+ if (convex.is_valid()) {
+ // Make concave
+ undo_redo->create_action(TTR("Make Polygon Concave"));
+ Ref<ConcavePolygonShape2D> _concave = memnew(ConcavePolygonShape2D);
+ edited_collision_shape = _concave;
+ _set_edited_shape_points(_get_collision_shape_points(convex));
+ } else if (concave.is_valid()) {
+ // Make convex
+ undo_redo->create_action(TTR("Make Polygon Convex"));
+ Ref<ConvexPolygonShape2D> _convex = memnew(ConvexPolygonShape2D);
+ edited_collision_shape = _convex;
+ _set_edited_shape_points(_get_collision_shape_points(concave));
+ } else {
+ // Shoudn't haphen
+ }
+ for (int i = 0; i < sd.size(); i++) {
+ if (sd[i].get("shape") == previous_shape) {
+ undo_redo->add_undo_method(tileset.ptr(), "tile_set_shapes", get_current_tile(), sd.duplicate());
+ sd.remove(i);
+ sd.insert(i, edited_collision_shape);
+ undo_redo->add_do_method(tileset.ptr(), "tile_set_shapes", get_current_tile(), sd);
+ undo_redo->add_do_method(this, "_select_edited_shape_coord");
+ undo_redo->add_undo_method(this, "_select_edited_shape_coord");
+ undo_redo->commit_action();
+ break;
+ }
+ }
+ _update_toggle_shape_button();
+ workspace->update();
+ workspace_container->update();
+ helper->_change_notify("");
+ }
+ } else if (p_tool == SELECT_NEXT) {
+ _select_next_shape();
+ } else if (p_tool == SELECT_PREVIOUS) {
+ _select_previous_shape();
} else if (p_tool == SHAPE_DELETE) {
if (creating_shape) {
creating_shape = false;
@@ -1641,6 +1712,378 @@ void TileSetEditor::_on_grid_snap_toggled(bool p_val) {
workspace->update();
}
+Vector<Vector2> TileSetEditor::_get_collision_shape_points(const Ref<Shape2D> &p_shape) {
+ Ref<ConvexPolygonShape2D> convex = p_shape;
+ Ref<ConcavePolygonShape2D> concave = p_shape;
+ if (convex.is_valid()) {
+ return convex->get_points();
+ } else if (concave.is_valid()) {
+ Vector<Vector2> points;
+ for (int i = 0; i < concave->get_segments().size(); i += 2) {
+ points.push_back(concave->get_segments()[i]);
+ }
+ return points;
+ } else {
+ return Vector<Vector2>();
+ }
+}
+
+Vector<Vector2> TileSetEditor::_get_edited_shape_points() {
+ return _get_collision_shape_points(edited_collision_shape);
+}
+
+void TileSetEditor::_set_edited_shape_points(const Vector<Vector2> points) {
+ Ref<ConvexPolygonShape2D> convex = edited_collision_shape;
+ Ref<ConcavePolygonShape2D> concave = edited_collision_shape;
+ if (convex.is_valid()) {
+ undo_redo->add_do_method(convex.ptr(), "set_points", points);
+ undo_redo->add_undo_method(convex.ptr(), "set_points", _get_edited_shape_points());
+ } else if (concave.is_valid()) {
+ PoolVector2Array segments;
+ for (int i = 0; i < points.size() - 1; i++) {
+ segments.push_back(points[i]);
+ segments.push_back(points[i + 1]);
+ }
+ segments.push_back(points[points.size() - 1]);
+ segments.push_back(points[0]);
+ concave->set_segments(segments);
+ undo_redo->add_do_method(concave.ptr(), "set_segments", segments);
+ undo_redo->add_undo_method(concave.ptr(), "set_segments", concave->get_segments());
+ } else {
+ // Invalid shape
+ }
+}
+
+void TileSetEditor::_update_tile_data() {
+ current_tile_data.clear();
+ if (get_current_tile() < 0)
+ return;
+
+ Vector<TileSet::ShapeData> sd = tileset->tile_get_shapes(get_current_tile());
+ if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) {
+ SubtileData data;
+ for (int i = 0; i < sd.size(); i++) {
+ data.collisions.push_back(sd[i].shape);
+ }
+ data.navigation_shape = tileset->tile_get_navigation_polygon(get_current_tile());
+ data.occlusion_shape = tileset->tile_get_light_occluder(get_current_tile());
+ current_tile_data[Vector2i()] = data;
+ } else {
+ int spacing = tileset->autotile_get_spacing(get_current_tile());
+ Vector2 size = tileset->tile_get_region(get_current_tile()).size;
+ Vector2i cell_count = size / (tileset->autotile_get_size(get_current_tile()) + Vector2(spacing, spacing));
+ for (int y = 0; y < cell_count.y; y++) {
+ for (int x = 0; x < cell_count.x; x++) {
+ SubtileData data;
+ Vector2i coord(x, y);
+ for (int i = 0; i < sd.size(); i++) {
+ if (sd[i].autotile_coord == coord) {
+ data.collisions.push_back(sd[i].shape);
+ }
+ }
+ data.navigation_shape = tileset->autotile_get_navigation_polygon(get_current_tile(), coord);
+ data.occlusion_shape = tileset->tile_get_light_occluder(get_current_tile());
+ current_tile_data[coord] = data;
+ }
+ }
+ }
+}
+
+void TileSetEditor::_update_toggle_shape_button() {
+ Ref<ConvexPolygonShape2D> convex = edited_collision_shape;
+ Ref<ConcavePolygonShape2D> concave = edited_collision_shape;
+ separator_shape_toggle->show();
+ tools[SHAPE_TOGGLE_TYPE]->show();
+ if (edit_mode != EDITMODE_COLLISION || !edited_collision_shape.is_valid()) {
+ separator_shape_toggle->hide();
+ tools[SHAPE_TOGGLE_TYPE]->hide();
+ } else if (concave.is_valid()) {
+ tools[SHAPE_TOGGLE_TYPE]->set_icon(get_icon("ConvexPolygonShape2D", "EditorIcons"));
+ tools[SHAPE_TOGGLE_TYPE]->set_text("Make Convex");
+ } else if (convex.is_valid()) {
+ tools[SHAPE_TOGGLE_TYPE]->set_icon(get_icon("ConcavePolygonShape2D", "EditorIcons"));
+ tools[SHAPE_TOGGLE_TYPE]->set_text("Make Concave");
+ } else {
+ // Shoudn't happen
+ separator_shape_toggle->hide();
+ tools[SHAPE_TOGGLE_TYPE]->hide();
+ }
+}
+
+void TileSetEditor::_select_next_tile() {
+ Array tiles = _get_tiles_in_current_texture(true);
+ if (tiles.size() == 0) {
+ set_current_tile(-1);
+ } else if (get_current_tile() == -1) {
+ set_current_tile(tiles[0]);
+ } else {
+ int index = tiles.find(get_current_tile());
+ if (index < 0) {
+ set_current_tile(tiles[0]);
+ } else if (index == tiles.size() - 1) {
+ set_current_tile(tiles[0]);
+ } else {
+ set_current_tile(tiles[index + 1]);
+ }
+ }
+ if (get_current_tile() == -1) {
+ return;
+ } else if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) {
+ return;
+ } else {
+ switch (edit_mode) {
+ case EDITMODE_COLLISION:
+ case EDITMODE_OCCLUSION:
+ case EDITMODE_NAVIGATION:
+ case EDITMODE_PRIORITY:
+ case EDITMODE_Z_INDEX: {
+ edited_shape_coord = Vector2();
+ _select_edited_shape_coord();
+ } break;
+ default: {}
+ }
+ }
+}
+
+void TileSetEditor::_select_previous_tile() {
+ Array tiles = _get_tiles_in_current_texture(true);
+ if (tiles.size() == 0) {
+ set_current_tile(-1);
+ } else if (get_current_tile() == -1) {
+ set_current_tile(tiles[tiles.size() - 1]);
+ } else {
+ int index = tiles.find(get_current_tile());
+ if (index <= 0) {
+ set_current_tile(tiles[tiles.size() - 1]);
+ } else {
+ set_current_tile(tiles[index - 1]);
+ }
+ }
+ if (get_current_tile() == -1) {
+ return;
+ } else if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) {
+ return;
+ } else {
+ switch (edit_mode) {
+ case EDITMODE_COLLISION:
+ case EDITMODE_OCCLUSION:
+ case EDITMODE_NAVIGATION:
+ case EDITMODE_PRIORITY:
+ case EDITMODE_Z_INDEX: {
+ int spacing = tileset->autotile_get_spacing(get_current_tile());
+ Vector2 size = tileset->tile_get_region(get_current_tile()).size;
+ Vector2i cell_count = size / (tileset->autotile_get_size(get_current_tile()) + Vector2(spacing, spacing));
+ cell_count -= Vector2(1, 1);
+ edited_shape_coord = cell_count;
+ _select_edited_shape_coord();
+ } break;
+ default: {}
+ }
+ }
+}
+
+Array TileSetEditor::_get_tiles_in_current_texture(bool sorted) {
+ Array a;
+ List<int> all_tiles;
+ if (!get_current_texture().is_valid()) {
+ return a;
+ }
+ tileset->get_tile_list(&all_tiles);
+ for (int i = 0; i < all_tiles.size(); i++) {
+ if (tileset->tile_get_texture(all_tiles[i]) == get_current_texture()) {
+ a.push_back(all_tiles[i]);
+ }
+ }
+ if (sorted) {
+ a.sort_custom(this, "_sort_tiles");
+ }
+ return a;
+}
+
+bool TileSetEditor::_sort_tiles(Variant p_a, Variant p_b) {
+ int a = p_a;
+ int b = p_b;
+
+ Vector2 pos_a = tileset->tile_get_region(a).position;
+ Vector2 pos_b = tileset->tile_get_region(b).position;
+ if (pos_a.y < pos_b.y) {
+ return true;
+
+ } else if (pos_a.y == pos_b.y) {
+ if (pos_a.x < pos_b.x) {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+}
+
+void TileSetEditor::_select_next_subtile() {
+ if (get_current_tile() == -1) {
+ _select_next_tile();
+ return;
+ }
+ if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) {
+ _select_next_tile();
+ } else if (edit_mode == EDITMODE_REGION || edit_mode == EDITMODE_BITMASK || edit_mode == EDITMODE_ICON) {
+ _select_next_tile();
+ } else {
+ int spacing = tileset->autotile_get_spacing(get_current_tile());
+ Vector2 size = tileset->tile_get_region(get_current_tile()).size;
+ Vector2i cell_count = size / (tileset->autotile_get_size(get_current_tile()) + Vector2(spacing, spacing));
+ if (edited_shape_coord.x >= cell_count.x - 1 && edited_shape_coord.y >= cell_count.y - 1) {
+ _select_next_tile();
+ } else {
+ edited_shape_coord.x++;
+ if (edited_shape_coord.x >= cell_count.x) {
+ edited_shape_coord.x = 0;
+ edited_shape_coord.y++;
+ }
+ _select_edited_shape_coord();
+ }
+ }
+}
+
+void TileSetEditor::_select_previous_subtile() {
+ if (get_current_tile() == -1) {
+ _select_previous_tile();
+ return;
+ }
+ if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) {
+ _select_previous_tile();
+ } else if (edit_mode == EDITMODE_REGION || edit_mode == EDITMODE_BITMASK || edit_mode == EDITMODE_ICON) {
+ _select_previous_tile();
+ } else {
+ int spacing = tileset->autotile_get_spacing(get_current_tile());
+ Vector2 size = tileset->tile_get_region(get_current_tile()).size;
+ Vector2i cell_count = size / (tileset->autotile_get_size(get_current_tile()) + Vector2(spacing, spacing));
+ if (edited_shape_coord.x <= 0 && edited_shape_coord.y <= 0) {
+ _select_previous_tile();
+ } else {
+ edited_shape_coord.x--;
+ if (edited_shape_coord.x == -1) {
+ edited_shape_coord.x = cell_count.x - 1;
+ edited_shape_coord.y--;
+ }
+ _select_edited_shape_coord();
+ }
+ }
+}
+
+void TileSetEditor::_select_next_shape() {
+ if (get_current_tile() == -1) {
+ _select_next_subtile();
+ } else if (edit_mode != EDITMODE_COLLISION) {
+ _select_next_subtile();
+ } else {
+ Vector2i edited_coord = Vector2();
+ if (tileset->tile_get_tile_mode(get_current_tile()) != TileSet::SINGLE_TILE) {
+ edited_coord = edited_shape_coord;
+ }
+ SubtileData data = current_tile_data[edited_coord];
+ if (data.collisions.size() == 0) {
+ _select_next_subtile();
+ } else {
+ int index = data.collisions.find(edited_collision_shape);
+ if (index < 0) {
+ _set_edited_collision_shape(data.collisions[0]);
+ } else if (index == data.collisions.size() - 1) {
+ _select_next_subtile();
+ } else {
+ _set_edited_collision_shape(data.collisions[index + 1]);
+ }
+ }
+ current_shape.resize(0);
+ Rect2 current_tile_region = tileset->tile_get_region(get_current_tile());
+ current_tile_region.position += WORKSPACE_MARGIN;
+
+ int spacing = tileset->autotile_get_spacing(get_current_tile());
+ Vector2 size = tileset->autotile_get_size(get_current_tile());
+ Vector2 shape_anchor = edited_shape_coord;
+ shape_anchor.x *= (size.x + spacing);
+ shape_anchor.y *= (size.y + spacing);
+ current_tile_region.position += shape_anchor;
+
+ if (edited_collision_shape.is_valid()) {
+ for (int i = 0; i < _get_edited_shape_points().size(); i++) {
+ current_shape.push_back(_get_edited_shape_points()[i] + current_tile_region.position);
+ }
+ }
+ workspace->update();
+ workspace_container->update();
+ helper->_change_notify("");
+ }
+}
+
+void TileSetEditor::_select_previous_shape() {
+ if (get_current_tile() == -1) {
+ _select_previous_subtile();
+ if (get_current_tile() != -1 && edit_mode == EDITMODE_COLLISION) {
+ SubtileData data = current_tile_data[Vector2i(edited_shape_coord)];
+ if (data.collisions.size() > 1) {
+ _set_edited_collision_shape(data.collisions[data.collisions.size() - 1]);
+ }
+ } else {
+ return;
+ }
+ } else if (edit_mode != EDITMODE_COLLISION) {
+ _select_previous_subtile();
+ } else {
+ Vector2i edited_coord = Vector2();
+ if (tileset->tile_get_tile_mode(get_current_tile()) != TileSet::SINGLE_TILE) {
+ edited_coord = edited_shape_coord;
+ }
+ SubtileData data = current_tile_data[edited_coord];
+ if (data.collisions.size() == 0) {
+ _select_previous_subtile();
+ data = current_tile_data[Vector2i(edited_shape_coord)];
+ if (data.collisions.size() > 1) {
+ _set_edited_collision_shape(data.collisions[data.collisions.size() - 1]);
+ }
+ } else {
+ int index = data.collisions.find(edited_collision_shape);
+ if (index < 0) {
+ _set_edited_collision_shape(data.collisions[data.collisions.size() - 1]);
+ } else if (index == 0) {
+ _select_previous_subtile();
+ data = current_tile_data[Vector2i(edited_shape_coord)];
+ if (data.collisions.size() > 1) {
+ _set_edited_collision_shape(data.collisions[data.collisions.size() - 1]);
+ }
+ } else {
+ _set_edited_collision_shape(data.collisions[index - 1]);
+ }
+ }
+
+ current_shape.resize(0);
+ Rect2 current_tile_region = tileset->tile_get_region(get_current_tile());
+ current_tile_region.position += WORKSPACE_MARGIN;
+
+ int spacing = tileset->autotile_get_spacing(get_current_tile());
+ Vector2 size = tileset->autotile_get_size(get_current_tile());
+ Vector2 shape_anchor = edited_shape_coord;
+ shape_anchor.x *= (size.x + spacing);
+ shape_anchor.y *= (size.y + spacing);
+ current_tile_region.position += shape_anchor;
+
+ if (edited_collision_shape.is_valid()) {
+ for (int i = 0; i < _get_edited_shape_points().size(); i++) {
+ current_shape.push_back(_get_edited_shape_points()[i] + current_tile_region.position);
+ }
+ }
+ workspace->update();
+ workspace_container->update();
+ helper->_change_notify("");
+ }
+}
+
+void TileSetEditor::_set_edited_collision_shape(const Ref<Shape2D> &p_shape) {
+ edited_collision_shape = p_shape;
+ _update_toggle_shape_button();
+}
+
void TileSetEditor::_set_snap_step(Vector2 p_val) {
snap_step.x = CLAMP(p_val.x, 0, 256);
snap_step.y = CLAMP(p_val.y, 0, 256);
@@ -1937,16 +2380,29 @@ void TileSetEditor::draw_polygon_shapes() {
}
anchor += WORKSPACE_MARGIN;
anchor += tileset->tile_get_region(t_id).position;
- Ref<ConvexPolygonShape2D> shape = sd[i].shape;
+ Ref<Shape2D> shape = sd[i].shape;
if (shape.is_valid()) {
Color c_bg;
Color c_border;
+ Ref<ConvexPolygonShape2D> convex = shape;
+ bool is_convex = convex.is_valid();
if ((tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE || coord == edited_shape_coord) && sd[i].shape == edited_collision_shape) {
- c_bg = Color(0, 1, 1, 0.5);
- c_border = Color(0, 1, 1);
+ if (is_convex) {
+ c_bg = Color(0, 1, 1, 0.5);
+ c_border = Color(0, 1, 1);
+ } else {
+ c_bg = Color(0.8, 0, 1, 0.5);
+ c_border = Color(0.8, 0, 1);
+ }
} else {
- c_bg = Color(0.9, 0.7, 0.07, 0.5);
- c_border = Color(0.9, 0.7, 0.07, 1);
+ if (is_convex) {
+ c_bg = Color(0.9, 0.7, 0.07, 0.5);
+ c_border = Color(0.9, 0.7, 0.07, 1);
+
+ } else {
+ c_bg = Color(0.9, 0.45, 0.075, 0.5);
+ c_border = Color(0.9, 0.45, 0.075);
+ }
}
Vector<Vector2> polygon;
Vector<Color> colors;
@@ -1956,8 +2412,8 @@ void TileSetEditor::draw_polygon_shapes() {
colors.push_back(c_bg);
}
} else {
- for (int j = 0; j < shape->get_points().size(); j++) {
- polygon.push_back(shape->get_points()[j] + anchor);
+ for (int j = 0; j < _get_collision_shape_points(shape).size(); j++) {
+ polygon.push_back(_get_collision_shape_points(shape)[j] + anchor);
colors.push_back(c_bg);
}
}
@@ -2174,11 +2630,11 @@ void TileSetEditor::close_shape(const Vector2 &shape_anchor) {
if (current_shape.size() >= 3) {
Ref<ConvexPolygonShape2D> shape = memnew(ConvexPolygonShape2D);
- Vector<Vector2> segments;
+ Vector<Vector2> points;
float p_total = 0;
for (int i = 0; i < current_shape.size(); i++) {
- segments.push_back(current_shape[i] - shape_anchor);
+ points.push_back(current_shape[i] - shape_anchor);
if (i != current_shape.size() - 1)
p_total += ((current_shape[i + 1].x - current_shape[i].x) * (-current_shape[i + 1].y + (-current_shape[i].y)));
@@ -2187,9 +2643,9 @@ void TileSetEditor::close_shape(const Vector2 &shape_anchor) {
}
if (p_total < 0)
- segments.invert();
+ points.invert();
- shape->set_points(segments);
+ shape->set_points(points);
undo_redo->create_action(TTR("Create Collision Polygon"));
// Necessary to get the version that returns a Array instead of a Vector.
@@ -2274,6 +2730,7 @@ void TileSetEditor::close_shape(const Vector2 &shape_anchor) {
}
void TileSetEditor::select_coord(const Vector2 &coord) {
+ _update_tile_data();
current_shape = PoolVector2Array();
if (get_current_tile() == -1)
return;
@@ -2281,7 +2738,7 @@ void TileSetEditor::select_coord(const Vector2 &coord) {
current_tile_region.position += WORKSPACE_MARGIN;
if (tileset->tile_get_tile_mode(get_current_tile()) == TileSet::SINGLE_TILE) {
if (edited_collision_shape != tileset->tile_get_shape(get_current_tile(), 0))
- edited_collision_shape = tileset->tile_get_shape(get_current_tile(), 0);
+ _set_edited_collision_shape(tileset->tile_get_shape(get_current_tile(), 0));
if (edited_occlusion_shape != tileset->tile_get_light_occluder(get_current_tile()))
edited_occlusion_shape = tileset->tile_get_light_occluder(get_current_tile());
if (edited_navigation_shape != tileset->tile_get_navigation_polygon(get_current_tile()))
@@ -2290,8 +2747,8 @@ void TileSetEditor::select_coord(const Vector2 &coord) {
if (edit_mode == EDITMODE_COLLISION) {
current_shape.resize(0);
if (edited_collision_shape.is_valid()) {
- for (int i = 0; i < edited_collision_shape->get_points().size(); i++) {
- current_shape.push_back(edited_collision_shape->get_points()[i] + current_tile_region.position);
+ for (int i = 0; i < _get_edited_shape_points().size(); i++) {
+ current_shape.push_back(_get_edited_shape_points()[i] + current_tile_region.position);
}
}
} else if (edit_mode == EDITMODE_OCCLUSION) {
@@ -2318,13 +2775,13 @@ void TileSetEditor::select_coord(const Vector2 &coord) {
for (int i = 0; i < sd.size(); i++) {
if (sd[i].autotile_coord == coord) {
if (edited_collision_shape != sd[i].shape)
- edited_collision_shape = sd[i].shape;
+ _set_edited_collision_shape(sd[i].shape);
found_collision_shape = true;
break;
}
}
if (!found_collision_shape)
- edited_collision_shape = Ref<ConvexPolygonShape2D>(NULL);
+ _set_edited_collision_shape(Ref<ConvexPolygonShape2D>(NULL));
if (edited_occlusion_shape != tileset->autotile_get_light_occluder(get_current_tile(), coord))
edited_occlusion_shape = tileset->autotile_get_light_occluder(get_current_tile(), coord);
if (edited_navigation_shape != tileset->autotile_get_navigation_polygon(get_current_tile(), coord))
@@ -2339,8 +2796,8 @@ void TileSetEditor::select_coord(const Vector2 &coord) {
if (edit_mode == EDITMODE_COLLISION) {
current_shape.resize(0);
if (edited_collision_shape.is_valid()) {
- for (int j = 0; j < edited_collision_shape->get_points().size(); j++) {
- current_shape.push_back(edited_collision_shape->get_points()[j] + shape_anchor);
+ for (int j = 0; j < _get_edited_shape_points().size(); j++) {
+ current_shape.push_back(_get_edited_shape_points()[j] + shape_anchor);
}
}
} else if (edit_mode == EDITMODE_OCCLUSION) {
@@ -2495,7 +2952,7 @@ void TileSetEditor::update_workspace_tile_mode() {
for (int i = 0; i < EDITMODE_MAX; i++) {
tool_editmode[i]->hide();
}
- for (int i = 0; i < ZOOM_OUT; i++) {
+ for (int i = TOOL_SELECT; i < ZOOM_OUT; i++) {
tools[i]->hide();
}
diff --git a/editor/plugins/tile_set_editor_plugin.h b/editor/plugins/tile_set_editor_plugin.h
index 9c4aa80dcb..2827964592 100644
--- a/editor/plugins/tile_set_editor_plugin.h
+++ b/editor/plugins/tile_set_editor_plugin.h
@@ -34,6 +34,7 @@
#include "editor/editor_name_dialog.h"
#include "editor/editor_node.h"
#include "scene/2d/sprite.h"
+#include "scene/resources/concave_polygon_shape_2d.h"
#include "scene/resources/convex_polygon_shape_2d.h"
#include "scene/resources/tile_set.h"
@@ -76,12 +77,15 @@ class TileSetEditor : public HSplitContainer {
};
enum TileSetTools {
+ SELECT_PREVIOUS,
+ SELECT_NEXT,
TOOL_SELECT,
BITMASK_COPY,
BITMASK_PASTE,
BITMASK_CLEAR,
SHAPE_NEW_POLYGON,
SHAPE_NEW_RECTANGLE,
+ SHAPE_TOGGLE_TYPE,
SHAPE_DELETE,
SHAPE_KEEP_INSIDE_TILE,
TOOL_GRID_SNAP,
@@ -92,6 +96,12 @@ class TileSetEditor : public HSplitContainer {
TOOL_MAX
};
+ struct SubtileData {
+ Array collisions;
+ Ref<OccluderPolygon2D> occlusion_shape;
+ Ref<NavigationPolygon> navigation_shape;
+ };
+
Ref<TileSet> tileset;
TilesetEditorContext *helper;
EditorNode *editor;
@@ -115,13 +125,14 @@ class TileSetEditor : public HSplitContainer {
bool draw_edited_region;
Vector2 edited_shape_coord;
PoolVector2Array current_shape;
+ Map<Vector2i, SubtileData> current_tile_data;
Map<Vector2, uint16_t> bitmask_map_copy;
Vector2 snap_step;
Vector2 snap_offset;
Vector2 snap_separation;
- Ref<ConvexPolygonShape2D> edited_collision_shape;
+ Ref<Shape2D> edited_collision_shape;
Ref<OccluderPolygon2D> edited_occlusion_shape;
Ref<NavigationPolygon> edited_navigation_shape;
@@ -137,6 +148,7 @@ class TileSetEditor : public HSplitContainer {
HSeparator *separator_editmode;
HBoxContainer *toolbar;
ToolButton *tools[TOOL_MAX];
+ VSeparator *separator_shape_toggle;
VSeparator *separator_bitmask;
VSeparator *separator_delete;
VSeparator *separator_grid;
@@ -188,6 +200,20 @@ private:
void _on_priority_changed(float val);
void _on_z_index_changed(float val);
void _on_grid_snap_toggled(bool p_val);
+ Vector<Vector2> _get_collision_shape_points(const Ref<Shape2D> &p_shape);
+ Vector<Vector2> _get_edited_shape_points();
+ void _set_edited_shape_points(const Vector<Vector2> points);
+ void _update_tile_data();
+ void _update_toggle_shape_button();
+ void _select_next_tile();
+ void _select_previous_tile();
+ Array _get_tiles_in_current_texture(bool sorted = false);
+ bool _sort_tiles(Variant p_a, Variant p_b);
+ void _select_next_subtile();
+ void _select_previous_subtile();
+ void _select_next_shape();
+ void _select_previous_shape();
+ void _set_edited_collision_shape(const Ref<Shape2D> &p_shape);
void _set_snap_step(Vector2 p_val);
void _set_snap_off(Vector2 p_val);
void _set_snap_sep(Vector2 p_val);
diff --git a/modules/csg/csg.cpp b/modules/csg/csg.cpp
index fb7f829cf0..0eb539b182 100644
--- a/modules/csg/csg.cpp
+++ b/modules/csg/csg.cpp
@@ -953,13 +953,15 @@ void CSGBrushOperation::_merge_poly(MeshMerge &mesh, int p_face_idx, const Build
//duplicate point
int insert_at = with_outline_vertex;
- polys.write[i].points.insert(insert_at, polys[i].points[insert_at]);
+ int point = polys[i].points[insert_at];
+ polys.write[i].points.insert(insert_at, point);
insert_at++;
//insert all others, outline should be backwards (must check)
int holesize = polys[i].holes[j].size();
for (int k = 0; k <= holesize; k++) {
int idx = (from_hole_vertex + k) % holesize;
- polys.write[i].points.insert(insert_at, polys[i].holes[j][idx]);
+ int point2 = polys[i].holes[j][idx];
+ polys.write[i].points.insert(insert_at, point2);
insert_at++;
}
diff --git a/modules/opus/SCsub b/modules/opus/SCsub
index cd5da75bab..aa656c575a 100644
--- a/modules/opus/SCsub
+++ b/modules/opus/SCsub
@@ -138,7 +138,7 @@ if env['builtin_opus']:
opus_sources_silk = []
- if("opus_fixed_point" in env and env.opus_fixed_point == "yes"):
+ if env["platform"] in ["android", "iphone", "javascript"]:
env_opus.Append(CFLAGS=["-DFIXED_POINT"])
opus_sources_silk = [
"silk/fixed/LTP_analysis_filter_FIX.c",
@@ -220,6 +220,12 @@ if env['builtin_opus']:
]
env_opus.Append(CPPPATH=[thirdparty_dir + "/" + dir for dir in thirdparty_include_paths])
+ if env["platform"] == "android" or env["platform"] == "iphone":
+ if ("arch" in env and env["arch"] == "arm") or ("android_arch" in env and env["android_arch"] in ["armv6", "armv7"]):
+ env_opus.Append(CFLAGS=["-DOPUS_ARM_OPT"])
+ elif ("arch" in env and env["arch"] == "arm64") or ("android_arch" in env and env["android_arch"] == "arm64v8"):
+ env_opus.Append(CFLAGS=["-DOPUS_ARM64_OPT"])
+
env_thirdparty = env_opus.Clone()
env_thirdparty.disable_warnings()
env_thirdparty.add_source_files(env.modules_sources, thirdparty_sources)
diff --git a/platform/android/detect.py b/platform/android/detect.py
index aa48252435..80cda68a9e 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -298,12 +298,6 @@ def configure(env):
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
- if 'module_opus_enabled' in env and env['module_opus_enabled']:
- if (env["android_arch"] == "armv6" or env["android_arch"] == "armv7"):
- env.Append(CFLAGS=["-DOPUS_ARM_OPT"])
- env.opus_fixed_point = "yes"
-
# Return NDK version string in source.properties (adapted from the Chromium project).
def get_ndk_version(path):
if path is None:
diff --git a/platform/android/java/src/org/godotengine/godot/GodotIO.java b/platform/android/java/src/org/godotengine/godot/GodotIO.java
index 8cee20e435..85bba8bb4c 100644
--- a/platform/android/java/src/org/godotengine/godot/GodotIO.java
+++ b/platform/android/java/src/org/godotengine/godot/GodotIO.java
@@ -516,14 +516,6 @@ public class GodotIO {
public void hideKeyboard() {
if (edit != null)
edit.hideKeyboard();
-
- InputMethodManager inputMgr = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE);
- View v = activity.getCurrentFocus();
- if (v != null) {
- inputMgr.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
- } else {
- inputMgr.hideSoftInputFromWindow(new View(activity).getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
- }
};
public void setScreenOrientation(int p_orientation) {
diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py
index d0e6a4cefe..172572bcb4 100644
--- a/platform/iphone/detect.py
+++ b/platform/iphone/detect.py
@@ -174,11 +174,3 @@ def configure(env):
env.Append(CPPPATH=['#platform/iphone'])
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']:
- env.opus_fixed_point = "yes"
- if (env["arch"] == "arm"):
- env.Append(CFLAGS=["-DOPUS_ARM_OPT"])
- elif (env["arch"] == "arm64"):
- env.Append(CFLAGS=["-DOPUS_ARM64_OPT"])
diff --git a/platform/javascript/detect.py b/platform/javascript/detect.py
index 3cc79097f8..47da8de5df 100644
--- a/platform/javascript/detect.py
+++ b/platform/javascript/detect.py
@@ -136,7 +136,3 @@ def configure(env):
# TODO: Reevaluate usage of this setting now that engine.js manages engine runtime.
env.Append(LINKFLAGS=['-s', 'NO_EXIT_RUNTIME=1'])
-
- # TODO: Move that to opus module's config.
- if 'module_opus_enabled' in env and env['module_opus_enabled']:
- env.opus_fixed_point = 'yes'
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index 1355ae542d..b5ad59e60a 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -20,12 +20,10 @@ def can_build():
# Check the minimal dependencies
x11_error = os.system("pkg-config --version > /dev/null")
if (x11_error):
- print("pkg-config not found.. x11 disabled.")
return False
x11_error = os.system("pkg-config x11 --modversion > /dev/null ")
if (x11_error):
- print("X11 not found.. x11 disabled.")
return False
x11_error = os.system("pkg-config xcursor --modversion > /dev/null ")
diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp
index 9e8bf62fc5..2a225e5797 100644
--- a/scene/2d/area_2d.cpp
+++ b/scene/2d/area_2d.cpp
@@ -428,8 +428,8 @@ void Area2D::set_monitorable(bool p_enable) {
if (locked || (is_inside_tree() && Physics2DServer::get_singleton()->is_flushing_queries())) {
ERR_EXPLAIN("Function blocked during in/out signal. Use set_deferred(\"monitorable\",true/false)");
+ ERR_FAIL();
}
- ERR_FAIL_COND(locked || Physics2DServer::get_singleton()->is_flushing_queries());
if (p_enable == monitorable)
return;
diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp
index 1c58073f1d..f6f1bad581 100644
--- a/scene/2d/polygon_2d.cpp
+++ b/scene/2d/polygon_2d.cpp
@@ -307,7 +307,9 @@ void Polygon2D::_notification(int p_what) {
if (invert || polygons.size() == 0) {
Vector<int> indices = Geometry::triangulate_polygon(points);
- VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID());
+ if (indices.size()) {
+ VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID());
+ }
} else {
//draw individual polygons
Vector<int> total_indices;
diff --git a/scene/3d/area.cpp b/scene/3d/area.cpp
index 9e15a416b2..e58e26d2d1 100644
--- a/scene/3d/area.cpp
+++ b/scene/3d/area.cpp
@@ -441,8 +441,8 @@ void Area::set_monitorable(bool p_enable) {
if (locked || (is_inside_tree() && PhysicsServer::get_singleton()->is_flushing_queries())) {
ERR_EXPLAIN("Function blocked during in/out signal. Use set_deferred(\"monitorable\",true/false)");
+ ERR_FAIL();
}
- ERR_FAIL_COND(locked || PhysicsServer::get_singleton()->is_flushing_queries());
if (p_enable == monitorable)
return;
diff --git a/scene/3d/light.cpp b/scene/3d/light.cpp
index 3b514dab8c..cf1af918f7 100644
--- a/scene/3d/light.cpp
+++ b/scene/3d/light.cpp
@@ -210,6 +210,13 @@ bool Light::is_editor_only() const {
return editor_only;
}
+void Light::_validate_property(PropertyInfo &property) const {
+
+ if (VisualServer::get_singleton()->is_low_end() && property.name == "shadow_contact") {
+ property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
+ }
+}
+
void Light::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_editor_only", "editor_only"), &Light::set_editor_only);
diff --git a/scene/3d/light.h b/scene/3d/light.h
index 85e0ce3c24..ddd5bc6b3a 100644
--- a/scene/3d/light.h
+++ b/scene/3d/light.h
@@ -92,6 +92,7 @@ protected:
static void _bind_methods();
void _notification(int p_what);
+ virtual void _validate_property(PropertyInfo &property) const;
Light(VisualServer::LightType p_type);
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 43ec8cebb0..016db15b73 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -287,7 +287,6 @@ void AnimationPlayer::_ensure_node_caches(AnimationData *p_anim) {
// broken track (nonexistent bone)
p_anim->node_cache[i]->skeleton = NULL;
p_anim->node_cache[i]->spatial = NULL;
- printf("bone is %ls\n", String(bone_name).c_str());
ERR_CONTINUE(p_anim->node_cache[i]->bone_idx < 0);
}
} else {
@@ -1133,8 +1132,6 @@ void AnimationPlayer::play_backwards(const StringName &p_name, float p_custom_bl
void AnimationPlayer::play(const StringName &p_name, float p_custom_blend, float p_custom_scale, bool p_from_end) {
- //printf("animation is %ls\n", String(p_name).c_str());
- //ERR_FAIL_COND(!is_inside_scene());
StringName name = p_name;
if (String(name) == "")
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 998e91cfc2..86894ce070 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -2721,7 +2721,7 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_scale"), &Control::get_scale);
ClassDB::bind_method(D_METHOD("get_pivot_offset"), &Control::get_pivot_offset);
ClassDB::bind_method(D_METHOD("get_custom_minimum_size"), &Control::get_custom_minimum_size);
- ClassDB::bind_method(D_METHOD("get_parent_area_size"), &Control::get_size);
+ ClassDB::bind_method(D_METHOD("get_parent_area_size"), &Control::get_parent_area_size);
ClassDB::bind_method(D_METHOD("get_global_position"), &Control::get_global_position);
ClassDB::bind_method(D_METHOD("get_rect"), &Control::get_rect);
ClassDB::bind_method(D_METHOD("get_global_rect"), &Control::get_global_rect);
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index f3f2e586a6..68e734502b 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -261,8 +261,9 @@ void GraphEdit::add_child_notify(Node *p_child) {
void GraphEdit::remove_child_notify(Node *p_child) {
Control::remove_child_notify(p_child);
-
- top_layer->call_deferred("raise"); //top layer always on top!
+ if (is_inside_tree()) {
+ top_layer->call_deferred("raise"); //top layer always on top!
+ }
GraphNode *gn = Object::cast_to<GraphNode>(p_child);
if (gn) {
gn->disconnect("offset_changed", this, "_graph_node_moved");
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index d4b008e277..9bcf10d5e7 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -1133,12 +1133,13 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
}
Variant meta;
- if (item && !outside && _find_meta(item, &meta)) {
- if (meta_hovering != item) {
+ ItemMeta *item_meta;
+ if (item && !outside && _find_meta(item, &meta, &item_meta)) {
+ if (meta_hovering != item_meta) {
if (meta_hovering) {
emit_signal("meta_hover_ended", current_meta);
}
- meta_hovering = static_cast<ItemMeta *>(item);
+ meta_hovering = item_meta;
current_meta = meta;
emit_signal("meta_hover_started", meta);
}
@@ -1269,7 +1270,7 @@ bool RichTextLabel::_find_strikethrough(Item *p_item) {
return false;
}
-bool RichTextLabel::_find_meta(Item *p_item, Variant *r_meta) {
+bool RichTextLabel::_find_meta(Item *p_item, Variant *r_meta, ItemMeta **r_item) {
Item *item = p_item;
@@ -1280,6 +1281,8 @@ bool RichTextLabel::_find_meta(Item *p_item, Variant *r_meta) {
ItemMeta *meta = static_cast<ItemMeta *>(item);
if (r_meta)
*r_meta = meta->meta;
+ if (r_item)
+ *r_item = meta;
return true;
}
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index bec2c5ac02..114c6103e2 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -285,7 +285,7 @@ private:
Color _find_color(Item *p_item, const Color &p_default_color);
bool _find_underline(Item *p_item);
bool _find_strikethrough(Item *p_item);
- bool _find_meta(Item *p_item, Variant *r_meta);
+ bool _find_meta(Item *p_item, Variant *r_meta, ItemMeta **r_item = NULL);
void _update_scroll();
void _scroll_changed(double);
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 090e6bdcb0..5bfdb5a9fd 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -2923,6 +2923,13 @@ bool Viewport::is_handling_input_locally() const {
return handle_input_locally;
}
+void Viewport::_validate_property(PropertyInfo &property) const {
+
+ if (VisualServer::get_singleton()->is_low_end() && property.name == "hdr") {
+ property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL;
+ }
+}
+
void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_use_arvr", "use"), &Viewport::set_use_arvr);
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 4d0a4e8c87..b8b5bf07a7 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -390,6 +390,7 @@ private:
protected:
void _notification(int p_what);
static void _bind_methods();
+ virtual void _validate_property(PropertyInfo &property) const;
public:
Listener *get_listener() const;
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp
index 2af92a788e..3eb16c544c 100644
--- a/scene/resources/animation.cpp
+++ b/scene/resources/animation.cpp
@@ -1836,9 +1836,14 @@ Variant Animation::value_track_interpolate(int p_track, float p_time) const {
void Animation::_value_track_get_key_indices_in_range(const ValueTrack *vt, float from_time, float to_time, List<int> *p_indices) const {
if (from_time != length && to_time == length)
- to_time = length * 1.01; //include a little more if at the end
+ to_time = length * 1.001; //include a little more if at the end
int to = _find(vt->values, to_time);
+ if (to >= 0 && from_time == to_time && vt->values[to].time == from_time) {
+ //find exact (0 delta), return if found
+ p_indices->push_back(to);
+ return;
+ }
// can't really send the events == time, will be sent in the next frame.
// if event>=len then it will probably never be requested by the anim player.
@@ -1884,7 +1889,7 @@ void Animation::value_track_get_key_indices(int p_track, float p_time, float p_d
if (from_time > to_time) {
// handle loop by splitting
- _value_track_get_key_indices_in_range(vt, length - from_time, length, p_indices);
+ _value_track_get_key_indices_in_range(vt, from_time, length, p_indices);
_value_track_get_key_indices_in_range(vt, 0, to_time, p_indices);
return;
}
diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp
index 98402dbeaf..85018f38d7 100644
--- a/scene/resources/mesh.cpp
+++ b/scene/resources/mesh.cpp
@@ -1028,34 +1028,6 @@ AABB ArrayMesh::get_custom_aabb() const {
return custom_aabb;
}
-void ArrayMesh::center_geometry() {
-
- /*
- Vector3 ofs = aabb.pos+aabb.size*0.5;
-
- for(int i=0;i<get_surface_count();i++) {
-
- PoolVector<Vector3> geom = surface_get_array(i,ARRAY_VERTEX);
- int gc =geom.size();
- PoolVector<Vector3>::Write w = geom.write();
- surfaces[i].aabb.pos-=ofs;
-
- for(int i=0;i<gc;i++) {
-
- w[i]-=ofs;
- }
-
- w = PoolVector<Vector3>::Write();
-
- surface_set_array(i,ARRAY_VERTEX,geom);
-
- }
-
- aabb.pos-=ofs;
-
-*/
-}
-
void ArrayMesh::regen_normalmaps() {
Vector<Ref<SurfaceTool> > surfs;
@@ -1295,8 +1267,6 @@ void ArrayMesh::_bind_methods() {
ClassDB::bind_method(D_METHOD("create_trimesh_shape"), &ArrayMesh::create_trimesh_shape);
ClassDB::bind_method(D_METHOD("create_convex_shape"), &ArrayMesh::create_convex_shape);
ClassDB::bind_method(D_METHOD("create_outline", "margin"), &ArrayMesh::create_outline);
- ClassDB::bind_method(D_METHOD("center_geometry"), &ArrayMesh::center_geometry);
- ClassDB::set_method_flags(get_class_static(), _scs_create("center_geometry"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
ClassDB::bind_method(D_METHOD("regen_normalmaps"), &ArrayMesh::regen_normalmaps);
ClassDB::set_method_flags(get_class_static(), _scs_create("regen_normalmaps"), METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR);
ClassDB::bind_method(D_METHOD("lightmap_unwrap", "transform", "texel_size"), &ArrayMesh::lightmap_unwrap);
diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h
index 2d0aef8ab0..dabfc6ea60 100644
--- a/scene/resources/mesh.h
+++ b/scene/resources/mesh.h
@@ -223,7 +223,6 @@ public:
AABB get_aabb() const;
virtual RID get_rid() const;
- void center_geometry();
void regen_normalmaps();
Error lightmap_unwrap(const Transform &p_base_transform = Transform(), float p_texel_size = 0.05);
diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp
index 0d12d388ef..99440ff202 100644
--- a/scene/resources/packed_scene.cpp
+++ b/scene/resources/packed_scene.cpp
@@ -92,6 +92,8 @@ Node *SceneState::instance(GenEditState p_edit_state) const {
if (i > 0) {
+ ERR_EXPLAIN(vformat("Invalid scene: node %s does not specify its parent node.", snames[n.name]))
+ ERR_FAIL_COND_V(n.parent == -1, NULL)
NODE_FROM_ID(nparent, n.parent);
#ifdef DEBUG_ENABLED
if (!nparent && (n.parent & FLAG_ID_IS_PATH)) {
diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp
index 12ee98595d..1a6430c499 100644
--- a/servers/audio/audio_stream.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -150,7 +150,7 @@ void AudioStreamPlaybackMicrophone::_mix_internal(AudioFrame *p_buffer, int p_fr
input_ofs = 0;
} else {
for (int i = 0; i < p_frames; i++) {
- if (input_size > input_ofs) {
+ if (input_size > input_ofs && (int)input_ofs < buf.size()) {
float l = (buf[input_ofs++] >> 16) / 32768.f;
if ((int)input_ofs >= buf.size()) {
input_ofs = 0;
@@ -186,6 +186,10 @@ float AudioStreamPlaybackMicrophone::get_stream_sampling_rate() {
void AudioStreamPlaybackMicrophone::start(float p_from_pos) {
+ if (active) {
+ return;
+ }
+
if (!GLOBAL_GET("audio/enable_audio_input")) {
WARN_PRINTS("Need to enable Project settings > Audio > Enable Audio Input option to use capturing.");
return;
@@ -193,15 +197,17 @@ void AudioStreamPlaybackMicrophone::start(float p_from_pos) {
input_ofs = 0;
- AudioDriver::get_singleton()->capture_start();
-
- active = true;
- _begin_resample();
+ if (AudioDriver::get_singleton()->capture_start() == OK) {
+ active = true;
+ _begin_resample();
+ }
}
void AudioStreamPlaybackMicrophone::stop() {
- AudioDriver::get_singleton()->capture_stop();
- active = false;
+ if (active) {
+ AudioDriver::get_singleton()->capture_stop();
+ active = false;
+ }
}
bool AudioStreamPlaybackMicrophone::is_playing() const {
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index df6218ac79..14c555ab5b 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -90,12 +90,16 @@ void AudioDriver::input_buffer_init(int driver_buffer_frames) {
void AudioDriver::input_buffer_write(int32_t sample) {
- input_buffer.write[input_position++] = sample;
- if ((int)input_position >= input_buffer.size()) {
- input_position = 0;
- }
- if ((int)input_size < input_buffer.size()) {
- input_size++;
+ if ((int)input_position < input_buffer.size()) {
+ input_buffer.write[input_position++] = sample;
+ if ((int)input_position >= input_buffer.size()) {
+ input_position = 0;
+ }
+ if ((int)input_size < input_buffer.size()) {
+ input_size++;
+ }
+ } else {
+ WARN_PRINTS("input_buffer_write: Invalid input_position=" + itos(input_position) + " input_buffer.size()=" + itos(input_buffer.size()));
}
}
@@ -145,6 +149,8 @@ AudioDriver::AudioDriver() {
_last_mix_time = 0;
_mix_amount = 0;
+ input_position = 0;
+ input_size = 0;
#ifdef DEBUG_ENABLED
prof_time = 0;
diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp
index 2975ae9453..36d18e8901 100644
--- a/servers/physics/physics_server_sw.cpp
+++ b/servers/physics/physics_server_sw.cpp
@@ -40,10 +40,10 @@
#include "joints/pin_joint_sw.h"
#include "joints/slider_joint_sw.h"
-#define FLUSH_QUERY_CHECK \
- if (flushing_queries) { \
- ERR_EXPLAIN("Can't change this state while flushing queries. Use call_deferred()/set_deferred() to change monitoring state instead"); \
- ERR_FAIL(); \
+#define FLUSH_QUERY_CHECK(m_object) \
+ if (m_object->get_space() && flushing_queries) { \
+ ERR_EXPLAIN("Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead"); \
+ ERR_FAIL(); \
}
RID PhysicsServerSW::shape_create(ShapeType p_shape) {
@@ -358,11 +358,10 @@ void PhysicsServerSW::area_clear_shapes(RID p_area) {
void PhysicsServerSW::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) {
- FLUSH_QUERY_CHECK
-
AreaSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
ERR_FAIL_INDEX(p_shape_idx, area->get_shape_count());
+ FLUSH_QUERY_CHECK(area);
area->set_shape_as_disabled(p_shape_idx, p_disabled);
}
@@ -443,10 +442,9 @@ void PhysicsServerSW::area_set_collision_mask(RID p_area, uint32_t p_mask) {
void PhysicsServerSW::area_set_monitorable(RID p_area, bool p_monitorable) {
- FLUSH_QUERY_CHECK
-
AreaSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
+ FLUSH_QUERY_CHECK(area);
area->set_monitorable(p_monitorable);
}
@@ -592,11 +590,11 @@ RID PhysicsServerSW::body_get_shape(RID p_body, int p_shape_idx) const {
void PhysicsServerSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) {
- FLUSH_QUERY_CHECK
-
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
+ FLUSH_QUERY_CHECK(body);
+
body->set_shape_as_disabled(p_shape_idx, p_disabled);
}
diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp
index 4d1c56b843..283d20876d 100644
--- a/servers/physics_2d/physics_2d_server_sw.cpp
+++ b/servers/physics_2d/physics_2d_server_sw.cpp
@@ -36,8 +36,8 @@
#include "core/project_settings.h"
#include "core/script_language.h"
-#define FLUSH_QUERY_CHECK \
- if (flushing_queries) { \
+#define FLUSH_QUERY_CHECK(m_object) \
+ if (m_object->get_space() && flushing_queries) { \
ERR_EXPLAIN("Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead"); \
ERR_FAIL(); \
}
@@ -410,12 +410,11 @@ void Physics2DServerSW::area_set_shape_transform(RID p_area, int p_shape_idx, co
void Physics2DServerSW::area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) {
- FLUSH_QUERY_CHECK
-
Area2DSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
-
ERR_FAIL_INDEX(p_shape, area->get_shape_count());
+ FLUSH_QUERY_CHECK(area);
+
area->set_shape_as_disabled(p_shape, p_disabled);
}
@@ -550,10 +549,9 @@ void Physics2DServerSW::area_set_pickable(RID p_area, bool p_pickable) {
void Physics2DServerSW::area_set_monitorable(RID p_area, bool p_monitorable) {
- FLUSH_QUERY_CHECK
-
Area2DSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
+ FLUSH_QUERY_CHECK(area);
area->set_monitorable(p_monitorable);
}
@@ -630,10 +628,9 @@ RID Physics2DServerSW::body_get_space(RID p_body) const {
void Physics2DServerSW::body_set_mode(RID p_body, BodyMode p_mode) {
- FLUSH_QUERY_CHECK
-
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
+ FLUSH_QUERY_CHECK(body);
body->set_mode(p_mode);
};
@@ -734,12 +731,10 @@ void Physics2DServerSW::body_clear_shapes(RID p_body) {
void Physics2DServerSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) {
- FLUSH_QUERY_CHECK
-
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
-
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
+ FLUSH_QUERY_CHECK(body);
body->set_shape_as_disabled(p_shape_idx, p_disabled);
}
@@ -747,8 +742,8 @@ void Physics2DServerSW::body_set_shape_as_one_way_collision(RID p_body, int p_sh
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
-
ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count());
+ FLUSH_QUERY_CHECK(body);
body->set_shape_as_one_way_collision(p_shape_idx, p_enable, p_margin);
}
diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp
index fb57de5a7b..85dcaa6b03 100644
--- a/servers/visual/visual_server_canvas.cpp
+++ b/servers/visual/visual_server_canvas.cpp
@@ -758,11 +758,12 @@ void VisualServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector
Item *canvas_item = canvas_item_owner.getornull(p_item);
ERR_FAIL_COND(!canvas_item);
- int ps = p_points.size();
- ERR_FAIL_COND(!p_colors.empty() && p_colors.size() != ps && p_colors.size() != 1);
- ERR_FAIL_COND(!p_uvs.empty() && p_uvs.size() != ps);
- ERR_FAIL_COND(!p_bones.empty() && p_bones.size() != ps * 4);
- ERR_FAIL_COND(!p_weights.empty() && p_weights.size() != ps * 4);
+ int vertex_count = p_points.size();
+ ERR_FAIL_COND(vertex_count == 0);
+ ERR_FAIL_COND(!p_colors.empty() && p_colors.size() != vertex_count && p_colors.size() != 1);
+ ERR_FAIL_COND(!p_uvs.empty() && p_uvs.size() != vertex_count);
+ ERR_FAIL_COND(!p_bones.empty() && p_bones.size() != vertex_count * 4);
+ ERR_FAIL_COND(!p_weights.empty() && p_weights.size() != vertex_count * 4);
Vector<int> indices = p_indices;
@@ -770,9 +771,9 @@ void VisualServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector
if (indices.empty()) {
- ERR_FAIL_COND(ps % 3 != 0);
+ ERR_FAIL_COND(vertex_count % 3 != 0);
if (p_count == -1)
- count = ps;
+ count = vertex_count;
} else {
ERR_FAIL_COND(indices.size() % 3 != 0);
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
index 42be56cfdd..2590e29aef 100644
--- a/servers/visual/visual_server_scene.cpp
+++ b/servers/visual/visual_server_scene.cpp
@@ -445,6 +445,9 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
InstanceGeometryData *geom = memnew(InstanceGeometryData);
instance->base_data = geom;
+ if (instance->base_type == VS::INSTANCE_MESH) {
+ instance->blend_values.resize(VSG::storage->mesh_get_blend_shape_count(p_base));
+ }
} break;
case VS::INSTANCE_REFLECTION_PROBE: {