diff options
36 files changed, 1738 insertions, 80 deletions
diff --git a/.gitignore b/.gitignore index f3a1b9693c..571af848ac 100644 --- a/.gitignore +++ b/.gitignore @@ -259,3 +259,4 @@ Desktop.ini # Recycle Bin used on file shares $RECYCLE.BIN/ logo.h +*.autosave diff --git a/core/os/input.cpp b/core/os/input.cpp index a827e75896..5d4b3a834d 100644 --- a/core/os/input.cpp +++ b/core/os/input.cpp @@ -62,6 +62,8 @@ void Input::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_mouse_mode","mode"),&Input::set_mouse_mode); ObjectTypeDB::bind_method(_MD("get_mouse_mode"),&Input::get_mouse_mode); ObjectTypeDB::bind_method(_MD("warp_mouse_pos","to"),&Input::warp_mouse_pos); + ObjectTypeDB::bind_method(_MD("action_press"),&Input::action_press); + ObjectTypeDB::bind_method(_MD("action_release"),&Input::action_release); BIND_CONSTANT( MOUSE_MODE_VISIBLE ); BIND_CONSTANT( MOUSE_MODE_HIDDEN ); diff --git a/core/variant_op.cpp b/core/variant_op.cpp index ec43b1275c..fbb5e2631d 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -1687,6 +1687,19 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid) return; } } + if (ie.type == InputEvent::ACTION) { + + if (str =="action") { + valid=true; + ie.action.action=p_value; + return; + } + else if (str == "pressed") { + valid=true; + ie.action.pressed=p_value; + return; + } + } } break; case DICTIONARY: { @@ -2365,6 +2378,17 @@ Variant Variant::get(const Variant& p_index, bool *r_valid) const { return Vector2(ie.screen_drag.speed_x,ie.screen_drag.speed_y); } } + if (ie.type == InputEvent::ACTION) { + + if (str =="action") { + valid=true; + return ie.action.action; + } + else if (str == "pressed") { + valid=true; + ie.action.pressed; + } + } } break; case DICTIONARY: { diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 9375532f07..3e68c65d45 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -4038,8 +4038,16 @@ void RasterizerGLES2::render_target_set_size(RID p_render_target,int p_width,int glGenTextures(1, &rt->color); glBindTexture(GL_TEXTURE_2D, rt->color); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rt->width, rt->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + if (rt->texture_ptr->flags&VS::TEXTURE_FLAG_FILTER) { + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } else { + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt->color, 0); @@ -4588,6 +4596,9 @@ void RasterizerGLES2::_update_shader( Shader* p_shader) const { enablers.push_back("#define USE_TEXPIXEL_SIZE\n"); } + if (vertex_flags.uses_worldvec) { + enablers.push_back("#define USE_WORLD_VEC\n"); + } canvas_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, light_code, fragment_globals,uniform_names,enablers); //postprocess_shader.set_custom_shader_code(p_shader->custom_code_id,vertex_code, vertex_globals,fragment_code, fragment_globals,uniform_names); @@ -4954,12 +4965,26 @@ _FORCE_INLINE_ void RasterizerGLES2::_update_material_shader_params(Material *p_ Material::UniformData ud; bool keep=true; //keep material value - bool has_old = old_mparams.has(E->key()); + + Map<StringName,Material::UniformData>::Element *OLD=old_mparams.find(E->key()); + bool has_old = OLD; bool old_inuse=has_old && old_mparams[E->key()].inuse; - if (!has_old || !old_inuse) + ud.istexture=(E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP); + + if (!has_old || !old_inuse) { keep=false; - else if (old_mparams[E->key()].value.get_type()!=E->value().default_value.get_type()) { + } + else if (OLD->get().value.get_type()!=E->value().default_value.get_type()) { + + if (OLD->get().value.get_type()==Variant::INT && E->get().type==ShaderLanguage::TYPE_FLOAT) { + //handle common mistake using shaders (feeding ints instead of float) + OLD->get().value=float(OLD->get().value); + keep=true; + } else if (!ud.istexture && E->value().default_value.get_type()!=Variant::NIL) { + + keep=false; + } //type changed between old and new /* if (old_mparams[E->key()].value.get_type()==Variant::OBJECT) { if (E->value().default_value.get_type()!=Variant::_RID) //hackfor textures @@ -4968,11 +4993,9 @@ _FORCE_INLINE_ void RasterizerGLES2::_update_material_shader_params(Material *p_ keep=false;*/ //value is invalid because type differs and default is not null - if (E->value().default_value.get_type()!=Variant::NIL) - keep=false; + ; } - ud.istexture=(E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP); if (keep) { ud.value=old_mparams[E->key()].value; @@ -5096,8 +5119,10 @@ bool RasterizerGLES2::_setup_material(const Geometry *p_geometry,const Material int texcoord=0; for (Map<StringName,Material::UniformData>::Element *E=p_material->shader_params.front();E;E=E->next()) { + if (E->get().index<0) continue; +// print_line(String(E->key())+": "+E->get().value); if (E->get().istexture) { //clearly a texture.. RID rid = E->get().value; @@ -8362,24 +8387,39 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) { int idx=0; for(Map<StringName,ShaderLanguage::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) { - Map<StringName,Variant>::Element *F=shader_owner->shader_param.find(E->key()); - Variant &v=F?F->get():E->get().default_value; - if (v.get_type()==Variant::_RID || v.get_type()==Variant::OBJECT) { - int loc = canvas_shader.get_custom_uniform_location(idx); //should be automatic.. - - glActiveTexture(GL_TEXTURE0+tex_id); - RID tex = v; - Texture *t=texture_owner.get(tex); - if (!t) - glBindTexture(GL_TEXTURE_2D,white_tex); - else - glBindTexture(t->target,t->tex_id); - glUniform1i(loc,tex_id); - tex_id++; + if ((E->get().type==ShaderLanguage::TYPE_TEXTURE || E->get().type==ShaderLanguage::TYPE_CUBEMAP)) { + + RID rid; + if (F) { + rid=F->get(); + } + if (!rid.is_valid()) { + + Map<StringName,RID>::Element *DT=shader->default_textures.find(E->key()); + if (DT) { + rid=DT->get(); + } + } + + if (rid.is_valid()) { + + int loc = canvas_shader.get_custom_uniform_location(idx); //should be automatic.. + + glActiveTexture(GL_TEXTURE0+tex_id); + Texture *t=texture_owner.get(rid); + if (!t) + glBindTexture(GL_TEXTURE_2D,white_tex); + else + glBindTexture(t->target,t->tex_id); + + glUniform1i(loc,tex_id); + tex_id++; + } } else { + Variant &v=F?F->get():E->get().default_value; canvas_shader.set_custom_uniform(idx,v); } @@ -8403,7 +8443,7 @@ void RasterizerGLES2::canvas_render_items(CanvasItem *p_item_list) { #endif glCopyTexSubImage2D(GL_TEXTURE_2D,0,x,y,x,y,viewport.width,viewport.height); if (current_clip) { - print_line(" a clip "); + // print_line(" a clip "); } canvas_texscreen_used=true; diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index f1ddcf8009..d8841d407e 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -226,6 +226,9 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a if (vnode->name==vname_var2_interp) { flags->use_var2_interp=true; } + if (vnode->name==vname_world_vec) { + uses_worldvec=true; + } } @@ -307,13 +310,13 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a String mul_l=dump_node_code(onode->arguments[0],p_level,true); String mul_r=dump_node_code(onode->arguments[1],p_level); - code=mul_l+"=(vec4("+mul_l+",1.0,1.0)*("+mul_r+")).xy"; + code=mul_l+"=(vec4("+mul_l+",0.0,1.0)*("+mul_r+")).xy"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_MAT4 && onode->arguments[1]->get_datatype()==SL::TYPE_VEC2) { String mul_l=dump_node_code(onode->arguments[0],p_level,true); String mul_r=dump_node_code(onode->arguments[1],p_level); - code=mul_l+"=(("+mul_l+")*vec4("+mul_r+",1.0,1.0)).xy"; + code=mul_l+"=(("+mul_l+")*vec4("+mul_r+",0.0,1.0)).xy"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_VEC2 && onode->arguments[1]->get_datatype()==SL::TYPE_MAT3) { String mul_l=dump_node_code(onode->arguments[0],p_level,true); @@ -343,11 +346,11 @@ String ShaderCompilerGLES2::dump_node_code(SL::Node *p_node,int p_level,bool p_a break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_MAT4 && onode->arguments[1]->get_datatype()==SL::TYPE_VEC2) { - code="("+dump_node_code(onode->arguments[0],p_level)+"*vec4("+dump_node_code(onode->arguments[1],p_level)+",1.0,1.0)).xyz"; + code="("+dump_node_code(onode->arguments[0],p_level)+"*vec4("+dump_node_code(onode->arguments[1],p_level)+",0.0,1.0)).xy"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_VEC2 && onode->arguments[1]->get_datatype()==SL::TYPE_MAT4) { - code="(vec4("+dump_node_code(onode->arguments[0],p_level)+",1.0,1.0)*"+dump_node_code(onode->arguments[1],p_level)+").xyz"; + code="(vec4("+dump_node_code(onode->arguments[0],p_level)+",0.0,1.0)*"+dump_node_code(onode->arguments[1],p_level)+").xy"; break; } else if (onode->arguments[0]->get_datatype()==SL::TYPE_MAT3 && onode->arguments[1]->get_datatype()==SL::TYPE_VEC2) { @@ -599,6 +602,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT uses_normalmap=false; uses_normal=false; uses_texpixel_size=false; + uses_worldvec=false; vertex_code_writes_vertex=false; uniforms=r_uniforms; flags=&r_flags; @@ -634,6 +638,7 @@ Error ShaderCompilerGLES2::compile(const String& p_code, ShaderLanguage::ShaderT r_flags.uses_normalmap=uses_normalmap; r_flags.uses_normal=uses_normalmap; r_flags.uses_texpixel_size=uses_texpixel_size; + r_flags.uses_worldvec=uses_worldvec; r_code_line=code; r_globals_line=global_code; @@ -774,6 +779,7 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { mode_replace_table[3]["SRC_VERTEX"]="src_vtx"; mode_replace_table[3]["VERTEX"]="outvec.xy"; + mode_replace_table[3]["WORLD_VERTEX"]="outvec.xy"; mode_replace_table[3]["UV"]="uv_interp"; mode_replace_table[3]["COLOR"]="color_interp"; mode_replace_table[3]["VAR1"]="var1_interp"; @@ -830,5 +836,6 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { vname_normalmap="NORMALMAP"; vname_normal="NORMAL"; vname_texpixel_size="TEXTURE_PIXEL_SIZE"; + vname_world_vec="WORLD_VERTEX"; } diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h index a10fa6dfe0..87722602fd 100644 --- a/drivers/gles2/shader_compiler_gles2.h +++ b/drivers/gles2/shader_compiler_gles2.h @@ -53,6 +53,7 @@ private: bool uses_normalmap; bool uses_normal; bool uses_texpixel_size; + bool uses_worldvec; bool vertex_code_writes_vertex; Flags *flags; @@ -72,6 +73,7 @@ private: StringName vname_normalmap; StringName vname_normal; StringName vname_texpixel_size; + StringName vname_world_vec; Map<StringName,ShaderLanguage::Uniform> *uniforms; @@ -107,6 +109,7 @@ public: bool uses_time; bool uses_normal; bool uses_texpixel_size; + bool uses_worldvec; }; Error compile(const String& p_code, ShaderLanguage::ShaderType p_type, String& r_code_line, String& r_globals_line, Flags& r_flags, Map<StringName,ShaderLanguage::Uniform> *r_uniforms=NULL); diff --git a/drivers/gles2/shaders/canvas.glsl b/drivers/gles2/shaders/canvas.glsl index 464cb9e188..dc0af017d0 100644 --- a/drivers/gles2/shaders/canvas.glsl +++ b/drivers/gles2/shaders/canvas.glsl @@ -46,29 +46,32 @@ void main() { color_interp = color_attrib; uv_interp = uv_attrib; - highp vec4 outvec = vec4(vertex, 1.0); + highp vec4 outvec = vec4(vertex, 1.0); { - vec2 src_vtx=outvec.xy; + vec2 src_vtx=outvec.xy; VERTEX_SHADER_CODE } - outvec = extra_matrix * outvec; - outvec = modelview_matrix * outvec; +#if !defined(USE_WORLD_VEC) + outvec = extra_matrix * outvec; + outvec = modelview_matrix * outvec; +#endif + #ifdef USE_PIXEL_SNAP outvec.xy=floor(outvec.xy+0.5); #endif + gl_Position = projection_matrix * outvec; + #ifdef USE_LIGHTING - light_tex_pos.xy = light_matrix * outvec; + light_tex_pos.xy = light_matrix * gl_Position; light_tex_pos.zw=outvec.xy - light_matrix[4].xy; //likely wrong #endif - - gl_Position = projection_matrix * outvec; } [fragment] diff --git a/drivers/unix/ip_unix.cpp b/drivers/unix/ip_unix.cpp index 841160f941..ad0d4e00ea 100644 --- a/drivers/unix/ip_unix.cpp +++ b/drivers/unix/ip_unix.cpp @@ -50,11 +50,16 @@ #ifdef ANDROID_ENABLED #include "platform/android/ifaddrs_android.h" #else + #ifdef __FreeBSD__ + #include <sys/types.h> + #endif #include <ifaddrs.h> #endif #include <arpa/inet.h> #include <sys/socket.h> - + #ifdef __FreeBSD__ + #include <netinet/in.h> + #endif #endif IP_Address IP_Unix::_resolve_hostname(const String& p_hostname) { diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 2de975e5d1..d51a7c74e8 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -44,7 +44,9 @@ #include "stream_peer_tcp_posix.h" #include "packet_peer_udp_posix.h" - +#ifdef __FreeBSD__ +#include <sys/param.h> +#endif #include <stdarg.h> #include <sys/time.h> #include <sys/wait.h> @@ -305,7 +307,17 @@ Error OS_Unix::execute(const String& p_path, const List<String>& p_arguments,boo args.push_back((char*)cs[i].get_data());// shitty C cast args.push_back(0); +#ifdef __FreeBSD__ + if(p_path.find("/")) { + // exec name contains path so use it + execv(p_path.utf8().get_data(),&args[0]); + }else{ + // use program name and search through PATH to find it + execvp(getprogname(),&args[0]); + } +#else execv(p_path.utf8().get_data(),&args[0]); +#endif // still alive? something failed.. fprintf(stderr,"**ERROR** OS_Unix::execute - Could not create child process while executing: %s\n",p_path.utf8().get_data()); abort(); @@ -421,6 +433,12 @@ String OS_Unix::get_executable_path() const { return OS::get_executable_path(); } return b; +#elif defined(__FreeBSD__) + char resolved_path[MAXPATHLEN]; + + realpath(OS::get_executable_path().utf8().get_data(), resolved_path); + + return String(resolved_path); #else ERR_PRINT("Warning, don't know how to obtain executable path on this OS! Please override this function properly."); return OS::get_executable_path(); diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 4fa061886d..915e1a6098 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -593,10 +593,11 @@ LRESULT OS_Windows::WndProc(HWND hWnd,UINT uMsg, WPARAM wParam, LPARAM lParam) { ERR_BREAK(key_event_pos >= KEY_EVENT_BUFFER_SIZE); + // Make sure we don't include modifiers for the modifier key itself. KeyEvent ke; - ke.mod_state.shift=shift_mem; - ke.mod_state.alt=alt_mem; - ke.mod_state.control=control_mem; + ke.mod_state.shift= (wParam != VK_SHIFT) ? shift_mem : false; + ke.mod_state.alt= (! (wParam == VK_MENU && (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN))) ? alt_mem : false; + ke.mod_state.control= (wParam != VK_CONTROL) ? control_mem : false; ke.mod_state.meta=meta_mem; ke.uMsg=uMsg; diff --git a/platform/x11/detect.py b/platform/x11/detect.py index 5171bc972d..fb5cdb5089 100644 --- a/platform/x11/detect.py +++ b/platform/x11/detect.py @@ -70,24 +70,23 @@ def configure(env): else: env["bits"]="32" - env.Append(CPPPATH=['#platform/x11']) if (env["use_llvm"]=="yes"): - env["CC"]="clang" - env["CXX"]="clang++" - env["LD"]="clang++" - if (env["use_sanitizer"]=="yes"): - env.Append(CXXFLAGS=['-fsanitize=address','-fno-omit-frame-pointer']) - env.Append(LINKFLAGS=['-fsanitize=address']) - env.extra_suffix=".llvms" - else: - env.extra_suffix=".llvm" + if 'clang++' not in env['CXX']: + env["CC"]="clang" + env["CXX"]="clang++" + env["LD"]="clang++" + env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND']) + env.extra_suffix=".llvm" + if (env["colored"]=="yes"): if sys.stdout.isatty(): env.Append(CXXFLAGS=["-fcolor-diagnostics"]) - - + if (env["use_sanitizer"]=="yes"): + env.Append(CXXFLAGS=['-fsanitize=address','-fno-omit-frame-pointer']) + env.Append(LINKFLAGS=['-fsanitize=address']) + env.extra_suffix+="s" #if (env["tools"]=="no"): # #no tools suffix @@ -141,11 +140,6 @@ def configure(env): env.Append(LINKFLAGS=['-m64','-L/usr/lib/i686-linux-gnu']) - if (env["CXX"]=="clang++"): - env.Append(CPPFLAGS=['-DTYPED_METHOD_BIND']) - env["CC"]="clang" - env["LD"]="clang++" - import methods env.Append( BUILDERS = { 'GLSL120' : env.Builder(action = methods.build_legacygl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index ae857bbce9..6b892839bb 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -969,7 +969,7 @@ CanvasItem::CanvasItem() : xform_change(this) { block_transform_notify=false; // viewport=NULL; canvas_layer=NULL; - use_parent_shader; + use_parent_shader=false; global_invalid=true; C=NULL; diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index 27420f8002..95eafa0df4 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -604,7 +604,7 @@ Vector3 Camera::project_position(const Point2& p_point) const { Vector2 point; point.x = (p_point.x/viewport_size.x) * 2.0 - 1.0; - point.y = (p_point.y/viewport_size.y) * 2.0 - 1.0; + point.y = (1.0-(p_point.y/viewport_size.y)) * 2.0 - 1.0; point*=vp_size; Vector3 p(point.x,point.y,-near); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index b7b52a39dc..035dbb8cc4 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -2472,6 +2472,10 @@ void Tree::_notification(int p_what) { } } + if (p_what==NOTIFICATION_THEME_CHANGED) { + update_cache(); + } + } diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 998e0b2044..9d907391ec 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -499,6 +499,7 @@ void register_scene_types() { ObjectTypeDB::register_virtual_type<Shader>(); ObjectTypeDB::register_virtual_type<ShaderGraph>(); ObjectTypeDB::register_type<CanvasItemShader>(); + ObjectTypeDB::register_type<CanvasItemShaderGraph>(); #ifndef _3D_DISABLED ObjectTypeDB::register_type<Mesh>(); diff --git a/scene/resources/shader_graph.cpp b/scene/resources/shader_graph.cpp index 9703799a48..b0d9ceee0e 100644 --- a/scene/resources/shader_graph.cpp +++ b/scene/resources/shader_graph.cpp @@ -221,6 +221,13 @@ void ShaderGraph::_bind_methods() { ObjectTypeDB::bind_method(_MD("comment_node_set_text","shader_type","id","text"),&ShaderGraph::comment_node_set_text); ObjectTypeDB::bind_method(_MD("comment_node_get_text","shader_type","id"),&ShaderGraph::comment_node_get_text); + ObjectTypeDB::bind_method(_MD("color_ramp_node_set_ramp","shader_type","id","colors","offsets"),&ShaderGraph::color_ramp_node_set_ramp); + ObjectTypeDB::bind_method(_MD("color_ramp_node_get_colors","shader_type","id"),&ShaderGraph::color_ramp_node_get_colors); + ObjectTypeDB::bind_method(_MD("color_ramp_node_get_offsets","shader_type","id"),&ShaderGraph::color_ramp_node_get_offsets); + + ObjectTypeDB::bind_method(_MD("curve_map_node_set_points","shader_type","id","points"),&ShaderGraph::curve_map_node_set_points); + ObjectTypeDB::bind_method(_MD("curve_map_node_get_points","shader_type","id"),&ShaderGraph::curve_map_node_get_points); + ObjectTypeDB::bind_method(_MD("connect_node:Error","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::connect_node); ObjectTypeDB::bind_method(_MD("is_node_connected","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::is_node_connected); ObjectTypeDB::bind_method(_MD("disconnect_node","shader_type","src_id","src_slot","dst_id","dst_slot"),&ShaderGraph::disconnect_node); @@ -263,12 +270,15 @@ void ShaderGraph::_bind_methods() { BIND_CONSTANT( NODE_XFORM_TO_VEC ); // 3 vec input ); 1 xform output BIND_CONSTANT( NODE_SCALAR_INTERP ); // scalar interpolation (with optional curve) BIND_CONSTANT( NODE_VEC_INTERP ); // vec3 interpolation (with optional curve) + BIND_CONSTANT( NODE_COLOR_RAMP ); + BIND_CONSTANT( NODE_CURVE_MAP ); BIND_CONSTANT( NODE_SCALAR_INPUT ); // scalar uniform (assignable in material) BIND_CONSTANT( NODE_VEC_INPUT ); // vec3 uniform (assignable in material) BIND_CONSTANT( NODE_RGB_INPUT ); // color uniform (assignable in material) BIND_CONSTANT( NODE_XFORM_INPUT ); // mat4 uniform (assignable in material) BIND_CONSTANT( NODE_TEXTURE_INPUT ); // texture input (assignable in material) BIND_CONSTANT( NODE_CUBEMAP_INPUT ); // cubemap input (assignable in material) + BIND_CONSTANT( NODE_DEFAULT_TEXTURE ); BIND_CONSTANT( NODE_OUTPUT ); // output (shader type dependent) BIND_CONSTANT( NODE_COMMENT ); // comment BIND_CONSTANT( NODE_TYPE_MAX ); @@ -519,12 +529,15 @@ void ShaderGraph::node_add(ShaderType p_type, NodeType p_node_type,int p_id) { case NODE_XFORM_TO_VEC: {} break; // 3 scalar input: {} break; 1 vec3 output case NODE_SCALAR_INTERP: {} break; // scalar interpolation (with optional curve) case NODE_VEC_INTERP: {} break; // vec3 interpolation (with optional curve) + case NODE_COLOR_RAMP: { node.param1=DVector<Color>(); node.param2=DVector<real_t>();} break; // vec3 interpolation (with optional curve) + case NODE_CURVE_MAP: { node.param1=DVector<Vector2>();} break; // vec3 interpolation (with optional curve) case NODE_SCALAR_INPUT: {node.param1=_find_unique_name("Scalar"); node.param2=0;} break; // scalar uniform (assignable in material) case NODE_VEC_INPUT: {node.param1=_find_unique_name("Vec3");node.param2=Vector3();} break; // vec3 uniform (assignable in material) case NODE_RGB_INPUT: {node.param1=_find_unique_name("Color");node.param2=Color();} break; // color uniform (assignable in material) case NODE_XFORM_INPUT: {node.param1=_find_unique_name("XForm"); node.param2=Transform();} break; // mat4 uniform (assignable in material) case NODE_TEXTURE_INPUT: {node.param1=_find_unique_name("Tex"); } break; // texture input (assignable in material) - case NODE_CUBEMAP_INPUT: {node.param1=_find_unique_name("Cube"); } break; // cubemap input (assignable in material) + case NODE_CUBEMAP_INPUT: {node.param1=_find_unique_name("Cube"); } break; // cubemap input (assignable in material) + case NODE_DEFAULT_TEXTURE: {}; break; case NODE_OUTPUT: {} break; // output (shader type dependent) case NODE_COMMENT: {} break; // comment case NODE_TYPE_MAX: {}; @@ -964,6 +977,59 @@ ShaderGraph::VecFunc ShaderGraph::vec_func_node_get_function(ShaderType p_type, return VecFunc(func); } +void ShaderGraph::color_ramp_node_set_ramp(ShaderType p_type,int p_id,const DVector<Color>& p_colors, const DVector<real_t>& p_offsets){ + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + ERR_FAIL_COND(p_colors.size()!=p_offsets.size()); + Node& n = shader[p_type].node_map[p_id]; + n.param1=p_colors; + n.param2=p_offsets; + _request_update(); + +} + +DVector<Color> ShaderGraph::color_ramp_node_get_colors(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,DVector<Color>()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),DVector<Color>()); + const Node& n = shader[p_type].node_map[p_id]; + return n.param1; + + +} + +DVector<real_t> ShaderGraph::color_ramp_node_get_offsets(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,DVector<real_t>()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),DVector<real_t>()); + const Node& n = shader[p_type].node_map[p_id]; + return n.param2; + +} + + +void ShaderGraph::curve_map_node_set_points(ShaderType p_type,int p_id,const DVector<Vector2>& p_points) { + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + Node& n = shader[p_type].node_map[p_id]; + n.param1=p_points; + _request_update(); + +} + +DVector<Vector2> ShaderGraph::curve_map_node_get_points(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,DVector<Vector2>()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),DVector<Vector2>()); + const Node& n = shader[p_type].node_map[p_id]; + return n.param1; + +} + + + void ShaderGraph::input_node_set_name(ShaderType p_type,int p_id,const String& p_name){ ERR_FAIL_INDEX(p_type,3); @@ -1223,7 +1289,7 @@ const ShaderGraph::InOutParamInfo ShaderGraph::inout_param_info[]={ {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Binormal","BINORMAL","",SLOT_TYPE_VEC,SLOT_IN}, {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"UV","vec3(UV,0);","",SLOT_TYPE_VEC,SLOT_IN}, {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"UV2","UV2","",SLOT_TYPE_VEC,SLOT_IN}, - {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"UVScreen","SCREEN_UV","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"UVScreen","vec3(SCREEN_UV,0)","",SLOT_TYPE_VEC,SLOT_IN}, {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"PointCoord","POINT_COORD","",SLOT_TYPE_VEC,SLOT_IN}, {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Color","COLOR.rgb","",SLOT_TYPE_VEC,SLOT_IN}, {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Alpha","COLOR.a","",SLOT_TYPE_SCALAR,SLOT_IN}, @@ -1254,6 +1320,43 @@ const ShaderGraph::InOutParamInfo ShaderGraph::inout_param_info[]={ {MODE_MATERIAL,SHADER_TYPE_LIGHT,"ShadeParam","SHADE_PARAM","",SLOT_TYPE_SCALAR,SLOT_IN}, //light out {MODE_MATERIAL,SHADER_TYPE_LIGHT,"Light","LIGHT","",SLOT_TYPE_VEC,SLOT_OUT}, + //canvas item vertex in + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Vertex","vec3(SRC_VERTEX,0)","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"UV","SRC_UV","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Color","SRC_COLOR.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Alpha","SRC_COLOR.a","",SLOT_TYPE_SCALAR,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"WorldMatrix","WORLD_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"ExtraMatrix","EXTRA_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"ProjectionMatrix","PROJECTION_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN}, + //canvas item vertex out + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Vertex","VERTEX",".xy",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"UV","UV",".xy",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Color","COLOR.rgb","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Alpha","COLOR.a","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Var1","VAR1.rgb","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"Var2","VAR2.rgb","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_VERTEX,"PointSize","POINT_SIZE","",SLOT_TYPE_SCALAR,SLOT_OUT}, + //canvas item fragment in + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Color","SRC_COLOR.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Alpha","SRC_COLOR.a","",SLOT_TYPE_SCALAR,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"UV","vec3(UV,0)","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"UVScreen","vec3(SCREEN_UV,0)","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"TexPixelSize","vec3(TEXTURE_PIXEL_SIZE,0)","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Var1","VAR1.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Var2","VAR2.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"PointCoord","POINT_COORD","",SLOT_TYPE_VEC,SLOT_IN}, + //canvas item fragment out + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Color","COLOR.rgb","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Alpha","COLOR.a","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_CANVAS_ITEM,SHADER_TYPE_FRAGMENT,"Normal","NORMAL","",SLOT_TYPE_VEC,SLOT_OUT}, + //canvas item light in + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Color","COLOR.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Normal","NORMAL","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightDist","LIGHT_DISTANCE","",SLOT_TYPE_SCALAR,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"LightDir","vec3(LIGHT_DIR,0)","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"PointCoord","POINT_COORD","",SLOT_TYPE_VEC,SLOT_IN}, + //canvas item light out + {MODE_CANVAS_ITEM,SHADER_TYPE_LIGHT,"Light","LIGHT","",SLOT_TYPE_VEC,SLOT_OUT}, //end {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,NULL,NULL,NULL,SLOT_TYPE_SCALAR,SLOT_OUT}, @@ -1299,12 +1402,15 @@ const ShaderGraph::NodeSlotInfo ShaderGraph::node_slot_info[]= { {NODE_SCALAR_TO_VEC,{SLOT_TYPE_SCALAR,SLOT_TYPE_SCALAR,SLOT_TYPE_SCALAR},{SLOT_TYPE_VEC,SLOT_MAX}}, // 3 scalar input,{SLOT_MAX},{SLOT_MAX}}, 1 vec3 output {NODE_SCALAR_INTERP,{SLOT_TYPE_SCALAR,SLOT_TYPE_SCALAR,SLOT_TYPE_SCALAR},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // scalar interpolation (with optional curve) {NODE_VEC_INTERP,{SLOT_TYPE_VEC,SLOT_TYPE_VEC,SLOT_TYPE_SCALAR},{SLOT_TYPE_VEC,SLOT_MAX}}, // vec3 interpolation (with optional curve) + {NODE_COLOR_RAMP,{SLOT_TYPE_SCALAR,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX}}, // vec3 interpolation (with optional curve) + {NODE_CURVE_MAP,{SLOT_TYPE_SCALAR,SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // vec3 interpolation (with optional curve) {NODE_SCALAR_INPUT,{SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // scalar uniform (assignable in material) {NODE_VEC_INPUT,{SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // vec3 uniform (assignable in material) {NODE_RGB_INPUT,{SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // color uniform (assignable in material) {NODE_XFORM_INPUT,{SLOT_MAX},{SLOT_TYPE_XFORM,SLOT_MAX}}, // mat4 uniform (assignable in material) {NODE_TEXTURE_INPUT,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX}}, // texture input (assignable in material) {NODE_CUBEMAP_INPUT,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX}}, // cubemap input (assignable in material) + {NODE_DEFAULT_TEXTURE,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX}}, // cubemap input (assignable in material) {NODE_COMMENT,{SLOT_MAX},{SLOT_MAX}}, // comment {NODE_TYPE_MAX,{SLOT_MAX},{SLOT_MAX}} }; @@ -1663,6 +1769,11 @@ void ShaderGraph::_update_shader() { } else if (i==SHADER_TYPE_FRAGMENT && get_mode()==MODE_MATERIAL) { if (name==("IN_NORMAL")) code[i]="vec3 IN_NORMAL=NORMAL;\n"+code[i]; + } else if (i==SHADER_TYPE_VERTEX && get_mode()==MODE_CANVAS_ITEM) { + if (name==("SRC_COLOR")) + code[i]="vec3 SRC_COLOR=COLOR.rgb;\n"+code[i]; + if (name==("SRC_UV")) + code[i]="vec3 SRC_UV=vec3(UV,0);\n"+code[i]; } } @@ -1679,6 +1790,10 @@ void ShaderGraph::_update_shader() { all_ok=false; } + /*print_line("VERTEX: \n"+code[0]); + print_line("FRAGMENT: \n"+code[1]); + print_line("LIGHT: \n"+code[2]);*/ + if (all_ok) { set_code(code[0],code[1],code[2]); } @@ -1688,6 +1803,134 @@ void ShaderGraph::_update_shader() { emit_signal(SceneStringNames::get_singleton()->updated); } +void ShaderGraph::_plot_curve(const Vector2& p_a,const Vector2& p_b,const Vector2& p_c,const Vector2& p_d,uint8_t* p_heights,bool *p_useds) { + + float geometry[4][4]; + float tmp1[4][4]; + float tmp2[4][4]; + float deltas[4][4]; + double x, dx, dx2, dx3; + double y, dy, dy2, dy3; + double d, d2, d3; + int lastx, lasty; + int newx, newy; + int ntimes; + int i,j; + + int xmax=255; + int ymax=255; + + /* construct the geometry matrix from the segment */ + for (i = 0; i < 4; i++) { + geometry[i][2] = 0; + geometry[i][3] = 0; + } + + geometry[0][0] = (p_a[0] * xmax); + geometry[1][0] = (p_b[0] * xmax); + geometry[2][0] = (p_c[0] * xmax); + geometry[3][0] = (p_d[0] * xmax); + + geometry[0][1] = (p_a[1] * ymax); + geometry[1][1] = (p_b[1] * ymax); + geometry[2][1] = (p_c[1] * ymax); + geometry[3][1] = (p_d[1] * ymax); + + /* subdivide the curve ntimes (1000) times */ + ntimes = 4 * xmax; + /* ntimes can be adjusted to give a finer or coarser curve */ + d = 1.0 / ntimes; + d2 = d * d; + d3 = d * d * d; + + /* construct a temporary matrix for determining the forward differencing deltas */ + tmp2[0][0] = 0; tmp2[0][1] = 0; tmp2[0][2] = 0; tmp2[0][3] = 1; + tmp2[1][0] = d3; tmp2[1][1] = d2; tmp2[1][2] = d; tmp2[1][3] = 0; + tmp2[2][0] = 6*d3; tmp2[2][1] = 2*d2; tmp2[2][2] = 0; tmp2[2][3] = 0; + tmp2[3][0] = 6*d3; tmp2[3][1] = 0; tmp2[3][2] = 0; tmp2[3][3] = 0; + + /* compose the basis and geometry matrices */ + + static const float CR_basis[4][4] = + { + { -0.5, 1.5, -1.5, 0.5 }, + { 1.0, -2.5, 2.0, -0.5 }, + { -0.5, 0.0, 0.5, 0.0 }, + { 0.0, 1.0, 0.0, 0.0 }, + }; + + for (i = 0; i < 4; i++) + { + for (j = 0; j < 4; j++) + { + tmp1[i][j] = (CR_basis[i][0] * geometry[0][j] + + CR_basis[i][1] * geometry[1][j] + + CR_basis[i][2] * geometry[2][j] + + CR_basis[i][3] * geometry[3][j]); + } + } + /* compose the above results to get the deltas matrix */ + + for (i = 0; i < 4; i++) + { + for (j = 0; j < 4; j++) + { + deltas[i][j] = (tmp2[i][0] * tmp1[0][j] + + tmp2[i][1] * tmp1[1][j] + + tmp2[i][2] * tmp1[2][j] + + tmp2[i][3] * tmp1[3][j]); + } + } + + + /* extract the x deltas */ + x = deltas[0][0]; + dx = deltas[1][0]; + dx2 = deltas[2][0]; + dx3 = deltas[3][0]; + + /* extract the y deltas */ + y = deltas[0][1]; + dy = deltas[1][1]; + dy2 = deltas[2][1]; + dy3 = deltas[3][1]; + + + lastx = CLAMP (x, 0, xmax); + lasty = CLAMP (y, 0, ymax); + + p_heights[lastx] = lasty; + p_useds[lastx] = true; + + /* loop over the curve */ + for (i = 0; i < ntimes; i++) + { + /* increment the x values */ + x += dx; + dx += dx2; + dx2 += dx3; + + /* increment the y values */ + y += dy; + dy += dy2; + dy2 += dy3; + + newx = CLAMP ((Math::round (x)), 0, xmax); + newy = CLAMP ((Math::round (y)), 0, ymax); + + /* if this point is different than the last one...then draw it */ + if ((lastx != newx) || (lasty != newy)) + { + p_useds[newx]=true; + p_heights[newx]=newy; + } + + lastx = newx; + lasty = newy; + } +} + + void ShaderGraph::_add_node_code(ShaderType p_type,Node *p_node,const Vector<String>& p_inputs,String& code) { @@ -1730,7 +1973,7 @@ void ShaderGraph::_add_node_code(ShaderType p_type,Node *p_node,const Vector<Str code+=OUTNAME(p_node->id,0)+"=TIME;\n"; }break; case NODE_SCREEN_TEX: { - code+=OUTNAME(p_node->id,0)+"=texscreen("+p_inputs[0]+");\n"; + code+=OUTNAME(p_node->id,0)+"=texscreen("+p_inputs[0]+".xy);\n"; }break; case NODE_SCALAR_OP: { int op = p_node->param1; @@ -1988,6 +2231,129 @@ void ShaderGraph::_add_node_code(ShaderType p_type,Node *p_node,const Vector<Str code += OUTNAME(p_node->id,0)+"=mix("+p_inputs[0]+","+p_inputs[1]+","+p_inputs[2]+");\n"; }break; + case NODE_COLOR_RAMP: { + + static const int color_ramp_len=512; + DVector<uint8_t> cramp; + cramp.resize(color_ramp_len*4); + { + + DVector<Color> colors=p_node->param1; + DVector<real_t> offsets=p_node->param2; + int cc =colors.size(); + DVector<uint8_t>::Write crw = cramp.write(); + DVector<Color>::Read cr = colors.read(); + DVector<real_t>::Read ofr = offsets.read(); + + int at=0; + Color color_at(0,0,0,1); + for(int i=0;i<=cc;i++) { + + int pos; + Color to; + if (i==cc) { + if (at==color_ramp_len) + break; + pos=color_ramp_len; + to=Color(1,1,1,1); + } else { + to=cr[i]; + pos= MIN(ofr[i]*color_ramp_len,color_ramp_len); + } + for(int j=at;j<pos;j++) { + float t = (j-at)/float(pos-at); + Color c = color_at.linear_interpolate(to,t); + crw[j*4+0]=Math::fast_ftoi( CLAMP(c.r*255.0,0,255) ); + crw[j*4+1]=Math::fast_ftoi( CLAMP(c.g*255.0,0,255) ); + crw[j*4+2]=Math::fast_ftoi( CLAMP(c.b*255.0,0,255) ); + crw[j*4+3]=Math::fast_ftoi( CLAMP(c.a*255.0,0,255) ); + } + + at=pos; + color_at=to; + } + } + + Image gradient(color_ramp_len,1,0,Image::FORMAT_RGBA,cramp); + Ref<ImageTexture> it = memnew( ImageTexture ); + it->create_from_image(gradient,Texture::FLAG_FILTER|Texture::FLAG_MIPMAPS); + + String crampname= "cramp_"+itos(p_node->id); + set_default_texture_param(crampname,it); + + code +="uniform texture "+crampname+";\n"; + code +="vec4 "+crampname+"_r=tex("+crampname+",vec2("+p_inputs[0]+",0));\n"; + code += OUTNAME(p_node->id,0)+"="+crampname+"_r.rgb;\n"; + code += OUTNAME(p_node->id,1)+"="+crampname+"_r.a;\n"; + + }break; + case NODE_CURVE_MAP: { + static const int curve_map_len=256; + bool mapped[256]; + zeromem(mapped,sizeof(mapped)); + DVector<uint8_t> cmap; + cmap.resize(curve_map_len); + { + + DVector<Point2> points=p_node->param1; + int pc =points.size(); + DVector<uint8_t>::Write cmw = cmap.write(); + DVector<Point2>::Read pr = points.read(); + + Vector2 prev=Vector2(0,0); + Vector2 prev2=Vector2(0,0); + + for(int i=-1;i<pc;i++) { + + Vector2 next; + Vector2 next2; + if (i+1>=pc) { + next=Vector2(1,1); + } else { + next=Vector2(pr[i+1].x,pr[i+1].y); + } + + if (i+2>=pc) { + next2=Vector2(1,1); + } else { + next2=Vector2(pr[i+2].x,pr[i+2].y); + } + + /*if (i==-1 && prev.offset==next.offset) { + prev=next; + continue; + }*/ + + _plot_curve(prev2,prev,next,next2,cmw.ptr(),mapped); + + prev2=prev; + prev=next; + } + + uint8_t pp=0; + for(int i=0;i<curve_map_len;i++) { + + if (!mapped[i]) { + cmw[i]=pp; + } else { + pp=cmw[i]; + } + } + } + + + + Image gradient(curve_map_len,1,0,Image::FORMAT_GRAYSCALE,cmap); + Ref<ImageTexture> it = memnew( ImageTexture ); + it->create_from_image(gradient,Texture::FLAG_FILTER|Texture::FLAG_MIPMAPS); + + String cmapname= "cmap_"+itos(p_node->id); + set_default_texture_param(cmapname,it); + + code +="uniform texture "+cmapname+";\n"; + code += OUTNAME(p_node->id,0)+"=tex("+cmapname+",vec2("+p_inputs[0]+",0)).r;\n"; + + }break; case NODE_SCALAR_INPUT: { String name = p_node->param1; float dv=p_node->param2; @@ -2043,6 +2409,22 @@ void ShaderGraph::_add_node_code(ShaderType p_type,Node *p_node,const Vector<Str code += OUTNAME(p_node->id,0)+"="+rname+".rgb;\n"; code += OUTNAME(p_node->id,1)+"="+rname+".a;\n"; }break; + case NODE_DEFAULT_TEXTURE: { + + if (get_mode()==MODE_CANVAS_ITEM && p_type==SHADER_TYPE_FRAGMENT) { + + String rname="rt_default_tex"+itos(p_node->id); + code +="vec4 "+rname+"=tex(TEXTURE,"+p_inputs[0]+".xy);\n"; + code += OUTNAME(p_node->id,0)+"="+rname+".rgb;\n"; + code += OUTNAME(p_node->id,1)+"="+rname+".a;\n"; + + } else { + //not supported + code += OUTNAME(p_node->id,0)+"=vec3(0,0,0);\n"; + code += OUTNAME(p_node->id,1)+"=1.0;\n"; + + } + } break; case NODE_OUTPUT: { diff --git a/scene/resources/shader_graph.h b/scene/resources/shader_graph.h index 55d09b4c38..5c34bedadd 100644 --- a/scene/resources/shader_graph.h +++ b/scene/resources/shader_graph.h @@ -66,12 +66,15 @@ public: NODE_VEC_TO_XFORM, // 3 vec input, 1 xform output NODE_SCALAR_INTERP, // scalar interpolation (with optional curve) NODE_VEC_INTERP, // vec3 interpolation (with optional curve) - NODE_SCALAR_INPUT, // scalar uniform (assignable in material) + NODE_COLOR_RAMP, //take scalar, output vec3 + NODE_CURVE_MAP, //take scalar, otput scalar + NODE_SCALAR_INPUT, // scalar uniform (assignable in material) NODE_VEC_INPUT, // vec3 uniform (assignable in material) NODE_RGB_INPUT, // color uniform (assignable in material) NODE_XFORM_INPUT, // mat4 uniform (assignable in material) NODE_TEXTURE_INPUT, // texture input (assignable in material) NODE_CUBEMAP_INPUT, // cubemap input (assignable in material) + NODE_DEFAULT_TEXTURE, NODE_OUTPUT, // output (shader type dependent) NODE_COMMENT, // comment NODE_TYPE_MAX @@ -172,6 +175,7 @@ private: void _update_shader(); void _request_update(); + void _plot_curve(const Vector2& p_a,const Vector2& p_b,const Vector2& p_c,const Vector2& p_d,uint8_t* p_heights,bool *p_useds); void _add_node_code(ShaderType p_type,Node *p_node,const Vector<String>& p_inputs,String& code); Array _get_node_list(ShaderType p_type) const; @@ -313,6 +317,13 @@ public: void vec_func_node_set_function(ShaderType p_which,int p_id,VecFunc p_func); VecFunc vec_func_node_get_function(ShaderType p_which,int p_id) const; + void color_ramp_node_set_ramp(ShaderType p_which,int p_id,const DVector<Color>& p_colors, const DVector<real_t>& p_offsets); + DVector<Color> color_ramp_node_get_colors(ShaderType p_which,int p_id) const; + DVector<real_t> color_ramp_node_get_offsets(ShaderType p_which,int p_id) const; + + void curve_map_node_set_points(ShaderType p_which, int p_id, const DVector<Vector2>& p_points); + DVector<Vector2> curve_map_node_get_points(ShaderType p_which,int p_id) const; + void input_node_set_name(ShaderType p_which,int p_id,const String& p_name); String input_node_get_name(ShaderType p_which,int p_id); @@ -395,7 +406,6 @@ VARIANT_ENUM_CAST( ShaderGraph::GraphError ); class MaterialShaderGraph : public ShaderGraph { OBJ_TYPE( MaterialShaderGraph, ShaderGraph ); - RES_BASE_EXTENSION("sgp"); public: @@ -405,4 +415,17 @@ public: } }; +class CanvasItemShaderGraph : public ShaderGraph { + + OBJ_TYPE( CanvasItemShaderGraph, ShaderGraph ); + +public: + + + CanvasItemShaderGraph() : ShaderGraph(MODE_CANVAS_ITEM) { + + } +}; + + #endif // SHADER_GRAPH_H diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp index 336eec73b5..ed63870a12 100644 --- a/servers/physics_2d/shape_2d_sw.cpp +++ b/servers/physics_2d/shape_2d_sw.cpp @@ -136,6 +136,7 @@ real_t LineShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale return 0; } + void LineShape2DSW::set_data(const Variant& p_data) { ERR_FAIL_COND(p_data.get_type()!=Variant::ARRAY); diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h index 51ece9fc7e..931491efd5 100644 --- a/servers/physics_2d/shape_2d_sw.h +++ b/servers/physics_2d/shape_2d_sw.h @@ -85,7 +85,6 @@ public: virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const=0; virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const=0; - virtual void set_data(const Variant& p_data)=0; virtual Variant get_data() const=0; diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 9a76a009a9..dfa0172e82 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -1112,6 +1112,7 @@ const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_vertex_builtins_defs[]={ { "SRC_VERTEX", TYPE_VEC2}, { "VERTEX", TYPE_VEC2}, + { "WORLD_VERTEX", TYPE_VEC2}, { "UV", TYPE_VEC2}, { "COLOR", TYPE_VEC4}, { "VAR1", TYPE_VEC4}, diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp index a3aa573e35..fc32702a12 100644 --- a/servers/visual/visual_server_raster.cpp +++ b/servers/visual/visual_server_raster.cpp @@ -3819,6 +3819,91 @@ void VisualServerRaster::canvas_item_raise(RID p_item) { } +/***** CANVAS LIGHT *******/ + +RID VisualServerRaster::canvas_light_create() { + + return RID(); +} + +void VisualServerRaster::canvas_light_attach_to_canvas(RID p_light,RID p_canvas){ + + +} +void VisualServerRaster::canvas_light_set_enabled(RID p_light, bool p_enabled){ + + +} +void VisualServerRaster::canvas_light_set_transform(RID p_light, const Matrix32& p_transform){ + + +} +void VisualServerRaster::canvas_light_set_texture(RID p_light, RID p_texture){ + + +} +void VisualServerRaster::canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset){ + + +} +void VisualServerRaster::canvas_light_set_color(RID p_light, const Color& p_color){ + + +} +void VisualServerRaster::canvas_light_set_height(RID p_light, float p_height){ + + +} +void VisualServerRaster::canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z){ + + +} +void VisualServerRaster::canvas_light_set_item_mask(RID p_light, int p_mask){ + + +} + +void VisualServerRaster::canvas_light_set_blend_mode(RID p_light, CanvasLightBlendMode p_blend_mode){ + + +} +void VisualServerRaster::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled){ + + +} +void VisualServerRaster::canvas_light_set_shadow_buffer_size(RID p_light, int p_size){ + + +} +void VisualServerRaster::canvas_light_set_shadow_filter(RID p_light, int p_size){ + + +} + +/****** CANVAS LIGHT OCCLUDER ******/ + +RID VisualServerRaster::canvas_light_occluder_create() { + + return RID(); +} + +void VisualServerRaster::canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas) { + + +} + +void VisualServerRaster::canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled){ + + +} + +void VisualServerRaster::canvas_light_occluder_set_shape(RID p_occluder,const DVector<Vector2>& p_shape){ + + +} + + + /******** CANVAS *********/ diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h index 6c4e15827a..57032ab441 100644 --- a/servers/visual/visual_server_raster.h +++ b/servers/visual/visual_server_raster.h @@ -1122,9 +1122,43 @@ public: virtual void canvas_item_set_use_parent_shader(RID p_item, bool p_enable); + virtual void canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value); virtual Variant canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const; + virtual RID canvas_light_create(); + virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas); + virtual void canvas_light_set_enabled(RID p_light, bool p_enabled); + virtual void canvas_light_set_transform(RID p_light, const Matrix32& p_transform); + virtual void canvas_light_set_texture(RID p_light, RID p_texture); + virtual void canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset); + virtual void canvas_light_set_color(RID p_light, const Color& p_color); + virtual void canvas_light_set_height(RID p_light, float p_height); + virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z); + virtual void canvas_light_set_item_mask(RID p_light, int p_mask); + + enum CanvasightBlendMode { + CANVAS_LIGHT_BLEND_ADD, + CANVAS_LIGHT_BLEND_SUB, + CANVAS_LIGHT_BLEND_MULTIPLY, + CANVAS_LIGHT_BLEND_DODGE, + CANVAS_LIGHT_BLEND_BURN, + CANVAS_LIGHT_BLEND_LIGHTEN, + CANVAS_LIGHT_BLEND_DARKEN, + CANVAS_LIGHT_BLEND_OVERLAY, + CANVAS_LIGHT_BLEND_SCREEN, + }; + virtual void canvas_light_set_blend_mode(RID p_light, CanvasLightBlendMode p_blend_mode); + virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled); + virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size); + virtual void canvas_light_set_shadow_filter(RID p_light, int p_size); + + + virtual RID canvas_light_occluder_create(); + virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas); + virtual void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled); + virtual void canvas_light_occluder_set_shape(RID p_occluder,const DVector<Vector2>& p_shape); + virtual void canvas_item_clear(RID p_item); virtual void canvas_item_raise(RID p_item); diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h index b59fdbc66a..9574dff018 100644 --- a/servers/visual/visual_server_wrap_mt.h +++ b/servers/visual/visual_server_wrap_mt.h @@ -1146,6 +1146,29 @@ public: FUNC1(canvas_item_clear,RID); FUNC1(canvas_item_raise,RID); + /* CANVAS LIGHT */ + FUNC0R(RID,canvas_light_create); + FUNC2(canvas_light_attach_to_canvas,RID,RID); + FUNC2(canvas_light_set_enabled,RID,bool); + FUNC2(canvas_light_set_transform,RID,const Matrix32&); + FUNC2(canvas_light_set_texture,RID,RID); + FUNC2(canvas_light_set_texture_offset,RID,const Vector2&); + FUNC2(canvas_light_set_color,RID,const Color&); + FUNC2(canvas_light_set_height,RID,float); + FUNC3(canvas_light_set_z_range,RID,int,int); + FUNC2(canvas_light_set_item_mask,RID,int); + + FUNC2(canvas_light_set_blend_mode,RID,CanvasLightBlendMode); + FUNC2(canvas_light_set_shadow_enabled,RID,bool); + FUNC2(canvas_light_set_shadow_buffer_size,RID,int); + FUNC2(canvas_light_set_shadow_filter,RID,int); + + /* CANVAS OCCLUDER */ + + FUNC0R(RID,canvas_light_occluder_create); + FUNC2(canvas_light_occluder_attach_to_canvas,RID,RID); + FUNC2(canvas_light_occluder_set_enabled,RID,bool); + FUNC2(canvas_light_occluder_set_shape,RID,const DVector<Vector2>&); /* CURSOR */ FUNC2(cursor_set_rotation,float , int ); // radians diff --git a/servers/visual_server.h b/servers/visual_server.h index 5721e7acf0..49ae8ce4e6 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -999,6 +999,39 @@ public: virtual void canvas_item_set_shader_param(RID p_canvas_item, const StringName& p_param, const Variant& p_value)=0; virtual Variant canvas_item_get_shader_param(RID p_canvas_item, const StringName& p_param) const=0; + virtual RID canvas_light_create()=0; + virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas)=0; + virtual void canvas_light_set_enabled(RID p_light, bool p_enabled)=0; + virtual void canvas_light_set_transform(RID p_light, const Matrix32& p_transform)=0; + virtual void canvas_light_set_texture(RID p_light, RID p_texture)=0; + virtual void canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset)=0; + virtual void canvas_light_set_color(RID p_light, const Color& p_color)=0; + virtual void canvas_light_set_height(RID p_light, float p_height)=0; + virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z)=0; + virtual void canvas_light_set_item_mask(RID p_light, int p_mask)=0; + + enum CanvasLightBlendMode { + CANVAS_LIGHT_BLEND_ADD, + CANVAS_LIGHT_BLEND_SUB, + CANVAS_LIGHT_BLEND_MULTIPLY, + CANVAS_LIGHT_BLEND_DODGE, + CANVAS_LIGHT_BLEND_BURN, + CANVAS_LIGHT_BLEND_LIGHTEN, + CANVAS_LIGHT_BLEND_DARKEN, + CANVAS_LIGHT_BLEND_OVERLAY, + CANVAS_LIGHT_BLEND_SCREEN, + }; + virtual void canvas_light_set_blend_mode(RID p_light, CanvasLightBlendMode p_blend_mode)=0; + virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled)=0; + virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size)=0; + virtual void canvas_light_set_shadow_filter(RID p_light, int p_size)=0; + + + virtual RID canvas_light_occluder_create()=0; + virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas)=0; + virtual void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled)=0; + virtual void canvas_light_occluder_set_shape(RID p_occluder,const DVector<Vector2>& p_shape)=0; + /* CURSOR */ virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0)=0; // radians virtual void cursor_set_texture(RID p_texture, const Point2 &p_center_offset = Point2(0, 0), int p_cursor=0)=0; diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index 005bb0958f..a48545d152 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -1967,6 +1967,25 @@ void EditorNode::_menu_option_confirm(int p_option,bool p_confirmed) { log->add_message("REDO: "+action); } break; + + case EDIT_REVERT: { + + Node *scene = get_edited_scene(); + + if (!scene) + break; + + if (unsaved_cache && !p_confirmed) { + confirmation->get_ok()->set_text("Revert"); + confirmation->set_text("This action cannot be undone. Revert anyway?"); + confirmation->popup_centered(Size2(300,70)); + break; + } + + Error err = load_scene(scene->get_filename()); + + } break; + #if 0 case NODE_EXTERNAL_INSTANCE: { @@ -3469,6 +3488,8 @@ EditorNode::EditorNode() { p->add_separator(); p->add_item("Project Settings",RUN_SETTINGS); p->add_separator(); + p->add_item("Revert Scene",EDIT_REVERT); + p->add_separator(); p->add_item("Quit to Project List",RUN_PROJECT_MANAGER,KEY_MASK_SHIFT+KEY_MASK_CMD+KEY_Q); p->add_item("Quit",FILE_QUIT,KEY_MASK_CMD+KEY_Q); @@ -4035,7 +4056,8 @@ EditorNode::EditorNode() { add_editor_plugin( memnew( ScriptEditorPlugin(this) ) ); add_editor_plugin( memnew( EditorHelpPlugin(this) ) ); add_editor_plugin( memnew( AnimationPlayerEditorPlugin(this) ) ); - add_editor_plugin( memnew( ShaderGraphEditorPlugin(this) ) ); + add_editor_plugin( memnew( ShaderGraphEditorPlugin(this,true) ) ); + add_editor_plugin( memnew( ShaderGraphEditorPlugin(this,false) ) ); add_editor_plugin( memnew( ShaderEditorPlugin(this,true) ) ); add_editor_plugin( memnew( ShaderEditorPlugin(this,false) ) ); add_editor_plugin( memnew( CameraEditorPlugin(this) ) ); diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index 7560c2b149..54b9dc2b0b 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -127,6 +127,7 @@ class EditorNode : public Node { FILE_EXTERNAL_OPEN_SCENE, EDIT_UNDO, EDIT_REDO, + EDIT_REVERT, RESOURCE_NEW, RESOURCE_LOAD, RESOURCE_SAVE, diff --git a/tools/editor/icons/icon_graph_color_ramp.png b/tools/editor/icons/icon_graph_color_ramp.png Binary files differnew file mode 100644 index 0000000000..9031b5ec53 --- /dev/null +++ b/tools/editor/icons/icon_graph_color_ramp.png diff --git a/tools/editor/icons/icon_graph_curve_map.png b/tools/editor/icons/icon_graph_curve_map.png Binary files differnew file mode 100644 index 0000000000..de5c32f09e --- /dev/null +++ b/tools/editor/icons/icon_graph_curve_map.png diff --git a/tools/editor/icons/icon_graph_default_texture.png b/tools/editor/icons/icon_graph_default_texture.png Binary files differnew file mode 100644 index 0000000000..da77ec9364 --- /dev/null +++ b/tools/editor/icons/icon_graph_default_texture.png diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp index d90597ddfb..4b7d1cf0e0 100644 --- a/tools/editor/plugins/script_editor_plugin.cpp +++ b/tools/editor/plugins/script_editor_plugin.cpp @@ -1607,7 +1607,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { edit_menu->get_popup()->add_item("Clone Down",EDIT_CLONE_DOWN,KEY_MASK_CMD|KEY_B); edit_menu->get_popup()->add_separator(); #ifdef OSX_ENABLED - edit_menu->get_popup()->add_item("Complete Symbol",EDIT_COMPLETE,KEY_MASK_META|KEY_SPACE); + edit_menu->get_popup()->add_item("Complete Symbol",EDIT_COMPLETE,KEY_MASK_CTRL|KEY_SPACE); #else edit_menu->get_popup()->add_item("Complete Symbol",EDIT_COMPLETE,KEY_MASK_CMD|KEY_SPACE); #endif diff --git a/tools/editor/plugins/shader_editor_plugin.cpp b/tools/editor/plugins/shader_editor_plugin.cpp index 81b5cd8f78..2fcd4e8cd1 100644 --- a/tools/editor/plugins/shader_editor_plugin.cpp +++ b/tools/editor/plugins/shader_editor_plugin.cpp @@ -396,7 +396,7 @@ void ShaderEditor::edit(const Ref<Shader>& p_shader) { light_editor->set_edited_shader(shader,ShaderLanguage::SHADER_CANVAS_ITEM_LIGHT); } - vertex_editor->set_edited_shader(shader,ShaderLanguage::SHADER_MATERIAL_VERTEX); + //vertex_editor->set_edited_shader(shader,ShaderLanguage::SHADER_MATERIAL_VERTEX); // see if already has it diff --git a/tools/editor/plugins/shader_graph_editor_plugin.cpp b/tools/editor/plugins/shader_graph_editor_plugin.cpp index 0a206c4a45..508e8b4cba 100644 --- a/tools/editor/plugins/shader_graph_editor_plugin.cpp +++ b/tools/editor/plugins/shader_graph_editor_plugin.cpp @@ -32,6 +32,642 @@ #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" #include "spatial_editor_plugin.h" +#include "os/keyboard.h" +#include "canvas_item_editor_plugin.h" + +void GraphColorRampEdit::_input_event(const InputEvent& p_event) { + + if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode==KEY_DELETE && grabbed!=-1) { + + points.remove(grabbed); + grabbed=-1; + update(); + emit_signal("ramp_changed"); + accept_event(); + } + + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) { + + update(); + int x = p_event.mouse_button.x; + int total_w = get_size().width-get_size().height-3; + if (x>total_w+3) { + + if (grabbed==-1) + return; + Size2 ms = Size2(350, picker->get_combined_minimum_size().height+10); + picker->set_color(points[grabbed].color); + popup->set_pos(get_global_pos()-Size2(0,ms.height)); + popup->set_size(ms); + popup->popup(); + return; + } + + + float ofs = CLAMP(x/float(total_w),0,1); + + grabbed=-1; + grabbing=true; + int pos=-1; + for(int i=0;i<points.size();i++) { + + if (ABS(x-points[i].offset*total_w)<4) { + grabbed=i; + } + if (points[i].offset<ofs) + pos=i; + } + + grabbed_at=ofs; + //grab or select + if (grabbed!=-1) { + return; + } + //insert + + + Point p; + p.offset=ofs; + + Point prev; + Point next; + + if (pos==-1) { + + prev.color=Color(0,0,0); + prev.offset=0; + if (points.size()) { + next=points[0]; + } else { + next.color=Color(1,1,1); + next.offset=1.0; + } + } else { + + if (pos==points.size()-1) { + next.color=Color(1,1,1); + next.offset=1.0; + } else { + next=points[pos+1]; + } + prev=points[pos]; + + } + + p.color=prev.color.linear_interpolate(next.color,(p.offset-prev.offset)/(next.offset-prev.offset)); + + points.push_back(p); + points.sort(); + for(int i=0;i<points.size();i++) { + if (points[i].offset==ofs) { + grabbed=i; + break; + } + } + + emit_signal("ramp_changed"); + + } + + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && !p_event.mouse_button.pressed) { + + if (grabbing) { + grabbing=false; + emit_signal("ramp_changed"); + } + update(); + } + + if (p_event.type==InputEvent::MOUSE_MOTION && grabbing) { + + int total_w = get_size().width-get_size().height-3; + + int x = p_event.mouse_motion.x; + float newofs = CLAMP(x/float(total_w),0,1); + + bool valid=true; + for(int i=0;i<points.size();i++) { + + if (points[i].offset==newofs && i!=grabbed) { + valid=false; + } + } + + if (!valid) + return; + + points[grabbed].offset=newofs; + + points.sort(); + for(int i=0;i<points.size();i++) { + if (points[i].offset==newofs) { + grabbed=i; + break; + } + } + + emit_signal("ramp_changed"); + + update(); + } +} + +void GraphColorRampEdit::_notification(int p_what){ + + if (p_what==NOTIFICATION_ENTER_TREE) { + picker->connect("color_changed",this,"_color_changed"); + } + if (p_what==NOTIFICATION_DRAW) { + + + Point prev; + prev.offset=0; + prev.color=Color(0,0,0); + int w = get_size().x; + int h = get_size().y; + + int total_w = get_size().width-get_size().height-3; + + for(int i=-1;i<points.size();i++) { + + Point next; + if (i+1==points.size()) { + next.color=Color(1,1,1); + next.offset=1; + } else { + next=points[i+1]; + } + + if (prev.offset==next.offset) { + prev=next; + continue; + } + + Vector<Vector2> points; + Vector<Color> colors; + points.push_back(Vector2(prev.offset*total_w,h)); + points.push_back(Vector2(prev.offset*total_w,0)); + points.push_back(Vector2(next.offset*total_w,0)); + points.push_back(Vector2(next.offset*total_w,h)); + colors.push_back(prev.color); + colors.push_back(prev.color); + colors.push_back(next.color); + colors.push_back(next.color); + draw_primitive(points,colors,Vector<Point2>()); + prev=next; + } + + for(int i=0;i<points.size();i++) { + + Color col=i==grabbed?Color(1,0.0,0.0,0.9):Color(1,1,1,0.8); + + draw_line(Vector2(points[i].offset*total_w,0),Vector2(points[i].offset*total_w,h-1),Color(0,0,0,0.7)); + draw_line(Vector2(points[i].offset*total_w-1,h/2),Vector2(points[i].offset*total_w-1,h-1),col); + draw_line(Vector2(points[i].offset*total_w+1,h/2),Vector2(points[i].offset*total_w+1,h-1),col); + draw_line(Vector2(points[i].offset*total_w-1,h/2),Vector2(points[i].offset*total_w+1,h/2),col); + draw_line(Vector2(points[i].offset*total_w-1,h-1),Vector2(points[i].offset*total_w+1,h-1),col); + + } + + if (grabbed!=-1) { + + draw_rect(Rect2(total_w+3,0,h,h),points[grabbed].color); + } + + if (has_focus()) { + + draw_line(Vector2(-1,-1),Vector2(total_w+1,-1),Color(1,1,1,0.6)); + draw_line(Vector2(total_w+1,-1),Vector2(total_w+1,h+1),Color(1,1,1,0.6)); + draw_line(Vector2(total_w+1,h+1),Vector2(-1,h+1),Color(1,1,1,0.6)); + draw_line(Vector2(-1,-1),Vector2(-1,h+1),Color(1,1,1,0.6)); + } + + } +} + +Size2 GraphColorRampEdit::get_minimum_size() const { + + return Vector2(0,16); +} + + +void GraphColorRampEdit::_color_changed(const Color& p_color) { + + if (grabbed==-1) + return; + points[grabbed].color=p_color; + update(); + emit_signal("ramp_changed"); + +} + +void GraphColorRampEdit::set_ramp(const Vector<float>& p_offsets,const Vector<Color>& p_colors) { + + ERR_FAIL_COND(p_offsets.size()!=p_colors.size()); + points.clear(); + for(int i=0;i<p_offsets.size();i++) { + Point p; + p.offset=p_offsets[i]; + p.color=p_colors[i]; + points.push_back(p); + } + + points.sort(); + update(); +} + +Vector<float> GraphColorRampEdit::get_offsets() const{ + Vector<float> ret; + for(int i=0;i<points.size();i++) + ret.push_back(points[i].offset); + return ret; +} +Vector<Color> GraphColorRampEdit::get_colors() const{ + + Vector<Color> ret; + for(int i=0;i<points.size();i++) + ret.push_back(points[i].color); + return ret; +} + + +void GraphColorRampEdit::_bind_methods(){ + + ObjectTypeDB::bind_method(_MD("_input_event"),&GraphColorRampEdit::_input_event); + ObjectTypeDB::bind_method(_MD("_color_changed"),&GraphColorRampEdit::_color_changed); + ADD_SIGNAL(MethodInfo("ramp_changed")); +} + +GraphColorRampEdit::GraphColorRampEdit(){ + + grabbed=-1; + grabbing=false; + set_focus_mode(FOCUS_ALL); + + popup = memnew( PopupPanel ); + picker = memnew( ColorPicker ); + popup->add_child(picker); + popup->set_child_rect(picker); + add_child(popup); + +} +//////////// + +void GraphCurveMapEdit::_input_event(const InputEvent& p_event) { + + if (p_event.type==InputEvent::KEY && p_event.key.pressed && p_event.key.scancode==KEY_DELETE && grabbed!=-1) { + + points.remove(grabbed); + grabbed=-1; + update(); + emit_signal("curve_changed"); + accept_event(); + } + + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && p_event.mouse_button.pressed) { + + update(); + Point2 p = Vector2(p_event.mouse_button.x,p_event.mouse_button.y)/get_size(); + p.y=1.0-p.y; + grabbed=-1; + grabbing=true; + + for(int i=0;i<points.size();i++) { + + Vector2 ps = p*get_size(); + Vector2 pt = Vector2(points[i].offset,points[i].height)*get_size(); + if (ps.distance_to(pt)<4) { + grabbed=i; + } + + } + + + //grab or select + if (grabbed!=-1) { + return; + } + //insert + + + Point np; + np.offset=p.x; + np.height=p.y; + + points.push_back(np); + points.sort(); + for(int i=0;i<points.size();i++) { + if (points[i].offset==p.x && points[i].height==p.y) { + grabbed=i; + break; + } + } + + emit_signal("curve_changed"); + + } + + if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==1 && !p_event.mouse_button.pressed) { + + if (grabbing) { + grabbing=false; + emit_signal("curve_changed"); + } + update(); + } + + if (p_event.type==InputEvent::MOUSE_MOTION && grabbing) { + + Point2 p = Vector2(p_event.mouse_button.x,p_event.mouse_button.y)/get_size(); + p.y=1.0-p.y; + + p.x = CLAMP(p.x,0.0,1.0); + p.y = CLAMP(p.y,0.0,1.0); + + bool valid=true; + + for(int i=0;i<points.size();i++) { + + if (points[i].offset==p.x && points[i].height==p.y && i!=grabbed) { + valid=false; + } + } + + if (!valid) + return; + + points[grabbed].offset=p.x; + points[grabbed].height=p.y; + + points.sort(); + for(int i=0;i<points.size();i++) { + if (points[i].offset==p.x && points[i].height==p.y) { + grabbed=i; + break; + } + } + + emit_signal("curve_changed"); + + update(); + } +} + +void GraphCurveMapEdit::_plot_curve(const Vector2& p_a,const Vector2& p_b,const Vector2& p_c,const Vector2& p_d) { + + float geometry[4][4]; + float tmp1[4][4]; + float tmp2[4][4]; + float deltas[4][4]; + double x, dx, dx2, dx3; + double y, dy, dy2, dy3; + double d, d2, d3; + int lastx, lasty; + int newx, newy; + int ntimes; + int i,j; + + int xmax=get_size().x; + int ymax=get_size().y; + + /* construct the geometry matrix from the segment */ + for (i = 0; i < 4; i++) { + geometry[i][2] = 0; + geometry[i][3] = 0; + } + + geometry[0][0] = (p_a[0] * xmax); + geometry[1][0] = (p_b[0] * xmax); + geometry[2][0] = (p_c[0] * xmax); + geometry[3][0] = (p_d[0] * xmax); + + geometry[0][1] = (p_a[1] * ymax); + geometry[1][1] = (p_b[1] * ymax); + geometry[2][1] = (p_c[1] * ymax); + geometry[3][1] = (p_d[1] * ymax); + + /* subdivide the curve ntimes (1000) times */ + ntimes = 4 * xmax; + /* ntimes can be adjusted to give a finer or coarser curve */ + d = 1.0 / ntimes; + d2 = d * d; + d3 = d * d * d; + + /* construct a temporary matrix for determining the forward differencing deltas */ + tmp2[0][0] = 0; tmp2[0][1] = 0; tmp2[0][2] = 0; tmp2[0][3] = 1; + tmp2[1][0] = d3; tmp2[1][1] = d2; tmp2[1][2] = d; tmp2[1][3] = 0; + tmp2[2][0] = 6*d3; tmp2[2][1] = 2*d2; tmp2[2][2] = 0; tmp2[2][3] = 0; + tmp2[3][0] = 6*d3; tmp2[3][1] = 0; tmp2[3][2] = 0; tmp2[3][3] = 0; + + /* compose the basis and geometry matrices */ + + static const float CR_basis[4][4] = + { + { -0.5, 1.5, -1.5, 0.5 }, + { 1.0, -2.5, 2.0, -0.5 }, + { -0.5, 0.0, 0.5, 0.0 }, + { 0.0, 1.0, 0.0, 0.0 }, + }; + + for (i = 0; i < 4; i++) + { + for (j = 0; j < 4; j++) + { + tmp1[i][j] = (CR_basis[i][0] * geometry[0][j] + + CR_basis[i][1] * geometry[1][j] + + CR_basis[i][2] * geometry[2][j] + + CR_basis[i][3] * geometry[3][j]); + } + } + /* compose the above results to get the deltas matrix */ + + for (i = 0; i < 4; i++) + { + for (j = 0; j < 4; j++) + { + deltas[i][j] = (tmp2[i][0] * tmp1[0][j] + + tmp2[i][1] * tmp1[1][j] + + tmp2[i][2] * tmp1[2][j] + + tmp2[i][3] * tmp1[3][j]); + } + } + + + /* extract the x deltas */ + x = deltas[0][0]; + dx = deltas[1][0]; + dx2 = deltas[2][0]; + dx3 = deltas[3][0]; + + /* extract the y deltas */ + y = deltas[0][1]; + dy = deltas[1][1]; + dy2 = deltas[2][1]; + dy3 = deltas[3][1]; + + + lastx = CLAMP (x, 0, xmax); + lasty = CLAMP (y, 0, ymax); + +/* if (fix255) + { + cd->curve[cd->outline][lastx] = lasty; + } + else + { + cd->curve_ptr[cd->outline][lastx] = lasty; + if(gb_debug) printf("bender_plot_curve xmax:%d ymax:%d\n", (int)xmax, (int)ymax); + } +*/ + /* loop over the curve */ + for (i = 0; i < ntimes; i++) + { + /* increment the x values */ + x += dx; + dx += dx2; + dx2 += dx3; + + /* increment the y values */ + y += dy; + dy += dy2; + dy2 += dy3; + + newx = CLAMP ((Math::round (x)), 0, xmax); + newy = CLAMP ((Math::round (y)), 0, ymax); + + /* if this point is different than the last one...then draw it */ + if ((lastx != newx) || (lasty != newy)) + { +#if 0 + /* + if(fix255) + { + /* use fixed array size (for the curve graph) */ + cd->curve[cd->outline][newx] = newy; + } + else + { + /* use dynamic allocated curve_ptr (for the real curve) */ + cd->curve_ptr[cd->outline][newx] = newy; + + if(gb_debug) printf("outline: %d cX: %d cY: %d\n", (int)cd->outline, (int)newx, (int)newy); + } +#endif + draw_line(Vector2(lastx,ymax-lasty),Vector2(newx,ymax-newy),Color(0.8,0.8,0.8,0.8),2.0); + } + + lastx = newx; + lasty = newy; + } +} + + +void GraphCurveMapEdit::_notification(int p_what){ + + if (p_what==NOTIFICATION_DRAW) { + + draw_style_box(get_stylebox("bg","Tree"),Rect2(Point2(),get_size())); + + int w = get_size().x; + int h = get_size().y; + + Vector2 prev=Vector2(0,0); + Vector2 prev2=Vector2(0,0); + + for(int i=-1;i<points.size();i++) { + + Vector2 next; + Vector2 next2; + if (i+1>=points.size()) { + next=Vector2(1,1); + } else { + next=Vector2(points[i+1].offset,points[i+1].height); + } + + if (i+2>=points.size()) { + next2=Vector2(1,1); + } else { + next2=Vector2(points[i+2].offset,points[i+2].height); + } + + /*if (i==-1 && prev.offset==next.offset) { + prev=next; + continue; + }*/ + + _plot_curve(prev2,prev,next,next2); + + prev2=prev; + prev=next; + } + + for(int i=0;i<points.size();i++) { + + Color col=i==grabbed?Color(1,0.0,0.0,0.9):Color(1,1,1,0.8); + + + draw_rect(Rect2( Vector2(points[i].offset,1.0-points[i].height)*get_size()-Vector2(2,2),Vector2(5,5)),col); + } + +/* if (grabbed!=-1) { + + draw_rect(Rect2(total_w+3,0,h,h),points[grabbed].color); + } +*/ + if (has_focus()) { + + draw_line(Vector2(-1,-1),Vector2(w+1,-1),Color(1,1,1,0.6)); + draw_line(Vector2(w+1,-1),Vector2(w+1,h+1),Color(1,1,1,0.6)); + draw_line(Vector2(w+1,h+1),Vector2(-1,h+1),Color(1,1,1,0.6)); + draw_line(Vector2(-1,-1),Vector2(-1,h+1),Color(1,1,1,0.6)); + } + + } +} + +Size2 GraphCurveMapEdit::get_minimum_size() const { + + return Vector2(64,64); +} + + + +void GraphCurveMapEdit::set_points(const Vector<Vector2>& p_points) { + + + points.clear(); + for(int i=0;i<p_points.size();i++) { + Point p; + p.offset=p_points[i].x; + p.height=p_points[i].y; + points.push_back(p); + } + + points.sort(); + update(); +} + +Vector<Vector2> GraphCurveMapEdit::get_points() const { + Vector<Vector2> ret; + for(int i=0;i<points.size();i++) + ret.push_back(Vector2(points[i].offset,points[i].height)); + return ret; +} + +void GraphCurveMapEdit::_bind_methods(){ + + ObjectTypeDB::bind_method(_MD("_input_event"),&GraphCurveMapEdit::_input_event); + ADD_SIGNAL(MethodInfo("curve_changed")); +} + +GraphCurveMapEdit::GraphCurveMapEdit(){ + + grabbed=-1; + grabbing=false; + set_focus_mode(FOCUS_ALL); + +} + ////cbacks /// @@ -306,6 +942,84 @@ void ShaderGraphView::_comment_edited(int p_id,Node* p_button) { } +void ShaderGraphView::_color_ramp_changed(int p_id,Node* p_ramp) { + + GraphColorRampEdit *cr=p_ramp->cast_to<GraphColorRampEdit>(); + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + + + Vector<float> offsets=cr->get_offsets(); + Vector<Color> colors=cr->get_colors(); + + DVector<float> new_offsets; + DVector<Color> new_colors; + { + new_offsets.resize(offsets.size()); + new_colors.resize(colors.size()); + DVector<float>::Write ow=new_offsets.write(); + DVector<Color>::Write cw=new_colors.write(); + for(int i=0;i<new_offsets.size();i++) { + ow[i]=offsets[i]; + cw[i]=colors[i]; + } + + } + + + DVector<float> old_offsets=graph->color_ramp_node_get_offsets(type,p_id); + DVector<Color> old_colors=graph->color_ramp_node_get_colors(type,p_id); + + if (old_offsets.size()!=new_offsets.size()) + ur->create_action("Add/Remove to Color Ramp"); + else + ur->create_action("Modify Color Ramp",true); + + ur->add_do_method(graph.ptr(),"color_ramp_node_set_ramp",type,p_id,new_colors,new_offsets); + ur->add_undo_method(graph.ptr(),"color_ramp_node_set_ramp",type,p_id,old_colors,old_offsets); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} + +void ShaderGraphView::_curve_changed(int p_id,Node* p_curve) { + + GraphCurveMapEdit *cr=p_curve->cast_to<GraphCurveMapEdit>(); + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + + + Vector<Point2> points=cr->get_points(); + + DVector<Vector2> new_points; + { + new_points.resize(points.size()); + DVector<Vector2>::Write ow=new_points.write(); + for(int i=0;i<new_points.size();i++) { + ow[i]=points[i]; + } + + } + + + DVector<Vector2> old_points=graph->curve_map_node_get_points(type,p_id); + + if (old_points.size()!=new_points.size()) + ur->create_action("Add/Remove to Curve Map"); + else + ur->create_action("Modify Curve Map",true); + + ur->add_do_method(graph.ptr(),"curve_map_node_set_points",type,p_id,new_points); + ur->add_undo_method(graph.ptr(),"curve_map_node_set_points",type,p_id,old_points); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} + void ShaderGraphView::_input_name_changed(const String& p_name, int p_id, Node *p_line_edit) { @@ -1026,6 +1740,96 @@ void ShaderGraphView::_create_node(int p_id) { gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); } break; // vec3 interpolation (with optional curve) + case ShaderGraph::NODE_COLOR_RAMP: { + + gn->set_title("ColorRamp"); + GraphColorRampEdit * ramp = memnew( GraphColorRampEdit ); + + DVector<real_t> offsets = graph->color_ramp_node_get_offsets(type,p_id); + DVector<Color> colors = graph->color_ramp_node_get_colors(type,p_id); + + int oc = offsets.size(); + + if (oc) { + DVector<real_t>::Read rofs = offsets.read(); + DVector<Color>::Read rcol = colors.read(); + + Vector<float> ofsv; + Vector<Color> colorv; + for(int i=0;i<oc;i++) { + ofsv.push_back(rofs[i]); + colorv.push_back(rcol[i]); + } + + ramp->set_ramp(ofsv,colorv); + + } + + ramp->connect("ramp_changed",this,"_color_ramp_changed",varray(p_id,ramp)); + ramp->set_custom_minimum_size(Size2(128,1)); + gn->add_child(ramp); + + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("c"))); + hbc->add_spacer(); + Label *l=memnew(Label("rgb")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + l=memnew(Label("alpha")); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child( l); + + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,false,ShaderGraph::SLOT_MAX,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + + } break; // scalar interpolation (with optional curve) + case ShaderGraph::NODE_CURVE_MAP: { + + gn->set_title("CurveMap"); + GraphCurveMapEdit * map = memnew( GraphCurveMapEdit ); + + DVector<Vector2> points = graph->curve_map_node_get_points(type,p_id); + + int oc = points.size(); + + if (oc) { + DVector<Vector2>::Read rofs = points.read(); + + + Vector<Vector2> ofsv; + for(int i=0;i<oc;i++) { + ofsv.push_back(rofs[i]); + } + + map->set_points(ofsv); + + } + map->connect("curve_changed",this,"_curve_changed",varray(p_id,map)); + + //map->connect("map_changed",this,"_curve_map_changed",varray(p_id,map)); + map->set_custom_minimum_size(Size2(128,64)); + gn->add_child(map); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("c"))); + hbc->add_spacer(); + Label *l=memnew(Label("cmap")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + + } break; // scalar interpolation (with optional curve) + case ShaderGraph::NODE_SCALAR_INPUT: { gn->set_title("ScalarUniform"); @@ -1173,6 +1977,28 @@ void ShaderGraphView::_create_node(int p_id) { gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); } break; // cubemap input (assignable in material) + case ShaderGraph::NODE_DEFAULT_TEXTURE: { + + gn->set_title("CanvasItemTex"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("UV"))); + hbc->add_spacer(); + Label *l=memnew(Label("RGB")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child(l); + gn->add_child(hbc); + l = memnew( Label ); + l->set_text("Alpha"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + + } break; // screen texture sampler (takes UV) (only usable in fragment case Shader) + case ShaderGraph::NODE_OUTPUT: { gn->set_title("Output"); @@ -1360,6 +2186,8 @@ void ShaderGraphView::_bind_methods() { ObjectTypeDB::bind_method("_variant_edited",&ShaderGraphView::_variant_edited); ObjectTypeDB::bind_method("_cube_edited",&ShaderGraphView::_cube_edited); ObjectTypeDB::bind_method("_comment_edited",&ShaderGraphView::_comment_edited); + ObjectTypeDB::bind_method("_color_ramp_changed",&ShaderGraphView::_color_ramp_changed); + ObjectTypeDB::bind_method("_curve_changed",&ShaderGraphView::_curve_changed); ObjectTypeDB::bind_method("_sg_updated",&ShaderGraphView::_sg_updated); } @@ -1406,6 +2234,9 @@ void ShaderGraphEditor::_notification(int p_what) { if (i==ShaderGraph::NODE_OUTPUT) continue; + if (!_2d && i==ShaderGraph::NODE_DEFAULT_TEXTURE) + continue; + String nn = node_names[i]; String ic = nn.get_slice(":",0); String v = nn.get_slice(":",1); @@ -1455,18 +2286,22 @@ const char* ShaderGraphEditor::node_names[ShaderGraph::NODE_TYPE_MAX]={ "GraphVecsToXform:Vectors -> XForm:", // 3 vec input", 1 xform output "GraphScalarInterp:Scalar Interpolate", // scalar interpolation (with optional curve) "GraphVecInterp:Vector Interpolate:", // vec3 interpolation (with optional curve) - "GraphScalarUniform:Scalar Uniform", // scalar uniform (assignable in material) + "GraphColorRamp:Color Ramp", // vec3 interpolation (with optional curve) + "GraphCurveMap:Curve Remap:", // vec3 interpolation (with optional curve) + "GraphScalarUniform:Scalar Uniform", // scalar uniform (assignable in material) "GraphVectorUniform:Vector Uniform", // vec3 uniform (assignable in material) "GraphRgbUniform:RGB Uniform", // color uniform (assignable in material) "GraphXformUniform:XForm Uniform", // mat4 uniform (assignable in material) "GraphTextureUniform:Texture Uniform", // texture input (assignable in material) "GraphCubeUniform:CubeMap Uniform:", // cubemap input (assignable in material) - "Output", // output (shader type dependent) + "GraphDefaultTexture:CanvasItem Texture:", // cubemap input (assignable in material) + "Output", // output (shader type dependent) "GraphComment:Comment", // comment }; -ShaderGraphEditor::ShaderGraphEditor() { +ShaderGraphEditor::ShaderGraphEditor(bool p_2d) { + _2d=p_2d; HBoxContainer *hbc = memnew( HBoxContainer ); menu = memnew( MenuButton ); @@ -1508,7 +2343,13 @@ void ShaderGraphEditorPlugin::edit(Object *p_object) { bool ShaderGraphEditorPlugin::handles(Object *p_object) const { - return p_object->is_type("ShaderGraph"); + ShaderGraph *shader=p_object->cast_to<ShaderGraph>(); + if (!shader) + return false; + if (_2d) + return shader->get_mode()==Shader::MODE_CANVAS_ITEM; + else + return shader->get_mode()==Shader::MODE_MATERIAL; } void ShaderGraphEditorPlugin::make_visible(bool p_visible) { @@ -1522,12 +2363,16 @@ void ShaderGraphEditorPlugin::make_visible(bool p_visible) { } -ShaderGraphEditorPlugin::ShaderGraphEditorPlugin(EditorNode *p_node) { +ShaderGraphEditorPlugin::ShaderGraphEditorPlugin(EditorNode *p_node, bool p_2d) { + _2d=p_2d; editor=p_node; - shader_editor = memnew( ShaderGraphEditor ); + shader_editor = memnew( ShaderGraphEditor(p_2d) ); shader_editor->hide(); - SpatialEditor::get_singleton()->get_shader_split()->add_child(shader_editor); + if (p_2d) + CanvasItemEditor::get_singleton()->get_bottom_split()->add_child(shader_editor); + else + SpatialEditor::get_singleton()->get_shader_split()->add_child(shader_editor); // editor->get_viewport()->add_child(shader_editor); diff --git a/tools/editor/plugins/shader_graph_editor_plugin.h b/tools/editor/plugins/shader_graph_editor_plugin.h index bd983c59be..1726302e90 100644 --- a/tools/editor/plugins/shader_graph_editor_plugin.h +++ b/tools/editor/plugins/shader_graph_editor_plugin.h @@ -45,6 +45,77 @@ */ +class GraphColorRampEdit : public Control { + + OBJ_TYPE(GraphColorRampEdit,Control); + + + struct Point { + + float offset; + Color color; + bool operator<(const Point& p_ponit) const { + return offset<p_ponit.offset; + } + }; + + PopupPanel *popup; + ColorPicker *picker; + + + bool grabbing; + int grabbed; + float grabbed_at; + Vector<Point> points; + + void _color_changed(const Color& p_color); + +protected: + void _input_event(const InputEvent& p_event); + void _notification(int p_what); + static void _bind_methods(); +public: + + void set_ramp(const Vector<float>& p_offsets,const Vector<Color>& p_colors); + Vector<float> get_offsets() const; + Vector<Color> get_colors() const; + virtual Size2 get_minimum_size() const; + GraphColorRampEdit(); +}; + + +class GraphCurveMapEdit : public Control { + + OBJ_TYPE(GraphCurveMapEdit,Control); + + + struct Point { + + float offset; + float height; + bool operator<(const Point& p_ponit) const { + return offset<p_ponit.offset; + } + }; + + + bool grabbing; + int grabbed; + Vector<Point> points; + + void _plot_curve(const Vector2& p_a,const Vector2& p_b,const Vector2& p_c,const Vector2& p_d); +protected: + void _input_event(const InputEvent& p_event); + void _notification(int p_what); + static void _bind_methods(); +public: + + void set_points(const Vector<Vector2>& p_points); + Vector<Vector2> get_points() const; + virtual Size2 get_minimum_size() const; + GraphCurveMapEdit(); +}; + class ShaderGraphView : public Node { OBJ_TYPE(ShaderGraphView,Node); @@ -95,7 +166,8 @@ class ShaderGraphView : public Node { void _cube_edited(int p_id,Node* p_button); void _variant_edited(); void _comment_edited(int p_id,Node* p_button); - + void _color_ramp_changed(int p_id,Node* p_ramp); + void _curve_changed(int p_id,Node* p_curve); void _sg_updated(); Map<int,GraphNode*> node_map; protected: @@ -119,6 +191,7 @@ class ShaderGraphEditor : public VBoxContainer { ShaderGraphView *graph_edits[ShaderGraph::SHADER_TYPE_MAX]; static const char* node_names[ShaderGraph::NODE_TYPE_MAX]; + bool _2d; void _add_node(int p_type); protected: void _notification(int p_what); @@ -126,13 +199,14 @@ protected: public: void edit(Ref<ShaderGraph> p_shader); - ShaderGraphEditor(); + ShaderGraphEditor(bool p_2d); }; class ShaderGraphEditorPlugin : public EditorPlugin { OBJ_TYPE( ShaderGraphEditorPlugin, EditorPlugin ); + bool _2d; ShaderGraphEditor *shader_editor; EditorNode *editor; @@ -144,7 +218,7 @@ public: virtual bool handles(Object *p_node) const; virtual void make_visible(bool p_visible); - ShaderGraphEditorPlugin(EditorNode *p_node); + ShaderGraphEditorPlugin(EditorNode *p_node,bool p_2d); ~ShaderGraphEditorPlugin(); }; diff --git a/tools/editor/scene_tree_dock.cpp b/tools/editor/scene_tree_dock.cpp index cff3913579..6f33d4b3d1 100644 --- a/tools/editor/scene_tree_dock.cpp +++ b/tools/editor/scene_tree_dock.cpp @@ -79,10 +79,22 @@ Node* SceneTreeDock::instance(const String& p_file) { //accept->get_cancel()->hide(); accept->get_ok()->set_text("Ugh"); accept->set_text(String("Error loading scene from ")+p_file); - accept->popup_centered(Size2(300,70));; + accept->popup_centered(Size2(300,70)); return NULL; } + // If the scene hasn't been saved yet a cyclical dependency cannot exist. + if (edited_scene->get_filename()!="") { + + if (_cyclical_dependency_exists(edited_scene->get_filename(), instanced_scene)) { + + accept->get_ok()->set_text("Ok"); + accept->set_text(String("Cannot instance the scene '")+p_file+String("' because the current scene exists within one of its' nodes.")); + accept->popup_centered(Size2(300,90)); + return NULL; + } + } + instanced_scene->generate_instance_state(); instanced_scene->set_filename( Globals::get_singleton()->localize_path(p_file) ); @@ -100,6 +112,25 @@ Node* SceneTreeDock::instance(const String& p_file) { } +bool SceneTreeDock::_cyclical_dependency_exists(const String& p_target_scene_path, Node* p_desired_node) { + int childCount = p_desired_node->get_child_count(); + + if (p_desired_node->get_filename()==p_target_scene_path) { + return true; + } + + for (int i=0;i<childCount;i++) { + Node* child=p_desired_node->get_child(i); + + if(_cyclical_dependency_exists(p_target_scene_path,child)) { + return true; + } + } + + return false; +} + + static String _get_name_num_separator() { switch(EditorSettings::get_singleton()->get("scenetree_editor/duplicate_node_name_num_separator").operator int()) { case 0: return ""; diff --git a/tools/editor/scene_tree_dock.h b/tools/editor/scene_tree_dock.h index ac5391f3b9..92ebfc5bee 100644 --- a/tools/editor/scene_tree_dock.h +++ b/tools/editor/scene_tree_dock.h @@ -102,6 +102,7 @@ class SceneTreeDock : public VBoxContainer { void _load_request(const String& p_path); void _script_open_request(const Ref<Script>& p_script); + bool _cyclical_dependency_exists(const String& p_target_scene_path, Node* p_desired_node); void _node_selected(); void _node_renamed(); diff --git a/tools/export/blender25/io_scene_dae/export_dae.py b/tools/export/blender25/io_scene_dae/export_dae.py index 8161f05bf8..8e751fc33c 100644 --- a/tools/export/blender25/io_scene_dae/export_dae.py +++ b/tools/export/blender25/io_scene_dae/export_dae.py @@ -212,8 +212,8 @@ class DaeExporter: imgid = self.new_id("image") if (not os.path.isfile(imgpath)): - if img_tmp_path.endswith((".bmp",".rgb",".png",".jpeg",".jpg",".jp2",".tga",".cin",".dpx",".exr",".hdr",".tif")): - imgpath="images/"+os.path.basename(img_tmp_path) + if imgpath.endswith((".bmp",".rgb",".png",".jpeg",".jpg",".jp2",".tga",".cin",".dpx",".exr",".hdr",".tif")): + imgpath="images/"+os.path.basename(imgpath) else: imgpath="images/"+image.name+".png" |