diff options
47 files changed, 742 insertions, 181 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..3bf5baec14 100644 --- a/drivers/gles2/shader_gles2.cpp +++ b/drivers/gles2/shader_gles2.cpp @@ -229,6 +229,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { glDeleteShader(v.vert_id); glDeleteShader(v.frag_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; } } @@ -242,6 +243,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; @@ -323,6 +329,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { if (iloglen < 0) { glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_PRINT("No OpenGL vertex shader compiler log. What the frick?"); @@ -344,6 +351,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { Memory::free_static(ilogmem); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; } @@ -398,6 +406,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_PRINT("No OpenGL fragment shader compiler log. What the frick?"); @@ -420,6 +429,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; } @@ -447,6 +457,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_PRINT("No OpenGL program link log. What the frick?"); @@ -471,6 +482,7 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_FAIL_V(NULL); @@ -514,6 +526,10 @@ ShaderGLES2::Version *ShaderGLES2::get_current_version() { glUseProgram(0); v.ok = true; + if (cc) { + cc->versions.insert(conditional_version.version); + } + return &v; } @@ -678,9 +694,26 @@ void ShaderGLES2::set_custom_shader(uint32_t p_code_id) { } void ShaderGLES2::free_custom_shader(uint32_t p_code_id) { + ERR_FAIL_COND(!custom_code_map.has(p_code_id)); if (conditional_version.code_version == p_code_id) - conditional_version.code_version = 0; + conditional_version.code_version = 0; //do not keep using a version that is going away + + VersionKey key; + key.code_version = p_code_id; + for (Set<uint32_t>::Element *E = custom_code_map[p_code_id].versions.front(); E; E = E->next()) { + key.version = E->get(); + ERR_CONTINUE(!version_map.has(key)); + Version &v = version_map[key]; + + glDeleteShader(v.vert_id); + glDeleteShader(v.frag_id); + glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); + v.id = 0; + + version_map.erase(key); + } custom_code_map.erase(p_code_id); } diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h index 468971471c..d493880d0b 100644 --- a/drivers/gles2/shader_gles2.h +++ b/drivers/gles2/shader_gles2.h @@ -104,6 +104,7 @@ private: Vector<StringName> texture_uniforms; Vector<StringName> custom_uniforms; Vector<CharString> custom_defines; + Set<uint32_t> versions; }; struct Version { @@ -465,6 +466,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..966466d9bc 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); @@ -4132,9 +4132,19 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glDepthFunc(GL_LEQUAL); - state.used_contact_shadows = true; + state.used_contact_shadows = false; - if (!storage->config.no_depth_prepass && storage->frame.current_rt && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { //detect with state.used_contact_shadows too + for (int i = 0; i < p_light_cull_count; i++) { + + ERR_BREAK(i >= RenderList::MAX_LIGHTS); + + LightInstance *li = light_instance_owner.getptr(p_light_cull_result[i]); + if (li->light_ptr->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] > CMP_EPSILON) { + state.used_contact_shadows = true; + } + } + + if (!storage->config.no_depth_prepass && storage->frame.current_rt && state.debug_draw != VS::VIEWPORT_DEBUG_DRAW_OVERDRAW && !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_NO_3D_EFFECTS]) { //detect with state.used_contact_shadows too //pre z pass glDisable(GL_BLEND); @@ -4164,7 +4174,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/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index edc2a6c054..64396cadd1 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -204,6 +204,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.vert_id); glDeleteShader(v.frag_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; } } @@ -324,6 +325,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_PRINT("Vertex shader compilation failed with empty log"); @@ -345,6 +347,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { memfree(ilogmem); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; } @@ -418,6 +421,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_PRINT("Fragment shader compilation failed with empty log"); } else { @@ -440,6 +444,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; } @@ -486,6 +491,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_FAIL_COND_V(iloglen <= 0, NULL); } @@ -508,6 +514,7 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glDeleteShader(v.frag_id); glDeleteShader(v.vert_id); glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); v.id = 0; ERR_FAIL_V(NULL); @@ -559,6 +566,9 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { glUseProgram(0); v.ok = true; + if (cc) { + cc->versions.insert(conditional_version.version); + } return &v; } @@ -742,7 +752,23 @@ void ShaderGLES3::free_custom_shader(uint32_t p_code_id) { ERR_FAIL_COND(!custom_code_map.has(p_code_id)); if (conditional_version.code_version == p_code_id) - conditional_version.code_version = 0; //bye + conditional_version.code_version = 0; //do not keep using a version that is going away + + VersionKey key; + key.code_version = p_code_id; + for (Set<uint32_t>::Element *E = custom_code_map[p_code_id].versions.front(); E; E = E->next()) { + key.version = E->get(); + ERR_CONTINUE(!version_map.has(key)); + Version &v = version_map[key]; + + glDeleteShader(v.vert_id); + glDeleteShader(v.frag_id); + glDeleteProgram(v.id); + memdelete_arr(v.uniform_location); + v.id = 0; + + version_map.erase(key); + } custom_code_map.erase(p_code_id); } diff --git a/drivers/gles3/shader_gles3.h b/drivers/gles3/shader_gles3.h index 1f98f4883d..1ed30986bf 100644 --- a/drivers/gles3/shader_gles3.h +++ b/drivers/gles3/shader_gles3.h @@ -117,6 +117,7 @@ private: uint32_t version; Vector<StringName> texture_uniforms; Vector<CharString> custom_defines; + Set<uint32_t> versions; }; struct Version { 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/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index 5d0abef4b8..6593eb8f03 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -75,9 +75,16 @@ void EditorAudioBus::_notification(int p_what) { disabled_vu = get_icon("BusVuFrozen", "EditorIcons"); + Color solo_color = Color::html(EditorSettings::get_singleton()->is_dark_theme() ? "#ffe337" : "#ffeb70"); + Color mute_color = Color::html(EditorSettings::get_singleton()->is_dark_theme() ? "#ff2929" : "#ff7070"); + Color bypass_color = Color::html(EditorSettings::get_singleton()->is_dark_theme() ? "#22ccff" : "#70deff"); + solo->set_icon(get_icon("AudioBusSolo", "EditorIcons")); + solo->add_color_override("icon_color_pressed", solo_color); mute->set_icon(get_icon("AudioBusMute", "EditorIcons")); + mute->add_color_override("icon_color_pressed", mute_color); bypass->set_icon(get_icon("AudioBusBypass", "EditorIcons")); + bypass->add_color_override("icon_color_pressed", bypass_color); bus_options->set_icon(get_icon("GuiMiniTabMenu", "EditorIcons")); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index e660bb2daf..d7e0302478 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -1899,13 +1899,13 @@ int EditorInspector::get_scroll_offset() const { return get_v_scroll(); } -void EditorInspector::set_use_sub_inspector_bg(bool p_enable) { +void EditorInspector::set_sub_inspector(bool p_enable) { - use_sub_inspector_bg = p_enable; + sub_inspector = p_enable; if (!is_inside_tree()) return; - if (use_sub_inspector_bg) { + if (sub_inspector) { add_style_override("bg", get_stylebox("sub_inspector_bg", "Editor")); } else { add_style_override("bg", get_stylebox("bg", "Tree")); @@ -2126,16 +2126,18 @@ void EditorInspector::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { - get_tree()->connect("node_removed", this, "_node_removed"); - if (use_sub_inspector_bg) { + if (sub_inspector) { add_style_override("bg", get_stylebox("sub_inspector_bg", "Editor")); - } else if (is_inside_tree()) { + } else { add_style_override("bg", get_stylebox("bg", "Tree")); + get_tree()->connect("node_removed", this, "_node_removed"); } } if (p_what == NOTIFICATION_EXIT_TREE) { - get_tree()->disconnect("node_removed", this, "_node_removed"); + if (!sub_inspector) { + get_tree()->disconnect("node_removed", this, "_node_removed"); + } edit(NULL); } @@ -2184,7 +2186,7 @@ void EditorInspector::_notification(int p_what) { if (p_what == EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED) { - if (use_sub_inspector_bg) { + if (sub_inspector) { add_style_override("bg", get_stylebox("sub_inspector_bg", "Editor")); } else if (is_inside_tree()) { add_style_override("bg", get_stylebox("bg", "Tree")); @@ -2280,7 +2282,7 @@ EditorInspector::EditorInspector() { _prop_edited = "property_edited"; set_process(true); property_focusable = -1; - use_sub_inspector_bg = false; + sub_inspector = false; get_v_scrollbar()->connect("value_changed", this, "_vscroll_changed"); update_scroll_request = -1; diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index d64a78be57..4fb3198e87 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -281,7 +281,7 @@ class EditorInspector : public ScrollContainer { bool update_all_pending; bool read_only; bool keying; - bool use_sub_inspector_bg; + bool sub_inspector; float refresh_countdown; bool update_tree_pending; @@ -375,7 +375,7 @@ public: void set_object_class(const String &p_class); String get_object_class() const; - void set_use_sub_inspector_bg(bool p_enable); + void set_sub_inspector(bool p_enable); EditorInspector(); }; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 719130621e..0ff0bca7ee 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -1108,12 +1108,15 @@ void EditorNode::_save_scene(String p_file, int idx) { } } -void EditorNode::save_all_scenes_and_restart() { +void EditorNode::save_all_scenes() { _menu_option_confirm(RUN_STOP, true); - exiting = true; - _save_all_scenes(); +} + +void EditorNode::restart_editor() { + + exiting = true; String to_reopen; if (get_tree()->get_edited_scene_root()) { @@ -2305,7 +2308,8 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { ProjectSettings::get_singleton()->set("rendering/quality/driver/driver_name", video_driver_request); ProjectSettings::get_singleton()->save(); - save_all_scenes_and_restart(); + save_all_scenes(); + restart_editor(); } break; default: { if (p_option >= IMPORT_PLUGIN_BASE) { @@ -4760,6 +4764,8 @@ EditorNode::EditorNode() { ResourceLoader::clear_translation_remaps(); //no remaps using during editor ResourceLoader::clear_path_remaps(); + ImageTexture::set_keep_images_cached(true); + InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton()); if (id) { diff --git a/editor/editor_node.h b/editor/editor_node.h index 13bebea5f0..a45ea54186 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -782,7 +782,8 @@ public: void add_tool_submenu_item(const String &p_name, PopupMenu *p_submenu); void remove_tool_menu_item(const String &p_name); - void save_all_scenes_and_restart(); + void save_all_scenes(); + void restart_editor(); void dim_editor(bool p_dimming); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index c5d0f13c60..f19eac6878 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -2448,7 +2448,7 @@ void EditorPropertyResource::update_property() { sub_inspector->set_enable_v_scroll(false); sub_inspector->set_use_doc_hints(true); - sub_inspector->set_use_sub_inspector_bg(true); + sub_inspector->set_sub_inspector(true); sub_inspector->set_enable_capitalize_paths(true); sub_inspector->connect("property_keyed", this, "_sub_inspector_property_keyed"); diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp index e59df7c932..40cf02ac9d 100644 --- a/editor/import_dock.cpp +++ b/editor/import_dock.cpp @@ -372,6 +372,63 @@ void ImportDock::clear() { preset->get_popup()->clear(); } +static bool _find_owners(EditorFileSystemDirectory *efsd, const String &p_path) { + + if (!efsd) + return false; + + for (int i = 0; i < efsd->get_subdir_count(); i++) { + + if (_find_owners(efsd->get_subdir(i), p_path)) { + return true; + } + } + + for (int i = 0; i < efsd->get_file_count(); i++) { + + Vector<String> deps = efsd->get_file_deps(i); + if (deps.find(p_path) != -1) + return true; + } + + return false; +} +void ImportDock::_reimport_attempt() { + + bool need_restart = false; + bool used_in_resources = false; + for (int i = 0; i < params->paths.size(); i++) { + Ref<ConfigFile> config; + config.instance(); + Error err = config->load(params->paths[i] + ".import"); + ERR_CONTINUE(err != OK); + + String imported_with = config->get_value("remap", "importer"); + if (imported_with != params->importer->get_importer_name()) { + need_restart = true; + if (_find_owners(EditorFileSystem::get_singleton()->get_filesystem(), params->paths[i])) { + used_in_resources = true; + } + } + } + + if (need_restart) { + label_warning->set_visible(used_in_resources); + reimport_confirm->popup_centered_minsize(); + return; + } + + _reimport(); +} + +void ImportDock::_reimport_and_restart() { + + EditorNode::get_singleton()->save_all_scenes(); + EditorResourcePreview::get_singleton()->stop(); //dont try to re-create previews after import + _reimport(); + EditorNode::get_singleton()->restart_editor(); +} + void ImportDock::_reimport() { for (int i = 0; i < params->paths.size(); i++) { @@ -416,6 +473,7 @@ void ImportDock::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { import_opts->edit(params); + label_warning->add_color_override("font_color", get_color("warning_color", "Editor")); } break; } } @@ -433,6 +491,8 @@ void ImportDock::_bind_methods() { ClassDB::bind_method(D_METHOD("_preset_selected"), &ImportDock::_preset_selected); ClassDB::bind_method(D_METHOD("_importer_selected"), &ImportDock::_importer_selected); ClassDB::bind_method(D_METHOD("_property_toggled"), &ImportDock::_property_toggled); + ClassDB::bind_method(D_METHOD("_reimport_and_restart"), &ImportDock::_reimport_and_restart); + ClassDB::bind_method(D_METHOD("_reimport_attempt"), &ImportDock::_reimport_attempt); } void ImportDock::initialize_import_options() const { @@ -469,11 +529,22 @@ ImportDock::ImportDock() { add_child(hb); import = memnew(Button); import->set_text(TTR("Reimport")); - import->connect("pressed", this, "_reimport"); + import->connect("pressed", this, "_reimport_attempt"); hb->add_spacer(); hb->add_child(import); hb->add_spacer(); + reimport_confirm = memnew(ConfirmationDialog); + reimport_confirm->get_ok()->set_text(TTR("Save scenes, re-import and restart")); + add_child(reimport_confirm); + reimport_confirm->connect("confirmed", this, "_reimport_and_restart"); + + VBoxContainer *vbc_confirm = memnew(VBoxContainer()); + vbc_confirm->add_child(memnew(Label(TTR("Changing the type of an imported file requires editor restart.")))); + label_warning = memnew(Label(TTR("WARNING: Assets exist that use this resource, they may stop loading properly."))); + vbc_confirm->add_child(label_warning); + reimport_confirm->add_child(vbc_confirm); + params = memnew(ImportDockParameters); } diff --git a/editor/import_dock.h b/editor/import_dock.h index bc992b2f7e..1d43e00b63 100644 --- a/editor/import_dock.h +++ b/editor/import_dock.h @@ -36,6 +36,7 @@ #include "editor/editor_file_system.h" #include "editor/editor_inspector.h" #include "scene/gui/box_container.h" +#include "scene/gui/dialogs.h" #include "scene/gui/menu_button.h" #include "scene/gui/option_button.h" #include "scene/gui/popup_menu.h" @@ -52,6 +53,8 @@ class ImportDock : public VBoxContainer { List<PropertyInfo> properties; Map<StringName, Variant> property_values; + ConfirmationDialog *reimport_confirm; + Label *label_warning; Button *import; ImportDockParameters *params; @@ -61,6 +64,8 @@ class ImportDock : public VBoxContainer { void _update_options(const Ref<ConfigFile> &p_config = Ref<ConfigFile>()); void _property_toggled(const StringName &p_prop, bool p_checked); + void _reimport_attempt(); + void _reimport_and_restart(); void _reimport(); enum { 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/editor/project_manager.cpp b/editor/project_manager.cpp index b8fb9d4ab0..7ce4029476 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -83,6 +83,8 @@ private: Container *name_container; Container *path_container; Container *install_path_container; + Container *rasterizer_container; + Ref<ButtonGroup> rasterizer_button_group; Label *msg; LineEdit *project_path; LineEdit *project_name; @@ -471,6 +473,13 @@ private: if (mode == MODE_NEW) { ProjectSettings::CustomMap initial_settings; + if (rasterizer_button_group->get_pressed_button()->get_meta("driver_name") == "GLES3") { + initial_settings["rendering/quality/driver/driver_name"] = "GLES3"; + } else { + initial_settings["rendering/quality/driver/driver_name"] = "GLES2"; + initial_settings["rendering/vram_compression/import_etc2"] = false; + initial_settings["rendering/vram_compression/import_etc"] = true; + } initial_settings["application/config/name"] = project_name->get_text(); initial_settings["application/config/icon"] = "res://icon.png"; initial_settings["rendering/environment/default_environment"] = "res://default_env.tres"; @@ -687,6 +696,7 @@ public: msg->hide(); install_path_container->hide(); install_status_rect->hide(); + rasterizer_container->hide(); get_ok()->set_disabled(false); ProjectSettings *current = memnew(ProjectSettings); @@ -738,6 +748,7 @@ public: get_ok()->set_text(TTR("Import & Edit")); name_container->hide(); install_path_container->hide(); + rasterizer_container->hide(); project_path->grab_focus(); } else if (mode == MODE_NEW) { @@ -746,6 +757,7 @@ public: get_ok()->set_text(TTR("Create & Edit")); name_container->show(); install_path_container->hide(); + rasterizer_container->show(); project_name->call_deferred("grab_focus"); project_name->call_deferred("select_all"); @@ -755,13 +767,14 @@ public: get_ok()->set_text(TTR("Install & Edit")); name_container->hide(); install_path_container->hide(); + rasterizer_container->hide(); project_path->grab_focus(); } _test_path(); } - popup_centered(Size2(500, 0) * EDSCALE); + popup_centered_minsize(Size2(500, 0) * EDSCALE); } ProjectDialog() { @@ -840,6 +853,48 @@ public: msg->set_align(Label::ALIGN_CENTER); vb->add_child(msg); + // rasterizer selection + rasterizer_container = memnew(VBoxContainer); + vb->add_child(rasterizer_container); + l = memnew(Label); + l->set_text(TTR("Renderer:")); + rasterizer_container->add_child(l); + Container *rshb = memnew(HBoxContainer); + rasterizer_container->add_child(rshb); + rasterizer_button_group.instance(); + + Container *rvb = memnew(VBoxContainer); + rvb->set_h_size_flags(SIZE_EXPAND_FILL); + rshb->add_child(rvb); + Button *rs_button = memnew(CheckBox); + rs_button->set_button_group(rasterizer_button_group); + rs_button->set_text(TTR("OpenGL ES 3.0")); + rs_button->set_meta("driver_name", "GLES3"); + rs_button->set_pressed(true); + rvb->add_child(rs_button); + l = memnew(Label); + l->set_text(TTR("Higher visual quality\nAll features available\nIncompatible with older hardware\nNot recommended for web games")); + rvb->add_child(l); + + rshb->add_child(memnew(VSeparator)); + + rvb = memnew(VBoxContainer); + rvb->set_h_size_flags(SIZE_EXPAND_FILL); + rshb->add_child(rvb); + rs_button = memnew(CheckBox); + rs_button->set_button_group(rasterizer_button_group); + rs_button->set_text(TTR("OpenGL ES 2.0")); + rs_button->set_meta("driver_name", "GLES2"); + rvb->add_child(rs_button); + l = memnew(Label); + l->set_text(TTR("Lower visual quality\nSome features not available\nWorks on most hardware\nRecommended for web games")); + rvb->add_child(l); + + l = memnew(Label); + l->set_text(TTR("Renderer can be changed later, but scenes may need to be adjusted.")); + l->set_align(Label::ALIGN_CENTER); + rasterizer_container->add_child(l); + fdialog = memnew(FileDialog); fdialog->set_access(FileDialog::ACCESS_FILESYSTEM); fdialog_install = memnew(FileDialog); diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index dd31853e73..cc33550ac9 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -1606,7 +1606,8 @@ TabContainer *ProjectSettingsEditor::get_tabs() { } void ProjectSettingsEditor::_editor_restart() { - EditorNode::get_singleton()->save_all_scenes_and_restart(); + EditorNode::get_singleton()->save_all_scenes(); + EditorNode::get_singleton()->restart_editor(); } void ProjectSettingsEditor::_editor_restart_request() { diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index acc735d571..5f6459045a 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -898,6 +898,10 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da item.name = strings[2]; item.script = strings[0]; item.line = strings[1].to_int(); + } else if (strings.size() == 4) { //Built-in scripts have an :: in their name + item.name = strings[3]; + item.script = strings[0] + "::" + strings[1]; + item.line = strings[2].to_int(); } } else { diff --git a/editor/settings_config_dialog.cpp b/editor/settings_config_dialog.cpp index e4d5573a9a..ecd35cb930 100644 --- a/editor/settings_config_dialog.cpp +++ b/editor/settings_config_dialog.cpp @@ -375,7 +375,8 @@ void EditorSettingsDialog::_focus_current_search_box() { } void EditorSettingsDialog::_editor_restart() { - EditorNode::get_singleton()->save_all_scenes_and_restart(); + EditorNode::get_singleton()->save_all_scenes(); + EditorNode::get_singleton()->restart_editor(); } void EditorSettingsDialog::_editor_restart_request() { 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_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index a343a4f0ed..0daa574f72 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -141,10 +141,14 @@ void AnimationNodeOneShot::get_parameter_list(List<PropertyInfo> *r_list) const r_list->push_back(PropertyInfo(Variant::BOOL, prev_active, PROPERTY_HINT_NONE, "", 0)); r_list->push_back(PropertyInfo(Variant::REAL, time, PROPERTY_HINT_NONE, "", 0)); r_list->push_back(PropertyInfo(Variant::REAL, remaining, PROPERTY_HINT_NONE, "", 0)); + r_list->push_back(PropertyInfo(Variant::REAL, time_to_restart, PROPERTY_HINT_NONE, "", 0)); } + Variant AnimationNodeOneShot::get_parameter_default_value(const StringName &p_parameter) const { if (p_parameter == active || p_parameter == prev_active) { return false; + } else if (p_parameter == time_to_restart) { + return -1; } else { return 0.0; } @@ -218,13 +222,26 @@ float AnimationNodeOneShot::process(float p_time, bool p_seek) { bool prev_active = get_parameter(this->prev_active); float time = get_parameter(this->time); float remaining = get_parameter(this->remaining); + float time_to_restart = get_parameter(this->time_to_restart); if (!active) { //make it as if this node doesn't exist, pass input 0 by. if (prev_active) { set_parameter(this->prev_active, false); } - return blend_input(0, p_time, p_seek, 1.0, FILTER_IGNORE, !sync); + if (time_to_restart >= 0.0 && !p_seek) { + time_to_restart -= p_time; + if (time_to_restart < 0) { + //restart + set_parameter(this->active, true); + active = true; + } + set_parameter(this->time_to_restart, time_to_restart); + } + + if (!active) { + return blend_input(0, p_time, p_seek, 1.0, FILTER_IGNORE, !sync); + } } bool os_seek = p_seek; @@ -276,6 +293,10 @@ float AnimationNodeOneShot::process(float p_time, bool p_seek) { if (remaining <= 0) { set_parameter(this->active, false); set_parameter(this->prev_active, false); + if (autorestart) { + float restart_sec = autorestart_delay + Math::randf() * autorestart_random_delay; + set_parameter(this->time_to_restart, restart_sec); + } } } @@ -350,6 +371,7 @@ AnimationNodeOneShot::AnimationNodeOneShot() { prev_active = "prev_active"; time = "time"; remaining = "remaining"; + time_to_restart = "time_to_restart"; } //////////////////////////////////////////////// diff --git a/scene/animation/animation_blend_tree.h b/scene/animation/animation_blend_tree.h index e207713134..c16dcb1b8c 100644 --- a/scene/animation/animation_blend_tree.h +++ b/scene/animation/animation_blend_tree.h @@ -91,6 +91,7 @@ private: StringName prev_active; StringName time; StringName remaining; + StringName time_to_restart; protected: static void _bind_methods(); 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/texture.cpp b/scene/resources/texture.cpp index 3870916779..26036c08a9 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -178,6 +178,12 @@ void ImageTexture::_reload_hook(const RID &p_hook) { _change_notify(); } +bool ImageTexture::keep_images_cached = false; + +void ImageTexture::set_keep_images_cached(bool p_enable) { + keep_images_cached = p_enable; +} + void ImageTexture::create(int p_width, int p_height, Image::Format p_format, uint32_t p_flags) { flags = p_flags; @@ -198,6 +204,10 @@ void ImageTexture::create_from_image(const Ref<Image> &p_image, uint32_t p_flags VisualServer::get_singleton()->texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_flags); VisualServer::get_singleton()->texture_set_data(texture, p_image); _change_notify(); + + if (keep_images_cached) { + image_cache = p_image; + } } void ImageTexture::set_flags(uint32_t p_flags) { @@ -245,6 +255,10 @@ void ImageTexture::set_data(const Ref<Image> &p_image) { _change_notify(); alpha_cache.unref(); + + if (keep_images_cached) { + image_cache = p_image; + } } void ImageTexture::_resource_path_changed() { @@ -254,7 +268,11 @@ void ImageTexture::_resource_path_changed() { Ref<Image> ImageTexture::get_data() const { - return VisualServer::get_singleton()->texture_get_data(texture); + if (image_cache.is_valid()) { + return image_cache; + } else { + return VisualServer::get_singleton()->texture_get_data(texture); + } } int ImageTexture::get_width() const { diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 2b67ebec62..4b5b504510 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -111,6 +111,7 @@ private: Size2 size_override; float lossy_storage_quality; mutable Ref<BitMap> alpha_cache; + Ref<Image> image_cache; protected: virtual void reload_from_file(); @@ -125,7 +126,11 @@ protected: void _set_data(Dictionary p_data); + static bool keep_images_cached; + public: + static void set_keep_images_cached(bool p_enable); + void create(int p_width, int p_height, Image::Format p_format, uint32_t p_flags = FLAGS_DEFAULT); void create_from_image(const Ref<Image> &p_image, uint32_t p_flags = FLAGS_DEFAULT); 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(); diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 02acf72951..14c9a29ae5 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -2406,7 +2406,7 @@ VisualServer::VisualServer() { GLOBAL_DEF("rendering/quality/shading/force_blinn_over_ggx.mobile", true); GLOBAL_DEF("rendering/quality/depth_prepass/enable", true); - GLOBAL_DEF("rendering/quality/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno"); + GLOBAL_DEF("rendering/quality/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple"); GLOBAL_DEF("rendering/quality/filters/use_nearest_mipmap_filter", false); } |