diff options
28 files changed, 449 insertions, 153 deletions
diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp index 047eaaf0ac..6f686690bf 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ b/drivers/gles2/rasterizer_canvas_gles2.cpp @@ -1162,7 +1162,65 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur void RasterizerCanvasGLES2::_copy_texscreen(const Rect2 &p_rect) { - // This isn't really working yet, so disabling for now. + if (storage->frame.current_rt->copy_screen_effect.color == 0) { + ERR_EXPLAIN("Can't use screen texture copying in a render target configured without copy buffers"); + ERR_FAIL(); + } + + glDisable(GL_BLEND); + + state.canvas_texscreen_used = true; + + Vector2 wh(storage->frame.current_rt->width, storage->frame.current_rt->height); + + Color copy_section(p_rect.position.x / wh.x, p_rect.position.y / wh.y, p_rect.size.x / wh.x, p_rect.size.y / wh.y); + + if (p_rect != Rect2()) { + storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, true); + } + + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->copy_screen_effect.fbo); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); + + glClearColor(1, 0, 1, 1); + glClear(GL_COLOR_BUFFER_BIT); + + storage->shaders.copy.bind(); + storage->shaders.copy.set_uniform(CopyShaderGLES2::COPY_SECTION, copy_section); + + const Vector2 vertpos[4] = { + Vector2(-1, -1), + Vector2(-1, 1), + Vector2(1, 1), + Vector2(1, -1), + }; + + const Vector2 uvpos[4] = { + Vector2(0, 0), + Vector2(0, 1), + Vector2(1, 1), + Vector2(1, 0) + }; + + const int indexpos[6] = { + 0, 1, 2, + 2, 3, 0 + }; + + _draw_polygon(indexpos, 6, 4, vertpos, uvpos, NULL, false); + + storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_COPY_SECTION, false); + + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //back to front + + // back to canvas, force rebind + state.using_texture_rect = false; + state.canvas_shader.bind(); + _bind_canvas_texture(state.current_tex, state.current_normal); + _set_uniforms(); + + glEnable(GL_BLEND); } void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light, const Transform2D &p_base_transform) { @@ -1178,6 +1236,7 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons state.current_tex = RID(); state.current_tex_ptr = NULL; state.current_normal = RID(); + state.canvas_texscreen_used = false; glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); @@ -1265,7 +1324,18 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons if (shader_ptr) { if (shader_ptr->canvas_item.uses_screen_texture) { - _copy_texscreen(Rect2()); + if (!state.canvas_texscreen_used) { + //copy if not copied before + _copy_texscreen(Rect2()); + + // blend mode will have been enabled so make sure we disable it again later on + //last_blend_mode = last_blend_mode != RasterizerStorageGLES2::Shader::CanvasItem::BLEND_MODE_DISABLED ? last_blend_mode : -1; + } + + if (storage->frame.current_rt->copy_screen_effect.color) { + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 4); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->copy_screen_effect.color); + } } if (shader_ptr != shader_cache) { diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index ce2961170a..ae677b606d 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -994,6 +994,12 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G e->depth_layer = e->instance->depth_layer; e->priority = p_material->render_priority; + if (has_alpha && p_material->shader->spatial.depth_draw_mode == RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { + //add element to opaque + RenderList::Element *eo = render_list.add_element(); + *eo = *e; + } + int rpsize = e->instance->reflection_probe_instances.size(); if (rpsize > 0) { bool first = true; @@ -3135,7 +3141,7 @@ void RasterizerSceneGLES2::initialize() { } // cubemaps for shadows - if (!storage->config.support_write_depth) { //not going to be used + if (storage->config.support_write_depth) { //not going to be used int max_shadow_cubemap_sampler_size = 512; int cube_size = max_shadow_cubemap_sampler_size; diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 22c05d9d77..f0deff4791 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -4251,7 +4251,8 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // copy texscreen buffers - { + if (!(rt->flags[RasterizerStorage::RENDER_TARGET_NO_SAMPLING])) { + int w = rt->width; int h = rt->height; @@ -4259,10 +4260,17 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { glBindTexture(GL_TEXTURE_2D, rt->copy_screen_effect.color); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glGenFramebuffers(1, &rt->copy_screen_effect.fbo); glBindFramebuffer(GL_FRAMEBUFFER, rt->copy_screen_effect.fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->copy_screen_effect.color, 0); + + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { diff --git a/drivers/gles2/shader_gles2.cpp b/drivers/gles2/shader_gles2.cpp index 65d4b63bb9..b50da3e9fe 100644 --- a/drivers/gles2/shader_gles2.cpp +++ b/drivers/gles2/shader_gles2.cpp @@ -242,6 +242,11 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { strings.push_back("#define USE_GLES_OVER_GL\n"); #else strings.push_back("#version 100\n"); +//angle does not like +#ifdef JAVASCRIPT_ENABLED + strings.push_back("#define USE_HIGHP_PRECISION\n"); +#endif + #endif int define_line_ofs = 1; diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h index 468971471c..5805432d09 100644 --- a/drivers/gles2/shader_gles2.h +++ b/drivers/gles2/shader_gles2.h @@ -465,6 +465,8 @@ public: void set_custom_shader(uint32_t p_code_id); void free_custom_shader(uint32_t p_code_id); + uint32_t get_version_key() const { return conditional_version.version; } + void set_uniform_default(int p_idx, const Variant &p_value) { if (p_value.get_type() == Variant::NIL) { diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index bc734a6597..c4a8c8b990 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -6,8 +6,8 @@ #define mediump #define highp #else -precision mediump float; -precision mediump int; +precision highp float; +precision highp int; #endif uniform highp mat4 projection_matrix; @@ -243,9 +243,14 @@ VERTEX_SHADER_CODE #define mediump #define highp #else +#if defined(USE_HIGHP_PRECISION) +precision highp float; +precision highp int; +#else precision mediump float; precision mediump int; #endif +#endif uniform sampler2D color_texture; // texunit:-1 /* clang-format on */ diff --git a/drivers/gles2/shaders/copy.glsl b/drivers/gles2/shaders/copy.glsl index f3c2a7eec4..931b3f3708 100644 --- a/drivers/gles2/shaders/copy.glsl +++ b/drivers/gles2/shaders/copy.glsl @@ -6,8 +6,8 @@ #define mediump #define highp #else -precision mediump float; -precision mediump int; +precision highp float; +precision highp int; #endif attribute highp vec4 vertex_attrib; // attrib:0 @@ -29,7 +29,7 @@ varying vec2 uv_interp; varying vec2 uv2_interp; #ifdef USE_COPY_SECTION -uniform vec4 copy_section; +uniform highp vec4 copy_section; #endif void main() { @@ -61,9 +61,14 @@ void main() { #define mediump #define highp #else +#if defined(USE_HIGHP_PRECISION) +precision highp float; +precision highp int; +#else precision mediump float; precision mediump int; #endif +#endif #if defined(USE_CUBEMAP) || defined(USE_PANORAMA) varying vec3 cube_interp; diff --git a/drivers/gles2/shaders/cubemap_filter.glsl b/drivers/gles2/shaders/cubemap_filter.glsl index 558c83960e..7643297a14 100644 --- a/drivers/gles2/shaders/cubemap_filter.glsl +++ b/drivers/gles2/shaders/cubemap_filter.glsl @@ -6,8 +6,8 @@ #define mediump #define highp #else -precision mediump float; -precision mediump int; +precision highp float; +precision highp int; #endif attribute highp vec2 vertex; // attrib:0 @@ -51,10 +51,16 @@ void main() { #define mediump #define highp #else +#if defined(USE_HIGHP_PRECISION) +precision highp float; +precision highp int; +#else precision mediump float; precision mediump int; #endif +#endif + #ifdef USE_SOURCE_PANORAMA uniform sampler2D source_panorama; //texunit:0 #else diff --git a/drivers/gles2/shaders/scene.glsl b/drivers/gles2/shaders/scene.glsl index 6aa91df20f..c7f5c97133 100644 --- a/drivers/gles2/shaders/scene.glsl +++ b/drivers/gles2/shaders/scene.glsl @@ -683,8 +683,13 @@ VERTEX_SHADER_CODE #define mediump #define highp #else -precision mediump float; +#if defined(USE_HIGHP_PRECISION) +precision highp float; precision highp int; +#else +precision mediump float; +precision mediump int; +#endif #endif #include "stdlib.glsl" diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index b831197759..02dbe096c5 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -3114,7 +3114,7 @@ void RasterizerSceneGLES3::_copy_screen(bool p_invalidate_color, bool p_invalida GLenum attachments[2] = { GL_COLOR_ATTACHMENT0, - GL_DEPTH_ATTACHMENT + GL_DEPTH_STENCIL_ATTACHMENT }; glInvalidateFramebuffer(GL_FRAMEBUFFER, p_invalidate_depth ? 2 : 1, attachments); @@ -4164,7 +4164,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glBindFramebuffer(GL_READ_FRAMEBUFFER, storage->frame.current_rt->buffers.fbo); glReadBuffer(GL_COLOR_ATTACHMENT0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, storage->frame.current_rt->fbo); - glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, 0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height, GL_DEPTH_BUFFER_BIT, GL_NEAREST); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); //bind depth for read diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 4818fd4927..8b3f1a1b77 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1056,6 +1056,128 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) return texture->images[p_layer]; } + // 3D textures and 2D texture arrays need special treatment, as the glGetTexImage reads **the whole** + // texture to host-memory. 3D textures and 2D texture arrays are potentially very big, so reading + // everything just to throw everything but one layer away is A Bad Idea. + // + // Unfortunately, to solve this, the copy shader has to read the data out via a shader and store it + // in a temporary framebuffer. The data from the framebuffer can then be read using glReadPixels. + if (texture->type == VS::TEXTURE_TYPE_2D_ARRAY || texture->type == VS::TEXTURE_TYPE_3D) { + // can't read a layer that doesn't exist + ERR_FAIL_INDEX_V(p_layer, texture->alloc_depth, Ref<Image>()); + + // get some information about the texture + Image::Format real_format; + GLenum gl_format; + GLenum gl_internal_format; + GLenum gl_type; + + bool compressed; + bool srgb; + + _get_gl_image_and_format( + Ref<Image>(), + texture->format, + texture->flags, + real_format, + gl_format, + gl_internal_format, + gl_type, + compressed, + srgb); + + PoolVector<uint8_t> data; + + // TODO need to decide between RgbaUnorm and RgbaFloat32 for output + int data_size = Image::get_image_data_size(texture->alloc_width, texture->alloc_height, Image::FORMAT_RGBA8, false); + + data.resize(data_size * 2); // add some more memory at the end, just in case for buggy drivers + PoolVector<uint8_t>::Write wb = data.write(); + + // generate temporary resources + GLuint tmp_fbo; + glGenFramebuffers(1, &tmp_fbo); + + GLuint tmp_color_attachment; + glGenTextures(1, &tmp_color_attachment); + + // now bring the OpenGL context into the correct state + { + glBindFramebuffer(GL_FRAMEBUFFER, tmp_fbo); + + // back color attachment with memory, then set properties + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tmp_color_attachment); + // TODO support HDR properly + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + // use the color texture as color attachment for this render pass + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tmp_color_attachment, 0); + + // more GL state, wheeeey + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_BLEND); + glDepthFunc(GL_LEQUAL); + glColorMask(1, 1, 1, 1); + + // use volume tex for reading + glActiveTexture(GL_TEXTURE0); + glBindTexture(texture->target, texture->tex_id); + + glViewport(0, 0, texture->alloc_width, texture->alloc_height); + + // set up copy shader for proper use + shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, !srgb); + shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE3D, texture->type == VS::TEXTURE_TYPE_3D); + shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE2DARRAY, texture->type == VS::TEXTURE_TYPE_2D_ARRAY); + shaders.copy.bind(); + + // calculate the normalized z coordinate for the layer + float layer = (float)p_layer / (float)texture->alloc_depth; + + shaders.copy.set_uniform(CopyShaderGLES3::LAYER, layer); + + glBindVertexArray(resources.quadie_array); + } + + // clear color attachment, then perform copy + glClearColor(0.0, 0.0, 0.0, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + // read the image into the host buffer + glReadPixels(0, 0, texture->alloc_width, texture->alloc_height, GL_RGBA, GL_UNSIGNED_BYTE, &wb[0]); + + // remove temp resources and unset some GL state + { + shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE3D, false); + shaders.copy.set_conditional(CopyShaderGLES3::USE_TEXTURE2DARRAY, false); + shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, false); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + glDeleteTextures(1, &tmp_color_attachment); + glDeleteFramebuffers(1, &tmp_fbo); + } + + wb = PoolVector<uint8_t>::Write(); + + data.resize(data_size); + + Image *img = memnew(Image(texture->alloc_width, texture->alloc_height, false, Image::FORMAT_RGBA8, data)); + if (!texture->compressed) { + img->convert(real_format); + } + + return Ref<Image>(img); + } + #ifdef GLES_OVER_GL Image::Format real_format; @@ -1172,9 +1294,8 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) glViewport(0, 0, texture->alloc_width, texture->alloc_height); - shaders.copy.bind(); - shaders.copy.set_conditional(CopyShaderGLES3::LINEAR_TO_SRGB, !srgb); + shaders.copy.bind(); glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); @@ -6931,12 +7052,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glGenTextures(1, &rt->exposure.color); glBindTexture(GL_TEXTURE_2D, rt->exposure.color); -#ifdef IPHONE_ENABLED - ///@TODO ugly hack to get around iOS not supporting 32bit single channel floating point textures... - glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, 1, 1, 0, GL_RED, GL_FLOAT, NULL); -#else glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 1, 1, 0, GL_RED, GL_FLOAT, NULL); -#endif glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->exposure.color, 0); status = glCheckFramebufferStatus(GL_FRAMEBUFFER); @@ -7168,12 +7284,7 @@ RID RasterizerStorageGLES3::canvas_light_shadow_buffer_create(int p_width) { if (config.use_rgba_2d_shadows) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, cls->size, cls->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); } else { -#ifdef IPHONE_ENABLED - ///@TODO ugly hack to get around iOS not supporting 32bit single channel floating point textures... - glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, cls->size, cls->height, 0, GL_RED, GL_FLOAT, NULL); -#else glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, cls->size, cls->height, 0, GL_RED, GL_FLOAT, NULL); -#endif } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl index 3b36bc7cc1..e1a0813efc 100644 --- a/drivers/gles3/shaders/copy.glsl +++ b/drivers/gles3/shaders/copy.glsl @@ -61,19 +61,35 @@ in vec3 cube_interp; #else in vec2 uv_interp; #endif -/* clang-format on */ #ifdef USE_ASYM_PANO uniform highp mat4 pano_transform; uniform highp vec4 asym_proj; #endif +// These definitions are here because the shader-wrapper builder does +// not understand `#elif defined()` +#ifdef USE_TEXTURE3D +#endif +#ifdef USE_TEXTURE2DARRAY +#endif + #ifdef USE_CUBEMAP uniform samplerCube source_cube; //texunit:0 +#elif defined(USE_TEXTURE3D) +uniform sampler3D source_3d; //texunit:0 +#elif defined(USE_TEXTURE2DARRAY) +uniform sampler2DArray source_2d_array; //texunit:0 #else uniform sampler2D source; //texunit:0 #endif +/* clang-format on */ + +#if defined(USE_TEXTURE3D) || defined(USE_TEXTURE2DARRAY) +uniform float layer; +#endif + #ifdef USE_MULTIPLIER uniform float multiplier; #endif @@ -97,7 +113,6 @@ vec4 texturePanorama(vec3 normal, sampler2D pano) { #endif -uniform float stuff; uniform vec2 pixel_size; in vec2 uv2_interp; @@ -147,6 +162,10 @@ void main() { #elif defined(USE_CUBEMAP) vec4 color = texture(source_cube, normalize(cube_interp)); +#elif defined(USE_TEXTURE3D) + vec4 color = textureLod(source_3d, vec3(uv_interp, layer), 0.0); +#elif defined(USE_TEXTURE2DARRAY) + vec4 color = textureLod(source_2d_array, vec3(uv_interp, layer), 0.0); #else vec4 color = textureLod(source, uv_interp, 0.0); #endif diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 02f6263887..2913c4ce56 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -474,7 +474,7 @@ void CanvasItemEditor::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_no if (canvas_item && canvas_item->is_visible_in_tree()) { Transform2D xform = (p_parent_xform * p_canvas_xform * canvas_item->get_transform()).affine_inverse(); - const real_t local_grab_distance = xform.basis_xform(Vector2(grab_distance, 0)).length(); + const real_t local_grab_distance = xform.basis_xform(Vector2(grab_distance, 0)).length() / zoom; if (canvas_item->_edit_is_selected_on_click(xform.xform(p_pos), local_grab_distance)) { Node2D *node = Object::cast_to<Node2D>(canvas_item); diff --git a/main/main.cpp b/main/main.cpp index b94130002d..f9044b61cd 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1789,9 +1789,9 @@ uint64_t Main::target_ticks = 0; uint32_t Main::frames = 0; uint32_t Main::frame = 0; bool Main::force_redraw_requested = false; -bool Main::iterating = false; +int Main::iterating = 0; bool Main::is_iterating() { - return iterating; + return iterating > 0; } // For performance metrics @@ -1800,9 +1800,10 @@ static uint64_t idle_process_max = 0; bool Main::iteration() { - ERR_FAIL_COND_V(iterating, false); + //for now do not error on this + //ERR_FAIL_COND_V(iterating, false); - iterating = true; + iterating++; uint64_t ticks = OS::get_singleton()->get_ticks_usec(); Engine::get_singleton()->_frame_ticks = ticks; @@ -1931,7 +1932,7 @@ bool Main::iteration() { frames = 0; } - iterating = false; + iterating--; if (fixed_fps != -1) return exit; diff --git a/main/main.h b/main/main.h index 1bdce7d17f..694305526a 100644 --- a/main/main.h +++ b/main/main.h @@ -47,7 +47,7 @@ class Main { static uint32_t frames; static uint32_t frame; static bool force_redraw_requested; - static bool iterating; + static int iterating; public: static bool is_project_manager(); diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp index ae70525de5..6d85eb3c90 100644 --- a/modules/gdscript/gdscript.cpp +++ b/modules/gdscript/gdscript.cpp @@ -223,16 +223,21 @@ void GDScript::_placeholder_erased(PlaceHolderScriptInstance *p_placeholder) { void GDScript::get_script_method_list(List<MethodInfo> *p_list) const { - for (const Map<StringName, GDScriptFunction *>::Element *E = member_functions.front(); E; E = E->next()) { - GDScriptFunction *func = E->get(); - MethodInfo mi; - mi.name = E->key(); - for (int i = 0; i < func->get_argument_count(); i++) { - mi.arguments.push_back(func->get_argument_type(i)); + const GDScript *current = this; + while (current) { + for (const Map<StringName, GDScriptFunction *>::Element *E = member_functions.front(); E; E = E->next()) { + GDScriptFunction *func = E->get(); + MethodInfo mi; + mi.name = E->key(); + for (int i = 0; i < func->get_argument_count(); i++) { + mi.arguments.push_back(func->get_argument_type(i)); + } + + mi.return_val = func->get_return_type(); + p_list->push_back(mi); } - mi.return_val = func->get_return_type(); - p_list->push_back(mi); + current = current->_base; } } diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index b92634c8d6..d7ba454051 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -861,8 +861,21 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, video_driver_index = p_video_driver; video_mode = p_desired; - // Can't fulfill fullscreen request during start-up due to browser security. + // fullscreen_change_callback will correct this if the request is successful. video_mode.fullscreen = false; + // Emscripten only attempts fullscreen requests if the user input callback + // was registered through one its own functions, so request manually for + // start-up fullscreen. + if (p_desired.fullscreen) { + /* clang-format off */ + EM_ASM({ + (canvas.requestFullscreen || canvas.msRequestFullscreen || + canvas.mozRequestFullScreen || canvas.mozRequestFullscreen || + canvas.webkitRequestFullscreen + ).call(canvas); + }); + /* clang-format on */ + } /* clang-format off */ if (EM_ASM_INT_V({ return Module.resizeCanvasOnStart })) { /* clang-format on */ diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 706717a8e3..dc022bcd70 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -685,6 +685,10 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { track = track_animation; } break; + default: { + ERR_PRINT("Animation corrupted (invalid track type"); + continue; + } } track_cache[path] = track; @@ -853,6 +857,9 @@ void AnimationTree::_process_graph(float p_delta) { for (int i = 0; i < a->get_track_count(); i++) { NodePath path = a->track_get_path(i); + + ERR_CONTINUE(!track_cache.has(path)); + TrackCache *track = track_cache[path]; if (track->type != a->track_get_type(i)) { continue; //may happen should not diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp index 35e8e984cd..cc37d4cf7d 100644 --- a/scene/gui/box_container.cpp +++ b/scene/gui/box_container.cpp @@ -255,6 +255,10 @@ void BoxContainer::_notification(int p_what) { _resort(); } break; + case NOTIFICATION_THEME_CHANGED: { + + minimum_size_changed(); + } break; } } diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 7c879d239c..8c588109d6 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -192,97 +192,104 @@ bool GraphNode::has_point(const Point2 &p_point) const { void GraphNode::_notification(int p_what) { - if (p_what == NOTIFICATION_DRAW) { + switch (p_what) { + case NOTIFICATION_DRAW: { - Ref<StyleBox> sb; + Ref<StyleBox> sb; - if (comment) { - sb = get_stylebox(selected ? "commentfocus" : "comment"); + if (comment) { + sb = get_stylebox(selected ? "commentfocus" : "comment"); - } else { + } else { - sb = get_stylebox(selected ? "selectedframe" : "frame"); - } + sb = get_stylebox(selected ? "selectedframe" : "frame"); + } - //sb=sb->duplicate(); - //sb->call("set_modulate",modulate); - Ref<Texture> port = get_icon("port"); - Ref<Texture> close = get_icon("close"); - Ref<Texture> resizer = get_icon("resizer"); - int close_offset = get_constant("close_offset"); - int close_h_offset = get_constant("close_h_offset"); - Color close_color = get_color("close_color"); - Ref<Font> title_font = get_font("title_font"); - int title_offset = get_constant("title_offset"); - int title_h_offset = get_constant("title_h_offset"); - Color title_color = get_color("title_color"); - Point2i icofs = -port->get_size() * 0.5; - int edgeofs = get_constant("port_offset"); - icofs.y += sb->get_margin(MARGIN_TOP); - - draw_style_box(sb, Rect2(Point2(), get_size())); - - switch (overlay) { - case OVERLAY_DISABLED: { - - } break; - case OVERLAY_BREAKPOINT: { - - draw_style_box(get_stylebox("breakpoint"), Rect2(Point2(), get_size())); - } break; - case OVERLAY_POSITION: { - draw_style_box(get_stylebox("position"), Rect2(Point2(), get_size())); - - } break; - } + //sb=sb->duplicate(); + //sb->call("set_modulate",modulate); + Ref<Texture> port = get_icon("port"); + Ref<Texture> close = get_icon("close"); + Ref<Texture> resizer = get_icon("resizer"); + int close_offset = get_constant("close_offset"); + int close_h_offset = get_constant("close_h_offset"); + Color close_color = get_color("close_color"); + Ref<Font> title_font = get_font("title_font"); + int title_offset = get_constant("title_offset"); + int title_h_offset = get_constant("title_h_offset"); + Color title_color = get_color("title_color"); + Point2i icofs = -port->get_size() * 0.5; + int edgeofs = get_constant("port_offset"); + icofs.y += sb->get_margin(MARGIN_TOP); + + draw_style_box(sb, Rect2(Point2(), get_size())); + + switch (overlay) { + case OVERLAY_DISABLED: { + + } break; + case OVERLAY_BREAKPOINT: { + + draw_style_box(get_stylebox("breakpoint"), Rect2(Point2(), get_size())); + } break; + case OVERLAY_POSITION: { + draw_style_box(get_stylebox("position"), Rect2(Point2(), get_size())); + + } break; + } - int w = get_size().width - sb->get_minimum_size().x; + int w = get_size().width - sb->get_minimum_size().x; - if (show_close) - w -= close->get_width(); + if (show_close) + w -= close->get_width(); - draw_string(title_font, Point2(sb->get_margin(MARGIN_LEFT) + title_h_offset, -title_font->get_height() + title_font->get_ascent() + title_offset), title, title_color, w); - if (show_close) { - Vector2 cpos = Point2(w + sb->get_margin(MARGIN_LEFT) + close_h_offset, -close->get_height() + close_offset); - draw_texture(close, cpos, close_color); - close_rect.position = cpos; - close_rect.size = close->get_size(); - } else { - close_rect = Rect2(); - } + draw_string(title_font, Point2(sb->get_margin(MARGIN_LEFT) + title_h_offset, -title_font->get_height() + title_font->get_ascent() + title_offset), title, title_color, w); + if (show_close) { + Vector2 cpos = Point2(w + sb->get_margin(MARGIN_LEFT) + close_h_offset, -close->get_height() + close_offset); + draw_texture(close, cpos, close_color); + close_rect.position = cpos; + close_rect.size = close->get_size(); + } else { + close_rect = Rect2(); + } - for (Map<int, Slot>::Element *E = slot_info.front(); E; E = E->next()) { - - if (E->key() < 0 || E->key() >= cache_y.size()) - continue; - if (!slot_info.has(E->key())) - continue; - const Slot &s = slot_info[E->key()]; - //left - if (s.enable_left) { - Ref<Texture> p = port; - if (s.custom_slot_left.is_valid()) { - p = s.custom_slot_left; + for (Map<int, Slot>::Element *E = slot_info.front(); E; E = E->next()) { + + if (E->key() < 0 || E->key() >= cache_y.size()) + continue; + if (!slot_info.has(E->key())) + continue; + const Slot &s = slot_info[E->key()]; + //left + if (s.enable_left) { + Ref<Texture> p = port; + if (s.custom_slot_left.is_valid()) { + p = s.custom_slot_left; + } + p->draw(get_canvas_item(), icofs + Point2(edgeofs, cache_y[E->key()]), s.color_left); } - p->draw(get_canvas_item(), icofs + Point2(edgeofs, cache_y[E->key()]), s.color_left); - } - if (s.enable_right) { - Ref<Texture> p = port; - if (s.custom_slot_right.is_valid()) { - p = s.custom_slot_right; + if (s.enable_right) { + Ref<Texture> p = port; + if (s.custom_slot_right.is_valid()) { + p = s.custom_slot_right; + } + p->draw(get_canvas_item(), icofs + Point2(get_size().x - edgeofs, cache_y[E->key()]), s.color_right); } - p->draw(get_canvas_item(), icofs + Point2(get_size().x - edgeofs, cache_y[E->key()]), s.color_right); } - } - if (resizable) { - draw_texture(resizer, get_size() - resizer->get_size()); - } - } + if (resizable) { + draw_texture(resizer, get_size() - resizer->get_size()); + } + } break; + + case NOTIFICATION_SORT_CHILDREN: { + + _resort(); + } break; - if (p_what == NOTIFICATION_SORT_CHILDREN) { + case NOTIFICATION_THEME_CHANGED: { - _resort(); + minimum_size_changed(); + } break; } } diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp index b37d08de71..d0e2edc7b5 100644 --- a/scene/gui/grid_container.cpp +++ b/scene/gui/grid_container.cpp @@ -164,6 +164,10 @@ void GridContainer::_notification(int p_what) { } } break; + case NOTIFICATION_THEME_CHANGED: { + + minimum_size_changed(); + } break; } } diff --git a/scene/gui/margin_container.cpp b/scene/gui/margin_container.cpp index a087b68d25..62ba45c484 100644 --- a/scene/gui/margin_container.cpp +++ b/scene/gui/margin_container.cpp @@ -64,27 +64,33 @@ Size2 MarginContainer::get_minimum_size() const { void MarginContainer::_notification(int p_what) { - if (p_what == NOTIFICATION_SORT_CHILDREN) { + switch (p_what) { + case NOTIFICATION_SORT_CHILDREN: { - int margin_left = get_constant("margin_left"); - int margin_top = get_constant("margin_top"); - int margin_right = get_constant("margin_right"); - int margin_bottom = get_constant("margin_bottom"); + int margin_left = get_constant("margin_left"); + int margin_top = get_constant("margin_top"); + int margin_right = get_constant("margin_right"); + int margin_bottom = get_constant("margin_bottom"); - Size2 s = get_size(); + Size2 s = get_size(); - for (int i = 0; i < get_child_count(); i++) { + for (int i = 0; i < get_child_count(); i++) { - Control *c = Object::cast_to<Control>(get_child(i)); - if (!c) - continue; - if (c->is_set_as_toplevel()) - continue; + Control *c = Object::cast_to<Control>(get_child(i)); + if (!c) + continue; + if (c->is_set_as_toplevel()) + continue; - int w = s.width - margin_left - margin_right; - int h = s.height - margin_top - margin_bottom; - fit_child_in_rect(c, Rect2(margin_left, margin_top, w, h)); - } + int w = s.width - margin_left - margin_right; + int h = s.height - margin_top - margin_bottom; + fit_child_in_rect(c, Rect2(margin_left, margin_top, w, h)); + } + } break; + case NOTIFICATION_THEME_CHANGED: { + + minimum_size_changed(); + } break; } } diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index e4cb2a06fc..d6a93238b2 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -193,6 +193,10 @@ void SplitContainer::_notification(int p_what) { draw_texture(tex, Point2i(middle_sep + (sep - tex->get_width()) / 2, (size.y - tex->get_height()) / 2)); } } break; + case NOTIFICATION_THEME_CHANGED: { + + minimum_size_changed(); + } break; } } diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index b4fe6b0255..212efa4976 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -338,6 +338,7 @@ void TabContainer::_notification(int p_what) { } } break; case NOTIFICATION_THEME_CHANGED: { + minimum_size_changed(); call_deferred("_on_theme_changed"); //wait until all changed theme } break; } diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index 1684cbf15f..2116dd0b1e 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -1021,8 +1021,6 @@ void SurfaceTool::_bind_methods() { ClassDB::bind_method(D_METHOD("generate_normals", "flip"), &SurfaceTool::generate_normals, DEFVAL(false)); ClassDB::bind_method(D_METHOD("generate_tangents"), &SurfaceTool::generate_tangents); - ClassDB::bind_method(D_METHOD("add_to_format", "flags"), &SurfaceTool::add_to_format); - ClassDB::bind_method(D_METHOD("set_material", "material"), &SurfaceTool::set_material); ClassDB::bind_method(D_METHOD("clear"), &SurfaceTool::clear); diff --git a/scene/resources/surface_tool.h b/scene/resources/surface_tool.h index 754254150d..ef13238c13 100644 --- a/scene/resources/surface_tool.h +++ b/scene/resources/surface_tool.h @@ -118,8 +118,6 @@ public: void generate_normals(bool p_flip = false); void generate_tangents(); - void add_to_format(int p_flags) { format |= p_flags; } - void set_material(const Ref<Material> &p_material); void clear(); diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index 786a136040..87b40d5447 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -622,43 +622,47 @@ void Theme::clear() { void Theme::copy_default_theme() { Ref<Theme> default_theme = get_default(); + copy_theme(default_theme); +} + +void Theme::copy_theme(const Ref<Theme> &p_other) { //these need reconnecting, so add normally { const StringName *K = NULL; - while ((K = default_theme->icon_map.next(K))) { + while ((K = p_other->icon_map.next(K))) { const StringName *L = NULL; - while ((L = default_theme->icon_map[*K].next(L))) { - set_icon(*K, *L, default_theme->icon_map[*K][*L]); + while ((L = p_other->icon_map[*K].next(L))) { + set_icon(*L, *K, p_other->icon_map[*K][*L]); } } } { const StringName *K = NULL; - while ((K = default_theme->style_map.next(K))) { + while ((K = p_other->style_map.next(K))) { const StringName *L = NULL; - while ((L = default_theme->style_map[*K].next(L))) { - set_stylebox(*K, *L, default_theme->style_map[*K][*L]); + while ((L = p_other->style_map[*K].next(L))) { + set_stylebox(*L, *K, p_other->style_map[*K][*L]); } } } { const StringName *K = NULL; - while ((K = default_theme->font_map.next(K))) { + while ((K = p_other->font_map.next(K))) { const StringName *L = NULL; - while ((L = default_theme->font_map[*K].next(L))) { - set_font(*K, *L, default_theme->font_map[*K][*L]); + while ((L = p_other->font_map[*K].next(L))) { + set_font(*L, *K, p_other->font_map[*K][*L]); } } } //these are ok to just copy - color_map = default_theme->color_map; - constant_map = default_theme->constant_map; - shader_map = default_theme->shader_map; + color_map = p_other->color_map; + constant_map = p_other->constant_map; + shader_map = p_other->shader_map; _change_notify(); emit_changed(); @@ -752,6 +756,7 @@ void Theme::_bind_methods() { ClassDB::bind_method(D_METHOD("_emit_theme_changed"), &Theme::_emit_theme_changed); ClassDB::bind_method("copy_default_theme", &Theme::copy_default_theme); + ClassDB::bind_method("copy_theme", &Theme::copy_theme); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "default_font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_default_font", "get_default_font"); } diff --git a/scene/resources/theme.h b/scene/resources/theme.h index 021a2936bd..fb59073cbe 100644 --- a/scene/resources/theme.h +++ b/scene/resources/theme.h @@ -184,6 +184,7 @@ public: void get_type_list(List<StringName> *p_list) const; void copy_default_theme(); + void copy_theme(const Ref<Theme> &p_other); void clear(); Theme(); |