diff options
Diffstat (limited to 'scene/resources')
-rw-r--r-- | scene/resources/audio_stream_resampled.cpp | 30 | ||||
-rw-r--r-- | scene/resources/audio_stream_resampled.h | 4 | ||||
-rw-r--r-- | scene/resources/curve.cpp | 6 | ||||
-rw-r--r-- | scene/resources/default_theme/default_theme.cpp | 19 | ||||
-rw-r--r-- | scene/resources/default_theme/graph_node.png | bin | 0 -> 770 bytes | |||
-rw-r--r-- | scene/resources/default_theme/graph_node_close.png | bin | 0 -> 243 bytes | |||
-rw-r--r-- | scene/resources/default_theme/graph_port.png | bin | 0 -> 509 bytes | |||
-rw-r--r-- | scene/resources/default_theme/theme_data.h | 15 | ||||
-rw-r--r-- | scene/resources/material.cpp | 18 | ||||
-rw-r--r-- | scene/resources/material.h | 1 | ||||
-rw-r--r-- | scene/resources/polygon_path_finder.cpp | 4 | ||||
-rw-r--r-- | scene/resources/shader.cpp | 59 | ||||
-rw-r--r-- | scene/resources/shader.h | 25 | ||||
-rw-r--r-- | scene/resources/shader_graph.cpp | 2531 | ||||
-rw-r--r-- | scene/resources/shader_graph.h | 413 | ||||
-rw-r--r-- | scene/resources/surface_tool.cpp | 4 | ||||
-rw-r--r-- | scene/resources/world_2d.cpp | 4 |
17 files changed, 2247 insertions, 886 deletions
diff --git a/scene/resources/audio_stream_resampled.cpp b/scene/resources/audio_stream_resampled.cpp index 8e694a6110..bc7bffa9d2 100644 --- a/scene/resources/audio_stream_resampled.cpp +++ b/scene/resources/audio_stream_resampled.cpp @@ -38,15 +38,18 @@ int AudioStreamResampled::get_channel_count() const { template<int C> -void AudioStreamResampled::_resample(int32_t *p_dest,int p_todo,int32_t p_increment) { +uint32_t AudioStreamResampled::_resample(int32_t *p_dest,int p_todo,int32_t p_increment) { + + uint32_t read=offset&MIX_FRAC_MASK; for (int i=0;i<p_todo;i++) { offset = (offset + p_increment)&(((1<<(rb_bits+MIX_FRAC_BITS))-1)); + read+=p_increment; uint32_t pos = offset >> MIX_FRAC_BITS; uint32_t frac = offset & MIX_FRAC_MASK; #ifndef FAST_AUDIO - ERR_FAIL_COND(pos>=rb_len); + ERR_FAIL_COND_V(pos>=rb_len,0); #endif uint32_t pos_next = (pos+1)&rb_mask; //printf("rb pos %i\n",pos); @@ -151,7 +154,7 @@ void AudioStreamResampled::_resample(int32_t *p_dest,int p_todo,int32_t p_increm } - rb_read_pos=offset>>MIX_FRAC_BITS; + return read>>MIX_FRAC_BITS;//rb_read_pos=offset>>MIX_FRAC_BITS; } @@ -173,10 +176,10 @@ bool AudioStreamResampled::mix(int32_t *p_dest, int p_frames) { } else if (rb_read_pos<write_pos_cache) { - rb_todo=write_pos_cache-rb_read_pos-1; + rb_todo=write_pos_cache-rb_read_pos; //-1? } else { - rb_todo=(rb_len-rb_read_pos)+write_pos_cache-1; + rb_todo=(rb_len-rb_read_pos)+write_pos_cache; //-1? } int todo = MIN( ((int64_t(rb_todo)<<MIX_FRAC_BITS)/increment)+1, p_frames ); @@ -220,13 +223,22 @@ bool AudioStreamResampled::mix(int32_t *p_dest, int p_frames) { #endif { + uint32_t read=0; switch(channels) { - case 1: _resample<1>(p_dest,todo,increment); break; - case 2: _resample<2>(p_dest,todo,increment); break; - case 4: _resample<4>(p_dest,todo,increment); break; - case 6: _resample<6>(p_dest,todo,increment); break; + case 1: read=_resample<1>(p_dest,todo,increment); break; + case 2: read=_resample<2>(p_dest,todo,increment); break; + case 4: read=_resample<4>(p_dest,todo,increment); break; + case 6: read=_resample<6>(p_dest,todo,increment); break; } + if (read>rb_todo) + read=rb_todo; + + rb_read_pos = (rb_read_pos+read)&rb_mask; + + + + } return true; diff --git a/scene/resources/audio_stream_resampled.h b/scene/resources/audio_stream_resampled.h index f1e3629ac7..a1b95e81d5 100644 --- a/scene/resources/audio_stream_resampled.h +++ b/scene/resources/audio_stream_resampled.h @@ -57,7 +57,7 @@ class AudioStreamResampled : public AudioStream { template<int C> - void _resample(int32_t *p_dest,int p_todo,int32_t p_increment); + uint32_t _resample(int32_t *p_dest,int p_todo,int32_t p_increment); protected: @@ -97,7 +97,7 @@ protected: _FORCE_INLINE_ int16_t *get_write_buffer() { return read_buf; } _FORCE_INLINE_ void write(uint32_t p_frames) { - ERR_FAIL_COND(p_frames > rb_len); + ERR_FAIL_COND(p_frames >= rb_len); switch(channels) { case 1: { diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index ae2c07ff56..6c27ffc6d9 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -134,7 +134,7 @@ Vector2 Curve2D::interpolate(int p_index, float p_offset) const { Vector2 Curve2D::interpolatef(real_t p_findex) const { - if (p_findex>0) + if (p_findex<0) p_findex=0; else if (p_findex>=points.size()) p_findex=points.size(); @@ -485,7 +485,7 @@ Vector2 Curve2D::interpolate(int p_index, float p_offset) const { Vector2 Curve2D::interpolatef(real_t p_findex) const { - if (p_findex>0) + if (p_findex<0) p_findex=0; else if (p_findex>=points.size()) p_findex=points.size(); @@ -956,7 +956,7 @@ Vector3 Curve3D::interpolate(int p_index, float p_offset) const { Vector3 Curve3D::interpolatef(real_t p_findex) const { - if (p_findex>0) + if (p_findex<0) p_findex=0; else if (p_findex>=points.size()) p_findex=points.size(); diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index d10bb37f60..e7f0d9b1f5 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -65,7 +65,7 @@ static Ref<Texture> make_icon(T p_src) { Ref<ImageTexture> texture( memnew( ImageTexture ) ); - texture->create_from_image( Image(p_src) ); + texture->create_from_image( Image(p_src),ImageTexture::FLAG_FILTER ); return texture; } @@ -331,6 +331,7 @@ void make_default_theme() { t->set_color("current_line_color","TextEdit", Color(0.3,0.5,0.8,0.15) ); t->set_color("cursor_color","TextEdit", control_font_color ); t->set_color("symbol_color","TextEdit", control_font_color_hover ); + t->set_color("brace_mismatch_color","TextEdit", Color(1,0.2,0.2) ); t->set_constant("line_spacing","TextEdit",1 ); t->set_stylebox("scroll","HScrollBar", make_stylebox( hscroll_bg_png,3,3,3,3,0,0,0,0) ); @@ -415,7 +416,21 @@ void make_default_theme() { t->set_color("font_color_hover","PopupMenu", control_font_color ); t->set_constant("hseparation","PopupMenu",2); t->set_constant("vseparation","PopupMenu",1); - + + Ref<StyleBoxTexture> graphsb = make_stylebox(graph_node_png,6,24,6,5,16,24,16,5); + //graphsb->set_expand_margin_size(MARGIN_LEFT,10); + //graphsb->set_expand_margin_size(MARGIN_RIGHT,10); + t->set_stylebox("frame","GraphNode", graphsb ); + t->set_constant("separation","GraphNode", 1 ); + t->set_icon("port","GraphNode", make_icon( graph_port_png ) ); + t->set_icon("close","GraphNode", make_icon( graph_node_close_png ) ); + t->set_font("title_font","GraphNode", default_font ); + t->set_color("title_color","GraphNode", Color(0,0,0,1)); + t->set_constant("title_offset","GraphNode", 18); + t->set_constant("close_offset","GraphNode", 18); + t->set_constant("port_offset","GraphNode", 3); + + t->set_stylebox("bg","Tree", make_stylebox( tree_bg_png,4,4,4,5,3,3,3,3) ); t->set_stylebox("bg_focus","Tree", focus ); Ref<StyleBoxTexture> tree_selected = make_stylebox( selection_png,4,4,4,4); diff --git a/scene/resources/default_theme/graph_node.png b/scene/resources/default_theme/graph_node.png Binary files differnew file mode 100644 index 0000000000..3adccf2c3b --- /dev/null +++ b/scene/resources/default_theme/graph_node.png diff --git a/scene/resources/default_theme/graph_node_close.png b/scene/resources/default_theme/graph_node_close.png Binary files differnew file mode 100644 index 0000000000..ea5b510418 --- /dev/null +++ b/scene/resources/default_theme/graph_node_close.png diff --git a/scene/resources/default_theme/graph_port.png b/scene/resources/default_theme/graph_port.png Binary files differnew file mode 100644 index 0000000000..92f425f977 --- /dev/null +++ b/scene/resources/default_theme/graph_port.png diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h index 9cef0265ee..a0f3dcd988 100644 --- a/scene/resources/default_theme/theme_data.h +++ b/scene/resources/default_theme/theme_data.h @@ -99,6 +99,21 @@ static const unsigned char full_panel_bg_png[]={ }; +static const unsigned char graph_node_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x10,0x0,0x0,0x0,0x40,0x8,0x6,0x0,0x0,0x0,0x13,0x7d,0xf7,0x96,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0xc,0x14,0x10,0x3,0x2e,0x15,0xb6,0x7,0x4a,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x2,0x6a,0x49,0x44,0x41,0x54,0x58,0xc3,0xed,0x97,0xbb,0x6e,0x13,0x51,0x10,0x86,0xbf,0xf1,0x2e,0xb1,0x83,0x85,0x63,0x5,0x10,0xe2,0x22,0xa5,0x0,0x1a,0x24,0x90,0x22,0x9e,0x81,0x2,0xd1,0x53,0xf1,0x2,0x20,0xa,0x1a,0xa,0xa0,0x44,0xd0,0xd0,0x20,0x81,0xe0,0x5,0xa8,0xe8,0x11,0x5,0xcf,0x80,0x22,0x81,0x42,0x3,0x14,0x91,0xb8,0x4,0x85,0x58,0x8e,0x21,0x78,0xd7,0xd9,0x73,0x86,0xe2,0x9c,0xdd,0xec,0xae,0xd7,0xce,0x85,0xe,0xed,0x34,0xbb,0x3a,0x3e,0xf3,0xcd,0xcc,0x3f,0x63,0x69,0x47,0xd8,0x36,0x1,0x1a,0x40,0xe0,0x9f,0x42,0xd1,0x14,0xb0,0x80,0xf1,0x4f,0x25,0x77,0xa9,0x1,0x1c,0x4,0xe6,0x81,0xa3,0x40,0x7,0x38,0x50,0x2,0x6c,0x1,0x3,0x60,0xd,0xe8,0x1,0x7f,0x0,0x9b,0x46,0x6d,0x3,0x67,0xe6,0xe,0x75,0xaf,0xb7,0x9a,0xad,0xcb,0x33,0x33,0xcd,0x53,0x54,0xd8,0x68,0x14,0x7f,0x89,0xe2,0xe8,0xf5,0xc6,0xaf,0xfe,0x73,0xe0,0x13,0xb0,0x29,0x3e,0xd2,0xc2,0x7c,0xf7,0xf0,0xe3,0xd3,0xb,0x67,0xaf,0x3c,0xb8,0xfb,0x88,0xd9,0x4e,0xab,0xca,0x9f,0xe1,0x20,0xe2,0xde,0xc3,0xdb,0x7c,0x5e,0xf9,0xf8,0xaa,0xd7,0x5f,0xbf,0x5,0xac,0x8,0xd0,0x2,0x16,0x8f,0x1f,0x3b,0xf9,0xe6,0xc5,0xb3,0x97,0xed,0x24,0xb1,0x24,0xa3,0xa4,0x12,0x10,0xce,0x84,0x84,0x61,0x83,0x6b,0x37,0xae,0x6e,0x7e,0xff,0xf1,0xf5,0x12,0xb0,0x14,0x7a,0x1d,0xda,0x61,0x10,0xb6,0x87,0xbf,0x63,0x10,0x75,0x47,0xa,0x2a,0x79,0x85,0x95,0x51,0xbc,0xc5,0x28,0x86,0x30,0x8,0xdb,0xbe,0x6c,0x49,0x1,0x1,0x80,0x51,0xeb,0xfc,0x9d,0xc0,0x4e,0x6b,0xf,0xd1,0xfc,0xb9,0xb3,0x20,0x5,0x68,0xfa,0x8b,0x5a,0x8b,0xaa,0x80,0x28,0x82,0xa0,0x28,0xa2,0x92,0x73,0xd3,0xb1,0xde,0x86,0x85,0x46,0x5b,0x45,0x51,0x50,0x45,0xc4,0x95,0x61,0x53,0x27,0x71,0x61,0x74,0x1a,0xc0,0xaa,0xcd,0x6e,0xa8,0x64,0x2f,0xee,0x5d,0x29,0x8a,0x32,0x39,0x3,0x5f,0xb6,0x2f,0x4c,0x45,0x73,0x5a,0xd8,0x31,0x48,0x1,0x60,0xac,0x2d,0xf1,0x5,0x51,0x75,0x45,0x68,0x5a,0xbf,0x4e,0xcf,0x60,0xfb,0x82,0x2b,0x5a,0x73,0x4e,0xb6,0xe2,0xf,0x52,0x2,0xd8,0x82,0xe2,0x14,0x50,0x54,0xc4,0x2f,0x8b,0x68,0xad,0x1f,0x99,0x54,0x79,0x41,0xdd,0x0,0xf8,0xb6,0x82,0x88,0x4e,0xeb,0x82,0x66,0x89,0xaa,0x3b,0xc8,0x52,0x48,0x41,0x56,0x76,0xcc,0x60,0x7b,0x74,0x75,0xac,0x1a,0x49,0x47,0x72,0x72,0x6,0xe2,0xe7,0x56,0x45,0xfd,0x5d,0xc9,0x44,0x28,0x40,0x2b,0x45,0x34,0xea,0x7,0xa8,0x14,0xc9,0x92,0x75,0x64,0x7,0x11,0x8d,0x8f,0x98,0x9b,0x87,0xf2,0xf4,0x4d,0xd5,0x40,0xd5,0xc9,0x97,0xf,0xa3,0x5a,0x74,0x9c,0x36,0x89,0xf7,0x9f,0xdc,0x61,0xaf,0x96,0x1,0x92,0x2d,0xc3,0xe2,0xf9,0x8b,0xbb,0x72,0x5a,0x7a,0xff,0xb6,0x3a,0x83,0x8d,0x41,0x7f,0xcf,0x19,0x34,0xf8,0x47,0xab,0x1,0x35,0xa0,0x6,0xd4,0x80,0x1a,0x50,0x3,0x6a,0xc0,0x7f,0x9,0x90,0x8a,0x4f,0xe0,0x3d,0x67,0x60,0xf7,0xe1,0x6b,0x53,0x80,0x5,0x22,0x63,0x4c,0x6c,0x93,0x5d,0x78,0x25,0x60,0x8c,0x89,0x81,0x8,0xb0,0xd,0xbf,0xca,0xae,0x47,0xf1,0x70,0x79,0xad,0xb7,0xca,0x34,0x88,0x4d,0x60,0xad,0xb7,0x4a,0x14,0xf,0x97,0x81,0x75,0xc0,0xa4,0x9b,0xeb,0x1c,0x70,0xa1,0xd3,0xee,0x3e,0x6d,0x35,0x67,0xcf,0x5,0x41,0x50,0x29,0xae,0x31,0xc6,0x46,0xf1,0xf0,0xc3,0x60,0xb3,0x7f,0x13,0x78,0x7,0x6c,0x48,0x6e,0x85,0xeb,0x0,0x27,0x80,0x23,0x40,0x73,0xc2,0xf2,0x1d,0x3,0x3f,0x81,0x6f,0x7e,0x8f,0x36,0x52,0x12,0x34,0x4c,0xf7,0xc1,0x9,0x55,0xa8,0x2f,0x39,0xd9,0xa7,0xf0,0xe3,0xf6,0x17,0x4c,0x97,0x1d,0x24,0x5b,0x8,0x8b,0x95,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + +static const unsigned char graph_node_close_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xc,0x0,0x0,0x0,0xc,0x8,0x6,0x0,0x0,0x0,0x56,0x75,0x5c,0xe7,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0xc,0x15,0x14,0x15,0x39,0x35,0x48,0xf8,0xe3,0x0,0x0,0x0,0x80,0x49,0x44,0x41,0x54,0x28,0xcf,0xa5,0xd1,0xb1,0xa,0xc2,0x40,0x10,0x84,0xe1,0x4f,0xe5,0x30,0xad,0x9d,0xb5,0x60,0xeb,0x3,0x88,0x2f,0x6d,0xfa,0xb4,0x29,0x83,0xbd,0xb5,0xb5,0x9d,0x68,0x15,0x9b,0x3d,0xb9,0x4,0x11,0xe,0x7,0xb6,0xd9,0xfd,0x67,0xb9,0xb9,0xa5,0x52,0xab,0xa8,0x13,0xb6,0x78,0xe0,0x39,0x63,0x36,0x38,0x60,0x87,0x1b,0x34,0xb8,0x60,0xc4,0x19,0xa9,0x80,0x53,0xf4,0xc6,0x60,0x9a,0x72,0xd0,0xc6,0xa0,0x2b,0xc,0x5d,0xf4,0xda,0xd9,0xa2,0x8f,0x29,0x3,0x43,0x54,0x5e,0x90,0x7e,0xe5,0xca,0x60,0x36,0x4e,0xb4,0xf4,0x87,0xaa,0x9e,0x54,0x15,0xba,0xea,0x5b,0x17,0x71,0xb8,0x23,0x5e,0xb8,0xe2,0xfe,0xe5,0x70,0x7b,0xac,0xd1,0x57,0x7,0x7d,0x3,0x51,0x8f,0x29,0x6b,0x3c,0x49,0x28,0x81,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + +static const unsigned char graph_port_png[]={ +0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0xa,0x0,0x0,0x0,0xa,0x8,0x6,0x0,0x0,0x0,0x8d,0x32,0xcf,0xbd,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x0,0x0,0x0,0x0,0x0,0xf9,0x43,0xbb,0x7f,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xde,0xc,0x14,0x17,0x20,0x3,0xeb,0x8f,0x3a,0xdb,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x1,0x65,0x49,0x44,0x41,0x54,0x18,0xd3,0x4d,0xd0,0x4f,0x6b,0xda,0x70,0x1c,0x7,0xe0,0xcf,0x37,0x7f,0x7e,0x49,0x66,0xd2,0x64,0x61,0x5,0x61,0x76,0x47,0xf1,0xa4,0x2d,0xdb,0x75,0x5,0x11,0x84,0xb0,0x5e,0xeb,0xd9,0xeb,0xf4,0x6d,0xec,0x2d,0xf8,0x26,0xb6,0x77,0xe0,0x45,0xba,0xa3,0x6c,0xa0,0x3b,0xad,0x39,0xb6,0x36,0x8,0x1b,0x4b,0x32,0xd2,0xc6,0x6c,0x9a,0x4f,0x4f,0x85,0x3e,0x2f,0xe1,0x11,0x0,0x20,0x29,0xd3,0xe9,0xd4,0xda,0x6e,0xb7,0x23,0xdf,0xf7,0xbb,0x0,0x90,0xe7,0xf9,0x8f,0x66,0xb3,0xf9,0x79,0x36,0x9b,0x55,0x22,0x42,0x83,0xa4,0x44,0x51,0xf4,0xea,0xe2,0xe2,0xc3,0xf7,0xf1,0x78,0xdc,0xa,0x82,0x40,0x8,0x20,0xcf,0x32,0x2e,0x97,0xcb,0x4f,0x51,0x14,0xbd,0x25,0xf9,0x5b,0x26,0x93,0x89,0xdd,0xe9,0x74,0xe2,0xf7,0xe7,0xe7,0x27,0x59,0xfa,0x87,0x65,0xb9,0x13,0x0,0xb0,0x1d,0x9b,0xe1,0xcb,0x50,0xbe,0x5e,0x5d,0xdd,0xfe,0xbc,0xbe,0x6e,0x6b,0x49,0x92,0x8c,0x4e,0x7b,0xa7,0xad,0xbf,0x79,0x4e,0xd3,0x54,0x12,0x86,0x21,0xc2,0x30,0x84,0x32,0x95,0xe4,0x79,0xc6,0xde,0xd9,0x59,0x2b,0x49,0xee,0x46,0x86,0xeb,0xba,0x5d,0xfb,0x85,0x23,0x87,0xfd,0x1e,0xb6,0xed,0x40,0xd7,0x35,0x0,0x40,0x7d,0x38,0xa0,0xdc,0xed,0x44,0x37,0x74,0xb8,0xae,0xd7,0x35,0x48,0x62,0xff,0xff,0x1f,0xfc,0x20,0x80,0xae,0xe9,0x78,0x42,0x0,0xca,0xb2,0x90,0x65,0x19,0x58,0xd7,0xd0,0x8a,0xa2,0x58,0xa7,0x69,0x56,0x6b,0xa2,0x51,0x29,0x5,0xcb,0x52,0xb0,0x94,0x5,0x4b,0x29,0x88,0x8,0xd3,0x34,0xad,0x8b,0xfb,0x62,0xad,0xf,0x6,0x83,0xb8,0xaa,0xaa,0xb1,0xe7,0x79,0xbe,0x77,0x74,0x44,0xb7,0xe1,0x89,0x69,0x1a,0x28,0xcb,0x92,0x9b,0xcd,0x46,0x56,0xab,0xd5,0x86,0xe4,0x47,0x21,0x29,0xc3,0xe1,0xf0,0xb8,0xdf,0xef,0x7f,0x6b,0xb7,0xdb,0xaf,0x1b,0x8d,0x86,0x46,0x10,0xf,0xf7,0xf,0x75,0x1c,0xc7,0x77,0x8b,0xc5,0xe2,0xdd,0x7c,0x3e,0xff,0x25,0xcf,0xc3,0x6f,0x6e,0x6f,0x2e,0x1d,0xdb,0xe9,0x9,0x80,0xb2,0x2a,0xd7,0x27,0xad,0x37,0x5f,0x9e,0xc2,0x1f,0x1,0x3a,0xe6,0xa5,0x7b,0xef,0xf2,0xf3,0xcd,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 +}; + + static const unsigned char hscroll_bg_png[]={ 0x89,0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b,0x0,0x0,0x0,0x6,0x62,0x4b,0x47,0x44,0x0,0x49,0x0,0x42,0x0,0x4e,0x4e,0xda,0xb4,0x7e,0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1,0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdd,0x9,0x1b,0x12,0x30,0x1c,0x3c,0x99,0xa,0x1c,0x0,0x0,0x0,0x19,0x74,0x45,0x58,0x74,0x43,0x6f,0x6d,0x6d,0x65,0x6e,0x74,0x0,0x43,0x72,0x65,0x61,0x74,0x65,0x64,0x20,0x77,0x69,0x74,0x68,0x20,0x47,0x49,0x4d,0x50,0x57,0x81,0xe,0x17,0x0,0x0,0x0,0x53,0x49,0x44,0x41,0x54,0x18,0xd3,0x7d,0x8f,0xc9,0xd,0x80,0x20,0x0,0xc0,0xca,0x21,0xe8,0x5f,0x12,0x89,0x84,0xfd,0x5c,0x48,0x26,0x34,0x3e,0x74,0x2,0xa2,0xe8,0x2,0x40,0xbf,0xed,0xa7,0xc2,0xbb,0xb0,0x3,0x1b,0x75,0x92,0xf0,0x2e,0x7c,0x46,0x9b,0xaa,0xcd,0x4f,0x46,0x3,0x8c,0x76,0xea,0x7,0x4a,0x29,0x5a,0x68,0x0,0x29,0x65,0x3f,0x30,0x83,0xed,0x6,0xe9,0xbc,0x8e,0xf6,0x45,0x79,0xb,0xc0,0x5c,0xb3,0xeb,0x12,0xef,0x1f,0xc6,0x6f,0x12,0x2,0xa,0xbd,0xc9,0x5d,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82 }; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 2c278f4fed..faba339fe1 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -458,6 +458,8 @@ FixedMaterial::~FixedMaterial() { } + + bool ShaderMaterial::_set(const StringName& p_name, const Variant& p_value) { if (p_name==SceneStringNames::get_singleton()->shader_shader) { @@ -499,7 +501,7 @@ bool ShaderMaterial::_get(const StringName& p_name,Variant &r_ret) const { void ShaderMaterial::_get_property_list( List<PropertyInfo> *p_list) const { - p_list->push_back( PropertyInfo( Variant::OBJECT, "shader/shader", PROPERTY_HINT_RESOURCE_TYPE,"Shader" ) ); + p_list->push_back( PropertyInfo( Variant::OBJECT, "shader/shader", PROPERTY_HINT_RESOURCE_TYPE,"MaterialShader,MaterialShaderGraph" ) ); if (!shader.is_null()) { @@ -558,7 +560,21 @@ void ShaderMaterial::_bind_methods() { } +void ShaderMaterial::get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const { + + String f = p_function.operator String(); + if ((f=="get_shader_param" || f=="set_shader_param") && p_idx==0) { + if (shader.is_valid()) { + List<PropertyInfo> pl; + shader->get_param_list(&pl); + for (List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) { + r_options->push_back(E->get().name); + } + } + } + Material::get_argument_options(p_function,p_idx,r_options); +} ShaderMaterial::ShaderMaterial() :Material(VisualServer::get_singleton()->material_create()){ diff --git a/scene/resources/material.h b/scene/resources/material.h index 9c3feede08..2b10078e16 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -243,6 +243,7 @@ public: void set_shader_param(const StringName& p_param,const Variant& p_value); Variant get_shader_param(const StringName& p_param) const; + void get_argument_options(const StringName& p_function,int p_idx,List<String>*r_options) const; ShaderMaterial(); }; diff --git a/scene/resources/polygon_path_finder.cpp b/scene/resources/polygon_path_finder.cpp index afb0ae1815..9f691d6ad3 100644 --- a/scene/resources/polygon_path_finder.cpp +++ b/scene/resources/polygon_path_finder.cpp @@ -142,6 +142,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2& p_from, const Vector if (d<closest_dist) { ignore_from_edge=E->get(); closest_dist=d; + closest_point=closest; } } @@ -168,6 +169,7 @@ Vector<Vector2> PolygonPathFinder::find_path(const Vector2& p_from, const Vector if (d<closest_dist) { ignore_to_edge=E->get(); closest_dist=d; + closest_point=closest; } } @@ -529,7 +531,7 @@ Vector2 PolygonPathFinder::get_closest_point(const Vector2& p_point) const { float d = p_point.distance_squared_to(points[i].pos); if (d<closest_dist) { - d=closest_dist; + closest_dist=d; closest_idx=i; } diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 6d65da3782..f3e625917a 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -33,12 +33,6 @@ #include "scene/scene_string_names.h" -void Shader::set_mode(Mode p_mode) { - - ERR_FAIL_INDEX(p_mode,2); - VisualServer::get_singleton()->shader_set_mode(shader,VisualServer::ShaderMode(p_mode)); - emit_signal(SceneStringNames::get_singleton()->changed); -} Shader::Mode Shader::get_mode() const { @@ -120,6 +114,13 @@ Dictionary Shader::_get_code() { c["vertex_ofs"]=0; c["light"]=ls; c["light_ofs"]=0; + Array arr; + for(const Map<StringName,Ref<Texture> >::Element *E=default_textures.front();E;E=E->next()) { + arr.push_back(E->key()); + arr.push_back(E->get()); + } + if (arr.size()) + c["default_tex"]=arr; return c; } @@ -132,11 +133,46 @@ void Shader::_set_code(const Dictionary& p_string) { light=p_string["light"]; set_code(p_string["vertex"],p_string["fragment"],light); + if (p_string.has("default_tex")) { + Array arr=p_string["default_tex"]; + if ((arr.size()&1)==0) { + for(int i=0;i<arr.size();i+=2) + set_default_texture_param(arr[i],arr[i+1]); + } + } } +void Shader::set_default_texture_param(const StringName& p_param,const Ref<Texture>& p_texture) { + + if (p_texture.is_valid()) { + default_textures[p_param]=p_texture; + VS::get_singleton()->shader_set_default_texture_param(shader,p_param,p_texture->get_rid()); + } else { + default_textures.erase(p_param); + VS::get_singleton()->shader_set_default_texture_param(shader,p_param,RID()); + } +} + +Ref<Texture> Shader::get_default_texture_param(const StringName& p_param) const{ + + if (default_textures.has(p_param)) + return default_textures[p_param]; + else + return Ref<Texture>(); +} + +void Shader::get_default_texture_param_list(List<StringName>* r_textures) const{ + + for(const Map<StringName,Ref<Texture> >::Element *E=default_textures.front();E;E=E->next()) { + + r_textures->push_back(E->key()); + } + +} + + void Shader::_bind_methods() { - ObjectTypeDB::bind_method(_MD("set_mode","mode"),&Shader::set_mode); ObjectTypeDB::bind_method(_MD("get_mode"),&Shader::get_mode); ObjectTypeDB::bind_method(_MD("set_code","vcode","fcode","lcode","fofs","lofs"),&Shader::set_code,DEFVAL(0),DEFVAL(0)); @@ -144,6 +180,9 @@ void Shader::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_fragment_code"),&Shader::get_fragment_code); ObjectTypeDB::bind_method(_MD("get_light_code"),&Shader::get_light_code); + ObjectTypeDB::bind_method(_MD("set_default_texture_param","param","texture:Texture"),&Shader::set_default_texture_param); + ObjectTypeDB::bind_method(_MD("get_default_texture_param:Texture","param"),&Shader::get_default_texture_param); + ObjectTypeDB::bind_method(_MD("has_param","name"),&Shader::has_param); ObjectTypeDB::bind_method(_MD("_set_code","code"),&Shader::_set_code); @@ -160,9 +199,9 @@ void Shader::_bind_methods() { } -Shader::Shader() { +Shader::Shader(Mode p_mode) { - shader = VisualServer::get_singleton()->shader_create(); + shader = VisualServer::get_singleton()->shader_create(VS::ShaderMode(p_mode)); params_cache_dirty=true; } @@ -194,7 +233,7 @@ RES ResourceFormatLoaderShader::load(const String &p_path,const String& p_origin String base_path = p_path.get_base_dir(); - Ref<Shader> shader( memnew( Shader ) ); + Ref<Shader> shader;//( memnew( Shader ) ); int line=0; diff --git a/scene/resources/shader.h b/scene/resources/shader.h index fff6f1d28a..8c15ca43d4 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -31,7 +31,7 @@ #include "resource.h" #include "io/resource_loader.h" - +#include "scene/resources/texture.h" class Shader : public Resource { OBJ_TYPE(Shader,Resource); @@ -48,6 +48,9 @@ class Shader : public Resource { // convertion fast and save memory. mutable bool params_cache_dirty; mutable Map<StringName,StringName> params_cache; //map a shader param to a material param.. + Map<StringName,Ref<Texture> > default_textures; + + protected: @@ -58,10 +61,11 @@ public: MODE_MATERIAL, MODE_CANVAS_ITEM, - MODE_POST_PROCESS + MODE_POST_PROCESS, + MODE_MAX }; - void set_mode(Mode p_mode); + //void set_mode(Mode p_mode); Mode get_mode() const; void set_code( const String& p_vertex, const String& p_fragment, const String& p_light,int p_fragment_ofs=0,int p_light_ofs=0); @@ -72,15 +76,28 @@ public: void get_param_list(List<PropertyInfo> *p_params) const; bool has_param(const StringName& p_param) const; + void set_default_texture_param(const StringName& p_param, const Ref<Texture> &p_texture); + Ref<Texture> get_default_texture_param(const StringName& p_param) const; + void get_default_texture_param_list(List<StringName>* r_textures) const; + virtual RID get_rid() const; - Shader(); + Shader(Mode p_mode); ~Shader(); }; VARIANT_ENUM_CAST( Shader::Mode ); +class MaterialShader : public Shader { + + OBJ_TYPE(MaterialShader,Shader); + +public: + + MaterialShader() : Shader(MODE_MATERIAL) {}; +}; + class ResourceFormatLoaderShader : public ResourceFormatLoader { diff --git a/scene/resources/shader_graph.cpp b/scene/resources/shader_graph.cpp index 3ed6cebf07..8b2f318ec0 100644 --- a/scene/resources/shader_graph.cpp +++ b/scene/resources/shader_graph.cpp @@ -27,121 +27,346 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "shader_graph.h" +#include "scene/scene_string_names.h" +//todo +//-RGB ops +//-mostrar error de conexion +Array ShaderGraph::_get_node_list(ShaderType p_type) const { + List<int> nodes; + get_node_list(p_type,&nodes); + Array arr(true); + for (List<int>::Element *E=nodes.front();E;E=E->next()) + arr.push_back(E->get()); + return arr; +} +Array ShaderGraph::_get_connections(ShaderType p_type) const { + + List<Connection> connections; + get_node_connections(p_type,&connections); + Array arr(true); + for (List<Connection>::Element *E=connections.front();E;E=E->next()) { + + Dictionary d(true); + d["src_id"]=E->get().src_id; + d["src_slot"]=E->get().src_slot; + d["dst_id"]=E->get().dst_id; + d["dst_slot"]=E->get().dst_slot; + arr.push_back(d); -# if 0 -void ShaderGraph::_set(const String& p_name, const Variant& p_value) { + } + return arr; +} - if (p_name.begins_with("nodes/")) { - int idx=p_name.get_slice("/",1).to_int(); - Dictionary data=p_value; +void ShaderGraph::_set_data(const Dictionary &p_data) { - ERR_FAIL_COND(!data.has("type")); - String type=data["type"]; + Dictionary d=p_data; + ERR_FAIL_COND(!d.has("shaders")); + Array sh=d["shaders"]; + ERR_FAIL_COND(sh.size()!=3); - VS::NodeType node_type=VS::NODE_TYPE_MAX; - for(int i=0;i<NODE_TYPE_MAX;i++) { + for(int t=0;t<3;t++) { + Array data=sh[t]; + ERR_FAIL_COND((data.size()%6)!=0); + shader[t].node_map.clear(); + for(int i=0;i<data.size();i+=6) { - if (type==VisualServer::shader_node_get_type_info((VS::NodeType)i).name) - node_type=(VS::NodeType)i; - } + Node n; + n.id=data[i+0]; + n.type=NodeType(int(data[i+1])); + n.pos=data[i+2]; + n.param1=data[i+3]; + n.param2=data[i+4]; - ERR_FAIL_COND(node_type==VS::NODE_TYPE_MAX); + Array conns=data[i+5]; + ERR_FAIL_COND((conns.size()%3)!=0); - node_add( (NodeType)node_type, idx ); - if (data.has("param")) - node_set_param(idx,data["param"]); - if (data.has("pos")) - node_set_pos(idx,data["pos"]); - } + for(int j=0;j<conns.size();j+=3) { - if (p_name.begins_with("conns/")) { - Dictionary data=p_value; - ERR_FAIL_COND( !data.has("src_id") ); - ERR_FAIL_COND( !data.has("src_slot") ); - ERR_FAIL_COND( !data.has("dst_id") ); - ERR_FAIL_COND( !data.has("dst_slot") ); + SourceSlot ss; + int ls=conns[j+0]; + ss.id=conns[j+1]; + ss.slot=conns[j+2]; + n.connections[ls]=ss; + } + shader[t].node_map[n.id]=n; - connect(data["src_id"],data["src_slot"],data["dst_id"],data["dst_slot"]); + } } - return false; + _update_shader(); + } -Variant ShaderGraph::_get(const String& p_name) const { - if (p_name.begins_with("nodes/")) { - int idx=p_name.get_slice("/",1).to_int(); - Dictionary data; - data["type"]=VisualServer::shader_node_get_type_info((VS::NodeType)node_get_type(idx)).name; - data["pos"]=node_get_pos(idx); - data["param"]=node_get_param(idx); - return data; - } - if (p_name.begins_with("conns/")) { - int idx=p_name.get_slice("/",1).to_int(); - Dictionary data; - - List<Connection> connections; - get_connections(&connections); - ERR_FAIL_INDEX_V( idx,connections.size(), Variant() ); - Connection c = connections[idx]; - - data["src_id"]=c.src_id; - data["src_slot"]=c.src_slot; - data["dst_id"]=c.dst_id; - data["dst_slot"]=c.dst_slot; - return data; +Dictionary ShaderGraph::_get_data() const { + + Array sh; + for(int i=0;i<3;i++) { + Array data; + int ec = shader[i].node_map.size(); + data.resize(ec*6); + int idx=0; + for (Map<int,Node>::Element*E=shader[i].node_map.front();E;E=E->next()) { + + data[idx+0]=E->key(); + data[idx+1]=E->get().type; + data[idx+2]=E->get().pos; + data[idx+3]=E->get().param1; + data[idx+4]=E->get().param2; + + Array conns; + conns.resize(E->get().connections.size()*3); + int idx2=0; + for(Map<int,SourceSlot>::Element*F=E->get().connections.front();F;F=F->next()) { + + conns[idx2+0]=F->key(); + conns[idx2+1]=F->get().id; + conns[idx2+2]=F->get().slot; + idx2+=3; + } + data[idx+5]=conns; + idx+=6; + } + sh.push_back(data); } - return Variant(); + Dictionary data; + data["shaders"]=sh; + return data; } -void ShaderGraph::_get_property_list( List<PropertyInfo> *p_list) const { - List<int> nodes; - get_node_list(&nodes); - for(List<int>::Element *E=nodes.front();E;E=E->next()) { - int idx=E->get(); - p_list->push_back(PropertyInfo( Variant::DICTIONARY , "nodes/"+itos(idx),PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NETWORK|PROPERTY_USAGE_STORAGE ) ); - } - - List<Connection> connections; - get_connections(&connections); - int idx=0; - for(List<Connection>::Element *E=connections.front();E;E=E->next()) { - p_list->push_back(PropertyInfo( Variant::DICTIONARY , "conns/"+itos(idx++),PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NETWORK|PROPERTY_USAGE_STORAGE ) ); - } +ShaderGraph::GraphError ShaderGraph::get_graph_error(ShaderType p_type) const { + ERR_FAIL_INDEX_V(p_type,3,GRAPH_OK); + return shader[p_type].error; } -#endif -#if 0 -Array ShaderGraph::_get_connections_helper() const { +void ShaderGraph::_bind_methods() { - Array connections_ret; - List<Connection> connections; - get_connections(&connections); - connections_ret.resize(connections.size()); - - int idx=0; - for(List<Connection>::Element *E=connections.front();E;E=E->next()) { - - Connection c = E->get(); - Dictionary data; - data["src_id"]=c.src_id; - data["src_slot"]=c.src_slot; - data["dst_id"]=c.dst_id; - data["dst_slot"]=c.dst_slot; - connections_ret.set(idx++,data); - } + ObjectTypeDB::bind_method(_MD("_update_shader"),&ShaderGraph::_update_shader); - return connections_ret; -} + ObjectTypeDB::bind_method(_MD("node_add","shader_type","node_type","id"),&ShaderGraph::node_add); + ObjectTypeDB::bind_method(_MD("node_remove","shader_type","id"),&ShaderGraph::node_remove); + ObjectTypeDB::bind_method(_MD("node_set_pos","shader_type","id","pos"),&ShaderGraph::node_set_pos); + ObjectTypeDB::bind_method(_MD("node_get_pos","shader_type","id"),&ShaderGraph::node_get_pos); -void ShaderGraph::_bind_methods() { + ObjectTypeDB::bind_method(_MD("node_get_type","shader_type","id"),&ShaderGraph::node_get_type); + + ObjectTypeDB::bind_method(_MD("get_node_list","shader_type"),&ShaderGraph::_get_node_list); + + ObjectTypeDB::bind_method(_MD("scalar_const_node_set_value","shader_type","id","value"),&ShaderGraph::scalar_const_node_set_value); + ObjectTypeDB::bind_method(_MD("scalar_const_node_get_value","shader_type","id"),&ShaderGraph::scalar_const_node_set_value); + + ObjectTypeDB::bind_method(_MD("vec_const_node_set_value","shader_type","id","value"),&ShaderGraph::vec_const_node_set_value); + ObjectTypeDB::bind_method(_MD("vec_const_node_get_value","shader_type","id"),&ShaderGraph::vec_const_node_set_value); + + ObjectTypeDB::bind_method(_MD("rgb_const_node_set_value","shader_type","id","value"),&ShaderGraph::rgb_const_node_set_value); + ObjectTypeDB::bind_method(_MD("rgb_const_node_get_value","shader_type","id"),&ShaderGraph::rgb_const_node_set_value); + + ObjectTypeDB::bind_method(_MD("xform_const_node_set_value","shader_type","id","value"),&ShaderGraph::xform_const_node_set_value); + ObjectTypeDB::bind_method(_MD("xform_const_node_get_value","shader_type","id"),&ShaderGraph::xform_const_node_set_value); + + +// void get_node_list(ShaderType p_which,List<int> *p_node_list) const; + + ObjectTypeDB::bind_method(_MD("texture_node_set_filter_size","shader_type","id","filter_size"),&ShaderGraph::texture_node_set_filter_size); + ObjectTypeDB::bind_method(_MD("texture_node_get_filter_size","shader_type","id"),&ShaderGraph::texture_node_set_filter_size); + + ObjectTypeDB::bind_method(_MD("texture_node_set_filter_strength","shader_type","id","filter_strength"),&ShaderGraph::texture_node_set_filter_strength); + ObjectTypeDB::bind_method(_MD("texture_node_get_filter_strength","shader_type","id"),&ShaderGraph::texture_node_set_filter_strength); + + ObjectTypeDB::bind_method(_MD("scalar_op_node_set_op","shader_type","id","op"),&ShaderGraph::scalar_op_node_set_op); + ObjectTypeDB::bind_method(_MD("scalar_op_node_get_op","shader_type","id"),&ShaderGraph::scalar_op_node_get_op); + + ObjectTypeDB::bind_method(_MD("vec_op_node_set_op","shader_type","id","op"),&ShaderGraph::vec_op_node_set_op); + ObjectTypeDB::bind_method(_MD("vec_op_node_get_op","shader_type","id"),&ShaderGraph::vec_op_node_get_op); + + ObjectTypeDB::bind_method(_MD("vec_scalar_op_node_set_op","shader_type","id","op"),&ShaderGraph::vec_scalar_op_node_set_op); + ObjectTypeDB::bind_method(_MD("vec_scalar_op_node_get_op","shader_type","id"),&ShaderGraph::vec_scalar_op_node_get_op); + + ObjectTypeDB::bind_method(_MD("rgb_op_node_set_op","shader_type","id","op"),&ShaderGraph::rgb_op_node_set_op); + ObjectTypeDB::bind_method(_MD("rgb_op_node_get_op","shader_type","id"),&ShaderGraph::rgb_op_node_get_op); + + ObjectTypeDB::bind_method(_MD("xform_vec_mult_node_set_no_translation","shader_type","id","disable"),&ShaderGraph::xform_vec_mult_node_set_no_translation); + ObjectTypeDB::bind_method(_MD("xform_vec_mult_node_get_no_translation","shader_type","id"),&ShaderGraph::xform_vec_mult_node_get_no_translation); + + ObjectTypeDB::bind_method(_MD("scalar_func_node_set_function","shader_type","id","func"),&ShaderGraph::scalar_func_node_set_function); + ObjectTypeDB::bind_method(_MD("scalar_func_node_get_function","shader_type","id"),&ShaderGraph::scalar_func_node_get_function); + + ObjectTypeDB::bind_method(_MD("vec_func_node_set_function","shader_type","id","func"),&ShaderGraph::vec_func_node_set_function); + ObjectTypeDB::bind_method(_MD("vec_func_node_get_function","shader_type","id"),&ShaderGraph::vec_func_node_get_function); + + ObjectTypeDB::bind_method(_MD("input_node_set_name","shader_type","id","name"),&ShaderGraph::input_node_set_name); + ObjectTypeDB::bind_method(_MD("input_node_get_name","shader_type","id"),&ShaderGraph::input_node_get_name); + + ObjectTypeDB::bind_method(_MD("scalar_input_node_set_value","shader_type","id","value"),&ShaderGraph::scalar_input_node_set_value); + ObjectTypeDB::bind_method(_MD("scalar_input_node_get_value","shader_type","id"),&ShaderGraph::scalar_input_node_get_value); + + ObjectTypeDB::bind_method(_MD("vec_input_node_set_value","shader_type","id","value"),&ShaderGraph::vec_input_node_set_value); + ObjectTypeDB::bind_method(_MD("vec_input_node_get_value","shader_type","id"),&ShaderGraph::vec_input_node_get_value); + + ObjectTypeDB::bind_method(_MD("rgb_input_node_set_value","shader_type","id","value"),&ShaderGraph::rgb_input_node_set_value); + ObjectTypeDB::bind_method(_MD("rgb_input_node_get_value","shader_type","id"),&ShaderGraph::rgb_input_node_get_value); + + ObjectTypeDB::bind_method(_MD("xform_input_node_set_value","shader_type","id","value"),&ShaderGraph::xform_input_node_set_value); + ObjectTypeDB::bind_method(_MD("xform_input_node_get_value","shader_type","id"),&ShaderGraph::xform_input_node_get_value); + + ObjectTypeDB::bind_method(_MD("texture_input_node_set_value","shader_type","id","value:Texture"),&ShaderGraph::texture_input_node_set_value); + ObjectTypeDB::bind_method(_MD("texture_input_node_get_value:Texture","shader_type","id"),&ShaderGraph::texture_input_node_get_value); + + ObjectTypeDB::bind_method(_MD("cubemap_input_node_set_value","shader_type","id","value:CubeMap"),&ShaderGraph::cubemap_input_node_set_value); + ObjectTypeDB::bind_method(_MD("cubemap_input_node_get_value:CubeMap","shader_type","id"),&ShaderGraph::cubemap_input_node_get_value); + + 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("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); + ObjectTypeDB::bind_method(_MD("get_node_connections","shader_type"),&ShaderGraph::_get_connections); + + ObjectTypeDB::bind_method(_MD("clear","shader_type"),&ShaderGraph::clear); + + ObjectTypeDB::bind_method(_MD("node_set_state","shader_type","id","state"),&ShaderGraph::node_set_state); + ObjectTypeDB::bind_method(_MD("node_get_state:var","shader_type","id"),&ShaderGraph::node_get_state); + + ObjectTypeDB::bind_method(_MD("_set_data"),&ShaderGraph::_set_data); + ObjectTypeDB::bind_method(_MD("_get_data"),&ShaderGraph::_get_data); + + ADD_PROPERTY( PropertyInfo(Variant::DICTIONARY,"_data",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR), _SCS("_set_data"),_SCS("_get_data")); + + //void get_connections(ShaderType p_which,List<Connection> *p_connections) const; + + + BIND_CONSTANT( NODE_INPUT ); // all inputs (shader type dependent) + BIND_CONSTANT( NODE_SCALAR_CONST ); //scalar constant + BIND_CONSTANT( NODE_VEC_CONST ); //vec3 constant + BIND_CONSTANT( NODE_RGB_CONST ); //rgb constant (shows a color picker instead) + BIND_CONSTANT( NODE_XFORM_CONST ); // 4x4 matrix constant + BIND_CONSTANT( NODE_TIME ); // time in seconds + BIND_CONSTANT( NODE_SCREEN_TEX ); // screen texture sampler (takes UV) (only usable in fragment shader) + BIND_CONSTANT( NODE_SCALAR_OP ); // scalar vs scalar op (mul ); add ); div ); etc) + BIND_CONSTANT( NODE_VEC_OP ); // vec3 vs vec3 op (mul );ad );div );crossprod );etc) + BIND_CONSTANT( NODE_VEC_SCALAR_OP ); // vec3 vs scalar op (mul ); add ); div ); etc) + BIND_CONSTANT( NODE_RGB_OP ); // vec3 vs vec3 rgb op (with scalar amount) ); like brighten ); darken ); burn ); dodge ); multiply ); etc. + BIND_CONSTANT( NODE_XFORM_MULT ); // mat4 x mat4 + BIND_CONSTANT( NODE_XFORM_VEC_MULT ); // mat4 x vec3 mult (with no-translation option) + BIND_CONSTANT( NODE_XFORM_VEC_INV_MULT ); // mat4 x vec3 inverse mult (with no-translation option) + BIND_CONSTANT( NODE_SCALAR_FUNC ); // scalar function (sin ); cos ); etc) + BIND_CONSTANT( NODE_VEC_FUNC ); // vector function (normalize ); negate ); reciprocal ); rgb2hsv ); hsv2rgb ); etc ); etc) + BIND_CONSTANT( NODE_VEC_LEN ); // vec3 length + BIND_CONSTANT( NODE_DOT_PROD ); // vec3 . vec3 (dot product -> scalar output) + BIND_CONSTANT( NODE_VEC_TO_SCALAR ); // 1 vec3 input ); 3 scalar outputs + BIND_CONSTANT( NODE_SCALAR_TO_VEC ); // 3 scalar input ); 1 vec3 output + BIND_CONSTANT( NODE_VEC_TO_XFORM ); // 3 vec input ); 1 xform output + 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_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_OUTPUT ); // output (shader type dependent) + BIND_CONSTANT( NODE_COMMENT ); // comment + BIND_CONSTANT( NODE_TYPE_MAX ); + + BIND_CONSTANT( SLOT_TYPE_SCALAR ); + BIND_CONSTANT( SLOT_TYPE_VEC ); + BIND_CONSTANT( SLOT_TYPE_XFORM ); + BIND_CONSTANT( SLOT_TYPE_TEXTURE ); + BIND_CONSTANT( SLOT_MAX ); + + BIND_CONSTANT( SHADER_TYPE_VERTEX ); + BIND_CONSTANT( SHADER_TYPE_FRAGMENT ); + BIND_CONSTANT( SHADER_TYPE_LIGHT ); + BIND_CONSTANT( SHADER_TYPE_MAX ); + + + BIND_CONSTANT( SLOT_IN ); + BIND_CONSTANT( SLOT_OUT ); + + BIND_CONSTANT( GRAPH_OK ); + BIND_CONSTANT( GRAPH_ERROR_CYCLIC ); + BIND_CONSTANT( GRAPH_ERROR_MISSING_CONNECTIONS ); + + BIND_CONSTANT( SCALAR_OP_ADD ); + BIND_CONSTANT( SCALAR_OP_SUB ); + BIND_CONSTANT( SCALAR_OP_MUL ); + BIND_CONSTANT( SCALAR_OP_DIV ); + BIND_CONSTANT( SCALAR_OP_MOD ); + BIND_CONSTANT( SCALAR_OP_POW ); + BIND_CONSTANT( SCALAR_OP_MAX ); + BIND_CONSTANT( SCALAR_OP_MIN ); + BIND_CONSTANT( SCALAR_OP_ATAN2 ); + BIND_CONSTANT( SCALAR_MAX_OP ); + + BIND_CONSTANT( VEC_OP_ADD ); + BIND_CONSTANT( VEC_OP_SUB ); + BIND_CONSTANT( VEC_OP_MUL ); + BIND_CONSTANT( VEC_OP_DIV ); + BIND_CONSTANT( VEC_OP_MOD ); + BIND_CONSTANT( VEC_OP_POW ); + BIND_CONSTANT( VEC_OP_MAX ); + BIND_CONSTANT( VEC_OP_MIN ); + BIND_CONSTANT( VEC_OP_CROSS ); + BIND_CONSTANT( VEC_MAX_OP ); + + BIND_CONSTANT( VEC_SCALAR_OP_MUL ); + BIND_CONSTANT( VEC_SCALAR_OP_DIV ); + BIND_CONSTANT( VEC_SCALAR_OP_POW ); + BIND_CONSTANT( VEC_SCALAR_MAX_OP ); + + BIND_CONSTANT( RGB_OP_SCREEN ); + BIND_CONSTANT( RGB_OP_DIFFERENCE ); + BIND_CONSTANT( RGB_OP_DARKEN ); + BIND_CONSTANT( RGB_OP_LIGHTEN ); + BIND_CONSTANT( RGB_OP_OVERLAY ); + BIND_CONSTANT( RGB_OP_DODGE ); + BIND_CONSTANT( RGB_OP_BURN ); + BIND_CONSTANT( RGB_OP_SOFT_LIGHT ); + BIND_CONSTANT( RGB_OP_HARD_LIGHT ); + BIND_CONSTANT( RGB_MAX_OP ); + + BIND_CONSTANT( SCALAR_FUNC_SIN ); + BIND_CONSTANT( SCALAR_FUNC_COS ); + BIND_CONSTANT( SCALAR_FUNC_TAN ); + BIND_CONSTANT( SCALAR_FUNC_ASIN ); + BIND_CONSTANT( SCALAR_FUNC_ACOS ); + BIND_CONSTANT( SCALAR_FUNC_ATAN ); + BIND_CONSTANT( SCALAR_FUNC_SINH ); + BIND_CONSTANT( SCALAR_FUNC_COSH ); + BIND_CONSTANT( SCALAR_FUNC_TANH ); + BIND_CONSTANT( SCALAR_FUNC_LOG ); + BIND_CONSTANT( SCALAR_FUNC_EXP ); + BIND_CONSTANT( SCALAR_FUNC_SQRT ); + BIND_CONSTANT( SCALAR_FUNC_ABS ); + BIND_CONSTANT( SCALAR_FUNC_SIGN ); + BIND_CONSTANT( SCALAR_FUNC_FLOOR ); + BIND_CONSTANT( SCALAR_FUNC_ROUND ); + BIND_CONSTANT( SCALAR_FUNC_CEIL ); + BIND_CONSTANT( SCALAR_FUNC_FRAC ); + BIND_CONSTANT( SCALAR_FUNC_SATURATE ); + BIND_CONSTANT( SCALAR_FUNC_NEGATE ); + BIND_CONSTANT( SCALAR_MAX_FUNC ); + + BIND_CONSTANT( VEC_FUNC_NORMALIZE ); + BIND_CONSTANT( VEC_FUNC_SATURATE ); + BIND_CONSTANT( VEC_FUNC_NEGATE ); + BIND_CONSTANT( VEC_FUNC_RECIPROCAL ); + BIND_CONSTANT( VEC_FUNC_RGB2HSV ); + BIND_CONSTANT( VEC_FUNC_HSV2RGB ); + BIND_CONSTANT( VEC_MAX_FUNC ); + + ADD_SIGNAL(MethodInfo("updated")); + + +#if 0 ObjectTypeDB::bind_method(_MD("node_add"),&ShaderGraph::node_add ); ObjectTypeDB::bind_method(_MD("node_remove"),&ShaderGraph::node_remove ); ObjectTypeDB::bind_method(_MD("node_set_param"),&ShaderGraph::node_set_param ); @@ -212,73 +437,158 @@ void ShaderGraph::_bind_methods() { BIND_CONSTANT( NODE_TEXTURE_2D_PARAMETER ); BIND_CONSTANT( NODE_TEXTURE_CUBE_PARAMETER ); BIND_CONSTANT( NODE_TYPE_MAX ); +#endif } -void ShaderGraph::node_add(NodeType p_type,int p_id) { + +String ShaderGraph::_find_unique_name(const String& p_base) { + - ERR_FAIL_COND( node_map.has(p_id ) ); - ERR_FAIL_INDEX( p_type, NODE_TYPE_MAX ); + int idx=1; + while(true) { + String tocmp=p_base; + if (idx>1) { + tocmp+="_"+itos(idx); + } + bool valid=true; + for(int i=0;i<3;i++) { + if (!valid) + break; + for (Map<int,Node>::Element *E=shader[i].node_map.front();E;E=E->next()) { + if (E->get().type!=NODE_SCALAR_INPUT && E->get().type!=NODE_VEC_INPUT && E->get().type==NODE_RGB_INPUT && E->get().type==NODE_XFORM_INPUT && E->get().type==NODE_TEXTURE_INPUT && E->get().type==NODE_CUBEMAP_INPUT) + continue; + String name = E->get().param1; + if (name==tocmp) { + valid=false; + break; + } + + } + } + + if (!valid) { + idx++; + continue; + } + return tocmp; + } + return String(); +} + +void ShaderGraph::node_add(ShaderType p_type, NodeType p_node_type,int p_id) { + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(p_id==0); + ERR_FAIL_COND(p_node_type==NODE_OUTPUT); //can't create output + ERR_FAIL_COND( shader[p_type].node_map.has(p_id ) ); + ERR_FAIL_INDEX( p_node_type, NODE_TYPE_MAX ); Node node; - node.type=p_type; + if (p_node_type==NODE_INPUT) { + //see if it already exists + for(Map<int,Node>::Element *E=shader[p_type].node_map.front();E;E=E->next()) { + if (E->get().type==NODE_INPUT) { + ERR_EXPLAIN("Only one input node can be added to the graph."); + ERR_FAIL_COND(E->get().type==NODE_INPUT); + } + } + } + node.type=p_node_type; node.id=p_id; - node.x=0; - node.y=0; - node_map[p_id]=node; + switch(p_node_type) { + case NODE_INPUT: {} break; // all inputs (shader type dependent) + case NODE_SCALAR_CONST: { node.param1=0;} break; //scalar constant + case NODE_VEC_CONST: {node.param1=Vector3();} break; //vec3 constant + case NODE_RGB_CONST: {node.param1=Color();} break; //rgb constant (shows a color picker instead) + case NODE_XFORM_CONST: {node.param1=Transform();} break; // 4x4 matrix constant + case NODE_TIME: {} break; // time in seconds + case NODE_SCREEN_TEX: {Array arr; arr.push_back(0); arr.push_back(0); node.param2=arr;} break; // screen texture sampler (takes UV) (only usable in fragment shader) + case NODE_SCALAR_OP: {node.param1=SCALAR_OP_ADD;} break; // scalar vs scalar op (mul: {} break; add: {} break; div: {} break; etc) + case NODE_VEC_OP: {node.param1=VEC_OP_ADD;} break; // vec3 vs vec3 op (mul: {} break;ad: {} break;div: {} break;crossprod: {} break;etc) + case NODE_VEC_SCALAR_OP: {node.param1=VEC_SCALAR_OP_MUL;} break; // vec3 vs scalar op (mul: {} break; add: {} break; div: {} break; etc) + case NODE_RGB_OP: {node.param1=RGB_OP_SCREEN;} break; // vec3 vs vec3 rgb op (with scalar amount): {} break; like brighten: {} break; darken: {} break; burn: {} break; dodge: {} break; multiply: {} break; etc. + case NODE_XFORM_MULT: {} break; // mat4 x mat4 + case NODE_XFORM_VEC_MULT: {} break; // mat4 x vec3 mult (with no-translation option) + case NODE_XFORM_VEC_INV_MULT: {} break; // mat4 x vec3 inverse mult (with no-translation option) + case NODE_SCALAR_FUNC: {node.param1=SCALAR_FUNC_SIN;} break; // scalar function (sin: {} break; cos: {} break; etc) + case NODE_VEC_FUNC: {node.param1=VEC_FUNC_NORMALIZE;} break; // vector function (normalize: {} break; negate: {} break; reciprocal: {} break; rgb2hsv: {} break; hsv2rgb: {} break; etc: {} break; etc) + case NODE_VEC_LEN: {} break; // vec3 length + case NODE_DOT_PROD: {} break; // vec3 . vec3 (dot product -> scalar output) + case NODE_VEC_TO_SCALAR: {} break; // 1 vec3 input: {} break; 3 scalar outputs + case NODE_SCALAR_TO_VEC: {} break; // 3 scalar input: {} break; 1 vec3 output + case NODE_VEC_TO_XFORM: {} break; // 3 scalar input: {} break; 1 vec3 output + 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_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_OUTPUT: {} break; // output (shader type dependent) + case NODE_COMMENT: {} break; // comment + case NODE_TYPE_MAX: {}; + } + shader[p_type].node_map[p_id]=node; + _request_update(); } -void ShaderGraph::node_set_pos(int p_id, const Vector2& p_pos) { +void ShaderGraph::node_set_pos(ShaderType p_type,int p_id, const Vector2& p_pos) { + ERR_FAIL_INDEX(p_type,3); + + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + shader[p_type].node_map[p_id].pos=p_pos; + _request_update(); - ERR_FAIL_COND(!node_map.has(p_id)); - node_map[p_id].x=p_pos.x; - node_map[p_id].y=p_pos.y; } -Vector2 ShaderGraph::node_get_pos(int p_id) const { +Vector2 ShaderGraph::node_get_pos(ShaderType p_type,int p_id) const { + ERR_FAIL_INDEX_V(p_type,3,Vector2()); - ERR_FAIL_COND_V(!node_map.has(p_id),Vector2()); - return Vector2(node_map[p_id].x,node_map[p_id].y); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Vector2()); + return shader[p_type].node_map[p_id].pos; } -void ShaderGraph::node_remove(int p_id) { +void ShaderGraph::node_remove(ShaderType p_type,int p_id) { + + ERR_FAIL_COND(p_id==0); + ERR_FAIL_INDEX(p_type,3); - ERR_FAIL_COND(!node_map.has(p_id)); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); //erase connections associated with node - List<Connection>::Element *N,*E=connections.front(); - while(E) { - N=E->next(); - const Connection &c = E->get(); - if (c.src_id==p_id || c.dst_id==p_id) { + for(Map<int,Node>::Element *E=shader[p_type].node_map.front();E;E=E->next()) { + if (E->key()==p_id) + continue; //no self + + for (Map<int,SourceSlot>::Element *F=E->get().connections.front();F;) { + Map<int,SourceSlot>::Element *N=F->next(); + + if (F->get().id==p_id) { + E->get().connections.erase(F); + } - connections.erase(E); + F=N; } - E=N; } - node_map.erase(p_id); -} - -void ShaderGraph::node_change_type(int p_id, NodeType p_type) { + shader[p_type].node_map.erase(p_id); - ERR_FAIL_COND(!node_map.has(p_id)); - node_map[p_id].type=p_type; - node_map[p_id].param=Variant(); + _request_update(); } -void ShaderGraph::node_set_param(int p_id, const Variant& p_value) { - ERR_FAIL_COND(!node_map.has(p_id)); - node_map[p_id].param=p_value; -} -void ShaderGraph::get_node_list(List<int> *p_node_list) const { +void ShaderGraph::get_node_list(ShaderType p_type,List<int> *p_node_list) const { - Map<int,Node>::Element *E = node_map.front(); + ERR_FAIL_INDEX(p_type,3); + + Map<int,Node>::Element *E = shader[p_type].node_map.front(); while(E) { @@ -288,740 +598,1463 @@ void ShaderGraph::get_node_list(List<int> *p_node_list) const { } -ShaderGraph::NodeType ShaderGraph::node_get_type(int p_id) const { +ShaderGraph::NodeType ShaderGraph::node_get_type(ShaderType p_type,int p_id) const { - ERR_FAIL_COND_V(!node_map.has(p_id),NODE_TYPE_MAX); - return node_map[p_id].type; -} + ERR_FAIL_INDEX_V(p_type,3,NODE_TYPE_MAX); -Variant ShaderGraph::node_get_param(int p_id) const { - - ERR_FAIL_COND_V(!node_map.has(p_id),Variant()); - return node_map[p_id].param; + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),NODE_TYPE_MAX); + return shader[p_type].node_map[p_id].type; } -Error ShaderGraph::connect(int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) { +Error ShaderGraph::connect_node(ShaderType p_type,int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) { + ERR_FAIL_INDEX_V(p_type,3,ERR_INVALID_PARAMETER); ERR_FAIL_COND_V(p_src_id==p_dst_id, ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(!node_map.has(p_src_id), ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(!node_map.has(p_dst_id), ERR_INVALID_PARAMETER); - NodeType type_src=node_map[p_src_id].type; - NodeType type_dst=node_map[p_dst_id].type; - //ERR_FAIL_INDEX_V( p_src_slot, VisualServer::shader_get_output_count(type_src), ERR_INVALID_PARAMETER ); - //ERR_FAIL_INDEX_V( p_dst_slot, VisualServer::shader_get_input_count(type_dst), ERR_INVALID_PARAMETER ); - //ERR_FAIL_COND_V(VisualServer::shader_is_output_vector(type_src,p_src_slot) != VisualServer::shader_is_input_vector(type_dst,p_dst_slot), ERR_INVALID_PARAMETER ); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_src_id), ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_dst_id), ERR_INVALID_PARAMETER); + NodeType type_src=shader[p_type].node_map[p_src_id].type; + NodeType type_dst=shader[p_type].node_map[p_dst_id].type; + ERR_FAIL_INDEX_V( p_src_slot, get_node_output_slot_count(get_mode(),p_type,type_src), ERR_INVALID_PARAMETER ); + ERR_FAIL_INDEX_V( p_dst_slot, get_node_input_slot_count(get_mode(),p_type,type_dst), ERR_INVALID_PARAMETER ); + ERR_FAIL_COND_V(get_node_output_slot_type(get_mode(),p_type,type_src,p_src_slot) != get_node_input_slot_type(get_mode(),p_type,type_dst,p_dst_slot), ERR_INVALID_PARAMETER ); - List<Connection>::Element *E=connections.front(); - while(E) { - const Connection &c = E->get(); - ERR_FAIL_COND_V(c.dst_slot==p_dst_slot && c.dst_id == p_dst_id, ERR_ALREADY_EXISTS); + SourceSlot ts; + ts.id=p_src_id; + ts.slot=p_src_slot; + shader[p_type].node_map[p_dst_id].connections[p_dst_slot]=ts; + _request_update(); - E=E->next(); - } + return OK; +} - Connection c; - c.src_slot=p_src_slot; - c.src_id=p_src_id; - c.dst_slot=p_dst_slot; - c.dst_id=p_dst_id; +bool ShaderGraph::is_node_connected(ShaderType p_type,int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) const { - connections.push_back(c); + ERR_FAIL_INDEX_V(p_type,3,false); - return OK; + SourceSlot ts; + ts.id=p_src_id; + ts.slot=p_src_slot; + return shader[p_type].node_map.has(p_dst_id) && shader[p_type].node_map[p_dst_id].connections.has(p_dst_slot) && + shader[p_type].node_map[p_dst_id].connections[p_dst_slot]==ts; } -bool ShaderGraph::is_connected(int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) const { +void ShaderGraph::disconnect_node(ShaderType p_type,int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) { + ERR_FAIL_INDEX(p_type,3); - const List<Connection>::Element *E=connections.front(); - while(E) { - const Connection &c = E->get(); - if (c.dst_slot==p_dst_slot && c.dst_id == p_dst_id && c.src_slot==p_src_slot && c.src_id == p_src_id) - return true; + SourceSlot ts; + ts.id=p_src_id; + ts.slot=p_src_slot; + if (shader[p_type].node_map.has(p_dst_id) && shader[p_type].node_map[p_dst_id].connections.has(p_dst_slot) && + shader[p_type].node_map[p_dst_id].connections[p_dst_slot]==ts) { + shader[p_type].node_map[p_dst_id].connections.erase(p_dst_slot); - E=E->next(); } + _request_update(); - return false; } -void ShaderGraph::disconnect(int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) { +void ShaderGraph::get_node_connections(ShaderType p_type,List<Connection> *p_connections) const { - List<Connection>::Element *N,*E=connections.front(); - while(E) { - N=E->next(); - const Connection &c = E->get(); - if (c.src_slot==p_src_slot && c.src_id==p_src_id && c.dst_slot==p_dst_slot && c.dst_id == p_dst_id) { + ERR_FAIL_INDEX(p_type,3); + + for(const Map<int,Node>::Element *E=shader[p_type].node_map.front();E;E=E->next()) { + for (const Map<int,SourceSlot>::Element *F=E->get().connections.front();F;F=F->next()) { - connections.erase(E); + Connection c; + c.dst_id=E->key(); + c.dst_slot=F->key(); + c.src_id=F->get().id; + c.src_slot=F->get().slot; + p_connections->push_back(c); } - E=N; } +} + + +void ShaderGraph::clear(ShaderType p_type) { + ERR_FAIL_INDEX(p_type,3); + shader[p_type].node_map.clear(); + Node out; + out.pos=Vector2(300,300); + out.type=NODE_OUTPUT; + shader[p_type].node_map.insert(0,out); + + _request_update(); } -void ShaderGraph::get_connections(List<Connection> *p_connections) const { - const List<Connection>::Element*E=connections.front(); - while(E) { - p_connections->push_back(E->get()); - E=E->next(); - } +void ShaderGraph::scalar_const_node_set_value(ShaderType p_type,int p_id,float p_value) { + 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]; + ERR_FAIL_COND(n.type!=NODE_SCALAR_CONST); + n.param1=p_value; + _request_update(); } +float ShaderGraph::scalar_const_node_get_value(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,0); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),0); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_SCALAR_CONST,0); + return n.param1; +} + +void ShaderGraph::vec_const_node_set_value(ShaderType p_type,int p_id,const Vector3& p_value){ + + 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]; + ERR_FAIL_COND(n.type!=NODE_VEC_CONST); + n.param1=p_value; + _request_update(); -void ShaderGraph::clear() { - connections.clear(); - node_map.clear(); } +Vector3 ShaderGraph::vec_const_node_get_value(ShaderType p_type,int p_id) const{ + ERR_FAIL_INDEX_V(p_type,3,Vector3()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Vector3()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_VEC_CONST,Vector3()); + return n.param1; -#if 0 -void ShaderGraph::node_add(NodeType p_type,int p_id) { +} + +void ShaderGraph::rgb_const_node_set_value(ShaderType p_type,int p_id,const Color& p_value){ + + 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]; + ERR_FAIL_COND(n.type!=NODE_RGB_CONST); + n.param1=p_value; + _request_update(); - ShaderNode sn; - sn.type=p_type; - nodes[p_id]=sn; - version++; } -void ShaderGraph::node_remove(int p_id) { +Color ShaderGraph::rgb_const_node_get_value(ShaderType p_type,int p_id) const{ - nodes.erase(p_id); + ERR_FAIL_INDEX_V(p_type,3,Color()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Color()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_RGB_CONST,Color()); + return n.param1; } -void ShaderGraph::node_set_param( int p_id, const Variant& p_value) { - VisualServer::get_singleton()->shader_node_set_param(shader,p_id,p_value); - version++; +void ShaderGraph::xform_const_node_set_value(ShaderType p_type,int p_id,const Transform& p_value){ + + 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]; + ERR_FAIL_COND(n.type!=NODE_XFORM_CONST); + n.param1=p_value; + _request_update(); + } +Transform ShaderGraph::xform_const_node_get_value(ShaderType p_type,int p_id) const{ -void ShaderGraph::get_node_list(List<int> *p_node_list) const { + ERR_FAIL_INDEX_V(p_type,3,Transform()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Transform()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_XFORM_CONST,Transform()); + return n.param1; - VisualServer::get_singleton()->shader_get_node_list(shader,p_node_list); } -ShaderGraph::NodeType ShaderGraph::node_get_type(int p_id) const { - return (NodeType)VisualServer::get_singleton()->shader_node_get_type(shader,p_id); +void ShaderGraph::texture_node_set_filter_size(ShaderType p_type,int p_id,int p_size){ + + 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]; + ERR_FAIL_COND(n.type!=NODE_TEXTURE_INPUT && n.type!=NODE_SCREEN_TEX); + Array arr = n.param2; + arr[0]=p_size; + n.param2=arr; + _request_update(); + } -Variant ShaderGraph::node_get_param(int p_id) const { +int ShaderGraph::texture_node_get_filter_size(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,0); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),0); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_TEXTURE_INPUT && n.type!=NODE_SCREEN_TEX,0); + Array arr = n.param2; + return arr[0]; - return VisualServer::get_singleton()->shader_node_get_param(shader,p_id); } -void ShaderGraph::connect(int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) { +void ShaderGraph::texture_node_set_filter_strength(ShaderType p_type,float p_id,float p_strength){ - VisualServer::get_singleton()->shader_connect(shader,p_src_id,p_src_slot,p_dst_id,p_dst_slot); - version++; + 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]; + ERR_FAIL_COND(n.type!=NODE_TEXTURE_INPUT && n.type!=NODE_SCREEN_TEX); + Array arr = n.param2; + arr[1]=p_strength; + n.param2=arr; + _request_update(); + +} +float ShaderGraph::texture_node_get_filter_strength(ShaderType p_type,float p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,0); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),0); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_TEXTURE_INPUT && n.type!=NODE_SCREEN_TEX,0); + Array arr = n.param2; + return arr[1]; } -void ShaderGraph::disconnect(int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) { - VisualServer::get_singleton()->shader_disconnect(shader,p_src_id,p_src_slot,p_dst_id,p_dst_slot); - version++; + +void ShaderGraph::scalar_op_node_set_op(ShaderType p_type,float p_id,ScalarOp p_op){ + + 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]; + ERR_FAIL_COND(n.type!=NODE_SCALAR_OP); + n.param1=p_op; + _request_update(); + } +ShaderGraph::ScalarOp ShaderGraph::scalar_op_node_get_op(ShaderType p_type,float p_id) const{ -void ShaderGraph::get_connections(List<Connection> *p_connections) const { + ERR_FAIL_INDEX_V(p_type,3,SCALAR_MAX_OP); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),SCALAR_MAX_OP); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_SCALAR_OP,SCALAR_MAX_OP); + int op = n.param1; + return ScalarOp(op); - List<VS::ShaderGraphConnection> connections; - VisualServer::get_singleton()->shader_get_connections(shader,&connections); - for( List<VS::ShaderGraphConnection>::Element *E=connections.front();E;E=E->next()) { +} + + +void ShaderGraph::vec_op_node_set_op(ShaderType p_type,float p_id,VecOp p_op){ + + 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]; + ERR_FAIL_COND(n.type!=NODE_VEC_OP); + n.param1=p_op; + _request_update(); - Connection c; - c.src_id=E->get().src_id; - c.src_slot=E->get().src_slot; - c.dst_id=E->get().dst_id; - c.dst_slot=E->get().dst_slot; - p_connections->push_back(c); - } } +ShaderGraph::VecOp ShaderGraph::vec_op_node_get_op(ShaderType p_type,float p_id) const{ -void ShaderGraph::node_set_pos(int p_id,const Point2& p_pos) { + ERR_FAIL_INDEX_V(p_type,3,VEC_MAX_OP); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),VEC_MAX_OP); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_VEC_OP,VEC_MAX_OP); + int op = n.param1; + return VecOp(op); -#ifdef TOOLS_ENABLED - ERR_FAIL_COND(!positions.has(p_id)); - positions[p_id]=p_pos; -#endif } -Point2 ShaderGraph::node_get_pos(int p_id) const { -#ifdef TOOLS_ENABLED - ERR_FAIL_COND_V(!positions.has(p_id),Point2()); - return positions[p_id]; -#endif + +void ShaderGraph::vec_scalar_op_node_set_op(ShaderType p_type,float p_id,VecScalarOp p_op){ + + 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]; + ERR_FAIL_COND(n.type!=NODE_VEC_SCALAR_OP); + n.param1=p_op; + _request_update(); + } +ShaderGraph::VecScalarOp ShaderGraph::vec_scalar_op_node_get_op(ShaderType p_type,float p_id) const{ -void ShaderGraph::clear() { + ERR_FAIL_INDEX_V(p_type,3,VEC_SCALAR_MAX_OP); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),VEC_SCALAR_MAX_OP); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_VEC_SCALAR_OP,VEC_SCALAR_MAX_OP); + int op = n.param1; + return VecScalarOp(op); - VisualServer::get_singleton()->shader_clear(shader); - version++; } -#endif -ShaderGraph::ShaderGraph() { +void ShaderGraph::rgb_op_node_set_op(ShaderType p_type,float p_id,RGBOp p_op){ + + 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]; + ERR_FAIL_COND(n.type!=NODE_RGB_OP); + n.param1=p_op; + + _request_update(); - //shader = VisualServer::get_singleton()->shader_create(); - version = 1; } +ShaderGraph::RGBOp ShaderGraph::rgb_op_node_get_op(ShaderType p_type,float p_id) const{ -ShaderGraph::~ShaderGraph() { + ERR_FAIL_INDEX_V(p_type,3,RGB_MAX_OP); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),RGB_MAX_OP); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_RGB_OP,RGB_MAX_OP); + int op = n.param1; + return RGBOp(op); - //VisualServer::get_singleton()->free(shader); } -#if 0 -void ShaderGraph::shader_get_default_input_nodes(Mode p_type,List<PropertyInfo> *p_inputs) { - switch(p_type) { +void ShaderGraph::xform_vec_mult_node_set_no_translation(ShaderType p_type,int p_id,bool p_no_translation){ - case SHADER_VERTEX: { + 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]; + ERR_FAIL_COND(n.type!=NODE_XFORM_VEC_MULT && n.type!=NODE_XFORM_VEC_INV_MULT); + n.param1=p_no_translation; + _request_update(); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"vertex") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"normal") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"binormal") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"tangent") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"uv") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"color") ); - p_inputs->push_back( PropertyInfo( Variant::REAL,"alpha") ); - } break; - case SHADER_FRAGMENT: { +} +bool ShaderGraph::xform_vec_mult_node_get_no_translation(ShaderType p_type,int p_id) const{ - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"position") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"normal") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"binormal") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"tangent") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"uv") ); - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"color") ); - p_inputs->push_back( PropertyInfo( Variant::REAL,"alpha") ); + ERR_FAIL_INDEX_V(p_type,3,false); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),false); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_XFORM_VEC_MULT && n.type!=NODE_XFORM_VEC_INV_MULT,false); + return n.param1; - } break; - case SHADER_POST_PROCESS: { - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"color") ); - p_inputs->push_back( PropertyInfo( Variant::REAL,"alpha") ); - } break; +} - } +void ShaderGraph::scalar_func_node_set_function(ShaderType p_type,int p_id,ScalarFunc p_func){ + 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]; + ERR_FAIL_COND(n.type!=NODE_SCALAR_FUNC); + int func = p_func; + ERR_FAIL_INDEX(func,SCALAR_MAX_FUNC); + n.param1=func; + _request_update(); + +} +ShaderGraph::ScalarFunc ShaderGraph::scalar_func_node_get_function(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,SCALAR_MAX_FUNC); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),SCALAR_MAX_FUNC); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_SCALAR_FUNC,SCALAR_MAX_FUNC); + int func = n.param1; + return ScalarFunc(func); } -void ShaderGraph::shader_get_default_output_nodes(ShaderGraphType p_type,List<PropertyInfo> *p_outputs) { - switch(p_type) { +void ShaderGraph::vec_func_node_set_function(ShaderType p_type,int p_id,VecFunc p_func){ - case SHADER_VERTEX: { + 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]; + ERR_FAIL_COND(n.type!=NODE_VEC_FUNC); + int func = p_func; + ERR_FAIL_INDEX(func,VEC_MAX_FUNC); + n.param1=func; - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"vertex") ); - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"normal") ); - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"binormal") ); - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"tangent") ); - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"uv") ); - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"color") ); - p_outputs->push_back( PropertyInfo( Variant::REAL,"alpha") ); - } break; - case SHADER_FRAGMENT: { + _request_update(); - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"normal") ); - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"diffuse") ); - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"specular") ); - p_outputs->push_back( PropertyInfo( Variant::REAL,"alpha") ); - p_outputs->push_back( PropertyInfo( Variant::REAL,"emission") ); - p_outputs->push_back( PropertyInfo( Variant::REAL,"spec_exp") ); - p_outputs->push_back( PropertyInfo( Variant::REAL,"glow") ); - p_outputs->push_back( PropertyInfo( Variant::REAL,"alpha_discard") ); +} +ShaderGraph::VecFunc ShaderGraph::vec_func_node_get_function(ShaderType p_type, int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,VEC_MAX_FUNC); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),VEC_MAX_FUNC); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_VEC_FUNC,VEC_MAX_FUNC); + int func = n.param1; + return VecFunc(func); +} - } break; - case SHADER_POST_PROCESS: { - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"color") ); - p_outputs->push_back( PropertyInfo( Variant::REAL,"alpha") ); - } break; +void ShaderGraph::input_node_set_name(ShaderType p_type,int p_id,const String& p_name){ + + ERR_FAIL_INDEX(p_type,3); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + ERR_FAIL_COND(!p_name.is_valid_identifier()); + Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND(n.type!=NODE_SCALAR_INPUT && n.type!=NODE_VEC_INPUT && n.type==NODE_RGB_INPUT && n.type==NODE_XFORM_INPUT && n.type==NODE_TEXTURE_INPUT && n.type==NODE_CUBEMAP_INPUT); + + n.param1=""; + n.param1=_find_unique_name(p_name); + _request_update(); + +} +String ShaderGraph::input_node_get_name(ShaderType p_type,int p_id){ + + ERR_FAIL_INDEX_V(p_type,3,String()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),String()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_SCALAR_INPUT && n.type!=NODE_VEC_INPUT && n.type==NODE_RGB_INPUT && n.type==NODE_XFORM_INPUT && n.type==NODE_TEXTURE_INPUT && n.type==NODE_CUBEMAP_INPUT,String()); + return n.param1; +} + + +void ShaderGraph::scalar_input_node_set_value(ShaderType p_type,int p_id,float p_value) { + + 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]; + ERR_FAIL_COND(n.type!=NODE_SCALAR_INPUT); + n.param2=p_value; + _request_update(); + +} + +float ShaderGraph::scalar_input_node_get_value(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,0); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),0); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_SCALAR_INPUT,0); + + return n.param2; +} + +void ShaderGraph::vec_input_node_set_value(ShaderType p_type,int p_id,const Vector3& p_value){ + + 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]; + ERR_FAIL_COND(n.type!=NODE_VEC_INPUT); + + n.param2=p_value; + _request_update(); + +} +Vector3 ShaderGraph::vec_input_node_get_value(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,Vector3()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Vector3()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_VEC_INPUT,Vector3()); + return n.param2; +} + +void ShaderGraph::rgb_input_node_set_value(ShaderType p_type,int p_id,const Color& p_value){ + + 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]; + ERR_FAIL_COND(n.type!=NODE_RGB_INPUT); + n.param2=p_value; + _request_update(); + +} +Color ShaderGraph::rgb_input_node_get_value(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,Color()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Color()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_RGB_INPUT,Color()); + return n.param2; +} + +void ShaderGraph::xform_input_node_set_value(ShaderType p_type,int p_id,const Transform& p_value){ + + 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]; + ERR_FAIL_COND(n.type!=NODE_XFORM_INPUT); + n.param2=p_value; + _request_update(); + +} +Transform ShaderGraph::xform_input_node_get_value(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,Transform()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Transform()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_XFORM_INPUT,Transform()); + return n.param2; +} + + +void ShaderGraph::texture_input_node_set_value(ShaderType p_type,int p_id,const Ref<Texture>& p_texture) { + + 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]; + ERR_FAIL_COND(n.type!=NODE_TEXTURE_INPUT); + n.param2=p_texture; + _request_update(); +} + +Ref<Texture> ShaderGraph::texture_input_node_get_value(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,Ref<Texture>()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Ref<Texture>()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_TEXTURE_INPUT,Ref<Texture>()); + return n.param2; +} + +void ShaderGraph::cubemap_input_node_set_value(ShaderType p_type,int p_id,const Ref<CubeMap>& p_cubemap){ + + 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]; + ERR_FAIL_COND(n.type!=NODE_CUBEMAP_INPUT); + n.param2=p_cubemap; + _request_update(); + +} + +Ref<CubeMap> ShaderGraph::cubemap_input_node_get_value(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,Ref<CubeMap>()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Ref<CubeMap>()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_CUBEMAP_INPUT,Ref<CubeMap>()); + return n.param2; + +} + + +void ShaderGraph::comment_node_set_text(ShaderType p_type,int p_id,const String& p_comment) { + + 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]; + ERR_FAIL_COND(n.type!=NODE_COMMENT); + n.param1=p_comment; + +} + +String ShaderGraph::comment_node_get_text(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,String()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),String()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_COMMENT,String()); + return n.param1; + +} + +void ShaderGraph::_request_update() { + + if (_pending_update_shader) + return; + + _pending_update_shader=true; + call_deferred("_update_shader"); + +} + +Variant ShaderGraph::node_get_state(ShaderType p_type,int p_id) const { + + ERR_FAIL_INDEX_V(p_type,3,Variant()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Variant()); + const Node& n = shader[p_type].node_map[p_id]; + Dictionary s; + s["pos"]=n.pos; + s["param1"]=n.param1; + s["param2"]=n.param2; + return s; + +} +void ShaderGraph::node_set_state(ShaderType p_type,int p_id,const Variant& p_state) { + + 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]; + Dictionary d = p_state; + ERR_FAIL_COND(!d.has("pos")); + ERR_FAIL_COND(!d.has("param1")); + ERR_FAIL_COND(!d.has("param2")); + n.pos=d["pos"]; + n.param1=d["param1"]; + n.param2=d["param2"]; + +} + +ShaderGraph::ShaderGraph(Mode p_mode) : Shader(p_mode) { + + //shader = VisualServer::get_singleton()->shader_create(); + _pending_update_shader=false; + Node out; + out.id=0; + out.pos=Vector2(250,20); + out.type=NODE_OUTPUT; + for(int i=0;i<3;i++) { + + shader[i].node_map.insert(0,out); } +} + +ShaderGraph::~ShaderGraph() { + //VisualServer::get_singleton()->free(shader); +} + + +const ShaderGraph::InOutParamInfo ShaderGraph::inout_param_info[]={ + //material vertex in + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Vertex","SRC_VERTEX","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Normal","SRC_NORMAL","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Tangent","SRC_TANGENT","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"BinormalF","SRC_BINORMALF","",SLOT_TYPE_SCALAR,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Color","SRC_COLOR","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Alpha","SRC_ALPHA","",SLOT_TYPE_SCALAR,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"UV","SRC_UV","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"UV2","SRC_UV2","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"WorldMatrix","WORLD_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"InvCameraMatrix","INV_CAMERA_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"ProjectionMatrix","PROJECTION_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"ModelviewMatrix","MODELVIEW_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"InstanceID","INSTANCE_ID","",SLOT_TYPE_SCALAR,SLOT_IN}, + + //material vertex out + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Vertex","VERTEX","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Normal","NORMAL","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Tangent","TANGENT","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Binormal","BINORMAL","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"UV","UV",".xy",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"UV2","UV2",".xy",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Color","COLOR.rgb","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Alpha","COLOR.a","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Var1","VAR1.rgb","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Var2","VAR2.rgb","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"SpecExp","SPEC_EXP","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"PointSize","POINT_SIZE","",SLOT_TYPE_SCALAR,SLOT_OUT}, + //pixel vertex in + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Vertex","VERTEX","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Position","POSITION.xyz","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Normal","IN_NORMAL","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Tangent","TANGENT","",SLOT_TYPE_VEC,SLOT_IN}, + {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,"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}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"InvCameraMatrix","INV_CAMERA_MATRIX","",SLOT_TYPE_XFORM,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Var1","VAR1.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Var2","VAR2.rgb","",SLOT_TYPE_VEC,SLOT_IN}, + //pixel vertex out + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Diffuse","DIFFUSE_OUT","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"DiffuseAlpha","ALPHA_OUT","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Specular","SPECULAR","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"SpecularExp","SPECULAR","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Emission","EMISSION","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Glow","GLOW","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"ShadeParam","SHADE_PARAM","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Normal","NORMAL","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"NormalMap","NORMALMAP","",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"NormalMapDepth","NORMALMAP_DEPTH","",SLOT_TYPE_SCALAR,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,"Discard","DISCARD",">0.5",SLOT_TYPE_SCALAR,SLOT_OUT}, + //light in + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"Normal","NORMAL","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"LightDir","LIGHT_DIR","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"LightDiffuse","LIGHT_DIFFUSE","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"LightSpecular","LIGHT_SPECULAR","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"EyeVec","EYE_VEC","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"Diffuse","DIFFUSE","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"Specular","SPECULAR","",SLOT_TYPE_VEC,SLOT_IN}, + {MODE_MATERIAL,SHADER_TYPE_LIGHT,"SpecExp","SPECULAR_EXP","",SLOT_TYPE_SCALAR,SLOT_IN}, + {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}, + //end + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,NULL,NULL,NULL,SLOT_TYPE_SCALAR,SLOT_OUT}, + +}; + +void ShaderGraph::get_input_output_node_slot_info(Mode p_mode, ShaderType p_type, List<SlotInfo> *r_slots) { + + const InOutParamInfo* iop = &inout_param_info[0]; + while(iop->name) { + if (p_mode==iop->shader_mode && p_type==iop->shader_type) { + + SlotInfo si; + si.dir=iop->dir; + si.name=iop->name; + si.type=iop->slot_type; + r_slots->push_back(si); + } + iop++; + } } -PropertyInfo ShaderGraph::shader_node_get_type_info(NodeType p_type) { - - switch(p_type) { - - case NODE_IN: return PropertyInfo(Variant::STRING,"in"); - case NODE_OUT: return PropertyInfo(Variant::STRING,"out"); - case NODE_CONSTANT: return PropertyInfo(Variant::REAL,"const"); - case NODE_PARAMETER: return PropertyInfo(Variant::STRING,"param"); - case NODE_ADD: return PropertyInfo(Variant::NIL,"add"); - case NODE_SUB: return PropertyInfo(Variant::NIL,"sub"); - case NODE_MUL: return PropertyInfo(Variant::NIL,"mul"); - case NODE_DIV: return PropertyInfo(Variant::NIL,"div"); - case NODE_MOD: return PropertyInfo(Variant::NIL,"rem"); - case NODE_SIN: return PropertyInfo(Variant::NIL,"sin"); - case NODE_COS: return PropertyInfo(Variant::NIL,"cos"); - case NODE_TAN: return PropertyInfo(Variant::NIL,"tan"); - case NODE_ARCSIN: return PropertyInfo(Variant::NIL,"arcsin"); - case NODE_ARCCOS: return PropertyInfo(Variant::NIL,"arccos"); - case NODE_ARCTAN: return PropertyInfo(Variant::NIL,"arctan"); - case NODE_POW: return PropertyInfo(Variant::NIL,"pow"); - case NODE_LOG: return PropertyInfo(Variant::NIL,"log"); - case NODE_MAX: return PropertyInfo(Variant::NIL,"max"); - case NODE_MIN: return PropertyInfo(Variant::NIL,"min"); - case NODE_COMPARE: return PropertyInfo(Variant::NIL,"cmp"); - case NODE_TEXTURE: return PropertyInfo(Variant::_RID,"texture1D",PROPERTY_HINT_RESOURCE_TYPE,"Texture"); - case NODE_TIME: return PropertyInfo(Variant::NIL,"time"); - case NODE_NOISE: return PropertyInfo(Variant::NIL,"noise"); - case NODE_PASS: return PropertyInfo(Variant::NIL,"pass"); - case NODE_VEC_IN: return PropertyInfo(Variant::STRING,"vin"); - case NODE_VEC_OUT: return PropertyInfo(Variant::STRING,"vout"); - case NODE_VEC_CONSTANT: return PropertyInfo(Variant::VECTOR3,"vconst"); - case NODE_VEC_PARAMETER: return PropertyInfo(Variant::STRING,"vparam"); - case NODE_VEC_ADD: return PropertyInfo(Variant::NIL,"vadd"); - case NODE_VEC_SUB: return PropertyInfo(Variant::NIL,"vsub"); - case NODE_VEC_MUL: return PropertyInfo(Variant::NIL,"vmul"); - case NODE_VEC_DIV: return PropertyInfo(Variant::NIL,"vdiv"); - case NODE_VEC_MOD: return PropertyInfo(Variant::NIL,"vrem"); - case NODE_VEC_CROSS: return PropertyInfo(Variant::NIL,"cross"); - case NODE_VEC_DOT: return PropertyInfo(Variant::NIL,"dot"); - case NODE_VEC_POW: return PropertyInfo(Variant::NIL,"vpow"); - case NODE_VEC_NORMALIZE: return PropertyInfo(Variant::NIL,"normalize"); - case NODE_VEC_INTERPOLATE: return PropertyInfo(Variant::NIL,"mix"); - case NODE_VEC_SCREEN_TO_UV: return PropertyInfo(Variant::NIL,"scrn2uv"); - case NODE_VEC_TRANSFORM3: return PropertyInfo(Variant::NIL,"xform3"); - case NODE_VEC_TRANSFORM4: return PropertyInfo(Variant::NIL,"xform4"); - case NODE_VEC_COMPARE: return PropertyInfo(Variant::_RID,"vcmp",PROPERTY_HINT_RESOURCE_TYPE,"Texture"); - case NODE_VEC_TEXTURE_2D: return PropertyInfo(Variant::_RID,"texture2D",PROPERTY_HINT_RESOURCE_TYPE,"Texture"); - case NODE_VEC_TEXTURE_CUBE: return PropertyInfo(Variant::NIL,"texcube"); - case NODE_VEC_NOISE: return PropertyInfo(Variant::NIL,"vec_noise"); - case NODE_VEC_0: return PropertyInfo(Variant::NIL,"vec_0"); - case NODE_VEC_1: return PropertyInfo(Variant::NIL,"vec_1"); - case NODE_VEC_2: return PropertyInfo(Variant::NIL,"vec_2"); - case NODE_VEC_BUILD: return PropertyInfo(Variant::NIL,"vbuild"); - case NODE_VEC_PASS: return PropertyInfo(Variant::NIL,"vpass"); - case NODE_COLOR_CONSTANT: return PropertyInfo(Variant::COLOR,"color_const"); - case NODE_COLOR_PARAMETER: return PropertyInfo(Variant::STRING,"color_param"); - case NODE_TEXTURE_PARAMETER: return PropertyInfo(Variant::STRING,"tex1D_param"); - case NODE_TEXTURE_2D_PARAMETER: return PropertyInfo(Variant::STRING,"tex2D_param"); - case NODE_TEXTURE_CUBE_PARAMETER: return PropertyInfo(Variant::STRING,"texcube_param"); - case NODE_TRANSFORM_CONSTANT: return PropertyInfo(Variant::TRANSFORM,"xform_const"); - case NODE_TRANSFORM_PARAMETER: return PropertyInfo(Variant::STRING,"xform_param"); - case NODE_LABEL: return PropertyInfo(Variant::STRING,"label"); - - default: {} +const ShaderGraph::NodeSlotInfo ShaderGraph::node_slot_info[]= { + + {NODE_SCALAR_CONST,{SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, //scalar constant + {NODE_VEC_CONST,{SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, //vec3 constant + {NODE_RGB_CONST,{SLOT_MAX},{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX}}, //rgb constant (shows a color picker instead) + {NODE_XFORM_CONST,{SLOT_MAX},{SLOT_TYPE_XFORM,SLOT_MAX}}, // 4x4 matrix constant + {NODE_TIME,{SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // time in seconds + {NODE_SCREEN_TEX,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // screen texture sampler (takes UV) (only usable in fragment shader) + {NODE_SCALAR_OP,{SLOT_TYPE_SCALAR,SLOT_TYPE_SCALAR,SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // scalar vs scalar op (mul,{SLOT_MAX},{SLOT_MAX}}, add,{SLOT_MAX},{SLOT_MAX}}, div,{SLOT_MAX},{SLOT_MAX}}, etc) + {NODE_VEC_OP,{SLOT_TYPE_VEC,SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // scalar vs scalar op (mul,{SLOT_MAX},{SLOT_MAX}}, add,{SLOT_MAX},{SLOT_MAX}}, div,{SLOT_MAX},{SLOT_MAX}}, etc) + {NODE_VEC_SCALAR_OP,{SLOT_TYPE_VEC,SLOT_TYPE_SCALAR,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // vec3 vs scalar op (mul,{SLOT_MAX},{SLOT_MAX}}, add,{SLOT_MAX},{SLOT_MAX}}, div,{SLOT_MAX},{SLOT_MAX}}, etc) + {NODE_RGB_OP,{SLOT_TYPE_VEC,SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // vec3 vs scalar op (mul,{SLOT_MAX},{SLOT_MAX}}, add,{SLOT_MAX},{SLOT_MAX}}, div,{SLOT_MAX},{SLOT_MAX}}, etc) + {NODE_XFORM_MULT,{SLOT_TYPE_XFORM,SLOT_TYPE_XFORM,SLOT_MAX},{SLOT_TYPE_XFORM,SLOT_MAX}}, // mat4 x mat4 + {NODE_XFORM_VEC_MULT,{SLOT_TYPE_XFORM,SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // mat4 x vec3 mult (with no-translation option) + {NODE_XFORM_VEC_INV_MULT,{SLOT_TYPE_VEC,SLOT_TYPE_XFORM,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // mat4 x vec3 inverse mult (with no-translation option) + {NODE_SCALAR_FUNC,{SLOT_TYPE_SCALAR,SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // scalar function (sin,{SLOT_MAX},{SLOT_MAX}}, cos,{SLOT_MAX},{SLOT_MAX}}, etc) + {NODE_VEC_FUNC,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_VEC,SLOT_MAX}}, // vector function (normalize,{SLOT_MAX},{SLOT_MAX}}, negate,{SLOT_MAX},{SLOT_MAX}}, reciprocal,{SLOT_MAX},{SLOT_MAX}}, rgb2hsv,{SLOT_MAX},{SLOT_MAX}}, hsv2rgb,{SLOT_MAX},{SLOT_MAX}}, etc,{SLOT_MAX},{SLOT_MAX}}, etc) + {NODE_VEC_LEN,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // vec3 length + {NODE_DOT_PROD,{SLOT_TYPE_VEC,SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_MAX}}, // vec3 . vec3 (dot product -> scalar output) + {NODE_VEC_TO_SCALAR,{SLOT_TYPE_VEC,SLOT_MAX},{SLOT_TYPE_SCALAR,SLOT_TYPE_SCALAR,SLOT_TYPE_SCALAR}}, // 1 vec3 input,{SLOT_MAX},{SLOT_MAX}}, 3 scalar outputs + {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_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_COMMENT,{SLOT_MAX},{SLOT_MAX}}, // comment + {NODE_TYPE_MAX,{SLOT_MAX},{SLOT_MAX}} +}; + +int ShaderGraph::get_node_input_slot_count(Mode p_mode, ShaderType p_shader_type,NodeType p_type) { + + if (p_type==NODE_INPUT || p_type==NODE_OUTPUT) { + + const InOutParamInfo* iop = &inout_param_info[0]; + int pc=0; + while(iop->name) { + if (p_mode==iop->shader_mode && p_shader_type==iop->shader_type) { + + if (iop->dir==SLOT_OUT) + pc++; + } + iop++; + } + return pc; + } else if (p_type==NODE_VEC_TO_XFORM){ + return 4; + } else if (p_type==NODE_XFORM_TO_VEC){ + return 1; + } else { + + const NodeSlotInfo*nsi=&node_slot_info[0]; + while(nsi->type!=NODE_TYPE_MAX) { + + if (nsi->type==p_type) { + int pc=0; + for(int i=0;i<NodeSlotInfo::MAX_INS;i++) { + if (nsi->ins[i]==SLOT_MAX) + break; + pc++; + } + return pc; + } + + nsi++; + } + + return 0; } +} + +int ShaderGraph::get_node_output_slot_count(Mode p_mode, ShaderType p_shader_type,NodeType p_type){ + + if (p_type==NODE_INPUT || p_type==NODE_OUTPUT) { + + const InOutParamInfo* iop = &inout_param_info[0]; + int pc=0; + while(iop->name) { + if (p_mode==iop->shader_mode && p_shader_type==iop->shader_type) { + + if (iop->dir==SLOT_IN) + pc++; + } + iop++; + } + return pc; + } else if (p_type==NODE_VEC_TO_XFORM){ + return 1; + } else if (p_type==NODE_XFORM_TO_VEC){ + return 4; + } else { + + const NodeSlotInfo*nsi=&node_slot_info[0]; + while(nsi->type!=NODE_TYPE_MAX) { + + if (nsi->type==p_type) { + int pc=0; + for(int i=0;i<NodeSlotInfo::MAX_OUTS;i++) { + if (nsi->outs[i]==SLOT_MAX) + break; + pc++; + } + return pc; + } + + nsi++; + } + + return 0; - ERR_FAIL_V( PropertyInfo(Variant::NIL,"error") ); -} -int ShaderGraph::shader_get_input_count(NodeType p_type) { - - switch(p_type) { - case NODE_IN: return 0; - case NODE_OUT: return 1; - case NODE_CONSTANT: return 0; - case NODE_PARAMETER: return 0; - case NODE_ADD: return 2; - case NODE_SUB: return 2; - case NODE_MUL: return 2; - case NODE_DIV: return 2; - case NODE_MOD: return 2; - case NODE_SIN: return 1; - case NODE_COS: return 1; - case NODE_TAN: return 1; - case NODE_ARCSIN: return 1; - case NODE_ARCCOS: return 1; - case NODE_ARCTAN: return 1; - case NODE_POW: return 2; - case NODE_LOG: return 1; - case NODE_MAX: return 2; - case NODE_MIN: return 2; - case NODE_COMPARE: return 4; - case NODE_TEXTURE: return 1; ///< param 0: texture - case NODE_TIME: return 1; ///< param 0: interval length - case NODE_NOISE: return 0; - case NODE_PASS: return 1; - case NODE_VEC_IN: return 0; ///< param 0: name - case NODE_VEC_OUT: return 1; ///< param 0: name - case NODE_VEC_CONSTANT: return 0; ///< param 0: value - case NODE_VEC_PARAMETER: return 0; ///< param 0: name - case NODE_VEC_ADD: return 2; - case NODE_VEC_SUB: return 2; - case NODE_VEC_MUL: return 2; - case NODE_VEC_DIV: return 2; - case NODE_VEC_MOD: return 2; - case NODE_VEC_CROSS: return 2; - case NODE_VEC_DOT: return 2; - case NODE_VEC_POW: return 2; - case NODE_VEC_NORMALIZE: return 1; - case NODE_VEC_INTERPOLATE: return 3; - case NODE_VEC_SCREEN_TO_UV: return 1; - case NODE_VEC_TRANSFORM3: return 4; - case NODE_VEC_TRANSFORM4: return 5; - case NODE_VEC_COMPARE: return 4; - case NODE_VEC_TEXTURE_2D: return 1; - case NODE_VEC_TEXTURE_CUBE: return 1; - case NODE_VEC_NOISE: return 0; - case NODE_VEC_0: return 1; - case NODE_VEC_1: return 1; - case NODE_VEC_2: return 1; - case NODE_VEC_BUILD: return 3; - case NODE_VEC_PASS: return 1; - case NODE_COLOR_CONSTANT: return 0; - case NODE_COLOR_PARAMETER: return 0; - case NODE_TEXTURE_PARAMETER: return 1; - case NODE_TEXTURE_2D_PARAMETER: return 1; - case NODE_TEXTURE_CUBE_PARAMETER: return 1; - case NODE_TRANSFORM_CONSTANT: return 1; - case NODE_TRANSFORM_PARAMETER: return 1; - case NODE_LABEL: return 0; - default: {} } - ERR_FAIL_V( 0 ); -} -int ShaderGraph::shader_get_output_count(NodeType p_type) { - - switch(p_type) { - case NODE_IN: return 1; - case NODE_OUT: return 0; - case NODE_CONSTANT: return 1; - case NODE_PARAMETER: return 1; - case NODE_ADD: return 1; - case NODE_SUB: return 1; - case NODE_MUL: return 1; - case NODE_DIV: return 1; - case NODE_MOD: return 1; - case NODE_SIN: return 1; - case NODE_COS: return 1; - case NODE_TAN: return 1; - case NODE_ARCSIN: return 1; - case NODE_ARCCOS: return 1; - case NODE_ARCTAN: return 1; - case NODE_POW: return 1; - case NODE_LOG: return 1; - case NODE_MAX: return 1; - case NODE_MIN: return 1; - case NODE_COMPARE: return 2; - case NODE_TEXTURE: return 3; ///< param 0: texture - case NODE_TIME: return 1; ///< param 0: interval length - case NODE_NOISE: return 1; - case NODE_PASS: return 1; - case NODE_VEC_IN: return 1; ///< param 0: name - case NODE_VEC_OUT: return 0; ///< param 0: name - case NODE_VEC_CONSTANT: return 1; ///< param 0: value - case NODE_VEC_PARAMETER: return 1; ///< param 0: name - case NODE_VEC_ADD: return 1; - case NODE_VEC_SUB: return 1; - case NODE_VEC_MUL: return 1; - case NODE_VEC_DIV: return 1; - case NODE_VEC_MOD: return 1; - case NODE_VEC_CROSS: return 1; - case NODE_VEC_DOT: return 1; - case NODE_VEC_POW: return 1; - case NODE_VEC_NORMALIZE: return 1; - case NODE_VEC_INTERPOLATE: return 1; - case NODE_VEC_SCREEN_TO_UV: return 1; - case NODE_VEC_TRANSFORM3: return 1; - case NODE_VEC_TRANSFORM4: return 1; - case NODE_VEC_COMPARE: return 2; - case NODE_VEC_TEXTURE_2D: return 3; - case NODE_VEC_TEXTURE_CUBE: return 3; - case NODE_VEC_NOISE: return 1; - case NODE_VEC_0: return 1; - case NODE_VEC_1: return 1; - case NODE_VEC_2: return 1; - case NODE_VEC_BUILD: return 1; - case NODE_VEC_PASS: return 1; - case NODE_COLOR_CONSTANT: return 2; - case NODE_COLOR_PARAMETER: return 2; - case NODE_TEXTURE_PARAMETER: return 3; - case NODE_TEXTURE_2D_PARAMETER: return 3; - case NODE_TEXTURE_CUBE_PARAMETER: return 3; - case NODE_TRANSFORM_CONSTANT: return 1; - case NODE_TRANSFORM_PARAMETER: return 1; - case NODE_LABEL: return 0; - - default: {} +} +ShaderGraph::SlotType ShaderGraph::get_node_input_slot_type(Mode p_mode, ShaderType p_shader_type,NodeType p_type,int p_idx){ + + if (p_type==NODE_INPUT || p_type==NODE_OUTPUT) { + + const InOutParamInfo* iop = &inout_param_info[0]; + int pc=0; + while(iop->name) { + if (p_mode==iop->shader_mode && p_shader_type==iop->shader_type) { + + if (iop->dir==SLOT_OUT) { + if (pc==p_idx) + return iop->slot_type; + pc++; + } + } + iop++; + } + ERR_FAIL_V(SLOT_MAX); + } else if (p_type==NODE_VEC_TO_XFORM){ + return SLOT_TYPE_VEC; + } else if (p_type==NODE_XFORM_TO_VEC){ + return SLOT_TYPE_XFORM; + } else { + + const NodeSlotInfo*nsi=&node_slot_info[0]; + while(nsi->type!=NODE_TYPE_MAX) { + + if (nsi->type==p_type) { + for(int i=0;i<NodeSlotInfo::MAX_INS;i++) { + + if (nsi->ins[i]==SLOT_MAX) + break; + if (i==p_idx) + return nsi->ins[i]; + } + } + + nsi++; + } + + ERR_FAIL_V(SLOT_MAX); + } - ERR_FAIL_V( 0 ); - -} - -#define RET2(m_a,m_b) if (p_idx==0) return m_a; else if (p_idx==1) return m_b; else return ""; -#define RET3(m_a,m_b,m_c) if (p_idx==0) return m_a; else if (p_idx==1) return m_b; else if (p_idx==2) return m_c; else return ""; -#define RET4(m_a,m_b,m_c,m_d) if (p_idx==0) return m_a; else if (p_idx==1) return m_b; else if (p_idx==2) return m_c; else if (p_idx==3) return m_d; else return ""; - -#define RET5(m_a,m_b,m_c,m_d,m_e) if (p_idx==0) return m_a; else if (p_idx==1) return m_b; else if (p_idx==2) return m_c; else if (p_idx==3) return m_d; else if (p_idx==4) return m_e; else return ""; - -String ShaderGraph::shader_get_input_name(NodeType p_type,int p_idx) { - - switch(p_type) { - - case NODE_IN: return ""; - case NODE_OUT: return "out"; - case NODE_CONSTANT: return ""; - case NODE_PARAMETER: return ""; - case NODE_ADD: RET2("a","b"); - case NODE_SUB: RET2("a","b"); - case NODE_MUL: RET2("a","b"); - case NODE_DIV: RET2("a","b"); - case NODE_MOD: RET2("a","b"); - case NODE_SIN: return "rad"; - case NODE_COS: return "rad"; - case NODE_TAN: return "rad"; - case NODE_ARCSIN: return "in"; - case NODE_ARCCOS: return "in"; - case NODE_ARCTAN: return "in"; - case NODE_POW: RET2("in","exp"); - case NODE_LOG: return "in"; - case NODE_MAX: return "in"; - case NODE_MIN: return "in"; - case NODE_COMPARE: RET4("a","b","ret1","ret2"); - case NODE_TEXTURE: return "u"; - case NODE_TIME: return ""; - case NODE_NOISE: return ""; - case NODE_PASS: return "in"; - case NODE_VEC_IN: return ""; - case NODE_VEC_OUT: return "out"; - case NODE_VEC_CONSTANT: return ""; - case NODE_VEC_PARAMETER: return ""; - case NODE_VEC_ADD: RET2("a","b"); - case NODE_VEC_SUB: RET2("a","b"); - case NODE_VEC_MUL: RET2("a","b"); - case NODE_VEC_DIV: RET2("a","b"); - case NODE_VEC_MOD: RET2("a","b"); - case NODE_VEC_CROSS: RET2("a","b"); - case NODE_VEC_DOT: RET2("a","b"); - case NODE_VEC_POW: RET2("a","b"); - case NODE_VEC_NORMALIZE: return "vec"; - case NODE_VEC_INTERPOLATE: RET3("a","b","c"); - case NODE_VEC_SCREEN_TO_UV: return "scr"; - case NODE_VEC_TRANSFORM3: RET4("in","col0","col1","col2"); - case NODE_VEC_TRANSFORM4: RET5("in","col0","col1","col2","col3"); - case NODE_VEC_COMPARE: RET4("a","b","ret1","ret2"); - case NODE_VEC_TEXTURE_2D: return "uv"; - case NODE_VEC_TEXTURE_CUBE: return "uvw"; - case NODE_VEC_NOISE: return ""; - case NODE_VEC_0: return "vec"; - case NODE_VEC_1: return "vec"; - case NODE_VEC_2: return "vec"; - case NODE_VEC_BUILD: RET3("x/r","y/g","z/b"); - case NODE_VEC_PASS: return "in"; - case NODE_COLOR_CONSTANT: return ""; - case NODE_COLOR_PARAMETER: return ""; - case NODE_TEXTURE_PARAMETER: return "u"; - case NODE_TEXTURE_2D_PARAMETER: return "uv"; - case NODE_TEXTURE_CUBE_PARAMETER: return "uvw"; - case NODE_TRANSFORM_CONSTANT: return "in"; - case NODE_TRANSFORM_PARAMETER: return "in"; - case NODE_LABEL: return ""; - - default: {} +} +ShaderGraph::SlotType ShaderGraph::get_node_output_slot_type(Mode p_mode, ShaderType p_shader_type,NodeType p_type,int p_idx){ + + if (p_type==NODE_INPUT || p_type==NODE_OUTPUT) { + + const InOutParamInfo* iop = &inout_param_info[0]; + int pc=0; + while(iop->name) { + if (p_mode==iop->shader_mode && p_shader_type==iop->shader_type) { + + if (iop->dir==SLOT_IN) { + if (pc==p_idx) + return iop->slot_type; + pc++; + } + } + iop++; + } + ERR_FAIL_V(SLOT_MAX); + } else if (p_type==NODE_VEC_TO_XFORM){ + return SLOT_TYPE_XFORM; + } else if (p_type==NODE_XFORM_TO_VEC){ + return SLOT_TYPE_VEC; + } else { + + const NodeSlotInfo*nsi=&node_slot_info[0]; + while(nsi->type!=NODE_TYPE_MAX) { + + if (nsi->type==p_type) { + for(int i=0;i<NodeSlotInfo::MAX_OUTS;i++) { + if (nsi->outs[i]==SLOT_MAX) + break; + if (i==p_idx) + return nsi->outs[i]; + } + } + + nsi++; + } + + ERR_FAIL_V(SLOT_MAX); } +} + + - ERR_FAIL_V(""); -} -String ShaderGraph::shader_get_output_name(NodeType p_type,int p_idx) { - - switch(p_type) { - - case NODE_IN: return "in"; - case NODE_OUT: return ""; - case NODE_CONSTANT: return "out"; - case NODE_PARAMETER: return "out"; - case NODE_ADD: return "sum"; - case NODE_SUB: return "dif"; - case NODE_MUL: return "prod"; - case NODE_DIV: return "quot"; - case NODE_MOD: return "rem"; - case NODE_SIN: return "out"; - case NODE_COS: return "out"; - case NODE_TAN: return "out"; - case NODE_ARCSIN: return "rad"; - case NODE_ARCCOS: return "rad"; - case NODE_ARCTAN: return "rad"; - case NODE_POW: RET2("in","exp"); - case NODE_LOG: return "out"; - case NODE_MAX: return "out"; - case NODE_MIN: return "out"; - case NODE_COMPARE: RET2("a/b","a/b"); - case NODE_TEXTURE: RET3("rgb","a","v"); - case NODE_TIME: return "out"; - case NODE_NOISE: return "out"; - case NODE_PASS: return "out"; - case NODE_VEC_IN: return "in"; - case NODE_VEC_OUT: return ""; - case NODE_VEC_CONSTANT: return "out"; - case NODE_VEC_PARAMETER: return "out"; - case NODE_VEC_ADD: return "sum"; - case NODE_VEC_SUB: return "sub"; - case NODE_VEC_MUL: return "mul"; - case NODE_VEC_DIV: return "div"; - case NODE_VEC_MOD: return "rem"; - case NODE_VEC_CROSS: return "crs"; - case NODE_VEC_DOT: return "prod"; - case NODE_VEC_POW: return "out"; - case NODE_VEC_NORMALIZE: return "norm"; - case NODE_VEC_INTERPOLATE: return "out"; - case NODE_VEC_SCREEN_TO_UV: return "uv"; - case NODE_VEC_TRANSFORM3: return "prod"; - case NODE_VEC_TRANSFORM4: return "prod"; - case NODE_VEC_COMPARE: RET2("a/b","a/b"); - case NODE_VEC_TEXTURE_2D: RET3("rgb","a","v"); - case NODE_VEC_TEXTURE_CUBE: RET3("rgb","a","v"); - case NODE_VEC_NOISE: return "out"; - case NODE_VEC_0: return "x/r"; - case NODE_VEC_1: return "y/g"; - case NODE_VEC_2: return "z/b"; - case NODE_VEC_BUILD: return "vec"; - case NODE_VEC_PASS: return "out"; - case NODE_COLOR_CONSTANT: RET2("rgb","a"); - case NODE_COLOR_PARAMETER: RET2("rgb","a"); - case NODE_TEXTURE_PARAMETER: RET3("rgb","a","v"); - case NODE_TEXTURE_2D_PARAMETER: RET3("rgb","a","v"); - case NODE_TEXTURE_CUBE_PARAMETER: RET3("rgb","a","v"); - case NODE_TRANSFORM_CONSTANT: return "out"; - case NODE_TRANSFORM_PARAMETER: return "out"; - case NODE_LABEL: return ""; - - default: {} + + +void ShaderGraph::_update_shader() { + + + String code[3]; + + List<StringName> names; + get_default_texture_param_list(&names); + + for (List<StringName>::Element *E=names.front();E;E=E->next()) { + set_default_texture_param(E->get(),Ref<Texture>()); } - ERR_FAIL_V(""); -} -bool ShaderGraph::shader_is_input_vector(NodeType p_type,int p_input) { - - switch(p_type) { - - case NODE_IN: return false; - case NODE_OUT: return false; - case NODE_CONSTANT: return false; - case NODE_PARAMETER: return false; - case NODE_ADD: return false; - case NODE_SUB: return false; - case NODE_MUL: return false; - case NODE_DIV: return false; - case NODE_MOD: return false; - case NODE_SIN: return false; - case NODE_COS: return false; - case NODE_TAN: return false; - case NODE_ARCSIN: return false; - case NODE_ARCCOS: return false; - case NODE_ARCTAN: return false; - case NODE_POW: return false; - case NODE_LOG: return false; - case NODE_MAX: return false; - case NODE_MIN: return false; - case NODE_COMPARE: return false; - case NODE_TEXTURE: return false; - case NODE_TIME: return false; - case NODE_NOISE: return false; - case NODE_PASS: return false; - case NODE_VEC_IN: return false; - case NODE_VEC_OUT: return true; - case NODE_VEC_CONSTANT: return false; - case NODE_VEC_PARAMETER: return false; - case NODE_VEC_ADD: return true; - case NODE_VEC_SUB: return true; - case NODE_VEC_MUL: return true; - case NODE_VEC_DIV: return true; - case NODE_VEC_MOD: return true; - case NODE_VEC_CROSS: return true; - case NODE_VEC_DOT: return true; - case NODE_VEC_POW: return (p_input==0)?true:false; - case NODE_VEC_NORMALIZE: return true; - case NODE_VEC_INTERPOLATE: return (p_input<2)?true:false; - case NODE_VEC_SCREEN_TO_UV: return true; - case NODE_VEC_TRANSFORM3: return true; - case NODE_VEC_TRANSFORM4: return true; - case NODE_VEC_COMPARE: return (p_input<2)?false:true; - case NODE_VEC_TEXTURE_2D: return true; - case NODE_VEC_TEXTURE_CUBE: return true; - case NODE_VEC_NOISE: return false; - case NODE_VEC_0: return true; - case NODE_VEC_1: return true; - case NODE_VEC_2: return true; - case NODE_VEC_BUILD: return false; - case NODE_VEC_PASS: return true; - case NODE_COLOR_CONSTANT: return false; - case NODE_COLOR_PARAMETER: return false; - case NODE_TEXTURE_PARAMETER: return false; - case NODE_TEXTURE_2D_PARAMETER: return true; - case NODE_TEXTURE_CUBE_PARAMETER: return true; - case NODE_TRANSFORM_CONSTANT: return true; - case NODE_TRANSFORM_PARAMETER: return true; - case NODE_LABEL: return false; - - default: {} + + for(int i=0;i<3;i++) { + + int idx=0; + for (Map<int,Node>::Element *E=shader[i].node_map.front();E;E=E->next()) { + + E->get().sort_order=idx++; + } + //simple method for graph solving using bubblesort derived algorithm + int iters=0; + int iter_max=shader[i].node_map.size()*shader[i].node_map.size(); + + while(true) { + if (iters>iter_max) + break; + + int swaps=0; + for (Map<int,Node>::Element *E=shader[i].node_map.front();E;E=E->next()) { + + for(Map<int,SourceSlot>::Element *F=E->get().connections.front();F;F=F->next()) { + + //this is kinda slow, could be sped up + Map<int,Node>::Element *G = shader[i].node_map.find(F->get().id); + ERR_FAIL_COND(!G); + if (G->get().sort_order > E->get().sort_order) { + + SWAP(G->get().sort_order,E->get().sort_order); + swaps++; + } + } + } + + iters++; + if (swaps==0) { + iters=0; + break; + } + } + + if (iters>0) { + + shader[i].error=GRAPH_ERROR_CYCLIC; + continue; + } + + Vector<Node*> order; + order.resize(shader[i].node_map.size()); + + for (Map<int,Node>::Element *E=shader[i].node_map.front();E;E=E->next()) { + + order[E->get().sort_order]=&E->get(); + } + + //generate code for the ordered graph + bool failed=false; + + if (i==SHADER_TYPE_FRAGMENT && get_mode()==MODE_MATERIAL) { + code[i]+="vec3 DIFFUSE_OUT=vec3(0,0,0);\n"; + code[i]+="float ALPHA_OUT=0;\n"; + } + + + Map<String,String> inputs_xlate; + Map<String,String> input_names_xlate; + Set<String> inputs_used; + + for(int j=0;j<order.size();j++) { + + Node *n=order[j]; + if (n->type==NODE_INPUT) { + + const InOutParamInfo* iop = &inout_param_info[0]; + int idx=0; + while(iop->name) { + if (get_mode()==iop->shader_mode && i==iop->shader_type && SLOT_IN==iop->dir) { + + const char *typestr[4]={"float","vec3","mat4","texture"}; + + String vname=("nd"+itos(n->id)+"sl"+itos(idx)); + inputs_xlate[vname]=String(typestr[iop->slot_type])+" "+vname+"="+iop->variable+";\n"; + input_names_xlate[vname]=iop->variable; + idx++; + } + iop++; + } + + } else if (n->type==NODE_OUTPUT) { + + + bool use_alpha=false; + const InOutParamInfo* iop = &inout_param_info[0]; + int idx=0; + while(iop->name) { + if (get_mode()==iop->shader_mode && i==iop->shader_type && SLOT_OUT==iop->dir) { + + if (n->connections.has(idx)) { + String iname=("nd"+itos(n->connections[idx].id)+"sl"+itos(n->connections[idx].slot)); + if (node_get_type(ShaderType(i),n->connections[idx].id)==NODE_INPUT) + inputs_used.insert(iname); + code[i]+=String(iop->variable)+"="+iname+String(iop->postfix)+";\n"; + if (i==SHADER_TYPE_FRAGMENT && get_mode()==MODE_MATERIAL && String(iop->name)=="DiffuseAlpha") + use_alpha=true; + } + idx++; + } + iop++; + } + + if (i==SHADER_TYPE_FRAGMENT && get_mode()==MODE_MATERIAL) { + + if (use_alpha) { + code[i]+="DIFFUSE_ALPHA=vec4(DIFFUSE_OUT,ALPHA_OUT);\n"; + } else { + code[i]+="DIFFUSE=DIFFUSE_OUT;\n"; + } + } + + } else { + Vector<String> inputs; + int max = get_node_input_slot_count(get_mode(),ShaderType(i),n->type); + for(int k=0;k<max;k++) { + if (!n->connections.has(k)) { + shader[i].error=GRAPH_ERROR_MISSING_CONNECTIONS; + failed=true; + break; + } + String iname="nd"+itos(n->connections[k].id)+"sl"+itos(n->connections[k].slot); + inputs.push_back(iname); + if (node_get_type(ShaderType(i),n->connections[k].id)==NODE_INPUT) { + inputs_used.insert(iname); + } + + } + + if (failed) + break; + + if (n->type==NODE_TEXTURE_INPUT || n->type==NODE_CUBEMAP_INPUT) { + + set_default_texture_param(n->param1,n->param2); + } + _add_node_code(ShaderType(i),n,inputs,code[i]); + } + + } + + if (failed) + continue; + + + for(Set<String>::Element *E=inputs_used.front();E;E=E->next()) { + + ERR_CONTINUE( !inputs_xlate.has(E->get())); + code[i]=inputs_xlate[E->get()]+code[i]; + String name=input_names_xlate[E->get()]; + + if (i==SHADER_TYPE_VERTEX && get_mode()==MODE_MATERIAL) { + if (name==("SRC_COLOR")) + code[i]="vec3 SRC_COLOR=COLOR.rgb;\n"+code[i]; + if (name==("SRC_ALPHA")) + code[i]="float SRC_ALPHA=COLOR.a;\n"+code[i]; + if (name==("SRC_UV")) + code[i]="vec3 SRC_UV=vec3(UV,0);\n"+code[i]; + if (name==("SRC_UV2")) + code[i]="float SRC_UV2=vec3(UV2,0);\n"+code[i]; + } else if (i==SHADER_TYPE_FRAGMENT && get_mode()==MODE_MATERIAL) { + if (name==("IN_NORMAL")) + code[i]="vec3 IN_NORMAL=NORMAL;\n"+code[i]; + } + + } + + + + shader[i].error=GRAPH_OK; + + } + + bool all_ok=true; + for(int i=0;i<3;i++) { + if (shader[i].error!=GRAPH_OK) + all_ok=false; } - ERR_FAIL_V(false); -} -bool ShaderGraph::shader_is_output_vector(NodeType p_type,int p_input) { - - switch(p_type) { - - case NODE_IN: return false; - case NODE_OUT: return false ; - case NODE_CONSTANT: return false; - case NODE_PARAMETER: return false; - case NODE_ADD: return false; - case NODE_SUB: return false; - case NODE_MUL: return false; - case NODE_DIV: return false; - case NODE_MOD: return false; - case NODE_SIN: return false; - case NODE_COS: return false; - case NODE_TAN: return false; - case NODE_ARCSIN: return false; - case NODE_ARCCOS: return false; - case NODE_ARCTAN: return false; - case NODE_POW: return false; - case NODE_LOG: return false; - case NODE_MAX: return false; - case NODE_MIN: return false; - case NODE_COMPARE: return false; - case NODE_TEXTURE: return false; - case NODE_TIME: return false; - case NODE_NOISE: return false; - case NODE_PASS: return false; - case NODE_VEC_IN: return true; - case NODE_VEC_OUT: return false; - case NODE_VEC_CONSTANT: return true; - case NODE_VEC_PARAMETER: return true; - case NODE_VEC_ADD: return true; - case NODE_VEC_SUB: return true; - case NODE_VEC_MUL: return true; - case NODE_VEC_DIV: return true; - case NODE_VEC_MOD: return true; - case NODE_VEC_CROSS: return true; - case NODE_VEC_DOT: return false; - case NODE_VEC_POW: return true; - case NODE_VEC_NORMALIZE: return true; - case NODE_VEC_INTERPOLATE: return true; - case NODE_VEC_SCREEN_TO_UV: return true; - case NODE_VEC_TRANSFORM3: return true; - case NODE_VEC_TRANSFORM4: return true; - case NODE_VEC_COMPARE: return true; - case NODE_VEC_TEXTURE_2D: return (p_input==0)?true:false; - case NODE_VEC_TEXTURE_CUBE: return (p_input==0)?true:false; - case NODE_VEC_NOISE: return true; - case NODE_VEC_0: return false; - case NODE_VEC_1: return false; - case NODE_VEC_2: return false; - case NODE_VEC_BUILD: return true; - case NODE_VEC_PASS: return true; - case NODE_COLOR_CONSTANT: return (p_input==0)?true:false; - case NODE_COLOR_PARAMETER: return (p_input==0)?true:false; - case NODE_TEXTURE_PARAMETER: return (p_input==0)?true:false; - case NODE_TEXTURE_2D_PARAMETER: return (p_input==0)?true:false; - case NODE_TEXTURE_CUBE_PARAMETER: return (p_input==0)?true:false; - case NODE_TRANSFORM_CONSTANT: return true; - case NODE_TRANSFORM_PARAMETER: return true; - case NODE_LABEL: return false; - - default: {} + if (all_ok) { + set_code(code[0],code[1],code[2]); } + //do shader here - ERR_FAIL_V(""); + _pending_update_shader=false; + emit_signal(SceneStringNames::get_singleton()->updated); } -#endif -#endif +void ShaderGraph::_add_node_code(ShaderType p_type,Node *p_node,const Vector<String>& p_inputs,String& code) { + + + const char *typestr[4]={"float","vec3","mat4","texture"}; +#define OUTNAME(id,slot) (String(typestr[get_node_output_slot_type(get_mode(),p_type,p_node->type,slot)])+" "+("nd"+itos(id)+"sl"+itos(slot))) +#define OUTVAR(id,slot) ("nd"+itos(id)+"sl"+itos(slot)) + + switch(p_node->type) { + + case NODE_INPUT: { + + + }break; + case NODE_SCALAR_CONST: { + + double scalar = p_node->param1; + code+=OUTNAME(p_node->id,0)+"="+rtos(scalar)+";\n"; + }break; + case NODE_VEC_CONST: { + Vector3 vec = p_node->param1; + code+=OUTNAME(p_node->id,0)+"=vec3("+rtos(vec.x)+","+rtos(vec.y)+","+rtos(vec.z)+");\n"; + }break; + case NODE_RGB_CONST: { + Color col = p_node->param1; + code+=OUTNAME(p_node->id,0)+"=vec3("+rtos(col.r)+","+rtos(col.g)+","+rtos(col.b)+");\n"; + code+=OUTNAME(p_node->id,1)+"="+rtos(col.a)+";\n"; + }break; + case NODE_XFORM_CONST: { + + Transform xf = p_node->param1; + code+=OUTNAME(p_node->id,0)+"=mat4(\n"; + code+="\tvec4(vec3("+rtos(xf.basis.get_axis(0).x)+","+rtos(xf.basis.get_axis(0).y)+","+rtos(xf.basis.get_axis(0).z)+"),0),\n"; + code+="\tvec4(vec3("+rtos(xf.basis.get_axis(1).x)+","+rtos(xf.basis.get_axis(1).y)+","+rtos(xf.basis.get_axis(1).z)+"),0),\n"; + code+="\tvec4(vec3("+rtos(xf.basis.get_axis(2).x)+","+rtos(xf.basis.get_axis(2).y)+","+rtos(xf.basis.get_axis(2).z)+"),0),\n"; + code+="\tvec4(vec3("+rtos(xf.origin.x)+","+rtos(xf.origin.y)+","+rtos(xf.origin.z)+"),1)\n"; + code+=");"; + + }break; + case NODE_TIME: { + code+=OUTNAME(p_node->id,0)+"=TIME;\n"; + }break; + case NODE_SCREEN_TEX: { + code+=OUTNAME(p_node->id,0)+"=texscreen("+p_inputs[0]+");\n"; + }break; + case NODE_SCALAR_OP: { + int op = p_node->param1; + String optxt; + switch(op) { + + case SCALAR_OP_ADD: optxt = p_inputs[0]+"+"+p_inputs[1]+";"; break; + case SCALAR_OP_SUB: optxt = p_inputs[0]+"-"+p_inputs[1]+";"; break; + case SCALAR_OP_MUL: optxt = p_inputs[0]+"*"+p_inputs[1]+";"; break; + case SCALAR_OP_DIV: optxt = p_inputs[0]+"/"+p_inputs[1]+";"; break; + case SCALAR_OP_MOD: optxt = "mod("+p_inputs[0]+","+p_inputs[1]+");"; break; + case SCALAR_OP_POW: optxt = "pow("+p_inputs[0]+","+p_inputs[1]+");"; break; + case SCALAR_OP_MAX: optxt = "max("+p_inputs[0]+","+p_inputs[1]+");"; break; + case SCALAR_OP_MIN: optxt = "min("+p_inputs[0]+","+p_inputs[1]+");"; break; + case SCALAR_OP_ATAN2: optxt = "atan2("+p_inputs[0]+","+p_inputs[1]+");"; break; + + } + code+=OUTNAME(p_node->id,0)+"="+optxt+"\n";; + + }break; + case NODE_VEC_OP: { + int op = p_node->param1; + String optxt; + switch(op) { + case VEC_OP_ADD: optxt = p_inputs[0]+"+"+p_inputs[1]+";"; break; + case VEC_OP_SUB: optxt = p_inputs[0]+"-"+p_inputs[1]+";"; break; + case VEC_OP_MUL: optxt = p_inputs[0]+"*"+p_inputs[1]+";"; break; + case VEC_OP_DIV: optxt = p_inputs[0]+"/"+p_inputs[1]+";"; break; + case VEC_OP_MOD: optxt = "mod("+p_inputs[0]+","+p_inputs[1]+");"; break; + case VEC_OP_POW: optxt = "pow("+p_inputs[0]+","+p_inputs[1]+");"; break; + case VEC_OP_MAX: optxt = "max("+p_inputs[0]+","+p_inputs[1]+");"; break; + case VEC_OP_MIN: optxt = "min("+p_inputs[0]+","+p_inputs[1]+");"; break; + case VEC_OP_CROSS: optxt = "cross("+p_inputs[0]+","+p_inputs[1]+");"; break; + } + code+=OUTNAME(p_node->id,0)+"="+optxt+"\n"; + + }break; + case NODE_VEC_SCALAR_OP: { + int op = p_node->param1; + String optxt; + switch(op) { + case VEC_SCALAR_OP_MUL: optxt = p_inputs[0]+"*"+p_inputs[1]+";"; break; + case VEC_SCALAR_OP_DIV: optxt = p_inputs[0]+"/"+p_inputs[1]+";"; break; + case VEC_SCALAR_OP_POW: optxt = "pow("+p_inputs[0]+","+p_inputs[1]+");"; break; + } + code+=OUTNAME(p_node->id,0)+"="+optxt+"\n"; + + }break; + case NODE_RGB_OP: { + + int op = p_node->param1; + static const char*axisn[3]={"x","y","z"}; + switch(op) { + case RGB_OP_SCREEN: { + + code += OUTNAME(p_node->id,0)+"=vec3(1.0)-(vec3(1.0)-"+p_inputs[0]+")*(vec3(1.0)-"+p_inputs[1]+");\n"; + } break; + case RGB_OP_DIFFERENCE: { + + code += OUTNAME(p_node->id,0)+"=abs("+p_inputs[0]+"-"+p_inputs[1]+");\n"; + + } break; + case RGB_OP_DARKEN: { + + code += OUTNAME(p_node->id,0)+"=min("+p_inputs[0]+","+p_inputs[1]+");\n"; + } break; + case RGB_OP_LIGHTEN: { + + code += OUTNAME(p_node->id,0)+"=max("+p_inputs[0]+","+p_inputs[1]+");\n"; + + } break; + case RGB_OP_OVERLAY: { + + code += OUTNAME(p_node->id,0)+";\n"; + for(int i=0;i<3;i++) { + code += "{\n"; + code += "\tfloat base="+p_inputs[0]+"."+axisn[i]+";\n"; + code += "\tfloat blend="+p_inputs[1]+"."+axisn[i]+";\n"; + code += "\tif (base < 0.5) {\n"; + code += "\t\t"+OUTVAR(p_node->id,0)+"."+axisn[i]+" = 2.0 * base * blend;\n"; + code += "\t} else {\n"; + code += "\t\t"+OUTVAR(p_node->id,0)+"."+axisn[i]+" = 1.0 - 2.0 * (1.0 - blend) * (1.0 - base);\n"; + code += "\t}\n"; + code += "}\n"; + } + + } break; + case RGB_OP_DODGE: { + + code += OUTNAME(p_node->id,0)+"=("+p_inputs[0]+")/(vec3(1.0)-"+p_inputs[1]+");\n"; + + } break; + case RGB_OP_BURN: { + + code += OUTNAME(p_node->id,0)+"=vec3(1.0)-(vec3(1.0)-"+p_inputs[0]+")/("+p_inputs[1]+");\n"; + } break; + case RGB_OP_SOFT_LIGHT: { + + code += OUTNAME(p_node->id,0)+";\n"; + for(int i=0;i<3;i++) { + code += "{\n"; + code += "\tfloat base="+p_inputs[0]+"."+axisn[i]+";\n"; + code += "\tfloat blend="+p_inputs[1]+"."+axisn[i]+";\n"; + code += "\tif (base < 0.5) {\n"; + code += "\t\t"+OUTVAR(p_node->id,0)+"."+axisn[i]+" = (base * (blend+0.5));\n"; + code += "\t} else {\n"; + code += "\t\t"+OUTVAR(p_node->id,0)+"."+axisn[i]+" = (1 - (1-base) * (1-(blend-0.5)));\n"; + code += "\t}\n"; + code += "}\n"; + } + + } break; + case RGB_OP_HARD_LIGHT: { + + code += OUTNAME(p_node->id,0)+";\n"; + for(int i=0;i<3;i++) { + code += "{\n"; + code += "\tfloat base="+p_inputs[0]+"."+axisn[i]+";\n"; + code += "\tfloat blend="+p_inputs[1]+"."+axisn[i]+";\n"; + code += "\tif (base < 0.5) {\n"; + code += "\t\t"+OUTVAR(p_node->id,0)+"."+axisn[i]+" = (base * (2*blend));\n"; + code += "\t} else {\n"; + code += "\t\t"+OUTVAR(p_node->id,0)+"."+axisn[i]+" = (1 - (1-base) * (1-2*(blend-0.5)));\n"; + code += "\t}\n"; + code += "}\n"; + } + + } break; + } + }break; + case NODE_XFORM_MULT: { + + code += OUTNAME(p_node->id,0)+"="+p_inputs[0]+"*"+p_inputs[1]+";\n"; + + }break; + case NODE_XFORM_VEC_MULT: { + + bool no_translation = p_node->param1; + if (no_translation) { + code += OUTNAME(p_node->id,0)+"=("+p_inputs[0]+"*vec4("+p_inputs[1]+",0)).xyz;\n"; + } else { + code += OUTNAME(p_node->id,0)+"=("+p_inputs[0]+"*vec4("+p_inputs[1]+",1)).xyz;\n"; + } + + }break; + case NODE_XFORM_VEC_INV_MULT: { + bool no_translation = p_node->param1; + if (no_translation) { + code += OUTNAME(p_node->id,0)+"=("+p_inputs[1]+"*vec4("+p_inputs[0]+",0)).xyz;\n"; + } else { + code += OUTNAME(p_node->id,0)+"=("+p_inputs[1]+"*vec4("+p_inputs[0]+",1)).xyz;\n"; + } + }break; + case NODE_SCALAR_FUNC: { + static const char*scalar_func_id[SCALAR_MAX_FUNC]={ + "sin($)", + "cos($)", + "tan($)", + "asin($)", + "acos($)", + "atan($)", + "sinh($)", + "cosh($)", + "tanh($)", + "log($)", + "exp($)", + "sqrt($)", + "abs($)", + "sign($)", + "floor($)", + "round($)", + "ceil($)", + "frac($)", + "min(max($,0),1)", + "-($)", + }; + + int func = p_node->param1; + ERR_FAIL_INDEX(func,SCALAR_MAX_FUNC); + code += OUTNAME(p_node->id,0)+"="+String(scalar_func_id[func]).replace("$",p_inputs[0])+";\n"; + + } break; + case NODE_VEC_FUNC: { + static const char*vec_func_id[VEC_MAX_FUNC]={ + "normalize($)", + "max(min($,vec3(1,1,1)),vec3(0,0,0))", + "-($)", + "1.0/($)", + "", + "", + }; + + + int func = p_node->param1; + ERR_FAIL_INDEX(func,VEC_MAX_FUNC); + if (func==VEC_FUNC_RGB2HSV) { + code += OUTNAME(p_node->id,0)+";\n"; + code+="{\n"; + code+="\tvec3 c = "+p_inputs[0]+";\n"; + code+="\tvec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n"; + code+="\tvec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n"; + code+="\tvec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n"; + code+="\tfloat d = q.x - min(q.w, q.y);\n"; + code+="\tfloat e = 1.0e-10;\n"; + code+="\t"+OUTVAR(p_node->id,0)+"=vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n"; + code+="}\n"; + } else if (func==VEC_FUNC_HSV2RGB) { + code += OUTNAME(p_node->id,0)+";\n";; + code+="{\n"; + code+="\tvec3 c = "+p_inputs[0]+";\n"; + code+="\tvec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n"; + code+="\tvec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n"; + code+="\t"+OUTVAR(p_node->id,0)+"=c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n"; + code+="}\n"; + + } else { + code += OUTNAME(p_node->id,0)+"="+String(vec_func_id[func]).replace("$",p_inputs[0])+";\n"; + } + }break; + case NODE_VEC_LEN: { + + code += OUTNAME(p_node->id,0)+"=length("+p_inputs[1]+");\n"; + + }break; + case NODE_DOT_PROD: { + code += OUTNAME(p_node->id,0)+"=dot("+p_inputs[1]+","+p_inputs[0]+");\n"; + + }break; + case NODE_VEC_TO_SCALAR: { + code += OUTNAME(p_node->id,0)+"="+p_inputs[0]+".x;\n"; + code += OUTNAME(p_node->id,1)+"="+p_inputs[0]+".y;\n"; + code += OUTNAME(p_node->id,2)+"="+p_inputs[0]+".z;\n"; + + }break; + case NODE_SCALAR_TO_VEC: { + code += OUTNAME(p_node->id,0)+"=vec3("+p_inputs[0]+","+p_inputs[1]+","+p_inputs[2]+""+");\n"; + + }break; + case NODE_VEC_TO_XFORM: { + code += OUTNAME(p_node->id,0)+"=xform("+p_inputs[0]+","+p_inputs[1]+","+p_inputs[2]+","+","+p_inputs[3]+");\n"; + + }break; + case NODE_XFORM_TO_VEC: { + code += OUTNAME(p_node->id,0)+"="+p_inputs[0]+".x;\n"; + code += OUTNAME(p_node->id,1)+"="+p_inputs[0]+".y;\n"; + code += OUTNAME(p_node->id,2)+"="+p_inputs[0]+".z;\n"; + code += OUTNAME(p_node->id,3)+"="+p_inputs[0]+".o;\n"; + }break; + case NODE_SCALAR_INTERP: { + + code += OUTNAME(p_node->id,0)+"=mix("+p_inputs[0]+","+p_inputs[1]+","+p_inputs[2]+");\n"; + + }break; + case NODE_VEC_INTERP: { + code += OUTNAME(p_node->id,0)+"=mix("+p_inputs[0]+","+p_inputs[1]+","+p_inputs[2]+");\n"; + + }break; + case NODE_SCALAR_INPUT: { + String name = p_node->param1; + float dv=p_node->param2; + code +="uniform float "+name+"="+rtos(dv)+";\n"; + code += OUTNAME(p_node->id,0)+"="+name+";\n"; + }break; + case NODE_VEC_INPUT: { + + String name = p_node->param1; + Vector3 dv=p_node->param2; + code +="uniform float "+name+"=vec3("+rtos(dv.x)+","+rtos(dv.y)+","+rtos(dv.z)+");\n"; + code += OUTNAME(p_node->id,0)+"="+name+";\n"; + }break; + case NODE_RGB_INPUT: { + + String name = p_node->param1; + Color dv= p_node->param2; + + code +="uniform color "+name+"=vec4("+rtos(dv.r)+","+rtos(dv.g)+","+rtos(dv.g)+","+rtos(dv.a)+");\n"; + code += OUTNAME(p_node->id,0)+"="+name+".rgb;\n"; + + }break; + case NODE_XFORM_INPUT: { + + String name = p_node->param1; + Transform dv= p_node->param2; + + code +="uniform mat4 "+name+"=mat4(\n"; + code+="\tvec4(vec3("+rtos(dv.basis.get_axis(0).x)+","+rtos(dv.basis.get_axis(0).y)+","+rtos(dv.basis.get_axis(0).z)+"),0),\n"; + code+="\tvec4(vec3("+rtos(dv.basis.get_axis(1).x)+","+rtos(dv.basis.get_axis(1).y)+","+rtos(dv.basis.get_axis(1).z)+"),0),\n"; + code+="\tvec4(vec3("+rtos(dv.basis.get_axis(2).x)+","+rtos(dv.basis.get_axis(2).y)+","+rtos(dv.basis.get_axis(2).z)+"),0),\n"; + code+="\tvec4(vec3("+rtos(dv.origin.x)+","+rtos(dv.origin.y)+","+rtos(dv.origin.z)+"),1)\n"; + code+=");"; + + code += OUTNAME(p_node->id,0)+"="+name+";\n"; + + }break; + case NODE_TEXTURE_INPUT: { + String name = p_node->param1; + String rname="rt_read_tex"+itos(p_node->id); + code +="uniform texture "+name+";"; + code +="vec4 "+rname+"=tex("+name+","+p_inputs[0]+".xy);\n"; + code += OUTNAME(p_node->id,0)+"="+rname+".rgb;\n"; + code += OUTNAME(p_node->id,1)+"="+rname+".a;\n"; + + }break; + case NODE_CUBEMAP_INPUT: { + + String name = p_node->param1; + code +="uniform cubemap "+name+";"; + String rname="rt_read_tex"+itos(p_node->id); + code +="vec4 "+rname+"=texcube("+name+","+p_inputs[0]+".xy);\n"; + code += OUTNAME(p_node->id,0)+"="+rname+".rgb;\n"; + code += OUTNAME(p_node->id,1)+"="+rname+".a;\n"; + }break; + case NODE_OUTPUT: { + + + }break; + case NODE_COMMENT: { + + }break; + case NODE_TYPE_MAX: { + + } + } +} diff --git a/scene/resources/shader_graph.h b/scene/resources/shader_graph.h index e20e010c6b..55d09b4c38 100644 --- a/scene/resources/shader_graph.h +++ b/scene/resources/shader_graph.h @@ -29,87 +29,54 @@ #ifndef SHADER_GRAPH_H #define SHADER_GRAPH_H -#if 0 + #include "map.h" #include "scene/resources/shader.h" -class ShaderGraph : public Resource { +class ShaderGraph : public Shader { - OBJ_TYPE( ShaderGraph, Resource ); + OBJ_TYPE( ShaderGraph, Shader ); RES_BASE_EXTENSION("sgp"); public: enum NodeType { - NODE_IN, ///< param 0: name - NODE_OUT, ///< param 0: name - NODE_CONSTANT, ///< param 0: value - NODE_PARAMETER, ///< param 0: name - NODE_ADD, - NODE_SUB, - NODE_MUL, - NODE_DIV, - NODE_MOD, - NODE_SIN, - NODE_COS, - NODE_TAN, - NODE_ARCSIN, - NODE_ARCCOS, - NODE_ARCTAN, - NODE_POW, - NODE_LOG, - NODE_MAX, - NODE_MIN, - NODE_COMPARE, - NODE_TEXTURE, ///< param 0: texture - NODE_TIME, ///< param 0: interval length - NODE_NOISE, - NODE_PASS, - NODE_VEC_IN, ///< param 0: name - NODE_VEC_OUT, ///< param 0: name - NODE_VEC_CONSTANT, ///< param 0: value - NODE_VEC_PARAMETER, ///< param 0: name - NODE_VEC_ADD, - NODE_VEC_SUB, - NODE_VEC_MUL, - NODE_VEC_DIV, - NODE_VEC_MOD, - NODE_VEC_CROSS, - NODE_VEC_DOT, - NODE_VEC_POW, - NODE_VEC_NORMALIZE, - NODE_VEC_INTERPOLATE, - NODE_VEC_SCREEN_TO_UV, - NODE_VEC_TRANSFORM3, - NODE_VEC_TRANSFORM4, - NODE_VEC_COMPARE, - NODE_VEC_TEXTURE_2D, - NODE_VEC_TEXTURE_CUBE, - NODE_VEC_NOISE, - NODE_VEC_0, - NODE_VEC_1, - NODE_VEC_2, - NODE_VEC_BUILD, - NODE_VEC_PASS, - NODE_COLOR_CONSTANT, - NODE_COLOR_PARAMETER, - NODE_TEXTURE_PARAMETER, - NODE_TEXTURE_2D_PARAMETER, - NODE_TEXTURE_CUBE_PARAMETER, - NODE_TRANSFORM_CONSTANT, - NODE_TRANSFORM_PARAMETER, - NODE_LABEL, + NODE_INPUT, // all inputs (shader type dependent) + NODE_SCALAR_CONST, //scalar constant + NODE_VEC_CONST, //vec3 constant + NODE_RGB_CONST, //rgb constant (shows a color picker instead) + NODE_XFORM_CONST, // 4x4 matrix constant + NODE_TIME, // time in seconds + NODE_SCREEN_TEX, // screen texture sampler (takes UV) (only usable in fragment shader) + NODE_SCALAR_OP, // scalar vs scalar op (mul, add, div, etc) + NODE_VEC_OP, // vec3 vs vec3 op (mul,ad,div,crossprod,etc) + NODE_VEC_SCALAR_OP, // vec3 vs scalar op (mul, add, div, etc) + NODE_RGB_OP, // vec3 vs vec3 rgb op (with scalar amount), like brighten, darken, burn, dodge, multiply, etc. + NODE_XFORM_MULT, // mat4 x mat4 + NODE_XFORM_VEC_MULT, // mat4 x vec3 mult (with no-translation option) + NODE_XFORM_VEC_INV_MULT, // mat4 x vec3 inverse mult (with no-translation option) + NODE_SCALAR_FUNC, // scalar function (sin, cos, etc) + NODE_VEC_FUNC, // vector function (normalize, negate, reciprocal, rgb2hsv, hsv2rgb, etc, etc) + NODE_VEC_LEN, // vec3 length + NODE_DOT_PROD, // vec3 . vec3 (dot product -> scalar output) + NODE_VEC_TO_SCALAR, // 1 vec3 input, 3 scalar outputs + NODE_SCALAR_TO_VEC, // 3 scalar input, 1 vec3 output + NODE_XFORM_TO_VEC, // 3 vec input, 1 xform output + 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_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_OUTPUT, // output (shader type dependent) + NODE_COMMENT, // comment NODE_TYPE_MAX }; - enum ShaderType { - SHADER_VERTEX, - SHADER_FRAGMENT, - SHADER_LIGHT - }; - -private: struct Connection { @@ -119,70 +86,292 @@ private: int dst_slot; }; + enum SlotType { + + SLOT_TYPE_SCALAR, + SLOT_TYPE_VEC, + SLOT_TYPE_XFORM, + SLOT_TYPE_TEXTURE, + SLOT_MAX + }; + + enum ShaderType { + SHADER_TYPE_VERTEX, + SHADER_TYPE_FRAGMENT, + SHADER_TYPE_LIGHT, + SHADER_TYPE_MAX + }; + + enum SlotDir { + SLOT_IN, + SLOT_OUT + }; + + enum GraphError { + GRAPH_OK, + GRAPH_ERROR_CYCLIC, + GRAPH_ERROR_MISSING_CONNECTIONS + }; + +private: + + String _find_unique_name(const String& p_base); + + struct SourceSlot { + + int id; + int slot; + bool operator==(const SourceSlot& p_slot) const { + return id==p_slot.id && slot==p_slot.slot; + } + }; + struct Node { - int16_t x,y; + Vector2 pos; NodeType type; - Variant param; + Variant param1; + Variant param2; int id; mutable int order; // used for sorting - mutable bool out_valid; - mutable bool in_valid; + int sort_order; + Map<int,SourceSlot> connections; + }; struct ShaderData { Map<int,Node> node_map; - List<Connection> connections; + GraphError error; } shader[3]; - uint64_t version; -protected: -/* bool _set(const StringName& p_name, const Variant& p_value); - bool _get(const StringName& p_name,Variant &r_ret) const; - void _get_property_list( List<PropertyInfo> *p_list) const;*/ - static void _bind_methods(); + struct InOutParamInfo { + Mode shader_mode; + ShaderType shader_type; + const char *name; + const char *variable; + const char *postfix; + SlotType slot_type; + SlotDir dir; + }; + + static const InOutParamInfo inout_param_info[]; + + struct NodeSlotInfo { + + enum { MAX_INS=3, MAX_OUTS=3 }; + NodeType type; + const SlotType ins[MAX_INS]; + const SlotType outs[MAX_OUTS]; + }; - Array _get_connections_helper() const; + static const NodeSlotInfo node_slot_info[]; + + bool _pending_update_shader; + void _update_shader(); + void _request_update(); + + 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; + Array _get_connections(ShaderType p_type) const; + + void _set_data(const Dictionary& p_data); + Dictionary _get_data() const; +protected: + + static void _bind_methods(); public: - void node_add(ShaderType p_which, NodeType p_type,int p_id); + void node_add(ShaderType p_type, NodeType p_node_type, int p_id); void node_remove(ShaderType p_which,int p_id); - void node_set_param(ShaderType p_which, int p_id, const Variant& p_value); void node_set_pos(ShaderType p_which,int p_id,const Point2& p_pos); - void node_change_type(ShaderType p_which,int p_id, NodeType p_type); Point2 node_get_pos(ShaderType p_which,int p_id) const; void get_node_list(ShaderType p_which,List<int> *p_node_list) const; NodeType node_get_type(ShaderType p_which,int p_id) const; - Variant node_get_param(ShaderType p_which,int p_id) const; - Error connect(ShaderType p_which,int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot); - bool is_connected(ShaderType p_which,int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) const; - void disconnect(ShaderType p_which,int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot); + void scalar_const_node_set_value(ShaderType p_which,int p_id,float p_value); + float scalar_const_node_get_value(ShaderType p_which,int p_id) const; - void get_connections(ShaderType p_which,List<Connection> *p_connections) const; + void vec_const_node_set_value(ShaderType p_which,int p_id,const Vector3& p_value); + Vector3 vec_const_node_get_value(ShaderType p_which,int p_id) const; - void clear(); + void rgb_const_node_set_value(ShaderType p_which,int p_id,const Color& p_value); + Color rgb_const_node_get_value(ShaderType p_which,int p_id) const; - uint64_t get_version() const { return version; } + void xform_const_node_set_value(ShaderType p_which,int p_id,const Transform& p_value); + Transform xform_const_node_get_value(ShaderType p_which,int p_id) const; - static void get_default_input_nodes(Mode p_type,List<PropertyInfo> *p_inputs); - static void get_default_output_nodes(Mode p_type,List<PropertyInfo> *p_outputs); + void texture_node_set_filter_size(ShaderType p_which,int p_id,int p_size); + int texture_node_get_filter_size(ShaderType p_which,int p_id) const; - static PropertyInfo node_get_type_info(NodeType p_type); - static int get_input_count(NodeType p_type); - static int get_output_count(NodeType p_type); - static String get_input_name(NodeType p_type,int p_input); - static String get_output_name(NodeType p_type,int p_output); - static bool is_input_vector(NodeType p_type,int p_input); - static bool is_output_vector(NodeType p_type,int p_input); + void texture_node_set_filter_strength(ShaderType p_which,float p_id,float p_strength); + float texture_node_get_filter_strength(ShaderType p_which,float p_id) const; + enum ScalarOp { + SCALAR_OP_ADD, + SCALAR_OP_SUB, + SCALAR_OP_MUL, + SCALAR_OP_DIV, + SCALAR_OP_MOD, + SCALAR_OP_POW, + SCALAR_OP_MAX, + SCALAR_OP_MIN, + SCALAR_OP_ATAN2, + SCALAR_MAX_OP + }; + + void scalar_op_node_set_op(ShaderType p_which,float p_id,ScalarOp p_op); + ScalarOp scalar_op_node_get_op(ShaderType p_which,float p_id) const; + + enum VecOp { + VEC_OP_ADD, + VEC_OP_SUB, + VEC_OP_MUL, + VEC_OP_DIV, + VEC_OP_MOD, + VEC_OP_POW, + VEC_OP_MAX, + VEC_OP_MIN, + VEC_OP_CROSS, + VEC_MAX_OP + }; - ShaderGraph(); + void vec_op_node_set_op(ShaderType p_which,float p_id,VecOp p_op); + VecOp vec_op_node_get_op(ShaderType p_which,float p_id) const; + + enum VecScalarOp { + VEC_SCALAR_OP_MUL, + VEC_SCALAR_OP_DIV, + VEC_SCALAR_OP_POW, + VEC_SCALAR_MAX_OP + }; + + void vec_scalar_op_node_set_op(ShaderType p_which,float p_id,VecScalarOp p_op); + VecScalarOp vec_scalar_op_node_get_op(ShaderType p_which,float p_id) const; + + enum RGBOp { + RGB_OP_SCREEN, + RGB_OP_DIFFERENCE, + RGB_OP_DARKEN, + RGB_OP_LIGHTEN, + RGB_OP_OVERLAY, + RGB_OP_DODGE, + RGB_OP_BURN, + RGB_OP_SOFT_LIGHT, + RGB_OP_HARD_LIGHT, + RGB_MAX_OP + }; + + void rgb_op_node_set_op(ShaderType p_which,float p_id,RGBOp p_op); + RGBOp rgb_op_node_get_op(ShaderType p_which,float p_id) const; + + void xform_vec_mult_node_set_no_translation(ShaderType p_which,int p_id,bool p_no_translation); + bool xform_vec_mult_node_get_no_translation(ShaderType p_which,int p_id) const; + + enum ScalarFunc { + SCALAR_FUNC_SIN, + SCALAR_FUNC_COS, + SCALAR_FUNC_TAN, + SCALAR_FUNC_ASIN, + SCALAR_FUNC_ACOS, + SCALAR_FUNC_ATAN, + SCALAR_FUNC_SINH, + SCALAR_FUNC_COSH, + SCALAR_FUNC_TANH, + SCALAR_FUNC_LOG, + SCALAR_FUNC_EXP, + SCALAR_FUNC_SQRT, + SCALAR_FUNC_ABS, + SCALAR_FUNC_SIGN, + SCALAR_FUNC_FLOOR, + SCALAR_FUNC_ROUND, + SCALAR_FUNC_CEIL, + SCALAR_FUNC_FRAC, + SCALAR_FUNC_SATURATE, + SCALAR_FUNC_NEGATE, + SCALAR_MAX_FUNC + }; + + void scalar_func_node_set_function(ShaderType p_which,int p_id,ScalarFunc p_func); + ScalarFunc scalar_func_node_get_function(ShaderType p_which,int p_id) const; + + enum VecFunc { + VEC_FUNC_NORMALIZE, + VEC_FUNC_SATURATE, + VEC_FUNC_NEGATE, + VEC_FUNC_RECIPROCAL, + VEC_FUNC_RGB2HSV, + VEC_FUNC_HSV2RGB, + VEC_MAX_FUNC + }; + + 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 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); + + void scalar_input_node_set_value(ShaderType p_which,int p_id,float p_value); + float scalar_input_node_get_value(ShaderType p_which,int p_id) const; + + void vec_input_node_set_value(ShaderType p_which,int p_id,const Vector3& p_value); + Vector3 vec_input_node_get_value(ShaderType p_which,int p_id) const; + + void rgb_input_node_set_value(ShaderType p_which,int p_id,const Color& p_value); + Color rgb_input_node_get_value(ShaderType p_which,int p_id) const; + + void xform_input_node_set_value(ShaderType p_which,int p_id,const Transform& p_value); + Transform xform_input_node_get_value(ShaderType p_which,int p_id) const; + + void texture_input_node_set_value(ShaderType p_which,int p_id,const Ref<Texture>& p_texture); + Ref<Texture> texture_input_node_get_value(ShaderType p_which,int p_id) const; + + void cubemap_input_node_set_value(ShaderType p_which,int p_id,const Ref<CubeMap>& p_cubemap); + Ref<CubeMap> cubemap_input_node_get_value(ShaderType p_which,int p_id) const; + + void comment_node_set_text(ShaderType p_which,int p_id,const String& p_comment); + String comment_node_get_text(ShaderType p_which,int p_id) const; + + Error connect_node(ShaderType p_which,int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot); + bool is_node_connected(ShaderType p_which,int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) const; + void disconnect_node(ShaderType p_which,int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot); + + void get_node_connections(ShaderType p_which,List<Connection> *p_connections) const; + + void clear(ShaderType p_which); + + Variant node_get_state(ShaderType p_type, int p_node) const; + void node_set_state(ShaderType p_type, int p_id, const Variant& p_state); + + GraphError get_graph_error(ShaderType p_type) const; + + static int get_type_input_count(NodeType p_type); + static int get_type_output_count(NodeType p_type); + static SlotType get_type_input_type(NodeType p_type,int p_idx); + static SlotType get_type_output_type(NodeType p_type,int p_idx); + static bool is_type_valid(Mode p_mode,ShaderType p_type); + + + struct SlotInfo { + String name; + SlotType type; + SlotDir dir; + }; + + static void get_input_output_node_slot_info(Mode p_mode, ShaderType p_type, List<SlotInfo> *r_slots); + + static int get_node_input_slot_count(Mode p_mode, ShaderType p_shader_type,NodeType p_type); + static int get_node_output_slot_count(Mode p_mode, ShaderType p_shader_type,NodeType p_type); + static SlotType get_node_input_slot_type(Mode p_mode, ShaderType p_shader_type,NodeType p_type,int p_idx); + static SlotType get_node_output_slot_type(Mode p_mode, ShaderType p_shader_type,NodeType p_type,int p_idx); + + + ShaderGraph(Mode p_mode); ~ShaderGraph(); }; @@ -192,6 +381,28 @@ public: VARIANT_ENUM_CAST( ShaderGraph::NodeType ); +VARIANT_ENUM_CAST( ShaderGraph::ShaderType ); +VARIANT_ENUM_CAST( ShaderGraph::SlotType ); +VARIANT_ENUM_CAST( ShaderGraph::ScalarOp ); +VARIANT_ENUM_CAST( ShaderGraph::VecOp ); +VARIANT_ENUM_CAST( ShaderGraph::VecScalarOp ); +VARIANT_ENUM_CAST( ShaderGraph::RGBOp ); +VARIANT_ENUM_CAST( ShaderGraph::ScalarFunc ); +VARIANT_ENUM_CAST( ShaderGraph::VecFunc ); +VARIANT_ENUM_CAST( ShaderGraph::GraphError ); + + +class MaterialShaderGraph : public ShaderGraph { + + OBJ_TYPE( MaterialShaderGraph, ShaderGraph ); + RES_BASE_EXTENSION("sgp"); + +public: + + + MaterialShaderGraph() : ShaderGraph(MODE_MATERIAL) { + + } +}; -#endif #endif // SHADER_GRAPH_H diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index dd39205932..113fd8209d 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -650,8 +650,8 @@ void SurfaceTool::mikktGetTexCoord(const SMikkTSpaceContext * pContext, float fv Vector<List<Vertex>::Element*> &varr = *((Vector<List<Vertex>::Element*>*)pContext->m_pUserData); Vector2 v = varr[iFace*3+iVert]->get().uv; fvTexcOut[0]=v.x; - //fvTexcOut[1]=v.y; - fvTexcOut[1]=1.0-v.y; + fvTexcOut[1]=v.y; + //fvTexcOut[1]=1.0-v.y; } void SurfaceTool::mikktSetTSpaceBasic(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert){ diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp index aee7ddde00..0dd6a3d5e7 100644 --- a/scene/resources/world_2d.cpp +++ b/scene/resources/world_2d.cpp @@ -364,12 +364,12 @@ World2D::World2D() { Physics2DServer::get_singleton()->space_set_active(space,true); Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_GRAVITY,GLOBAL_DEF("physics_2d/default_gravity",98)); Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_GRAVITY_VECTOR,GLOBAL_DEF("physics_2d/default_gravity_vector",Vector2(0,1))); - Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_DENSITY,GLOBAL_DEF("physics_2d/default_density",0.1)); + Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_LINEAR_DAMP,GLOBAL_DEF("physics_2d/default_density",0.1)); + Physics2DServer::get_singleton()->area_set_param(space,Physics2DServer::AREA_PARAM_ANGULAR_DAMP,GLOBAL_DEF("physics_2d/default_density",1)); Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_CONTACT_RECYCLE_RADIUS,1.0); Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_CONTACT_MAX_SEPARATION,1.5); Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION,0.3); Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_TRESHOLD,2); - Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO,20); Physics2DServer::get_singleton()->space_set_param(space,Physics2DServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS,0.2); indexer = memnew( SpatialIndexer2D ); |