diff options
47 files changed, 654 insertions, 251 deletions
diff --git a/doc/base/classes.xml b/doc/base/classes.xml index c2c8d3e8dd..af90b5cde0 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -7202,7 +7202,7 @@ <argument index="0" name="v" type="Vector3"> </argument> <description> - Return a vector transformed (multiplied) by the matrix and return it. + Return a vector transformed (multiplied) by the matrix. </description> </method> <method name="xform_inv"> @@ -7211,7 +7211,7 @@ <argument index="0" name="v" type="Vector3"> </argument> <description> - Return a vector transformed (multiplied) by the transposed matrix and return it. Note that this is a multiplication by inverse only when the matrix represents a rotation-reflection. + Return a vector transformed (multiplied) by the transposed matrix. Note that this results in a multiplication by the inverse of the matrix only if it represents a rotation-reflection. </description> </method> </methods> diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index c71bf22965..8c3569bec0 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -28,10 +28,10 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "rasterizer_canvas_gles3.h" -#include "servers/visual/visual_server_raster.h" - #include "global_config.h" #include "os/os.h" +#include "rasterizer_scene_gles3.h" +#include "servers/visual/visual_server_raster.h" #ifndef GLES_OVER_GL #define glClearDepth glClearDepthf #endif @@ -172,6 +172,11 @@ void RasterizerCanvasGLES3::canvas_begin() { state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE, Color(1, 1, 1, 1)); state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, Transform2D()); state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, Transform2D()); + if (storage->frame.current_rt) { + state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height)); + } else { + state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0, 1.0)); + } //state.canvas_shader.set_uniform(CanvasShaderGLES3::PROJECTION_MATRIX,state.vp); //state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX,Transform()); @@ -282,7 +287,11 @@ void RasterizerCanvasGLES3::_set_texture_rect_mode(bool p_enable, bool p_ninepat state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE, state.canvas_item_modulate); state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform); state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, state.extra_matrix); - + if (storage->frame.current_rt) { + state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height)); + } else { + state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0, 1.0)); + } state.using_texture_rect = p_enable; state.using_ninepatch = p_ninepatch; } @@ -822,6 +831,78 @@ void RasterizerGLES2::_canvas_item_setup_shader_params(ShaderMaterial *material, #endif +void RasterizerCanvasGLES3::_copy_texscreen(const Rect2 &p_rect) { + + state.canvas_texscreen_used = true; + //blur diffuse into effect mipmaps using separatable convolution + //storage->shaders.copy.set_conditional(CopyShaderGLES3::GAUSSIAN_HORIZONTAL,true); + + Vector2 wh(storage->frame.current_rt->width, storage->frame.current_rt->height); + + Color blur_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()) { + + scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_BLUR_SECTION, true); + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_COPY_SECTION, true); + } + + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[0].fbo); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->color); + + storage->shaders.copy.bind(); + storage->shaders.copy.set_uniform(CopyShaderGLES3::COPY_SECTION, blur_section); + + scene_render->_copy_screen(); + + for (int i = 0; i < storage->frame.current_rt->effects.mip_maps[1].sizes.size(); i++) { + + int vp_w = storage->frame.current_rt->effects.mip_maps[1].sizes[i].width; + int vp_h = storage->frame.current_rt->effects.mip_maps[1].sizes[i].height; + glViewport(0, 0, vp_w, vp_h); + //horizontal pass + scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL, true); + scene_render->state.effect_blur_shader.bind(); + scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); + scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i)); + scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::BLUR_SECTION, blur_section); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); //previous level, since mipmaps[0] starts one level bigger + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[1].sizes[i].fbo); + + scene_render->_copy_screen(); + + scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_HORIZONTAL, false); + + //vertical pass + scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL, true); + scene_render->state.effect_blur_shader.bind(); + scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::PIXEL_SIZE, Vector2(1.0 / vp_w, 1.0 / vp_h)); + scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::LOD, float(i)); + scene_render->state.effect_blur_shader.set_uniform(EffectBlurShaderGLES3::BLUR_SECTION, blur_section); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[1].color); + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->effects.mip_maps[0].sizes[i + 1].fbo); //next level, since mipmaps[0] starts one level bigger + + scene_render->_copy_screen(); + + scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::GAUSSIAN_VERTICAL, false); + } + + scene_render->state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::USE_BLUR_SECTION, false); + storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_COPY_SECTION, false); + + glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); //back to front + glViewport(0, 0, storage->frame.current_rt->width, storage->frame.current_rt->height); + state.canvas_shader.bind(); //back to canvas + + if (state.using_texture_rect) { + state.using_texture_rect = false; + _set_texture_rect_mode(state.using_texture_rect, state.using_ninepatch); + } +} + void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light) { Item *current_clip = NULL; @@ -875,44 +956,17 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons glDisable(GL_SCISSOR_TEST); } } -#if 0 - if (ci->copy_back_buffer && framebuffer.active && framebuffer.scale==1) { - Rect2 rect; - int x,y; + if (ci->copy_back_buffer) { if (ci->copy_back_buffer->full) { - x = viewport.x; - y = window_size.height-(viewport.height+viewport.y); - } else { - x = viewport.x+ci->copy_back_buffer->screen_rect.pos.x; - y = window_size.height-(viewport.y+ci->copy_back_buffer->screen_rect.pos.y+ci->copy_back_buffer->screen_rect.size.y); - } - glActiveTexture(GL_TEXTURE0+max_texture_units-1); - glBindTexture(GL_TEXTURE_2D,framebuffer.sample_color); - -#ifdef GLEW_ENABLED - if (current_rt) { - glReadBuffer(GL_COLOR_ATTACHMENT0); - } else { - glReadBuffer(GL_BACK); - } -#endif - if (current_rt) { - glCopyTexSubImage2D(GL_TEXTURE_2D,0,viewport.x,viewport.y,viewport.x,viewport.y,viewport.width,viewport.height); - //window_size.height-(viewport.height+viewport.y) + _copy_texscreen(Rect2()); } else { - glCopyTexSubImage2D(GL_TEXTURE_2D,0,x,y,x,y,viewport.width,viewport.height); + _copy_texscreen(ci->copy_back_buffer->rect); } - - canvas_texscreen_used=true; - glActiveTexture(GL_TEXTURE0); - } -#endif - //begin rect Item *material_owner = ci->material_owner ? ci->material_owner : ci; @@ -934,6 +988,11 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons if (shader_ptr && shader_ptr != shader_cache) { + if (shader_ptr->canvas_item.uses_screen_texture && !state.canvas_texscreen_used) { + //copy if not copied before + _copy_texscreen(Rect2()); + } + state.canvas_shader.set_custom_shader(shader_ptr->custom_code_id); state.canvas_shader.bind(); @@ -1046,7 +1105,11 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons state.canvas_shader.set_uniform(CanvasShaderGLES3::FINAL_MODULATE, state.canvas_item_modulate); state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform); state.canvas_shader.set_uniform(CanvasShaderGLES3::EXTRA_MATRIX, state.extra_matrix); - + if (storage->frame.current_rt) { + state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0 / storage->frame.current_rt->width, 1.0 / storage->frame.current_rt->height)); + } else { + state.canvas_shader.set_uniform(CanvasShaderGLES3::SCREEN_PIXEL_SIZE, Vector2(1.0, 1.0)); + } if (unshaded || (state.canvas_item_modulate.a > 0.001 && (!shader_cache || shader_cache->canvas_item.light_mode != RasterizerStorageGLES3::Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY) && !ci->light_masked)) _canvas_item_render_commands(ci, current_clip, reclip); @@ -1376,6 +1439,12 @@ void RasterizerCanvasGLES3::reset_canvas() { glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + //use for reading from screen + if (storage->frame.current_rt) { + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); + } + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); @@ -1543,7 +1612,7 @@ void RasterizerCanvasGLES3::initialize() { glBindBuffer(GL_UNIFORM_BUFFER, 0); state.canvas_shader.init(); - state.canvas_shader.set_base_material_tex_index(1); + state.canvas_shader.set_base_material_tex_index(2); state.canvas_shadow_shader.init(); state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_RGBA_SHADOWS, storage->config.use_rgba_2d_shadows); diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index 5859820364..ee018e15ea 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -34,6 +34,8 @@ #include "servers/visual/rasterizer.h" #include "shaders/canvas_shadow.glsl.gen.h" +class RasterizerSceneGLES3; + class RasterizerCanvasGLES3 : public RasterizerCanvas { public: struct CanvasItemUBO { @@ -42,6 +44,8 @@ public: float time; }; + RasterizerSceneGLES3 *scene_render; + struct Data { GLuint canvas_quad_vertices; @@ -118,6 +122,7 @@ public: _FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs); _FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor); _FORCE_INLINE_ void _canvas_item_render_commands(Item *p_item, Item *current_clip, bool &reclip); + _FORCE_INLINE_ void _copy_texscreen(const Rect2 &p_rect); virtual void canvas_render_items(Item *p_item_list, int p_z, const Color &p_modulate, Light *p_light); virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow); diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 53df7e9c3d..0cfa8a7d6e 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -412,6 +412,7 @@ RasterizerGLES3::RasterizerGLES3() { canvas = memnew(RasterizerCanvasGLES3); scene = memnew(RasterizerSceneGLES3); canvas->storage = storage; + canvas->scene_render = scene; storage->canvas = canvas; scene->storage = storage; storage->scene = scene; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 24a57b772b..b1dc32e1c0 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -1445,6 +1445,8 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const { p_shader->canvas_item.light_mode = Shader::CanvasItem::LIGHT_MODE_NORMAL; p_shader->canvas_item.blend_mode = Shader::CanvasItem::BLEND_MODE_MIX; + p_shader->canvas_item.uses_screen_texture = false; + p_shader->canvas_item.uses_screen_uv = false; shaders.actions_canvas.render_mode_values["blend_add"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_ADD); shaders.actions_canvas.render_mode_values["blend_mix"] = Pair<int *, int>(&p_shader->canvas_item.blend_mode, Shader::CanvasItem::BLEND_MODE_MIX); @@ -1455,6 +1457,10 @@ void RasterizerStorageGLES3::_update_shader(Shader *p_shader) const { shaders.actions_canvas.render_mode_values["unshaded"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_UNSHADED); shaders.actions_canvas.render_mode_values["light_only"] = Pair<int *, int>(&p_shader->canvas_item.light_mode, Shader::CanvasItem::LIGHT_MODE_LIGHT_ONLY); + shaders.actions_canvas.usage_flag_pointers["SCREEN_UV"] = &p_shader->canvas_item.uses_screen_uv; + shaders.actions_canvas.usage_flag_pointers["SCREEN_PIXEL_SIZE"] = &p_shader->canvas_item.uses_screen_uv; + shaders.actions_canvas.usage_flag_pointers["SCREEN_TEXTURE"] = &p_shader->canvas_item.uses_screen_texture; + actions = &shaders.actions_canvas; actions->uniforms = &p_shader->uniforms; diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 2ef47fe2cb..3f8055d613 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -401,6 +401,8 @@ public: }; int light_mode; + bool uses_screen_texture; + bool uses_screen_uv; } canvas_item; diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index 41421a3e2f..6c568714f8 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -680,7 +680,8 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE_PIXEL_SIZE"] = "color_texpixel_size"; actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_UV"] = "screen_uv"; actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_TEXTURE"] = "screen_texture"; - actions[VS::SHADER_CANVAS_ITEM].renames["POSITION"] = "(gl_FragCoord.xy)"; + actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_PIXEL_SIZE"] = "screen_pixel_size"; + actions[VS::SHADER_CANVAS_ITEM].renames["FRAGCOORD"] = "gl_FragCoord"; actions[VS::SHADER_CANVAS_ITEM].renames["POINT_COORD"] = "gl_PointCoord"; actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_VEC"] = "light_vec"; @@ -694,6 +695,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_CANVAS_ITEM].usage_defines["COLOR"] = "#define COLOR_USED\n"; actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; + actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_PIXEL_SIZE"] = "@SCREEN_UV"; actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMAL"] = "#define NORMAL_USED\n"; actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n"; actions[VS::SHADER_CANVAS_ITEM].usage_defines["SHADOW_COLOR"] = "#define SHADOW_COLOR_USED\n"; diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index e08ef0ad12..c821acadf5 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -289,16 +289,17 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { #endif strings.push_back(vertex_code0.get_data()); + if (cc) { - code_globals = cc->vertex_globals.ascii(); - strings.push_back(code_globals.get_data()); + material_string = cc->uniforms.ascii(); + strings.push_back(material_string.get_data()); } strings.push_back(vertex_code1.get_data()); if (cc) { - material_string = cc->uniforms.ascii(); - strings.push_back(material_string.get_data()); + code_globals = cc->vertex_globals.ascii(); + strings.push_back(code_globals.get_data()); } strings.push_back(vertex_code2.get_data()); @@ -387,15 +388,15 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { strings.push_back(fragment_code0.get_data()); if (cc) { - code_globals = cc->fragment_globals.ascii(); - strings.push_back(code_globals.get_data()); + material_string = cc->uniforms.ascii(); + strings.push_back(material_string.get_data()); } strings.push_back(fragment_code1.get_data()); if (cc) { - material_string = cc->uniforms.ascii(); - strings.push_back(material_string.get_data()); + code_globals = cc->fragment_globals.ascii(); + strings.push_back(code_globals.get_data()); } strings.push_back(fragment_code2.get_data()); @@ -617,21 +618,21 @@ void ShaderGLES3::setup(const char **p_conditional_defines, int p_conditional_co String material_tag = "\nMATERIAL_UNIFORMS"; String code_tag = "\nVERTEX_SHADER_CODE"; String code = vertex_code; - int cpos = code.find(globals_tag); + int cpos = code.find(material_tag); if (cpos == -1) { vertex_code0 = code.ascii(); } else { vertex_code0 = code.substr(0, cpos).ascii(); - code = code.substr(cpos + globals_tag.length(), code.length()); + code = code.substr(cpos + material_tag.length(), code.length()); - cpos = code.find(material_tag); + cpos = code.find(globals_tag); if (cpos == -1) { vertex_code1 = code.ascii(); } else { vertex_code1 = code.substr(0, cpos).ascii(); - String code2 = code.substr(cpos + material_tag.length(), code.length()); + String code2 = code.substr(cpos + globals_tag.length(), code.length()); cpos = code2.find(code_tag); if (cpos == -1) { @@ -651,14 +652,14 @@ void ShaderGLES3::setup(const char **p_conditional_defines, int p_conditional_co String code_tag = "\nFRAGMENT_SHADER_CODE"; String light_code_tag = "\nLIGHT_SHADER_CODE"; String code = fragment_code; - int cpos = code.find(globals_tag); + int cpos = code.find(material_tag); if (cpos == -1) { fragment_code0 = code.ascii(); } else { fragment_code0 = code.substr(0, cpos).ascii(); //print_line("CODE0:\n"+String(fragment_code0.get_data())); - code = code.substr(cpos + globals_tag.length(), code.length()); - cpos = code.find(material_tag); + code = code.substr(cpos + material_tag.length(), code.length()); + cpos = code.find(globals_tag); if (cpos == -1) { fragment_code1 = code.ascii(); @@ -667,7 +668,7 @@ void ShaderGLES3::setup(const char **p_conditional_defines, int p_conditional_co fragment_code1 = code.substr(0, cpos).ascii(); //print_line("CODE1:\n"+String(fragment_code1.get_data())); - String code2 = code.substr(cpos + material_tag.length(), code.length()); + String code2 = code.substr(cpos + globals_tag.length(), code.length()); cpos = code2.find(light_code_tag); if (cpos == -1) { diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index e97ce62daa..31bae66278 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -90,7 +90,6 @@ uniform int h_frames; uniform int v_frames; #endif -VERTEX_SHADER_GLOBALS #if defined(USE_MATERIAL) @@ -102,6 +101,8 @@ MATERIAL_UNIFORMS #endif +VERTEX_SHADER_GLOBALS + void main() { vec4 vertex_color = color_attrib; @@ -211,6 +212,11 @@ uniform sampler2D screen_texture; // texunit:-3 #endif +#if defined(SCREEN_UV_USED) + +uniform vec2 screen_pixel_size; +#endif + layout(std140) uniform CanvasItemData { highp mat4 projection_matrix; @@ -256,7 +262,7 @@ const bool at_light_pass = false; uniform mediump vec4 final_modulate; -FRAGMENT_SHADER_GLOBALS + layout(location=0) out mediump vec4 frag_color; @@ -272,6 +278,7 @@ MATERIAL_UNIFORMS #endif +FRAGMENT_SHADER_GLOBALS void light_compute(inout vec3 light,vec3 light_vec,float light_height,vec4 light_color,vec2 light_uv,vec4 shadow,vec3 normal,vec2 uv,vec2 screen_uv,vec4 color) { @@ -410,8 +417,8 @@ void main() { -#if defined(ENABLE_SCREEN_UV) - vec2 screen_uv = gl_FragCoord.xy*screen_uv_mult; +#if defined(SCREEN_UV_USED) + vec2 screen_uv = gl_FragCoord.xy*screen_pixel_size; #endif diff --git a/drivers/gles3/shaders/copy.glsl b/drivers/gles3/shaders/copy.glsl index b0fb525e20..a7c388815d 100644 --- a/drivers/gles3/shaders/copy.glsl +++ b/drivers/gles3/shaders/copy.glsl @@ -17,6 +17,12 @@ out vec2 uv_interp; out vec2 uv2_interp; +#ifdef USE_COPY_SECTION + +uniform vec4 copy_section; + +#endif + void main() { #if defined(USE_CUBEMAP) || defined(USE_PANORAMA) @@ -30,6 +36,13 @@ void main() { #endif uv2_interp = uv2_in; gl_Position = vertex_attrib; + +#ifdef USE_COPY_SECTION + + uv_interp = copy_section.xy + uv_interp * copy_section.zw; + gl_Position.xy = (copy_section.xy + (gl_Position.xy * 0.5 + 0.5) * copy_section.zw) * 2.0 - 1.0; +#endif + } [fragment] diff --git a/drivers/gles3/shaders/effect_blur.glsl b/drivers/gles3/shaders/effect_blur.glsl index 89afa12f60..8ca8e21f11 100644 --- a/drivers/gles3/shaders/effect_blur.glsl +++ b/drivers/gles3/shaders/effect_blur.glsl @@ -6,11 +6,21 @@ layout(location=4) in vec2 uv_in; out vec2 uv_interp; +#ifdef USE_BLUR_SECTION + +uniform vec4 blur_section; + +#endif void main() { - uv_interp = uv_in; + uv_interp = uv_in; gl_Position = vertex_attrib; +#ifdef USE_BLUR_SECTION + + uv_interp = blur_section.xy + uv_interp * blur_section.zw; + gl_Position.xy = (blur_section.xy + (gl_Position.xy * 0.5 + 0.5) * blur_section.zw) * 2.0 - 1.0; +#endif } [fragment] diff --git a/drivers/gles3/shaders/particles.glsl b/drivers/gles3/shaders/particles.glsl index ec2577538c..6a977a201e 100644 --- a/drivers/gles3/shaders/particles.glsl +++ b/drivers/gles3/shaders/particles.glsl @@ -47,7 +47,6 @@ out highp vec4 out_xform_1; //tfb: out highp vec4 out_xform_2; //tfb: out highp vec4 out_xform_3; //tfb: -VERTEX_SHADER_GLOBALS #if defined(USE_MATERIAL) @@ -59,6 +58,9 @@ MATERIAL_UNIFORMS #endif + +VERTEX_SHADER_GLOBALS + uint hash(uint x) { x = ((x >> uint(16)) ^ x) * uint(0x45d9f3b); @@ -233,7 +235,6 @@ VERTEX_SHADER_CODE //any code here is never executed, stuff is filled just so it works -FRAGMENT_SHADER_GLOBALS #if defined(USE_MATERIAL) @@ -245,6 +246,8 @@ MATERIAL_UNIFORMS #endif +FRAGMENT_SHADER_GLOBALS + void main() { { diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index a047e693cb..40a295bc83 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -146,7 +146,7 @@ out vec3 binormal_interp; #endif -VERTEX_SHADER_GLOBALS + #if defined(USE_MATERIAL) @@ -159,6 +159,8 @@ MATERIAL_UNIFORMS #endif +VERTEX_SHADER_GLOBALS + #ifdef RENDER_DEPTH_DUAL_PARABOLOID out highp float dp_clip; @@ -418,8 +420,6 @@ layout(std140) uniform Radiance { //ubo:2 /* Material Uniforms */ -FRAGMENT_SHADER_GLOBALS - #if defined(USE_MATERIAL) @@ -431,6 +431,7 @@ MATERIAL_UNIFORMS #endif +FRAGMENT_SHADER_GLOBALS layout(std140) uniform SceneData { diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 4903d86bff..ab7a3ed459 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -2746,12 +2746,10 @@ void EditorNode::_discard_changes(const String &p_str) { _update_scene_tabs(); if (current_option == FILE_CLOSE_ALL_AND_QUIT || current_option == FILE_CLOSE_ALL_AND_RUN_PROJECT_MANAGER) { - int next_scene = _next_unsaved_scene(); - if (next_scene == -1) { + if (_next_unsaved_scene() == -1) { current_option = current_option == FILE_CLOSE_ALL_AND_QUIT ? FILE_QUIT : RUN_PROJECT_MANAGER; _discard_changes(); } else { - tab_closing = next_scene; _menu_option_confirm(current_option, false); } } else { diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 75ab1e8a44..e4b055a9e2 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -284,12 +284,12 @@ void EditorPlugin::save_global_state() {} void EditorPlugin::add_import_plugin(const Ref<EditorImportPlugin> &p_importer) { ResourceFormatImporter::get_singleton()->add_importer(p_importer); - EditorFileSystem::get_singleton()->scan_changes(); + EditorFileSystem::get_singleton()->scan(); } void EditorPlugin::remove_import_plugin(const Ref<EditorImportPlugin> &p_importer) { ResourceFormatImporter::get_singleton()->remove_importer(p_importer); - EditorFileSystem::get_singleton()->scan_changes(); + EditorFileSystem::get_singleton()->scan(); } void EditorPlugin::set_window_layout(Ref<ConfigFile> p_layout) { diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp index 40ac95e2b5..c6b9d4bb41 100644 --- a/editor/editor_plugin_settings.cpp +++ b/editor/editor_plugin_settings.cpp @@ -82,7 +82,7 @@ void EditorPluginSettings::update_plugins() { plugins.sort(); - Vector<String> active_plugins = GlobalConfig::get_singleton()->get("plugins/active"); + Vector<String> active_plugins = GlobalConfig::get_singleton()->get("editor_plugins/enabled"); for (int i = 0; i < plugins.size(); i++) { diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index f018603bfc..5c6ba892cb 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -42,7 +42,7 @@ #include "os/keyboard.h" #include "os/os.h" #include "scene/main/node.h" -#include "scene/main/scene_main_loop.h" +#include "scene/main/scene_tree.h" #include "scene/main/viewport.h" #include "translations.gen.h" #include "version.h" @@ -737,7 +737,7 @@ void EditorSettings::_load_default_text_editor_theme() { set("text_editor/highlighting/string_color", Color::html("ef6ebe")); set("text_editor/highlighting/number_color", Color::html("EB9532")); set("text_editor/highlighting/symbol_color", Color::html("badfff")); - set("text_editor/highlighting/selection_color", Color::html("7b5dbe")); + set("text_editor/highlighting/selection_color", Color::html("6ca9c2")); set("text_editor/highlighting/brace_mismatch_color", Color(1, 0.2, 0.2)); set("text_editor/highlighting/current_line_color", Color(0.3, 0.5, 0.8, 0.15)); set("text_editor/highlighting/line_length_guideline_color", Color(0.3, 0.5, 0.8, 0.1)); diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index 50a625ddc1..d729bb7b76 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -43,7 +43,6 @@ CurveEditor::CurveEditor() { _tangents_length = 40; _dragging = false; _has_undo_data = false; - _world_rect = Rect2(0, 0, 1, 1); set_focus_mode(FOCUS_ALL); set_clip_contents(true); @@ -70,11 +69,15 @@ void CurveEditor::set_curve(Ref<Curve> curve) { return; if (_curve_ref.is_valid()) { - _curve_ref->disconnect("changed", this, "_curve_changed"); + _curve_ref->disconnect(CoreStringNames::get_singleton()->changed, this, "_curve_changed"); + _curve_ref->disconnect(Curve::SIGNAL_RANGE_CHANGED, this, "_curve_changed"); } + _curve_ref = curve; + if (_curve_ref.is_valid()) { - _curve_ref->connect("changed", this, "_curve_changed"); + _curve_ref->connect(CoreStringNames::get_singleton()->changed, this, "_curve_changed"); + _curve_ref->connect(Curve::SIGNAL_RANGE_CHANGED, this, "_curve_changed"); } _selected_point = -1; @@ -130,7 +133,16 @@ void CurveEditor::on_gui_input(const Ref<InputEvent> &p_event) { if (!mb.is_pressed() && _dragging && mb.get_button_index() == BUTTON_LEFT) { _dragging = false; if (_has_undo_data) { - push_undo(_undo_data); + + UndoRedo &ur = *EditorNode::get_singleton()->get_undo_redo(); + + ur.create_action(_selected_tangent == TANGENT_NONE ? TTR("Modify Curve Point") : TTR("Modify Curve Tangent")); + ur.add_do_method(*_curve_ref, "_set_data", _curve_ref->get_data()); + ur.add_undo_method(*_curve_ref, "_set_data", _undo_data); + // Note: this will trigger one more "changed" signal even if nothing changes, + // but it's ok since it would have fired every frame during the drag anyways + ur.commit_action(); + _has_undo_data = false; } } @@ -144,11 +156,14 @@ void CurveEditor::on_gui_input(const Ref<InputEvent> &p_event) { Vector2 mpos = mm.get_position(); if (_dragging && _curve_ref.is_valid()) { + Curve &curve = **_curve_ref; + if (_selected_point != -1) { if (!_has_undo_data) { - // Save curve state before dragging points - _undo_data = _curve_ref->get_data(); + // Save full curve state before dragging points, + // because this operation can modify their order + _undo_data = curve.get_data(); _has_undo_data = true; } @@ -157,26 +172,23 @@ void CurveEditor::on_gui_input(const Ref<InputEvent> &p_event) { Vector2 point_pos = get_world_pos(mpos); - int i = _curve_ref->set_point_offset(_selected_point, point_pos.x); + int i = curve.set_point_offset(_selected_point, point_pos.x); // The index may change if the point is dragged across another one set_hover_point_index(i); set_selected_point(i); - // TODO Get rid of this clamp if zoom is implemented in this editor. // This is to prevent the user from loosing a point out of view. - if (point_pos.y < 0.0) - point_pos.y = 0.0; - else if (point_pos.y > 1.0) - point_pos.y = 1.0; - - _curve_ref->set_point_value(_selected_point, point_pos.y); + if (point_pos.y < curve.get_min_value()) + point_pos.y = curve.get_min_value(); + else if (point_pos.y > curve.get_max_value()) + point_pos.y = curve.get_max_value(); - //auto_calculate_tangents(i); + curve.set_point_value(_selected_point, point_pos.y); } else { // Drag tangent - Vector2 point_pos = _curve_ref->get_point_pos(_selected_point); + Vector2 point_pos = curve.get_point_pos(_selected_point); Vector2 control_pos = get_world_pos(mpos); Vector2 dir = (control_pos - point_pos).normalized(); @@ -190,13 +202,17 @@ void CurveEditor::on_gui_input(const Ref<InputEvent> &p_event) { bool link = !Input::get_singleton()->is_key_pressed(KEY_SHIFT); if (_selected_tangent == TANGENT_LEFT) { - _curve_ref->set_point_left_tangent(_selected_point, tangent); - if (link && _selected_point != _curve_ref->get_point_count() - 1) - _curve_ref->set_point_right_tangent(_selected_point, tangent); + curve.set_point_left_tangent(_selected_point, tangent); + + // Note: if a tangent is set to linear, it shouldn't be linked to the other + if (link && _selected_point != curve.get_point_count() - 1 && !curve.get_point_right_mode(_selected_point) != Curve::TANGENT_FREE) + curve.set_point_right_tangent(_selected_point, tangent); + } else { - _curve_ref->set_point_right_tangent(_selected_point, tangent); - if (link && _selected_point != 0) - _curve_ref->set_point_left_tangent(_selected_point, tangent); + curve.set_point_right_tangent(_selected_point, tangent); + + if (link && _selected_point != 0 && !curve.get_point_left_mode(_selected_point) != Curve::TANGENT_FREE) + curve.set_point_left_tangent(_selected_point, tangent); } } } @@ -230,25 +246,31 @@ void CurveEditor::on_preset_item_selected(int preset_id) { case PRESET_FLAT0: curve.add_point(Vector2(0, 0)); curve.add_point(Vector2(1, 0)); + curve.set_point_right_mode(0, Curve::TANGENT_LINEAR); + curve.set_point_left_mode(1, Curve::TANGENT_LINEAR); break; case PRESET_FLAT1: curve.add_point(Vector2(0, 1)); curve.add_point(Vector2(1, 1)); + curve.set_point_right_mode(0, Curve::TANGENT_LINEAR); + curve.set_point_left_mode(1, Curve::TANGENT_LINEAR); break; case PRESET_LINEAR: - curve.add_point(Vector2(0, 0), 0, 1); - curve.add_point(Vector2(1, 1), 1, 0); + curve.add_point(Vector2(0, 0)); + curve.add_point(Vector2(1, 1)); + curve.set_point_right_mode(0, Curve::TANGENT_LINEAR); + curve.set_point_left_mode(1, Curve::TANGENT_LINEAR); break; case PRESET_EASE_IN: curve.add_point(Vector2(0, 0)); - curve.add_point(Vector2(1, 1), 1.4, 0); + curve.add_point(Vector2(1, 1), (curve.get_max_value() - curve.get_min_value()) * 1.4, 0); break; case PRESET_EASE_OUT: - curve.add_point(Vector2(0, 0), 0, 1.4); + curve.add_point(Vector2(0, 0), 0, (curve.get_max_value() - curve.get_min_value()) * 1.4); curve.add_point(Vector2(1, 1)); break; @@ -261,7 +283,13 @@ void CurveEditor::on_preset_item_selected(int preset_id) { break; } - push_undo(previous_data); + UndoRedo &ur = *EditorNode::get_singleton()->get_undo_redo(); + ur.create_action(TTR("Load Curve Preset")); + + ur.add_do_method(&curve, "_set_data", curve.get_data()); + ur.add_undo_method(&curve, "_set_data", previous_data); + + ur.commit_action(); } void CurveEditor::_curve_changed() { @@ -281,6 +309,18 @@ void CurveEditor::on_context_menu_item_selected(int action_id) { case CONTEXT_REMOVE_POINT: remove_point(_selected_point); break; + + case CONTEXT_LINEAR: + toggle_linear(); + break; + + case CONTEXT_LEFT_LINEAR: + toggle_linear(TANGENT_LEFT); + break; + + case CONTEXT_RIGHT_LINEAR: + toggle_linear(TANGENT_RIGHT); + break; } } @@ -291,9 +331,37 @@ void CurveEditor::open_context_menu(Vector2 pos) { if (_curve_ref.is_valid()) { _context_menu->add_item(TTR("Add point"), CONTEXT_ADD_POINT); + if (_selected_point >= 0) { _context_menu->add_item(TTR("Remove point"), CONTEXT_REMOVE_POINT); + + if (_selected_tangent != TANGENT_NONE) { + _context_menu->add_separator(); + + _context_menu->add_check_item(TTR("Linear"), CONTEXT_LINEAR); + + bool is_linear = _selected_tangent == TANGENT_LEFT ? + _curve_ref->get_point_left_mode(_selected_point) == Curve::TANGENT_LINEAR : + _curve_ref->get_point_right_mode(_selected_point) == Curve::TANGENT_LINEAR; + + _context_menu->set_item_checked(CONTEXT_LINEAR, is_linear); + + } else { + _context_menu->add_separator(); + + if (_selected_point > 0) { + _context_menu->add_check_item(TTR("Left linear"), CONTEXT_LEFT_LINEAR); + _context_menu->set_item_checked(CONTEXT_LEFT_LINEAR, + _curve_ref->get_point_left_mode(_selected_point) == Curve::TANGENT_LINEAR); + } + if (_selected_point + 1 < _curve_ref->get_point_count()) { + _context_menu->add_check_item(TTR("Right linear"), CONTEXT_RIGHT_LINEAR); + _context_menu->set_item_checked(CONTEXT_RIGHT_LINEAR, + _curve_ref->get_point_right_mode(_selected_point) == Curve::TANGENT_LINEAR); + } + } } + _context_menu->add_separator(); } @@ -319,7 +387,7 @@ int CurveEditor::get_point_at(Vector2 pos) const { return -1; } -int CurveEditor::get_tangent_at(Vector2 pos) const { +CurveEditor::TangentIndex CurveEditor::get_tangent_at(Vector2 pos) const { if (_curve_ref.is_null() || _selected_point < 0) return TANGENT_NONE; @@ -343,7 +411,8 @@ int CurveEditor::get_tangent_at(Vector2 pos) const { void CurveEditor::add_point(Vector2 pos) { ERR_FAIL_COND(_curve_ref.is_null()); - Array prev_data = _curve_ref->get_data(); + UndoRedo &ur = *EditorNode::get_singleton()->get_undo_redo(); + ur.create_action(TTR("Remove Curve Point")); Vector2 point_pos = get_world_pos(pos); if (point_pos.y < 0.0) @@ -351,22 +420,64 @@ void CurveEditor::add_point(Vector2 pos) { else if (point_pos.y > 1.0) point_pos.y = 1.0; - _curve_ref->add_point(point_pos); + // Small trick to get the point index to feed the undo method + int i = _curve_ref->add_point(point_pos); + _curve_ref->remove_point(i); - push_undo(prev_data); + ur.add_do_method(*_curve_ref, "add_point", point_pos); + ur.add_undo_method(*_curve_ref, "remove_point", i); + + ur.commit_action(); } void CurveEditor::remove_point(int index) { ERR_FAIL_COND(_curve_ref.is_null()); - Array prev_data = _curve_ref->get_data(); + UndoRedo &ur = *EditorNode::get_singleton()->get_undo_redo(); + ur.create_action(TTR("Remove Curve Point")); + + Curve::Point p = _curve_ref->get_point(index); - _curve_ref->remove_point(index); + ur.add_do_method(*_curve_ref, "remove_point", index); + ur.add_undo_method(*_curve_ref, "add_point", p.pos, p.left_tangent, p.right_tangent, p.left_mode, p.right_mode); if (index == _selected_point) set_selected_point(-1); - push_undo(prev_data); + ur.commit_action(); +} + +void CurveEditor::toggle_linear(TangentIndex tangent) { + ERR_FAIL_COND(_curve_ref.is_null()); + + UndoRedo &ur = *EditorNode::get_singleton()->get_undo_redo(); + ur.create_action(TTR("Toggle Curve Linear Tangent")); + + if (tangent == TANGENT_NONE) + tangent = _selected_tangent; + + if (tangent == TANGENT_LEFT) { + + bool is_linear = _curve_ref->get_point_left_mode(_selected_point) == Curve::TANGENT_LINEAR; + + Curve::TangentMode prev_mode = _curve_ref->get_point_left_mode(_selected_point); + Curve::TangentMode mode = is_linear ? Curve::TANGENT_FREE : Curve::TANGENT_LINEAR; + + ur.add_do_method(*_curve_ref, "set_point_left_mode", _selected_point, mode); + ur.add_undo_method(*_curve_ref, "set_point_left_mode", _selected_point, prev_mode); + + } else { + + bool is_linear = _curve_ref->get_point_right_mode(_selected_point) == Curve::TANGENT_LINEAR; + + Curve::TangentMode prev_mode = _curve_ref->get_point_right_mode(_selected_point); + Curve::TangentMode mode = is_linear ? Curve::TANGENT_FREE : Curve::TANGENT_LINEAR; + + ur.add_do_method(*_curve_ref, "set_point_right_mode", _selected_point, mode); + ur.add_undo_method(*_curve_ref, "set_point_right_mode", _selected_point, prev_mode); + } + + ur.commit_action(); } void CurveEditor::set_selected_point(int index) { @@ -383,32 +494,27 @@ void CurveEditor::set_hover_point_index(int index) { } } -void CurveEditor::push_undo(Array previous_curve_data) { - UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - - ur->create_action(TTR("Modify Curve")); - ur->add_do_method(*_curve_ref, "_set_data", _curve_ref->get_data()); - ur->add_undo_method(*_curve_ref, "_set_data", previous_curve_data); - - // This boolean is to prevent commit_action from executing the do method, - // because at this point it's already done, there is no point in doing it twice - _curve_ref->_disable_set_data = true; - ur->commit_action(); - _curve_ref->_disable_set_data = false; -} - void CurveEditor::update_view_transform() { Vector2 control_size = get_size(); const real_t margin = 24; - _world_rect = Rect2(Curve::MIN_X, 0, Curve::MAX_X, 1); + float min_y = 0; + float max_y = 1; + + if (_curve_ref.is_valid()) { + min_y = _curve_ref->get_min_value(); + max_y = _curve_ref->get_max_value(); + } + + Rect2 world_rect = Rect2(Curve::MIN_X, min_y, Curve::MAX_X, max_y - min_y); Vector2 wm = Vector2(margin, margin) / control_size; - _world_rect.position -= wm; - _world_rect.size += 2.0 * wm; + wm.y *= (max_y - min_y); + world_rect.position -= wm; + world_rect.size += 2.0 * wm; _world_to_view = Transform2D(); - _world_to_view.translate(-_world_rect.position - Vector2(0, _world_rect.size.y)); - _world_to_view.scale(Vector2(control_size.x, -control_size.y) / _world_rect.size); + _world_to_view.translate(-world_rect.position - Vector2(0, world_rect.size.y)); + _world_to_view.scale(Vector2(control_size.x, -control_size.y) / world_rect.size); } Vector2 CurveEditor::get_tangent_view_pos(int i, TangentIndex tangent) const { @@ -509,17 +615,18 @@ void CurveEditor::_draw() { const Color grid_color0(0, 0, 0, 0.5); const Color grid_color1(0, 0, 0, 0.15); - draw_line(Vector2(min_edge.x, 0), Vector2(max_edge.x, 0), grid_color0); + draw_line(Vector2(min_edge.x, curve.get_min_value()), Vector2(max_edge.x, curve.get_min_value()), grid_color0); + draw_line(Vector2(max_edge.x, curve.get_max_value()), Vector2(min_edge.x, curve.get_max_value()), grid_color0); draw_line(Vector2(0, min_edge.y), Vector2(0, max_edge.y), grid_color0); draw_line(Vector2(1, max_edge.y), Vector2(1, min_edge.y), grid_color0); - draw_line(Vector2(max_edge.x, 1), Vector2(min_edge.x, 1), grid_color0); - const Vector2 grid_step(0.25, 0.5); + float curve_height = (curve.get_max_value() - curve.get_min_value()); + const Vector2 grid_step(0.25, 0.5 * curve_height); for (real_t x = 0; x < 1.0; x += grid_step.x) { draw_line(Vector2(x, min_edge.y), Vector2(x, max_edge.y), grid_color1); } - for (real_t y = 0; y < 1.0; y += grid_step.y) { + for (real_t y = curve.get_min_value(); y < curve.get_max_value(); y += grid_step.y) { draw_line(Vector2(min_edge.x, y), Vector2(max_edge.x, y), grid_color1); } @@ -528,17 +635,30 @@ void CurveEditor::_draw() { draw_set_transform_matrix(Transform2D()); Ref<Font> font = get_font("font", "Label"); + float font_height = font->get_height(); const Color text_color(1, 1, 1, 0.3); - draw_string(font, get_view_pos(Vector2(0, 0)), "0.0", text_color); - - draw_string(font, get_view_pos(Vector2(0.25, 0)), "0.25", text_color); - draw_string(font, get_view_pos(Vector2(0.5, 0)), "0.5", text_color); - draw_string(font, get_view_pos(Vector2(0.75, 0)), "0.75", text_color); - draw_string(font, get_view_pos(Vector2(1, 0)), "1.0", text_color); + { + // X axis + float y = curve.get_min_value(); + Vector2 off(0, font_height - 1); + draw_string(font, get_view_pos(Vector2(0, y)) + off, "0.0", text_color); + draw_string(font, get_view_pos(Vector2(0.25, y)) + off, "0.25", text_color); + draw_string(font, get_view_pos(Vector2(0.5, y)) + off, "0.5", text_color); + draw_string(font, get_view_pos(Vector2(0.75, y)) + off, "0.75", text_color); + draw_string(font, get_view_pos(Vector2(1, y)) + off, "1.0", text_color); + } - draw_string(font, get_view_pos(Vector2(0, 0.5)), "0.5", text_color); - draw_string(font, get_view_pos(Vector2(0, 1)), "1.0", text_color); + { + // Y axis + float m0 = curve.get_min_value(); + float m1 = 0.5 * (curve.get_min_value() + curve.get_max_value()); + float m2 = curve.get_max_value(); + Vector2 off(1, -1); + draw_string(font, get_view_pos(Vector2(0, m0)) + off, String::num(m0, 2), text_color); + draw_string(font, get_view_pos(Vector2(0, m1)) + off, String::num(m1, 2), text_color); + draw_string(font, get_view_pos(Vector2(0, m2)) + off, String::num(m2, 3), text_color); + } // Draw tangents for current point @@ -611,6 +731,12 @@ void CurveEditor::_draw() { Vector2 pos = curve.get_point_pos(_hover_point); stroke_rect(Rect2(get_view_pos(pos), Vector2(1, 1)).grow(_hover_radius), hover_color); } + + // Help text + + if (_selected_point > 0 && _selected_point + 1 < curve.get_point_count()) { + draw_string(font, Vector2(50, font_height), TTR("Hold Shift to edit tangents individually"), text_color); + } } // TODO That should be part of the drawing API... diff --git a/editor/plugins/curve_editor_plugin.h b/editor/plugins/curve_editor_plugin.h index 0ed4ee3517..a4952dfb28 100644 --- a/editor/plugins/curve_editor_plugin.h +++ b/editor/plugins/curve_editor_plugin.h @@ -57,7 +57,10 @@ public: enum ContextAction { CONTEXT_ADD_POINT = 0, - CONTEXT_REMOVE_POINT + CONTEXT_REMOVE_POINT, + CONTEXT_LINEAR, + CONTEXT_LEFT_LINEAR, + CONTEXT_RIGHT_LINEAR }; enum TangentIndex { @@ -79,12 +82,12 @@ private: void open_context_menu(Vector2 pos); int get_point_at(Vector2 pos) const; - int get_tangent_at(Vector2 pos) const; + TangentIndex get_tangent_at(Vector2 pos) const; void add_point(Vector2 pos); void remove_point(int index); + void toggle_linear(TangentIndex tangent = TANGENT_NONE); void set_selected_point(int index); void set_hover_point_index(int index); - void push_undo(Array previous_curve_data); void update_view_transform(); Vector2 get_tangent_view_pos(int i, TangentIndex tangent) const; @@ -96,7 +99,6 @@ private: void stroke_rect(Rect2 rect, Color color); private: - Rect2 _world_rect; Transform2D _world_to_view; Ref<Curve> _curve_ref; @@ -105,12 +107,11 @@ private: Array _undo_data; bool _has_undo_data; - bool _undo_no_commit; Vector2 _context_click_pos; int _selected_point; int _hover_point; - int _selected_tangent; + TangentIndex _selected_tangent; bool _dragging; // Constant diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index f3941d6a16..0024870665 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -313,6 +313,13 @@ void ScriptEditor::_goto_script_line(REF p_script, int p_line) { editor->push_item(p_script.ptr()); + if (bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor"))) { + + Ref<Script> script = p_script->cast_to<Script>(); + if (!script.is_null() && script->get_path().is_resource_file()) + edit(p_script, p_line, 0); + } + int selected = tab_container->get_current_tab(); if (selected < 0 || selected >= tab_container->get_child_count()) return; @@ -866,6 +873,11 @@ void ScriptEditor::_menu_option(int p_option) { debugger->set_hide_on_stop(visible); debug_menu->get_popup()->set_item_checked(debug_menu->get_popup()->get_item_index(DEBUG_SHOW_KEEP_OPEN), !visible); } break; + case DEBUG_WITH_EXTERNAL_EDITOR: { + bool debug_with_external_editor = !debug_menu->get_popup()->is_item_checked(debug_menu->get_popup()->get_item_index(DEBUG_WITH_EXTERNAL_EDITOR)); + debugger->set_debug_with_external_editor(debug_with_external_editor); + debug_menu->get_popup()->set_item_checked(debug_menu->get_popup()->get_item_index(DEBUG_WITH_EXTERNAL_EDITOR), debug_with_external_editor); + } } int selected = tab_container->get_current_tab(); @@ -1545,13 +1557,10 @@ bool ScriptEditor::edit(const Ref<Script> &p_script, int p_line, int p_col, bool bool open_dominant = EditorSettings::get_singleton()->get("text_editor/files/open_dominant_script_on_scene_change"); - Error err = p_script->get_language()->open_in_external_editor(p_script, p_line >= 0 ? p_line : 0, p_col); - if (err == OK) - return false; - if (err != ERR_UNAVAILABLE) - WARN_PRINT("Couldn't open in custom external text editor"); - - if (p_script->get_path().is_resource_file() && bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor"))) { + if ((debugger->get_dump_stack_script() != p_script || debugger->get_debug_with_external_editor()) && + p_script->get_language()->open_in_external_editor(p_script, p_line >= 0 ? p_line : 0, p_col) == OK && + p_script->get_path().is_resource_file() && + bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor"))) { String path = EditorSettings::get_singleton()->get("text_editor/external/exec_path"); String flags = EditorSettings::get_singleton()->get("text_editor/external/exec_flags"); @@ -2244,6 +2253,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { debug_menu->get_popup()->add_separator(); //debug_menu->get_popup()->add_check_item("Show Debugger",DEBUG_SHOW); debug_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("debugger/keep_debugger_open", TTR("Keep Debugger Open")), DEBUG_SHOW_KEEP_OPEN); + debug_menu->get_popup()->add_check_shortcut(ED_SHORTCUT("debugger/debug_with_exteral_editor", TTR("Debug with external editor")), DEBUG_WITH_EXTERNAL_EDITOR); debug_menu->get_popup()->connect("id_pressed", this, "_menu_option"); debug_menu->get_popup()->set_item_disabled(debug_menu->get_popup()->get_item_index(DEBUG_NEXT), true); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index e036d1ed9c..3b444c0883 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -141,6 +141,7 @@ class ScriptEditor : public VBoxContainer { DEBUG_CONTINUE, DEBUG_SHOW, DEBUG_SHOW_KEEP_OPEN, + DEBUG_WITH_EXTERNAL_EDITOR, SEARCH_HELP, SEARCH_CLASSES, SEARCH_WEBSITE, diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 9f76119374..60fd9d8e30 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -557,6 +557,8 @@ void ScriptEditor::_update_modified_scripts_for_external_editor(Ref<Script> p_fo if (!bool(EditorSettings::get_singleton()->get("text_editor/external/use_external_editor"))) return; + ERR_FAIL_COND(!get_tree()); + Set<Ref<Script> > scripts; Node *base = get_tree()->get_edited_scene_root(); diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index 6d22935dcb..9dce48937c 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -1137,8 +1137,9 @@ void ScriptEditorDebugger::_stack_dump_frame_selected() { Dictionary d = ti->get_metadata(0); - Ref<Script> s = ResourceLoader::load(d["file"]); - emit_signal("goto_script_line", s, int(d["line"]) - 1); + stack_script = ResourceLoader::load(d["file"]); + emit_signal("goto_script_line", stack_script, int(d["line"]) - 1); + stack_script.unref(); ERR_FAIL_COND(connection.is_null()); ERR_FAIL_COND(!connection->is_connected_to_host()); @@ -1522,6 +1523,21 @@ void ScriptEditorDebugger::set_hide_on_stop(bool p_hide) { hide_on_stop = p_hide; } +bool ScriptEditorDebugger::get_debug_with_external_editor() const { + + return enable_external_editor; +} + +void ScriptEditorDebugger::set_debug_with_external_editor(bool p_enabled) { + + enable_external_editor = p_enabled; +} + +Ref<Script> ScriptEditorDebugger::get_dump_stack_script() const { + + return stack_script; +} + void ScriptEditorDebugger::_paused() { ERR_FAIL_COND(connection.is_null()); @@ -1871,6 +1887,7 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { last_path_id = false; error_count = 0; hide_on_stop = true; + enable_external_editor = false; last_error_count = 0; EditorNode::get_singleton()->get_pause_button()->connect("pressed", this, "_paused"); diff --git a/editor/script_editor_debugger.h b/editor/script_editor_debugger.h index 49a4abb6ac..907c267d49 100644 --- a/editor/script_editor_debugger.h +++ b/editor/script_editor_debugger.h @@ -84,6 +84,8 @@ class ScriptEditorDebugger : public Control { int last_error_count; bool hide_on_stop; + bool enable_external_editor; + Ref<Script> stack_script; TabContainer *tabs; @@ -201,6 +203,11 @@ public: void set_hide_on_stop(bool p_hide); + bool get_debug_with_external_editor() const; + void set_debug_with_external_editor(bool p_enabled); + + Ref<Script> get_dump_stack_script() const; + void set_tool_button(Button *p_tb) { debugger_button = p_tb; } void reload_scripts(); diff --git a/main/main.cpp b/main/main.cpp index cd464de1aa..2d6b151e14 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -43,7 +43,7 @@ #include "input_map.h" #include "io/resource_loader.h" -#include "scene/main/scene_main_loop.h" +#include "scene/main/scene_tree.h" #include "servers/audio_server.h" #include "io/resource_loader.h" diff --git a/main/performance.cpp b/main/performance.cpp index 5788f64239..c819e15f71 100644 --- a/main/performance.cpp +++ b/main/performance.cpp @@ -30,7 +30,7 @@ #include "performance.h" #include "message_queue.h" #include "os/os.h" -#include "scene/main/scene_main_loop.h" +#include "scene/main/scene_tree.h" #include "servers/physics_2d_server.h" #include "servers/physics_server.h" #include "servers/visual_server.h" diff --git a/main/tests/test_gui.cpp b/main/tests/test_gui.cpp index 291a557d04..3c6a708cd8 100644 --- a/main/tests/test_gui.cpp +++ b/main/tests/test_gui.cpp @@ -50,7 +50,7 @@ #include "scene/gui/tab_container.h" #include "scene/gui/texture_rect.h" #include "scene/gui/tree.h" -#include "scene/main/scene_main_loop.h" +#include "scene/main/scene_tree.h" #include "scene/3d/camera.h" #include "scene/main/viewport.h" diff --git a/modules/gdnative/gdnative.cpp b/modules/gdnative/gdnative.cpp index 706b81f7a3..dad9a54df6 100644 --- a/modules/gdnative/gdnative.cpp +++ b/modules/gdnative/gdnative.cpp @@ -35,7 +35,7 @@ #include "os/file_access.h" #include "os/os.h" -#include "scene/main/scene_main_loop.h" +#include "scene/main/scene_tree.h" #include "scene/resources/scene_format_text.h" #if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED) diff --git a/modules/gdnative/gdnative.h b/modules/gdnative/gdnative.h index 6716b684a0..650f999192 100644 --- a/modules/gdnative/gdnative.h +++ b/modules/gdnative/gdnative.h @@ -335,7 +335,7 @@ public: virtual bool has_named_classes() const; virtual int find_function(const String &p_function, const String &p_code) const; virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const; - + virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return ERR_UNAVAILABLE; } virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, String &r_call_hint) { return ERR_UNAVAILABLE; } virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_base_path, Object *p_owner, LookupResult &r_result) { return ERR_UNAVAILABLE; } diff --git a/modules/gdscript/gd_script.h b/modules/gdscript/gd_script.h index ebef4fed74..0add348ca9 100644 --- a/modules/gdscript/gd_script.h +++ b/modules/gdscript/gd_script.h @@ -389,6 +389,7 @@ public: virtual bool can_inherit_from_file() { return true; } virtual int find_function(const String &p_function, const String &p_code) const; virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const; + virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return OK; } virtual Error complete_code(const String &p_code, const String &p_base_path, Object *p_owner, List<String> *r_options, String &r_call_hint); #ifdef TOOLS_ENABLED virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_base_path, Object *p_owner, LookupResult &r_result); diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index 1ccc358342..20a1cf49c5 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -571,6 +571,7 @@ public: virtual bool has_named_classes() const; virtual int find_function(const String &p_function, const String &p_code) const; virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const; + virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return ERR_UNAVAILABLE; } virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const; virtual void add_global_constant(const StringName &p_variable, const Variant &p_value); diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index b466e64aec..e0e1a217b3 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -33,7 +33,7 @@ #include "io/resource_loader.h" #include "os/os.h" #include "scene/main/node.h" -#include "scene/main/scene_main_loop.h" +#include "scene/main/scene_tree.h" #include "visual_script_nodes.h" ////////////////////////////////////////// diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 8ea3b8098d..86c98d076e 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -34,7 +34,7 @@ #include "os/input.h" #include "os/os.h" #include "scene/main/node.h" -#include "scene/main/scene_main_loop.h" +#include "scene/main/scene_tree.h" ////////////////////////////////////////// ////////////////FUNCTION////////////////// diff --git a/modules/visual_script/visual_script_yield_nodes.cpp b/modules/visual_script/visual_script_yield_nodes.cpp index 8f96eb6800..be5b218d0a 100644 --- a/modules/visual_script/visual_script_yield_nodes.cpp +++ b/modules/visual_script/visual_script_yield_nodes.cpp @@ -31,7 +31,7 @@ #include "os/os.h" #include "scene/main/node.h" -#include "scene/main/scene_main_loop.h" +#include "scene/main/scene_tree.h" #include "visual_script_nodes.h" ////////////////////////////////////////// diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index bffc171fc1..06130e3252 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -31,7 +31,7 @@ #define CANVAS_ITEM_H #include "scene/main/node.h" -#include "scene/main/scene_main_loop.h" +#include "scene/main/scene_tree.h" #include "scene/resources/material.h" #include "scene/resources/shader.h" #include "scene/resources/texture.h" diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp index c291aa33ed..edf97bc248 100644 --- a/scene/3d/particles.cpp +++ b/scene/3d/particles.cpp @@ -1052,16 +1052,11 @@ float ParticlesMaterial::get_param_randomness(Parameter p_param) const { static void _adjust_curve_range(const Ref<Texture> &p_texture, float p_min, float p_max) { - Ref<CurveTexture> curve = p_texture; - if (!curve.is_valid()) + Ref<CurveTexture> curve_tex = p_texture; + if (!curve_tex.is_valid()) return; - if (curve->get_max() == 1.0) { - curve->set_max(p_max); - } - if (curve->get_min() == 0.0) { - curve->set_min(p_min); - } + curve_tex->ensure_default_setup(p_min, p_max); } void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture> &p_texture) { diff --git a/scene/3d/spatial.h b/scene/3d/spatial.h index 764950aa8e..d114a6231b 100644 --- a/scene/3d/spatial.h +++ b/scene/3d/spatial.h @@ -31,7 +31,7 @@ #define SPATIAL_H #include "scene/main/node.h" -#include "scene/main/scene_main_loop.h" +#include "scene/main/scene_tree.h" /** @author Juan Linietsky <reduzio@gmail.com> diff --git a/scene/main/node.h b/scene/main/node.h index 4a41fb82ab..ffd2b7ce5f 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -35,7 +35,7 @@ #include "map.h" #include "object.h" #include "path_db.h" -#include "scene/main/scene_main_loop.h" +#include "scene/main/scene_tree.h" #include "script_language.h" class Viewport; diff --git a/scene/main/scene_main_loop.cpp b/scene/main/scene_tree.cpp index f7a255cd33..39d5469360 100644 --- a/scene/main/scene_main_loop.cpp +++ b/scene/main/scene_tree.cpp @@ -27,7 +27,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "scene_main_loop.h" +#include "scene_tree.h" #include "global_config.h" #include "message_queue.h" diff --git a/scene/main/scene_main_loop.h b/scene/main/scene_tree.h index 2ea79bf945..2ea79bf945 100644 --- a/scene/main/scene_main_loop.h +++ b/scene/main/scene_tree.h diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 151bc80321..76e07db93d 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -129,7 +129,7 @@ #include "scene/animation/animation_tree_player.h" #include "scene/animation/tween.h" #include "scene/main/resource_preloader.h" -#include "scene/main/scene_main_loop.h" +#include "scene/main/scene_tree.h" #include "scene/resources/packed_scene.h" #include "scene/resources/mesh_data_tool.h" diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index 3957923c6a..bc6d0230a0 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -380,15 +380,16 @@ Curve2D::Curve2D() #endif +const char *Curve::SIGNAL_RANGE_CHANGED = "range_changed"; + Curve::Curve() { _bake_resolution = 100; _baked_cache_dirty = false; -#ifdef TOOLS_ENABLED - _disable_set_data = false; -#endif + _min_value = 0; + _max_value = 1; } -int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent) { +int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent, TangentMode left_mode, TangentMode right_mode) { // Add a point and preserve order // Curve bounds is in 0..1 @@ -400,7 +401,7 @@ int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent) { int ret = -1; if (_points.size() == 0) { - _points.push_back(Point(p_pos, left_tangent, right_tangent)); + _points.push_back(Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); ret = 0; } else if (_points.size() == 1) { @@ -409,10 +410,10 @@ int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent) { real_t diff = p_pos.x - _points[0].pos.x; if (diff > 0) { - _points.push_back(Point(p_pos, left_tangent, right_tangent)); + _points.push_back(Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); ret = 1; } else { - _points.insert(0, Point(p_pos, left_tangent, right_tangent)); + _points.insert(0, Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); ret = 0; } @@ -431,16 +432,18 @@ int Curve::add_point(Vector2 p_pos, real_t left_tangent, real_t right_tangent) { if (i == 0 && p_pos.x < _points[0].pos.x) { // Insert before anything else - _points.insert(0, Point(p_pos, left_tangent, right_tangent)); + _points.insert(0, Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); ret = 0; } else { // Insert between i and i+1 ++i; - _points.insert(i, Point(p_pos, left_tangent, right_tangent)); + _points.insert(i, Point(p_pos, left_tangent, right_tangent, left_mode, right_mode)); ret = i; } } + update_auto_tangents(ret); + mark_dirty(); return ret; @@ -496,12 +499,38 @@ void Curve::clean_dupes() { void Curve::set_point_left_tangent(int i, real_t tangent) { ERR_FAIL_INDEX(i, _points.size()); _points[i].left_tangent = tangent; + _points[i].left_mode = TANGENT_FREE; mark_dirty(); } void Curve::set_point_right_tangent(int i, real_t tangent) { ERR_FAIL_INDEX(i, _points.size()); _points[i].right_tangent = tangent; + _points[i].right_mode = TANGENT_FREE; + mark_dirty(); +} + +void Curve::set_point_left_mode(int i, TangentMode p_mode) { + ERR_FAIL_INDEX(i, _points.size()); + _points[i].left_mode = p_mode; + if (i > 0) { + if (p_mode == TANGENT_LINEAR) { + Vector2 v = (_points[i - 1].pos - _points[i].pos).normalized(); + _points[i].left_tangent = v.y / v.x; + } + } + mark_dirty(); +} + +void Curve::set_point_right_mode(int i, TangentMode p_mode) { + ERR_FAIL_INDEX(i, _points.size()); + _points[i].right_mode = p_mode; + if (i + 1 < _points.size()) { + if (p_mode == TANGENT_LINEAR) { + Vector2 v = (_points[i + 1].pos - _points[i].pos).normalized(); + _points[i].right_tangent = v.y / v.x; + } + } mark_dirty(); } @@ -515,6 +544,16 @@ real_t Curve::get_point_right_tangent(int i) const { return _points[i].right_tangent; } +Curve::TangentMode Curve::get_point_left_mode(int i) const { + ERR_FAIL_INDEX_V(i, _points.size(), TANGENT_FREE); + return _points[i].left_mode; +} + +Curve::TangentMode Curve::get_point_right_mode(int i) const { + ERR_FAIL_INDEX_V(i, _points.size(), TANGENT_FREE); + return _points[i].right_mode; +} + void Curve::remove_point(int p_index) { ERR_FAIL_INDEX(p_index, _points.size()); _points.remove(p_index); @@ -529,6 +568,7 @@ void Curve::clear_points() { void Curve::set_point_value(int p_index, real_t pos) { ERR_FAIL_INDEX(p_index, _points.size()); _points[p_index].pos.y = pos; + update_auto_tangents(p_index); mark_dirty(); } @@ -539,6 +579,11 @@ int Curve::set_point_offset(int p_index, float offset) { int i = add_point(Vector2(offset, p.pos.y)); _points[i].left_tangent = p.left_tangent; _points[i].right_tangent = p.right_tangent; + _points[i].left_mode = p.left_mode; + _points[i].right_mode = p.right_mode; + if (p_index != i) + update_auto_tangents(p_index); + update_auto_tangents(i); return i; } @@ -547,6 +592,58 @@ Vector2 Curve::get_point_pos(int p_index) const { return _points[p_index].pos; } +Curve::Point Curve::get_point(int p_index) const { + ERR_FAIL_INDEX_V(p_index, _points.size(), Point()); + return _points[p_index]; +} + +void Curve::update_auto_tangents(int i) { + + Point &p = _points[i]; + + if (i > 0) { + if (p.left_mode == TANGENT_LINEAR) { + Vector2 v = (_points[i - 1].pos - p.pos).normalized(); + p.left_tangent = v.y / v.x; + } + if (_points[i - 1].right_mode == TANGENT_LINEAR) { + Vector2 v = (_points[i - 1].pos - p.pos).normalized(); + _points[i - 1].right_tangent = v.y / v.x; + } + } + + if (i + 1 < _points.size()) { + if (p.right_mode == TANGENT_LINEAR && i + 1 < _points.size()) { + Vector2 v = (_points[i + 1].pos - p.pos).normalized(); + p.right_tangent = v.y / v.x; + } + if (_points[i + 1].left_mode == TANGENT_LINEAR) { + Vector2 v = (_points[i + 1].pos - p.pos).normalized(); + _points[i + 1].left_tangent = v.y / v.x; + } + } +} + +#define MIN_Y_RANGE 0.01 + +void Curve::set_min_value(float p_min) { + if (p_min > _max_value - MIN_Y_RANGE) + _min_value = _max_value - MIN_Y_RANGE; + else + _min_value = p_min; + // Note: min and max are indicative values, + // it's still possible that existing points are out of range at this point. + emit_signal(SIGNAL_RANGE_CHANGED); +} + +void Curve::set_max_value(float p_max) { + if (p_max < _min_value + MIN_Y_RANGE) + _max_value = _min_value + MIN_Y_RANGE; + else + _max_value = p_max; + emit_signal(SIGNAL_RANGE_CHANGED); +} + real_t Curve::interpolate(real_t offset) const { if (_points.size() == 0) return 0; @@ -606,48 +703,60 @@ void Curve::mark_dirty() { Array Curve::get_data() const { Array output; - output.resize(_points.size() * 3); + const unsigned int ELEMS = 5; + output.resize(_points.size() * ELEMS); for (int j = 0; j < _points.size(); ++j) { const Point p = _points[j]; - int i = j * 3; + int i = j * ELEMS; output[i] = p.pos; output[i + 1] = p.left_tangent; output[i + 2] = p.right_tangent; + output[i + 3] = p.left_mode; + output[i + 4] = p.right_mode; } return output; } void Curve::set_data(Array input) { - ERR_FAIL_COND(input.size() % 3 != 0); - -#ifdef TOOLS_ENABLED - if (_disable_set_data) - return; -#endif + const unsigned int ELEMS = 5; + ERR_FAIL_COND(input.size() % ELEMS != 0); _points.clear(); // Validate input - for (int i = 0; i < input.size(); i += 3) { + for (int i = 0; i < input.size(); i += ELEMS) { ERR_FAIL_COND(input[i].get_type() != Variant::VECTOR2); ERR_FAIL_COND(input[i + 1].get_type() != Variant::REAL); ERR_FAIL_COND(input[i + 2].get_type() != Variant::REAL); + + ERR_FAIL_COND(input[i + 3].get_type() != Variant::INT); + int left_mode = input[i + 3]; + ERR_FAIL_COND(left_mode < 0 || left_mode >= TANGENT_MODE_COUNT); + + ERR_FAIL_COND(input[i + 4].get_type() != Variant::INT); + int right_mode = input[i + 4]; + ERR_FAIL_COND(right_mode < 0 || right_mode >= TANGENT_MODE_COUNT); } - _points.resize(input.size() / 3); + _points.resize(input.size() / ELEMS); for (int j = 0; j < _points.size(); ++j) { Point &p = _points[j]; - int i = j * 3; + int i = j * ELEMS; p.pos = input[i]; p.left_tangent = input[i + 1]; p.right_tangent = input[i + 2]; + // TODO For some reason the compiler won't convert from Variant to enum + int left_mode = input[i + 3]; + int right_mode = input[i + 4]; + p.left_mode = (TangentMode)left_mode; + p.right_mode = (TangentMode)right_mode; } mark_dirty(); @@ -716,7 +825,8 @@ real_t Curve::interpolate_baked(real_t offset) { void Curve::_bind_methods() { - ClassDB::bind_method(D_METHOD("add_point", "pos", "left_tangent", "right_tangent"), &Curve::add_point, DEFVAL(0), DEFVAL(0)); + ClassDB::bind_method(D_METHOD("add_point", "pos", "left_tangent", "right_tangent", "left_mode", "right_mode"), + &Curve::add_point, DEFVAL(0), DEFVAL(0), DEFVAL(TANGENT_FREE), DEFVAL(TANGENT_FREE)); ClassDB::bind_method(D_METHOD("remove_point", "index"), &Curve::remove_point); ClassDB::bind_method(D_METHOD("clear_points"), &Curve::clear_points); ClassDB::bind_method(D_METHOD("get_point_pos", "index"), &Curve::get_point_pos); @@ -726,8 +836,16 @@ void Curve::_bind_methods() { ClassDB::bind_method(D_METHOD("interpolate_baked", "offset"), &Curve::interpolate_baked); ClassDB::bind_method(D_METHOD("get_point_left_tangent", "index"), &Curve::get_point_left_tangent); ClassDB::bind_method(D_METHOD("get_point_right_tangent", "index"), &Curve::get_point_left_tangent); + ClassDB::bind_method(D_METHOD("get_point_left_mode", "index"), &Curve::get_point_left_mode); + ClassDB::bind_method(D_METHOD("get_point_right_mode", "index"), &Curve::get_point_left_mode); ClassDB::bind_method(D_METHOD("set_point_left_tangent", "index", "tangent"), &Curve::set_point_left_tangent); ClassDB::bind_method(D_METHOD("set_point_right_tangent", "index", "tangent"), &Curve::set_point_left_tangent); + ClassDB::bind_method(D_METHOD("set_point_left_mode", "index", "mode"), &Curve::set_point_left_mode); + ClassDB::bind_method(D_METHOD("set_point_right_mode", "index", "mode"), &Curve::set_point_left_mode); + ClassDB::bind_method(D_METHOD("get_min_value"), &Curve::get_min_value); + ClassDB::bind_method(D_METHOD("set_min_value", "min"), &Curve::set_min_value); + ClassDB::bind_method(D_METHOD("get_max_value"), &Curve::get_max_value); + ClassDB::bind_method(D_METHOD("set_max_value", "max"), &Curve::set_max_value); ClassDB::bind_method(D_METHOD("clean_dupes"), &Curve::clean_dupes); ClassDB::bind_method(D_METHOD("bake"), &Curve::bake); ClassDB::bind_method(D_METHOD("get_bake_resolution"), &Curve::get_bake_resolution); @@ -735,8 +853,12 @@ void Curve::_bind_methods() { ClassDB::bind_method(D_METHOD("_get_data"), &Curve::get_data); ClassDB::bind_method(D_METHOD("_set_data", "data"), &Curve::set_data); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "min_value", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_min_value", "get_min_value"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "max_value", PROPERTY_HINT_RANGE, "-1024,1024,0.01"), "set_max_value", "get_max_value"); ADD_PROPERTY(PropertyInfo(Variant::INT, "bake_resolution", PROPERTY_HINT_RANGE, "1,1000,1"), "set_bake_resolution", "get_bake_resolution"); ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_data", "_get_data"); + + ADD_SIGNAL(MethodInfo(SIGNAL_RANGE_CHANGED)); } int Curve2D::get_point_count() const { diff --git a/scene/resources/curve.h b/scene/resources/curve.h index 63b9a07f07..83a4357bfb 100644 --- a/scene/resources/curve.h +++ b/scene/resources/curve.h @@ -89,24 +89,39 @@ public: static const int MIN_X = 0.f; static const int MAX_X = 1.f; -#ifdef TOOLS_ENABLED - bool _disable_set_data; -#endif + static const char *SIGNAL_RANGE_CHANGED; + + enum TangentMode { + TANGENT_FREE = 0, + TANGENT_LINEAR, + TANGENT_MODE_COUNT + }; struct Point { Vector2 pos; real_t left_tangent; real_t right_tangent; + TangentMode left_mode; + TangentMode right_mode; Point() { left_tangent = 0; right_tangent = 0; + left_mode = TANGENT_FREE; + right_mode = TANGENT_FREE; } - Point(Vector2 p, real_t left = 0, real_t right = 0) { - pos = p; - left_tangent = left; - right_tangent = right; + Point(Vector2 p_pos, + real_t p_left = 0, + real_t p_right = 0, + TangentMode p_left_mode = TANGENT_FREE, + TangentMode p_right_mode = TANGENT_FREE) { + + pos = p_pos; + left_tangent = p_left; + right_tangent = p_right; + left_mode = p_left_mode; + right_mode = p_right_mode; } }; @@ -114,7 +129,12 @@ public: int get_point_count() const { return _points.size(); } - int add_point(Vector2 p_pos, real_t left_tangent = 0, real_t right_tangent = 0); + int add_point(Vector2 p_pos, + real_t left_tangent = 0, + real_t right_tangent = 0, + TangentMode left_mode = TANGENT_FREE, + TangentMode right_mode = TANGENT_FREE); + void remove_point(int p_index); void clear_points(); @@ -124,6 +144,14 @@ public: int set_point_offset(int p_index, float offset); Vector2 get_point_pos(int p_index) const; + Point get_point(int p_index) const; + + float get_min_value() const { return _min_value; } + void set_min_value(float p_min); + + float get_max_value() const { return _max_value; } + void set_max_value(float p_max); + real_t interpolate(real_t offset) const; real_t interpolate_local_nocheck(int index, real_t local_offset) const; @@ -131,8 +159,15 @@ public: void set_point_left_tangent(int i, real_t tangent); void set_point_right_tangent(int i, real_t tangent); + void set_point_left_mode(int i, TangentMode p_mode); + void set_point_right_mode(int i, TangentMode p_mode); + real_t get_point_left_tangent(int i) const; real_t get_point_right_tangent(int i) const; + TangentMode get_point_left_mode(int i) const; + TangentMode get_point_right_mode(int i) const; + + void update_auto_tangents(int i); Array get_data() const; void set_data(Array input); @@ -152,8 +187,12 @@ private: bool _baked_cache_dirty; Vector<real_t> _baked_cache; int _bake_resolution; + float _min_value; + float _max_value; }; +VARIANT_ENUM_CAST(Curve::TangentMode) + class Curve2D : public Resource { GDCLASS(Curve2D, Resource); diff --git a/scene/resources/shape.cpp b/scene/resources/shape.cpp index 77f2096d9b..6be88374e5 100644 --- a/scene/resources/shape.cpp +++ b/scene/resources/shape.cpp @@ -30,7 +30,7 @@ #include "shape.h" #include "os/os.h" -#include "scene/main/scene_main_loop.h" +#include "scene/main/scene_tree.h" #include "scene/resources/mesh.h" #include "servers/physics_server.h" diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 0bd8c41228..6c7ae2445c 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -1370,12 +1370,6 @@ CubeMap::~CubeMap() { void CurveTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_max", "max"), &CurveTexture::set_max); - ClassDB::bind_method(D_METHOD("get_max"), &CurveTexture::get_max); - - ClassDB::bind_method(D_METHOD("set_min", "min"), &CurveTexture::set_min); - ClassDB::bind_method(D_METHOD("get_min"), &CurveTexture::get_min); - ClassDB::bind_method(D_METHOD("set_width", "width"), &CurveTexture::set_width); ClassDB::bind_method(D_METHOD("set_curve", "curve:Curve"), &CurveTexture::set_curve); @@ -1383,52 +1377,31 @@ void CurveTexture::_bind_methods() { ClassDB::bind_method(D_METHOD("_update"), &CurveTexture::_update); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "min", PROPERTY_HINT_RANGE, "-1024,1024"), "set_min", "get_min"); - ADD_PROPERTY(PropertyInfo(Variant::REAL, "max", PROPERTY_HINT_RANGE, "-1024,1024"), "set_max", "get_max"); ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "32,4096"), "set_width", "get_width"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_curve", "get_curve"); } -void CurveTexture::set_max(float p_max) { - - _max = p_max; - emit_changed(); -} -float CurveTexture::get_max() const { - return _max; -} - -void CurveTexture::set_min(float p_min) { - - _min = p_min; - emit_changed(); -} -float CurveTexture::get_min() const { - - return _min; -} void CurveTexture::set_width(int p_width) { ERR_FAIL_COND(p_width < 32 || p_width > 4096); _width = p_width; _update(); } + int CurveTexture::get_width() const { return _width; } -void CurveTexture::ensure_default_setup() { - +void CurveTexture::ensure_default_setup(float p_min, float p_max) { if (_curve.is_null()) { Ref<Curve> curve = Ref<Curve>(memnew(Curve)); curve->add_point(Vector2(0, 1)); curve->add_point(Vector2(1, 1)); + curve->set_min_value(p_min); + curve->set_max_value(p_max); set_curve(curve); - } - - if (get_min() == 0 && get_max() == 1) { - set_max(32); + // Min and max is 0..1 by default } } @@ -1457,11 +1430,9 @@ void CurveTexture::_update() { if (_curve.is_valid()) { Curve &curve = **_curve; - float height = _max - _min; for (int i = 0; i < _width; ++i) { float t = i / static_cast<float>(_width); - float v = curve.interpolate_baked(t); - wd[i] = CLAMP(_min + v * height, _min, _max); + wd[i] = curve.interpolate_baked(t); } } else { @@ -1490,9 +1461,6 @@ RID CurveTexture::get_rid() const { } CurveTexture::CurveTexture() { - - _max = 1; - _min = 0; _width = 2048; _texture = VS::get_singleton()->texture_create(); } diff --git a/scene/resources/texture.h b/scene/resources/texture.h index ff5a58c221..9bbbd1d091 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -403,7 +403,6 @@ class CurveTexture : public Texture { private: RID _texture; Ref<Curve> _curve; - float _min, _max; int _width; void _update(); @@ -412,16 +411,10 @@ protected: static void _bind_methods(); public: - void set_max(float p_max); - float get_max() const; - - void set_min(float p_min); - float get_min() const; - void set_width(int p_width); int get_width() const; - void ensure_default_setup(); + void ensure_default_setup(float p_min=0, float p_max=1); void set_curve(Ref<Curve> p_curve); Ref<Curve> get_curve() const; diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp index 42f1a98826..b04c8716fb 100644 --- a/servers/visual/shader_types.cpp +++ b/servers/visual/shader_types.cpp @@ -102,7 +102,6 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SSS_STRENGTH"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["AO"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["EMISSION"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SPECIAL"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["DISCARD"] = ShaderLanguage::TYPE_BOOL; shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["DEPTH_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; @@ -156,7 +155,7 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["AT_LIGHT_PASS"] = ShaderLanguage::TYPE_BOOL; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["SRC_COLOR"] = ShaderLanguage::TYPE_VEC4; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["POSITION"] = ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["FRAGCOORD"] = ShaderLanguage::TYPE_VEC4; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMAL"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMALMAP"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMALMAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT; @@ -165,9 +164,12 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TEXTURE_PIXEL_SIZE"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["SCREEN_PIXEL_SIZE"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["POINT_COORD"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TIME"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["AT_LIGHT_PASS"] = ShaderLanguage::TYPE_BOOL; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; + shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["POSITION"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["NORMAL"] = ShaderLanguage::TYPE_VEC3; |