From 0b7a5b84255a53138b3a092175de7b6b9f32b058 Mon Sep 17 00:00:00 2001 From: sanikoyes Date: Fri, 19 Dec 2014 13:08:48 +0800 Subject: [PATCH 01/37] Fix RasterizerGLES2::canvas_draw_polygon can't work correct at some devices(like Sumsung Note2) in some devices, gpu doe's not support uint(32bit) indies --- drivers/gles2/rasterizer_gles2.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 9f2fd032fa3..79d163b0199 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -8142,7 +8142,14 @@ void RasterizerGLES2::canvas_draw_polygon(int p_vertex_count, const int* p_indic if (p_indices) { - glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_INT, p_indices ); + static const int _max_draw_poly_indices = 8*1024; // change this size if needed!!! + ERR_FAIL_COND(p_vertex_count > _max_draw_poly_indices); + static uint16_t _draw_poly_indices[_max_draw_poly_indices]; + for (int i=0; i Date: Thu, 25 Dec 2014 13:05:57 +0800 Subject: [PATCH 02/37] Reduce android build size(-fvisibility=hidden) Fix gridmap link error when disable_3d=Yes --- modules/gridmap/register_types.cpp | 4 ++++ platform/android/detect.py | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/gridmap/register_types.cpp b/modules/gridmap/register_types.cpp index 3c3c8aa98fd..887687a37bf 100644 --- a/modules/gridmap/register_types.cpp +++ b/modules/gridmap/register_types.cpp @@ -27,16 +27,20 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "register_types.h" +#ifndef _3D_DISABLED #include "object_type_db.h" #include "grid_map.h" #include "grid_map_editor_plugin.h" +#endif void register_gridmap_types() { +#ifndef _3D_DISABLED ObjectTypeDB::register_type(); #ifdef TOOLS_ENABLED EditorPlugins::add_by_type(); #endif +#endif } diff --git a/platform/android/detect.py b/platform/android/detect.py index 417f3e68ab1..695caf1e5d4 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -124,11 +124,11 @@ def configure(env): # env['CCFLAGS'] = string.split('-DNO_THREADS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -fno-exceptions -mthumb -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED ') if env['x86']=='yes': - env['CCFLAGS'] = string.split('-DNO_STATVFS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -D__GLIBC__ -Wno-psabi -ftree-vectorize -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED -DGLES1_ENABLED') + env['CCFLAGS'] = string.split('-DNO_STATVFS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -fvisibility=hidden -D__GLIBC__ -Wno-psabi -ftree-vectorize -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED -DGLES1_ENABLED') elif env["armv6"]!="no": - env['CCFLAGS'] = string.split('-DNO_STATVFS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_6__ -D__GLIBC__ -Wno-psabi -march=armv6 -mfpu=vfp -mfloat-abi=softfp -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED -DGLES1_ENABLED') + env['CCFLAGS'] = string.split('-DNO_STATVFS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -fvisibility=hidden -D__ARM_ARCH_6__ -D__GLIBC__ -Wno-psabi -march=armv6 -mfpu=vfp -mfloat-abi=softfp -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED -DGLES1_ENABLED') else: - env['CCFLAGS'] = string.split('-DNO_STATVFS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -D__ARM_ARCH_7__ -D__GLIBC__ -Wno-psabi -march=armv6 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED -DGLES1_ENABLED') + env['CCFLAGS'] = string.split('-DNO_STATVFS -MMD -MP -MF -fpic -ffunction-sections -funwind-tables -fstack-protector -fvisibility=hidden -D__ARM_ARCH_7__ -D__GLIBC__ -Wno-psabi -march=armv6 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize -funsafe-math-optimizations -fno-strict-aliasing -DANDROID -Wa,--noexecstack -DGLES2_ENABLED -DGLES1_ENABLED') env.Append(LDPATH=[ld_path]) env.Append(LIBS=['OpenSLES']) From 61fcca71111a35fa1e3e812f99939beba94244e8 Mon Sep 17 00:00:00 2001 From: marynate Date: Sun, 28 Dec 2014 00:28:02 +0800 Subject: [PATCH 03/37] Add Stop pause mode implementation --- scene/main/node.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scene/main/node.cpp b/scene/main/node.cpp index d9b208d6d3a..fbdc87a7cc0 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -382,6 +382,8 @@ bool Node::can_process() const { if (get_tree()->is_paused()) { + if (data.pause_mode==PAUSE_MODE_STOP) + return false; if (data.pause_mode==PAUSE_MODE_PROCESS) return true; if (data.pause_mode==PAUSE_MODE_INHERIT) { @@ -391,6 +393,9 @@ bool Node::can_process() const { if (data.pause_owner->data.pause_mode==PAUSE_MODE_PROCESS) return true; + + if (data.pause_owner->data.pause_mode==PAUSE_MODE_STOP) + return false; } } From 645a0385687fc2deefdb47f73eb4415932987c42 Mon Sep 17 00:00:00 2001 From: Lee Zher Huei Date: Sat, 27 Dec 2014 16:42:37 +0000 Subject: [PATCH 04/37] Fix for MinGW compilation --- SConstruct | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/SConstruct b/SConstruct index 42e90851714..f5aa0cd1bd6 100644 --- a/SConstruct +++ b/SConstruct @@ -133,8 +133,8 @@ Help(opts.GenerateHelpText(env_base)) # generate help # add default include paths env_base.Append(CPPPATH=['#core','#core/math','#tools','#drivers','#']) - -# configure ENV for platform + +# configure ENV for platform env_base.platform_exporters=platform_exporters """ @@ -170,6 +170,26 @@ if selected_platform in platform_list: else: env = env_base.Clone() + # Workaround for MinGW. See: + # http://www.scons.org/wiki/LongCmdLinesOnWin32 + if (os.name=="nt"): + import subprocess + def mySpawn(sh, escape, cmd, args, env): + newargs = ' '.join(args[1:]) + cmdline = cmd + " " + newargs + startupinfo = subprocess.STARTUPINFO() + startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW + proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, startupinfo=startupinfo, shell = False, env = env) + data, err = proc.communicate() + rv = proc.wait() + if rv: + print "=====" + print err + print "=====" + return rv + env['SPAWN'] = mySpawn + env.extra_suffix="" CCFLAGS = env.get('CCFLAGS', '') From d128ec926369afca89155361c68249df17bdc278 Mon Sep 17 00:00:00 2001 From: jaromirhribal Date: Sun, 28 Dec 2014 14:01:08 +0100 Subject: [PATCH 05/37] added blender/maya like zoom style --- tools/editor/editor_settings.cpp | 2 ++ .../editor/plugins/spatial_editor_plugin.cpp | 25 ++++++++++++++++--- tools/editor/plugins/spatial_editor_plugin.h | 6 +++++ 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp index 8b0fd204e32..3f44701b98f 100644 --- a/tools/editor/editor_settings.cpp +++ b/tools/editor/editor_settings.cpp @@ -419,6 +419,8 @@ void EditorSettings::_load_defaults() { set("3d_editor/navigation_scheme",0); hints["3d_editor/navigation_scheme"]=PropertyInfo(Variant::INT,"3d_editor/navigation_scheme",PROPERTY_HINT_ENUM,"Godot,Maya,Modo"); + set("3d_editor/zoom_style",0); + hints["3d_editor/zoom_style"]=PropertyInfo(Variant::INT,"3d_editor/zoom_style",PROPERTY_HINT_ENUM,"Vertical, Horizontal"); set("3d_editor/orbit_modifier",0); hints["3d_editor/orbit_modifier"]=PropertyInfo(Variant::INT,"3d_editor/orbit_modifier",PROPERTY_HINT_ENUM,"None,Shift,Alt,Meta,Ctrl"); set("3d_editor/pan_modifier",1); diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp index a1f1ccf5e37..0960a961ecd 100644 --- a/tools/editor/plugins/spatial_editor_plugin.cpp +++ b/tools/editor/plugins/spatial_editor_plugin.cpp @@ -535,6 +535,14 @@ SpatialEditorViewport::NavigationScheme SpatialEditorViewport::_get_navigation_s return NAVIGATION_GODOT; } +SpatialEditorViewport::NavigationZoomStyle SpatialEditorViewport::_get_navigation_zoom_style(const String& p_property) { + switch(EditorSettings::get_singleton()->get(p_property).operator int()) { + case 0: return NAVIGATION_ZOOM_VERTICAL; + case 1: return NAVIGATION_ZOOM_HORIZONTAL; + } + return NAVIGATION_ZOOM_VERTICAL; +} + bool SpatialEditorViewport::_gizmo_select(const Vector2& p_screenpos,bool p_hilite_only) { if (!spatial_editor->is_gizmo_visible()) @@ -1429,10 +1437,19 @@ void SpatialEditorViewport::_sinput(const InputEvent &p_event) { if (nav_scheme==NAVIGATION_MAYA && m.mod.shift) zoom_speed *= zoom_speed_modifier; - if ( m.relative_y > 0) - cursor.distance*=1+m.relative_y*zoom_speed; - else if (m.relative_y < 0) - cursor.distance/=1-m.relative_y*zoom_speed; + NavigationZoomStyle zoom_style = _get_navigation_zoom_style("3d_editor/zoom_style"); + if (zoom_style == NAVIGATION_ZOOM_HORIZONTAL) { + if ( m.relative_x > 0) + cursor.distance*=1-m.relative_x*zoom_speed; + else if (m.relative_x < 0) + cursor.distance/=1+m.relative_x*zoom_speed; + } + else { + if ( m.relative_y > 0) + cursor.distance*=1+m.relative_y*zoom_speed; + else if (m.relative_y < 0) + cursor.distance/=1-m.relative_y*zoom_speed; + } } break; diff --git a/tools/editor/plugins/spatial_editor_plugin.h b/tools/editor/plugins/spatial_editor_plugin.h index 1fdc97c49d2..646a4d2d868 100644 --- a/tools/editor/plugins/spatial_editor_plugin.h +++ b/tools/editor/plugins/spatial_editor_plugin.h @@ -144,6 +144,12 @@ private: }; NavigationScheme _get_navigation_schema(const String& p_property); + enum NavigationZoomStyle { + NAVIGATION_ZOOM_VERTICAL, + NAVIGATION_ZOOM_HORIZONTAL + }; + NavigationZoomStyle _get_navigation_zoom_style(const String& p_property); + enum NavigationMode { NAVIGATION_NONE, NAVIGATION_PAN, From 079f1b1642aa35fe20a927c777aa42f629e1fbaf Mon Sep 17 00:00:00 2001 From: tommy3 Date: Sun, 28 Dec 2014 14:34:37 +0100 Subject: [PATCH 06/37] fixed a typo --- tools/editor/animation_editor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/editor/animation_editor.cpp b/tools/editor/animation_editor.cpp index 95f9ee65095..2eef8214387 100644 --- a/tools/editor/animation_editor.cpp +++ b/tools/editor/animation_editor.cpp @@ -3238,7 +3238,7 @@ AnimationKeyEditor::AnimationKeyEditor(UndoRedo *p_undo_redo, EditorHistory *p_h move_down_button->connect("pressed",this,"_menu_track",make_binds(TRACK_MENU_MOVE_DOWN)); move_down_button->set_focus_mode(FOCUS_NONE); move_down_button->set_disabled(true); - move_down_button->set_tooltip("Move current track dosn."); + move_down_button->set_tooltip("Move current track down."); remove_button = memnew( ToolButton ); hb->add_child(remove_button); From 4faf47eb503931f3fd44d617aadca8f34cc0ae47 Mon Sep 17 00:00:00 2001 From: Carl Olsson Date: Mon, 29 Dec 2014 08:37:25 +1000 Subject: [PATCH 07/37] Replace TileMapEditor floating tile palette with HSplitContainer. --- .../plugins/canvas_item_editor_plugin.cpp | 12 ++++- .../plugins/canvas_item_editor_plugin.h | 6 +++ .../editor/plugins/tile_map_editor_plugin.cpp | 51 ++++++------------- tools/editor/plugins/tile_map_editor_plugin.h | 9 +--- 4 files changed, 34 insertions(+), 44 deletions(-) diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp index 599160eb468..a18c2a58a71 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.cpp +++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp @@ -2683,6 +2683,11 @@ void CanvasItemEditor::add_control_to_menu_panel(Control *p_control) { hb->add_child(p_control); } +HSplitContainer *CanvasItemEditor::get_palette_split() { + + return palette_split; +} + CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { tool = TOOL_SELECT; @@ -2697,15 +2702,20 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { add_child( hb ); hb->set_area_as_parent_rect(); + palette_split = memnew( HSplitContainer); + palette_split->set_v_size_flags(SIZE_EXPAND_FILL); + add_child(palette_split); + Control *vp_base = memnew (Control); - add_child(vp_base); vp_base->set_v_size_flags(SIZE_EXPAND_FILL); + palette_split->add_child(vp_base); Control *vp = memnew (Control); vp_base->add_child(vp); vp->set_area_as_parent_rect(); vp->add_child(p_editor->get_scene_root()); + viewport = memnew( Control ); vp_base->add_child(viewport); viewport->set_area_as_parent_rect(); diff --git a/tools/editor/plugins/canvas_item_editor_plugin.h b/tools/editor/plugins/canvas_item_editor_plugin.h index 15ac7b1bb3c..c56570d43f2 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.h +++ b/tools/editor/plugins/canvas_item_editor_plugin.h @@ -289,6 +289,10 @@ class CanvasItemEditor : public VBoxContainer { void _viewport_input_event(const InputEvent& p_event); void _viewport_draw(); + +private: + HSplitContainer *palette_split; + friend class CanvasItemEditorPlugin; protected: @@ -341,6 +345,8 @@ public: void add_control_to_menu_panel(Control *p_control); + HSplitContainer *get_palette_split(); + Control *get_viewport_control() { return viewport; } diff --git a/tools/editor/plugins/tile_map_editor_plugin.cpp b/tools/editor/plugins/tile_map_editor_plugin.cpp index a25997108b1..21474205d7a 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.cpp +++ b/tools/editor/plugins/tile_map_editor_plugin.cpp @@ -42,7 +42,6 @@ void TileMapEditor::_notification(int p_what) { case NOTIFICATION_READY: { - pane_drag->connect("dragged", this,"_pane_drag"); mirror_x->set_icon( get_icon("MirrorX","EditorIcons")); mirror_y->set_icon( get_icon("MirrorY","EditorIcons")); @@ -701,23 +700,10 @@ void TileMapEditor::_tileset_settings_changed() { canvas_item_editor->update(); } -void TileMapEditor::_pane_drag(const Point2& p_to) { - - int x = theme_panel->get_margin(MARGIN_RIGHT); - - x+=p_to.x; - if (x<10) - x=10; - if (x>300) - x=300; - theme_panel->set_margin(MARGIN_RIGHT,x); -} - void TileMapEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_menu_option"),&TileMapEditor::_menu_option); ObjectTypeDB::bind_method(_MD("_canvas_draw"),&TileMapEditor::_canvas_draw); - ObjectTypeDB::bind_method(_MD("_pane_drag"),&TileMapEditor::_pane_drag); ObjectTypeDB::bind_method(_MD("_canvas_mouse_enter"),&TileMapEditor::_canvas_mouse_enter); ObjectTypeDB::bind_method(_MD("_canvas_mouse_exit"),&TileMapEditor::_canvas_mouse_exit); ObjectTypeDB::bind_method(_MD("_tileset_settings_changed"),&TileMapEditor::_tileset_settings_changed); @@ -731,36 +717,30 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { editor=p_editor; undo_redo = editor->get_undo_redo(); - theme_panel = memnew( Panel ); - theme_panel->set_anchor(MARGIN_BOTTOM,ANCHOR_END); - theme_panel->set_begin( Point2(0,26)); - theme_panel->set_end( Point2(100,0) ); - p_editor->get_viewport()->add_child(theme_panel); - theme_panel->hide(); + int mw = EDITOR_DEF("tile_map/palette_min_width",80); + EmptyControl *ec = memnew( EmptyControl); + ec->set_minsize(Size2(mw,0)); + add_child(ec); + // Add tile palette palette = memnew( Tree ); - palette->set_area_as_parent_rect(4); - palette->set_margin(MARGIN_TOP,25);; - theme_panel->add_child(palette); - - pane_drag = memnew( PaneDrag ) ; - pane_drag->set_anchor(MARGIN_LEFT,ANCHOR_END); - pane_drag->set_begin(Point2(16,4)); - theme_panel->add_child(pane_drag); - - add_child( memnew( VSeparator )); + palette->set_v_size_flags(SIZE_EXPAND_FILL); + add_child(palette); + // Add menu items + HBoxContainer *canvas_item_editor_hb = memnew( HBoxContainer ); + CanvasItemEditor::get_singleton()->add_control_to_menu_panel(canvas_item_editor_hb); + canvas_item_editor_hb->add_child( memnew( VSeparator )); mirror_x = memnew( ToolButton ); mirror_x->set_toggle_mode(true); mirror_x->set_tooltip("Mirror X (A)"); mirror_x->set_focus_mode(FOCUS_NONE); - add_child(mirror_x); + canvas_item_editor_hb->add_child(mirror_x); mirror_y = memnew( ToolButton ); mirror_y->set_toggle_mode(true); mirror_y->set_tooltip("Mirror Y (S)"); mirror_y->set_focus_mode(FOCUS_NONE); - add_child(mirror_y); - + canvas_item_editor_hb->add_child(mirror_y); tool=TOOL_NONE; selection_active=false; @@ -782,12 +762,10 @@ void TileMapEditorPlugin::make_visible(bool p_visible) { if (p_visible) { tile_map_editor->show(); - tile_map_editor->theme_panel->show(); } else { tile_map_editor->hide(); - tile_map_editor->theme_panel->hide(); tile_map_editor->edit(NULL); } @@ -797,7 +775,8 @@ TileMapEditorPlugin::TileMapEditorPlugin(EditorNode *p_node) { editor=p_node; tile_map_editor = memnew( TileMapEditor(p_node) ); - CanvasItemEditor::get_singleton()->add_control_to_menu_panel(tile_map_editor); + CanvasItemEditor::get_singleton()->get_palette_split()->add_child(tile_map_editor); + CanvasItemEditor::get_singleton()->get_palette_split()->move_child(tile_map_editor,0); tile_map_editor->hide(); diff --git a/tools/editor/plugins/tile_map_editor_plugin.h b/tools/editor/plugins/tile_map_editor_plugin.h index 2336507f1bb..0a09a29f9d1 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.h +++ b/tools/editor/plugins/tile_map_editor_plugin.h @@ -34,15 +34,14 @@ #include "scene/2d/tile_map.h" #include "scene/gui/tool_button.h" #include "scene/gui/button_group.h" -#include "tools/editor/pane_drag.h" /** @author Juan Linietsky */ class CanvasItemEditor; -class TileMapEditor : public HBoxContainer { +class TileMapEditor : public VBoxContainer { - OBJ_TYPE(TileMapEditor, BoxContainer ); + OBJ_TYPE(TileMapEditor, VBoxContainer ); UndoRedo *undo_redo; @@ -63,7 +62,6 @@ class TileMapEditor : public HBoxContainer { Panel *panel; TileMap *node; MenuButton *options; - PaneDrag *pane_drag; bool selection_active; Point2i selection_begin; @@ -88,7 +86,6 @@ class TileMapEditor : public HBoxContainer { int get_selected_tile() const; void _update_palette(); - void _pane_drag(const Point2& p_to); void _canvas_draw(); void _menu_option(int p_option); @@ -99,8 +96,6 @@ class TileMapEditor : public HBoxContainer { void _tileset_settings_changed(); -friend class TileMapEditorPlugin; - Panel *theme_panel; protected: void _notification(int p_what); void _node_removed(Node *p_node); From b0509bf8f0c437e4693d7f7e5dce99cec78ce15f Mon Sep 17 00:00:00 2001 From: Dana Olson Date: Thu, 1 Jan 2015 22:22:24 -0500 Subject: [PATCH 08/37] change parameter name from ip to port --- core/io/stream_peer_tcp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/io/stream_peer_tcp.cpp b/core/io/stream_peer_tcp.cpp index 0e75e22767a..f83c1740844 100644 --- a/core/io/stream_peer_tcp.cpp +++ b/core/io/stream_peer_tcp.cpp @@ -32,7 +32,7 @@ StreamPeerTCP* (*StreamPeerTCP::_create)()=NULL; void StreamPeerTCP::_bind_methods() { - ObjectTypeDB::bind_method(_MD("connect","host","ip"),&StreamPeerTCP::connect); + ObjectTypeDB::bind_method(_MD("connect","host","port"),&StreamPeerTCP::connect); ObjectTypeDB::bind_method(_MD("is_connected"),&StreamPeerTCP::is_connected); ObjectTypeDB::bind_method(_MD("get_status"),&StreamPeerTCP::get_status); ObjectTypeDB::bind_method(_MD("get_connected_host"),&StreamPeerTCP::get_connected_host); From 9ee218ac9ba464687a41eea59707187aea28c962 Mon Sep 17 00:00:00 2001 From: Muresan Vlad aka Mury Date: Fri, 2 Jan 2015 13:31:25 +0200 Subject: [PATCH 09/37] Fix for bug 1088 --- core/dictionary.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/dictionary.cpp b/core/dictionary.cpp index 16ee3973824..2d503bae50c 100644 --- a/core/dictionary.cpp +++ b/core/dictionary.cpp @@ -186,10 +186,12 @@ Error Dictionary::parse_json(const String& p_json) { String errstr; int errline=0; + if (p_json != ""){ Error err = JSON::parse(p_json,*this,errstr,errline); if (err!=OK) { ERR_EXPLAIN("Error parsing JSON: "+errstr+" at line: "+itos(errline)); ERR_FAIL_COND_V(err!=OK,err); + } } return OK; From 0378e1109b8ff96a3583d7da02966ef3344ee35a Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 2 Jan 2015 12:52:51 -0300 Subject: [PATCH 10/37] -fixed NODE_OUT error in animtreeplayer #1078 -fixed randon button when editing menubutton #1079 --- scene/animation/animation_tree_player.cpp | 3 ++- tools/editor/plugins/item_list_editor_plugin.cpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp index ec72123c983..5172907d185 100644 --- a/scene/animation/animation_tree_player.cpp +++ b/scene/animation/animation_tree_player.cpp @@ -83,7 +83,8 @@ bool AnimationTreePlayer::_set(const StringName& p_name, const Variant& p_value) ERR_FAIL_COND_V(nt==NODE_MAX,false); - add_node(nt,id); + if (nt!=NODE_OUTPUT) + add_node(nt,id); node_set_pos(id,pos); diff --git a/tools/editor/plugins/item_list_editor_plugin.cpp b/tools/editor/plugins/item_list_editor_plugin.cpp index eb7ab69987a..a8b34ef503e 100644 --- a/tools/editor/plugins/item_list_editor_plugin.cpp +++ b/tools/editor/plugins/item_list_editor_plugin.cpp @@ -210,6 +210,7 @@ void ItemListEditor::_bind_methods() { } bool ItemListEditor::handles(Object *p_object) const { + return false; for(int i=0;ihandles(p_object)) { return true; From 2e08e111205b3ffc7fc28f0cb80e857dd4bc9640 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 2 Jan 2015 13:08:28 -0300 Subject: [PATCH 11/37] -fixed signal in #1075 --- scene/3d/sprite_3d.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 77f2cf5cc1f..35f6523c6af 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -497,7 +497,7 @@ void Sprite3D::set_frame(int p_frame) { frame=p_frame; _queue_update(); - ADD_SIGNAL(MethodInfo("frame_changed")); + emit_signal(SceneStringNames::get_singleton()->frame_changed); } From 28daf19744423b989e0e2f04895554e3918b5920 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 2 Jan 2015 13:17:46 -0300 Subject: [PATCH 12/37] -assignment of ord to string index made valid #1072 --- core/variant_op.cpp | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/core/variant_op.cpp b/core/variant_op.cpp index 9c489c5ef2e..d9fe6537a19 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -922,21 +922,31 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid) case REAL: { return; } break; case STRING: { - if (p_value.type!=Variant::STRING) - return; - if (p_index.get_type()==Variant::INT || p_index.get_type()==Variant::REAL) { - //string index - int idx=p_index; - String *str=reinterpret_cast(_data._mem); - if (idx >=0 && idxlength()) { - String chr = p_value; - *str = str->substr(0,idx-1)+chr+str->substr(idx+1,str->length()); - valid=true; - return; - } + if (p_index.type!=Variant::INT && p_index.type!=Variant::REAL) + return; + + int idx=p_index; + String *str=reinterpret_cast(_data._mem); + if (idx <0 || idx>=str->length()) + return; + + String chr; + if (p_value.type==Variant::INT || p_value.type==Variant::REAL) { + + chr = String::chr(p_value); + } else if (p_value.type==Variant::STRING) { + + chr = p_value; + } else { + return; } + *str = str->substr(0,idx-1)+chr+str->substr(idx+1,str->length()); + valid=true; + return; + + } break; case VECTOR2: { From aa36be3c9a588bdceae9fbe3f19407522668a7de Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 2 Jan 2015 13:21:07 -0300 Subject: [PATCH 13/37] -typo fixed in ImmediateGeometry (#1066) --- scene/3d/immediate_geometry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scene/3d/immediate_geometry.cpp b/scene/3d/immediate_geometry.cpp index a4206894ff3..651d20ae71a 100644 --- a/scene/3d/immediate_geometry.cpp +++ b/scene/3d/immediate_geometry.cpp @@ -127,7 +127,7 @@ void ImmediateGeometry::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_color","color"),&ImmediateGeometry::set_color); ObjectTypeDB::bind_method(_MD("set_uv","uv"),&ImmediateGeometry::set_uv); ObjectTypeDB::bind_method(_MD("set_uv2","uv"),&ImmediateGeometry::set_uv2); - ObjectTypeDB::bind_method(_MD("add_vertex","color"),&ImmediateGeometry::add_vertex); + ObjectTypeDB::bind_method(_MD("add_vertex","pos"),&ImmediateGeometry::add_vertex); ObjectTypeDB::bind_method(_MD("add_sphere","lats","lons","radius"),&ImmediateGeometry::add_sphere); ObjectTypeDB::bind_method(_MD("end"),&ImmediateGeometry::end); ObjectTypeDB::bind_method(_MD("clear"),&ImmediateGeometry::clear); From bbaddfa70f3c69d040f1f2b6edcbdb5ded9e1979 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 2 Jan 2015 13:30:59 -0300 Subject: [PATCH 14/37] -fixed silly bug in trigger check (#1051) --- scene/3d/physics_body.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 5c047b3fef1..f2806f2af29 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -852,6 +852,8 @@ Vector3 KinematicBody::move(const Vector3& p_motion) { //motion recover for(int i=0;icollide_shape(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i),m,sr,max_shapes,res_shapes,exclude,get_layer_mask(),mask)) { collided=true; @@ -870,9 +872,6 @@ Vector3 KinematicBody::move(const Vector3& p_motion) { for(int j=0;j<8;j++) { for(int i=0;i "+b); From e0bcec4fb8c589a68fbf898458ca87502954f81e Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 2 Jan 2015 13:38:31 -0300 Subject: [PATCH 15/37] -make sure selected font is applied on load (#1050) --- tools/editor/code_editor.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tools/editor/code_editor.cpp b/tools/editor/code_editor.cpp index 242654c4727..2209b24245e 100644 --- a/tools/editor/code_editor.cpp +++ b/tools/editor/code_editor.cpp @@ -599,7 +599,19 @@ CodeTextEditor::CodeTextEditor() { add_child(text_editor); text_editor->set_area_as_parent_rect(); text_editor->set_margin(MARGIN_BOTTOM,20); - text_editor->add_font_override("font",get_font("source","Fonts")); + + String editor_font = EDITOR_DEF("text_editor/font", ""); + bool font_overrode = false; + if (editor_font!="") { + Ref fnt = ResourceLoader::load(editor_font); + if (fnt.is_valid()) { + text_editor->add_font_override("font",fnt); + font_overrode = true; + } + } + + if (!font_overrode) + text_editor->add_font_override("font",get_font("source","Fonts")); text_editor->set_show_line_numbers(true); text_editor->set_brace_matching(true); From d88e192ae49dd8c30cf4f94f4a50e41b7d912c2d Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 2 Jan 2015 14:27:21 -0300 Subject: [PATCH 16/37] -fix readonly issues (#1018) --- scene/gui/text_edit.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 3f2f95bbd97..e152c45e52b 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -829,7 +829,7 @@ void TextEdit::_notification(int p_what) { completion_rect.pos.x=cursor_pos.x-nofs; } - completion_rect.size.width=w; + completion_rect.size.width=w+2; completion_rect.size.height=h; if (completion_options.size()<=maxlines) scrollw=0; @@ -1034,6 +1034,8 @@ void TextEdit::_consume_backspace_for_pair_symbol(int prev_line, int prev_column } void TextEdit::backspace_at_cursor() { + if (readonly) + return; if (cursor.column==0 && cursor.line==0) return; @@ -1251,6 +1253,8 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { return; if (completion_active) { + if (readonly) + break; bool valid=true; if (k.mod.command || k.mod.alt || k.mod.meta) @@ -1400,6 +1404,9 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { if (selection.active) { + if (readonly) + break; + bool clear=false; bool unselect=false; bool dobreak=false; @@ -1513,6 +1520,9 @@ void TextEdit::_input_event(const InputEvent& p_input_event) { case KEY_ENTER: case KEY_RETURN: { + if (readonly) + break; + String ins="\n"; //keep indentation From ed8e70243fb1a7e88c02a8f47c431fbcc641ec62 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 2 Jan 2015 14:32:05 -0300 Subject: [PATCH 17/37] -refresh play options in property when setting samplelibrary (#1016) --- scene/2d/sample_player_2d.cpp | 1 + scene/3d/spatial_sample_player.cpp | 1 + scene/audio/sample_player.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/scene/2d/sample_player_2d.cpp b/scene/2d/sample_player_2d.cpp index 99dfa67c27b..a231acd13d5 100644 --- a/scene/2d/sample_player_2d.cpp +++ b/scene/2d/sample_player_2d.cpp @@ -102,6 +102,7 @@ void SamplePlayer2D::_notification(int p_what) { void SamplePlayer2D::set_sample_library(const Ref& p_library) { library=p_library; + _change_notify(); } Ref SamplePlayer2D::get_sample_library() const { diff --git a/scene/3d/spatial_sample_player.cpp b/scene/3d/spatial_sample_player.cpp index b4a5d3bc1bb..6dc71e06ad4 100644 --- a/scene/3d/spatial_sample_player.cpp +++ b/scene/3d/spatial_sample_player.cpp @@ -103,6 +103,7 @@ void SpatialSamplePlayer::_notification(int p_what) { void SpatialSamplePlayer::set_sample_library(const Ref& p_library) { library=p_library; + _change_notify(); } Ref SpatialSamplePlayer::get_sample_library() const { diff --git a/scene/audio/sample_player.cpp b/scene/audio/sample_player.cpp index 90994f01b4b..bf1c5e97a35 100644 --- a/scene/audio/sample_player.cpp +++ b/scene/audio/sample_player.cpp @@ -498,6 +498,7 @@ bool SamplePlayer::is_active() const { void SamplePlayer::set_sample_library(const Ref& p_library) { library=p_library; + _change_notify(); } Ref SamplePlayer::get_sample_library() const { From fbfb87ec4f4c27c051e281978dc2e9a7d75bf3ab Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 2 Jan 2015 14:34:57 -0300 Subject: [PATCH 18/37] -accelerometer precission changed to "GAME" (#1015) --- platform/android/java/src/com/android/godot/Godot.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/android/java/src/com/android/godot/Godot.java b/platform/android/java/src/com/android/godot/Godot.java index f6cd57f4f3c..1a7659a473a 100644 --- a/platform/android/java/src/com/android/godot/Godot.java +++ b/platform/android/java/src/com/android/godot/Godot.java @@ -358,7 +358,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC GodotLib.initialize(this,io.needsReloadHooks(),command_line); mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); - mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); + mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_GAME); result_callback = null; From 8a28af024e077cdc67a527ab70f19affcf0201b5 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 2 Jan 2015 15:08:40 -0300 Subject: [PATCH 19/37] -fix TextEdit shift-click functionality past begin and end of selection (#1004) --- scene/gui/text_edit.cpp | 5464 ++++++++++++++++++++------------------- scene/gui/text_edit.h | 1 + 2 files changed, 2751 insertions(+), 2714 deletions(-) diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index e152c45e52b..933895a2076 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -26,7 +26,7 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ - /*****f********************************************/ +/*****f********************************************/ /* text_edit.cpp */ /*************************************************/ /* This file is part of: */ @@ -47,343 +47,343 @@ #define TAB_PIXELS static bool _is_text_char(CharType c) { - - return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_'; + + return (c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='_'; } static bool _is_symbol(CharType c) { - - return c!='_' && ((c>='!' && c<='/') || (c>=':' && c<='@') || (c>='[' && c<='`') || (c>='{' && c<='~') || c=='\t'); + + return c!='_' && ((c>='!' && c<='/') || (c>=':' && c<='@') || (c>='[' && c<='`') || (c>='{' && c<='~') || c=='\t'); } static bool _is_pair_right_symbol(CharType c) { - return - c == '"' || - c == '\'' || - c == ')' || - c == ']' || - c == '}'; + return + c == '"' || + c == '\'' || + c == ')' || + c == ']' || + c == '}'; } static bool _is_pair_left_symbol(CharType c) { - return - c == '"' || - c == '\'' || - c == '(' || - c == '[' || - c == '{'; + return + c == '"' || + c == '\'' || + c == '(' || + c == '[' || + c == '{'; } static bool _is_pair_symbol(CharType c) { - return _is_pair_left_symbol(c) || _is_pair_right_symbol(c); + return _is_pair_left_symbol(c) || _is_pair_right_symbol(c); } static CharType _get_right_pair_symbol(CharType c) { - if(c == '"') - return '"'; - if(c == '\'') - return '\''; - if(c == '(') - return ')'; - if(c == '[') - return ']'; - if(c == '{') - return '}'; - return 0; + if(c == '"') + return '"'; + if(c == '\'') + return '\''; + if(c == '(') + return ')'; + if(c == '[') + return ']'; + if(c == '{') + return '}'; + return 0; } void TextEdit::Text::set_font(const Ref& p_font) { - - font=p_font; + + font=p_font; } void TextEdit::Text::set_tab_size(int p_tab_size) { - - tab_size=p_tab_size; + + tab_size=p_tab_size; } void TextEdit::Text::_update_line_cache(int p_line) const { - - int w =0; - int tab_w=font->get_char_size(' ').width; - - int len = text[p_line].data.length(); - const CharType *str = text[p_line].data.c_str(); - - //update width - - for(int i=0;iget_char_size(str[i],str[i+1]).width; - } - } - - - text[p_line].width_cache=w; - - //update regions - - text[p_line].region_info.clear(); - - for(int i=0;isize();j++) { - - const ColorRegion& cr=color_regions->operator [](j); - - /* BEGIN */ - - int lr=cr.begin_key.length(); - if (lr==0 || lr>left) - continue; - - const CharType* kc = cr.begin_key.c_str(); - - bool match=true; - - for(int k=0;kleft) - continue; - - kc = cr.end_key.c_str(); - - match=true; - - for(int k=0;kget_char_size(' ').width; + + int len = text[p_line].data.length(); + const CharType *str = text[p_line].data.c_str(); + + //update width + + for(int i=0;iget_char_size(str[i],str[i+1]).width; + } + } + + + text[p_line].width_cache=w; + + //update regions + + text[p_line].region_info.clear(); + + for(int i=0;isize();j++) { + + const ColorRegion& cr=color_regions->operator [](j); + + /* BEGIN */ + + int lr=cr.begin_key.length(); + if (lr==0 || lr>left) + continue; + + const CharType* kc = cr.begin_key.c_str(); + + bool match=true; + + for(int k=0;kleft) + continue; + + kc = cr.end_key.c_str(); + + match=true; + + for(int k=0;k& TextEdit::Text::get_color_region_info(int p_line) { - - Map *cri=NULL; - ERR_FAIL_INDEX_V(p_line,text.size(),*cri); //enjoy your crash - - if (text[p_line].width_cache==-1) { - _update_line_cache(p_line); - } - - return text[p_line].region_info; + + Map *cri=NULL; + ERR_FAIL_INDEX_V(p_line,text.size(),*cri); //enjoy your crash + + if (text[p_line].width_cache==-1) { + _update_line_cache(p_line); + } + + return text[p_line].region_info; } int TextEdit::Text::get_line_width(int p_line) const { - - ERR_FAIL_INDEX_V(p_line,text.size(),-1); - - if (text[p_line].width_cache==-1) { - _update_line_cache(p_line); - } - - return text[p_line].width_cache; + + ERR_FAIL_INDEX_V(p_line,text.size(),-1); + + if (text[p_line].width_cache==-1) { + _update_line_cache(p_line); + } + + return text[p_line].width_cache; } void TextEdit::Text::clear_caches() { - - for(int i=0;iget_combined_minimum_size(); - Size2 vmin = v_scroll->get_combined_minimum_size(); - - - - v_scroll->set_begin( Point2(size.width - vmin.width, cache.style_normal->get_margin(MARGIN_TOP)) ); - v_scroll->set_end( Point2(size.width, size.height - cache.style_normal->get_margin(MARGIN_TOP) - cache.style_normal->get_margin(MARGIN_BOTTOM)) ); - - h_scroll->set_begin( Point2( 0, size.height - hmin.height) ); - h_scroll->set_end( Point2(size.width-vmin.width, size.height) ); - - - int hscroll_rows = ((hmin.height-1)/get_row_height())+1; - int visible_rows = get_visible_rows(); - int total_rows = text.size() * cache.line_spacing; - - int vscroll_pixels = v_scroll->get_combined_minimum_size().width; - int visible_width = size.width - cache.style_normal->get_minimum_size().width; - int total_width = text.get_max_width(); - - bool use_hscroll=true; - bool use_vscroll=true; - - if (total_rows <= visible_rows && total_width <= visible_width) { - //thanks yessopie for this clever bit of logic - use_hscroll=false; - use_vscroll=false; - - } else { - - if (total_rows > visible_rows && total_width <= visible_width - vscroll_pixels) { - //thanks yessopie for this clever bit of logic - use_hscroll=false; - } - - if (total_rows <= visible_rows - hscroll_rows && total_width > visible_width) { - //thanks yessopie for this clever bit of logic - use_vscroll=false; - } - } - - updating_scrolls=true; - - if (use_vscroll) { - - v_scroll->show(); - v_scroll->set_max(total_rows); - v_scroll->set_page(visible_rows); - - v_scroll->set_val(cursor.line_ofs); - - } else { - cursor.line_ofs = 0; - v_scroll->hide(); - } - - if (use_hscroll) { - - h_scroll->show(); - h_scroll->set_max(total_width); - h_scroll->set_page(visible_width); - h_scroll->set_val(cursor.x_ofs); - } else { - - h_scroll->hide(); - } - - - - updating_scrolls=false; + + + Size2 size = get_size(); + Size2 hmin = h_scroll->get_combined_minimum_size(); + Size2 vmin = v_scroll->get_combined_minimum_size(); + + + + v_scroll->set_begin( Point2(size.width - vmin.width, cache.style_normal->get_margin(MARGIN_TOP)) ); + v_scroll->set_end( Point2(size.width, size.height - cache.style_normal->get_margin(MARGIN_TOP) - cache.style_normal->get_margin(MARGIN_BOTTOM)) ); + + h_scroll->set_begin( Point2( 0, size.height - hmin.height) ); + h_scroll->set_end( Point2(size.width-vmin.width, size.height) ); + + + int hscroll_rows = ((hmin.height-1)/get_row_height())+1; + int visible_rows = get_visible_rows(); + int total_rows = text.size() * cache.line_spacing; + + int vscroll_pixels = v_scroll->get_combined_minimum_size().width; + int visible_width = size.width - cache.style_normal->get_minimum_size().width; + int total_width = text.get_max_width(); + + bool use_hscroll=true; + bool use_vscroll=true; + + if (total_rows <= visible_rows && total_width <= visible_width) { + //thanks yessopie for this clever bit of logic + use_hscroll=false; + use_vscroll=false; + + } else { + + if (total_rows > visible_rows && total_width <= visible_width - vscroll_pixels) { + //thanks yessopie for this clever bit of logic + use_hscroll=false; + } + + if (total_rows <= visible_rows - hscroll_rows && total_width > visible_width) { + //thanks yessopie for this clever bit of logic + use_vscroll=false; + } + } + + updating_scrolls=true; + + if (use_vscroll) { + + v_scroll->show(); + v_scroll->set_max(total_rows); + v_scroll->set_page(visible_rows); + + v_scroll->set_val(cursor.line_ofs); + + } else { + cursor.line_ofs = 0; + v_scroll->hide(); + } + + if (use_hscroll) { + + h_scroll->show(); + h_scroll->set_max(total_width); + h_scroll->set_page(visible_width); + h_scroll->set_val(cursor.x_ofs); + } else { + + h_scroll->hide(); + } + + + + updating_scrolls=false; } void TextEdit::_notification(int p_what) { - + switch(p_what) { case NOTIFICATION_ENTER_TREE: { - + _update_caches(); if (cursor_changed_dirty) MessageQueue::get_singleton()->push_call(this,"_cursor_changed_emit"); if (text_changed_dirty) MessageQueue::get_singleton()->push_call(this,"_text_changed_emit"); - + } break; case NOTIFICATION_RESIZED: { - + cache.size=get_size(); adjust_viewport_to_cursor(); - - + + } break; case NOTIFICATION_THEME_CHANGED: { - + _update_caches(); }; case NOTIFICATION_DRAW: { - + int line_number_char_count=0; - + { int lc=text.size()+1; cache.line_number_w=0; @@ -391,20 +391,20 @@ void TextEdit::_notification(int p_what) { cache.line_number_w+=1; lc/=10; }; - + if (line_numbers) { - + line_number_char_count=cache.line_number_w; cache.line_number_w=(cache.line_number_w+1)*cache.font->get_char_size('0').width; } else { cache.line_number_w=0; } - - + + } _update_scrollbars(); - - + + RID ci = get_canvas_item(); int xmargin_beg=cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w; int xmargin_end=cache.size.width-cache.style_normal->get_margin(MARGIN_RIGHT); @@ -412,56 +412,56 @@ void TextEdit::_notification(int p_what) { cache.style_normal->draw(ci,Rect2(Point2(),cache.size)); if (has_focus()) cache.style_focus->draw(ci,Rect2(Point2(),cache.size)); - - + + int ascent=cache.font->get_ascent(); - + int visible_rows = get_visible_rows(); - + int tab_w = cache.font->get_char_size(' ').width*tab_size; - + Color color = cache.font_color; int in_region=-1; - + if (syntax_coloring) { - + if (custom_bg_color.a>0.01) { - + Point2i ofs = Point2i(cache.style_normal->get_offset())/2.0; VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(ofs, get_size()-cache.style_normal->get_minimum_size()+ofs),custom_bg_color); } //compute actual region to start (may be inside say, a comment). //slow in very large documments :( but ok for source! - + for(int i=0;i& cri_map=text.get_color_region_info(i); - + if (in_region>=0 && color_regions[in_region].line_only) { in_region=-1; //reset regions that end at end of line } - + for( const Map::Element* E= cri_map.front();E;E=E->next() ) { - + const Text::ColorRegionInfo &cri=E->get(); - + if (in_region==-1) { - + if (!cri.end) { - + in_region=cri.region; } } else if (in_region==cri.region && !color_regions[cri.region].line_only) { //ignore otherwise - + if (cri.end || color_regions[cri.region].eq) { - + in_region=-1; } } } } } - + int brace_open_match_line=-1; int brace_open_match_column=-1; bool brace_open_matching=false; @@ -470,15 +470,15 @@ void TextEdit::_notification(int p_what) { int brace_close_match_column=-1; bool brace_close_matching=false; bool brace_close_mismatch=false; - - + + if (brace_matching_enabled) { - + if (cursor.column0) { CharType c = text[cursor.line][cursor.column-1]; CharType closec=0; - - - + + + if (c==']') { closec='['; } else if (c=='}') { @@ -535,65 +535,65 @@ void TextEdit::_notification(int p_what) { } else if (c==')') { closec='('; } - + if (closec!=0) { - + int stack=1; - - + + for(int i=cursor.line;i>=0;i--) { - + int from = i==cursor.line?cursor.column-2:text[i].length()-1; for(int j=from;j>=0;j--) { - + CharType cc = text[i][j]; if (cc==c) stack++; else if (cc==closec) stack--; - + if (stack==0) { brace_close_match_line=i; brace_close_match_column=j; brace_close_matching=true; - + break; } } if (brace_close_match_line!=-1) break; } - + if (!brace_close_matching) brace_close_mismatch=true; - - + + } - - + + } } - - + + int deregion=0; //force it to clear inrgion Point2 cursor_pos; - + for (int i=0;i=(int)text.size()) continue; - + const String &str=text[line]; - + int char_margin=xmargin_beg-cursor.x_ofs; int char_ofs=0; int ofs_y=i*get_row_height()+cache.line_spacing/2; bool prev_is_char=false; bool in_keyword=false; Color keyword_color; - + if (cache.line_number_w) { Color fcol = cache.font_color; fcol.a*=0.4; @@ -601,191 +601,191 @@ void TextEdit::_notification(int p_what) { while (fc.length() < line_number_char_count) { fc="0"+fc; } - + cache.font->draw(ci,Point2(cache.style_normal->get_margin(MARGIN_LEFT),ofs_y+cache.font->get_ascent()),fc,fcol); } - + const Map& cri_map=text.get_color_region_info(line); - - + + if (text.is_marked(line)) { - + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.mark_color); } - + if (text.is_breakpoint(line)) { - + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.breakpoint_color); } - - + + if (line==cursor.line) { - + VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(xmargin_beg, ofs_y,xmargin_end-xmargin_beg,get_row_height()),cache.current_line_color); - + } for (int j=0;j0) { deregion--; if (deregion==0) in_region=-1; } if (syntax_coloring && deregion==0) { - - + + color = cache.font_color; //reset //find keyword bool is_char = _is_text_char(str[j]); bool is_symbol=_is_symbol(str[j]); - + if (j==0 && in_region>=0 && color_regions[in_region].line_only) { in_region=-1; //reset regions that end at end of line } - + if (is_symbol && cri_map.has(j)) { - - + + const Text::ColorRegionInfo &cri=cri_map[j]; - + if (in_region==-1) { - + if (!cri.end) { - + in_region=cri.region; } } else if (in_region==cri.region && !color_regions[cri.region].line_only) { //ignore otherwise - + if (cri.end || color_regions[cri.region].eq) { - + deregion=color_regions[cri.region].eq?color_regions[cri.region].begin_key.length():color_regions[cri.region].end_key.length(); } } } - + if (!is_char) in_keyword=false; - + if (in_region==-1 && !in_keyword && is_char && !prev_is_char) { - + int to=j; while(_is_text_char(str[to]) && to=0) color=color_regions[in_region].color; else if (in_keyword) color=keyword_color; else if (is_symbol) color=symbol_color; - + prev_is_char=is_char; - + } int char_w; - + //handle tabulator - - + + if (str[j]=='\t') { int left = char_ofs%tab_w; if (left==0) char_w=tab_w; else char_w=tab_w-char_ofs%tab_w; // is right... - + } else { char_w=cache.font->get_char_size(str[j],str[j+1]).width; } - + if ( (char_ofs+char_margin)=xmargin_end) { if (syntax_coloring) continue; else break; } - + bool in_selection = (selection.active && line>=selection.from_line && line<=selection.to_line && (line>selection.from_line || j>=selection.from_column) && (linecanvas_item_add_rect(ci,Rect2(Point2i( char_ofs+char_margin, ofs_y ), Size2i(char_w,get_row_height())),cache.selection_color); } - - + + if (brace_matching_enabled) { if ( (brace_open_match_line==line && brace_open_match_column==j) || - (cursor.column==j && cursor.line==line && (brace_open_matching||brace_open_mismatch))) { - + (cursor.column==j && cursor.line==line && (brace_open_matching||brace_open_mismatch))) { + if (brace_open_mismatch) color=cache.brace_mismatch_color; cache.font->draw_char(ci,Point2i( char_ofs+char_margin, ofs_y+ascent),'_',str[j+1],in_selection?cache.font_selected_color:color); - + } - + if ( - (brace_close_match_line==line && brace_close_match_column==j) || - (cursor.column==j+1 && cursor.line==line && (brace_close_matching||brace_close_mismatch))) { - - + (brace_close_match_line==line && brace_close_match_column==j) || + (cursor.column==j+1 && cursor.line==line && (brace_close_matching||brace_close_mismatch))) { + + if (brace_close_mismatch) color=cache.brace_mismatch_color; cache.font->draw_char(ci,Point2i( char_ofs+char_margin, ofs_y+ascent),'_',str[j+1],in_selection?cache.font_selected_color:color); - + } } - - + + if (str[j]>=32) cache.font->draw_char(ci,Point2i( char_ofs+char_margin, ofs_y+ascent),str[j],str[j+1],in_selection?cache.font_selected_color:color); - + else if (draw_tabs && str[j]=='\t') { int yofs= (get_row_height() - cache.tab_icon->get_height())/2; cache.tab_icon->draw(ci, Point2(char_ofs+char_margin,ofs_y+yofs),in_selection?cache.font_selected_color:color); } - - + + if (cursor.column==j && cursor.line==line) { - + cursor_pos = Point2i( char_ofs+char_margin, ofs_y ); VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.font_color); - - + + } char_ofs+=char_w; - + } - + if (cursor.column==str.length() && cursor.line==line) { - + cursor_pos=Point2i( char_ofs+char_margin, ofs_y ); VisualServer::get_singleton()->canvas_item_add_rect(ci,Rect2(cursor_pos, Size2i(1,get_row_height())),cache.font_color); - + } } - - + + if (completion_active) { // code completion box Ref csb = get_stylebox("completion"); @@ -796,15 +796,15 @@ void TextEdit::_notification(int p_what) { existing.a=0.2; int scrollw = get_constant("completion_scroll_width"); Color scrollc = get_color("completion_scroll_color"); - - - + + + int lines = MIN(completion_options.size(),maxlines); int w=0; int h=lines*get_row_height(); int nofs = cache.font->get_string_size(completion_base).width; - - + + if (completion_options.size() < 50) { for(int i=0;iget_string_size(completion_options[i]).x,cmax_width); @@ -814,39 +814,39 @@ void TextEdit::_notification(int p_what) { } else { w=cmax_width; } - + int th = h + csb->get_minimum_size().y; if (cursor_pos.y+get_row_height()+th > get_size().height) { completion_rect.pos.y=cursor_pos.y-th; } else { completion_rect.pos.y=cursor_pos.y+get_row_height()+csb->get_offset().y; - + } - + if (cursor_pos.x-nofs+w+scrollw > get_size().width) { completion_rect.pos.x=get_size().width-w-scrollw; } else { completion_rect.pos.x=cursor_pos.x-nofs; } - + completion_rect.size.width=w+2; completion_rect.size.height=h; if (completion_options.size()<=maxlines) scrollw=0; - + draw_style_box(csb,Rect2(completion_rect.pos-csb->get_offset(),completion_rect.size+csb->get_minimum_size()+Size2(scrollw,0))); - - + + int line_from = CLAMP(completion_index - lines/2, 0, completion_options.size() - lines); draw_style_box(csel,Rect2(Point2(completion_rect.pos.x,completion_rect.pos.y+(completion_index-line_from)*get_row_height()),Size2(completion_rect.size.width,get_row_height()))); - + draw_rect(Rect2(completion_rect.pos,Size2(nofs,completion_rect.size.height)),existing); - - - - + + + + for(int i=0;i= completion_options.size()); Color text_color = cache.font_color; @@ -857,31 +857,31 @@ void TextEdit::_notification(int p_what) { } draw_string(cache.font,Point2(completion_rect.pos.x,completion_rect.pos.y+i*get_row_height()+cache.font->get_ascent()),completion_options[l],text_color,completion_rect.size.width); } - + if (scrollw) { //draw a small scroll rectangle to show a position in the options float r = maxlines / (float)completion_options.size(); float o = line_from / (float)completion_options.size(); draw_rect(Rect2(completion_rect.pos.x+completion_rect.size.width,completion_rect.pos.y+o*completion_rect.size.y,scrollw,completion_rect.size.y*r),scrollc); } - + completion_line_ofs=line_from; - + } - + if (completion_hint!="") { - + Ref sb = get_stylebox("panel","TooltipPanel"); Ref font = cache.font; Color font_color = get_color("font_color","TooltipLabel"); - - + + int max_w=0; int sc = completion_hint.get_slice_count("\n"); int offset=0; int spacing=0; for(int i=0;iget_string_size(l).x; max_w = MAX(len,max_w); @@ -890,35 +890,35 @@ void TextEdit::_notification(int p_what) { } else { spacing+=cache.line_spacing; } - - + + } - - - + + + Size2 size = Size2(max_w,sc*font->get_height()+spacing); Size2 minsize = size+sb->get_minimum_size(); - - + + if (completion_hint_offset==-0xFFFF) { completion_hint_offset=cursor_pos.x-offset; } - - + + Point2 hint_ofs = Vector2(completion_hint_offset,cursor_pos.y-minsize.y); draw_style_box(sb,Rect2(hint_ofs,minsize)); - + spacing=0; for(int i=0;iget_string_size(l.substr(0,l.find(String::chr(0xFFFF)))).x; end = font->get_string_size(l.substr(0,l.rfind(String::chr(0xFFFF)))).x; } - + draw_string(font,hint_ofs+sb->get_offset()+Vector2(0,font->get_ascent()+font->get_height()*i+spacing),l.replace(String::chr(0xFFFF),""),font_color); if (end>0) { Vector2 b = hint_ofs+sb->get_offset()+Vector2(begin,font->get_height()+font->get_height()*i+spacing-1); @@ -927,1487 +927,1523 @@ void TextEdit::_notification(int p_what) { spacing+=cache.line_spacing; } } - - + + } break; case NOTIFICATION_FOCUS_ENTER: { - + if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->show_virtual_keyboard(get_text(),get_global_rect()); - + } break; case NOTIFICATION_FOCUS_EXIT: { - + if (OS::get_singleton()->has_virtual_keyboard()) OS::get_singleton()->hide_virtual_keyboard(); - + } break; - + } } void TextEdit::_consume_pair_symbol(CharType ch) { - - int cursor_position_to_move = cursor_get_column() + 1; - - CharType ch_single[2] = {ch, 0}; - CharType ch_single_pair[2] = {_get_right_pair_symbol(ch), 0}; - CharType ch_pair[3] = {ch, _get_right_pair_symbol(ch), 0}; - - if(is_selection_active()) { - - int new_column,new_line; - - _begin_compex_operation(); - _insert_text(get_selection_from_line(), get_selection_from_column(), - ch_single, - &new_line, &new_column); - - int to_col_offset = 0; - if(get_selection_from_line() == get_selection_to_line()) - to_col_offset = 1; - - _insert_text(get_selection_to_line(), - get_selection_to_column() + to_col_offset, - ch_single_pair, - &new_line,&new_column); - _end_compex_operation(); - - cursor_set_line(get_selection_to_line()); - cursor_set_column(get_selection_to_column() + to_col_offset); - - deselect(); - update(); - return; - } - - if( (ch == '\'' || ch == '"') && - cursor_get_column() > 0 && - _is_text_char(text[cursor.line][cursor_get_column() - 1]) - ) { - insert_text_at_cursor(ch_single); - cursor_set_column(cursor_position_to_move); - return; - } - - if(cursor_get_column() < text[cursor.line].length()) { - if(_is_text_char(text[cursor.line][cursor_get_column()])) { - insert_text_at_cursor(ch_single); - cursor_set_column(cursor_position_to_move); - return; - } - if( _is_pair_right_symbol(ch) && - text[cursor.line][cursor_get_column()] == ch - ) { - cursor_set_column(cursor_position_to_move); - return; - } - } - - - insert_text_at_cursor(ch_pair); - cursor_set_column(cursor_position_to_move); - return; - + + int cursor_position_to_move = cursor_get_column() + 1; + + CharType ch_single[2] = {ch, 0}; + CharType ch_single_pair[2] = {_get_right_pair_symbol(ch), 0}; + CharType ch_pair[3] = {ch, _get_right_pair_symbol(ch), 0}; + + if(is_selection_active()) { + + int new_column,new_line; + + _begin_compex_operation(); + _insert_text(get_selection_from_line(), get_selection_from_column(), + ch_single, + &new_line, &new_column); + + int to_col_offset = 0; + if(get_selection_from_line() == get_selection_to_line()) + to_col_offset = 1; + + _insert_text(get_selection_to_line(), + get_selection_to_column() + to_col_offset, + ch_single_pair, + &new_line,&new_column); + _end_compex_operation(); + + cursor_set_line(get_selection_to_line()); + cursor_set_column(get_selection_to_column() + to_col_offset); + + deselect(); + update(); + return; + } + + if( (ch == '\'' || ch == '"') && + cursor_get_column() > 0 && + _is_text_char(text[cursor.line][cursor_get_column() - 1]) + ) { + insert_text_at_cursor(ch_single); + cursor_set_column(cursor_position_to_move); + return; + } + + if(cursor_get_column() < text[cursor.line].length()) { + if(_is_text_char(text[cursor.line][cursor_get_column()])) { + insert_text_at_cursor(ch_single); + cursor_set_column(cursor_position_to_move); + return; + } + if( _is_pair_right_symbol(ch) && + text[cursor.line][cursor_get_column()] == ch + ) { + cursor_set_column(cursor_position_to_move); + return; + } + } + + + insert_text_at_cursor(ch_pair); + cursor_set_column(cursor_position_to_move); + return; + } void TextEdit::_consume_backspace_for_pair_symbol(int prev_line, int prev_column) { - - bool remove_right_symbol = false; - - if(cursor.column < text[cursor.line].length() && cursor.column > 0) { - - CharType left_char = text[cursor.line][cursor.column - 1]; - CharType right_char = text[cursor.line][cursor.column]; - - if(right_char == _get_right_pair_symbol(left_char)) { - remove_right_symbol = true; - } - - } - if(remove_right_symbol) { - _remove_text(prev_line,prev_column,cursor.line,cursor.column + 1); - } else { - _remove_text(prev_line,prev_column,cursor.line,cursor.column); - } - + + bool remove_right_symbol = false; + + if(cursor.column < text[cursor.line].length() && cursor.column > 0) { + + CharType left_char = text[cursor.line][cursor.column - 1]; + CharType right_char = text[cursor.line][cursor.column]; + + if(right_char == _get_right_pair_symbol(left_char)) { + remove_right_symbol = true; + } + + } + if(remove_right_symbol) { + _remove_text(prev_line,prev_column,cursor.line,cursor.column + 1); + } else { + _remove_text(prev_line,prev_column,cursor.line,cursor.column); + } + } void TextEdit::backspace_at_cursor() { - if (readonly) - return; - - if (cursor.column==0 && cursor.line==0) - return; - - int prev_line = cursor.column?cursor.line:cursor.line-1; - int prev_column = cursor.column?(cursor.column-1):(text[cursor.line-1].length()); - if(auto_brace_completion_enabled && - cursor.column > 0 && - _is_pair_left_symbol(text[cursor.line][cursor.column - 1])) { - _consume_backspace_for_pair_symbol(prev_line, prev_column); - } else { - _remove_text(prev_line,prev_column,cursor.line,cursor.column); - } - - cursor_set_line(prev_line); - cursor_set_column(prev_column); + if (readonly) + return; + if (cursor.column==0 && cursor.line==0) + return; + + int prev_line = cursor.column?cursor.line:cursor.line-1; + int prev_column = cursor.column?(cursor.column-1):(text[cursor.line-1].length()); + if(auto_brace_completion_enabled && + cursor.column > 0 && + _is_pair_left_symbol(text[cursor.line][cursor.column - 1])) { + _consume_backspace_for_pair_symbol(prev_line, prev_column); + } else { + _remove_text(prev_line,prev_column,cursor.line,cursor.column); + } + + cursor_set_line(prev_line); + cursor_set_column(prev_column); + } bool TextEdit::_get_mouse_pos(const Point2i& p_mouse, int &r_row, int &r_col) const { - - int row=p_mouse.y; - row-=cache.style_normal->get_margin(MARGIN_TOP); - row/=get_row_height(); - - if (row<0 || row>=get_visible_rows()) - return false; - - row+=cursor.line_ofs; - int col=0; - - if (row>=text.size()) { - - row=text.size()-1; - col=text[row].size(); - } else { - - col=p_mouse.x-(cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w); - col+=cursor.x_ofs; - col=get_char_pos_for( col, get_line(row) ); - } - - r_row=row; - r_col=col; - return true; + + int row=p_mouse.y; + row-=cache.style_normal->get_margin(MARGIN_TOP); + row/=get_row_height(); + + if (row<0 || row>=get_visible_rows()) + return false; + + row+=cursor.line_ofs; + int col=0; + + if (row>=text.size()) { + + row=text.size()-1; + col=text[row].size(); + } else { + + col=p_mouse.x-(cache.style_normal->get_margin(MARGIN_LEFT)+cache.line_number_w); + col+=cursor.x_ofs; + col=get_char_pos_for( col, get_line(row) ); + } + + r_row=row; + r_col=col; + return true; } void TextEdit::_input_event(const InputEvent& p_input_event) { - - switch(p_input_event.type) { - - case InputEvent::MOUSE_BUTTON: { - - const InputEventMouseButton &mb=p_input_event.mouse_button; - - if (completion_active && completion_rect.has_point(Point2(mb.x,mb.y))) { - - if (!mb.pressed) - return; - - if (mb.button_index==BUTTON_WHEEL_UP) { - if (completion_index>0) { - completion_index--; - completion_current=completion_options[completion_index]; - update(); - } - - } - if (mb.button_index==BUTTON_WHEEL_DOWN) { - - if (completion_indexset_val( v_scroll->get_val() -3 ); - } - if (mb.button_index==BUTTON_WHEEL_DOWN) { - v_scroll->set_val( v_scroll->get_val() +3 ); - } - if (mb.button_index==BUTTON_LEFT) { - - int row,col; - if (!_get_mouse_pos(Point2i(mb.x,mb.y), row,col)) - return; - - int prev_col=cursor.column; - int prev_line=cursor.line; - - - - cursor_set_line( row ); - cursor_set_column( col ); - - if (mb.mod.shift && (cursor.column!=prev_col || cursor.line!=prev_line)) { - - selection.active=true; - selection.selecting_mode=Selection::MODE_POINTER; - selection.from_column=prev_col; - selection.from_line=prev_line; - selection.to_column=cursor.column; - selection.to_line=cursor.line; - if (selection.from_column>selection.to_column) { - SWAP(selection.from_column,selection.to_column); - SWAP(selection.from_line,selection.to_line); - } - selection.selecting_line=prev_line; - selection.selecting_column=prev_col; - update(); - - } else { - - //if sel active and dblick last time < something - - //else - selection.active=false; - selection.selecting_mode=Selection::MODE_POINTER; - selection.selecting_line=row; - selection.selecting_column=col; - } - - - if (!mb.doubleclick && (OS::get_singleton()->get_ticks_msec()-last_dblclk)<600) { - //tripleclick select line - select(cursor.line,0,cursor.line,text[cursor.line].length()); - last_dblclk=0; - - } else if (mb.doubleclick && text[cursor.line].length()) { - - //doubleclick select world - String s = text[cursor.line]; - int beg=CLAMP(cursor.column,0,s.length()); - int end=beg; - - if (s[beg]>32 || beg==s.length()) { - - bool symbol = beg < s.length() && _is_symbol(s[beg]); //not sure if right but most editors behave like this - - while(beg>0 && s[beg-1]>32 && (symbol==_is_symbol(s[beg-1]))) { - beg--; - } - while(end32 && (symbol==_is_symbol(s[end+1]))) { - end++; - } - - if (endget_ticks_msec(); - - } - - update(); - } - } else { - - selection.selecting_mode=Selection::MODE_NONE; - // notify to show soft keyboard - notification(NOTIFICATION_FOCUS_ENTER); - } - - } break; - case InputEvent::MOUSE_MOTION: { - - const InputEventMouseMotion &mm=p_input_event.mouse_motion; - - if (mm.button_mask&BUTTON_MASK_LEFT) { - - int row,col; - if (!_get_mouse_pos(Point2i(mm.x,mm.y), row,col)) - return; - - if (selection.selecting_mode==Selection::MODE_POINTER) { - - select(selection.selecting_line,selection.selecting_column,row,col); - - cursor_set_line( row ); - cursor_set_column( col ); - update(); - - } - - } - - } break; - - case InputEvent::KEY: { - - InputEventKey k=p_input_event.key; - - if (!k.pressed) - return; - - if (completion_active) { - if (readonly) - break; - - bool valid=true; - if (k.mod.command || k.mod.alt || k.mod.meta) - valid=false; - - if (valid) { - - if (k.scancode==KEY_UP) { - - if (completion_index>0) { - completion_index--; - completion_current=completion_options[completion_index]; - update(); - } - accept_event(); - return; - } - - - if (k.scancode==KEY_DOWN) { - - if (completion_index=completion_options.size()) - completion_index=completion_options.size()-1; - completion_current=completion_options[completion_index]; - update(); - accept_event(); - return; - } - - if (k.scancode==KEY_HOME) { - - completion_index=0; - completion_current=completion_options[completion_index]; - update(); - accept_event(); - return; - } - - if (k.scancode==KEY_END) { - - completion_index=completion_options.size()-1; - completion_current=completion_options[completion_index]; - update(); - accept_event(); - return; - } - - - if (k.scancode==KEY_DOWN) { - - if (completion_index32) { - - if (cursor.column0 && txt[i-1]=='\n') || (i==0 /*&& selection.from_column==0*/)) && (txt[i]=='\t' || txt[i]==' ')) { - txt.remove(i); - //i--; - } - } - } else { - - for(int i=0;i0 && txt[i-1]=='\n') || (i==0 /*&& selection.from_column==0*/))) { - txt=txt.insert(i,"\t"); - //i--; - } - } - } - - if (txt!=prev_txt) { - - int sel_line=selection.from_line; - int sel_column=selection.from_column; - - cursor_set_line(selection.from_line); - cursor_set_column(selection.from_column); - _begin_compex_operation(); - _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); - _insert_text_at_cursor(txt); - _end_compex_operation(); - selection.active=true; - selection.from_column=sel_column; - selection.from_line=sel_line; - selection.to_column=cursor.column; - selection.to_line=cursor.line; - update(); - } - - dobreak=true; - accept_event(); - - } break; - case KEY_X: - case KEY_C: - //special keys often used with control, wait... - clear=(!k.mod.command || k.mod.shift || k.mod.alt ); - break; - case KEY_DELETE: - case KEY_BACKSPACE: - accept_event(); - clear=true; dobreak=true; - break; - case KEY_LEFT: - case KEY_RIGHT: - case KEY_UP: - case KEY_DOWN: - case KEY_PAGEUP: - case KEY_PAGEDOWN: - case KEY_HOME: - case KEY_END: - // ignore arrows if any modifiers are held (shift = selecting, others may be used for editor hotkeys) - if (k.mod.command || k.mod.shift || k.mod.alt || k.mod.command) - break; - unselect=true; - break; - - default: - if (k.unicode>=32 && !k.mod.command && !k.mod.alt && !k.mod.meta) - clear=true; - if (auto_brace_completion_enabled && _is_pair_left_symbol(k.unicode)) - clear=false; - } - - if (unselect) { - selection.active=false; - selection.selecting_mode=Selection::MODE_NONE; - update(); - } - if (clear) { - - selection.active=false; - update(); - _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); - cursor_set_line(selection.from_line); - cursor_set_column(selection.from_column); - update(); - } - if (dobreak) - break; - } - - selection.selecting_test=false; - - bool scancode_handled=true; - - // special scancode test... - - switch (k.scancode) { - - case KEY_ENTER: - case KEY_RETURN: { - - if (readonly) - break; - - String ins="\n"; - - //keep indentation - for(int i=0;i0 && cc<=text[cursor.line].length() && text[cursor.line][cursor.column-1]=='\t') { - //simple unindent - - backspace_at_cursor(); - } - } else { - //simple indent - _insert_text_at_cursor("\t"); - } - } - - } break; - case KEY_BACKSPACE: { - if (readonly) - break; - backspace_at_cursor(); - - } break; - case KEY_LEFT: { - - if (k.mod.shift) - _pre_shift_selection(); - -#ifdef APPLE_STYLE_KEYS - if (k.mod.command) { - cursor_set_column(0); - } else if (k.mod.alt) { - -#else - if (k.mod.alt) { - scancode_handled=false; - break; - } else if (k.mod.command) { -#endif - bool prev_char=false; - int cc=cursor.column; - while (cc>0) { - - bool ischar=_is_text_char(text[cursor.line][cc-1]); - - if (prev_char && !ischar) - break; - - prev_char=ischar; - cc--; - - } - - cursor_set_column(cc); - - } else if (cursor.column==0) { - - if (cursor.line>0) { - cursor_set_line(cursor.line-1); - cursor_set_column(text[cursor.line].length()); - } - } else { - cursor_set_column(cursor_get_column()-1); - } - - if (k.mod.shift) - _post_shift_selection(); - - } break; - case KEY_RIGHT: { - - if (k.mod.shift) - _pre_shift_selection(); - -#ifdef APPLE_STYLE_KEYS - if (k.mod.command) { - cursor_set_column(text[cursor.line].length()); - } else if (k.mod.alt) { -#else - if (k.mod.alt) { - scancode_handled=false; - break; - } else if (k.mod.command) { -#endif - bool prev_char=false; - int cc=cursor.column; - while (ccset_clipboard(clipboard); - cursor_set_line(cursor.line); - cursor_set_column(0); - _remove_text(cursor.line,0,cursor.line,text[cursor.line].length()); - - backspace_at_cursor(); - update(); - cursor_set_line(cursor.line+1); - cut_copy_line = true; - - } - else - { - - String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); - OS::get_singleton()->set_clipboard(clipboard); - - cursor_set_line(selection.from_line); - cursor_set_column(selection.from_column); - - _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); - selection.active=false; - selection.selecting_mode=Selection::MODE_NONE; - update(); - cut_copy_line = false; - } - - } break; - case KEY_C: { - - if (!k.mod.command || k.mod.shift || k.mod.alt) { - scancode_handled=false; - break; - } - - if (!selection.active){ - String clipboard = _base_get_text(cursor.line,0,cursor.line,text[cursor.line].length()); - OS::get_singleton()->set_clipboard(clipboard); - cut_copy_line = true; - } - else{ - String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); - OS::get_singleton()->set_clipboard(clipboard); - cut_copy_line = false; - } - } break; - case KEY_Z: { - - if (!k.mod.command) { - scancode_handled=false; - break; - } - - if (k.mod.shift) - redo(); - else - undo(); - } break; - case KEY_V: { - - if (!k.mod.command || k.mod.shift || k.mod.alt) { - scancode_handled=false; - break; - } - - String clipboard = OS::get_singleton()->get_clipboard(); - - if (selection.active) { - selection.active=false; - _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); - cursor_set_line(selection.from_line); - cursor_set_column(selection.from_column); - - } - else if (cut_copy_line) - { - cursor_set_column(0); - String ins="\n"; - clipboard += ins; - } - - _insert_text_at_cursor(clipboard); - - update(); - } break; - case KEY_SPACE: { - if (completion_enabled && k.mod.command) { - - query_code_comple(); - scancode_handled=true; - } else { - scancode_handled=false; - } - - } break; - - case KEY_U:{ - if (!k.mod.command || k.mod.shift || k.mod.alt) { - scancode_handled=false; - break; - } - else { - if (selection.active) { - int ini = selection.from_line; - int end = selection.to_line; - for (int i=ini; i<= end; i++) - { - if (text[i][0] == '#') - _remove_text(i,0,i,1); - } - } - else{ - if (text[cursor.line][0] == '#') - _remove_text(cursor.line,0,cursor.line,1); - } - update(); - } - break;} - - default: { - - scancode_handled=false; + + switch(p_input_event.type) { + + case InputEvent::MOUSE_BUTTON: { + + const InputEventMouseButton &mb=p_input_event.mouse_button; + + if (completion_active && completion_rect.has_point(Point2(mb.x,mb.y))) { + + if (!mb.pressed) + return; + + if (mb.button_index==BUTTON_WHEEL_UP) { + if (completion_index>0) { + completion_index--; + completion_current=completion_options[completion_index]; + update(); + } + + } + if (mb.button_index==BUTTON_WHEEL_DOWN) { + + if (completion_indexset_val( v_scroll->get_val() -3 ); + } + if (mb.button_index==BUTTON_WHEEL_DOWN) { + v_scroll->set_val( v_scroll->get_val() +3 ); + } + if (mb.button_index==BUTTON_LEFT) { + + int row,col; + if (!_get_mouse_pos(Point2i(mb.x,mb.y), row,col)) + return; + + int prev_col=cursor.column; + int prev_line=cursor.line; + + + + cursor_set_line( row ); + cursor_set_column( col ); + + if (mb.mod.shift && (cursor.column!=prev_col || cursor.line!=prev_line)) { + + if (!selection.active) { + selection.active=true; + selection.selecting_mode=Selection::MODE_POINTER; + selection.from_column=prev_col; + selection.from_line=prev_line; + selection.to_column=cursor.column; + selection.to_line=cursor.line; + + if (selection.from_line>selection.to_line || (selection.from_line==selection.to_line && selection.from_column>selection.to_column)) { + SWAP(selection.from_column,selection.to_column); + SWAP(selection.from_line,selection.to_line); + selection.shiftclick_left=false; + } else { + selection.shiftclick_left=true; + } + selection.selecting_line=prev_line; + selection.selecting_column=prev_col; + update(); + } else { + + if (cursor.lineselection.to_line || (cursor.line==selection.to_line && cursor.column>=selection.to_column)) { + selection.to_column=cursor.column; + selection.to_line=cursor.line; + + } else if (!selection.shiftclick_left) { + + selection.from_column=cursor.column; + selection.from_line=cursor.line; + } else { + + selection.to_column=cursor.column; + selection.to_line=cursor.line; + } + + if (selection.from_line>selection.to_line || (selection.from_line==selection.to_line && selection.from_column>selection.to_column)) { + SWAP(selection.from_column,selection.to_column); + SWAP(selection.from_line,selection.to_line); + } + update(); + } + + + + + + + + } else { + + //if sel active and dblick last time < something + + //else + selection.active=false; + selection.selecting_mode=Selection::MODE_POINTER; + selection.selecting_line=row; + selection.selecting_column=col; + } + + + if (!mb.doubleclick && (OS::get_singleton()->get_ticks_msec()-last_dblclk)<600) { + //tripleclick select line + select(cursor.line,0,cursor.line,text[cursor.line].length()); + last_dblclk=0; + + } else if (mb.doubleclick && text[cursor.line].length()) { + + //doubleclick select world + String s = text[cursor.line]; + int beg=CLAMP(cursor.column,0,s.length()); + int end=beg; + + if (s[beg]>32 || beg==s.length()) { + + bool symbol = beg < s.length() && _is_symbol(s[beg]); //not sure if right but most editors behave like this + + while(beg>0 && s[beg-1]>32 && (symbol==_is_symbol(s[beg-1]))) { + beg--; + } + while(end32 && (symbol==_is_symbol(s[end+1]))) { + end++; + } + + if (endget_ticks_msec(); + + } + + update(); + } + } else { + + selection.selecting_mode=Selection::MODE_NONE; + // notify to show soft keyboard + notification(NOTIFICATION_FOCUS_ENTER); + } + } break; + case InputEvent::MOUSE_MOTION: { + + const InputEventMouseMotion &mm=p_input_event.mouse_motion; + + if (mm.button_mask&BUTTON_MASK_LEFT) { + + int row,col; + if (!_get_mouse_pos(Point2i(mm.x,mm.y), row,col)) + return; + + if (selection.selecting_mode==Selection::MODE_POINTER) { + + select(selection.selecting_line,selection.selecting_column,row,col); + + cursor_set_line( row ); + cursor_set_column( col ); + update(); + + } + + } + + } break; + + case InputEvent::KEY: { + + InputEventKey k=p_input_event.key; + + if (!k.pressed) + return; + + if (completion_active) { + if (readonly) + break; - } + bool valid=true; + if (k.mod.command || k.mod.alt || k.mod.meta) + valid=false; + + if (valid) { + + if (k.scancode==KEY_UP) { + + if (completion_index>0) { + completion_index--; + completion_current=completion_options[completion_index]; + update(); + } + accept_event(); + return; + } + + + if (k.scancode==KEY_DOWN) { + + if (completion_index=completion_options.size()) + completion_index=completion_options.size()-1; + completion_current=completion_options[completion_index]; + update(); + accept_event(); + return; + } + + if (k.scancode==KEY_HOME) { + + completion_index=0; + completion_current=completion_options[completion_index]; + update(); + accept_event(); + return; + } + + if (k.scancode==KEY_END) { + + completion_index=completion_options.size()-1; + completion_current=completion_options[completion_index]; + update(); + accept_event(); + return; + } + + + if (k.scancode==KEY_DOWN) { + + if (completion_index32) { + + if (cursor.column=32) { + bool clear=false; + bool unselect=false; + bool dobreak=false; + + switch(k.scancode) { + + case KEY_TAB: { + + String txt = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); + String prev_txt=txt; + + if (k.mod.shift) { + + for(int i=0;i0 && txt[i-1]=='\n') || (i==0 /*&& selection.from_column==0*/)) && (txt[i]=='\t' || txt[i]==' ')) { + txt.remove(i); + //i--; + } + } + } else { + + for(int i=0;i0 && txt[i-1]=='\n') || (i==0 /*&& selection.from_column==0*/))) { + txt=txt.insert(i,"\t"); + //i--; + } + } + } + + if (txt!=prev_txt) { + + int sel_line=selection.from_line; + int sel_column=selection.from_column; + + cursor_set_line(selection.from_line); + cursor_set_column(selection.from_column); + _begin_compex_operation(); + _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); + _insert_text_at_cursor(txt); + _end_compex_operation(); + selection.active=true; + selection.from_column=sel_column; + selection.from_line=sel_line; + selection.to_column=cursor.column; + selection.to_line=cursor.line; + update(); + } + + dobreak=true; + accept_event(); + + } break; + case KEY_X: + case KEY_C: + //special keys often used with control, wait... + clear=(!k.mod.command || k.mod.shift || k.mod.alt ); + break; + case KEY_DELETE: + case KEY_BACKSPACE: + accept_event(); + clear=true; dobreak=true; + break; + case KEY_LEFT: + case KEY_RIGHT: + case KEY_UP: + case KEY_DOWN: + case KEY_PAGEUP: + case KEY_PAGEDOWN: + case KEY_HOME: + case KEY_END: + // ignore arrows if any modifiers are held (shift = selecting, others may be used for editor hotkeys) + if (k.mod.command || k.mod.shift || k.mod.alt || k.mod.command) + break; + unselect=true; + break; + + default: + if (k.unicode>=32 && !k.mod.command && !k.mod.alt && !k.mod.meta) + clear=true; + if (auto_brace_completion_enabled && _is_pair_left_symbol(k.unicode)) + clear=false; + } + + if (unselect) { + selection.active=false; + selection.selecting_mode=Selection::MODE_NONE; + update(); + } + if (clear) { + + selection.active=false; + update(); + _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); + cursor_set_line(selection.from_line); + cursor_set_column(selection.from_column); + update(); + } + if (dobreak) + break; + } + + selection.selecting_test=false; + + bool scancode_handled=true; + + // special scancode test... + + switch (k.scancode) { + + case KEY_ENTER: + case KEY_RETURN: { - if (readonly) - break; + if (readonly) + break; - accept_event(); - } else { - - break; - } - } + String ins="\n"; + + //keep indentation + for(int i=0;i0 && cc<=text[cursor.line].length() && text[cursor.line][cursor.column-1]=='\t') { + //simple unindent + + backspace_at_cursor(); + } + } else { + //simple indent + _insert_text_at_cursor("\t"); + } + } + + } break; + case KEY_BACKSPACE: { + if (readonly) + break; + backspace_at_cursor(); + + } break; + case KEY_LEFT: { + + if (k.mod.shift) + _pre_shift_selection(); + +#ifdef APPLE_STYLE_KEYS + if (k.mod.command) { + cursor_set_column(0); + } else if (k.mod.alt) { + +#else + if (k.mod.alt) { + scancode_handled=false; + break; + } else if (k.mod.command) { +#endif + bool prev_char=false; + int cc=cursor.column; + while (cc>0) { + + bool ischar=_is_text_char(text[cursor.line][cc-1]); + + if (prev_char && !ischar) + break; + + prev_char=ischar; + cc--; + + } + + cursor_set_column(cc); + + } else if (cursor.column==0) { + + if (cursor.line>0) { + cursor_set_line(cursor.line-1); + cursor_set_column(text[cursor.line].length()); + } + } else { + cursor_set_column(cursor_get_column()-1); + } + + if (k.mod.shift) + _post_shift_selection(); + + } break; + case KEY_RIGHT: { + + if (k.mod.shift) + _pre_shift_selection(); + +#ifdef APPLE_STYLE_KEYS + if (k.mod.command) { + cursor_set_column(text[cursor.line].length()); + } else if (k.mod.alt) { +#else + if (k.mod.alt) { + scancode_handled=false; + break; + } else if (k.mod.command) { +#endif + bool prev_char=false; + int cc=cursor.column; + while (ccset_clipboard(clipboard); + cursor_set_line(cursor.line); + cursor_set_column(0); + _remove_text(cursor.line,0,cursor.line,text[cursor.line].length()); + + backspace_at_cursor(); + update(); + cursor_set_line(cursor.line+1); + cut_copy_line = true; + + } + else + { + + String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); + OS::get_singleton()->set_clipboard(clipboard); + + cursor_set_line(selection.from_line); + cursor_set_column(selection.from_column); + + _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); + selection.active=false; + selection.selecting_mode=Selection::MODE_NONE; + update(); + cut_copy_line = false; + } + + } break; + case KEY_C: { + + if (!k.mod.command || k.mod.shift || k.mod.alt) { + scancode_handled=false; + break; + } + + if (!selection.active){ + String clipboard = _base_get_text(cursor.line,0,cursor.line,text[cursor.line].length()); + OS::get_singleton()->set_clipboard(clipboard); + cut_copy_line = true; + } + else{ + String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); + OS::get_singleton()->set_clipboard(clipboard); + cut_copy_line = false; + } + } break; + case KEY_Z: { + + if (!k.mod.command) { + scancode_handled=false; + break; + } + + if (k.mod.shift) + redo(); + else + undo(); + } break; + case KEY_V: { + + if (!k.mod.command || k.mod.shift || k.mod.alt) { + scancode_handled=false; + break; + } + + String clipboard = OS::get_singleton()->get_clipboard(); + + if (selection.active) { + selection.active=false; + _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); + cursor_set_line(selection.from_line); + cursor_set_column(selection.from_column); + + } + else if (cut_copy_line) + { + cursor_set_column(0); + String ins="\n"; + clipboard += ins; + } + + _insert_text_at_cursor(clipboard); + + update(); + } break; + case KEY_SPACE: { + if (completion_enabled && k.mod.command) { + + query_code_comple(); + scancode_handled=true; + } else { + scancode_handled=false; + } + + } break; + + case KEY_U:{ + if (!k.mod.command || k.mod.shift || k.mod.alt) { + scancode_handled=false; + break; + } + else { + if (selection.active) { + int ini = selection.from_line; + int end = selection.to_line; + for (int i=ini; i<= end; i++) + { + if (text[i][0] == '#') + _remove_text(i,0,i,1); + } + } + else{ + if (text[cursor.line][0] == '#') + _remove_text(cursor.line,0,cursor.line,1); + } + update(); + } + break;} + + default: { + + scancode_handled=false; + } break; + + } + + if (scancode_handled) + accept_event(); + /* + if (!scancode_handled && !k.mod.command && !k.mod.alt) { + + if (k.unicode>=32) { + + if (readonly) + break; + + accept_event(); + } else { + + break; + } + } */ - if (!scancode_handled && !k.mod.command && !k.mod.alt) { //for german kbds - - if (k.unicode>=32) { - - if (readonly) - break; - - const CharType chr[2] = {k.unicode, 0}; - - if(auto_brace_completion_enabled && _is_pair_symbol(chr[0])) { - _consume_pair_symbol(chr[0]); - } else { - _insert_text_at_cursor(chr); - } - - accept_event(); - } else { - - break; - } - } - - - if (!selection.selecting_test) { - - selection.selecting_mode=Selection::MODE_NONE; - } - - return; - } break; - - } - + if (!scancode_handled && !k.mod.command && !k.mod.alt) { //for german kbds + + if (k.unicode>=32) { + + if (readonly) + break; + + const CharType chr[2] = {k.unicode, 0}; + + if(auto_brace_completion_enabled && _is_pair_symbol(chr[0])) { + _consume_pair_symbol(chr[0]); + } else { + _insert_text_at_cursor(chr); + } + + accept_event(); + } else { + + break; + } + } + + + if (!selection.selecting_test) { + + selection.selecting_mode=Selection::MODE_NONE; + } + + return; + } break; + + } + } void TextEdit::_pre_shift_selection() { - - - if (!selection.active || selection.selecting_mode!=Selection::MODE_SHIFT) { - - selection.selecting_line=cursor.line; - selection.selecting_column=cursor.column; - selection.active=true; - selection.selecting_mode=Selection::MODE_SHIFT; - } + + + if (!selection.active || selection.selecting_mode!=Selection::MODE_SHIFT) { + + selection.selecting_line=cursor.line; + selection.selecting_column=cursor.column; + selection.active=true; + selection.selecting_mode=Selection::MODE_SHIFT; + } } void TextEdit::_post_shift_selection() { - - - if (selection.active && selection.selecting_mode==Selection::MODE_SHIFT) { - - select(selection.selecting_line,selection.selecting_column,cursor.line,cursor.column); - update(); - } - - - selection.selecting_test=true; + + + if (selection.active && selection.selecting_mode==Selection::MODE_SHIFT) { + + select(selection.selecting_line,selection.selecting_column,cursor.line,cursor.column); + update(); + } + + + selection.selecting_test=true; } /**** TEXT EDIT CORE API ****/ void TextEdit::_base_insert_text(int p_line, int p_char,const String& p_text,int &r_end_line,int &r_end_column) { - - //save for undo... - ERR_FAIL_INDEX(p_line,text.size()); - ERR_FAIL_COND(p_char<0); - - /* STEP 1 add spaces if the char is greater than the end of the line */ - while(p_char>text[p_line].length()) { - - text.set(p_line,text[p_line]+String::chr(' ')); - } - - /* STEP 2 separate dest string in pre and post text */ - - String preinsert_text = text[p_line].substr(0,p_char); - String postinsert_text = text[p_line].substr(p_char,text[p_line].size()); - - /* STEP 3 remove \r from source text and separate in substrings */ - - //buh bye \r and split - Vector substrings = p_text.replace("\r","").split("\n"); - - - for(int i=0;ipush_call(this,"_text_changed_emit"); - text_changed_dirty=true; - } - + + //save for undo... + ERR_FAIL_INDEX(p_line,text.size()); + ERR_FAIL_COND(p_char<0); + + /* STEP 1 add spaces if the char is greater than the end of the line */ + while(p_char>text[p_line].length()) { + + text.set(p_line,text[p_line]+String::chr(' ')); + } + + /* STEP 2 separate dest string in pre and post text */ + + String preinsert_text = text[p_line].substr(0,p_char); + String postinsert_text = text[p_line].substr(p_char,text[p_line].size()); + + /* STEP 3 remove \r from source text and separate in substrings */ + + //buh bye \r and split + Vector substrings = p_text.replace("\r","").split("\n"); + + + for(int i=0;ipush_call(this,"_text_changed_emit"); + text_changed_dirty=true; + } + } String TextEdit::_base_get_text(int p_from_line, int p_from_column,int p_to_line,int p_to_column) const { - - ERR_FAIL_INDEX_V(p_from_line,text.size(),String()); - ERR_FAIL_INDEX_V(p_from_column,text[p_from_line].length()+1,String()); - ERR_FAIL_INDEX_V(p_to_line,text.size(),String()); - ERR_FAIL_INDEX_V(p_to_column,text[p_to_line].length()+1,String()); - ERR_FAIL_COND_V(p_to_line < p_from_line ,String()); // from > to - ERR_FAIL_COND_V(p_to_line == p_from_line && p_to_column to - - String ret; - - for(int i=p_from_line;i<=p_to_line;i++) { - - int begin = (i==p_from_line)?p_from_column:0; - int end = (i==p_to_line)?p_to_column:text[i].length(); - - if (i>p_from_line) - ret+="\n"; - ret+=text[i].substr(begin,end-begin); - } - - return ret; + + ERR_FAIL_INDEX_V(p_from_line,text.size(),String()); + ERR_FAIL_INDEX_V(p_from_column,text[p_from_line].length()+1,String()); + ERR_FAIL_INDEX_V(p_to_line,text.size(),String()); + ERR_FAIL_INDEX_V(p_to_column,text[p_to_line].length()+1,String()); + ERR_FAIL_COND_V(p_to_line < p_from_line ,String()); // from > to + ERR_FAIL_COND_V(p_to_line == p_from_line && p_to_column to + + String ret; + + for(int i=p_from_line;i<=p_to_line;i++) { + + int begin = (i==p_from_line)?p_from_column:0; + int end = (i==p_to_line)?p_to_column:text[i].length(); + + if (i>p_from_line) + ret+="\n"; + ret+=text[i].substr(begin,end-begin); + } + + return ret; } void TextEdit::_base_remove_text(int p_from_line, int p_from_column,int p_to_line,int p_to_column) { - - ERR_FAIL_INDEX(p_from_line,text.size()); - ERR_FAIL_INDEX(p_from_column,text[p_from_line].length()+1); - ERR_FAIL_INDEX(p_to_line,text.size()); - ERR_FAIL_INDEX(p_to_column,text[p_to_line].length()+1); - ERR_FAIL_COND(p_to_line < p_from_line ); // from > to - ERR_FAIL_COND(p_to_line == p_from_line && p_to_column to - - - String pre_text = text[p_from_line].substr(0,p_from_column); - String post_text = text[p_to_line].substr(p_to_column,text[p_to_line].length()); - - for(int i=p_from_line;ipush_call(this,"_text_changed_emit"); - text_changed_dirty=true; - } + + ERR_FAIL_INDEX(p_from_line,text.size()); + ERR_FAIL_INDEX(p_from_column,text[p_from_line].length()+1); + ERR_FAIL_INDEX(p_to_line,text.size()); + ERR_FAIL_INDEX(p_to_column,text[p_to_line].length()+1); + ERR_FAIL_COND(p_to_line < p_from_line ); // from > to + ERR_FAIL_COND(p_to_line == p_from_line && p_to_column to + + + String pre_text = text[p_from_line].substr(0,p_from_column); + String post_text = text[p_to_line].substr(p_to_column,text[p_to_line].length()); + + for(int i=p_from_line;ipush_call(this,"_text_changed_emit"); + text_changed_dirty=true; + } } void TextEdit::_insert_text(int p_line, int p_char,const String& p_text,int *r_end_line,int *r_end_column) { - - if (!setting_text) - idle_detect->start(); - - if (undo_enabled) { - _clear_redo(); - } - - int retline,retchar; - _base_insert_text(p_line,p_char,p_text,retline,retchar); - if (r_end_line) - *r_end_line=retline; - if (r_end_column) - *r_end_column=retchar; - - if (!undo_enabled) - return; - - /* UNDO!! */ - TextOperation op; - op.type=TextOperation::TYPE_INSERT; - op.from_line=p_line; - op.from_column=p_char; - op.to_line=retline; - op.to_column=retchar; - op.text=p_text; - op.version=++version; - op.chain_forward=false; - op.chain_backward=false; - - //see if it shold just be set as current op - if (current_op.type!=op.type) { - _push_current_op(); - current_op=op; - - return; //set as current op, return - } - //see if it can be merged - if (current_op.to_line!=p_line || current_op.to_column!=p_char) { - _push_current_op(); - current_op=op; - return; //set as current op, return - } - //merge current op - - current_op.text+=p_text; - current_op.to_column=retchar; - current_op.to_line=retline; - current_op.version=op.version; - + + if (!setting_text) + idle_detect->start(); + + if (undo_enabled) { + _clear_redo(); + } + + int retline,retchar; + _base_insert_text(p_line,p_char,p_text,retline,retchar); + if (r_end_line) + *r_end_line=retline; + if (r_end_column) + *r_end_column=retchar; + + if (!undo_enabled) + return; + + /* UNDO!! */ + TextOperation op; + op.type=TextOperation::TYPE_INSERT; + op.from_line=p_line; + op.from_column=p_char; + op.to_line=retline; + op.to_column=retchar; + op.text=p_text; + op.version=++version; + op.chain_forward=false; + op.chain_backward=false; + + //see if it shold just be set as current op + if (current_op.type!=op.type) { + _push_current_op(); + current_op=op; + + return; //set as current op, return + } + //see if it can be merged + if (current_op.to_line!=p_line || current_op.to_column!=p_char) { + _push_current_op(); + current_op=op; + return; //set as current op, return + } + //merge current op + + current_op.text+=p_text; + current_op.to_column=retchar; + current_op.to_line=retline; + current_op.version=op.version; + } void TextEdit::_remove_text(int p_from_line, int p_from_column,int p_to_line,int p_to_column) { - - if (!setting_text) - idle_detect->start(); - - String text; - if (undo_enabled) { - _clear_redo(); - text=_base_get_text(p_from_line,p_from_column,p_to_line,p_to_column); - } - - _base_remove_text(p_from_line,p_from_column,p_to_line,p_to_column); - - if (!undo_enabled) - return; - - /* UNDO!! */ - TextOperation op; - op.type=TextOperation::TYPE_REMOVE; - op.from_line=p_from_line; - op.from_column=p_from_column; - op.to_line=p_to_line; - op.to_column=p_to_column; - op.text=text; - op.version=++version; - op.chain_forward=false; - op.chain_backward=false; - - //see if it shold just be set as current op - if (current_op.type!=op.type) { - _push_current_op(); - current_op=op; - return; //set as current op, return - } - //see if it can be merged - if (current_op.from_line==p_to_line && current_op.from_column==p_to_column) { - //basckace or similar - current_op.text=text+current_op.text; - current_op.from_line=p_from_line; - current_op.from_column=p_from_column; - return; //update current op - } - if (current_op.from_line==p_from_line && current_op.from_column==p_from_column) { - - //current_op.text=text+current_op.text; - //current_op.from_line=p_from_line; - //current_op.from_column=p_from_column; - //return; //update current op - } - - _push_current_op(); - current_op=op; - + + if (!setting_text) + idle_detect->start(); + + String text; + if (undo_enabled) { + _clear_redo(); + text=_base_get_text(p_from_line,p_from_column,p_to_line,p_to_column); + } + + _base_remove_text(p_from_line,p_from_column,p_to_line,p_to_column); + + if (!undo_enabled) + return; + + /* UNDO!! */ + TextOperation op; + op.type=TextOperation::TYPE_REMOVE; + op.from_line=p_from_line; + op.from_column=p_from_column; + op.to_line=p_to_line; + op.to_column=p_to_column; + op.text=text; + op.version=++version; + op.chain_forward=false; + op.chain_backward=false; + + //see if it shold just be set as current op + if (current_op.type!=op.type) { + _push_current_op(); + current_op=op; + return; //set as current op, return + } + //see if it can be merged + if (current_op.from_line==p_to_line && current_op.from_column==p_to_column) { + //basckace or similar + current_op.text=text+current_op.text; + current_op.from_line=p_from_line; + current_op.from_column=p_from_column; + return; //update current op + } + if (current_op.from_line==p_from_line && current_op.from_column==p_from_column) { + + //current_op.text=text+current_op.text; + //current_op.from_line=p_from_line; + //current_op.from_column=p_from_column; + //return; //update current op + } + + _push_current_op(); + current_op=op; + } void TextEdit::_insert_text_at_cursor(const String& p_text) { - - int new_column,new_line; - _insert_text(cursor.line,cursor.column,p_text,&new_line,&new_column); - cursor_set_line(new_line); - cursor_set_column(new_column); - - update(); + + int new_column,new_line; + _insert_text(cursor.line,cursor.column,p_text,&new_line,&new_column); + cursor_set_line(new_line); + cursor_set_column(new_column); + + update(); } int TextEdit::get_char_count() { - - int totalsize=0; - - for (int i=0;i0) - totalsize++; // incliude \n - totalsize+=text[i].length(); - } - - return totalsize; // omit last \n + + int totalsize=0; + + for (int i=0;i0) + totalsize++; // incliude \n + totalsize+=text[i].length(); + } + + return totalsize; // omit last \n } Size2 TextEdit::get_minimum_size() { - - return cache.style_normal->get_minimum_size(); + + return cache.style_normal->get_minimum_size(); } int TextEdit::get_visible_rows() const { - - int total=cache.size.height; - total-=cache.style_normal->get_minimum_size().height; - total/=get_row_height(); - return total; + + int total=cache.size.height; + total-=cache.style_normal->get_minimum_size().height; + total/=get_row_height(); + return total; } void TextEdit::adjust_viewport_to_cursor() { - - if (cursor.line_ofs>cursor.line) - cursor.line_ofs=cursor.line; - - int visible_width=cache.size.width-cache.style_normal->get_minimum_size().width-cache.line_number_w; - if (v_scroll->is_visible()) - visible_width-=v_scroll->get_combined_minimum_size().width; - visible_width-=20; // give it a little more space - - - //printf("rowofs %i, visrows %i, cursor.line %i\n",cursor.line_ofs,get_visible_rows(),cursor.line); - - int visible_rows = get_visible_rows(); - if (h_scroll->is_visible()) - visible_rows-=((h_scroll->get_combined_minimum_size().height-1)/get_row_height()); - - if (cursor.line>=(cursor.line_ofs+visible_rows)) - cursor.line_ofs=cursor.line-visible_rows+1; - if (cursor.line(cursor.x_ofs+visible_width)) - cursor.x_ofs=cursor_x-visible_width+1; - - if (cursor_x < cursor.x_ofs) - cursor.x_ofs=cursor_x; - - update(); -/* + + if (cursor.line_ofs>cursor.line) + cursor.line_ofs=cursor.line; + + int visible_width=cache.size.width-cache.style_normal->get_minimum_size().width-cache.line_number_w; + if (v_scroll->is_visible()) + visible_width-=v_scroll->get_combined_minimum_size().width; + visible_width-=20; // give it a little more space + + + //printf("rowofs %i, visrows %i, cursor.line %i\n",cursor.line_ofs,get_visible_rows(),cursor.line); + + int visible_rows = get_visible_rows(); + if (h_scroll->is_visible()) + visible_rows-=((h_scroll->get_combined_minimum_size().height-1)/get_row_height()); + + if (cursor.line>=(cursor.line_ofs+visible_rows)) + cursor.line_ofs=cursor.line-visible_rows+1; + if (cursor.line(cursor.x_ofs+visible_width)) + cursor.x_ofs=cursor_x-visible_width+1; + + if (cursor_x < cursor.x_ofs) + cursor.x_ofs=cursor_x; + + update(); + /* get_range()->set_max(text.size()); - + get_range()->set_page(get_visible_rows()); - + get_range()->set((int)cursor.line_ofs); */ - - + + } void TextEdit::cursor_set_column(int p_col) { - - if (p_col<0) - p_col=0; - - cursor.column=p_col; - if (cursor.column > get_line( cursor.line ).length()) - cursor.column=get_line( cursor.line ).length(); - - cursor.last_fit_x=get_column_x_offset(cursor.column,get_line(cursor.line)); - - adjust_viewport_to_cursor(); - - if (!cursor_changed_dirty) { - if (is_inside_tree()) - MessageQueue::get_singleton()->push_call(this,"_cursor_changed_emit"); - cursor_changed_dirty=true; - } - + + if (p_col<0) + p_col=0; + + cursor.column=p_col; + if (cursor.column > get_line( cursor.line ).length()) + cursor.column=get_line( cursor.line ).length(); + + cursor.last_fit_x=get_column_x_offset(cursor.column,get_line(cursor.line)); + + adjust_viewport_to_cursor(); + + if (!cursor_changed_dirty) { + if (is_inside_tree()) + MessageQueue::get_singleton()->push_call(this,"_cursor_changed_emit"); + cursor_changed_dirty=true; + } + } void TextEdit::cursor_set_line(int p_row) { - - if (setting_row) - return; - - setting_row=true; - if (p_row<0) - p_row=0; - - - if (p_row>=(int)text.size()) - p_row=(int)text.size()-1; - - cursor.line=p_row; - cursor.column=get_char_pos_for( cursor.last_fit_x, get_line( cursor.line) ); - - - adjust_viewport_to_cursor(); - - setting_row=false; - - - if (!cursor_changed_dirty) { - if (is_inside_tree()) - MessageQueue::get_singleton()->push_call(this,"_cursor_changed_emit"); - cursor_changed_dirty=true; - } - + + if (setting_row) + return; + + setting_row=true; + if (p_row<0) + p_row=0; + + + if (p_row>=(int)text.size()) + p_row=(int)text.size()-1; + + cursor.line=p_row; + cursor.column=get_char_pos_for( cursor.last_fit_x, get_line( cursor.line) ); + + + adjust_viewport_to_cursor(); + + setting_row=false; + + + if (!cursor_changed_dirty) { + if (is_inside_tree()) + MessageQueue::get_singleton()->push_call(this,"_cursor_changed_emit"); + cursor_changed_dirty=true; + } + } int TextEdit::cursor_get_column() const { - - return cursor.column; + + return cursor.column; } int TextEdit::cursor_get_line() const { - - return cursor.line; + + return cursor.line; } void TextEdit::_scroll_moved(double p_to_val) { - - if (updating_scrolls) - return; - - if (h_scroll->is_visible()) - cursor.x_ofs=h_scroll->get_val(); - if (v_scroll->is_visible()) - cursor.line_ofs=v_scroll->get_val(); - update(); + + if (updating_scrolls) + return; + + if (h_scroll->is_visible()) + cursor.x_ofs=h_scroll->get_val(); + if (v_scroll->is_visible()) + cursor.line_ofs=v_scroll->get_val(); + update(); } @@ -2415,798 +2451,798 @@ void TextEdit::_scroll_moved(double p_to_val) { int TextEdit::get_row_height() const { - - return cache.font->get_height()+cache.line_spacing; + + return cache.font->get_height()+cache.line_spacing; } int TextEdit::get_char_pos_for(int p_px,String p_str) const { - - int px=0; - int c=0; - - int tab_w = cache.font->get_char_size(' ').width*tab_size; - - while (cget_char_size(p_str[c],p_str[c+1]).width; - } - - if (p_px<(px+w/2)) - break; - px+=w; - c++; - } - - return c; + + int px=0; + int c=0; + + int tab_w = cache.font->get_char_size(' ').width*tab_size; + + while (cget_char_size(p_str[c],p_str[c+1]).width; + } + + if (p_px<(px+w/2)) + break; + px+=w; + c++; + } + + return c; } int TextEdit::get_column_x_offset(int p_char,String p_str) { - - int px=0; - - int tab_w = cache.font->get_char_size(' ').width*tab_size; - - for (int i=0;i=p_str.length()) - break; - - if (p_str[i]=='\t') { - - int left = px%tab_w; - if (left==0) - px+=tab_w; - else - px+=tab_w-px%tab_w; // is right... - - } else { - px+=cache.font->get_char_size(p_str[i],p_str[i+1]).width; - } - } - - return px; - + + int px=0; + + int tab_w = cache.font->get_char_size(' ').width*tab_size; + + for (int i=0;i=p_str.length()) + break; + + if (p_str[i]=='\t') { + + int left = px%tab_w; + if (left==0) + px+=tab_w; + else + px+=tab_w-px%tab_w; // is right... + + } else { + px+=cache.font->get_char_size(p_str[i],p_str[i+1]).width; + } + } + + return px; + } void TextEdit::insert_text_at_cursor(const String& p_text) { - - if (selection.active) { - - cursor_set_line(selection.from_line); - cursor_set_column(selection.from_column); - - _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); - selection.active=false; - selection.selecting_mode=Selection::MODE_NONE; - - } - - _insert_text_at_cursor(p_text); - update(); - + + if (selection.active) { + + cursor_set_line(selection.from_line); + cursor_set_column(selection.from_column); + + _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); + selection.active=false; + selection.selecting_mode=Selection::MODE_NONE; + + } + + _insert_text_at_cursor(p_text); + update(); + } Control::CursorShape TextEdit::get_cursor_shape(const Point2& p_pos) const { - if(completion_active && completion_rect.has_point(p_pos)) { - return CURSOR_ARROW; - } - return CURSOR_IBEAM; + if(completion_active && completion_rect.has_point(p_pos)) { + return CURSOR_ARROW; + } + return CURSOR_IBEAM; } void TextEdit::set_text(String p_text){ - - setting_text=true; - _clear(); - _insert_text_at_cursor(p_text); - - cursor.column=0; - cursor.line=0; - cursor.x_ofs=0; - cursor.line_ofs=0; - cursor.last_fit_x=0; - cursor_set_line(0); - cursor_set_column(0); - update(); - setting_text=false; - - //get_range()->set(0); + + setting_text=true; + _clear(); + _insert_text_at_cursor(p_text); + + cursor.column=0; + cursor.line=0; + cursor.x_ofs=0; + cursor.line_ofs=0; + cursor.last_fit_x=0; + cursor_set_line(0); + cursor_set_column(0); + update(); + setting_text=false; + + //get_range()->set(0); }; String TextEdit::get_text() { - String longthing; - int len = text.size(); - for (int i=0;i=text.size()) - return ""; - - return text[line]; - + + if (line<0 || line>=text.size()) + return ""; + + return text[line]; + }; void TextEdit::_clear() { - - clear_undo_history(); - text.clear(); - cursor.column=0; - cursor.line=0; - cursor.x_ofs=0; - cursor.line_ofs=0; - cursor.last_fit_x=0; + + clear_undo_history(); + text.clear(); + cursor.column=0; + cursor.line=0; + cursor.x_ofs=0; + cursor.line_ofs=0; + cursor.last_fit_x=0; } void TextEdit::clear() { - - setting_text=true; - _clear(); - setting_text=false; - + + setting_text=true; + _clear(); + setting_text=false; + }; void TextEdit::set_readonly(bool p_readonly) { - - - readonly=p_readonly; + + + readonly=p_readonly; } void TextEdit::set_wrap(bool p_wrap) { - - wrap=p_wrap; + + wrap=p_wrap; } void TextEdit::set_max_chars(int p_max_chars) { - - max_chars=p_max_chars; + + max_chars=p_max_chars; } void TextEdit::_update_caches() { - - cache.style_normal=get_stylebox("normal"); - cache.style_focus=get_stylebox("focus"); - cache.font=get_font("font"); - cache.font_color=get_color("font_color"); - cache.font_selected_color=get_color("font_selected_color"); - cache.keyword_color=get_color("keyword_color"); - cache.selection_color=get_color("selection_color"); - cache.mark_color=get_color("mark_color"); - cache.current_line_color=get_color("current_line_color"); - cache.breakpoint_color=get_color("breakpoint_color"); - cache.brace_mismatch_color=get_color("brace_mismatch_color"); - cache.line_spacing=get_constant("line_spacing"); - cache.row_height = cache.font->get_height() + cache.line_spacing; - cache.tab_icon=get_icon("tab"); - text.set_font(cache.font); - + + cache.style_normal=get_stylebox("normal"); + cache.style_focus=get_stylebox("focus"); + cache.font=get_font("font"); + cache.font_color=get_color("font_color"); + cache.font_selected_color=get_color("font_selected_color"); + cache.keyword_color=get_color("keyword_color"); + cache.selection_color=get_color("selection_color"); + cache.mark_color=get_color("mark_color"); + cache.current_line_color=get_color("current_line_color"); + cache.breakpoint_color=get_color("breakpoint_color"); + cache.brace_mismatch_color=get_color("brace_mismatch_color"); + cache.line_spacing=get_constant("line_spacing"); + cache.row_height = cache.font->get_height() + cache.line_spacing; + cache.tab_icon=get_icon("tab"); + text.set_font(cache.font); + } void TextEdit::clear_colors() { - - keywords.clear(); - color_regions.clear();; - text.clear_caches(); - custom_bg_color=Color(0,0,0,0); + + keywords.clear(); + color_regions.clear();; + text.clear_caches(); + custom_bg_color=Color(0,0,0,0); } void TextEdit::set_custom_bg_color(const Color& p_color) { - - custom_bg_color=p_color; - update(); + + custom_bg_color=p_color; + update(); } void TextEdit::add_keyword_color(const String& p_keyword,const Color& p_color) { - - keywords[p_keyword]=p_color; - update(); - + + keywords[p_keyword]=p_color; + update(); + } void TextEdit::add_color_region(const String& p_begin_key,const String& p_end_key,const Color &p_color,bool p_line_only) { - - color_regions.push_back(ColorRegion(p_begin_key,p_end_key,p_color,p_line_only)); - text.clear_caches(); - update(); - + + color_regions.push_back(ColorRegion(p_begin_key,p_end_key,p_color,p_line_only)); + text.clear_caches(); + update(); + } void TextEdit::set_symbol_color(const Color& p_color) { - - symbol_color=p_color; - update(); + + symbol_color=p_color; + update(); } void TextEdit::set_syntax_coloring(bool p_enabled) { - - syntax_coloring=p_enabled; - update(); + + syntax_coloring=p_enabled; + update(); } bool TextEdit::is_syntax_coloring_enabled() const { - - return syntax_coloring; + + return syntax_coloring; } void TextEdit::cut() { - - if (!selection.active) - return; - - String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); - OS::get_singleton()->set_clipboard(clipboard); - - cursor_set_line(selection.from_line); - cursor_set_column(selection.from_column); - - _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); - selection.active=false; - selection.selecting_mode=Selection::MODE_NONE; - update(); - + + if (!selection.active) + return; + + String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); + OS::get_singleton()->set_clipboard(clipboard); + + cursor_set_line(selection.from_line); + cursor_set_column(selection.from_column); + + _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); + selection.active=false; + selection.selecting_mode=Selection::MODE_NONE; + update(); + } void TextEdit::copy() { - - if (!selection.active) - return; - - String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); - OS::get_singleton()->set_clipboard(clipboard); - + + if (!selection.active) + return; + + String clipboard = _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); + OS::get_singleton()->set_clipboard(clipboard); + } void TextEdit::paste() { - - if (selection.active) { - - cursor_set_line(selection.from_line); - cursor_set_column(selection.from_column); - - _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); - selection.active=false; - selection.selecting_mode=Selection::MODE_NONE; - - } - - String clipboard = OS::get_singleton()->get_clipboard(); - _insert_text_at_cursor(clipboard); - update(); - + + if (selection.active) { + + cursor_set_line(selection.from_line); + cursor_set_column(selection.from_column); + + _remove_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); + selection.active=false; + selection.selecting_mode=Selection::MODE_NONE; + + } + + String clipboard = OS::get_singleton()->get_clipboard(); + _insert_text_at_cursor(clipboard); + update(); + } void TextEdit::select_all() { - - if (text.size()==1 && text[0].length()==0) - return; - selection.active=true; - selection.from_line=0; - selection.from_column=0; - selection.to_line=text.size()-1; - selection.to_column=text[selection.to_line].size(); - selection.selecting_mode=Selection::MODE_NONE; - update(); - + + if (text.size()==1 && text[0].length()==0) + return; + selection.active=true; + selection.from_line=0; + selection.from_column=0; + selection.to_line=text.size()-1; + selection.to_column=text[selection.to_line].size(); + selection.selecting_mode=Selection::MODE_NONE; + update(); + } void TextEdit::deselect() { - - selection.active=false; - update(); + + selection.active=false; + update(); } void TextEdit::select(int p_from_line,int p_from_column,int p_to_line,int p_to_column) { - - if (p_from_line>=text.size()) - p_from_line=text.size()-1; - if (p_from_column>=text[p_from_line].length()) - p_from_column=text[p_from_line].length(); - - if (p_to_line>=text.size()) - p_to_line=text.size()-1; - if (p_to_column>=text[p_to_line].length()) - p_to_column=text[p_to_line].length(); - - selection.from_line=p_from_line; - selection.from_column=p_from_column; - selection.to_line=p_to_line; - selection.to_column=p_to_column; - - selection.active=true; - - if (selection.from_line==selection.to_line) { - - if (selection.from_column==selection.to_column) { - - selection.active=false; - - } else if (selection.from_column>selection.to_column) { - - SWAP( selection.from_column, selection.to_column ); - } - } else if (selection.from_line>selection.to_line) { - - SWAP( selection.from_line, selection.to_line ); - SWAP( selection.from_column, selection.to_column ); - } - - - update(); + + if (p_from_line>=text.size()) + p_from_line=text.size()-1; + if (p_from_column>=text[p_from_line].length()) + p_from_column=text[p_from_line].length(); + + if (p_to_line>=text.size()) + p_to_line=text.size()-1; + if (p_to_column>=text[p_to_line].length()) + p_to_column=text[p_to_line].length(); + + selection.from_line=p_from_line; + selection.from_column=p_from_column; + selection.to_line=p_to_line; + selection.to_column=p_to_column; + + selection.active=true; + + if (selection.from_line==selection.to_line) { + + if (selection.from_column==selection.to_column) { + + selection.active=false; + + } else if (selection.from_column>selection.to_column) { + + SWAP( selection.from_column, selection.to_column ); + } + } else if (selection.from_line>selection.to_line) { + + SWAP( selection.from_line, selection.to_line ); + SWAP( selection.from_column, selection.to_column ); + } + + + update(); } bool TextEdit::is_selection_active() const { - - return selection.active; + + return selection.active; } int TextEdit::get_selection_from_line() const { - - ERR_FAIL_COND_V(!selection.active,-1); - return selection.from_line; - + + ERR_FAIL_COND_V(!selection.active,-1); + return selection.from_line; + } int TextEdit::get_selection_from_column() const { - - ERR_FAIL_COND_V(!selection.active,-1); - return selection.from_column; - + + ERR_FAIL_COND_V(!selection.active,-1); + return selection.from_column; + } int TextEdit::get_selection_to_line() const { - - ERR_FAIL_COND_V(!selection.active,-1); - return selection.to_line; - + + ERR_FAIL_COND_V(!selection.active,-1); + return selection.to_line; + } int TextEdit::get_selection_to_column() const { - - ERR_FAIL_COND_V(!selection.active,-1); - return selection.to_column; - + + ERR_FAIL_COND_V(!selection.active,-1); + return selection.to_column; + } String TextEdit::get_selection_text() const { - - if (!selection.active) - return ""; - - return _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); - + + if (!selection.active) + return ""; + + return _base_get_text(selection.from_line,selection.from_column,selection.to_line,selection.to_column); + } String TextEdit::get_word_under_cursor() const { - - int prev_cc = cursor.column; - while(prev_cc >0) { - bool is_char = _is_text_char(text[cursor.line][prev_cc-1]); - if (!is_char) - break; - --prev_cc; - } - - int next_cc = cursor.column; - while(next_cc0) { + bool is_char = _is_text_char(text[cursor.line][prev_cc-1]); + if (!is_char) + break; + --prev_cc; + } + + int next_cc = cursor.column; + while(next_cc TextEdit::_search_bind(const String &p_key,uint32_t p_search_flags, int p_from_line,int p_from_column) const { - - int col,line; - if (search(p_key,p_search_flags,p_from_line,p_from_column,col,line)) { - DVector result; - result.resize(2); - result.set(0,line); - result.set(1,col); - return result; - - } else { - - return DVector(); - } + + int col,line; + if (search(p_key,p_search_flags,p_from_line,p_from_column,col,line)) { + DVector result; + result.resize(2); + result.set(0,line); + result.set(1,col); + return result; + + } else { + + return DVector(); + } } bool TextEdit::search(const String &p_key,uint32_t p_search_flags, int p_from_line, int p_from_column,int &r_line,int &r_column) const { - - if (p_key.length()==0) - return false; - ERR_FAIL_INDEX_V(p_from_line,text.size(),false); - ERR_FAIL_INDEX_V(p_from_column,text[p_from_line].length()+1,false); - - //search through the whole documment, but start by current line - - int line=-1; - int pos=-1; - - line=p_from_line; - - for(int i=0;i0 && _is_text_char(text_line[pos-1])) - pos=-1; - else if (_is_text_char(text_line[pos+p_key.length()])) - pos=-1; - } - - if (pos!=-1) - break; - - if (p_search_flags&SEARCH_BACKWARDS) - line--; - else - line++; - - } - - if (pos==-1) { - r_line=-1; - r_column=-1; - return false; - } - - r_line=line; - r_column=pos; - - - return true; + + if (p_key.length()==0) + return false; + ERR_FAIL_INDEX_V(p_from_line,text.size(),false); + ERR_FAIL_INDEX_V(p_from_column,text[p_from_line].length()+1,false); + + //search through the whole documment, but start by current line + + int line=-1; + int pos=-1; + + line=p_from_line; + + for(int i=0;i0 && _is_text_char(text_line[pos-1])) + pos=-1; + else if (_is_text_char(text_line[pos+p_key.length()])) + pos=-1; + } + + if (pos!=-1) + break; + + if (p_search_flags&SEARCH_BACKWARDS) + line--; + else + line++; + + } + + if (pos==-1) { + r_line=-1; + r_column=-1; + return false; + } + + r_line=line; + r_column=pos; + + + return true; } void TextEdit::_cursor_changed_emit() { - - emit_signal("cursor_changed"); - cursor_changed_dirty=false; + + emit_signal("cursor_changed"); + cursor_changed_dirty=false; } void TextEdit::_text_changed_emit() { - - emit_signal("text_changed"); - text_changed_dirty=false; + + emit_signal("text_changed"); + text_changed_dirty=false; } void TextEdit::set_line_as_marked(int p_line,bool p_marked) { - - ERR_FAIL_INDEX(p_line,text.size()); - text.set_marked(p_line,p_marked); - update(); + + ERR_FAIL_INDEX(p_line,text.size()); + text.set_marked(p_line,p_marked); + update(); } bool TextEdit::is_line_set_as_breakpoint(int p_line) const { - - ERR_FAIL_INDEX_V(p_line,text.size(),false); - return text.is_breakpoint(p_line); - + + ERR_FAIL_INDEX_V(p_line,text.size(),false); + return text.is_breakpoint(p_line); + } void TextEdit::set_line_as_breakpoint(int p_line,bool p_breakpoint) { - - - ERR_FAIL_INDEX(p_line,text.size()); - text.set_breakpoint(p_line,p_breakpoint); - update(); + + + ERR_FAIL_INDEX(p_line,text.size()); + text.set_breakpoint(p_line,p_breakpoint); + update(); } void TextEdit::get_breakpoints(List *p_breakpoints) const { - - for(int i=0;ipush_back(i); - } + + for(int i=0;ipush_back(i); + } } int TextEdit::get_line_count() const { - - return text.size(); + + return text.size(); } void TextEdit::_do_text_op(const TextOperation& p_op, bool p_reverse) { - - ERR_FAIL_COND(p_op.type==TextOperation::TYPE_NONE); - - bool insert = p_op.type==TextOperation::TYPE_INSERT; - if (p_reverse) - insert=!insert; - - if (insert) { - - int check_line; - int check_column; - _base_insert_text(p_op.from_line,p_op.from_column,p_op.text,check_line,check_column); - ERR_FAIL_COND( check_line != p_op.to_line ); // BUG - ERR_FAIL_COND( check_column != p_op.to_column ); // BUG - } else { - - _base_remove_text(p_op.from_line,p_op.from_column,p_op.to_line,p_op.to_column); - } - + + ERR_FAIL_COND(p_op.type==TextOperation::TYPE_NONE); + + bool insert = p_op.type==TextOperation::TYPE_INSERT; + if (p_reverse) + insert=!insert; + + if (insert) { + + int check_line; + int check_column; + _base_insert_text(p_op.from_line,p_op.from_column,p_op.text,check_line,check_column); + ERR_FAIL_COND( check_line != p_op.to_line ); // BUG + ERR_FAIL_COND( check_column != p_op.to_column ); // BUG + } else { + + _base_remove_text(p_op.from_line,p_op.from_column,p_op.to_line,p_op.to_column); + } + } void TextEdit::_clear_redo() { - - if (undo_stack_pos==NULL) - return; //nothing to clear - - _push_current_op(); - - while (undo_stack_pos) { - List::Element *elem = undo_stack_pos; - undo_stack_pos=undo_stack_pos->next(); - undo_stack.erase(elem); - } + + if (undo_stack_pos==NULL) + return; //nothing to clear + + _push_current_op(); + + while (undo_stack_pos) { + List::Element *elem = undo_stack_pos; + undo_stack_pos=undo_stack_pos->next(); + undo_stack.erase(elem); + } } void TextEdit::undo() { - - _push_current_op(); - - if (undo_stack_pos==NULL) { - - if (!undo_stack.size()) - return; //nothing to undo - - undo_stack_pos=undo_stack.back(); - - } else if (undo_stack_pos==undo_stack.front()) - return; // at the bottom of the undo stack - else - undo_stack_pos=undo_stack_pos->prev(); - - _do_text_op( undo_stack_pos->get(),true); - if(undo_stack_pos->get().chain_backward) { - do { - undo_stack_pos = undo_stack_pos->prev(); - _do_text_op(undo_stack_pos->get(), true); - } while(!undo_stack_pos->get().chain_forward); - } - - cursor_set_line(undo_stack_pos->get().from_line); - cursor_set_column(undo_stack_pos->get().from_column); - update(); + + _push_current_op(); + + if (undo_stack_pos==NULL) { + + if (!undo_stack.size()) + return; //nothing to undo + + undo_stack_pos=undo_stack.back(); + + } else if (undo_stack_pos==undo_stack.front()) + return; // at the bottom of the undo stack + else + undo_stack_pos=undo_stack_pos->prev(); + + _do_text_op( undo_stack_pos->get(),true); + if(undo_stack_pos->get().chain_backward) { + do { + undo_stack_pos = undo_stack_pos->prev(); + _do_text_op(undo_stack_pos->get(), true); + } while(!undo_stack_pos->get().chain_forward); + } + + cursor_set_line(undo_stack_pos->get().from_line); + cursor_set_column(undo_stack_pos->get().from_column); + update(); } void TextEdit::redo() { - - _push_current_op(); - - if (undo_stack_pos==NULL) - return; //nothing to do. - - _do_text_op(undo_stack_pos->get(), false); - if(undo_stack_pos->get().chain_forward) { - do { - undo_stack_pos=undo_stack_pos->next(); - _do_text_op(undo_stack_pos->get(), false); - } while(!undo_stack_pos->get().chain_backward); - } - cursor_set_line(undo_stack_pos->get().from_line); - cursor_set_column(undo_stack_pos->get().from_column); - undo_stack_pos=undo_stack_pos->next(); - update(); + + _push_current_op(); + + if (undo_stack_pos==NULL) + return; //nothing to do. + + _do_text_op(undo_stack_pos->get(), false); + if(undo_stack_pos->get().chain_forward) { + do { + undo_stack_pos=undo_stack_pos->next(); + _do_text_op(undo_stack_pos->get(), false); + } while(!undo_stack_pos->get().chain_backward); + } + cursor_set_line(undo_stack_pos->get().from_line); + cursor_set_column(undo_stack_pos->get().from_column); + undo_stack_pos=undo_stack_pos->next(); + update(); } void TextEdit::clear_undo_history() { - - saved_version=0; - current_op.type=TextOperation::TYPE_NONE; - undo_stack_pos=NULL; - undo_stack.clear(); - + + saved_version=0; + current_op.type=TextOperation::TYPE_NONE; + undo_stack_pos=NULL; + undo_stack.clear(); + } void TextEdit::_begin_compex_operation() { - _push_current_op(); - next_operation_is_complex=true; + _push_current_op(); + next_operation_is_complex=true; } void TextEdit::_end_compex_operation() { - - _push_current_op(); - ERR_FAIL_COND(undo_stack.size() == 0); - - if(undo_stack.back()->get().chain_forward) { - undo_stack.back()->get().chain_forward=false; - return; - } - - undo_stack.back()->get().chain_backward=true; + + _push_current_op(); + ERR_FAIL_COND(undo_stack.size() == 0); + + if(undo_stack.back()->get().chain_forward) { + undo_stack.back()->get().chain_forward=false; + return; + } + + undo_stack.back()->get().chain_backward=true; } void TextEdit::_push_current_op() { - - if (current_op.type==TextOperation::TYPE_NONE) - return; // do nothing - - if(next_operation_is_complex) { - current_op.chain_forward=true; - next_operation_is_complex=false; - } - - undo_stack.push_back(current_op); - current_op.type=TextOperation::TYPE_NONE; - current_op.text=""; - current_op.chain_forward=false; - + + if (current_op.type==TextOperation::TYPE_NONE) + return; // do nothing + + if(next_operation_is_complex) { + current_op.chain_forward=true; + next_operation_is_complex=false; + } + + undo_stack.push_back(current_op); + current_op.type=TextOperation::TYPE_NONE; + current_op.text=""; + current_op.chain_forward=false; + } void TextEdit::set_draw_tabs(bool p_draw) { - - draw_tabs=p_draw; + + draw_tabs=p_draw; } bool TextEdit::is_drawing_tabs() const{ - - return draw_tabs; + + return draw_tabs; } uint32_t TextEdit::get_version() const { - return current_op.version; + return current_op.version; } uint32_t TextEdit::get_saved_version() const { - - return saved_version; + + return saved_version; } void TextEdit::tag_saved_version() { - - saved_version=get_version(); + + saved_version=get_version(); } int TextEdit::get_v_scroll() const { - - return v_scroll->get_val(); + + return v_scroll->get_val(); } void TextEdit::set_v_scroll(int p_scroll) { - - v_scroll->set_val(p_scroll); - cursor.line_ofs=p_scroll; + + v_scroll->set_val(p_scroll); + cursor.line_ofs=p_scroll; } int TextEdit::get_h_scroll() const { - - return h_scroll->get_val(); + + return h_scroll->get_val(); } void TextEdit::set_h_scroll(int p_scroll) { - - h_scroll->set_val(p_scroll); + + h_scroll->set_val(p_scroll); } void TextEdit::set_completion(bool p_enabled,const Vector& p_prefixes) { - - completion_prefixes.clear(); - completion_enabled=p_enabled; - for(int i=0;i=l.length() || l[c]!=remaining[i]) { - same=false; - break; - } - } - - if (same) - cursor_set_column(cursor.column+remaining.length()); - else { - insert_text_at_cursor(remaining); - if (remaining.ends_with("(") && auto_brace_completion_enabled) { - insert_text_at_cursor(")"); - cursor.column--; + + String remaining=completion_current.substr(completion_base.length(),completion_current.length()-completion_base.length()); + String l = text[cursor.line]; + bool same=true; + //if what is going to be inserted is the same as what it is, don't change it + for(int i=0;i=l.length() || l[c]!=remaining[i]) { + same=false; + break; + } } - } - - _cancel_completion(); + + if (same) + cursor_set_column(cursor.column+remaining.length()); + else { + insert_text_at_cursor(remaining); + if (remaining.ends_with("(") && auto_brace_completion_enabled) { + insert_text_at_cursor(")"); + cursor.column--; + } + } + + _cancel_completion(); } @@ -3216,185 +3252,185 @@ void TextEdit::_cancel_code_hint() { } void TextEdit::_cancel_completion() { - - if (!completion_active) - return; - - completion_active=false; - update(); - + + if (!completion_active) + return; + + completion_active=false; + update(); + } static bool _is_completable(CharType c) { - + return !_is_symbol(c) || c=='"' || c=='\''; } void TextEdit::_update_completion_candidates() { - - String l = text[cursor.line]; - int cofs = CLAMP(cursor.column,0,l.length()); - - - String s; - - while(cofs>0 && l[cofs-1]>32 && _is_completable(l[cofs-1])) { - s=String::chr(l[cofs-1])+s; - if (l[cofs-1]=='\'' || l[cofs-1]=='"') - break; - - cofs--; - } - - - update(); - - if (s=="" && (cofs==0 || !completion_prefixes.has(String::chr(l[cofs-1])))) { - //none to complete, cancel - _cancel_completion(); - return; - } - - completion_options.clear(); - completion_index=0; - completion_base=s; - int ci_match=0; - for(int i=0;i=completion_strings[i].length()) - break; - if (completion_current[j]!=completion_strings[i][j]) - break; - m++; - } - if (m>ci_match) { - ci_match=m; - completion_index=completion_options.size()-1; - } - - } - } - - - - if (completion_options.size()==0) { - //no options to complete, cancel - _cancel_completion(); - return; - - } - - completion_current=completion_options[completion_index]; - + + String l = text[cursor.line]; + int cofs = CLAMP(cursor.column,0,l.length()); + + + String s; + + while(cofs>0 && l[cofs-1]>32 && _is_completable(l[cofs-1])) { + s=String::chr(l[cofs-1])+s; + if (l[cofs-1]=='\'' || l[cofs-1]=='"') + break; + + cofs--; + } + + + update(); + + if (s=="" && (cofs==0 || !completion_prefixes.has(String::chr(l[cofs-1])))) { + //none to complete, cancel + _cancel_completion(); + return; + } + + completion_options.clear(); + completion_index=0; + completion_base=s; + int ci_match=0; + for(int i=0;i=completion_strings[i].length()) + break; + if (completion_current[j]!=completion_strings[i][j]) + break; + m++; + } + if (m>ci_match) { + ci_match=m; + completion_index=completion_options.size()-1; + } + + } + } + + + + if (completion_options.size()==0) { + //no options to complete, cancel + _cancel_completion(); + return; + + } + + completion_current=completion_options[completion_index]; + #if 0 // even there's only one option, user still get the chance to choose using it or not - if (completion_options.size()==1) { - //one option to complete, just complete it automagically - _confirm_completion(); -// insert_text_at_cursor(completion_options[0].substr(s.length(),completion_options[0].length()-s.length())); - _cancel_completion(); - return; - - } + if (completion_options.size()==1) { + //one option to complete, just complete it automagically + _confirm_completion(); + // insert_text_at_cursor(completion_options[0].substr(s.length(),completion_options[0].length()-s.length())); + _cancel_completion(); + return; + + } #endif - if (completion_options.size()==1 && s==completion_options[0]) - _cancel_completion(); - - completion_enabled=true; + if (completion_options.size()==1 && s==completion_options[0]) + _cancel_completion(); + + completion_enabled=true; } void TextEdit::query_code_comple() { - + String l = text[cursor.line]; int ofs = CLAMP(cursor.column,0,l.length()); - + if (ofs>0 && (_is_completable(l[ofs-1]) || completion_prefixes.has(String::chr(l[ofs-1])))) emit_signal("request_completion"); - + } void TextEdit::set_code_hint(const String& p_hint) { - + completion_hint=p_hint; completion_hint_offset=-0xFFFF; update(); } void TextEdit::code_complete(const Vector &p_strings) { - - - completion_strings=p_strings; - completion_active=true; - completion_current=""; - completion_index=0; - _update_completion_candidates(); -// + + + completion_strings=p_strings; + completion_active=true; + completion_current=""; + completion_index=0; + _update_completion_candidates(); + // } String TextEdit::get_tooltip(const Point2& p_pos) const { - - if (!tooltip_obj) - return Control::get_tooltip(p_pos); - int row,col; - if (!_get_mouse_pos(p_pos, row,col)) { - return Control::get_tooltip(p_pos); - } - - String s = text[row]; - if (s.length()==0) - return Control::get_tooltip(p_pos); - int beg=CLAMP(col,0,s.length()); - int end=beg; - - - if (s[beg]>32 || beg==s.length()) { - - bool symbol = beg < s.length() && _is_symbol(s[beg]); //not sure if right but most editors behave like this - - while(beg>0 && s[beg-1]>32 && (symbol==_is_symbol(s[beg-1]))) { - beg--; - } - while(end32 && (symbol==_is_symbol(s[end+1]))) { - end++; - } - - if (endcall(tooltip_func,s.substr(beg,end-beg),tooltip_ud); - - return tt; - - } - - return Control::get_tooltip(p_pos); - + + if (!tooltip_obj) + return Control::get_tooltip(p_pos); + int row,col; + if (!_get_mouse_pos(p_pos, row,col)) { + return Control::get_tooltip(p_pos); + } + + String s = text[row]; + if (s.length()==0) + return Control::get_tooltip(p_pos); + int beg=CLAMP(col,0,s.length()); + int end=beg; + + + if (s[beg]>32 || beg==s.length()) { + + bool symbol = beg < s.length() && _is_symbol(s[beg]); //not sure if right but most editors behave like this + + while(beg>0 && s[beg-1]>32 && (symbol==_is_symbol(s[beg-1]))) { + beg--; + } + while(end32 && (symbol==_is_symbol(s[end+1]))) { + end++; + } + + if (endcall(tooltip_func,s.substr(beg,end-beg),tooltip_ud); + + return tt; + + } + + return Control::get_tooltip(p_pos); + } void TextEdit::set_tooltip_request_func(Object *p_obj, const StringName& p_function,const Variant& p_udata) { - - tooltip_obj=p_obj; - tooltip_func=p_function; - tooltip_ud=p_udata; + + tooltip_obj=p_obj; + tooltip_func=p_function; + tooltip_ud=p_udata; } void TextEdit::set_line(int line, String new_text) { - if (line < 0 || line > text.size()) - return; - _remove_text(line, 0, line, text[line].length()); - _insert_text(line, 0, new_text); + if (line < 0 || line > text.size()) + return; + _remove_text(line, 0, line, text[line].length()); + _insert_text(line, 0, new_text); } void TextEdit::insert_at(const String &p_text, int at) @@ -3405,167 +3441,167 @@ void TextEdit::insert_at(const String &p_text, int at) } void TextEdit::set_show_line_numbers(bool p_show) { - - line_numbers=p_show; - update(); + + line_numbers=p_show; + update(); } void TextEdit::_bind_methods() { - - - ObjectTypeDB::bind_method(_MD("_input_event"),&TextEdit::_input_event); - ObjectTypeDB::bind_method(_MD("_scroll_moved"),&TextEdit::_scroll_moved); - ObjectTypeDB::bind_method(_MD("_cursor_changed_emit"),&TextEdit::_cursor_changed_emit); - ObjectTypeDB::bind_method(_MD("_text_changed_emit"),&TextEdit::_text_changed_emit); - ObjectTypeDB::bind_method(_MD("_push_current_op"),&TextEdit::_push_current_op); - - BIND_CONSTANT( SEARCH_MATCH_CASE ); - BIND_CONSTANT( SEARCH_WHOLE_WORDS ); - BIND_CONSTANT( SEARCH_BACKWARDS ); - -/* + + + ObjectTypeDB::bind_method(_MD("_input_event"),&TextEdit::_input_event); + ObjectTypeDB::bind_method(_MD("_scroll_moved"),&TextEdit::_scroll_moved); + ObjectTypeDB::bind_method(_MD("_cursor_changed_emit"),&TextEdit::_cursor_changed_emit); + ObjectTypeDB::bind_method(_MD("_text_changed_emit"),&TextEdit::_text_changed_emit); + ObjectTypeDB::bind_method(_MD("_push_current_op"),&TextEdit::_push_current_op); + + BIND_CONSTANT( SEARCH_MATCH_CASE ); + BIND_CONSTANT( SEARCH_WHOLE_WORDS ); + BIND_CONSTANT( SEARCH_BACKWARDS ); + + /* ObjectTypeDB::bind_method(_MD("delete_char"),&TextEdit::delete_char); ObjectTypeDB::bind_method(_MD("delete_line"),&TextEdit::delete_line); */ - - ObjectTypeDB::bind_method(_MD("set_text","text"),&TextEdit::set_text); - ObjectTypeDB::bind_method(_MD("insert_text_at_cursor","text"),&TextEdit::insert_text_at_cursor); - - ObjectTypeDB::bind_method(_MD("get_line_count"),&TextEdit::get_line_count); - ObjectTypeDB::bind_method(_MD("get_text"),&TextEdit::get_text); - ObjectTypeDB::bind_method(_MD("get_line"),&TextEdit::get_line); - - ObjectTypeDB::bind_method(_MD("cursor_set_column","column"),&TextEdit::cursor_set_column); - ObjectTypeDB::bind_method(_MD("cursor_set_line","line"),&TextEdit::cursor_set_line); - - ObjectTypeDB::bind_method(_MD("cursor_get_column"),&TextEdit::cursor_get_column); - ObjectTypeDB::bind_method(_MD("cursor_get_line"),&TextEdit::cursor_get_line); - - - ObjectTypeDB::bind_method(_MD("set_readonly","enable"),&TextEdit::set_readonly); - ObjectTypeDB::bind_method(_MD("set_wrap","enable"),&TextEdit::set_wrap); - ObjectTypeDB::bind_method(_MD("set_max_chars","amount"),&TextEdit::set_max_chars); - - ObjectTypeDB::bind_method(_MD("cut"),&TextEdit::cut); - ObjectTypeDB::bind_method(_MD("copy"),&TextEdit::copy); - ObjectTypeDB::bind_method(_MD("paste"),&TextEdit::paste); - ObjectTypeDB::bind_method(_MD("select_all"),&TextEdit::select_all); - ObjectTypeDB::bind_method(_MD("select","from_line","from_column","to_line","to_column"),&TextEdit::select); - - ObjectTypeDB::bind_method(_MD("is_selection_active"),&TextEdit::is_selection_active); - ObjectTypeDB::bind_method(_MD("get_selection_from_line"),&TextEdit::get_selection_from_line); - ObjectTypeDB::bind_method(_MD("get_selection_from_column"),&TextEdit::get_selection_from_column); - ObjectTypeDB::bind_method(_MD("get_selection_to_line"),&TextEdit::get_selection_to_line); - ObjectTypeDB::bind_method(_MD("get_selection_to_column"),&TextEdit::get_selection_to_column); - ObjectTypeDB::bind_method(_MD("get_selection_text"),&TextEdit::get_selection_text); - ObjectTypeDB::bind_method(_MD("get_word_under_cursor"),&TextEdit::get_word_under_cursor); - ObjectTypeDB::bind_method(_MD("search","flags","from_line","from_column","to_line","to_column"),&TextEdit::_search_bind); - - ObjectTypeDB::bind_method(_MD("undo"),&TextEdit::undo); - ObjectTypeDB::bind_method(_MD("redo"),&TextEdit::redo); - ObjectTypeDB::bind_method(_MD("clear_undo_history"),&TextEdit::clear_undo_history); - - ObjectTypeDB::bind_method(_MD("set_syntax_coloring","enable"),&TextEdit::set_syntax_coloring); - ObjectTypeDB::bind_method(_MD("is_syntax_coloring_enabled"),&TextEdit::is_syntax_coloring_enabled); - - - ObjectTypeDB::bind_method(_MD("add_keyword_color","keyword","color"),&TextEdit::add_keyword_color); - ObjectTypeDB::bind_method(_MD("add_color_region","begin_key","end_key","color","line_only"),&TextEdit::add_color_region,DEFVAL(false)); - ObjectTypeDB::bind_method(_MD("set_symbol_color","color"),&TextEdit::set_symbol_color); - ObjectTypeDB::bind_method(_MD("set_custom_bg_color","color"),&TextEdit::set_custom_bg_color); - ObjectTypeDB::bind_method(_MD("clear_colors"),&TextEdit::clear_colors); - - - ADD_SIGNAL(MethodInfo("cursor_changed")); - ADD_SIGNAL(MethodInfo("text_changed")); - ADD_SIGNAL(MethodInfo("request_completion")); - + + ObjectTypeDB::bind_method(_MD("set_text","text"),&TextEdit::set_text); + ObjectTypeDB::bind_method(_MD("insert_text_at_cursor","text"),&TextEdit::insert_text_at_cursor); + + ObjectTypeDB::bind_method(_MD("get_line_count"),&TextEdit::get_line_count); + ObjectTypeDB::bind_method(_MD("get_text"),&TextEdit::get_text); + ObjectTypeDB::bind_method(_MD("get_line"),&TextEdit::get_line); + + ObjectTypeDB::bind_method(_MD("cursor_set_column","column"),&TextEdit::cursor_set_column); + ObjectTypeDB::bind_method(_MD("cursor_set_line","line"),&TextEdit::cursor_set_line); + + ObjectTypeDB::bind_method(_MD("cursor_get_column"),&TextEdit::cursor_get_column); + ObjectTypeDB::bind_method(_MD("cursor_get_line"),&TextEdit::cursor_get_line); + + + ObjectTypeDB::bind_method(_MD("set_readonly","enable"),&TextEdit::set_readonly); + ObjectTypeDB::bind_method(_MD("set_wrap","enable"),&TextEdit::set_wrap); + ObjectTypeDB::bind_method(_MD("set_max_chars","amount"),&TextEdit::set_max_chars); + + ObjectTypeDB::bind_method(_MD("cut"),&TextEdit::cut); + ObjectTypeDB::bind_method(_MD("copy"),&TextEdit::copy); + ObjectTypeDB::bind_method(_MD("paste"),&TextEdit::paste); + ObjectTypeDB::bind_method(_MD("select_all"),&TextEdit::select_all); + ObjectTypeDB::bind_method(_MD("select","from_line","from_column","to_line","to_column"),&TextEdit::select); + + ObjectTypeDB::bind_method(_MD("is_selection_active"),&TextEdit::is_selection_active); + ObjectTypeDB::bind_method(_MD("get_selection_from_line"),&TextEdit::get_selection_from_line); + ObjectTypeDB::bind_method(_MD("get_selection_from_column"),&TextEdit::get_selection_from_column); + ObjectTypeDB::bind_method(_MD("get_selection_to_line"),&TextEdit::get_selection_to_line); + ObjectTypeDB::bind_method(_MD("get_selection_to_column"),&TextEdit::get_selection_to_column); + ObjectTypeDB::bind_method(_MD("get_selection_text"),&TextEdit::get_selection_text); + ObjectTypeDB::bind_method(_MD("get_word_under_cursor"),&TextEdit::get_word_under_cursor); + ObjectTypeDB::bind_method(_MD("search","flags","from_line","from_column","to_line","to_column"),&TextEdit::_search_bind); + + ObjectTypeDB::bind_method(_MD("undo"),&TextEdit::undo); + ObjectTypeDB::bind_method(_MD("redo"),&TextEdit::redo); + ObjectTypeDB::bind_method(_MD("clear_undo_history"),&TextEdit::clear_undo_history); + + ObjectTypeDB::bind_method(_MD("set_syntax_coloring","enable"),&TextEdit::set_syntax_coloring); + ObjectTypeDB::bind_method(_MD("is_syntax_coloring_enabled"),&TextEdit::is_syntax_coloring_enabled); + + + ObjectTypeDB::bind_method(_MD("add_keyword_color","keyword","color"),&TextEdit::add_keyword_color); + ObjectTypeDB::bind_method(_MD("add_color_region","begin_key","end_key","color","line_only"),&TextEdit::add_color_region,DEFVAL(false)); + ObjectTypeDB::bind_method(_MD("set_symbol_color","color"),&TextEdit::set_symbol_color); + ObjectTypeDB::bind_method(_MD("set_custom_bg_color","color"),&TextEdit::set_custom_bg_color); + ObjectTypeDB::bind_method(_MD("clear_colors"),&TextEdit::clear_colors); + + + ADD_SIGNAL(MethodInfo("cursor_changed")); + ADD_SIGNAL(MethodInfo("text_changed")); + ADD_SIGNAL(MethodInfo("request_completion")); + } TextEdit::TextEdit() { - - readonly=false; - setting_row=false; - draw_tabs=false; - max_chars=0; - clear(); - wrap=false; - set_focus_mode(FOCUS_ALL); - _update_caches(); - cache.size=Size2(1,1); - tab_size=4; - text.set_tab_size(tab_size); - text.clear(); -// text.insert(1,"Mongolia.."); -// text.insert(2,"PAIS GENEROSO!!"); - text.set_color_regions(&color_regions); - - h_scroll = memnew( HScrollBar ); - v_scroll = memnew( VScrollBar ); - - add_child(h_scroll); - add_child(v_scroll); - - updating_scrolls=false; - selection.active=false; - - h_scroll->connect("value_changed", this,"_scroll_moved"); - v_scroll->connect("value_changed", this,"_scroll_moved"); - - cursor_changed_dirty=false; - text_changed_dirty=false; - - selection.selecting_mode=Selection::MODE_NONE; - selection.selecting_line=0; - selection.selecting_column=0; - selection.selecting_test=false; - selection.active=false; - syntax_coloring=false; - - custom_bg_color=Color(0,0,0,0); - idle_detect = memnew( Timer ); - add_child(idle_detect); - idle_detect->set_one_shot(true); - idle_detect->set_wait_time(GLOBAL_DEF("display/text_edit_idle_detect_sec",3)); - idle_detect->connect("timeout", this,"_push_current_op"); - + + readonly=false; + setting_row=false; + draw_tabs=false; + max_chars=0; + clear(); + wrap=false; + set_focus_mode(FOCUS_ALL); + _update_caches(); + cache.size=Size2(1,1); + tab_size=4; + text.set_tab_size(tab_size); + text.clear(); + // text.insert(1,"Mongolia.."); + // text.insert(2,"PAIS GENEROSO!!"); + text.set_color_regions(&color_regions); + + h_scroll = memnew( HScrollBar ); + v_scroll = memnew( VScrollBar ); + + add_child(h_scroll); + add_child(v_scroll); + + updating_scrolls=false; + selection.active=false; + + h_scroll->connect("value_changed", this,"_scroll_moved"); + v_scroll->connect("value_changed", this,"_scroll_moved"); + + cursor_changed_dirty=false; + text_changed_dirty=false; + + selection.selecting_mode=Selection::MODE_NONE; + selection.selecting_line=0; + selection.selecting_column=0; + selection.selecting_test=false; + selection.active=false; + syntax_coloring=false; + + custom_bg_color=Color(0,0,0,0); + idle_detect = memnew( Timer ); + add_child(idle_detect); + idle_detect->set_one_shot(true); + idle_detect->set_wait_time(GLOBAL_DEF("display/text_edit_idle_detect_sec",3)); + idle_detect->connect("timeout", this,"_push_current_op"); + #if 0 - syntax_coloring=true; - keywords["void"]=Color(0.3,0.0,0.1); - keywords["int"]=Color(0.3,0.0,0.1); - keywords["function"]=Color(0.3,0.0,0.1); - keywords["class"]=Color(0.3,0.0,0.1); - keywords["extends"]=Color(0.3,0.0,0.1); - keywords["constructor"]=Color(0.3,0.0,0.1); - symbol_color=Color(0.1,0.0,0.3,1.0); - - color_regions.push_back(ColorRegion("/*","*/",Color(0.4,0.6,0,4))); - color_regions.push_back(ColorRegion("//","",Color(0.6,0.6,0.4))); - color_regions.push_back(ColorRegion("\"","\"",Color(0.4,0.7,0.7))); - color_regions.push_back(ColorRegion("'","'",Color(0.4,0.8,0.8))); - color_regions.push_back(ColorRegion("#","",Color(0.2,1.0,0.2))); - + syntax_coloring=true; + keywords["void"]=Color(0.3,0.0,0.1); + keywords["int"]=Color(0.3,0.0,0.1); + keywords["function"]=Color(0.3,0.0,0.1); + keywords["class"]=Color(0.3,0.0,0.1); + keywords["extends"]=Color(0.3,0.0,0.1); + keywords["constructor"]=Color(0.3,0.0,0.1); + symbol_color=Color(0.1,0.0,0.3,1.0); + + color_regions.push_back(ColorRegion("/*","*/",Color(0.4,0.6,0,4))); + color_regions.push_back(ColorRegion("//","",Color(0.6,0.6,0.4))); + color_regions.push_back(ColorRegion("\"","\"",Color(0.4,0.7,0.7))); + color_regions.push_back(ColorRegion("'","'",Color(0.4,0.8,0.8))); + color_regions.push_back(ColorRegion("#","",Color(0.2,1.0,0.2))); + #endif - - current_op.type=TextOperation::TYPE_NONE; - undo_enabled=true; - undo_stack_pos=NULL; - setting_text=false; - last_dblclk=0; - current_op.version=0; - version=0; - saved_version=0; - - completion_enabled=false; - completion_active=false; - completion_line_ofs=0; - tooltip_obj=NULL; - line_numbers=false; - next_operation_is_complex=false; - auto_brace_completion_enabled=false; - brace_matching_enabled=false; - + + current_op.type=TextOperation::TYPE_NONE; + undo_enabled=true; + undo_stack_pos=NULL; + setting_text=false; + last_dblclk=0; + current_op.version=0; + version=0; + saved_version=0; + + completion_enabled=false; + completion_active=false; + completion_line_ofs=0; + tooltip_obj=NULL; + line_numbers=false; + next_operation_is_complex=false; + auto_brace_completion_enabled=false; + brace_matching_enabled=false; + } TextEdit::~TextEdit() diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index ed4d30a9d2a..1d57aef4161 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -63,6 +63,7 @@ class TextEdit : public Control { int from_line,from_column; int to_line,to_column; + bool shiftclick_left; } selection; From 2144648a3d9d7f23cf580a429af3f7bdc13f94e8 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 2 Jan 2015 15:53:02 -0300 Subject: [PATCH 20/37] -fix assignment to vector types in script using integer indices crash (#978) --- core/variant_op.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/variant_op.cpp b/core/variant_op.cpp index d9fe6537a19..ec43b1275cb 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -961,7 +961,7 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid) Vector2 *v=reinterpret_cast(_data._mem); valid=true; - v[idx]=p_value; + (*v)[idx]=p_value; return; } } else if (p_index.get_type()==Variant::STRING) { @@ -1055,7 +1055,7 @@ void Variant::set(const Variant& p_index, const Variant& p_value, bool *r_valid) Vector3 *v=reinterpret_cast(_data._mem); valid=true; - v[idx]=p_value; + (*v)[idx]=p_value; return; } } else if (p_index.get_type()==Variant::STRING) { From 58a67a1e0f412b3daf7f4905ad7d0ebb1dc0cf6b Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 2 Jan 2015 17:31:43 -0300 Subject: [PATCH 21/37] -fixed key insert from editor window (#976) --- tools/editor/plugins/canvas_item_editor_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp index a18c2a58a71..482340ca00b 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.cpp +++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp @@ -2307,7 +2307,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { } break; case ANIM_INSERT_ROT: { - key_pos = key_rot_button->is_pressed(); + key_rot = key_rot_button->is_pressed(); } break; case ANIM_INSERT_SCALE: { From d722537154cd87dca134e7055aa2bfdc187eb1b0 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 2 Jan 2015 22:34:22 -0300 Subject: [PATCH 22/37] -proper minimum size computation for TabContainer --- drivers/gles2/rasterizer_gles2.cpp | 7 +++++-- scene/gui/tab_container.cpp | 33 ++++++++++++++++++++++++++++++ scene/gui/tab_container.h | 2 ++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index 0072ca9c865..ccbba2f51c8 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -8188,14 +8188,17 @@ void RasterizerGLES2::canvas_draw_polygon(int p_vertex_count, const int* p_indic } if (p_indices) { - - static const int _max_draw_poly_indices = 8*1024; // change this size if needed!!! +#ifdef GLEW_ENABLED + glDrawElements(GL_TRIANGLES, p_vertex_count, GL_UNSIGNED_INT, p_indices ); +#else + static const int _max_draw_poly_indices = 16*1024; // change this size if needed!!! ERR_FAIL_COND(p_vertex_count > _max_draw_poly_indices); static uint16_t _draw_poly_indices[_max_draw_poly_indices]; for (int i=0; i *p_strings) const { } +Size2 TabContainer::get_minimum_size() const { + + Size2 ms; + + for(int i=0;icast_to(); + if (!c) + continue; + if (c->is_set_as_toplevel()) + continue; + + if (!c->has_meta("_tab_name")) + continue; + + if (!c->is_visible()) + continue; + + Size2 cms = c->get_minimum_size(); + ms.x=MAX(ms.x,cms.x); + ms.y=MAX(ms.y,cms.y); + } + + Ref tab_bg = get_stylebox("tab_bg"); + Ref tab_fg = get_stylebox("tab_fg"); + Ref font = get_font("font"); + + ms.y+=MAX(tab_bg->get_minimum_size().y,tab_fg->get_minimum_size().y); + ms.y+=font->get_height(); + + return ms; +} + void TabContainer::_bind_methods() { ObjectTypeDB::bind_method(_MD("_input_event"),&TabContainer::_input_event); diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index d5b6a2b503c..df7b03e040a 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -85,6 +85,8 @@ public: void set_current_tab(int p_current); int get_current_tab() const; + virtual Size2 get_minimum_size() const; + virtual void get_translatable_strings(List *p_strings) const; TabContainer(); From 0df45672e7d985268de3040c24b86b4ac075a1d8 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 3 Jan 2015 00:23:14 -0300 Subject: [PATCH 23/37] -ability to scale and modulate texturebutton, closes #818 -fixed bug in ordering of modal subwindows, closes #1001 --- scene/gui/control.cpp | 8 ++++ scene/gui/texture_button.cpp | 78 ++++++++++++++++++++++++++++-------- scene/gui/texture_button.h | 7 ++++ 3 files changed, 77 insertions(+), 16 deletions(-) diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 5a0706f01ef..91d6a162f56 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -768,6 +768,12 @@ Control* Control::_find_control_at_pos(CanvasItem* p_node,const Point2& p_global c->_window_sort_subwindows(); // sort them + int idx=0; + for (List::Element *E=c->window->subwindows.front();E;E=E->next()) { + + if (!E->get()->is_visible()) + continue; + } for (List::Element *E=c->window->subwindows.back();E;E=E->prev()) { Control *sw = E->get(); @@ -1126,6 +1132,7 @@ void Control::_window_input_event(InputEvent p_event) { over = _find_control_at_pos(this,pos,parent_xform,window->focus_inv_xform); } + if (window->drag_data.get_type()==Variant::NIL && over && !window->modal_stack.empty()) { Control *top = window->modal_stack.back()->get(); @@ -2267,6 +2274,7 @@ void Control::_window_sort_subwindows() { return; window->modal_stack.sort_custom(); + window->subwindows.sort_custom(); window->subwindow_order_dirty=false; } diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp index 7954ac65dff..e8967927cb7 100644 --- a/scene/gui/texture_button.cpp +++ b/scene/gui/texture_button.cpp @@ -31,28 +31,33 @@ Size2 TextureButton::get_minimum_size() const { + Size2 rscale; if (normal.is_null()) { if (pressed.is_null()) { if (hover.is_null()) if (click_mask.is_null()) - return Size2(); + rscale= Size2(); else - return click_mask->get_size(); + rscale= click_mask->get_size(); else - return hover->get_size(); + rscale= hover->get_size(); } else - return pressed->get_size(); + rscale= pressed->get_size()*scale; } else - return normal->get_size(); + rscale= normal->get_size(); + + return rscale*scale; } bool TextureButton::has_point(const Point2& p_point) const { + Point2 ppos = p_point/scale; + if (click_mask.is_valid()) { - Point2i p =p_point; + Point2i p =ppos; if (p.x<0 || p.x>=click_mask->get_size().width || p.y<0 || p.y>=click_mask->get_size().height) return false; @@ -71,46 +76,57 @@ void TextureButton::_notification(int p_what) { DrawMode draw_mode = get_draw_mode(); // if (normal.is_null()) // break; + + Ref texdraw; + switch (draw_mode) { case DRAW_NORMAL: { if (normal.is_valid()) - normal->draw(canvas_item,Point2()); + texdraw=normal; } break; case DRAW_PRESSED: { if (pressed.is_null()) { if (hover.is_null()) { if (normal.is_valid()) - normal->draw(canvas_item,Point2()); + texdraw=normal; } else - hover->draw(canvas_item,Point2()); + texdraw=hover; } else - pressed->draw(canvas_item,Point2()); + texdraw=pressed; } break; case DRAW_HOVER: { if (hover.is_null()) { if (pressed.is_valid() && is_pressed()) - pressed->draw(canvas_item,Point2()); + texdraw=pressed; else if (normal.is_valid()) - normal->draw(canvas_item,Point2()); + texdraw=normal; } else - hover->draw(canvas_item,Point2()); + texdraw=hover; } break; case DRAW_DISABLED: { if (disabled.is_null()) { if (normal.is_valid()) - normal->draw(canvas_item,Point2()); + texdraw=normal; } else - disabled->draw(canvas_item,Point2()); + texdraw=disabled; } break; } + + if (texdraw.is_valid()) { + Rect2 drect(Point2(),texdraw->get_size()*scale); + draw_texture_rect(texdraw,drect,false,modulate); + + } if (has_focus() && focused.is_valid()) { - focused->draw(canvas_item, Point2()); + Rect2 drect(Point2(),focused->get_size()*scale); + draw_texture_rect(focused,drect,false,modulate); + }; } break; @@ -125,6 +141,8 @@ void TextureButton::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_disabled_texture","texture:Texture"),&TextureButton::set_disabled_texture); ObjectTypeDB::bind_method(_MD("set_focused_texture","texture:Texture"),&TextureButton::set_focused_texture); ObjectTypeDB::bind_method(_MD("set_click_mask","mask:BitMap"),&TextureButton::set_click_mask); + ObjectTypeDB::bind_method(_MD("set_scale","scale"),&TextureButton::set_scale); + ObjectTypeDB::bind_method(_MD("set_modulate","color"),&TextureButton::set_modulate); ObjectTypeDB::bind_method(_MD("get_normal_texture:Texture"),&TextureButton::get_normal_texture); ObjectTypeDB::bind_method(_MD("get_pressed_texture:Texture"),&TextureButton::get_pressed_texture); @@ -132,6 +150,8 @@ void TextureButton::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_disabled_texture:Texture"),&TextureButton::get_disabled_texture); ObjectTypeDB::bind_method(_MD("get_focused_texture:Texture"),&TextureButton::get_focused_texture); ObjectTypeDB::bind_method(_MD("get_click_mask:BitMap"),&TextureButton::get_click_mask); + ObjectTypeDB::bind_method(_MD("get_scale"),&TextureButton::get_scale); + ObjectTypeDB::bind_method(_MD("get_modulate"),&TextureButton::get_modulate); ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/normal",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_normal_texture"), _SCS("get_normal_texture")); ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/pressed",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_pressed_texture"), _SCS("get_pressed_texture")); @@ -139,6 +159,8 @@ void TextureButton::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/disabled",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_disabled_texture"), _SCS("get_disabled_texture")); ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/focused",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_focused_texture"), _SCS("get_focused_texture")); ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/click_mask",PROPERTY_HINT_RESOURCE_TYPE,"BitMap"), _SCS("set_click_mask"), _SCS("get_click_mask")) ; + ADD_PROPERTY(PropertyInfo(Variant::REAL,"params/scale",PROPERTY_HINT_RANGE,"0.01,1024,0.01"), _SCS("set_scale"), _SCS("get_scale")); + ADD_PROPERTY(PropertyInfo(Variant::COLOR,"params/modulate"), _SCS("set_modulate"), _SCS("get_modulate")); } @@ -206,6 +228,30 @@ void TextureButton::set_focused_texture(const Ref& p_focused) { focused = p_focused; }; +void TextureButton::set_scale(float p_scale) { + + ERR_FAIL_COND(p_scale<=0); + scale=p_scale; + minimum_size_changed(); + update(); +} + +float TextureButton::get_scale() const{ + + return scale; +} + +void TextureButton::set_modulate(const Color& p_modulate) { + modulate=p_modulate; + update(); +} + +Color TextureButton::get_modulate() const { + return modulate; +} + TextureButton::TextureButton() { + scale=1.0; + modulate=Color(1,1,1); } diff --git a/scene/gui/texture_button.h b/scene/gui/texture_button.h index d186966cb1f..0209d3c2602 100644 --- a/scene/gui/texture_button.h +++ b/scene/gui/texture_button.h @@ -41,6 +41,8 @@ class TextureButton : public BaseButton { Ref disabled; Ref focused; Ref click_mask; + float scale; + Color modulate; protected: @@ -66,6 +68,11 @@ public: Ref get_focused_texture() const; Ref get_click_mask() const; + void set_scale(float p_scale); + float get_scale() const; + + void set_modulate(const Color& p_modulate); + Color get_modulate() const; TextureButton(); }; From fa7a3ac0d329f7e3e7ade9cd530880af2da7b7dd Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 3 Jan 2015 00:25:21 -0300 Subject: [PATCH 24/37] removed deadcode --- scene/gui/control.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 91d6a162f56..068801d0bbc 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -768,12 +768,6 @@ Control* Control::_find_control_at_pos(CanvasItem* p_node,const Point2& p_global c->_window_sort_subwindows(); // sort them - int idx=0; - for (List::Element *E=c->window->subwindows.front();E;E=E->next()) { - - if (!E->get()->is_visible()) - continue; - } for (List::Element *E=c->window->subwindows.back();E;E=E->prev()) { Control *sw = E->get(); From 60afd79a6e2354e0254c280d826bc6f12f68ffa1 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 3 Jan 2015 00:57:02 -0300 Subject: [PATCH 25/37] -added a check for setget while running the game , closes #1009 -fixed issues in tilemap editor (swap arrows not showing/hiding properly) --- modules/gdscript/gd_compiler.cpp | 53 +++++++++++++++++-- .../editor/plugins/tile_map_editor_plugin.cpp | 5 +- tools/editor/plugins/tile_map_editor_plugin.h | 4 ++ 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/modules/gdscript/gd_compiler.cpp b/modules/gdscript/gd_compiler.cpp index d4fe8b626be..6289e6961c8 100644 --- a/modules/gdscript/gd_compiler.cpp +++ b/modules/gdscript/gd_compiler.cpp @@ -45,8 +45,13 @@ void GDCompiler::_set_error(const String& p_error,const GDParser::Node *p_node) return; error=p_error; - err_line=p_node->line; - err_column=p_node->column; + if (p_node) { + err_line=p_node->line; + err_column=p_node->column; + } else { + err_line=0; + err_column=0; + } } bool GDCompiler::_create_unary_operator(CodeGen& codegen,const GDParser::OperatorNode *on,Variant::Operator op, int p_stack_level) { @@ -1522,7 +1527,7 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars GDScript::MemberInfo minfo; minfo.index = p_script->member_indices.size(); minfo.setter = p_class->variables[i].setter; - minfo.getter = p_class->variables[i].getter; + minfo.getter = p_class->variables[i].getter; p_script->member_indices[name]=minfo; p_script->members.insert(name); @@ -1586,6 +1591,48 @@ Error GDCompiler::_parse_class(GDScript *p_script,GDScript *p_owner,const GDPars return err; } +#ifdef DEBUG_ENABLED + //validate setters/getters if debug is enabled + for(int i=0;ivariables.size();i++) { + + if (p_class->variables[i].setter) { + const Map::Element *E=p_script->get_member_functions().find(p_class->variables[i].setter); + if (!E) { + _set_error("Setter function '"+String(p_class->variables[i].setter)+"' not found in class.",NULL); + err_line=p_class->variables[i].line; + err_column=0; + return ERR_PARSE_ERROR; + } + + if (E->get().is_static()) { + + _set_error("Setter function '"+String(p_class->variables[i].setter)+"' is static.",NULL); + err_line=p_class->variables[i].line; + err_column=0; + return ERR_PARSE_ERROR; + } + + } + if (p_class->variables[i].getter) { + const Map::Element *E=p_script->get_member_functions().find(p_class->variables[i].getter); + if (!E) { + _set_error("Getter function '"+String(p_class->variables[i].getter)+"' not found in class.",NULL); + err_line=p_class->variables[i].line; + err_column=0; + return ERR_PARSE_ERROR; + } + + if (E->get().is_static()) { + + _set_error("Getter function '"+String(p_class->variables[i].getter)+"' is static.",NULL); + err_line=p_class->variables[i].line; + err_column=0; + return ERR_PARSE_ERROR; + } + + } + } +#endif return OK; } diff --git a/tools/editor/plugins/tile_map_editor_plugin.cpp b/tools/editor/plugins/tile_map_editor_plugin.cpp index 21474205d7a..118ddc97e68 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.cpp +++ b/tools/editor/plugins/tile_map_editor_plugin.cpp @@ -728,7 +728,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { add_child(palette); // Add menu items - HBoxContainer *canvas_item_editor_hb = memnew( HBoxContainer ); + canvas_item_editor_hb = memnew( HBoxContainer ); CanvasItemEditor::get_singleton()->add_control_to_menu_panel(canvas_item_editor_hb); canvas_item_editor_hb->add_child( memnew( VSeparator )); mirror_x = memnew( ToolButton ); @@ -741,6 +741,7 @@ TileMapEditor::TileMapEditor(EditorNode *p_editor) { mirror_y->set_tooltip("Mirror Y (S)"); mirror_y->set_focus_mode(FOCUS_NONE); canvas_item_editor_hb->add_child(mirror_y); + canvas_item_editor_hb->hide(); tool=TOOL_NONE; selection_active=false; @@ -762,10 +763,12 @@ void TileMapEditorPlugin::make_visible(bool p_visible) { if (p_visible) { tile_map_editor->show(); + tile_map_editor->get_canvas_item_editor_hb()->show(); } else { tile_map_editor->hide(); + tile_map_editor->get_canvas_item_editor_hb()->hide(); tile_map_editor->edit(NULL); } diff --git a/tools/editor/plugins/tile_map_editor_plugin.h b/tools/editor/plugins/tile_map_editor_plugin.h index 0a09a29f9d1..ef869591bd7 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.h +++ b/tools/editor/plugins/tile_map_editor_plugin.h @@ -73,6 +73,8 @@ class TileMapEditor : public VBoxContainer { ToolButton *mirror_x; ToolButton *mirror_y; + HBoxContainer *canvas_item_editor_hb; + struct CellOp { int idx; @@ -102,6 +104,7 @@ protected: static void _bind_methods(); public: + HBoxContainer *get_canvas_item_editor_hb() const { return canvas_item_editor_hb; } Vector2 snap_point(const Vector2& p_point) const; bool forward_input_event(const InputEvent& p_event); void edit(Node *p_tile_map); @@ -115,6 +118,7 @@ class TileMapEditorPlugin : public EditorPlugin { TileMapEditor *tile_map_editor; EditorNode *editor; + public: virtual bool forward_input_event(const InputEvent& p_event) { return tile_map_editor->forward_input_event(p_event); } From c83a00c603c84eeac2188cae6b4986c3b86a05c6 Mon Sep 17 00:00:00 2001 From: romulox_x Date: Fri, 2 Jan 2015 20:23:52 -0800 Subject: [PATCH 26/37] Changed texturebutton scale from float to Size2 --- scene/gui/texture_button.cpp | 13 ++++++++----- scene/gui/texture_button.h | 6 +++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp index e8967927cb7..1a7087b7efd 100644 --- a/scene/gui/texture_button.cpp +++ b/scene/gui/texture_button.cpp @@ -53,6 +53,10 @@ Size2 TextureButton::get_minimum_size() const { bool TextureButton::has_point(const Point2& p_point) const { + if (scale[0] <= 0 || scale[1] <= 0) { + return false; + } + Point2 ppos = p_point/scale; if (click_mask.is_valid()) { @@ -159,7 +163,7 @@ void TextureButton::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/disabled",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_disabled_texture"), _SCS("get_disabled_texture")); ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/focused",PROPERTY_HINT_RESOURCE_TYPE,"Texture"), _SCS("set_focused_texture"), _SCS("get_focused_texture")); ADD_PROPERTY(PropertyInfo(Variant::OBJECT,"textures/click_mask",PROPERTY_HINT_RESOURCE_TYPE,"BitMap"), _SCS("set_click_mask"), _SCS("get_click_mask")) ; - ADD_PROPERTY(PropertyInfo(Variant::REAL,"params/scale",PROPERTY_HINT_RANGE,"0.01,1024,0.01"), _SCS("set_scale"), _SCS("get_scale")); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2,"params/scale",PROPERTY_HINT_RANGE,"0.01,1024,0.01"), _SCS("set_scale"), _SCS("get_scale")); ADD_PROPERTY(PropertyInfo(Variant::COLOR,"params/modulate"), _SCS("set_modulate"), _SCS("get_modulate")); } @@ -228,15 +232,14 @@ void TextureButton::set_focused_texture(const Ref& p_focused) { focused = p_focused; }; -void TextureButton::set_scale(float p_scale) { +void TextureButton::set_scale(Size2 p_scale) { - ERR_FAIL_COND(p_scale<=0); scale=p_scale; minimum_size_changed(); update(); } -float TextureButton::get_scale() const{ +Size2 TextureButton::get_scale() const{ return scale; } @@ -252,6 +255,6 @@ Color TextureButton::get_modulate() const { TextureButton::TextureButton() { - scale=1.0; + scale=Size2(1.0, 1.0); modulate=Color(1,1,1); } diff --git a/scene/gui/texture_button.h b/scene/gui/texture_button.h index 0209d3c2602..94bc53b3ff6 100644 --- a/scene/gui/texture_button.h +++ b/scene/gui/texture_button.h @@ -41,7 +41,7 @@ class TextureButton : public BaseButton { Ref disabled; Ref focused; Ref click_mask; - float scale; + Size2 scale; Color modulate; @@ -68,8 +68,8 @@ public: Ref get_focused_texture() const; Ref get_click_mask() const; - void set_scale(float p_scale); - float get_scale() const; + void set_scale(Size2 p_scale); + Size2 get_scale() const; void set_modulate(const Color& p_modulate); Color get_modulate() const; From cef3bd026fa6a6c1b2e19693b111210b3ce876ac Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 3 Jan 2015 11:06:53 -0300 Subject: [PATCH 27/37] -fixed issue with denormals in half precission, closes #1073 -added h_offset and v_offset to 3D Camera, should allow to do the same as in #1102 --- bin/tests/test_math.cpp | 1 + core/io/json.cpp | 2 +- core/ustring.cpp | 16 +++++++++----- core/ustring.h | 2 +- drivers/gles2/rasterizer_gles2.cpp | 4 +++- scene/3d/camera.cpp | 35 ++++++++++++++++++++++++++++++ scene/3d/camera.h | 8 +++++++ 7 files changed, 60 insertions(+), 8 deletions(-) diff --git a/bin/tests/test_math.cpp b/bin/tests/test_math.cpp index 2db945d5fde..ea324a73815 100644 --- a/bin/tests/test_math.cpp +++ b/bin/tests/test_math.cpp @@ -80,6 +80,7 @@ MainLoop* test() { { + // print_line("NUM: "+itos(237641278346127)); print_line("NUM: "+itos(-128)); return NULL; diff --git a/core/io/json.cpp b/core/io/json.cpp index a83d7e4d6e0..88a23eb4cd8 100644 --- a/core/io/json.cpp +++ b/core/io/json.cpp @@ -250,7 +250,7 @@ Error JSON::_get_token(const CharType *p_str, int &idx, int p_len, Token& r_toke if (p_str[idx]=='-' || (p_str[idx]>='0' && p_str[idx]<='9')) { //a number const CharType *rptr; - double number = String::to_double(&p_str[idx],-1,&rptr); + double number = String::to_double(&p_str[idx],&rptr); idx+=(rptr - &p_str[idx]); r_token.type=TK_NUMBER; r_token.value=number; diff --git a/core/ustring.cpp b/core/ustring.cpp index d75c21d16e3..50e5dc95c71 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -626,7 +626,7 @@ Vector String::split_floats(const String &p_splitter,bool p_allow_empty) if (end<0) end=len; if (p_allow_empty || (end>from)) - ret.push_back(String::to_double(&c_str()[from],end-from)); + ret.push_back(String::to_double(&c_str()[from])); if (end==len) break; @@ -654,8 +654,11 @@ Vector String::split_floats_mk(const Vector &p_splitters,bool p_a spl_len=p_splitters[idx].length(); } - if (p_allow_empty || (end>from)) - ret.push_back(String::to_double(&c_str()[from],end-from)); + if (p_allow_empty || (end>from)) { + double d = String::to_double(&c_str()[from]); + print_line("get db: "+rtos(d)); + ret.push_back(String::to_double(&c_str()[from])); + } if (end==len) break; @@ -1959,8 +1962,10 @@ float String::to_float() const { return to_double(); } -double String::to_double(const CharType* p_str, int p_len, const CharType **r_end) { +double String::to_double(const CharType* p_str, const CharType **r_end) { + return built_in_strtod(p_str,(CharType**)r_end); +#if 0 #if 0 //ndef NO_USE_STDLIB return wcstod(p_str,p_len<0?NULL:p_str+p_len); @@ -2053,6 +2058,7 @@ double String::to_double(const CharType* p_str, int p_len, const CharType **r_en return sign*(integer+decimal)*Math::pow(10,exp_sign*exp); #endif +#endif } int64_t String::to_int(const CharType* p_str,int p_len) { @@ -3437,7 +3443,7 @@ String String::percent_encode() const { uint8_t c = cs[i]; if ( (c>='A' && c<='Z') || (c>='a' && c<='z') || (c>='0' && c<='9') || c=='-' || c=='_' || c=='~' || c=='.') { - char p[2]={c,0}; + char p[2]={(char)c,0}; encoded+=p; } else { char p[4]={'%',0,0,0}; diff --git a/core/ustring.h b/core/ustring.h index 8fe3a95463d..e1d67617423 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -142,7 +142,7 @@ public: int64_t to_int64() const; static int to_int(const char* p_str); static double to_double(const char* p_str); - static double to_double(const CharType* p_str, int p_len=-1, const CharType **r_end=NULL); + static double to_double(const CharType* p_str, const CharType **r_end=NULL); static int64_t to_int(const CharType* p_str,int p_len=-1); String capitalize() const; diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index ccbba2f51c8..b4791fc6d8c 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -139,11 +139,13 @@ static _FORCE_INLINE_ uint16_t make_half_float(float f) { else if (exp <= 0x38000000) { - // store a denorm half-float value or zero + /*// store a denorm half-float value or zero exp = (0x38000000 - exp) >> 23; mantissa >>= (14 + exp); hf = (((uint16_t)sign) << 15) | (uint16_t)(mantissa); + */ + hf=0; //denormals do not work for 3D } else { diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index 1db98862615..27420f80021 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -86,6 +86,10 @@ bool Camera::_set(const StringName& p_name, const Variant& p_value) { set_keep_aspect_mode(KeepAspect(int(p_value))); else if (p_name=="vaspect") set_keep_aspect_mode(p_value?KEEP_WIDTH:KEEP_HEIGHT); + else if (p_name=="h_offset") + h_offset=p_value; + else if (p_name=="v_offset") + v_offset=p_value; else if (p_name=="current") { if (p_value.operator bool()) { make_current(); @@ -128,6 +132,10 @@ bool Camera::_get(const StringName& p_name,Variant &r_ret) const { } } else if (p_name=="visible_layers") { r_ret=get_visible_layers(); + } else if (p_name=="h_offset") { + r_ret=get_h_offset(); + } else if (p_name=="v_offset") { + r_ret=get_v_offset(); } else if (p_name=="environment") { r_ret=get_environment(); } else @@ -170,12 +178,16 @@ void Camera::_get_property_list( List *p_list) const { p_list->push_back( PropertyInfo( Variant::BOOL, "current" ) ); p_list->push_back( PropertyInfo( Variant::INT, "visible_layers",PROPERTY_HINT_ALL_FLAGS ) ); p_list->push_back( PropertyInfo( Variant::OBJECT, "environment",PROPERTY_HINT_RESOURCE_TYPE,"Environment" ) ); + p_list->push_back( PropertyInfo( Variant::REAL, "h_offset" ) ); + p_list->push_back( PropertyInfo( Variant::REAL, "v_offset" ) ); } void Camera::_update_camera() { Transform tr = get_camera_transform(); + tr.origin+=tr.basis.get_axis(1)*v_offset; + tr.origin+=tr.basis.get_axis(0)*h_offset; VisualServer::get_singleton()->camera_set_transform( camera, tr ); // here goes listener stuff @@ -757,6 +769,27 @@ void Camera::look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, cons } +void Camera::set_v_offset(float p_offset) { + + v_offset=p_offset; + _update_camera();; +} + +float Camera::get_v_offset() const { + + return v_offset; +} + +void Camera::set_h_offset(float p_offset) { + h_offset=p_offset; + _update_camera(); +} + +float Camera::get_h_offset() const { + + return h_offset; +} + Camera::Camera() { @@ -772,6 +805,8 @@ Camera::Camera() { set_perspective(60.0,0.1,100.0); keep_aspect=KEEP_HEIGHT; layers=0xfffff; + v_offset=0; + h_offset=0; VisualServer::get_singleton()->camera_set_visible_layers(camera,layers); //active=false; } diff --git a/scene/3d/camera.h b/scene/3d/camera.h index bac8173bb7c..950688dfda3 100644 --- a/scene/3d/camera.h +++ b/scene/3d/camera.h @@ -61,6 +61,8 @@ private: float fov; float size; float near,far; + float v_offset; + float h_offset; KeepAspect keep_aspect; RID camera; @@ -140,6 +142,12 @@ public: void look_at(const Vector3& p_target, const Vector3& p_up_normal); void look_at_from_pos(const Vector3& p_pos,const Vector3& p_target, const Vector3& p_up_normal); + void set_v_offset(float p_offset); + float get_v_offset() const; + + void set_h_offset(float p_offset); + float get_h_offset() const; + Camera(); ~Camera(); From 6b5b95bb4e269a1bd740707e27eae09983b84268 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 3 Jan 2015 13:03:13 -0300 Subject: [PATCH 28/37] -added new code completion guess locations, closes #1032 -moved commandline fix to mingw-only, should fix #1064 --- SConstruct | 20 ----------- core/os/input.cpp | 25 ++++++++++++++ core/os/input.h | 2 ++ drivers/gles2/rasterizer_gles2.cpp | 2 +- modules/gdscript/gd_editor.cpp | 53 ++++++++++++++++++++++++++++-- modules/gdscript/gd_parser.cpp | 14 +++++--- modules/gdscript/gd_parser.h | 1 + platform/windows/detect.py | 21 ++++++++++++ scene/gui/text_edit.cpp | 40 +++++++++++++++++----- 9 files changed, 141 insertions(+), 37 deletions(-) diff --git a/SConstruct b/SConstruct index f5aa0cd1bd6..b9f2b7e2c4a 100644 --- a/SConstruct +++ b/SConstruct @@ -170,26 +170,6 @@ if selected_platform in platform_list: else: env = env_base.Clone() - # Workaround for MinGW. See: - # http://www.scons.org/wiki/LongCmdLinesOnWin32 - if (os.name=="nt"): - import subprocess - def mySpawn(sh, escape, cmd, args, env): - newargs = ' '.join(args[1:]) - cmdline = cmd + " " + newargs - startupinfo = subprocess.STARTUPINFO() - startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW - proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, startupinfo=startupinfo, shell = False, env = env) - data, err = proc.communicate() - rv = proc.wait() - if rv: - print "=====" - print err - print "=====" - return rv - env['SPAWN'] = mySpawn - env.extra_suffix="" CCFLAGS = env.get('CCFLAGS', '') diff --git a/core/os/input.cpp b/core/os/input.cpp index 4151c1b5a8c..a827e75896c 100644 --- a/core/os/input.cpp +++ b/core/os/input.cpp @@ -29,6 +29,7 @@ #include "input.h" #include "input_map.h" #include "os/os.h" +#include "globals.h" Input *Input::singleton=NULL; Input *Input::get_singleton() { @@ -69,6 +70,30 @@ void Input::_bind_methods() { ADD_SIGNAL( MethodInfo("joy_connection_changed", PropertyInfo(Variant::INT, "index"), PropertyInfo(Variant::BOOL, "connected")) ); } +void Input::get_argument_options(const StringName& p_function,int p_idx,List*r_options) const { +#ifdef TOOLS_ENABLED + + String pf=p_function; + if (p_idx==0 && (pf=="is_action_pressed" || pf=="action_press" || pf=="action_release")) { + + List pinfo; + Globals::get_singleton()->get_property_list(&pinfo); + + for(List::Element *E=pinfo.front();E;E=E->next()) { + const PropertyInfo &pi=E->get(); + + if (!pi.name.begins_with("input/")) + continue; + + String name = pi.name.substr(pi.name.find("/")+1,pi.name.length()); + r_options->push_back("\""+name+"\""); + + } + } +#endif + +} + Input::Input() { singleton=this; diff --git a/core/os/input.h b/core/os/input.h index 1cb0f35d963..387a43a35a4 100644 --- a/core/os/input.h +++ b/core/os/input.h @@ -76,6 +76,8 @@ public: virtual void action_press(const StringName& p_action)=0; virtual void action_release(const StringName& p_action)=0; + void get_argument_options(const StringName& p_function,int p_idx,List*r_options) const; + Input(); }; diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index b4791fc6d8c..161e3048272 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -145,7 +145,7 @@ static _FORCE_INLINE_ uint16_t make_half_float(float f) { hf = (((uint16_t)sign) << 15) | (uint16_t)(mantissa); */ - hf=0; //denormals do not work for 3D + hf=0; //denormals do not work for 3D, convert to zero } else { diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index eb1d0a4db32..12dc1bb1391 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -28,7 +28,7 @@ /*************************************************************************/ #include "gd_script.h" #include "gd_compiler.h" - +#include "globals.h" void GDScriptLanguage::get_comment_delimiters(List *p_delimiters) const { @@ -1276,7 +1276,23 @@ static void _make_function_hint(const GDParser::FunctionNode* p_func,int p_argid static void _find_type_arguments(const GDParser::Node*p_node,int p_line,const StringName& p_method,const GDCompletionIdentifier& id, int p_argidx, Set& result, String& arghint) { - if (id.type==Variant::OBJECT && id.obj_type!=StringName()) { + if (id.type==Variant::INPUT_EVENT && String(p_method)=="is_action" && p_argidx==0) { + + List pinfo; + Globals::get_singleton()->get_property_list(&pinfo); + + for(List::Element *E=pinfo.front();E;E=E->next()) { + const PropertyInfo &pi=E->get(); + + if (!pi.name.begins_with("input/")) + continue; + + String name = pi.name.substr(pi.name.find("/")+1,pi.name.length()); + result.insert("\""+name+"\""); + } + + + } else if (id.type==Variant::OBJECT && id.obj_type!=StringName()) { MethodBind *m = ObjectTypeDB::get_method(id.obj_type,p_method); @@ -1299,7 +1315,7 @@ static void _find_type_arguments(const GDParser::Node*p_node,int p_line,const St const GDParser::OperatorNode *op=static_cast(p_node); if (op->arguments.size()>) - }*/ + }*/ } else { Object *obj=id.value; @@ -1826,6 +1842,37 @@ Error GDScriptLanguage::complete_code(const String& p_code, const String& p_base _find_call_arguments(context,p.get_completion_node(),p.get_completion_line(),p.get_completion_argument_index(),options,r_call_hint); } break; + case GDParser::COMPLETION_VIRTUAL_FUNC: { + + GDCompletionIdentifier cid = _get_native_class(context); + + if (cid.obj_type!=StringName()) { + List vm; + ObjectTypeDB::get_virtual_methods(cid.obj_type,&vm); + for(List::Element *E=vm.front();E;E=E->next()) { + + MethodInfo &mi=E->get(); + String m = mi.name; + if (m.find(":")!=-1) + m=m.substr(0,m.find(":")); + m+="("; + + if (mi.arguments.size()) { + for(int i=0;i0) + m+=", "; + String n =mi.arguments[i].name; + if (n.find(":")!=-1) + n=n.substr(0,n.find(":")); + m+=n; + } + } + m+="):"; + + options.insert(m); + } + } + } break; } diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index f79f3ee44a5..aa2878f9e14 100644 --- a/modules/gdscript/gd_parser.cpp +++ b/modules/gdscript/gd_parser.cpp @@ -2027,14 +2027,20 @@ void GDParser::_parse_class(ClassNode *p_class) { } - if (tokenizer->get_token(1)!=GDTokenizer::TK_IDENTIFIER) { + tokenizer->advance(); + StringName name; + + if (_get_completable_identifier(COMPLETION_VIRTUAL_FUNC,name)) { + + } + + + if (name==StringName()) { _set_error("Expected identifier after 'func' (syntax: 'func ([arguments]):' )."); return; } - StringName name = tokenizer->get_token_identifier(1); - for(int i=0;ifunctions.size();i++) { if (p_class->functions[i]->name==name) { _set_error("Function '"+String(name)+"' already exists in this class (at line: "+itos(p_class->functions[i]->line)+")."); @@ -2045,7 +2051,7 @@ void GDParser::_parse_class(ClassNode *p_class) { _set_error("Function '"+String(name)+"' already exists in this class (at line: "+itos(p_class->static_functions[i]->line)+")."); } } - tokenizer->advance(2); + if (tokenizer->get_token()!=GDTokenizer::TK_PARENTHESIS_OPEN) { diff --git a/modules/gdscript/gd_parser.h b/modules/gdscript/gd_parser.h index 26955d2b7a2..44e7b55323a 100644 --- a/modules/gdscript/gd_parser.h +++ b/modules/gdscript/gd_parser.h @@ -363,6 +363,7 @@ public: COMPLETION_METHOD, COMPLETION_CALL_ARGUMENTS, COMPLETION_INDEX, + COMPLETION_VIRTUAL_FUNC }; diff --git a/platform/windows/detect.py b/platform/windows/detect.py index be92ee8f6da..245d6f1bd3d 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -135,6 +135,27 @@ def configure(env): env.Append(LIBPATH=[DIRECTX_PATH+"/Lib/x86"]) env['ENV'] = os.environ; else: + + # Workaround for MinGW. See: + # http://www.scons.org/wiki/LongCmdLinesOnWin32 + if (os.name=="nt"): + import subprocess + def mySpawn(sh, escape, cmd, args, env): + newargs = ' '.join(args[1:]) + cmdline = cmd + " " + newargs + startupinfo = subprocess.STARTUPINFO() + startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW + proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, startupinfo=startupinfo, shell = False, env = env) + data, err = proc.communicate() + rv = proc.wait() + if rv: + print "=====" + print err + print "=====" + return rv + env['SPAWN'] = mySpawn + #build using mingw if (os.name=="nt"): env['ENV']['TMP'] = os.environ['TMP'] #way to go scons, you can be so stupid sometimes diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 933895a2076..8afcbf32836 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -3274,19 +3274,41 @@ void TextEdit::_update_completion_candidates() { String s; - - while(cofs>0 && l[cofs-1]>32 && _is_completable(l[cofs-1])) { - s=String::chr(l[cofs-1])+s; - if (l[cofs-1]=='\'' || l[cofs-1]=='"') - break; - - cofs--; + + //look for keywords first + + bool pre_keyword=false; + + if (cofs>0 && l[cofs-1]==' ') { + int kofs=cofs-1; + String kw; + while (kofs>=0 && l[kofs]==' ') + kofs--; + + while(kofs>=0 && l[kofs]>32 && _is_completable(l[kofs])) { + kw=String::chr(l[kofs])+kw; + kofs--; + } + + pre_keyword=keywords.has(kw); + print_line("KW "+kw+"? "+itos(pre_keyword)); + + } else { + + + while(cofs>0 && l[cofs-1]>32 && _is_completable(l[cofs-1])) { + s=String::chr(l[cofs-1])+s; + if (l[cofs-1]=='\'' || l[cofs-1]=='"') + break; + + cofs--; + } } - + update(); - if (s=="" && (cofs==0 || !completion_prefixes.has(String::chr(l[cofs-1])))) { + if (!pre_keyword && s=="" && (cofs==0 || !completion_prefixes.has(String::chr(l[cofs-1])))) { //none to complete, cancel _cancel_completion(); return; From ffd4b22e09e0da3c6e14b59c930747d35535726b Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 3 Jan 2015 13:10:00 -0300 Subject: [PATCH 29/37] -add *.flags as a filter automatically when exporting, solves #1029 --- tools/editor/editor_import_export.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/editor/editor_import_export.cpp b/tools/editor/editor_import_export.cpp index a511e78863b..58f9afaa5d7 100644 --- a/tools/editor/editor_import_export.cpp +++ b/tools/editor/editor_import_export.cpp @@ -292,7 +292,11 @@ Vector EditorExportPlatform::get_dependencies(bool p_bundles) const _add_filter_to_list(exported,"*"); } else { _add_to_list(EditorFileSystem::get_singleton()->get_filesystem(),exported); - _add_filter_to_list(exported,EditorImportExport::get_singleton()->get_export_custom_filter()); + String cf = EditorImportExport::get_singleton()->get_export_custom_filter(); + if (cf!="") + cf+=","; + cf+="*.flags"; + _add_filter_to_list(exported,cf); } @@ -361,8 +365,12 @@ Vector EditorExportPlatform::get_dependencies(bool p_bundles) const } } } + String cf = EditorImportExport::get_singleton()->get_export_custom_filter(); + if (cf!="") + cf+=","; + cf+="*.flags"; + _add_filter_to_list(exported,cf); - _add_filter_to_list(exported,EditorImportExport::get_singleton()->get_export_custom_filter()); } From 167c1027bea5b208e5878c96682eb2bec6f59633 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 3 Jan 2015 15:39:01 -0300 Subject: [PATCH 30/37] -fixed bug on focus capture, now respets line/text edit -when playing animations, property editor is now refreshed properly, fixes #1046 --- scene/gui/control.cpp | 4 +- tools/editor/editor_settings.cpp | 1 + .../animation_player_editor_plugin.cpp | 4 + tools/editor/property_editor.cpp | 73 +++++++++++++++++++ tools/editor/property_editor.h | 4 + 5 files changed, 84 insertions(+), 2 deletions(-) diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 068801d0bbc..ce268843b1a 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -2684,8 +2684,8 @@ bool Control::is_stopping_mouse() const { Control *Control::get_focus_owner() const { ERR_FAIL_COND_V(!is_inside_tree(),NULL); - ERR_FAIL_COND_V(!window,NULL); - return window->key_focus; + ERR_FAIL_COND_V(!data.window,NULL); + return data.window->window->key_focus; } void Control::_bind_methods() { diff --git a/tools/editor/editor_settings.cpp b/tools/editor/editor_settings.cpp index 3f44701b98f..bc800d7e9e0 100644 --- a/tools/editor/editor_settings.cpp +++ b/tools/editor/editor_settings.cpp @@ -446,6 +446,7 @@ void EditorSettings::_load_defaults() { set("animation/confirm_insert_track",true); set("property_editor/texture_preview_width",48); + set("property_editor/auto_refresh_interval",0.3); set("help/doc_path",""); set("import/ask_save_before_reimport",false); diff --git a/tools/editor/plugins/animation_player_editor_plugin.cpp b/tools/editor/plugins/animation_player_editor_plugin.cpp index 8bb37f1d715..f706d67f6d8 100644 --- a/tools/editor/plugins/animation_player_editor_plugin.cpp +++ b/tools/editor/plugins/animation_player_editor_plugin.cpp @@ -76,6 +76,8 @@ void AnimationPlayerEditor::_notification(int p_what) { seek->set_val(player->get_current_animation_pos()); if (edit_anim->is_pressed()) editor->get_animation_editor()->set_anim_pos(player->get_current_animation_pos()); + EditorNode::get_singleton()->get_property_editor()->refresh(); + } else if (last_active) { //need the last frame after it stopped @@ -854,6 +856,8 @@ void AnimationPlayerEditor::_animation_key_editor_seek(float p_pos) { return; seek->set_val(p_pos); + EditorNode::get_singleton()->get_property_editor()->refresh(); + //seekit diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index 777694481b8..559d9b1db54 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -1876,6 +1876,14 @@ void PropertyEditor::_notification(int p_what) { if (p_what==NOTIFICATION_FIXED_PROCESS) { + if (refresh_countdown>0) { + refresh_countdown-=get_fixed_process_delta_time(); + if (refresh_countdown<=0) { + TreeItem *root = tree->get_root(); + _refresh_item(root); + } + } + changing=true; if (update_tree_pending) { @@ -1982,7 +1990,71 @@ TreeItem *PropertyEditor::get_parent_node(String p_path,HashMapget_metadata(1); + + if (name!=String()) { + + if (get_instanced_node()) { + + Dictionary d = get_instanced_node()->get_instance_state(); + if (d.has(name)) { + Variant v = obj->get(name); + Variant vorig = d[name]; + + int found=-1; + for(int i=0;iget_button_count(1);i++) { + + if (p_item->get_button_id(1,i)==3) { + found=i; + break; + } + } + + bool changed = ! (v==vorig); + + if ((found!=-1)!=changed) { + + if (changed) { + + p_item->add_button(1,get_icon("Reload","EditorIcons"),3); + } else { + + p_item->erase_button(1,found); + } + + } + + } + + } + + Dictionary d=p_item->get_metadata(0); + set_item_text(p_item,d["type"],d["name"],d["hint"],d["hint_text"]); + } + + TreeItem *c=p_item->get_children(); + + while (c) { + + _refresh_item(c); + + c=c->get_next(); + } + +} + +void PropertyEditor::refresh() { + + if (refresh_countdown>0) + return; + refresh_countdown=EditorSettings::get_singleton()->get("property_editor/auto_refresh_interval"); + +} void PropertyEditor::update_tree() { @@ -3021,6 +3093,7 @@ PropertyEditor::PropertyEditor() { keying=false; read_only=false; show_categories=false; + refresh_countdown=0; } diff --git a/tools/editor/property_editor.h b/tools/editor/property_editor.h index 08435ad75d4..c05e13b90e9 100644 --- a/tools/editor/property_editor.h +++ b/tools/editor/property_editor.h @@ -156,6 +156,7 @@ class PropertyEditor : public Control { bool keying; bool read_only; bool show_categories; + float refresh_countdown; HashMap pending; String selected_property; @@ -185,6 +186,7 @@ class PropertyEditor : public Control { void _draw_flags(Object *ti,const Rect2& p_rect); Node *get_instanced_node(); + void _refresh_item(TreeItem *p_item); UndoRedo *undo_redo; protected: @@ -203,6 +205,8 @@ public: void update_tree(); void update_property(const String& p_prop); + void refresh(); + void edit(Object* p_object); void set_keying(bool p_active); From 507736690de2f4125aec25ecb0339196fb89ba56 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 3 Jan 2015 16:00:37 -0300 Subject: [PATCH 31/37] removed print --- core/ustring.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/ustring.cpp b/core/ustring.cpp index 50e5dc95c71..581cc29440b 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -655,8 +655,6 @@ Vector String::split_floats_mk(const Vector &p_splitters,bool p_a } if (p_allow_empty || (end>from)) { - double d = String::to_double(&c_str()[from]); - print_line("get db: "+rtos(d)); ret.push_back(String::to_double(&c_str()[from])); } From fbdd925d9be1c4c96d05089d7d5a58cd938b002c Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 3 Jan 2015 16:52:37 -0300 Subject: [PATCH 32/37] -Work in progress visual shader editor *DOES NOT WORK YET* --- core/method_bind.h | 1 + core/object_type_db.cpp | 12 + core/object_type_db.h | 2 + demos/2d/platformer/player.gd | 3 + demos/2d/platformer/player.xml | 277 +- drivers/builtin_openssl2/openssl/md5.h | 4 +- drivers/gles2/rasterizer_gles2.cpp | 3 +- drivers/mpc/audio_stream_mpc.cpp | 8 +- drivers/theoraplayer/SCsub | 10 +- drivers/theoraplayer/src/TheoraVideoClip.cpp | 1 + .../video_stream_theoraplayer.cpp | 6 +- drivers/unix/memory_pool_static_malloc.cpp | 8 +- drivers/webp/dsp/dsp.h | 2 +- drivers/webp/utils/bit_reader.h | 1 + modules/gdscript/gd_functions.cpp | 4 + platform/iphone/detect.py | 41 +- platform/iphone/platform_config.h | 1 + platform/iphone/platform_refcount.h | 18 + platform/winrt/include/angle_windowsstore.h | 37 + scene/3d/collision_object.cpp | 5 + scene/3d/ray_cast.cpp | 58 +- scene/3d/ray_cast.h | 9 +- scene/gui/graph_edit.cpp | 517 ++++ scene/gui/graph_edit.h | 93 + scene/gui/graph_node.cpp | 272 +- scene/gui/graph_node.h | 46 +- scene/gui/menu_button.cpp | 1 + scene/gui/popup_menu.cpp | 19 +- scene/gui/popup_menu.h | 4 + scene/register_scene_types.cpp | 16 +- .../resources/default_theme/default_theme.cpp | 8 +- .../default_theme/graph_node_close.png | Bin 0 -> 243 bytes scene/resources/default_theme/theme_data.h | 5 + scene/resources/material.cpp | 2 +- scene/resources/shader.cpp | 13 +- scene/resources/shader.h | 18 +- scene/resources/shader_graph.cpp | 2359 +++++++++++------ scene/resources/shader_graph.h | 407 ++- servers/visual/shader_graph.h | 3 - tools/SCsub | 17 +- tools/doc/doc_data.cpp | 6 +- tools/editor/editor_node.cpp | 4 +- tools/editor/editor_node.h | 4 + .../editor/icons/icon_canvas_item_shader.png | Bin 0 -> 568 bytes .../icons/icon_canvas_item_shader_graph.png | Bin 0 -> 575 bytes tools/editor/icons/icon_material_shader.png | Bin 0 -> 844 bytes .../icons/icon_material_shader_graph.png | Bin 0 -> 949 bytes .../collision_polygon_2d_editor_plugin.cpp | 2 + .../plugins/shader_graph_editor_plugin.cpp | 2277 +++++++++------- .../plugins/shader_graph_editor_plugin.h | 143 +- tools/editor/property_editor.cpp | 12 +- 51 files changed, 4587 insertions(+), 2172 deletions(-) create mode 100644 platform/iphone/platform_refcount.h create mode 100644 platform/winrt/include/angle_windowsstore.h create mode 100644 scene/gui/graph_edit.cpp create mode 100644 scene/gui/graph_edit.h create mode 100644 scene/resources/default_theme/graph_node_close.png create mode 100644 tools/editor/icons/icon_canvas_item_shader.png create mode 100644 tools/editor/icons/icon_canvas_item_shader_graph.png create mode 100644 tools/editor/icons/icon_material_shader.png create mode 100644 tools/editor/icons/icon_material_shader_graph.png diff --git a/core/method_bind.h b/core/method_bind.h index 3f08c70af8b..6ea9340ad54 100644 --- a/core/method_bind.h +++ b/core/method_bind.h @@ -178,6 +178,7 @@ public: #ifdef DEBUG_METHODS_ENABLED _FORCE_INLINE_ void set_return_type(const StringName& p_type) { ret_type=p_type; } + _FORCE_INLINE_ StringName get_return_type() const { return ret_type; } _FORCE_INLINE_ Variant::Type get_argument_type(int p_argument) const { diff --git a/core/object_type_db.cpp b/core/object_type_db.cpp index efd92542ce8..f7917b74184 100644 --- a/core/object_type_db.cpp +++ b/core/object_type_db.cpp @@ -191,6 +191,7 @@ MethodDefinition _MD(const char* p_name,const char *p_arg1,const char *p_arg2,co HashMap ObjectTypeDB::types; HashMap ObjectTypeDB::resource_base_extensions; +HashMap ObjectTypeDB::compat_types; ObjectTypeDB::TypeInfo::TypeInfo() { @@ -263,12 +264,22 @@ bool ObjectTypeDB::type_exists(const String &p_type) { return types.has(p_type); } +void ObjectTypeDB::add_compatibility_type(const StringName& p_type,const StringName& p_fallback) { + + compat_types[p_type]=p_fallback; +} + Object *ObjectTypeDB::instance(const String &p_type) { TypeInfo *ti; { OBJTYPE_LOCK; ti=types.getptr(p_type); + if (!ti || ti->disabled || !ti->creation_func) { + if (compat_types.has(p_type)) { + ti=types.getptr(compat_types[p_type]); + } + } ERR_FAIL_COND_V(!ti,NULL); ERR_FAIL_COND_V(ti->disabled,NULL); ERR_FAIL_COND_V(!ti->creation_func,NULL); @@ -914,6 +925,7 @@ void ObjectTypeDB::cleanup() { } types.clear(); resource_base_extensions.clear(); + compat_types.clear(); } // diff --git a/core/object_type_db.h b/core/object_type_db.h index f2ff194e28b..617a0a7c20c 100644 --- a/core/object_type_db.h +++ b/core/object_type_db.h @@ -151,6 +151,7 @@ class ObjectTypeDB { static Mutex *lock; static HashMap types; static HashMap resource_base_extensions; + static HashMap compat_types; #ifdef DEBUG_METHODS_ENABLED static MethodBind* bind_methodfi(uint32_t p_flags, MethodBind *p_bind , const MethodDefinition &method_name, const Variant **p_defs, int p_defcount); @@ -482,6 +483,7 @@ public: static void get_resource_base_extensions(List *p_extensions); static void get_extensions_for_type(const StringName& p_type,List *p_extensions); + static void add_compatibility_type(const StringName& p_type,const StringName& p_fallback); static void init(); static void cleanup(); }; diff --git a/demos/2d/platformer/player.gd b/demos/2d/platformer/player.gd index 481f340ab8c..b08105212ce 100644 --- a/demos/2d/platformer/player.gd +++ b/demos/2d/platformer/player.gd @@ -53,12 +53,15 @@ var enemy func _integrate_forces(s): + + var lv = s.get_linear_velocity() var step = s.get_step() var new_anim=anim var new_siding_left=siding_left + # Get the controls var move_left = Input.is_action_pressed("move_left") var move_right = Input.is_action_pressed("move_right") diff --git a/demos/2d/platformer/player.xml b/demos/2d/platformer/player.xml index c129d01f0df..196881dee43 100644 --- a/demos/2d/platformer/player.xml +++ b/demos/2d/platformer/player.xml @@ -1,13 +1,13 @@ - + - - + + @@ -50,7 +50,52 @@ - "run" + "jumping" + 0.5 + True + 0.25 + "value" + "sprite:frame" + 1 + + "cont" + False + "transitions" + 1, 1, 1 + "values" + + 23 + 24 + 23 + + "times" + 0, 0.25, 0.5 + + + + + "idle_weapon" + 0.5 + True + 0.25 + "value" + "sprite:frame" + 1 + + "cont" + False + "transitions" + 1 + "values" + + 25 + + "times" + 0 + + + + 1.25 True 0.25 @@ -75,55 +120,6 @@ 0, 0.25, 0.5, 0.75, 1, 1.25 - - - "run_gun_fire" - 1.25 - True - 0.25 - "value" - "sprite:frame" - 1 - - "cont" - False - "transitions" - 1, 1, 1, 1, 1, 1 - "values" - - 10 - 11 - 12 - 13 - 14 - 5 - - "times" - 0, 0.25, 0.5, 0.75, 1, 1.25 - - - - - "jumping_weapon" - 0.5 - True - 0.25 - "value" - "sprite:frame" - 1 - - "cont" - False - "transitions" - 1 - "values" - - 26 - - "times" - 0 - - "crouch" @@ -148,7 +144,55 @@ - "jumping" + "falling" + 0.01 + True + 0.25 + "value" + "sprite:frame" + 1 + + "cont" + False + "transitions" + 1 + "values" + + 21 + + "times" + 0 + + + + + 1.25 + True + 0.25 + "value" + "sprite:frame" + 1 + + "cont" + False + "transitions" + 1, 1, 1, 1, 1, 1 + "values" + + 10 + 11 + 12 + 13 + 14 + 5 + + "times" + 0, 0.25, 0.5, 0.75, 1, 1.25 + + + + + "falling_weapon" 0.5 True 0.25 @@ -159,20 +203,17 @@ "cont" False "transitions" - 1, 1, 1 + 1 "values" - - 23 - 24 - 23 + + 26 "times" - 0, 0.25, 0.5 + 0 - - "run_weapon" + 1.25 True 0.25 @@ -198,30 +239,7 @@ - - "idle_weapon" - 0.5 - True - 0.25 - "value" - "sprite:frame" - 1 - - "cont" - False - "transitions" - 1 - "values" - - 25 - - "times" - 0 - - - - - "falling_weapon" + 0.5 True 0.25 @@ -241,28 +259,6 @@ 0 - - - "falling" - 0.01 - True - 0.25 - "value" - "sprite:frame" - 1 - - "cont" - False - "transitions" - 1 - "values" - - 21 - - "times" - 0 - - @@ -294,9 +290,10 @@ "names" - + "player" "RigidBody2D" + "_import_path" "visibility/visible" "visibility/opacity" "visibility/self_opacity" @@ -311,6 +308,7 @@ "shapes/1/shape" "shapes/1/transform" "shapes/1/trigger" + "layers" "mode" "mass" "friction" @@ -319,7 +317,7 @@ "continuous_cd" "contacts_reported" "contact_monitor" - "active" + "sleeping" "can_sleep" "velocity/linear" "velocity/angular" @@ -354,6 +352,8 @@ "config/flip_h" "config/flip_v" "config/texture" + "config/h_frames" + "config/v_frames" "params/direction" "params/spread" "params/linear_velocity" @@ -364,9 +364,12 @@ "params/radial_accel" "params/tangential_accel" "params/damping" + "params/initial_angle" "params/initial_size" "params/final_size" "params/hue_variation" + "params/anim_speed_scale" + "params/anim_initial_pos" "randomness/direction" "randomness/spread" "randomness/linear_velocity" @@ -377,9 +380,12 @@ "randomness/radial_accel" "randomness/tangential_accel" "randomness/damping" + "randomness/initial_angle" "randomness/initial_size" "randomness/final_size" "randomness/hue_variation" + "randomness/anim_speed_scale" + "randomness/anim_initial_pos" "color_phases/count" "phase_0/pos" "phase_0/color" @@ -396,15 +402,15 @@ "playback/default_blend_time" "root/root" "anims/idle" - "anims/run" - "anims/standing_weapon_ready" - "anims/jumping_weapon" - "anims/crouch" "anims/jumping" - "anims/run_weapon" "anims/idle_weapon" - "anims/falling_weapon" + "anims/run" + "anims/crouch" "anims/falling" + "anims/standing_weapon_ready" + "anims/falling_weapon" + "anims/run_weapon" + "anims/jumping_weapon" "playback/active" "playback/speed" "blend_times" @@ -473,7 +479,8 @@ "node_count" 14 "variants" - + + "" True 1 False @@ -485,6 +492,7 @@ 1, -0, 0, 1.76469, 0.291992, -12.1587 1, -0, 0, 1, 0, 0 + 1 3 0 3 @@ -507,11 +515,17 @@ False "zoom" 2.272073 + "use_snap" + False "ofs" -181.946, -86.2812 + "snap" + 10 "3D" + "deflight_rot_y" + 0.628319 "zfar" 500 "fov" @@ -525,10 +539,12 @@ 0 "y_rot" 0 - "use_orthogonal" - False + "listener" + True "use_environment" False + "use_orthogonal" + False "pos" 0, 0, 0 @@ -539,10 +555,12 @@ 0 "y_rot" 0 - "use_orthogonal" + "listener" False "use_environment" False + "use_orthogonal" + False "pos" 0, 0, 0 @@ -553,10 +571,12 @@ 0 "y_rot" 0 - "use_orthogonal" + "listener" False "use_environment" False + "use_orthogonal" + False "pos" 0, 0, 0 @@ -567,10 +587,12 @@ 0 "y_rot" 0 - "use_orthogonal" + "listener" False "use_environment" False + "use_orthogonal" + False "pos" 0, 0, 0 @@ -579,12 +601,18 @@ 1 "default_light" True + "ambient_light_color" + 0.15, 0.15, 0.15, 1 "show_grid" True "show_origin" True "znear" 0.1 + "default_srgb" + False + "deflight_rot_x" + 0.942478 "__editor_run_settings__" @@ -595,14 +623,13 @@ 0 "__editor_plugin_screen__" - "3D" + "Script" 16 1, 1, 1, 1 0, 0, 0, 0 0.363636 - 1 20.7312, 3.21187 83.450417 4 @@ -654,7 +681,7 @@ "shoot" "nodes" - -1, -1, 1, 0, -1, 28, 2, 0, 3, 1, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11, 8, 12, 2, 13, 9, 14, 10, 15, 2, 16, 6, 17, 11, 18, 4, 19, 4, 20, 0, 21, 12, 22, 13, 23, 2, 24, 0, 25, 0, 26, 3, 27, 4, 28, 14, 29, 15, 0, 0, 0, 31, 30, -1, 18, 2, 0, 3, 1, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 32, 16, 33, 0, 34, 3, 35, 2, 36, 2, 37, 6, 38, 17, 39, 12, 40, 18, 41, 2, 42, 19, 0, 1, 0, 44, 43, -1, 57, 2, 0, 3, 1, 4, 20, 5, 2, 45, 21, 6, 22, 7, 23, 8, 5, 46, 24, 47, 25, 48, 1, 49, 4, 50, 25, 51, 2, 52, 3, 53, 3, 54, 2, 55, 26, 56, 2, 57, 2, 58, 27, 59, 4, 60, 28, 61, 29, 62, 1, 63, 4, 64, 4, 65, 30, 66, 4, 67, 4, 68, 4, 69, 31, 70, 31, 71, 4, 72, 4, 73, 4, 74, 4, 75, 31, 76, 4, 77, 4, 78, 4, 79, 4, 80, 4, 81, 4, 82, 4, 83, 4, 84, 4, 85, 6, 86, 4, 87, 18, 88, 1, 89, 32, 90, 1, 91, 33, 92, 1, 93, 34, 94, 35, 0, 0, 0, 96, 95, -1, 17, 97, 21, 98, 4, 99, 36, 100, 37, 101, 38, 102, 39, 103, 40, 104, 41, 105, 42, 106, 43, 107, 44, 108, 45, 109, 46, 110, 0, 111, 31, 112, 47, 113, 48, 0, 0, 0, 115, 114, -1, 22, 2, 0, 3, 1, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 33, 0, 116, 2, 117, 0, 118, 4, 119, 5, 120, 12, 121, 12, 122, 49, 123, 49, 124, 0, 125, 0, 126, 50, 127, 50, 128, 50, 129, 50, 0, 0, 0, 131, 130, -1, 7, 2, 0, 3, 1, 4, 1, 5, 2, 6, 51, 7, 4, 8, 5, 0, 0, 0, 132, 132, -1, 9, 2, 0, 3, 1, 4, 1, 5, 2, 6, 52, 7, 4, 8, 53, 133, 7, 134, 2, 0, 0, 0, 136, 135, -1, 14, 137, 13, 138, 54, 139, 4, 140, 1, 141, 4, 142, 4, 143, 4, 144, 55, 145, 55, 146, 55, 147, 55, 148, 6, 149, 4, 150, 4, 0, 0, 0, 151, 151, -1, 9, 2, 0, 3, 1, 4, 1, 5, 2, 6, 3, 7, 4, 8, 5, 152, 12, 153, 56, 0, 0, 0, 155, 154, -1, 4, 156, 12, 34, 3, 157, 4, 158, 5, 0, 9, 0, 160, 159, -1, 13, 2, 0, 3, 1, 4, 1, 5, 2, 6, 57, 7, 4, 8, 58, 161, 59, 162, 60, 163, 60, 164, 0, 165, 61, 166, 21, 0, 9, 0, 160, 167, -1, 13, 2, 0, 3, 1, 4, 1, 5, 2, 6, 62, 7, 4, 8, 58, 161, 63, 162, 60, 163, 60, 164, 0, 165, 64, 166, 21, 0, 9, 0, 160, 168, -1, 13, 2, 0, 3, 1, 4, 1, 5, 2, 6, 65, 7, 4, 8, 58, 161, 66, 162, 60, 163, 60, 164, 2, 165, 67, 166, 21, 0, 9, 0, 160, 169, -1, 13, 2, 0, 3, 1, 4, 1, 5, 2, 6, 68, 7, 4, 8, 58, 161, 69, 162, 60, 163, 60, 164, 2, 165, 70, 166, 21, 0 + -1, -1, 1, 0, -1, 30, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 10, 7, 11, 8, 12, 9, 13, 3, 14, 10, 15, 11, 16, 3, 17, 12, 18, 7, 19, 13, 20, 5, 21, 5, 22, 1, 23, 14, 24, 15, 25, 3, 26, 3, 27, 1, 28, 4, 29, 5, 30, 16, 31, 17, 0, 0, 0, 33, 32, -1, 19, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 34, 18, 35, 1, 36, 4, 37, 3, 38, 3, 39, 7, 40, 19, 41, 14, 42, 20, 43, 3, 44, 21, 0, 1, 0, 46, 45, -1, 66, 2, 0, 3, 1, 4, 2, 5, 22, 6, 3, 47, 12, 7, 23, 8, 24, 9, 6, 48, 25, 49, 26, 50, 2, 51, 5, 52, 26, 53, 3, 54, 4, 55, 4, 56, 3, 57, 27, 58, 3, 59, 3, 60, 28, 61, 12, 62, 12, 63, 5, 64, 29, 65, 30, 66, 2, 67, 5, 68, 5, 69, 31, 70, 5, 71, 5, 72, 5, 73, 5, 74, 32, 75, 32, 76, 5, 77, 2, 78, 5, 79, 5, 80, 5, 81, 5, 82, 32, 83, 5, 84, 5, 85, 5, 86, 5, 87, 5, 88, 5, 89, 5, 90, 5, 91, 5, 92, 5, 93, 5, 94, 5, 95, 7, 96, 5, 97, 20, 98, 2, 99, 33, 100, 2, 101, 34, 102, 2, 103, 35, 104, 36, 0, 0, 0, 106, 105, -1, 18, 2, 0, 107, 12, 108, 5, 109, 37, 110, 38, 111, 39, 112, 40, 113, 41, 114, 42, 115, 43, 116, 44, 117, 45, 118, 46, 119, 47, 120, 1, 121, 32, 122, 48, 123, 49, 0, 0, 0, 125, 124, -1, 23, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 35, 1, 126, 3, 127, 1, 128, 5, 129, 6, 130, 14, 131, 14, 132, 50, 133, 50, 134, 1, 135, 1, 136, 51, 137, 51, 138, 51, 139, 51, 0, 0, 0, 141, 140, -1, 8, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 52, 8, 5, 9, 6, 0, 0, 0, 142, 142, -1, 10, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 53, 8, 5, 9, 54, 143, 8, 144, 3, 0, 0, 0, 146, 145, -1, 15, 2, 0, 147, 15, 148, 55, 149, 5, 150, 2, 151, 5, 152, 5, 153, 5, 154, 56, 155, 56, 156, 56, 157, 56, 158, 7, 159, 5, 160, 5, 0, 0, 0, 161, 161, -1, 10, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 4, 8, 5, 9, 6, 162, 14, 163, 57, 0, 0, 0, 165, 164, -1, 5, 2, 0, 166, 14, 36, 4, 167, 5, 168, 6, 0, 9, 0, 170, 169, -1, 14, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 58, 8, 5, 9, 59, 171, 60, 172, 61, 173, 61, 174, 1, 175, 62, 176, 12, 0, 9, 0, 170, 177, -1, 14, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 63, 8, 5, 9, 59, 171, 64, 172, 61, 173, 61, 174, 1, 175, 65, 176, 12, 0, 9, 0, 170, 178, -1, 14, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 66, 8, 5, 9, 59, 171, 67, 172, 61, 173, 61, 174, 3, 175, 68, 176, 12, 0, 9, 0, 170, 179, -1, 14, 2, 0, 3, 1, 4, 2, 5, 2, 6, 3, 7, 69, 8, 5, 9, 59, 171, 70, 172, 61, 173, 61, 174, 3, 175, 71, 176, 12, 0 "conns" diff --git a/drivers/builtin_openssl2/openssl/md5.h b/drivers/builtin_openssl2/openssl/md5.h index 8f392f0ec64..765be94335a 100644 --- a/drivers/builtin_openssl2/openssl/md5.h +++ b/drivers/builtin_openssl2/openssl/md5.h @@ -105,9 +105,9 @@ typedef struct MD5state_st unsigned int num; } MD5_CTX; -#ifdef OPENSSL_FIPS +//#ifdef OPENSSL_FIPS int private_MD5_Init(MD5_CTX *c); -#endif +//#endif //#define MD5_Init _SSL_MD5_Init #define MD5_Final _SSL_MD5_Final diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index ccbba2f51c8..0816396385e 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -969,7 +969,7 @@ void RasterizerGLES2::texture_set_data(RID p_texture,const Image& p_image,VS::Cu - if (img.detect_alpha()==Image::ALPHA_BLEND) { + if ((!texture->flags&VS::TEXTURE_FLAG_VIDEO_SURFACE) && img.detect_alpha()==Image::ALPHA_BLEND) { texture->has_alpha=true; } @@ -4224,7 +4224,6 @@ void RasterizerGLES2::capture_viewport(Image* r_capture) { } w=DVector::Write(); - r_capture->create(viewport.width,viewport.height,0,Image::FORMAT_RGBA,pixels); //r_capture->flip_y(); diff --git a/drivers/mpc/audio_stream_mpc.cpp b/drivers/mpc/audio_stream_mpc.cpp index d94f57e6834..cd8125c9af9 100644 --- a/drivers/mpc/audio_stream_mpc.cpp +++ b/drivers/mpc/audio_stream_mpc.cpp @@ -8,6 +8,7 @@ Error AudioStreamMPC::_open_file() { f=NULL; } Error err; + //printf("mpc open file %ls\n", file.c_str()); f=FileAccess::open(file,FileAccess::READ,&err); if (err) { @@ -16,9 +17,10 @@ Error AudioStreamMPC::_open_file() { return err; } - f->seek_end(0); - streamlen=f->get_pos(); - f->seek(0); + //printf("file size is %i\n", f->get_len()); + //f->seek_end(0); + streamlen=f->get_len(); + //f->seek(0); if (streamlen<=0) { memdelete(f); f=NULL; diff --git a/drivers/theoraplayer/SCsub b/drivers/theoraplayer/SCsub index cd8cabcc948..419f2b65ae6 100644 --- a/drivers/theoraplayer/SCsub +++ b/drivers/theoraplayer/SCsub @@ -61,13 +61,17 @@ src/YUV/C/yuv420_rgb_c.c src/TheoraVideoFrame.cpp """) +env_theora = env.Clone() + if env["platform"] == "iphone": sources.append("src/AVFoundation/TheoraVideoClip_AVFoundation.mm") env.Append(LINKFLAGS=['-framework', 'CoreVideo', '-framework', 'CoreMedia', '-framework', 'AVFoundation']) + if env["target"] == "release": + env_theora.Append(CPPFLAGS=["-D_IOS", "-D__ARM_NEON__", "-fstrict-aliasing", "-fmessage-length=210", "-fdiagnostics-show-note-include-stack", "-fmacro-backtrace-limit=0", "-fcolor-diagnostics", "-Wno-trigraphs", "-fpascal-strings", "-fvisibility=hidden", "-fvisibility-inlines-hidden"]) -env_theora = env.Clone() - -env_theora.Append(CPPFLAGS=["-D_YUV_C", "-D_LIB", "-D__THEORA"]) +env_theora.Append(CPPFLAGS=["-D_LIB", "-D__THEORA"]) # removed -D_YUV_C +env_theora.Append(CPPFLAGS=["-D_YUV_LIBYUV", "-DLIBYUV_NEON"]) +#env_theora.Append(CPPFLAGS=["-D_YUV_C"]) if env["platform"] == "iphone": env_theora.Append(CPPFLAGS=["-D__AVFOUNDATION"]) diff --git a/drivers/theoraplayer/src/TheoraVideoClip.cpp b/drivers/theoraplayer/src/TheoraVideoClip.cpp index ed9f2c22dac..16897ee80eb 100644 --- a/drivers/theoraplayer/src/TheoraVideoClip.cpp +++ b/drivers/theoraplayer/src/TheoraVideoClip.cpp @@ -249,6 +249,7 @@ int TheoraVideoClip::discardOutdatedFrames(float absTime) if (nPop > 0) { +#define _DEBUG #ifdef _DEBUG std::string log = getName() + ": dropped frame "; diff --git a/drivers/theoraplayer/video_stream_theoraplayer.cpp b/drivers/theoraplayer/video_stream_theoraplayer.cpp index 62dee1336a7..9f4a44ae9d9 100644 --- a/drivers/theoraplayer/video_stream_theoraplayer.cpp +++ b/drivers/theoraplayer/video_stream_theoraplayer.cpp @@ -215,7 +215,7 @@ public: channels = p_channels; freq = p_freq; total_wrote = 0; - rb_power = 12; + rb_power = 22; rb.resize(rb_power); }; @@ -258,10 +258,12 @@ public: void update(float time_increase) { + float prev_time = mTime; //mTime = (float)(stream->get_total_wrote()) / freq; //mTime = MAX(0,mTime-AudioServer::get_singleton()->get_output_delay()); //mTime = (float)sample_count / channels / freq; mTime += time_increase; + if (mTime - prev_time > .02) printf("time increase %f secs\n", mTime - prev_time); //float duration=mClip->getDuration(); //if (mTime > duration) mTime=duration; //printf("time at timer is %f, %f, samples %i\n", mTime, time_increase, sample_count); @@ -386,7 +388,7 @@ void VideoStreamTheoraplayer::pop_frame(Ref p_tex) { { DVector::Write wr = data.write(); uint8_t* ptr = wr.ptr(); - copymem(ptr, f->getBuffer(), imgsize); + memcpy(ptr, f->getBuffer(), imgsize); } /* for (int i=0; inext == ringptr) && (ringptr->prev == ringptr); bool is_list = ( ringlist == ringptr ); - RingPtr *new_ringptr=(RingPtr*)::realloc(ringptr, p_bytes+sizeof(RingPtr)); ERR_FAIL_COND_V( new_ringptr == 0, NULL ); /// reallocation failed @@ -213,7 +211,7 @@ void MemoryPoolStaticMalloc::free(void *p_ptr) { ERR_FAIL_COND( !MemoryPoolStatic::get_singleton()); - #if DFAULT_ALIGNMENT == 1 + #if DEFAULT_ALIGNMENT == 1 _free(p_ptr); #else diff --git a/drivers/webp/dsp/dsp.h b/drivers/webp/dsp/dsp.h index 9ff53174d49..afe30413c64 100644 --- a/drivers/webp/dsp/dsp.h +++ b/drivers/webp/dsp/dsp.h @@ -33,7 +33,7 @@ extern "C" { #define WEBP_ANDROID_NEON // Android targets that might support NEON #endif -#if (defined(__ARM_NEON__) || defined(WEBP_ANDROID_NEON)) && !defined(PSP2_ENABLED) +#if ( (defined(__ARM_NEON__) && !defined(__aarch64__)) || defined(WEBP_ANDROID_NEON)) && !defined(PSP2_ENABLED) #define WEBP_USE_NEON #endif diff --git a/drivers/webp/utils/bit_reader.h b/drivers/webp/utils/bit_reader.h index d80b4971490..43cd948fd4f 100644 --- a/drivers/webp/utils/bit_reader.h +++ b/drivers/webp/utils/bit_reader.h @@ -1,3 +1,4 @@ +// // Copyright 2010 Google Inc. All Rights Reserved. // // This code is licensed under the same terms as WebM: diff --git a/modules/gdscript/gd_functions.cpp b/modules/gdscript/gd_functions.cpp index 0d11734bbd2..fcfbbb04da3 100644 --- a/modules/gdscript/gd_functions.cpp +++ b/modules/gdscript/gd_functions.cpp @@ -1166,6 +1166,8 @@ MethodInfo GDFunctions::get_info(Function p_func) { MethodInfo mi("weakref",PropertyInfo(Variant::OBJECT,"obj")); mi.return_val.type=Variant::OBJECT; + mi.return_val.name="WeakRef"; + return mi; } break; @@ -1173,6 +1175,7 @@ MethodInfo GDFunctions::get_info(Function p_func) { MethodInfo mi("funcref",PropertyInfo(Variant::OBJECT,"instance"),PropertyInfo(Variant::STRING,"funcname")); mi.return_val.type=Variant::OBJECT; + mi.return_val.name="FuncRef"; return mi; } break; @@ -1231,6 +1234,7 @@ MethodInfo GDFunctions::get_info(Function p_func) { MethodInfo mi("load",PropertyInfo(Variant::STRING,"path")); mi.return_val.type=Variant::OBJECT; + mi.return_val.name="Resource"; return mi; } break; case INST2DICT: { diff --git a/platform/iphone/detect.py b/platform/iphone/detect.py index 93345be7302..f8d86a3c7a6 100644 --- a/platform/iphone/detect.py +++ b/platform/iphone/detect.py @@ -54,20 +54,35 @@ def configure(env): env['AR'] = 'ar' import string - #env['CCFLAGS'] = string.split('-arch armv7 -Wall -fno-strict-aliasing -fno-common -D__IPHONE_OS_VERSION_MIN_REQUIRED=20000 -isysroot $IPHONESDK -fvisibility=hidden -mmacosx-version-min=10.5 -DCUSTOM_MATRIX_TRANSFORM_H=\\\"build/iphone/matrix4_iphone.h\\\" -DCUSTOM_VECTOR3_TRANSFORM_H=\\\"build/iphone/vector3_iphone.h\\\" -DNO_THUMB') - env['CCFLAGS'] = string.split('-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -Wno-trigraphs -fpascal-strings -Wmissing-prototypes -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk -gdwarf-2 -fvisibility=hidden -Wno-sign-conversion -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=4.3 -MMD -MT dependencies -isysroot $IPHONESDK') + if (env["bits"]=="64"): + #env['CCFLAGS'] = string.split('-arch arm64 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -Wno-trigraphs -fpascal-strings -O0 -Wno-missing-field-initializers -Wno-missing-prototypes -Wno-return-type -Wno-non-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wno-unused-variable -Wunused-value -Wno-empty-body -Wno-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wno-constant-conversion -Wno-int-conversion -Wno-bool-conversion -Wno-enum-conversion -Wshorten-64-to-32 -Wno-newline-eof -Wno-c++11-extensions -fstrict-aliasing -Wdeprecated-declarations -Winvalid-offsetof -g -Wno-sign-conversion -miphoneos-version-min=5.1.1 -Wmost -Wno-four-char-constants -Wno-unknown-pragmas -Wno-invalid-offsetof -ffast-math -m64 -DDEBUG -D_DEBUG -MMD -MT dependencies -isysroot $IPHONESDK') + env['CCFLAGS'] = string.split('-fno-objc-arc -arch arm64 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -Wno-trigraphs -fpascal-strings -Wmissing-prototypes -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -gdwarf-2 -fvisibility=hidden -Wno-sign-conversion -MMD -MT dependencies -miphoneos-version-min=5.1.1 -isysroot $IPHONESDK') + env.Append(CPPFLAGS=['-DNEED_LONG_INT']) + env.Append(CPPFLAGS=['-DLIBYUV_DISABLE_NEON']) + else: + env['CCFLAGS'] = string.split('-fno-objc-arc -arch armv7 -fmessage-length=0 -fno-strict-aliasing -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -Wno-trigraphs -fpascal-strings -Wmissing-prototypes -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk -gdwarf-2 -fvisibility=hidden -Wno-sign-conversion -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=4.3 -MMD -MT dependencies -isysroot $IPHONESDK') - -#/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/clang++ fno-objc-arc -arch armv7 -fmessage-length=0 -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -Wno-trigraphs -fpascal-strings -Wmissing-prototypes -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk -gdwarf-2 -fvisibility=hidden -Wno-sign-conversion -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=4.3 -MMD -MT dependencies -v -Os -ffast-math -DSTOREKIT_ENABLED -DIPHONE_ENABLED -DUNIX_ENABLED -DGLES2_ENABLED -DNO_THREADS -DMODULE_GRIDMAP_ENABLED -DMUSEPACK_ENABLED -DOLD_SCENE_FORMAT_ENABLED -DSQUIRREL_ENABLED -DVORBIS_ENABLED -DTHEORA_ENABLED -DPNG_ENABLED -DDDS_ENABLED -DPVR_ENABLED -DJPG_ENABLED -DSPEEX_ENABLED -DTOOLS_ENABLED -DGDSCRIPT_ENABLED -DMINIZIP_ENABLED -DXML_ENABLED -Icore -Icore/math -Itools -Idrivers -I. -Iplatform/iphone -Iplatform/iphone/include -Iplatform/iphone/scoreloop/SDKs -I/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/System/Library/Frameworks/OpenGLES.framework/Headers -Iscript/squirrel/src -Iscript/vorbis script/gdscript/gd_script.cpp -#/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/clang -x objective-c -arch armv7 -fmessage-length=0 -fdiagnostics-print-source-range-info -fdiagnostics-show-category=id -fdiagnostics-parseable-fixits -std=gnu99 -fobjc-arc -Wno-trigraphs -fpascal-strings -Os -Wmissing-prototypes -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk -gdwarf-2 -fvisibility=hidden -Wno-sign-conversion -mthumb "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=4.3 -iquote /Users/red/test2/build/test2.build/Release-iphoneos/test2.build/test2-generated-files.hmap -I/Users/red/test2/build/test2.build/Release-iphoneos/test2.build/test2-own-target-headers.hmap -I/Users/red/test2/build/test2.build/Release-iphoneos/test2.build/test2-all-target-headers.hmap -iquote /Users/red/test2/build/test2.build/Release-iphoneos/test2.build/test2-project-headers.hmap -I/Users/red/test2/build/Release-iphoneos/include -I/Users/red/test2/build/test2.build/Release-iphoneos/test2.build/DerivedSources/armv7 -I/Users/red/test2/build/test2.build/Release-iphoneos/test2.build/DerivedSources -F/Users/red/test2/build/Release-iphoneos -DNS_BLOCK_ASSERTIONS=1 -include /var/folders/LX/LXYXHTeSHSqbkhuPJRIsuE+++TI/-Caches-/com.apple.Xcode.501/SharedPrecompiledHeaders/test2-Prefix-dvdhnltoisfpmyalexovdrmfyeky/test2-Prefix.pch -MMD -MT dependencies -MF /Users/red/test2/build/test2.build/Release-iphoneos/test2.build/Objects-normal/armv7/main.d -c /Users/red/test2/test2/main.m -o /Users/red/test2/build/test2.build/Release-iphoneos/test2.build/Objects-normal/armv7/main.o - - - - - - env.Append(LINKFLAGS=['-arch', 'armv7', '-Wl,-dead_strip', '-miphoneos-version-min=4.3', + if (env["bits"]=="64"): + env.Append(LINKFLAGS=['-arch', 'arm64', '-Wl,-dead_strip', '-miphoneos-version-min=5.1.1', + '-isysroot', '$IPHONESDK', + #'-stdlib=libc++', + '-framework', 'Foundation', + '-framework', 'UIKit', + '-framework', 'CoreGraphics', + '-framework', 'OpenGLES', + '-framework', 'QuartzCore', + '-framework', 'CoreAudio', + '-framework', 'AudioToolbox', + '-framework', 'SystemConfiguration', + '-framework', 'Security', + #'-framework', 'AdSupport', + '-framework', 'MediaPlayer', + '-framework', 'AVFoundation', + '-framework', 'CoreMedia', + ]) + else: + env.Append(LINKFLAGS=['-arch', 'armv7', '-Wl,-dead_strip', '-miphoneos-version-min=4.3', '-isysroot', '$IPHONESDK', - #'-mmacosx-version-min=10.5', '-framework', 'Foundation', '-framework', 'UIKit', '-framework', 'CoreGraphics', @@ -128,4 +143,4 @@ def configure(env): env.Append( BUILDERS = { 'GLSL' : env.Builder(action = methods.build_glsl_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) env.Append( BUILDERS = { 'GLSL120GLES' : env.Builder(action = methods.build_gles2_headers, suffix = 'glsl.h',src_suffix = '.glsl') } ) -# /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x objective-c-header -arch armv7s -fmessage-length=0 -std=gnu99 -fobjc-arc -Wno-trigraphs -fpascal-strings -Os -Wno-missing-field-initializers -Wno-missing-prototypes -Wreturn-type -Wno-implicit-atomic-properties -Wno-receiver-is-weak -Wduplicate-method-match -Wformat -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wempty-body -Wuninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wno-shorten-64-to-32 -Wpointer-sign -Wno-newline-eof -Wno-selector -Wno-strict-selector-match -Wno-undeclared-selector -Wno-deprecated-implementations -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.0.sdk -Wprotocol -Wdeprecated-declarations -g -fvisibility=hidden -Wno-sign-conversion "-DIBOutlet=__attribute__((iboutlet))" "-DIBOutletCollection(ClassName)=__attribute__((iboutletcollection(ClassName)))" "-DIBAction=void)__attribute__((ibaction)" -miphoneos-version-min=4.3 -iquote /Users/lucasgondolo/test/build/test.build/Release-iphoneos/test.build/test-generated-files.hmap -I/Users/lucasgondolo/test/build/test.build/Release-iphoneos/test.build/test-own-target-headers.hmap -I/Users/lucasgondolo/test/build/test.build/Release-iphoneos/test.build/test-all-target-headers.hmap -iquote /Users/lucasgondolo/test/build/test.build/Release-iphoneos/test.build/test-project-headers.hmap -I/Users/lucasgondolo/test/build/Release-iphoneos/include -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -I/Users/lucasgondolo/test/build/test.build/Release-iphoneos/test.build/DerivedSources/armv7s -I/Users/lucasgondolo/test/build/test.build/Release-iphoneos/test.build/DerivedSources -F/Users/lucasgondolo/test/build/Release-iphoneos -DNS_BLOCK_ASSERTIONS=1 --serialize-diagnostics /var/folders/9r/_65jj9457bgb4n4nxcsm0xl80000gn/C/com.apple.Xcode.501/SharedPrecompiledHeaders/test-Prefix-esrzoamhgruxcxbhemvvlrjmmvoh/test-Prefix.pch.dia -c /Users/lucasgondolo/test/test/test-Prefix.pch -o /var/folders/9r/_65jj9457bgb4n4nxcsm0xl80000gn/C/com.apple.Xcode.501/SharedPrecompiledHeaders/test-Prefix-esrzoamhgruxcxbhemvvlrjmmvoh/test-Prefix.pch.pth -MMD -MT dependencies -MF /var/folders/9r/_65jj9457bgb4n4nxcsm0xl80000gn/C/com.apple.Xcode.501/SharedPrecompiledHeaders/test-Prefix-esrzoamhgruxcxbhemvvlrjmmvoh/test-Prefix.pch.d + diff --git a/platform/iphone/platform_config.h b/platform/iphone/platform_config.h index df50d30f408..7e961176d9d 100644 --- a/platform/iphone/platform_config.h +++ b/platform/iphone/platform_config.h @@ -30,3 +30,4 @@ #define GLES2_INCLUDE_H #define GLES1_INCLUDE_H +#define PLATFORM_REFCOUNT diff --git a/platform/iphone/platform_refcount.h b/platform/iphone/platform_refcount.h new file mode 100644 index 00000000000..45391e651ae --- /dev/null +++ b/platform/iphone/platform_refcount.h @@ -0,0 +1,18 @@ +#include "safe_refcount.h" + +#ifdef IPHONE_ENABLED + +#define REFCOUNT_T int +#define REFCOUNT_GET_T int const volatile& + +#include + +inline int atomic_conditional_increment(volatile int* v) { + return (*v==0)? 0 : OSAtomicIncrement32(v); +} + +inline int atomic_decrement(volatile int* v) { + return OSAtomicDecrement32(v); +} + +#endif diff --git a/platform/winrt/include/angle_windowsstore.h b/platform/winrt/include/angle_windowsstore.h new file mode 100644 index 00000000000..fe587bf2690 --- /dev/null +++ b/platform/winrt/include/angle_windowsstore.h @@ -0,0 +1,37 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// angle_windowsstore.h: + +#ifndef ANGLE_WINDOWSSTORE_H_ +#define ANGLE_WINDOWSSTORE_H_ + +// The following properties can be set on the CoreApplication to support additional +// ANGLE configuration options. +// +// The Visual Studio sample templates provided with this version of ANGLE have examples +// of how to set these property values. + +// +// Property: EGLNativeWindowTypeProperty +// Type: IInspectable +// Description: Set this property to specify the window type to use for creating a surface. +// If this property is missing, surface creation will fail. +// +const wchar_t EGLNativeWindowTypeProperty[] = L"EGLNativeWindowTypeProperty"; + +// +// Property: EGLRenderSurfaceSizeProperty +// Type: Size +// Description: Set this property to specify a preferred size in pixels of the render surface. +// The render surface size width and height must be greater than 0. +// If this property is set, then the render surface size is fixed. +// If this property is missing, a default behavior will be provided. +// The default behavior uses the window size if a CoreWindow is specified or +// the size of the SwapChainPanel control if one is specified. +// +const wchar_t EGLRenderSurfaceSizeProperty[] = L"EGLRenderSurfaceSizeProperty"; + +#endif // ANGLE_WINDOWSSTORE_H_ diff --git a/scene/3d/collision_object.cpp b/scene/3d/collision_object.cpp index 82158405ea7..9c388a28834 100644 --- a/scene/3d/collision_object.cpp +++ b/scene/3d/collision_object.cpp @@ -47,6 +47,11 @@ void CollisionObject::_notification(int p_what) { case NOTIFICATION_ENTER_WORLD: { + if (area) + PhysicsServer::get_singleton()->area_set_transform(rid,get_global_transform()); + else + PhysicsServer::get_singleton()->body_set_state(rid,PhysicsServer::BODY_STATE_TRANSFORM,get_global_transform()); + RID space = get_world()->get_space(); if (area) { PhysicsServer::get_singleton()->area_set_space(rid,space); diff --git a/scene/3d/ray_cast.cpp b/scene/3d/ray_cast.cpp index 6bc0c677c0d..639a86e7593 100644 --- a/scene/3d/ray_cast.cpp +++ b/scene/3d/ray_cast.cpp @@ -95,18 +95,6 @@ void RayCast::_notification(int p_what) { if (enabled && !get_tree()->is_editor_hint()) { set_fixed_process(true); - Node *p = get_parent(); - while( p && p->cast_to() ) { - - CollisionObject *co = p->cast_to(); - if (co) { - - exception=co->get_rid(); - exceptions.insert(exception); - } - - p=p->get_parent(); - } } else set_fixed_process(false); @@ -119,7 +107,6 @@ void RayCast::_notification(int p_what) { set_fixed_process(false); } - exceptions.erase(exception); } break; case NOTIFICATION_FIXED_PROCESS: { @@ -143,7 +130,7 @@ void RayCast::_notification(int p_what) { PhysicsDirectSpaceState::RayResult rr; - if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exceptions)) { + if (dss->intersect_ray(gt.get_origin(),gt.xform(to),rr,exclude)) { collided=true; against=rr.collider_id; @@ -160,6 +147,41 @@ void RayCast::_notification(int p_what) { } } +void RayCast::add_exception_rid(const RID& p_rid) { + + exclude.insert(p_rid); +} + +void RayCast::add_exception(const Object* p_object){ + + ERR_FAIL_NULL(p_object); + CollisionObject *co=((Object*)p_object)->cast_to(); + if (!co) + return; + add_exception_rid(co->get_rid()); +} + +void RayCast::remove_exception_rid(const RID& p_rid) { + + exclude.erase(p_rid); +} + +void RayCast::remove_exception(const Object* p_object){ + + ERR_FAIL_NULL(p_object); + CollisionObject *co=((Object*)p_object)->cast_to(); + if (!co) + return; + remove_exception_rid(co->get_rid()); +} + + +void RayCast::clear_exceptions(){ + + exclude.clear(); +} + + void RayCast::_bind_methods() { @@ -176,6 +198,14 @@ void RayCast::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_collision_point"),&RayCast::get_collision_point); ObjectTypeDB::bind_method(_MD("get_collision_normal"),&RayCast::get_collision_normal); + ObjectTypeDB::bind_method(_MD("add_exception_rid","rid"),&RayCast::add_exception_rid); + ObjectTypeDB::bind_method(_MD("add_exception","node"),&RayCast::add_exception); + + ObjectTypeDB::bind_method(_MD("remove_exception_rid","rid"),&RayCast::remove_exception_rid); + ObjectTypeDB::bind_method(_MD("remove_exception","node"),&RayCast::remove_exception); + + ObjectTypeDB::bind_method(_MD("clear_exceptions"),&RayCast::clear_exceptions); + ADD_PROPERTY(PropertyInfo(Variant::BOOL,"enabled"),_SCS("set_enabled"),_SCS("is_enabled")); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3,"cast_to"),_SCS("set_cast_to"),_SCS("get_cast_to")); } diff --git a/scene/3d/ray_cast.h b/scene/3d/ray_cast.h index 96606b1628a..0239c61b678 100644 --- a/scene/3d/ray_cast.h +++ b/scene/3d/ray_cast.h @@ -45,8 +45,7 @@ class RayCast : public Spatial { Vector3 cast_to; - RID exception; - Set exceptions; + Set exclude; protected: @@ -66,6 +65,12 @@ public: Vector3 get_collision_point() const; Vector3 get_collision_normal() const; + void add_exception_rid(const RID& p_rid); + void add_exception(const Object* p_object); + void remove_exception_rid(const RID& p_rid); + void remove_exception(const Object* p_object); + void clear_exceptions(); + RayCast(); }; diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp new file mode 100644 index 00000000000..957e63e3ce1 --- /dev/null +++ b/scene/gui/graph_edit.cpp @@ -0,0 +1,517 @@ +#include "graph_edit.h" + +bool GraphEditFilter::has_point(const Point2& p_point) const { + + return ge->_filter_input(p_point); +} + + +GraphEditFilter::GraphEditFilter(GraphEdit *p_edit) { + + ge=p_edit; +} + + +Error GraphEdit::connect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port) { + + if (is_node_connected(p_from,p_from_port,p_to,p_to_port)) + return OK; + Connection c; + c.from=p_from; + c.from_port=p_from_port; + c.to=p_to; + c.to_port=p_to_port; + connections.push_back(c); + top_layer->update(); + + return OK; +} + +bool GraphEdit::is_node_connected(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port) { + + for(List::Element *E=connections.front();E;E=E->next()) { + + if (E->get().from==p_from && E->get().from_port==p_from_port && E->get().to==p_to && E->get().to_port==p_to_port) + return true; + } + + return false; + +} + +void GraphEdit::disconnect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port){ + + + for(List::Element *E=connections.front();E;E=E->next()) { + + if (E->get().from==p_from && E->get().from_port==p_from_port && E->get().to==p_to && E->get().to_port==p_to_port) { + + connections.erase(E); + top_layer->update(); + return; + } + } +} + +void GraphEdit::get_connection_list(List *r_connections) { + + *r_connections=connections; +} + + +void GraphEdit::_scroll_moved(double) { + + + _update_scroll_offset(); + top_layer->update(); +} + +void GraphEdit::_update_scroll_offset() { + + for(int i=0;icast_to(); + if (!gn) + continue; + + Point2 pos=gn->get_offset(); + pos-=Point2(h_scroll->get_val(),v_scroll->get_val()); + gn->set_pos(pos); + } + +} + +void GraphEdit::_update_scroll() { + + if (updating) + return; + + updating=true; + Rect2 screen; + screen.size=get_size(); + for(int i=0;icast_to(); + if (!gn) + continue; + + Rect2 r; + r.pos=gn->get_offset(); + r.size=gn->get_size(); + screen = screen.merge(r); + } + + h_scroll->set_min(screen.pos.x); + h_scroll->set_max(screen.pos.x+screen.size.x); + h_scroll->set_page(get_size().x); + if (h_scroll->get_max() - h_scroll->get_min() <= h_scroll->get_page()) + h_scroll->hide(); + else + h_scroll->show(); + + v_scroll->set_min(screen.pos.y); + v_scroll->set_max(screen.pos.y+screen.size.y); + v_scroll->set_page(get_size().y); + + if (v_scroll->get_max() - v_scroll->get_min() <= v_scroll->get_page()) + v_scroll->hide(); + else + v_scroll->show(); + + _update_scroll_offset(); + updating=false; +} + + +void GraphEdit::_graph_node_raised(Node* p_gn) { + + GraphNode *gn=p_gn->cast_to(); + ERR_FAIL_COND(!gn); + gn->raise(); + top_layer->raise(); + +} + + +void GraphEdit::_graph_node_moved(Node *p_gn) { + + GraphNode *gn=p_gn->cast_to(); + ERR_FAIL_COND(!gn); + + //gn->set_pos(gn->get_offset()+scroll_offset); + + top_layer->update(); +} + +void GraphEdit::add_child_notify(Node *p_child) { + + top_layer->call_deferred("raise"); //top layer always on top! + GraphNode *gn = p_child->cast_to(); + if (gn) { + gn->connect("offset_changed",this,"_graph_node_moved",varray(gn)); + gn->connect("raise_request",this,"_graph_node_raised",varray(gn)); + _graph_node_moved(gn); + gn->set_stop_mouse(false); + } +} + +void GraphEdit::remove_child_notify(Node *p_child) { + + top_layer->call_deferred("raise"); //top layer always on top! + GraphNode *gn = p_child->cast_to(); + if (gn) { + gn->disconnect("offset_changed",this,"_graph_node_moved"); + gn->disconnect("raise_request",this,"_graph_node_raised"); + } +} + +void GraphEdit::_notification(int p_what) { + + if (p_what==NOTIFICATION_READY) { + Size2 size = top_layer->get_size(); + Size2 hmin = h_scroll->get_combined_minimum_size(); + Size2 vmin = v_scroll->get_combined_minimum_size(); + + v_scroll->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,vmin.width); + v_scroll->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,0); + v_scroll->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,0); + v_scroll->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,0); + + h_scroll->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,0); + h_scroll->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,0); + h_scroll->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,hmin.height); + h_scroll->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,0); + + } + if (p_what==NOTIFICATION_DRAW) { + VS::get_singleton()->canvas_item_set_clip(get_canvas_item(),true); + + } + + if (p_what==NOTIFICATION_RESIZED) { + _update_scroll(); + top_layer->update(); + } +} + +bool GraphEdit::_filter_input(const Point2& p_point) { + + Ref port =get_icon("port","GraphNode"); + + float grab_r=port->get_width()*0.5; + for(int i=get_child_count()-1;i>=0;i--) { + + GraphNode *gn=get_child(i)->cast_to(); + if (!gn) + continue; + + for(int j=0;jget_connection_output_count();j++) { + + Vector2 pos = gn->get_connection_output_pos(j)+gn->get_pos(); + if (pos.distance_to(p_point)get_connection_input_count();j++) { + + Vector2 pos = gn->get_connection_input_pos(j)+gn->get_pos(); + if (pos.distance_to(p_point) port =get_icon("port","GraphNode"); + Vector2 mpos(p_ev.mouse_button.x,p_ev.mouse_button.y); + float grab_r=port->get_width()*0.5; + for(int i=get_child_count()-1;i>=0;i--) { + + GraphNode *gn=get_child(i)->cast_to(); + if (!gn) + continue; + + for(int j=0;jget_connection_output_count();j++) { + + Vector2 pos = gn->get_connection_output_pos(j)+gn->get_pos(); + if (pos.distance_to(mpos)get_name(); + connecting_index=j; + connecting_out=true; + connecting_type=gn->get_connection_output_type(j); + connecting_color=gn->get_connection_output_color(j); + connecting_target=false; + connecting_to=pos; + return; + } + + + } + + for(int j=0;jget_connection_input_count();j++) { + + Vector2 pos = gn->get_connection_input_pos(j)+gn->get_pos(); + + if (pos.distance_to(mpos)get_name(); + connecting_index=j; + connecting_out=false; + connecting_type=gn->get_connection_input_type(j); + connecting_color=gn->get_connection_input_color(j); + connecting_target=false; + connecting_to=pos; + return; + } + + + } + } + } + + if (p_ev.type==InputEvent::MOUSE_MOTION && connecting) { + + connecting_to=Vector2(p_ev.mouse_motion.x,p_ev.mouse_motion.y); + connecting_target=false; + top_layer->update(); + + Ref port =get_icon("port","GraphNode"); + Vector2 mpos(p_ev.mouse_button.x,p_ev.mouse_button.y); + float grab_r=port->get_width()*0.5; + for(int i=get_child_count()-1;i>=0;i--) { + + GraphNode *gn=get_child(i)->cast_to(); + if (!gn) + continue; + + if (!connecting_out) { + for(int j=0;jget_connection_output_count();j++) { + + Vector2 pos = gn->get_connection_output_pos(j)+gn->get_pos(); + int type =gn->get_connection_output_type(j); + if (type==connecting_type && pos.distance_to(mpos)get_name(); + connecting_target_index=j; + return; + } + + + } + } else { + + for(int j=0;jget_connection_input_count();j++) { + + Vector2 pos = gn->get_connection_input_pos(j)+gn->get_pos(); + int type =gn->get_connection_input_type(j); + if (type==connecting_type && pos.distance_to(mpos)get_name(); + connecting_target_index=j; + return; + } + } + } + } + } + + if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index==BUTTON_LEFT && !p_ev.mouse_button.pressed) { + + if (connecting && connecting_target) { + + String from = connecting_from; + int from_slot = connecting_index; + String to =connecting_target_to; + int to_slot = connecting_target_index; + + if (!connecting_out) { + SWAP(from,to); + SWAP(from_slot,to_slot); + } + emit_signal("connection_request",from,from_slot,to,to_slot); + + } + connecting=false; + top_layer->update(); + + } + + + +} + +void GraphEdit::_draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color) { + + static const int steps = 20; + + Rect2 r; + r.pos=p_from; + r.expand_to(p_to); + Vector2 sign=Vector2((p_from.x < p_to.x) ? 1 : -1,(p_from.y < p_to.y) ? 1 : -1); + bool flip = sign.x * sign.y < 0; + + Vector2 prev; + for(int i=0;i<=steps;i++) { + + float d = i/float(steps); + float c=-Math::cos(d*Math_PI) * 0.5+0.5; + if (flip) + c=1.0-c; + Vector2 p = r.pos+Vector2(d*r.size.width,c*r.size.height); + + if (i>0) { + + top_layer->draw_line(prev,p,p_color,2); + } + + prev=p; + } +} + +void GraphEdit::_top_layer_draw() { + + _update_scroll(); + + if (connecting) { + + Node *fromn = get_node(connecting_from); + ERR_FAIL_COND(!fromn); + GraphNode *from = fromn->cast_to(); + ERR_FAIL_COND(!from); + Vector2 pos; + if (connecting_out) + pos=from->get_connection_output_pos(connecting_index); + else + pos=from->get_connection_input_pos(connecting_index); + pos+=from->get_pos(); + + Vector2 topos; + topos=connecting_to; + + Color col=connecting_color; + + if (connecting_target) { + col.r+=0.4; + col.g+=0.4; + col.b+=0.4; + } + _draw_cos_line(pos,topos,col); + } + + List::Element* > to_erase; + for(List::Element *E=connections.front();E;E=E->next()) { + + NodePath fromnp(E->get().from); + + Node * from = get_node(fromnp); + if (!from) { + to_erase.push_back(E); + continue; + } + + GraphNode *gfrom = from->cast_to(); + + if (!gfrom) { + to_erase.push_back(E); + continue; + } + + NodePath tonp(E->get().to); + Node * to = get_node(tonp); + if (!to) { + to_erase.push_back(E); + continue; + } + + GraphNode *gto = to->cast_to(); + + if (!gto) { + to_erase.push_back(E); + continue; + } + + Vector2 frompos=gfrom->get_connection_output_pos(E->get().from_port)+gfrom->get_pos(); + Color color = gfrom->get_connection_output_color(E->get().from_port); + Vector2 topos=gto->get_connection_input_pos(E->get().to_port)+gto->get_pos(); + _draw_cos_line(frompos,topos,color); + + } + + while(to_erase.size()) { + connections.erase(to_erase.front()->get()); + to_erase.pop_front(); + } + //draw connections +} + +void GraphEdit::_input_event(const InputEvent& p_ev) { + + if (p_ev.type==InputEvent::MOUSE_MOTION && p_ev.mouse_motion.button_mask&BUTTON_MASK_MIDDLE) { + h_scroll->set_val( h_scroll->get_val() - p_ev.mouse_motion.relative_x ); + v_scroll->set_val( v_scroll->get_val() - p_ev.mouse_motion.relative_y ); + } +} + +void GraphEdit::clear_connections() { + + connections.clear(); + update(); +} + + +void GraphEdit::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("connect_node:Error","from","from_port","to","to_port"),&GraphEdit::connect_node); + ObjectTypeDB::bind_method(_MD("is_node_connected","from","from_port","to","to_port"),&GraphEdit::is_node_connected); + ObjectTypeDB::bind_method(_MD("disconnect_node","from","from_port","to","to_port"),&GraphEdit::disconnect_node); + ObjectTypeDB::bind_method(_MD("_graph_node_moved"),&GraphEdit::_graph_node_moved); + ObjectTypeDB::bind_method(_MD("_graph_node_raised"),&GraphEdit::_graph_node_raised); + + ObjectTypeDB::bind_method(_MD("_top_layer_input"),&GraphEdit::_top_layer_input); + ObjectTypeDB::bind_method(_MD("_top_layer_draw"),&GraphEdit::_top_layer_draw); + ObjectTypeDB::bind_method(_MD("_scroll_moved"),&GraphEdit::_scroll_moved); + + ObjectTypeDB::bind_method(_MD("_input_event"),&GraphEdit::_input_event); + + ADD_SIGNAL(MethodInfo("connection_request",PropertyInfo(Variant::STRING,"from"),PropertyInfo(Variant::INT,"from_slot"),PropertyInfo(Variant::STRING,"to"),PropertyInfo(Variant::INT,"to_slot"))); + +} + +GraphEdit::GraphEdit() { + top_layer=NULL; + top_layer=memnew(GraphEditFilter(this)); + add_child(top_layer); + top_layer->set_stop_mouse(false); + top_layer->set_area_as_parent_rect(); + top_layer->connect("draw",this,"_top_layer_draw"); + top_layer->set_stop_mouse(false); + top_layer->connect("input_event",this,"_top_layer_input"); + + h_scroll = memnew(HScrollBar); + h_scroll->set_name("_h_scroll"); + top_layer->add_child(h_scroll); + + v_scroll = memnew(VScrollBar); + v_scroll->set_name("_v_scroll"); + top_layer->add_child(v_scroll); + updating=false; + connecting=false; + + h_scroll->connect("value_changed", this,"_scroll_moved"); + v_scroll->connect("value_changed", this,"_scroll_moved"); +} diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h new file mode 100644 index 00000000000..f8a2f3fee73 --- /dev/null +++ b/scene/gui/graph_edit.h @@ -0,0 +1,93 @@ +#ifndef GRAPH_EDIT_H +#define GRAPH_EDIT_H + +#include "scene/gui/graph_node.h" +#include "scene/gui/scroll_bar.h" + +class GraphEdit; + +class GraphEditFilter : public Control { + + OBJ_TYPE(GraphEditFilter,Control); + +friend class GraphEdit; + GraphEdit *ge; + virtual bool has_point(const Point2& p_point) const; + +public: + + + GraphEditFilter(GraphEdit *p_edit); +}; + +class GraphEdit : public Control { + + OBJ_TYPE(GraphEdit,Control); +public: + + struct Connection { + StringName from; + StringName to; + int from_port; + int to_port; + + }; +private: + + HScrollBar* h_scroll; + VScrollBar* v_scroll; + + + bool connecting; + String connecting_from; + bool connecting_out; + int connecting_index; + int connecting_type; + Color connecting_color; + bool connecting_target; + Vector2 connecting_to; + String connecting_target_to; + int connecting_target_index; + + + + bool updating; + List connections; + + void _draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color); + + void _graph_node_raised(Node* p_gn); + void _graph_node_moved(Node *p_gn); + + void _update_scroll(); + void _scroll_moved(double); + void _input_event(const InputEvent& p_ev); + + GraphEditFilter *top_layer; + void _top_layer_input(const InputEvent& p_ev); + void _top_layer_draw(); + void _update_scroll_offset(); + +friend class GraphEditFilter; + bool _filter_input(const Point2& p_point); +protected: + + static void _bind_methods(); + virtual void add_child_notify(Node *p_child); + virtual void remove_child_notify(Node *p_child); + void _notification(int p_what); + +public: + + Error connect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port); + bool is_node_connected(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port); + void disconnect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port); + void clear_connections(); + + void get_connection_list(List *r_connections); + + + GraphEdit(); +}; + +#endif // GRAPHEdit_H diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 6e3afeefd01..50ee9abcf82 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -76,7 +76,7 @@ void GraphNode::_get_property_list( List *p_list) const{ int idx=0; for(int i=0;icast_to(); - if (!c || c->is_set_as_toplevel() || !c->get_owner()) + if (!c || c->is_set_as_toplevel() ) continue; String base="slot/"+itos(idx)+"/"; @@ -122,6 +122,7 @@ void GraphNode::_resort() { } + int vofs=0; int w = get_size().x - sb->get_minimum_size().x; @@ -131,7 +132,7 @@ void GraphNode::_resort() { Control *c=get_child(i)->cast_to(); if (!c) continue; - if (c->is_set_as_toplevel() || !c->get_owner()) + if (c->is_set_as_toplevel()) continue; Size2i size=c->get_combined_minimum_size(); @@ -150,6 +151,8 @@ void GraphNode::_resort() { _change_notify(); update(); + connpos_dirty=true; + } @@ -160,14 +163,34 @@ void GraphNode::_notification(int p_what) { Ref sb=get_stylebox("frame"); Ref port =get_icon("port"); + Ref close =get_icon("close"); + int close_offset = get_constant("close_offset"); + Ref title_font = get_font("title_font"); + int title_offset = get_constant("title_offset"); + Color title_color = get_color("title_color"); Point2i icofs = -port->get_size()*0.5; - int edgeofs=3; + int edgeofs=get_constant("port_offset"); icofs.y+=sb->get_margin(MARGIN_TOP); draw_style_box(sb,Rect2(Point2(),get_size())); + int w = get_size().width-sb->get_minimum_size().x; + + if (show_close) + w-=close->get_width(); + + draw_string(title_font,Point2(sb->get_margin(MARGIN_LEFT),-title_font->get_height()+title_font->get_ascent()+title_offset),title,title_color,w); + if (show_close) { + Vector2 cpos = Point2(w+sb->get_margin(MARGIN_LEFT),-close->get_height()+close_offset); + draw_texture(close,cpos); + close_rect.pos=cpos; + close_rect.size=close->get_size(); + } else { + close_rect=Rect2(); + } + for (Map::Element *E=slot_info.front();E;E=E->next()) { - if (E->key()>cache_y.size()) + if (E->key() < 0 || E->key()>=cache_y.size()) continue; if (!slot_info.has(E->key())) continue; @@ -180,6 +203,7 @@ void GraphNode::_notification(int p_what) { } } + if (p_what==NOTIFICATION_SORT_CHILDREN) { _resort(); @@ -187,16 +211,6 @@ void GraphNode::_notification(int p_what) { } -void GraphNode::set_title(const String& p_title) { - - title=p_title; - update(); -} - -String GraphNode::get_title() const { - - return title; -} void GraphNode::set_slot(int p_idx,bool p_enable_left,int p_type_left,const Color& p_color_left, bool p_enable_right,int p_type_right,const Color& p_color_right) { @@ -216,17 +230,23 @@ void GraphNode::set_slot(int p_idx,bool p_enable_left,int p_type_left,const Colo s.color_right=p_color_right; slot_info[p_idx]=s; update(); + connpos_dirty=true; + } void GraphNode::clear_slot(int p_idx){ slot_info.erase(p_idx); update(); + connpos_dirty=true; + } void GraphNode::clear_all_slots(){ slot_info.clear(); update(); + connpos_dirty=true; + } bool GraphNode::is_slot_enabled_left(int p_idx) const{ @@ -280,18 +300,26 @@ Color GraphNode::get_slot_color_right(int p_idx) const{ Size2 GraphNode::get_minimum_size() const { + Ref title_font = get_font("title_font"); + int sep=get_constant("separation"); Ref sb=get_stylebox("frame"); bool first=true; Size2 minsize; + minsize.x=title_font->get_string_size(title).x; + if (show_close) { + Ref close =get_icon("close"); + minsize.x+=sep+close->get_width(); + } + for(int i=0;icast_to(); if (!c) continue; - if (c->is_set_as_toplevel() || !c->get_owner()) + if (c->is_set_as_toplevel()) continue; Size2i size=c->get_combined_minimum_size(); @@ -308,13 +336,225 @@ Size2 GraphNode::get_minimum_size() const { return minsize+sb->get_minimum_size(); } +void GraphNode::set_title(const String& p_title) { + + title=p_title; + minimum_size_changed(); + update(); + +} + +String GraphNode::get_title() const{ + + return title; +} + +void GraphNode::set_offset(const Vector2& p_offset) { + + offset=p_offset; + emit_signal("offset_changed"); + update(); +} + +Vector2 GraphNode::get_offset() const { + + return offset; +} + + + +void GraphNode::set_show_close_button(bool p_enable){ + + show_close=p_enable; + update(); +} +bool GraphNode::is_close_button_visible() const{ + + return show_close; +} + +void GraphNode::_connpos_update() { + + + int edgeofs=get_constant("port_offset"); + int sep=get_constant("separation"); + + Ref sb=get_stylebox("frame"); + Ref port =get_icon("port"); + conn_input_cache.clear(); + conn_output_cache.clear(); + int vofs=0; + + int idx=0; + + for(int i=0;icast_to(); + if (!c) + continue; + if (c->is_set_as_toplevel()) + continue; + + Size2i size=c->get_combined_minimum_size(); + + int y = sb->get_margin(MARGIN_TOP)+vofs; + int h = size.y; + + + if (slot_info.has(idx)) { + + if (slot_info[idx].enable_left) { + ConnCache cc; + cc.pos=Point2i(edgeofs,y+h/2); + cc.type=slot_info[idx].type_left; + cc.color=slot_info[idx].color_left; + conn_input_cache.push_back(cc); + } + if (slot_info[idx].enable_right) { + ConnCache cc; + cc.pos=Point2i(get_size().width-edgeofs,y+h/2); + cc.type=slot_info[idx].type_right; + cc.color=slot_info[idx].color_right; + conn_output_cache.push_back(cc); + } + } + + if (vofs>0) + vofs+=sep; + vofs+=size.y; + idx++; + + } + + + connpos_dirty=false; +} + +int GraphNode::get_connection_input_count() { + + if (connpos_dirty) + _connpos_update(); + + return conn_input_cache.size(); + +} +int GraphNode::get_connection_output_count() { + + if (connpos_dirty) + _connpos_update(); + + return conn_output_cache.size(); + +} + + +Vector2 GraphNode::get_connection_input_pos(int p_idx) { + + if (connpos_dirty) + _connpos_update(); + + ERR_FAIL_INDEX_V(p_idx,conn_input_cache.size(),Vector2()); + return conn_input_cache[p_idx].pos; +} + +int GraphNode::get_connection_input_type(int p_idx) { + + if (connpos_dirty) + _connpos_update(); + + ERR_FAIL_INDEX_V(p_idx,conn_input_cache.size(),0); + return conn_input_cache[p_idx].type; +} + +Color GraphNode::get_connection_input_color(int p_idx) { + + if (connpos_dirty) + _connpos_update(); + + ERR_FAIL_INDEX_V(p_idx,conn_input_cache.size(),Color()); + return conn_input_cache[p_idx].color; +} + +Vector2 GraphNode::get_connection_output_pos(int p_idx){ + + if (connpos_dirty) + _connpos_update(); + + ERR_FAIL_INDEX_V(p_idx,conn_output_cache.size(),Vector2()); + return conn_output_cache[p_idx].pos; + +} + +int GraphNode::get_connection_output_type(int p_idx) { + + if (connpos_dirty) + _connpos_update(); + + ERR_FAIL_INDEX_V(p_idx,conn_output_cache.size(),0); + return conn_output_cache[p_idx].type; +} + +Color GraphNode::get_connection_output_color(int p_idx) { + + if (connpos_dirty) + _connpos_update(); + + ERR_FAIL_INDEX_V(p_idx,conn_output_cache.size(),Color()); + return conn_output_cache[p_idx].color; +} + +void GraphNode::_input_event(const InputEvent& p_ev) { + + if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) { + + Vector2 mpos = Vector2(p_ev.mouse_button.x,p_ev.mouse_button.y); + if (close_rect.size!=Size2() && close_rect.has_point(mpos)) { + emit_signal("close_request"); + return; + } + + drag_from=get_offset(); + drag_accum=Vector2(); + dragging=true; + emit_signal("raise_request"); + + } + + if (p_ev.type==InputEvent::MOUSE_BUTTON && !p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) { + + dragging=false; + emit_signal("dragged",drag_from,get_offset()); //useful for undo/redo + } + + if (p_ev.type==InputEvent::MOUSE_MOTION && dragging) { + + drag_accum+=Vector2(p_ev.mouse_motion.relative_x,p_ev.mouse_motion.relative_y); + set_offset(drag_from+drag_accum); + } + +} + void GraphNode::_bind_methods() { + ObjectTypeDB::bind_method(_MD("set_title","title"),&GraphNode::set_title); + ObjectTypeDB::bind_method(_MD("get_title"),&GraphNode::get_title); + ObjectTypeDB::bind_method(_MD("_input_event"),&GraphNode::_input_event); + ObjectTypeDB::bind_method(_MD("set_show_close_button","show"),&GraphNode::set_show_close_button); + ObjectTypeDB::bind_method(_MD("is_close_button_visible"),&GraphNode::is_close_button_visible); + + ADD_PROPERTY( PropertyInfo(Variant::STRING,"title"),_SCS("set_title"),_SCS("get_title")); + ADD_PROPERTY( PropertyInfo(Variant::BOOL,"show_close"),_SCS("set_show_close_button"),_SCS("is_close_button_visible")); + + ADD_SIGNAL(MethodInfo("offset_changed")); + ADD_SIGNAL(MethodInfo("dragged",PropertyInfo(Variant::VECTOR2,"from"),PropertyInfo(Variant::VECTOR2,"to"))); + ADD_SIGNAL(MethodInfo("raise_request")); + ADD_SIGNAL(MethodInfo("close_request")); } GraphNode::GraphNode() { - + dragging=false; + show_close=false; + connpos_dirty=true; } diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h index 3b89da9f0f2..0d5cbf8dd33 100644 --- a/scene/gui/graph_node.h +++ b/scene/gui/graph_node.h @@ -8,7 +8,7 @@ class GraphNode : public Container { OBJ_TYPE(GraphNode,Container); - String title; + struct Slot { bool enable_left; int type_left; @@ -21,13 +21,36 @@ class GraphNode : public Container { Slot() { enable_left=false; type_left=0; color_left=Color(1,1,1,1); enable_right=false; type_right=0; color_right=Color(1,1,1,1); }; }; + String title; + bool show_close; + Vector2 offset; + + Rect2 close_rect; + Vector cache_y; + struct ConnCache { + Vector2 pos; + int type; + Color color; + }; + + Vector conn_input_cache; + Vector conn_output_cache; + Map slot_info; + bool connpos_dirty; + + void _connpos_update(); void _resort(); + + Vector2 drag_from; + Vector2 drag_accum; + bool dragging; protected: + void _input_event(const InputEvent& p_ev); void _notification(int p_what); static void _bind_methods(); @@ -39,8 +62,6 @@ public: - void set_title(const String& p_title); - String get_title() const; void set_slot(int p_idx,bool p_enable_left,int p_type_left,const Color& p_color_left, bool p_enable_right,int p_type_right,const Color& p_color_right); void clear_slot(int p_idx); @@ -52,6 +73,25 @@ public: int get_slot_type_right(int p_idx) const; Color get_slot_color_right(int p_idx) const; + void set_title(const String& p_title); + String get_title() const; + + void set_offset(const Vector2& p_offset); + Vector2 get_offset() const; + + void set_show_close_button(bool p_enable); + bool is_close_button_visible() const; + + int get_connection_input_count() ; + int get_connection_output_count() ; + Vector2 get_connection_input_pos(int p_idx); + int get_connection_input_type(int p_idx); + Color get_connection_input_color(int p_idx); + Vector2 get_connection_output_pos(int p_idx); + int get_connection_output_type(int p_idx); + Color get_connection_output_color(int p_idx); + + virtual Size2 get_minimum_size() const; GraphNode(); diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 7353744d077..d10ca20fc3f 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -84,6 +84,7 @@ void MenuButton::pressed() { popup->set_parent_rect( Rect2(Point2(gp-popup->get_global_pos()),get_size())); popup->popup(); popup->call_deferred("grab_click_focus"); + popup->set_invalidate_click_until_motion(); } diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 0ba3bdb7c65..1fd1d8adc8c 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -30,6 +30,7 @@ #include "print_string.h" #include "os/keyboard.h" #include "translation.h" +#include "os/input.h" String PopupMenu::_get_accel_text(uint32_t p_accel) const { @@ -318,6 +319,10 @@ void PopupMenu::_input_event(const InputEvent &p_event) { int over=_get_mouse_over(Point2(b.x,b.y)); + if (invalidated_click) { + invalidated_click=false; + break; + } if (over<0 || items[over].separator || items[over].disabled) break; //non-activable @@ -336,6 +341,13 @@ void PopupMenu::_input_event(const InputEvent &p_event) { case InputEvent::MOUSE_MOTION: { + if (invalidated_click) { + moved+=Vector2(p_event.mouse_motion.relative_x,p_event.mouse_motion.relative_y); + if (moved.length()>4) + invalidated_click=false; + + } + const InputEventMouseMotion &m=p_event.mouse_motion; for(List::Element *E=autohide_areas.front();E;E=E->next()) { @@ -893,12 +905,17 @@ void PopupMenu::_bind_methods() { } + +void PopupMenu::set_invalidate_click_until_motion() { + moved=Vector2(); + invalidated_click=true; +} + PopupMenu::PopupMenu() { idcount=0; mouse_over=-1; - set_focus_mode(FOCUS_ALL); set_as_toplevel(true); diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index b150be10086..c2e988de954 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -70,6 +70,8 @@ class PopupMenu : public Popup { void _activate_submenu(int over); void _submenu_timeout(); + bool invalidated_click; + Vector2 moved; Array _get_items() const; void _set_items(const Array& p_items); @@ -134,6 +136,8 @@ public: void add_autohide_area(const Rect2& p_area); void clear_autohide_areas(); + void set_invalidate_click_until_motion(); + PopupMenu(); ~PopupMenu(); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 962e8c26e0d..ee6b481a9fb 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -76,6 +76,7 @@ #include "scene/gui/video_player.h" #include "scene/gui/reference_frame.h" #include "scene/gui/graph_node.h" +#include "scene/gui/graph_edit.h" #include "scene/resources/video_stream.h" #include "scene/2d/particles_2d.h" #include "scene/2d/path_2d.h" @@ -153,6 +154,8 @@ #include "scene/resources/mesh.h" #include "scene/resources/room.h" +#include "scene/resources/shader_graph.h" + #include "scene/resources/world.h" #include "scene/resources/world_2d.h" #include "scene/resources/volume.h" @@ -305,6 +308,7 @@ void register_scene_types() { ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); OS::get_singleton()->yield(); //may take time to init @@ -496,11 +500,17 @@ void register_scene_types() { ObjectTypeDB::register_type(); ObjectTypeDB::register_virtual_type(); ObjectTypeDB::register_type(); - ObjectTypeDB::register_type(); - ObjectTypeDB::register_type(); + //ObjectTypeDB::register_type(); + //ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); - ObjectTypeDB::register_type(); + ObjectTypeDB::register_virtual_type(); + ObjectTypeDB::register_virtual_type(); + ObjectTypeDB::register_type(); + ObjectTypeDB::register_type(); + ObjectTypeDB::add_compatibility_type("Shader","MaterialShader"); + ObjectTypeDB::add_compatibility_type("ParticleSystemMaterial","FixedMaterial"); + ObjectTypeDB::add_compatibility_type("UnshadedMaterial","FixedMaterial"); ObjectTypeDB::register_type(); ObjectTypeDB::register_type(); diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 050e4629026..e7f0d9b1f56 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -417,12 +417,18 @@ void make_default_theme() { t->set_constant("hseparation","PopupMenu",2); t->set_constant("vseparation","PopupMenu",1); - Ref graphsb = make_stylebox(graph_node_png,6,21,6,5,16,21,16,5); + Ref 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) ); diff --git a/scene/resources/default_theme/graph_node_close.png b/scene/resources/default_theme/graph_node_close.png new file mode 100644 index 0000000000000000000000000000000000000000..ea5b510418eb2c7199f3b4ac4d9dcb0a26e477eb GIT binary patch literal 243 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$1|-8uW1a&kwj^(N7l!{JxM1({$v_d#0*}aI z1_o|n5N2eUHAey{$X?><>&kwQM^r@A($wR}W1vujr;B5V#`&ceH*y_v5NLVm|I}dZ z+^q?(nLG4ze{Ioh-n(_{+zip#wmVq_`PjGJ{F}aW=hC3nD}=XIJg`hQvq)%{HrbJI zL~>YkoTF!S5;rG3@B5Yb()qQwh$D97!1 j^zUgw^_q*}?6u5+{hHY}o*Ionw=j6R`njxgN@xNALKInm literal 0 HcmV?d00001 diff --git a/scene/resources/default_theme/theme_data.h b/scene/resources/default_theme/theme_data.h index 9fe77b32236..a0f3dcd9883 100644 --- a/scene/resources/default_theme/theme_data.h +++ b/scene/resources/default_theme/theme_data.h @@ -104,6 +104,11 @@ static const unsigned char graph_node_png[]={ }; +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 }; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index e3427cbe2ce..faba339fe1d 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -501,7 +501,7 @@ bool ShaderMaterial::_get(const StringName& p_name,Variant &r_ret) const { void ShaderMaterial::_get_property_list( List *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()) { diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index cc6bed3148c..e47b2432f24 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 { @@ -176,7 +170,6 @@ void Shader::get_default_texture_param_list(List* r_textures) const{ 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)); @@ -203,9 +196,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; } @@ -237,7 +230,7 @@ RES ResourceFormatLoaderShader::load(const String &p_path,const String& p_origin String base_path = p_path.get_base_dir(); - Ref shader( memnew( Shader ) ); + Ref shader;//( memnew( Shader ) ); int line=0; diff --git a/scene/resources/shader.h b/scene/resources/shader.h index e1b8288c51b..8c15ca43d48 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -50,6 +50,8 @@ class Shader : public Resource { mutable Map params_cache; //map a shader param to a material param.. Map > default_textures; + + protected: @@ -59,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); @@ -79,13 +82,22 @@ public: 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 3ed6cebf074..a06a70be9f7 100644 --- a/scene/resources/shader_graph.cpp +++ b/scene/resources/shader_graph.cpp @@ -30,118 +30,249 @@ -# if 0 -void ShaderGraph::_set(const String& p_name, const Variant& p_value) { - - if (p_name.begins_with("nodes/")) { - int idx=p_name.get_slice("/",1).to_int(); - Dictionary data=p_value; - - ERR_FAIL_COND(!data.has("type")); - String type=data["type"]; - - VS::NodeType node_type=VS::NODE_TYPE_MAX; - for(int i=0;i 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; - } - - return Variant(); -} -void ShaderGraph::_get_property_list( List *p_list) const { +Array ShaderGraph::_get_node_list(ShaderType p_type) const { List nodes; - get_node_list(&nodes); - - for(List::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 connections; - get_connections(&connections); - int idx=0; - for(List::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 ) ); - } - + get_node_list(p_type,&nodes); + Array arr(true); + for (List::Element *E=nodes.front();E;E=E->next()) + arr.push_back(E->get()); + return arr; } +Array ShaderGraph::_get_connections(ShaderType p_type) const { -#endif -#if 0 -Array ShaderGraph::_get_connections_helper() const { - - Array connections_ret; List connections; - get_connections(&connections); - connections_ret.resize(connections.size()); + get_node_connections(p_type,&connections); + Array arr(true); + for (List::Element *E=connections.front();E;E=E->next()) { - int idx=0; - for(List::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); - 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); } - - return connections_ret; + return arr; } void ShaderGraph::_bind_methods() { + ObjectTypeDB::bind_method(_MD("_update_shader"),&ShaderGraph::_update_shader); + + 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); + + 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 *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","c"),&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("rgb_op_node_get_c","shader_type","id"),&ShaderGraph::rgb_op_node_get_c); + + 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); + + //void get_connections(ShaderType p_which,List *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 ); + + +#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 +343,154 @@ 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(ShaderType p_which, 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 (Map::Element *E=shader[p_which].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; - node.id=p_id; - node.x=0; - node.y=0; - - node_map[p_id]=node; - -} - -void ShaderGraph::node_set_pos(int p_id, const Vector2& p_pos) { - - 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 { - - ERR_FAIL_COND_V(!node_map.has(p_id),Vector2()); - return Vector2(node_map[p_id].x,node_map[p_id].y); -} - - -void ShaderGraph::node_remove(int p_id) { - - ERR_FAIL_COND(!node_map.has(p_id)); - - //erase connections associated with node - List::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) { - - connections.erase(E); + if (p_node_type==NODE_INPUT) { + //see if it already exists + for(Map::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); + } } - E=N; + } + node.type=p_node_type; + node.id=p_id; + + 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(p_type,"Scalar"); node.param2=0;} break; // scalar uniform (assignable in material) + case NODE_VEC_INPUT: {node.param1=_find_unique_name(p_type,"Vec3");node.param2=Vector3();} break; // vec3 uniform (assignable in material) + case NODE_RGB_INPUT: {node.param1=_find_unique_name(p_type,"Color");node.param2=Color();} break; // color uniform (assignable in material) + case NODE_XFORM_INPUT: {node.param1=_find_unique_name(p_type,"XForm"); node.param2=Transform();} break; // mat4 uniform (assignable in material) + case NODE_TEXTURE_INPUT: {node.param1=_find_unique_name(p_type,"Tex"); } break; // texture input (assignable in material) + case NODE_CUBEMAP_INPUT: {node.param1=_find_unique_name(p_type,"Cube"); } break; // cubemap input (assignable in material) + case NODE_OUTPUT: {} break; // output (shader type dependent) + case NODE_COMMENT: {} break; // comment + case NODE_TYPE_MAX: {}; } - node_map.erase(p_id); + shader[p_type].node_map[p_id]=node; + _request_update(); } -void ShaderGraph::node_change_type(int p_id, NodeType p_type) { +void ShaderGraph::node_set_pos(ShaderType p_type,int p_id, const Vector2& p_pos) { + ERR_FAIL_INDEX(p_type,3); - ERR_FAIL_COND(!node_map.has(p_id)); - node_map[p_id].type=p_type; - node_map[p_id].param=Variant(); + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + shader[p_type].node_map[p_id].pos=p_pos; + _request_update(); + +} +Vector2 ShaderGraph::node_get_pos(ShaderType p_type,int p_id) const { + ERR_FAIL_INDEX_V(p_type,3,Vector2()); + + 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(ShaderType p_type,int p_id) { + + ERR_FAIL_COND(p_id==0); + ERR_FAIL_INDEX(p_type,3); + + ERR_FAIL_COND(!shader[p_type].node_map.has(p_id)); + + //erase connections associated with node + for(Map::Element *E=shader[p_type].node_map.front();E;E=E->next()) { + if (E->key()==p_id) + continue; //no self + + for (Map::Element *F=E->get().connections.front();F;) { + Map::Element *N=F->next(); + + if (F->get().id==p_id) { + E->get().connections.erase(F); + } + + F=N; + } + } + + shader[p_type].node_map.erase(p_id); + print_line("erased node, amount left: "+itos(shader[p_type].node_map.size())); + _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 *p_node_list) const { +void ShaderGraph::get_node_list(ShaderType p_type,List *p_node_list) const { - Map::Element *E = node_map.front(); + ERR_FAIL_INDEX(p_type,3); + + Map::Element *E = shader[p_type].node_map.front(); while(E) { @@ -288,183 +500,593 @@ void ShaderGraph::get_node_list(List *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::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); - - E=E->next(); - } - - 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; - - connections.push_back(c); + 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(); return OK; } -bool ShaderGraph::is_connected(int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) const { +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 { - const List::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; + ERR_FAIL_INDEX_V(p_type,3,false); - E=E->next(); - } - - return false; + 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; } -void ShaderGraph::disconnect(int p_src_id,int p_src_slot, int p_dst_id,int p_dst_slot) { +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); - List::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) { + print_line("** dsisconnect"); + 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); - connections.erase(E); + } + _request_update(); + +} + +void ShaderGraph::get_node_connections(ShaderType p_type,List *p_connections) const { + + ERR_FAIL_INDEX(p_type,3); + + for(const Map::Element *E=shader[p_type].node_map.front();E;E=E->next()) { + for (const Map::Element *F=E->get().connections.front();F;F=F->next()) { + + 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::get_connections(List *p_connections) const { - - const List::Element*E=connections.front(); - while(E) { - p_connections->push_back(E->get()); - E=E->next(); - } - - -} - - -void ShaderGraph::clear() { - - connections.clear(); - node_map.clear(); -} - - -#if 0 -void ShaderGraph::node_add(NodeType p_type,int p_id) { - - ShaderNode sn; - sn.type=p_type; - nodes[p_id]=sn; - version++; -} -void ShaderGraph::node_remove(int p_id) { - - nodes.erase(p_id); - -} -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::get_node_list(List *p_node_list) const { - - 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); -} -Variant ShaderGraph::node_get_param(int p_id) const { - - 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) { - - VisualServer::get_singleton()->shader_connect(shader,p_src_id,p_src_slot,p_dst_id,p_dst_slot); - version++; -} -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::get_connections(List *p_connections) const { - - List connections; - VisualServer::get_singleton()->shader_get_connections(shader,&connections); - for( List::Element *E=connections.front();E;E=E->next()) { - - 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); } } -void ShaderGraph::node_set_pos(int p_id,const Point2& p_pos) { -#ifdef TOOLS_ENABLED - ERR_FAIL_COND(!positions.has(p_id)); - positions[p_id]=p_pos; -#endif +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(); + } -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::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(); + } -void ShaderGraph::clear() { +float ShaderGraph::scalar_const_node_get_value(ShaderType p_type,int p_id) const{ - VisualServer::get_singleton()->shader_clear(shader); - version++; + 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; } -#endif -ShaderGraph::ShaderGraph() { +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(); + + +} +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; + +} + +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(); + +} +Color ShaderGraph::rgb_const_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_CONST,Color()); + return n.param1; + +} + +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{ + + 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; + +} + +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(); + +} +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]; + +} + +void ShaderGraph::texture_node_set_filter_strength(ShaderType p_type,float p_id,float p_strength){ + + 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::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{ + + 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); + +} + + +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(); + +} +ShaderGraph::VecOp ShaderGraph::vec_op_node_get_op(ShaderType p_type,float p_id) const{ + + 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); + +} + + +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{ + + 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); + +} + +void ShaderGraph::rgb_op_node_set_op(ShaderType p_type,float p_id,RGBOp p_op,float p_c){ + + 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; + n.param2=p_c; + _request_update(); + +} +ShaderGraph::RGBOp ShaderGraph::rgb_op_node_get_op(ShaderType p_type,float p_id) const{ + + 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); + +} +float ShaderGraph::rgb_op_node_get_c(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_RGB_OP,0); + return n.param2; + +} + +void ShaderGraph::xform_vec_mult_node_set_no_translation(ShaderType p_type,int p_id,bool p_no_translation){ + + 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(); + +} +bool ShaderGraph::xform_vec_mult_node_get_no_translation(ShaderType p_type,int p_id) const{ + + 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; + +} + +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); + n.param1=p_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::vec_func_node_set_function(ShaderType p_type,int p_id,VecFunc 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_VEC_FUNC); + n.param1=p_func; + + _request_update(); + +} +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); +} + +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_type,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& 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 ShaderGraph::texture_input_node_get_value(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,Ref()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Ref()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_TEXTURE_INPUT,Ref()); + return n.param2; +} + +void ShaderGraph::cubemap_input_node_set_value(ShaderType p_type,int p_id,const Ref& 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 ShaderGraph::cubemap_input_node_get_value(ShaderType p_type,int p_id) const{ + + ERR_FAIL_INDEX_V(p_type,3,Ref()); + ERR_FAIL_COND_V(!shader[p_type].node_map.has(p_id),Ref()); + const Node& n = shader[p_type].node_map[p_id]; + ERR_FAIL_COND_V(n.type!=NODE_CUBEMAP_INPUT,Ref()); + 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(); - version = 1; + _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() { @@ -472,556 +1094,681 @@ ShaderGraph::~ShaderGraph() { //VisualServer::get_singleton()->free(shader); } -#if 0 -void ShaderGraph::shader_get_default_input_nodes(Mode p_type,List *p_inputs) { - switch(p_type) { +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,"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}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"Time","TIME",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",SLOT_TYPE_VEC,SLOT_OUT}, + {MODE_MATERIAL,SHADER_TYPE_VERTEX,"UV2","UV2",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",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","UV",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,"Time","TIME",SLOT_TYPE_SCALAR,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",SLOT_TYPE_SCALAR,SLOT_OUT}, + //end + {MODE_MATERIAL,SHADER_TYPE_FRAGMENT,NULL,NULL,SLOT_TYPE_SCALAR,SLOT_OUT}, - case SHADER_VERTEX: { +}; - 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: { +void ShaderGraph::get_input_output_node_slot_info(Mode p_mode, ShaderType p_type, List *r_slots) { - 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") ); - - } break; - case SHADER_POST_PROCESS: { - p_inputs->push_back( PropertyInfo( Variant::VECTOR3,"color") ); - p_inputs->push_back( PropertyInfo( Variant::REAL,"alpha") ); - } break; + 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++; } - -} -void ShaderGraph::shader_get_default_output_nodes(ShaderGraphType p_type,List *p_outputs) { - - switch(p_type) { - - case SHADER_VERTEX: { - - 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: { - - 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") ); - - } break; - case SHADER_POST_PROCESS: { - p_outputs->push_back( PropertyInfo( Variant::VECTOR3,"color") ); - p_outputs->push_back( PropertyInfo( Variant::REAL,"alpha") ); - } break; - - } - } -PropertyInfo ShaderGraph::shader_node_get_type_info(NodeType p_type) { +const ShaderGraph::NodeSlotInfo ShaderGraph::node_slot_info[]= { - switch(p_type) { + {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_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_TYPE_SCALAR},{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_XFORM,SLOT_TYPE_VEC,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}} +}; - 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"); +int ShaderGraph::get_node_input_slot_count(Mode p_mode, ShaderType p_shader_type,NodeType p_type) { - default: {} + 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;iins[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: {} +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;iouts[i]==SLOT_MAX) + break; + pc++; + } + return pc; + } + + nsi++; + } + + return 0; + } - ERR_FAIL_V( 0 ); } -int ShaderGraph::shader_get_output_count(NodeType p_type) { +ShaderGraph::SlotType ShaderGraph::get_node_input_slot_type(Mode p_mode, ShaderType p_shader_type,NodeType p_type,int p_idx){ - 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; + 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;iins[i]==SLOT_MAX) + break; + if (i==p_idx) + return nsi->ins[i]; + } + } + + nsi++; + } + + ERR_FAIL_V(SLOT_MAX); - default: {} } - ERR_FAIL_V( 0 ); +} +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;iouts[i]==SLOT_MAX) + break; + if (i==p_idx) + return nsi->outs[i]; + } + } + + nsi++; + } + + ERR_FAIL_V(SLOT_MAX); + } } -#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 ""; +void ShaderGraph::_update_shader() { - default: {} + + String code[3]; + + for(int i=0;i<3;i++) { + + int idx=0; + for (Map::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::Element *E=shader[i].node_map.front();E;E=E->next()) { + + for(Map::Element *F=E->get().connections.front();F;F=F->next()) { + + //this is kinda slow, could be sped up + Map::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 order; + order.resize(shader[i].node_map.size()); + + for (Map::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);"; + code[i]+="float ALPHA_OUT=0;"; + } + + Map inputs_xlate; + Set inputs_used; + + for(int j=0;jtype==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"; + 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+";\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.rgb=DIFFUSE_OUT;\n"; + code[i]+="DIFFUSE_ALPHA.a=ALPHA_OUT;\n"; + } else { + code[i]+="DIFFUSE=DIFFUSE_OUT;\n"; + } + } + + } else { + Vector inputs; + int max = get_node_input_slot_count(get_mode(),ShaderType(i),n->type); + for(int k=0;kconnections.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; + _add_node_code(ShaderType(i),n,inputs,code[i]); + } + + } + + if (failed) + continue; + + for(Set::Element *E=inputs_used.front();E;E=E->next()) { + + ERR_CONTINUE( !inputs_xlate.has(E->get())); + code[i]=inputs_xlate[E->get()]+code[i]; + } + shader[i].error=GRAPH_OK; + print_line("ShADER: "+code[i]); } - 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: {} + bool all_ok=true; + for(int i=0;i<3;i++) { + if (shader[i].error!=GRAPH_OK) + all_ok=false; } - 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: {} + if (all_ok) { + set_code(code[0],code[1],code[2]); } - - ERR_FAIL_V(false); + //do shader here + print_line("UPDATING SHADER"); + _pending_update_shader=false; } -bool ShaderGraph::shader_is_output_vector(NodeType p_type,int p_input) { - switch(p_type) { +void ShaderGraph::_add_node_code(ShaderType p_type,Node *p_node,const Vector& p_inputs,String& code) { - 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: {} + 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))) + + 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"; + }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_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_POW: optxt = "pow("+p_inputs[0]+","+p_inputs[1]+");"; break; + } + code+=OUTNAME(p_node->id,0)+"="+optxt+"\n"; + + }break; + case NODE_RGB_OP: { + + + }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);\n"; + } else { + code += OUTNAME(p_node->id,0)+"="+p_inputs[0]+"*vec4("+p_inputs[1]+",1);\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);\n"; + } else { + code += OUTNAME(p_node->id,0)+"="+p_inputs[1]+"*vec4("+p_inputs[0]+",1);\n"; + } + }break; + case NODE_SCALAR_FUNC: { + + + }break; + case NODE_VEC_FUNC: { + + }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="_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="_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: { + + } } - - ERR_FAIL_V(""); } - -#endif -#endif diff --git a/scene/resources/shader_graph.h b/scene/resources/shader_graph.h index e20e010c6b0..c73895db8a5 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,287 @@ 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(ShaderType p_which, 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 connections; + }; struct ShaderData { Map node_map; - List connections; + GraphError error; } shader[3]; - uint64_t version; + + + struct InOutParamInfo { + Mode shader_mode; + ShaderType shader_type; + const char *name; + const char *variable; + 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]; + }; + + 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& p_inputs,String& code); + + Array _get_node_list(ShaderType p_type) const; + Array _get_connections(ShaderType p_type) const; 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 *p_list) const;*/ - static void _bind_methods(); - Array _get_connections_helper() const; - 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 *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 *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 *p_inputs); - static void get_default_output_nodes(Mode p_type,List *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 + }; + + 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,float p_c); + RGBOp rgb_op_node_get_op(ShaderType p_which,float p_id) const; + float rgb_op_node_get_c(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& p_texture); + Ref 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& p_cubemap); + Ref 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 *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); + + 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); - ShaderGraph(); + struct SlotInfo { + String name; + SlotType type; + SlotDir dir; + }; + + static void get_input_output_node_slot_info(Mode p_mode, ShaderType p_type, List *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 +376,27 @@ 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 ); + + +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/servers/visual/shader_graph.h b/servers/visual/shader_graph.h index 5c5079202ff..fe305f39558 100644 --- a/servers/visual/shader_graph.h +++ b/servers/visual/shader_graph.h @@ -26,8 +26,6 @@ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SHADER_GRAPH_H -#define SHADER_GRAPH_H #if 0 @@ -109,4 +107,3 @@ public: }; #endif -#endif diff --git a/tools/SCsub b/tools/SCsub index 875663b8498..4d8b05fe794 100644 --- a/tools/SCsub +++ b/tools/SCsub @@ -5,13 +5,16 @@ env.add_source_files(env.tool_sources,"*.cpp") Export('env') -SConscript('editor/SCsub'); -#SConscript('scintilla/SCsub'); -SConscript('collada/SCsub'); -SConscript('docdump/SCsub'); -SConscript('freetype/SCsub'); -SConscript('doc/SCsub'); -SConscript('pck/SCsub'); +if (env["tools"]!="no"): + SConscript('editor/SCsub'); + #SConscript('scintilla/SCsub'); + SConscript('collada/SCsub'); + SConscript('docdump/SCsub'); + SConscript('freetype/SCsub'); + SConscript('doc/SCsub') + SConscript('pck/SCsub') + + lib = env.Library("tool",env.tool_sources) diff --git a/tools/doc/doc_data.cpp b/tools/doc/doc_data.cpp index d13c7ea73c3..75759e7d306 100644 --- a/tools/doc/doc_data.cpp +++ b/tools/doc/doc_data.cpp @@ -186,8 +186,10 @@ void DocData::generate(bool p_basic_types) { arginfo=E->get().return_val; if (arginfo.type==Variant::NIL) continue; - - method.return_type=(arginfo.hint==PROPERTY_HINT_RESOURCE_TYPE)?arginfo.hint_string:Variant::get_type_name(arginfo.type); + if (m && m->get_return_type()!=StringName()) + method.return_type=m->get_return_type(); + else + method.return_type=(arginfo.hint==PROPERTY_HINT_RESOURCE_TYPE)?arginfo.hint_string:Variant::get_type_name(arginfo.type); } else { diff --git a/tools/editor/editor_node.cpp b/tools/editor/editor_node.cpp index dbc896cbb9e..b2fdd2fe03f 100644 --- a/tools/editor/editor_node.cpp +++ b/tools/editor/editor_node.cpp @@ -75,6 +75,7 @@ #include "plugins/tile_map_editor_plugin.h" #include "plugins/cube_grid_theme_editor_plugin.h" #include "plugins/shader_editor_plugin.h" +#include "plugins/shader_graph_editor_plugin.h" #include "plugins/path_editor_plugin.h" #include "plugins/rich_text_editor_plugin.h" #include "plugins/collision_polygon_editor_plugin.h" @@ -3245,7 +3246,7 @@ EditorNode::EditorNode() { gui_base->set_area_as_parent_rect(); - Ref theme( memnew( Theme ) ); + theme = Ref( memnew( Theme ) ); gui_base->set_theme( theme ); editor_register_icons(theme); editor_register_fonts(theme); @@ -4016,6 +4017,7 @@ EditorNode::EditorNode() { add_editor_plugin( memnew( ScriptEditorPlugin(this) ) ); add_editor_plugin( memnew( EditorHelpPlugin(this) ) ); add_editor_plugin( memnew( AnimationPlayerEditorPlugin(this) ) ); + add_editor_plugin( memnew( ShaderGraphEditorPlugin(this) ) ); add_editor_plugin( memnew( ShaderEditorPlugin(this) ) ); add_editor_plugin( memnew( CameraEditorPlugin(this) ) ); add_editor_plugin( memnew( SampleEditorPlugin(this) ) ); diff --git a/tools/editor/editor_node.h b/tools/editor/editor_node.h index 7b66a7809e0..381993646ed 100644 --- a/tools/editor/editor_node.h +++ b/tools/editor/editor_node.h @@ -212,6 +212,7 @@ class EditorNode : public Node { AcceptDialog *load_error_dialog; Control *scene_root_base; + Ref theme; PopupMenu *recent_scenes; Button *property_back; @@ -472,6 +473,9 @@ public: void stop_child_process(); + Ref get_editor_theme() const { return theme; } + + Error export_platform(const String& p_platform, const String& p_path, bool p_debug,const String& p_password,bool p_quit_after=false); static void register_editor_types(); diff --git a/tools/editor/icons/icon_canvas_item_shader.png b/tools/editor/icons/icon_canvas_item_shader.png new file mode 100644 index 0000000000000000000000000000000000000000..a5f4e7bf850bc7807f7ac9829c76f3a630a75232 GIT binary patch literal 568 zcmV-80>}M{P)N$2OJJO=W5uA)-NMlq5n6q9PEA(1RH5(oU^Ym%Iof zcv)0uZ_bN&D58Vdp(yy% z2D<=LGZ=lGVr5s5--0|(v2^^rWOS5AxS|V36cgZH*4n$3+s5zS zr&uciR%3&yt0u2!o-q+gQaiG687it5-u+l5SNu-ZDmcOa&+i3#c=K|e4lPDGUt}S> z&aXc^RO|adshNRFDCoiG3F1}_tdknWQl7)30#G{*2KWa{vW;51!^6!00000J%=P)4Ez(7LFon=}>z5}gF4RuR-y`~w^!=pq?J5k<0;7KvL| z?dqzNE}@D-=unaBU=_?SL+njZlj!Sk)8y8emcH=u!N>PL=Wxzz1R4Ui(61KIWE~lB zCd=64IyDDsfDa?U2wM0}?n#kL8$r^tQ4-^ZO__0O1h|26f@>Klz|JO& z0{aN=dbdk}t$-Ku3i#0h{Kq^B6uY0@%NKbXPjI{u!F-?{qm@l@B>=?g{pLMDtXnA( zPjKSuE!$BD%CQKLQo;f9k33cCKZ(>o zDszA`2An^4T66AhES=>VFbA{&*AJPOfktl*YvfJDd8Id|*Zqj;S`mUOz-}n=Q7R8G$YfUprhLZg4FAv+`_2>MKh{^FY(2!lc|A8 z>?u6$PZA|F3P5$UfUhBQ2%wDs&80Rs N002ovPDHLkV1oBm`1}9> literal 0 HcmV?d00001 diff --git a/tools/editor/icons/icon_material_shader.png b/tools/editor/icons/icon_material_shader.png new file mode 100644 index 0000000000000000000000000000000000000000..0e476b25407d05d6a75c23bebe74bfd05f2a285b GIT binary patch literal 844 zcmV-S1GD^zP)e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00Oj0L_t(I%Vm>GZyQwrg}-~} z&e-EeoTN_DCQ+qWK&q%xTd6{9EV9UwKaCIz7L)}lk4PwW(>8WHPG>ytJNLl?0fBz& z^DT~aj^Ga7djW{~*_j>odPGv>&&wDYf@^8DE&P97ezGZ_%zuw6~tRwT(Smsd-E zdbvOjg#Y%3Uj=~j-i!0|$96t{%EiT3d~rHsG#aCnL`s8m6 z)&9kcS3&{eV0Ogp`6G5uXZXn;ZP=%i5=)06pb0FMFyuQLj(3@!9x`040gzATXLfS3 z&-k+=y3v>_>{A61g;W$W;#Nc~Wym`faubE5qaN;Hi*Rqm@#zDv#2_X*IKYhWQ3o-R z>|+VQ3k-(B_sRT_%o{S{NTs3fO^{m?2qTn?wg}>VjF{4iT{<5lP=H5!i}oSfMCdL? z>lo8Tc;6t^E`f?s&h}{agxX9g%r-*yh=c?{J4ay+g>EUUK1~tP9^B!Xj zw$o@`QMUzEnX<_f)*r6ftX8a7*Fphg>({&wBZggzoa{pwBc#Ati?JQ9Yp_j;sWaL< zp-dL&D*boLS8sn2fwSJ#In~Y)+ru3q75!DiS~{z#+mf_QNwO8$X2oiKE&g*RfQR>v z{Z>3?9FG}9F=3!^-eaAmY)i6gL*5j;xqT--dE;FkY)`$C0V)XafOC${8gA0$ll-4T WjE14N3=(hv0000e zSad^gZEa<4bO1wgWnpw>WFU8GbZ8()Nlj2!fese{00SLKL_t(I%WaciXj^q0#XrA$ zZ*J41X-%@UNub>f#p)VsC;NklPgb`vU*?=IGC_w9oJNX>zUaU`DDJ^o#VMlTgD}{G ziZD9_p^Oz*9V;#CY&526+Wcv5+uWo#X>M|JeMl)qJ@9$?!Z|PJd<8AF15zLm5C9Rc z_kv4RamsR2mL$t;G%#v4Zp7m;{v`n%e&rLsEf^?zL$n)0UDR5^cIH%s^8yyDU~4WrnJ~pUupq&nf_!|1p)K z(Lu#B<)_E499!u21Z}%RGzage`S4>FqwoKqbOkz}%23=kW`Hs-AOwIet5nRIlTlWxfAFgv3&nYgSNBiwlqgvV&a#6SBjq`0X6J50Zj=8%K&Nf|MOE(%4wg(7q z5du_@B%uT%k<BEn!s?%MN{XKn0ef~bWJiVxLr#;{wUb_C{_+I1EDfiNIUx?_TV~bZWeYt1)%`*>@ z&=`FCoykXo;cKqDQ`438;+j&`N)+y-$T=5ibT^p&b@Cq1cXRssTQBdL9tjR!JagKN zJ2nUS=scdICkjIk9hoj=@>X@FOue#+02m%RGS=UJ2*0ma`8qoOLjCoVPHZoTK43TC z1Pvkw_uq_0N2XQ^3oI|skxtLX6aam7krjuEVibiPaY*0=5d?OD*#b{hTx XDV$zZkQMT)00000NkvXXu0mjf_%Np2 literal 0 HcmV?d00001 diff --git a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp index 6bae0d2fd0c..ed228e9a1cc 100644 --- a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp +++ b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp @@ -398,11 +398,13 @@ CollisionPolygon2DEditor::CollisionPolygon2DEditor(EditorNode *p_editor) { add_child(button_create); button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE)); button_create->set_toggle_mode(true); + button_create->set_tooltip("Create a new polygon from scratch"); button_edit = memnew( ToolButton ); add_child(button_edit); button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT)); button_edit->set_toggle_mode(true); + button_edit->set_tooltip("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point."); //add_constant_override("separation",0); diff --git a/tools/editor/plugins/shader_graph_editor_plugin.cpp b/tools/editor/plugins/shader_graph_editor_plugin.cpp index 2686ca895e8..710f11e7268 100644 --- a/tools/editor/plugins/shader_graph_editor_plugin.cpp +++ b/tools/editor/plugins/shader_graph_editor_plugin.cpp @@ -28,1082 +28,1427 @@ /*************************************************************************/ #include "shader_graph_editor_plugin.h" -#if 0 + #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" +#include "spatial_editor_plugin.h" -class _ShaderTester : public ShaderCodeGenerator { -public: +////cbacks +/// +void ShaderGraphView::_scalar_const_changed(double p_value,int p_id) { - Set *_set; + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Scalar Constant",true); + ur->add_do_method(graph.ptr(),"scalar_const_node_set_value",type,p_id,p_value); + ur->add_undo_method(graph.ptr(),"scalar_const_node_set_value",type,p_id,graph->scalar_const_node_get_value(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} - virtual void begin() {} - virtual Error add_node(VS::ShaderNodeType p_type,int p_node_pos,int p_id,const Variant& p_param,const Vector& p_in_connections,const Vector& p_out_connections,const Vector& p_out_connection_outputs) { if (_set) _set->insert(p_id); return OK; } - virtual void end() {} +void ShaderGraphView::_vec_const_changed(double p_value, int p_id,Array p_arr){ - _ShaderTester() { _set=NULL; } -}; + Vector3 val; + for(int i=0;iget_undo_redo(); + ur->create_action("Change Vec Constant",true); + ur->add_do_method(graph.ptr(),"vec_const_node_set_value",type,p_id,val); + ur->add_undo_method(graph.ptr(),"vec_const_node_set_value",type,p_id,graph->vec_const_node_get_value(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; + +} +void ShaderGraphView::_rgb_const_changed(const Color& p_color, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change RGB Constant",true); + ur->add_do_method(graph.ptr(),"rgb_const_node_set_value",type,p_id,p_color); + ur->add_undo_method(graph.ptr(),"rgb_const_node_set_value",type,p_id,graph->rgb_const_node_get_value(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; + +} +void ShaderGraphView::_scalar_op_changed(int p_op, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Scalar Operator"); + ur->add_do_method(graph.ptr(),"scalar_op_node_set_op",type,p_id,p_op); + ur->add_undo_method(graph.ptr(),"scalar_op_node_set_op",type,p_id,graph->scalar_op_node_get_op(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; + +} +void ShaderGraphView::_vec_op_changed(int p_op, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Vec Operator"); + ur->add_do_method(graph.ptr(),"vec_op_node_set_op",type,p_id,p_op); + ur->add_undo_method(graph.ptr(),"vec_op_node_set_op",type,p_id,graph->vec_op_node_get_op(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} +void ShaderGraphView::_vec_scalar_op_changed(int p_op, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change VecxScalar Operator"); + ur->add_do_method(graph.ptr(),"vec_scalar_op_node_set_op",type,p_id,p_op); + ur->add_undo_method(graph.ptr(),"vec_scalar_op_node_set_op",type,p_id,graph->vec_scalar_op_node_get_op(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; + +} +void ShaderGraphView::_rgb_op_changed(int p_op, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change RGB Operator"); + ur->add_do_method(graph.ptr(),"rgb_op_node_set_op",type,p_id,p_op); + ur->add_undo_method(graph.ptr(),"rgb_op_node_set_op",type,p_id,graph->rgb_op_node_get_op(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} +void ShaderGraphView::_xform_inv_rev_changed(bool p_enabled, int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Toggle Rot Only"); + ur->add_do_method(graph.ptr(),"xform_vec_mult_node_set_no_translation",type,p_id,p_enabled); + ur->add_undo_method(graph.ptr(),"xform_vec_mult_node_set_no_translation",type,p_id,graph->xform_vec_mult_node_get_no_translation(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} +void ShaderGraphView::_scalar_func_changed(int p_func, int p_id){ + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Scalar Function"); + ur->add_do_method(graph.ptr(),"scalar_func_node_set_function",type,p_id,p_func); + ur->add_undo_method(graph.ptr(),"scalar_func_node_set_function",type,p_id,graph->scalar_func_node_get_function(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} +void ShaderGraphView::_vec_func_changed(int p_func, int p_id){ -void ShaderEditor::edit(Ref p_shader) { + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Vec Function"); + ur->add_do_method(graph.ptr(),"vec_func_node_set_function",type,p_id,p_func); + ur->add_undo_method(graph.ptr(),"vec_func_node_set_function",type,p_id,graph->vec_func_node_get_function(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; + +} +void ShaderGraphView::_scalar_input_changed(double p_value,int p_id){ + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Scalar Uniform",true); + ur->add_do_method(graph.ptr(),"scalar_input_node_set_value",type,p_id,p_value); + ur->add_undo_method(graph.ptr(),"scalar_input_node_set_value",type,p_id,graph->scalar_input_node_get_value(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; + +} +void ShaderGraphView::_vec_input_changed(double p_value, int p_id,Array p_arr){ + + Vector3 val; + for(int i=0;iget_undo_redo(); + ur->create_action("Change Vec Uniform",true); + ur->add_do_method(graph.ptr(),"vec_input_node_set_value",type,p_id,val); + ur->add_undo_method(graph.ptr(),"vec_input_node_set_value",type,p_id,graph->vec_input_node_get_value(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; + +} +void ShaderGraphView::_xform_input_changed(int p_id, Node *p_button){ + + print_line("XFIC"); + ToolButton *tb = p_button->cast_to(); + ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height)); + ped_popup->set_size(tb->get_size()); + edited_id=p_id; + ped_popup->edit(NULL,"",Variant::TRANSFORM,graph->xform_input_node_get_value(type,p_id),PROPERTY_HINT_NONE,""); + ped_popup->popup(); + +} +void ShaderGraphView::_xform_const_changed(int p_id, Node *p_button){ + + ToolButton *tb = p_button->cast_to(); + ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height)); + ped_popup->set_size(tb->get_size()); + edited_id=p_id; + ped_popup->edit(NULL,"",Variant::TRANSFORM,graph->xform_const_node_get_value(type,p_id),PROPERTY_HINT_NONE,""); + ped_popup->popup(); + +} + +void ShaderGraphView::_rgb_input_changed(const Color& p_color, int p_id){ - shader=p_shader; + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change RGB Uniform",true); + ur->add_do_method(graph.ptr(),"rgb_input_node_set_value",type,p_id,p_color); + ur->add_undo_method(graph.ptr(),"rgb_input_node_set_value",type,p_id,graph->rgb_input_node_get_value(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; +} +void ShaderGraphView::_tex_input_change(int p_id, Node *p_button){ - if (shader.is_null()) - hide(); - else { - _read_shader_graph(); + +} +void ShaderGraphView::_cube_input_change(int p_id){ + + +} + +void ShaderGraphView::_variant_edited() { + + if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_XFORM_CONST) { + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change XForm Uniform"); + ur->add_do_method(graph.ptr(),"xform_const_node_set_value",type,edited_id,ped_popup->get_variant()); + ur->add_undo_method(graph.ptr(),"xform_const_node_set_value",type,edited_id,graph->xform_const_node_get_value(type,edited_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); + } + + + if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_XFORM_INPUT) { + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change XForm Uniform"); + ur->add_do_method(graph.ptr(),"xform_input_node_set_value",type,edited_id,ped_popup->get_variant()); + ur->add_undo_method(graph.ptr(),"xform_input_node_set_value",type,edited_id,graph->xform_input_node_get_value(type,edited_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); + } + + if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_TEXTURE_INPUT) { + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Texture Uniform"); + ur->add_do_method(graph.ptr(),"texture_input_node_set_value",type,edited_id,ped_popup->get_variant()); + ur->add_undo_method(graph.ptr(),"texture_input_node_set_value",type,edited_id,graph->texture_input_node_get_value(type,edited_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); + } + + if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_CUBEMAP_INPUT) { + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Cubemap Uniform"); + ur->add_do_method(graph.ptr(),"cubemap_input_node_set_value",type,edited_id,ped_popup->get_variant()); + ur->add_undo_method(graph.ptr(),"cubemap_input_node_set_value",type,edited_id,graph->cubemap_input_node_get_value(type,edited_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); } } -Size2 ShaderEditor::_get_maximum_size() { +void ShaderGraphView::_comment_edited(int p_id,Node* p_button) { - Size2 max; + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + TextEdit *te=p_button->cast_to(); + ur->create_action("Change Comment",true); + ur->add_do_method(graph.ptr(),"comment_node_set_text",type,p_id,te->get_text()); + ur->add_undo_method(graph.ptr(),"comment_node_set_text",type,p_id,graph->comment_node_get_text(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; - for(List::Element *E=order.front();E;E=E->next()) { +} - Point2 pos = Point2( shader_graph.node_get_pos_x(E->get()), shader_graph.node_get_pos_y(E->get()) ); - if (click_type==CLICK_NODE && click_node==E->get()) { +void ShaderGraphView::_input_name_changed(const String& p_name, int p_id, Node *p_line_edit) { - pos+=click_motion-click_pos; + LineEdit *le=p_line_edit->cast_to(); + ERR_FAIL_COND(!le); + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change Input Name"); + ur->add_do_method(graph.ptr(),"input_node_set_name",type,p_id,p_name); + ur->add_undo_method(graph.ptr(),"input_node_set_name",type,p_id,graph->input_node_get_name(type,p_id)); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + block_update=true; + ur->commit_action(); + block_update=false; + le->set_text(graph->input_node_get_name(type,p_id)); +} + +void ShaderGraphView::_tex_edited(int p_id,Node* p_button) { + + ToolButton *tb = p_button->cast_to(); + ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height)); + ped_popup->set_size(tb->get_size()); + edited_id=p_id; + ped_popup->edit(NULL,"",Variant::OBJECT,graph->texture_input_node_get_value(type,p_id),PROPERTY_HINT_RESOURCE_TYPE,"Texture"); +} + +void ShaderGraphView::_cube_edited(int p_id,Node* p_button) { + + ToolButton *tb = p_button->cast_to(); + ped_popup->set_pos(tb->get_global_pos()+Vector2(0,tb->get_size().height)); + ped_popup->set_size(tb->get_size()); + edited_id=p_id; + ped_popup->edit(NULL,"",Variant::OBJECT,graph->cubemap_input_node_get_value(type,p_id),PROPERTY_HINT_RESOURCE_TYPE,"CubeMap"); +} + + +//////////////view///////////// + + +void ShaderGraphView::_connection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot) { + + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + + int from_idx=-1; + int to_idx=-1; + for (Map::Element *E=node_map.front();E;E=E->next()) { + + if (p_from==E->get()->get_name()) + from_idx=E->key(); + if (p_to==E->get()->get_name()) + to_idx=E->key(); + } + + ERR_FAIL_COND(from_idx==-1); + ERR_FAIL_COND(to_idx==-1); + + ur->create_action("Connect Graph Nodes"); + + List conns; + + graph->get_node_connections(type,&conns); + //disconnect/reconnect dependencies + ur->add_undo_method(graph.ptr(),"disconnect_node",type,from_idx,p_from_slot,to_idx,p_to_slot); + for(List::Element *E=conns.front();E;E=E->next()) { + + if (E->get().dst_id==to_idx && E->get().dst_slot==p_to_slot) { + ur->add_do_method(graph.ptr(),"disconnect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot); + ur->add_undo_method(graph.ptr(),"connect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot); } - pos+=get_node_size(E->get()); - if (pos.x>max.x) - max.x=pos.x; - if (pos.y>max.y) - max.y=pos.y; - } + ur->add_do_method(graph.ptr(),"connect_node",type,from_idx,p_from_slot,to_idx,p_to_slot); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); + - return max; } -Size2 ShaderEditor::get_node_size(int p_node) const { +void ShaderGraphView::_node_removed(int p_id) { - VisualServer::ShaderNodeType type=shader_graph.node_get_type(p_node); - Ref style = get_stylebox("panel","PopupMenu"); - Ref font = get_font("font","PopupMenu"); - Color font_color = get_color("font_color","PopupMenu"); + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Remove Shader Graph Node"); - Size2 size = style->get_minimum_size(); + ur->add_do_method(graph.ptr(),"node_remove",type,p_id); + ur->add_undo_method(graph.ptr(),"node_add",type,graph->node_get_type(type,p_id),p_id); + ur->add_undo_method(graph.ptr(),"node_set_state",type,p_id,graph->node_get_state(type,p_id)); + List conns; - int count=1; // title - count += VisualServer::shader_get_input_count( type) + VisualServer::shader_get_output_count( type); + graph->get_node_connections(type,&conns); + for(List::Element *E=conns.front();E;E=E->next()) { - float max_w=font->get_string_size( VisualServer::shader_node_get_type_info(type).name ).width; - - for(int i=0;iget_string_size( VisualServer::shader_get_input_name(type,i) ).width ); - - - for(int i=0;iget_string_size( VisualServer::shader_get_output_name(type,i) ).width ); - - - - - switch(type) { - - case VS::NODE_IN: - case VS::NODE_OUT: - case VS::NODE_VEC_IN: - case VS::NODE_VEC_OUT: - case VS::NODE_PARAMETER: - case VS::NODE_VEC_PARAMETER: - case VS::NODE_COLOR_PARAMETER: - case VS::NODE_TEXTURE_PARAMETER: - case VS::NODE_TEXTURE_2D_PARAMETER: - case VS::NODE_TEXTURE_CUBE_PARAMETER: - case VS::NODE_TRANSFORM_PARAMETER: - case VS::NODE_LABEL: { - - max_w=MAX( max_w, font->get_string_size( shader_graph.node_get_param(p_node) ).width ); - count++; - } break; - case VS::NODE_TIME: - case VS::NODE_CONSTANT: - case VS::NODE_VEC_CONSTANT: - case VS::NODE_COLOR_CONSTANT: - case VS::NODE_TRANSFORM_CONSTANT: { - count++; - } break; - case VS::NODE_TEXTURE: - case VS::NODE_VEC_TEXTURE_2D: - case VS::NODE_VEC_TEXTURE_CUBE: { - - RefPtr res = shader_graph.node_get_param(p_node); - Ref texture = res; - if (texture.is_null() || texture->get_width()==0) { - - size.y+=max_w; - } else { - - size.y+=max_w * texture->get_height() / texture->get_width(); - } - } break; - default: {} - - } - - size.x+=max_w; - size.y+=count*(font->get_height()+get_constant("vseparation","PopupMenu")); - - return size; -} - - -Error ShaderEditor::validate_graph() { - - _ShaderTester st; - active_nodes.clear(); - st._set=&active_nodes; - return shader_graph.generate(&st); -} - -void ShaderEditor::_draw_node(int p_node) { - - VisualServer::ShaderNodeType type=shader_graph.node_get_type(p_node); - Ref style = active_nodes.has(p_node)?get_stylebox("panel","PopupMenu"):get_stylebox("panel_disabled","PopupMenu"); - Ref font = get_font("font","PopupMenu"); - Color font_color = get_color("font_color","PopupMenu"); - Color font_color_title = get_color("font_color_hover","PopupMenu"); - Size2 size=get_node_size(p_node); - Point2 pos = Point2( shader_graph.node_get_pos_x(p_node), shader_graph.node_get_pos_y(p_node) )-offset; - - if (click_type==CLICK_NODE && click_node==p_node) { - - pos+=click_motion-click_pos; - } - - RID ci = get_canvas_item(); - style->draw(ci,Rect2(pos,size)); - - Point2 ofs=style->get_offset()+pos; - Point2 ascent=Point2(0,font->get_ascent()); - float w = size.width-style->get_minimum_size().width; - float h = font->get_height()+get_constant("vseparation","PopupMenu"); - - font->draw_halign( ci, ofs+ascent, HALIGN_CENTER,w, VisualServer::shader_node_get_type_info(type).name,font_color_title); - ofs.y+=h; - - Ref vec_icon = get_icon("NodeVecSlot","EditorIcons"); - Ref real_icon = get_icon("NodeRealSlot","EditorIcons"); - float icon_h_ofs = Math::floor(( font->get_height()-vec_icon->get_height())/2.0 )+1; - - - for(int i=0;idraw_halign( ci, ofs+ascent, HALIGN_LEFT,w, name,font_color); - Ref icon = VisualServer::shader_is_input_vector(type,i)?vec_icon:real_icon; - icon->draw(ci,ofs+Point2(-real_icon->get_width(),icon_h_ofs)); - ofs.y+=h; - } - - for(int i=0;idraw_halign( ci, ofs+ascent, HALIGN_RIGHT,w, name,font_color); - Ref icon = VisualServer::shader_is_output_vector(type,i)?vec_icon:real_icon; - icon->draw(ci,ofs+Point2(w,icon_h_ofs)); - ofs.y+=h; - } - - switch(type) { - - case VS::NODE_IN: - case VS::NODE_OUT: - case VS::NODE_PARAMETER: - case VS::NODE_VEC_IN: - case VS::NODE_COLOR_PARAMETER: - case VS::NODE_VEC_OUT: - case VS::NODE_TEXTURE_PARAMETER: - case VS::NODE_TEXTURE_2D_PARAMETER: - case VS::NODE_TEXTURE_CUBE_PARAMETER: - case VS::NODE_TRANSFORM_CONSTANT: - case VS::NODE_TRANSFORM_PARAMETER: - case VS::NODE_VEC_PARAMETER: - case VS::NODE_LABEL: { - String text = shader_graph.node_get_param(p_node); - font->draw_halign( ci, ofs+ascent, HALIGN_CENTER,w, text,font_color); - } break; - case VS::NODE_TIME: - case VS::NODE_CONSTANT: { - String text = rtos(shader_graph.node_get_param(p_node)); - font->draw_halign( ci, ofs+ascent, HALIGN_CENTER,w, text,font_color); - - } break; - case VS::NODE_VEC_CONSTANT: { - String text = Vector3(shader_graph.node_get_param(p_node)); - font->draw_halign( ci, ofs+ascent, HALIGN_CENTER,w, text,font_color); - } break; - case VS::NODE_COLOR_CONSTANT: { - - Color color = shader_graph.node_get_param(p_node); - Rect2 r(ofs,Size2(w,h)); - VisualServer::get_singleton()->canvas_item_add_rect(ci,r,color); - } break; - case VS::NODE_TEXTURE: - case VS::NODE_VEC_TEXTURE_2D: - case VS::NODE_VEC_TEXTURE_CUBE: { - - Rect2 r(ofs,Size2(w,(pos.y+size.y-style->get_margin(MARGIN_BOTTOM))-ofs.y)); - Vector points; - Vector uvs; - points.resize(4); - uvs.resize(4); - points[0]=r.pos; - points[1]=r.pos+Point2(r.size.x,0); - points[2]=r.pos+r.size; - points[3]=r.pos+Point2(0,r.size.y); - uvs[0]=Point2(0,0); - uvs[1]=Point2(1,0); - uvs[2]=Point2(1,1); - uvs[3]=Point2(0,1); - - Ref texture = shader_graph.node_get_param(p_node).operator RefPtr(); - if (texture.is_null() || texture->get_width()==0) { - texture=get_icon("Click2Edit","EditorIcons"); - } - - VisualServer::get_singleton()->canvas_item_add_primitive(ci,points,Vector(),uvs,texture->get_rid()); - } break; - default: {} - } -} - -void ShaderEditor::_node_param_changed() { - - shader_graph.node_set_param( click_node,property_editor->get_variant() ); - update(); - _write_shader_graph(); -} - -ShaderEditor::ClickType ShaderEditor::_locate_click(const Point2& p_click,int *p_node_id,int *p_slot_index) const { - - Ref style = get_stylebox("panel","PopupMenu"); - Ref real_icon = get_icon("NodeRealSlot","EditorIcons"); - Ref font = get_font("font","PopupMenu"); - float h = font->get_height()+get_constant("vseparation","PopupMenu"); - float extra_left=MAX( real_icon->get_width()-style->get_margin(MARGIN_LEFT), 0 ); - float extra_right=MAX( real_icon->get_width()-style->get_margin(MARGIN_RIGHT), 0 ); - - - for(const List::Element *E=order.back();E;E=E->prev()) { - - Size2 size=get_node_size(E->get()); - size.width+=extra_left+extra_right; - Point2 pos = Point2( shader_graph.node_get_pos_x(E->get()), shader_graph.node_get_pos_y(E->get()) )-offset; - pos.x-=extra_left; - - Rect2 rect( pos, size ); - if (!rect.has_point(p_click)) - continue; - VisualServer::ShaderNodeType type=shader_graph.node_get_type(E->get()); - if (p_node_id) - *p_node_id=E->get(); - float y=p_click.y-(pos.y+style->get_margin(MARGIN_TOP)); - if (yget().dst_id==p_id || E->get().src_id==p_id) { + ur->add_undo_method(graph.ptr(),"connect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot); } + } + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); - for(int i=0;iget_undo_redo(); + ur->create_action("Move Shader Graph Node"); + ur->add_do_method(this,"_move_node",p_id,p_to); + ur->add_undo_method(this,"_move_node",p_id,p_from); + ur->commit_action(); +} + +void ShaderGraphView::_move_node(int p_id,const Vector2& p_to) { + + ERR_FAIL_COND(!node_map.has(p_id)); + node_map[p_id]->set_offset(p_to); + graph->node_set_pos(type,p_id,p_to); +} + + +void ShaderGraphView::_create_node(int p_id) { + + + GraphNode *gn = memnew( GraphNode ); + gn->set_show_close_button(true); + Color typecol[4]={ + Color(0.2,1,0.2), + Color(0.7,0.1,1), + Color(1,0.2,0.2), + Color(0,1,1) + }; + + + switch(graph->node_get_type(type,p_id)) { + + case ShaderGraph::NODE_INPUT: { + + gn->set_title("Input"); + + List si; + ShaderGraph::get_input_output_node_slot_info(graph->get_mode(),type,&si); + + int idx=0; + for (List::Element *E=si.front();E;E=E->next()) { + ShaderGraph::SlotInfo& s=E->get(); + if (s.dir==ShaderGraph::SLOT_IN) { + + Label *l= memnew( Label ); + l->set_text(s.name); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + gn->set_slot(idx,false,0,Color(),true,s.type,typecol[s.type]); + idx++; + } } - y-=h; - } - if (p_click.y<(rect.pos.y+rect.size.height-style->get_margin(MARGIN_BOTTOM))) - return CLICK_PARAMETER; - else - return CLICK_NODE; + } break; // all inputs (case Shader type dependent) + case ShaderGraph::NODE_SCALAR_CONST: { + gn->set_title("Scalar"); + SpinBox *sb = memnew( SpinBox ); + sb->set_min(-100000); + sb->set_max(100000); + sb->set_step(0.001); + sb->set_val(graph->scalar_const_node_get_value(type,p_id)); + sb->connect("value_changed",this,"_scalar_const_changed",varray(p_id)); + gn->add_child(sb); + gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; //scalar constant + case ShaderGraph::NODE_VEC_CONST: { + + gn->set_title("Vector"); + Array v3p(true); + for(int i=0;i<3;i++) { + HBoxContainer *hbc = memnew( HBoxContainer ); + Label *l = memnew( Label ); + l->set_text(String::chr('X'+i)); + hbc->add_child(l); + SpinBox *sb = memnew( SpinBox ); + sb->set_h_size_flags(Control::SIZE_EXPAND_FILL); + sb->set_min(-100000); + sb->set_max(100000); + sb->set_step(0.001); + sb->set_val(graph->vec_const_node_get_value(type,p_id)[i]); + sb->connect("value_changed",this,"_vec_const_changed",varray(p_id,v3p)); + v3p.push_back(sb); + hbc->add_child(sb); + gn->add_child(hbc); + } + gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + + } break; //vec3 constant + case ShaderGraph::NODE_RGB_CONST: { + + gn->set_title("Color"); + ColorPickerButton *cpb = memnew( ColorPickerButton ); + cpb->set_color(graph->rgb_const_node_get_value(type,p_id)); + cpb->connect("color_changed",this,"_rgb_const_changed",varray(p_id)); + gn->add_child(cpb); + Label *l = memnew( Label ); + l->set_text("RGB"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + l = memnew( Label ); + l->set_text("Alpha"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; //rgb constant (shows a color picker instead) + case ShaderGraph::NODE_XFORM_CONST: { + gn->set_title("XForm"); + ToolButton *edit = memnew( ToolButton ); + edit->set_text("edit.."); + edit->connect("pressed",this,"_xform_const_changed",varray(p_id,edit)); + gn->add_child(edit); + gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]); + + } break; // 4x4 matrix constant + case ShaderGraph::NODE_TIME: { + + gn->set_title("Time"); + Label *l = memnew( Label ); + l->set_text("(s)"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; // time in seconds + case ShaderGraph::NODE_SCREEN_TEX: { + + gn->set_title("ScreenTex"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("UV"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("RGB"))); + gn->add_child(hbc); + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + + } break; // screen texture sampler (takes UV) (only usable in fragment case Shader) + case ShaderGraph::NODE_SCALAR_OP: { + + gn->set_title("ScalarOp"); + static const char* op_name[ShaderGraph::SCALAR_MAX_OP]={ + "Add", + "Sub", + "Mul", + "Div", + "Mod", + "Pow", + "Max", + "Min", + "Atan2" + }; + + OptionButton *ob = memnew( OptionButton ); + for(int i=0;iadd_item(op_name[i],i); + } + + ob->select(graph->scalar_op_node_get_op(type,p_id)); + ob->connect("item_selected",this,"_scalar_op_changed",varray(p_id)); + gn->add_child(ob); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + + + } break; // scalar vs scalar op (mul: { } break; add: { } break; div: { } break; etc) + case ShaderGraph::NODE_VEC_OP: { + + gn->set_title("VecOp"); + static const char* op_name[ShaderGraph::VEC_MAX_OP]={ + "Add", + "Sub", + "Mul", + "Div", + "Mod", + "Pow", + "Max", + "Min", + "Cross" + }; + + OptionButton *ob = memnew( OptionButton ); + for(int i=0;iadd_item(op_name[i],i); + } + + ob->select(graph->vec_op_node_get_op(type,p_id)); + ob->connect("item_selected",this,"_vec_op_changed",varray(p_id)); + gn->add_child(ob); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + + + } break; // vec3 vs vec3 op (mul: { } break;ad: { } break;div: { } break;crossprod: { } break;etc) + case ShaderGraph::NODE_VEC_SCALAR_OP: { + + gn->set_title("VecScalarOp"); + static const char* op_name[ShaderGraph::VEC_SCALAR_MAX_OP]={ + "Mul", + "Div", + "Pow", + }; + + OptionButton *ob = memnew( OptionButton ); + for(int i=0;iadd_item(op_name[i],i); + } + + ob->select(graph->vec_scalar_op_node_get_op(type,p_id)); + ob->connect("item_selected",this,"_vec_scalar_op_changed",varray(p_id)); + gn->add_child(ob); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + + + } break; // vec3 vs scalar op (mul: { } break; add: { } break; div: { } break; etc) + case ShaderGraph::NODE_RGB_OP: { + + gn->set_title("RGB Op"); + static const char* op_name[ShaderGraph::RGB_MAX_OP]={ + "Screen", + "Difference", + "Darken", + "Lighten", + "Overlay", + "Dodge", + "Burn", + "SoftLight", + "HardLight" + }; + + OptionButton *ob = memnew( OptionButton ); + for(int i=0;iadd_item(op_name[i],i); + } + + ob->select(graph->rgb_op_node_get_op(type,p_id)); + ob->connect("item_selected",this,"_rgb_op_changed",varray(p_id)); + gn->add_child(ob); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + + } break; // vec3 vs vec3 rgb op (with scalar amount): { } break; like brighten: { } break; darken: { } break; burn: { } break; dodge: { } break; multiply: { } break; etc. + case ShaderGraph::NODE_XFORM_MULT: { + + gn->set_title("XFMult"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],false,0,Color()); + + + } break; // mat4 x mat4 + case ShaderGraph::NODE_XFORM_VEC_MULT: + case ShaderGraph::NODE_XFORM_VEC_INV_MULT: { + + if (graph->node_get_type(type,p_id)==ShaderGraph::NODE_XFORM_VEC_INV_MULT) + gn->set_title("XFVecMult"); + else + gn->set_title("XFVecInvMult"); + + + Button *button = memnew( Button("RotOnly")); + button->set_toggle_mode(true); + button->set_pressed(graph->xform_vec_mult_node_get_no_translation(type,p_id)); + button->connect("toggled",this,"_xform_inv_rev_changed",varray(p_id)); + + gn->add_child(button); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("xf"))); + hbc->add_spacer(); + Label *l = memnew(Label("out")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + gn->add_child( memnew(Label("vec"))); + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + + + } break; // mat4 x vec3 inverse mult (with no-translation option) + case ShaderGraph::NODE_SCALAR_FUNC: { + + gn->set_title("ScalarFunc"); + static const char* func_name[ShaderGraph::SCALAR_MAX_FUNC]={ + "Sin", + "Cos", + "Tan", + "ASin", + "ACos", + "ATan", + "SinH", + "CosH", + "TanH", + "Log", + "Exp", + "Sqrt", + "Abs", + "Sign", + "Floor", + "Round", + "Ceil", + "Frac", + "Satr", + "Neg" + }; + + OptionButton *ob = memnew( OptionButton ); + for(int i=0;iadd_item(func_name[i],i); + } + + ob->select(graph->scalar_func_node_get_function(type,p_id)); + ob->connect("item_selected",this,"_scalar_func_changed",varray(p_id)); + gn->add_child(ob); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_child( memnew(Label("in"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + + } break; // scalar function (sin: { } break; cos: { } break; etc) + case ShaderGraph::NODE_VEC_FUNC: { + + + + gn->set_title("VecFunc"); + static const char* func_name[ShaderGraph::VEC_MAX_FUNC]={ + "Normalize", + "Saturate", + "Negate", + "Reciprocal", + "RGB to HSV", + "HSV to RGB", + }; + + OptionButton *ob = memnew( OptionButton ); + for(int i=0;iadd_item(func_name[i],i); + } + + ob->select(graph->vec_func_node_get_function(type,p_id)); + ob->connect("item_selected",this,"_vec_func_changed",varray(p_id)); + gn->add_child(ob); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("in"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + + } break; // vector function (normalize: { } break; negate: { } break; reciprocal: { } break; rgb2hsv: { } break; hsv2rgb: { } break; etc: { } break; etc) + case ShaderGraph::NODE_VEC_LEN: { + gn->set_title("VecLength"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_child( memnew(Label("in"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("len"))); + gn->add_child(hbc); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; // vec3 length + case ShaderGraph::NODE_DOT_PROD: { + + gn->set_title("DotProduct"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("dp"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + + } break; // vec3 . vec3 (dot product -> scalar output) + case ShaderGraph::NODE_VEC_TO_SCALAR: { + + gn->set_title("Vec2Scalar"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("vec"))); + hbc->add_spacer(); + Label *l=memnew(Label("x")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + l=memnew(Label("y")); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child( l ); + l=memnew(Label("z")); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child( l); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + + + + } break; // 1 vec3 input: { } break; 3 scalar outputs + case ShaderGraph::NODE_SCALAR_TO_VEC: { + + gn->set_title("Scalar2Vec"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_child( memnew(Label("x"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("vec"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("y"))); + gn->add_child( memnew(Label("z"))); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + + } break; // 3 scalar input: { } break; 1 vec3 output + case ShaderGraph::NODE_VEC_TO_XFORM: { + + gn->set_title("Vec2XForm"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("x"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("xf"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("y"))); + gn->add_child( memnew(Label("z"))); + gn->add_child( memnew(Label("ofs"))); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + gn->set_slot(3,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + + } break; // 3 vec input: { } break; 1 xform output + case ShaderGraph::NODE_XFORM_TO_VEC: { + + gn->set_title("XForm2Vec"); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("xf"))); + hbc->add_spacer(); + Label *l=memnew(Label("x")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + l=memnew(Label("y")); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child( l ); + l=memnew(Label("z")); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child( l); + l=memnew(Label("ofs")); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child( l); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + + } break; // 3 vec input: { } break; 1 xform output + case ShaderGraph::NODE_SCALAR_INTERP: { + + gn->set_title("ScalarInterp"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("interp"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); + gn->add_child( memnew(Label("c"))); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + + + } break; // scalar interpolation (with optional curve) + case ShaderGraph::NODE_VEC_INTERP: { + + gn->set_title("VecInterp"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_child( memnew(Label("a"))); + hbc->add_spacer(); + hbc->add_child( memnew(Label("interp"))); + gn->add_child(hbc); + gn->add_child( memnew(Label("b"))); + gn->add_child( memnew(Label("c"))); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color()); + + } break; // vec3 interpolation (with optional curve) + case ShaderGraph::NODE_SCALAR_INPUT: { + + gn->set_title("ScalarUniform"); + LineEdit *le = memnew( LineEdit ); + gn->add_child(le); + le->set_text(graph->input_node_get_name(type,p_id)); + le->connect("text_entered",this,"_input_name_changed",varray(p_id,le)); + SpinBox *sb = memnew( SpinBox ); + sb->set_min(-100000); + sb->set_max(100000); + sb->set_step(0.001); + sb->set_val(graph->scalar_input_node_get_value(type,p_id)); + sb->connect("value_changed",this,"_scalar_input_changed",varray(p_id)); + gn->add_child(sb); + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; // scalar uniform (assignable in material) + case ShaderGraph::NODE_VEC_INPUT: { + + gn->set_title("VectorUniform"); + LineEdit *le = memnew( LineEdit ); + gn->add_child(le); + le->set_text(graph->input_node_get_name(type,p_id)); + le->connect("text_entered",this,"_input_name_changed",varray(p_id,le)); + Array v3p(true); + for(int i=0;i<3;i++) { + HBoxContainer *hbc = memnew( HBoxContainer ); + Label *l = memnew( Label ); + l->set_text(String::chr('X'+i)); + hbc->add_child(l); + SpinBox *sb = memnew( SpinBox ); + sb->set_h_size_flags(Control::SIZE_EXPAND_FILL); + sb->set_min(-100000); + sb->set_max(100000); + sb->set_step(0.001); + sb->set_val(graph->vec_input_node_get_value(type,p_id)[i]); + sb->connect("value_changed",this,"_vec_input_changed",varray(p_id,v3p)); + v3p.push_back(sb); + hbc->add_child(sb); + gn->add_child(hbc); + } + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + + } break; // vec3 uniform (assignable in material) + case ShaderGraph::NODE_RGB_INPUT: { + + gn->set_title("ColorUniform"); + LineEdit *le = memnew( LineEdit ); + gn->add_child(le); + le->set_text(graph->input_node_get_name(type,p_id)); + le->connect("text_entered",this,"_input_name_changed",varray(p_id,le)); + ColorPickerButton *cpb = memnew( ColorPickerButton ); + cpb->set_color(graph->rgb_input_node_get_value(type,p_id)); + cpb->connect("color_changed",this,"_rgb_input_changed",varray(p_id)); + gn->add_child(cpb); + Label *l = memnew( Label ); + l->set_text("RGB"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + l = memnew( Label ); + l->set_text("Alpha"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + + gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + + } break; // color uniform (assignable in material) + case ShaderGraph::NODE_XFORM_INPUT: { + gn->set_title("XFUniform"); + LineEdit *le = memnew( LineEdit ); + gn->add_child(le); + le->set_text(graph->input_node_get_name(type,p_id)); + le->connect("text_entered",this,"_input_name_changed",varray(p_id,le)); + ToolButton *edit = memnew( ToolButton ); + edit->set_text("edit.."); + edit->connect("pressed",this,"_xform_input_changed",varray(p_id,edit)); + gn->add_child(edit); + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]); + + } break; // mat4 uniform (assignable in material) + case ShaderGraph::NODE_TEXTURE_INPUT: { + + gn->set_title("TexUniform"); + LineEdit *le = memnew( LineEdit ); + gn->add_child(le); + le->set_text(graph->input_node_get_name(type,p_id)); + le->connect("text_entered",this,"_input_name_changed",varray(p_id,le)); + TextureFrame *tex = memnew( TextureFrame ); + tex->set_expand(true); + tex->set_custom_minimum_size(Size2(80,80)); + gn->add_child(tex); + tex->set_texture(graph->texture_input_node_get_value(type,p_id)); + ToolButton *edit = memnew( ToolButton ); + edit->set_text("edit.."); + edit->connect("pressed",this,"_tex_edited",varray(p_id,edit)); + gn->add_child(edit); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("UV"))); + hbc->add_spacer(); + Label *l=memnew(Label("RGB")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child(l); + gn->add_child(hbc); + l = memnew( Label ); + l->set_text("Alpha"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + + gn->set_slot(3,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(4,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; // texture input (assignable in material) + case ShaderGraph::NODE_CUBEMAP_INPUT: { + + gn->set_title("TexUniform"); + LineEdit *le = memnew( LineEdit ); + gn->add_child(le); + le->set_text(graph->input_node_get_name(type,p_id)); + le->connect("text_entered",this,"_input_name_changed",varray(p_id,le)); + + ToolButton *edit = memnew( ToolButton ); + edit->set_text("edit.."); + edit->connect("pressed",this,"_cube_edited",varray(p_id,edit)); + gn->add_child(edit); + + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + hbc->add_child( memnew(Label("UV"))); + hbc->add_spacer(); + Label *l=memnew(Label("RGB")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child(l); + gn->add_child(hbc); + l = memnew( Label ); + l->set_text("Alpha"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + + gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + } break; // cubemap input (assignable in material) + case ShaderGraph::NODE_OUTPUT: { + gn->set_title("Output"); + + List si; + ShaderGraph::get_input_output_node_slot_info(graph->get_mode(),type,&si); + + int idx=0; + for (List::Element *E=si.front();E;E=E->next()) { + ShaderGraph::SlotInfo& s=E->get(); + if (s.dir==ShaderGraph::SLOT_OUT) { + + Label *l= memnew( Label ); + l->set_text(s.name); + l->set_align(Label::ALIGN_LEFT); + gn->add_child(l); + gn->set_slot(idx,true,s.type,typecol[s.type],false,0,Color()); + idx++; + } + } + + } break; // output (case Shader type dependent) + case ShaderGraph::NODE_COMMENT: { + gn->set_title("Comment"); + TextEdit *te = memnew(TextEdit); + te->set_custom_minimum_size(Size2(100,100)); + gn->add_child(te); + te->set_text(graph->comment_node_get_text(type,p_id)); + te->connect("text_changed",this,"_comment_edited",varray(p_id,te)); + + } break; // comment + + } - return CLICK_NONE; + gn->connect("dragged",this,"_node_moved",varray(p_id)); + gn->connect("close_request",this,"_node_removed",varray(p_id),CONNECT_DEFERRED); + graph_edit->add_child(gn); + node_map[p_id]=gn; + gn->set_offset(graph->node_get_pos(type,p_id)); + print_line("NODE "+itos(p_id)+" OFS "+gn->get_offset()); } -Point2 ShaderEditor::_get_slot_pos(int p_node_id,bool p_input,int p_slot) { +void ShaderGraphView::_update_graph() { - Ref style = get_stylebox("panel","PopupMenu"); - float w = get_node_size(p_node_id).width; - Ref font = get_font("font","PopupMenu"); - float h = font->get_height()+get_constant("vseparation","PopupMenu"); - Ref vec_icon = get_icon("NodeVecSlot","EditorIcons"); - Point2 pos = Point2( shader_graph.node_get_pos_x(p_node_id), shader_graph.node_get_pos_y(p_node_id) )-offset; - pos+=style->get_offset(); - pos.y+=h; - if(p_input) { - - pos.y+=p_slot*h; - pos+=Point2( -vec_icon->get_width()/2.0, h/2.0).floor(); - return pos; - } else { - - pos.y+=VisualServer::shader_get_input_count( shader_graph.node_get_type(p_node_id ) )*h; - } - - pos.y+=p_slot*h; - pos+=Point2( w-style->get_minimum_size().width+vec_icon->get_width()/2.0, h/2.0).floor(); - - return pos; - -} - -void ShaderEditor::_node_edit_property(int p_node) { - - Ref style = get_stylebox("panel","PopupMenu"); - Size2 size = get_node_size(p_node); - Point2 pos = Point2( shader_graph.node_get_pos_x(p_node), shader_graph.node_get_pos_y(p_node) )-offset; - - VisualServer::ShaderNodeType type=shader_graph.node_get_type(p_node); - - PropertyInfo ph = VisualServer::get_singleton()->shader_node_get_type_info(type); - if (ph.type==Variant::NIL) + if (block_update) return; - if (ph.type==Variant::_RID) - ph.type=Variant::OBJECT; - property_editor->edit(NULL,ph.name,ph.type,shader_graph.node_get_param(p_node),ph.hint,ph.hint_string); + for (Map::Element *E=node_map.front();E;E=E->next()) { - Point2 popup_pos=Point2( pos.x+(size.width-property_editor->get_size().width)/2.0,pos.y+(size.y-style->get_margin(MARGIN_BOTTOM))).floor(); - popup_pos+=get_global_pos(); - property_editor->set_pos(popup_pos); - - property_editor->popup(); - -} - -bool ShaderEditor::has_point(const Point2& p_point) const { - - int n,si; - - return _locate_click(p_point,&n,&si)!=CLICK_NONE; -} - -void ShaderEditor::_input_event(InputEvent p_event) { - - switch(p_event.type) { - - case InputEvent::MOUSE_BUTTON: { - - if (p_event.mouse_button.pressed) { - - - if (p_event.mouse_button.button_index==1) { - click_pos=Point2(p_event.mouse_button.x,p_event.mouse_button.y); - click_motion=click_pos; - click_type = _locate_click(click_pos,&click_node,&click_slot); - if( click_type!=CLICK_NONE) { - - order.erase(click_node); - order.push_back(click_node); - update(); - } - switch(click_type) { - case CLICK_INPUT_SLOT: { - click_pos=_get_slot_pos(click_node,true,click_slot); - } break; - case CLICK_OUTPUT_SLOT: { - click_pos=_get_slot_pos(click_node,false,click_slot); - } break; - case CLICK_PARAMETER: { - //open editor - _node_edit_property(click_node); - } break; - } - } - if (p_event.mouse_button.button_index==2) { - - if (click_type!=CLICK_NONE) { - click_type=CLICK_NONE; - update(); - } else { - // try to disconnect/remove - - Point2 rclick_pos=Point2(p_event.mouse_button.x,p_event.mouse_button.y); - rclick_type = _locate_click(rclick_pos,&rclick_node,&rclick_slot); - if (rclick_type==CLICK_INPUT_SLOT || rclick_type==CLICK_OUTPUT_SLOT) { - - node_popup->clear(); - node_popup->add_item("Disconnect",NODE_DISCONNECT); - node_popup->set_pos(rclick_pos); - node_popup->popup(); - - } - - if (rclick_type==CLICK_NODE) { - node_popup->clear(); - node_popup->add_item("Remove",NODE_ERASE); - node_popup->set_pos(rclick_pos); - node_popup->popup(); - } - - - } - } - } else { - - if (p_event.mouse_button.button_index==1 && click_type!=CLICK_NONE) { - - switch(click_type) { - case CLICK_INPUT_SLOT: - case CLICK_OUTPUT_SLOT: { - - Point2 dst_click_pos=Point2(p_event.mouse_button.x,p_event.mouse_button.y); - int id; - int slot; - ClickType dst_click_type = _locate_click(dst_click_pos,&id,&slot); - if (dst_click_type==CLICK_INPUT_SLOT && click_type==CLICK_OUTPUT_SLOT) { - - shader_graph.connect(click_node,click_slot,id,slot); - - Error err = validate_graph(); - if (err==ERR_CYCLIC_LINK) - shader_graph.disconnect(click_node,click_slot,id,slot); - _write_shader_graph(); - - } - if (click_type==CLICK_INPUT_SLOT && dst_click_type==CLICK_OUTPUT_SLOT) { - - shader_graph.connect(id,slot,click_node,click_slot); - - Error err = validate_graph(); - if (err==ERR_CYCLIC_LINK) - shader_graph.disconnect(id,slot,click_node,click_slot); - _write_shader_graph(); - } - - } break; - case CLICK_NODE: { - int new_x=shader_graph.node_get_pos_x(click_node)+(click_motion.x-click_pos.x); - int new_y=shader_graph.node_get_pos_y(click_node)+(click_motion.y-click_pos.y); - shader_graph.node_set_pos(click_node,new_x,new_y); - _write_shader_graph(); - - } break; - } - - click_type=CLICK_NONE; - update(); - } - } - - } - - case InputEvent::MOUSE_MOTION: { - - if (p_event.mouse_motion.button_mask&1 && click_type!=CLICK_NONE) { - - click_motion=Point2(p_event.mouse_button.x,p_event.mouse_button.y); - update(); - } - - } break; - } -} - -void ShaderEditor::_notification(int p_what) { - - - switch(p_what) { - - case NOTIFICATION_DRAW: { - - _update_scrollbars(); - //VisualServer::get_singleton()->canvas_item_add_rect(get_canvas_item(),Rect2(Point2(),get_size()),Color(0,0,0,1)); - - for(List::Element *E=order.front();E;E=E->next()) { - - _draw_node(E->get()); - } - - if (click_type==CLICK_INPUT_SLOT || click_type==CLICK_OUTPUT_SLOT) { - - VisualServer::get_singleton()->canvas_item_add_line(get_canvas_item(),click_pos,click_motion,Color(0.5,1,0.5,0.8),2); - } - - List connections = shader_graph.get_connection_list(); - for(List::Element *E=connections.front();E;E=E->next()) { - - const ShaderGraph::Connection &c=E->get(); - Point2 source = _get_slot_pos(c.src_id,false,c.src_slot); - Point2 dest = _get_slot_pos(c.dst_id,true,c.dst_slot); - bool vec = VisualServer::shader_is_input_vector( shader_graph.node_get_type(c.dst_id), c.dst_slot ); - Color col = vec?Color(1,0.5,0.5,0.8):Color(1,1,0.5,0.8); - - if (click_type==CLICK_NODE && click_node==c.src_id) { - - source+=click_motion-click_pos; - } - - if (click_type==CLICK_NODE && click_node==c.dst_id) { - - dest+=click_motion-click_pos; - } - - VisualServer::get_singleton()->canvas_item_add_line(get_canvas_item(),source,dest,col,2); - - } - } break; + memdelete(E->get()); } -} + node_map.clear(); -void ShaderEditor::_update_scrollbars() { - - Size2 size = get_size(); - Size2 hmin = h_scroll->get_minimum_size(); - Size2 vmin = v_scroll->get_minimum_size(); - - v_scroll->set_begin( Point2(size.width - vmin.width, 0) ); - v_scroll->set_end( Point2(size.width, size.height) ); - - h_scroll->set_begin( Point2( 0, size.height - hmin.height) ); - h_scroll->set_end( Point2(size.width-vmin.width, size.height) ); + if (!graph.is_valid()) + return; - Size2 min = _get_maximum_size(); + List nl; + graph->get_node_list(type,&nl); + print_line("graph nodes: "+itos(nl.size())); + for(List::Element *E=nl.front();E;E=E->next()) { - if (min.height < size.height - hmin.height) { - - v_scroll->hide(); - offset.y=0; - } else { - - v_scroll->show(); - v_scroll->set_max(min.height); - v_scroll->set_page(size.height - hmin.height); - offset.y=v_scroll->get_val(); + _create_node(E->get()); } + graph_edit->clear_connections(); - if (min.width < size.width - vmin.width) { - - h_scroll->hide(); - offset.x=0; - } else { - - h_scroll->show(); - h_scroll->set_max(min.width); - h_scroll->set_page(size.width - vmin.width); - offset.x=h_scroll->get_val(); - } -} - -void ShaderEditor::_scroll_moved() { - - offset.x=h_scroll->get_val(); - offset.y=v_scroll->get_val(); - update(); -} - -void ShaderEditor::_bind_methods() { - - ObjectTypeDB::bind_method( "_node_menu_item", &ShaderEditor::_node_menu_item ); - ObjectTypeDB::bind_method( "_node_add_callback", &ShaderEditor::_node_add_callback ); - ObjectTypeDB::bind_method( "_input_event", &ShaderEditor::_input_event ); - ObjectTypeDB::bind_method( "_node_param_changed", &ShaderEditor::_node_param_changed ); - ObjectTypeDB::bind_method( "_scroll_moved", &ShaderEditor::_scroll_moved ); - ObjectTypeDB::bind_method( "_vertex_item", &ShaderEditor::_vertex_item ); - ObjectTypeDB::bind_method( "_fragment_item", &ShaderEditor::_fragment_item ); - ObjectTypeDB::bind_method( "_post_item", &ShaderEditor::_post_item ); -} - -void ShaderEditor::_read_shader_graph() { - - shader_graph.clear();; - order.clear(); - List nodes; - shader->get_node_list(&nodes); - int larger_id=0; - for(List::Element *E=nodes.front();E;E=E->next()) { - - if (E->get() > larger_id) - larger_id = E->get(); - - shader_graph.node_add( (VS::ShaderNodeType)shader->node_get_type(E->get()), E->get() ); - shader_graph.node_set_param( E->get(), shader->node_get_param( E->get() ) ); - Point2 pos = shader->node_get_pos(E->get()); - shader_graph.node_set_pos( E->get(), pos.x,pos.y ); - order.push_back(E->get()); - } - - last_id=larger_id+1; - - List connections; - shader->get_connections(&connections); - - for(List::Element *E=connections.front();E;E=E->next()) { - - Shader::Connection &c=E->get(); - shader_graph.connect(c.src_id,c.src_slot,c.dst_id,c.dst_slot); - } - - validate_graph(); - update(); -} - -void ShaderEditor::_write_shader_graph() { - - shader->clear(); - List nodes; - shader_graph.get_node_list(&nodes); - for(List::Element *E=nodes.front();E;E=E->next()) { - - shader->node_add((Shader::NodeType)shader_graph.node_get_type(E->get()),E->get()); - shader->node_set_param(E->get(),shader_graph.node_get_param(E->get())); - shader->node_set_pos(E->get(),Point2( shader_graph.node_get_pos_x(E->get()),shader_graph.node_get_pos_y(E->get()) ) ); - } - - List connections = shader_graph.get_connection_list(); + List connections; + graph->get_node_connections(type,&connections); for(List::Element *E=connections.front();E;E=E->next()) { - const ShaderGraph::Connection &c=E->get(); - shader->connect(c.src_id,c.src_slot,c.dst_id,c.dst_slot); + ERR_CONTINUE(!node_map.has(E->get().src_id) || !node_map.has(E->get().dst_id)); + graph_edit->connect_node(node_map[E->get().src_id]->get_name(),E->get().src_slot,node_map[E->get().dst_id]->get_name(),E->get().dst_slot); } + + + } -void ShaderEditor::_add_node_from_text(const String& p_text) { +void ShaderGraphView::set_graph(Ref p_graph){ - ERR_FAIL_COND( p_text.get_slice_count(" ") != 3 ); - bool input = p_text.get_slice(" ",0)=="In:"; - String name = p_text.get_slice(" ",1); - bool vec = p_text.get_slice(" ",2)=="(vec3)"; + print_line("GRAPH EDIT: "+itos(p_graph.is_valid())); + graph=p_graph; + _update_graph(); - _node_add( input? - ( vec? VisualServer::NODE_VEC_IN : VisualServer::NODE_IN ) : - ( vec? VisualServer::NODE_VEC_OUT : VisualServer::NODE_OUT ) ); - - shader_graph.node_set_param( last_id-1,name ); - _write_shader_graph(); } -void ShaderEditor::_vertex_item(int p_item) { +void ShaderGraphView::_notification(int p_what) { - _add_node_from_text(vertex_popup->get_item_text(p_item)); -} -void ShaderEditor::_fragment_item(int p_item) { + if (p_what==NOTIFICATION_ENTER_TREE) { - _add_node_from_text(fragment_popup->get_item_text(p_item)); -} -void ShaderEditor::_post_item(int p_item) { + ped_popup->connect("variant_changed",this,"_variant_edited"); + } + } - _add_node_from_text(post_popup->get_item_text(p_item)); -} +void ShaderGraphView::add_node(int p_type) { + List existing; + graph->get_node_list(type,&existing); + existing.sort(); + int newid=1; + for(List::Element *E=existing.front();E;E=E->next()) { + if (!E->next() || (E->get()+1!=E->next()->get())){ + newid=E->get()+1; + break; + } + } -void ShaderEditor::_node_menu_item(int p_item) { + Vector2 init_ofs(20,20); + while(true) { + bool valid=true; + for(List::Element *E=existing.front();E;E=E->next()) { + Vector2 pos = graph->node_get_pos(type,E->get()); + if (init_ofs==pos) { + init_ofs+=Vector2(20,20); + valid=false; + break; - switch(p_item) { - - case GRAPH_ADD_NODE: { - add_popup->popup_centered_ratio(); - validate_graph(); - } break; - case NODE_DISCONNECT: { - - if (rclick_type==CLICK_INPUT_SLOT) { - - List connections = shader_graph.get_connection_list(); - for(List::Element *E=connections.front();E;E=E->next()) { - - const ShaderGraph::Connection &c=E->get(); - if( c.dst_id==rclick_node && c.dst_slot==rclick_slot) { - - shader_graph.disconnect(c.src_id,c.src_slot,c.dst_id,c.dst_slot); - } - } - update(); - _write_shader_graph(); - validate_graph(); } + } - if (rclick_type==CLICK_OUTPUT_SLOT) { - - List connections = shader_graph.get_connection_list(); - for(List::Element *E=connections.front();E;E=E->next()) { - - const ShaderGraph::Connection &c=E->get(); - if( c.src_id==rclick_node && c.src_slot==rclick_slot) { - - shader_graph.disconnect(c.src_id,c.src_slot,c.dst_id,c.dst_slot); - } - } - update(); - _write_shader_graph(); - validate_graph(); - } - - } break; - case NODE_ERASE: { - - order.erase(rclick_node); - shader_graph.node_remove(rclick_node); - update(); - _write_shader_graph(); - validate_graph(); - } break; - case GRAPH_CLEAR: { - - order.clear(); - shader_graph.clear(); - last_id=1; - last_x=20; - last_y=20; - update(); - _write_shader_graph(); - validate_graph(); - - } break; + if (valid) + break; } -} - -void ShaderEditor::_node_add(VisualServer::ShaderNodeType p_type) { - - shader_graph.node_add(p_type,last_id ); - shader_graph.node_set_pos(last_id ,last_x,last_y); - String test_param; - - switch(p_type) { - case VS::NODE_PARAMETER: { - - test_param="param"; - } break; - case VS::NODE_VEC_PARAMETER: { - - test_param="vec"; - } break; - case VS::NODE_COLOR_PARAMETER: { - - test_param="color"; - } break; - case VS::NODE_TEXTURE_PARAMETER: { - - test_param="tex"; - } break; - case VS::NODE_TEXTURE_2D_PARAMETER: { - - test_param="tex2D"; - } break; - case VS::NODE_TEXTURE_CUBE_PARAMETER: { - - test_param="cubemap"; - } break; - case VS::NODE_TRANSFORM_PARAMETER: { - test_param="xform"; - } break; - case VS::NODE_LABEL: { - - test_param="label"; - } break; - } - - if(test_param!="") { - - int iter=0; - List l; - - shader_graph.get_node_list(&l); - - bool found; - String test; - do { - iter++; - test=test_param; - if (iter>1) - test+="_"+itos(iter); - found=false; - for(List::Element *E=l.front();E;E=E->next()) { - - - String param = shader_graph.node_get_param( E->get() ); - if (param==test) { - found=true; - break; - } - } - - } while (found); - - - shader_graph.node_set_param(last_id,test); - - } - order.push_back(last_id); - last_x+=10; - last_y+=10; - last_id++; - last_x=last_x % (int)get_size().width; - last_y=last_y % (int)get_size().height; - update(); - add_popup->hide();; - _write_shader_graph(); + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Add Shader Graph Node"); + ur->add_do_method(graph.ptr(),"node_add",type,p_type,newid); + ur->add_do_method(graph.ptr(),"node_set_pos",type,newid,init_ofs); + ur->add_undo_method(graph.ptr(),"node_remove",type,newid); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); } -void ShaderEditor::_node_add_callback() { +void ShaderGraphView::_bind_methods() { + + ObjectTypeDB::bind_method("_update_graph",&ShaderGraphView::_update_graph); + ObjectTypeDB::bind_method("_node_moved",&ShaderGraphView::_node_moved); + ObjectTypeDB::bind_method("_move_node",&ShaderGraphView::_move_node); + ObjectTypeDB::bind_method("_node_removed",&ShaderGraphView::_node_removed); + ObjectTypeDB::bind_method("_connection_request",&ShaderGraphView::_connection_request); + + ObjectTypeDB::bind_method("_scalar_const_changed",&ShaderGraphView::_scalar_const_changed); + ObjectTypeDB::bind_method("_vec_const_changed",&ShaderGraphView::_vec_const_changed); + ObjectTypeDB::bind_method("_rgb_const_changed",&ShaderGraphView::_rgb_const_changed); + ObjectTypeDB::bind_method("_xform_const_changed",&ShaderGraphView::_xform_const_changed); + ObjectTypeDB::bind_method("_scalar_op_changed",&ShaderGraphView::_scalar_op_changed); + ObjectTypeDB::bind_method("_vec_op_changed",&ShaderGraphView::_vec_op_changed); + ObjectTypeDB::bind_method("_vec_scalar_op_changed",&ShaderGraphView::_vec_scalar_op_changed); + ObjectTypeDB::bind_method("_rgb_op_changed",&ShaderGraphView::_rgb_op_changed); + ObjectTypeDB::bind_method("_xform_inv_rev_changed",&ShaderGraphView::_xform_inv_rev_changed); + ObjectTypeDB::bind_method("_scalar_func_changed",&ShaderGraphView::_scalar_func_changed); + ObjectTypeDB::bind_method("_vec_func_changed",&ShaderGraphView::_vec_func_changed); + ObjectTypeDB::bind_method("_scalar_input_changed",&ShaderGraphView::_scalar_input_changed); + ObjectTypeDB::bind_method("_vec_input_changed",&ShaderGraphView::_vec_input_changed); + ObjectTypeDB::bind_method("_xform_input_changed",&ShaderGraphView::_xform_input_changed); + ObjectTypeDB::bind_method("_rgb_input_changed",&ShaderGraphView::_rgb_input_changed); + ObjectTypeDB::bind_method("_tex_input_change",&ShaderGraphView::_tex_input_change); + ObjectTypeDB::bind_method("_cube_input_change",&ShaderGraphView::_cube_input_change); + ObjectTypeDB::bind_method("_input_name_changed",&ShaderGraphView::_input_name_changed); + ObjectTypeDB::bind_method("_tex_edited",&ShaderGraphView::_tex_edited); + ObjectTypeDB::bind_method("_variant_edited",&ShaderGraphView::_variant_edited); + ObjectTypeDB::bind_method("_cube_edited",&ShaderGraphView::_cube_edited); + ObjectTypeDB::bind_method("_comment_edited",&ShaderGraphView::_comment_edited); - TreeItem * item = add_types->get_selected(); - ERR_FAIL_COND(!item); - _node_add((VisualServer::ShaderNodeType)(int)item->get_metadata(0)); - add_popup->hide() ; } -ShaderEditor::ShaderEditor() { +ShaderGraphView::ShaderGraphView(ShaderGraph::ShaderType p_type) { - set_focus_mode(FOCUS_ALL); + type=p_type; + graph_edit = memnew( GraphEdit ); + block_update=false; + ped_popup = memnew( CustomPropertyEditor ); + graph_edit->add_child(ped_popup); - Panel* menu_panel = memnew( Panel ); - menu_panel->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END ); - menu_panel->set_end( Point2(0,22) ); - - add_child( menu_panel ); - - PopupMenu *p; - List defaults; - - MenuButton* node_menu = memnew( MenuButton ); - node_menu->set_text("Graph"); - node_menu->set_pos( Point2( 5,0) ); - menu_panel->add_child( node_menu ); - - p=node_menu->get_popup(); - p->add_item("Add Node",GRAPH_ADD_NODE); - p->add_separator(); - p->add_item("Clear",GRAPH_CLEAR); - p->connect("item_pressed", this,"_node_menu_item"); - - MenuButton* vertex_menu = memnew( MenuButton ); - vertex_menu->set_text("Vertex"); - vertex_menu->set_pos( Point2( 49,0) ); - menu_panel->add_child( vertex_menu ); - - p=vertex_menu->get_popup(); - defaults.clear(); - VisualServer::shader_get_default_input_nodes(VisualServer::SHADER_VERTEX,&defaults); - - int id=0; - for(int i=0;iadd_item("In: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++); - } - p->add_separator(); - id++; - - defaults.clear(); - VisualServer::shader_get_default_output_nodes(VisualServer::SHADER_VERTEX,&defaults); - - for(int i=0;iadd_item("Out: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++); - } - - vertex_popup=p; - vertex_popup->connect("item_pressed", this,"_vertex_item"); - MenuButton* fragment_menu = memnew( MenuButton ); - fragment_menu->set_text("Fragment"); - fragment_menu->set_pos( Point2( 95 ,0) ); - menu_panel->add_child( fragment_menu ); - - p=fragment_menu->get_popup(); - defaults.clear(); - VisualServer::shader_get_default_input_nodes(VisualServer::SHADER_FRAGMENT,&defaults); - id=0; - for(int i=0;iadd_item("In: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++); - } - p->add_separator(); - id++; - defaults.clear(); - VisualServer::shader_get_default_output_nodes(VisualServer::SHADER_FRAGMENT,&defaults); - - for(int i=0;iadd_item("Out: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++); - } - - fragment_popup=p; - fragment_popup->connect("item_pressed", this,"_fragment_item"); - - MenuButton* post_menu = memnew( MenuButton ); - post_menu->set_text("Post"); - post_menu->set_pos( Point2( 161,0) ); - menu_panel->add_child( post_menu ); - - p=post_menu->get_popup(); - defaults.clear(); - VisualServer::shader_get_default_input_nodes(VisualServer::SHADER_POST_PROCESS,&defaults); - id=0; - for(int i=0;iadd_item("In: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++); - } - p->add_separator(); - id++; - - defaults.clear(); - VisualServer::shader_get_default_output_nodes(VisualServer::SHADER_POST_PROCESS,&defaults); - - for(int i=0;iadd_item("Out: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++); - } - - post_popup=p; - post_popup->connect("item_pressed", this,"_post_item"); - - - /* add popup */ - - add_popup = memnew( Popup ); - add_child(add_popup); - add_popup->set_as_toplevel(true); - Panel *add_panel = memnew( Panel ); - add_popup->add_child(add_panel); - add_panel->set_area_as_parent_rect(); - - Label *add_label = memnew (Label ); - add_label->set_pos(Point2(5,5)); - add_label->set_text("Available Nodes:"); - add_panel->add_child(add_label); - - - add_types = memnew( Tree ); - add_types->set_anchor( MARGIN_RIGHT, ANCHOR_END ); - add_types->set_anchor( MARGIN_BOTTOM, ANCHOR_END ); - add_types->set_begin( Point2( 20,25 ) ); - add_types->set_end( Point2( 10, 30 ) ); - add_types->set_hide_root(true); - add_types->set_columns(4); - add_types->set_select_mode(Tree::SELECT_ROW); - - - TreeItem *add_types_root = add_types->create_item(NULL); - TreeItem *info_item = add_types->create_item(add_types_root); - - for(int i=0;icreate_item(add_types_root); - PropertyInfo prop = VisualServer::shader_node_get_type_info((VisualServer::ShaderNodeType)i); - item->set_text(0,prop.name); - item->set_text(1,itos(VisualServer::shader_get_input_count((VisualServer::ShaderNodeType)i))); - item->set_text(2,itos(VisualServer::shader_get_output_count((VisualServer::ShaderNodeType)i))); - String hint = (prop.type==Variant::_RID)?prop.hint_string:Variant::get_type_name(prop.type); - item->set_text(3,hint); - item->set_metadata(0,i); - } - info_item->set_text(0,"::NODE::"); - info_item->set_custom_color(0,Color(0.6,0.1,0.1)); - info_item->set_text(1,"::INPUTS::"); - info_item->set_custom_color(1,Color(0.6,0.1,0.1)); - info_item->set_text(2,"::OUTPUTS::"); - info_item->set_custom_color(2,Color(0.6,0.1,0.1)); - info_item->set_text(3,"::PARAM::"); - info_item->set_custom_color(3,Color(0.6,0.1,0.1)); - info_item->set_selectable(0,false); - info_item->set_selectable(1,false); - info_item->set_selectable(2,false); - info_item->set_selectable(3,false); - - add_panel->add_child(add_types); - - add_confirm = memnew( Button ); - add_confirm->set_anchor( MARGIN_LEFT, ANCHOR_END ); - add_confirm->set_anchor( MARGIN_TOP, ANCHOR_END ); - add_confirm->set_anchor( MARGIN_RIGHT, ANCHOR_END ); - add_confirm->set_anchor( MARGIN_BOTTOM, ANCHOR_END ); - add_confirm->set_begin( Point2( 75, 29 ) ); - add_confirm->set_end( Point2( 10, 15 ) ); - add_confirm->set_text("Add"); - add_panel->add_child(add_confirm); - add_confirm->connect("pressed", this,"_node_add_callback"); - - last_id=1; - last_x=20; - last_y=20; - - property_editor = memnew( CustomPropertyEditor ); - add_child(property_editor); - property_editor->connect("variant_changed", this,"_node_param_changed"); - - h_scroll = memnew( HScrollBar ); - v_scroll = memnew( VScrollBar ); - - add_child(h_scroll); - add_child(v_scroll); - - h_scroll->connect("value_changed", this,"_scroll_moved"); - v_scroll->connect("value_changed", this,"_scroll_moved"); - - node_popup= memnew(PopupMenu ); - add_child(node_popup); - node_popup->set_as_toplevel(true); - - node_popup->connect("item_pressed", this,"_node_menu_item"); } -void ShaderEditorPlugin::edit(Object *p_object) { +//////////////edit////////////// +void ShaderGraphEditor::edit(Ref p_shader) { - shader_editor->edit(p_object->cast_to()); + for(int i=0;iset_graph(p_shader); + } } -bool ShaderEditorPlugin::handles(Object *p_object) const { +void ShaderGraphEditor::_add_node(int p_type) { - return p_object->is_type("Shader"); + ShaderGraph::ShaderType shader_type=ShaderGraph::ShaderType(tabs->get_current_tab()); + + graph_edits[shader_type]->add_node(p_type); } -void ShaderEditorPlugin::make_visible(bool p_visible) { + +void ShaderGraphEditor::_notification(int p_what) { + if (p_what==NOTIFICATION_ENTER_TREE) { + menu->get_popup()->connect("item_pressed",this,"_add_node"); + + + } +} + +void ShaderGraphEditor::_bind_methods() { + + ObjectTypeDB::bind_method("_add_node",&ShaderGraphEditor::_add_node); + +} + + +const char* ShaderGraphEditor::node_names[ShaderGraph::NODE_TYPE_MAX]={ + "Input", // all inputs (shader type dependent) + "Scalar Constant", //scalar constant + "Vector Constant", //vec3 constant + "RGB Constant", //rgb constant (shows a color picker instead) + "XForm Constant", // 4x4 matrix constant + "Time:", // time in seconds + "Screen Sample", // screen texture sampler (takes uv) (only usable in fragment shader) + "Scalar Operator", // scalar vs scalar op (mul", add", div", etc) + "Vector Operator", // vec3 vs vec3 op (mul",ad",div",crossprod",etc) + "Scalar+Vector Operator", // vec3 vs scalar op (mul", add", div", etc) + "RGB Operator:", // vec3 vs vec3 rgb op (with scalar amount)", like brighten", darken", burn", dodge", multiply", etc. + "XForm Multiply", // mat4 x mat4 + "XForm+Vector Multiply", // mat4 x vec3 mult (with no-translation option) + "XForm+Vector InvMultiply:", // mat4 x vec3 inverse mult (with no-translation option) + "Scalar Function", // scalar function (sin", cos", etc) + "Vector Function", // vector function (normalize", negate", reciprocal", rgb2hsv", hsv2rgb", etc", etc) + "Vector Length", // vec3 length + "Dot Product:", // vec3 . vec3 (dot product -> scalar output) + "Vector -> Scalars", // 1 vec3 input", 3 scalar outputs + "Scalars -> Vector", // 3 scalar input", 1 vec3 output + "XForm -> Vectors", // 3 vec input", 1 xform output + "Vectors -> XForm:", // 3 vec input", 1 xform output + "Scalar Interpolate", // scalar interpolation (with optional curve) + "Vector Interpolate:", // vec3 interpolation (with optional curve) + "Scalar Uniform", // scalar uniform (assignable in material) + "Vector Uniform", // vec3 uniform (assignable in material) + "RGB Uniform", // color uniform (assignable in material) + "XForm Uniform", // mat4 uniform (assignable in material) + "Texture Uniform", // texture input (assignable in material) + "CubeMap Uniform:", // cubemap input (assignable in material) + "Output", // output (shader type dependent) + "Comment", // comment + + +}; +ShaderGraphEditor::ShaderGraphEditor() { + + HBoxContainer *hbc = memnew( HBoxContainer ); + menu = memnew( MenuButton ); + menu->set_text("Add.."); + hbc->add_child(menu); + add_child(hbc); + for(int i=0;iget_popup()->add_item(v,i); + if (addsep) + menu->get_popup()->add_separator(); + } + + tabs = memnew(TabContainer); + tabs->set_v_size_flags(SIZE_EXPAND_FILL); + add_child(tabs); + const char* sname[ShaderGraph::SHADER_TYPE_MAX]={ + "Vertex", + "Fragment", + "Light" + }; + for(int i=0;iget_graph_edit()->set_name(sname[i]); + tabs->add_child(graph_edits[i]->get_graph_edit()); + graph_edits[i]->get_graph_edit()->connect("connection_request",graph_edits[i],"_connection_request"); + } + + set_custom_minimum_size(Size2(100,300)); +} + + +void ShaderGraphEditorPlugin::edit(Object *p_object) { + + shader_editor->edit(p_object->cast_to()); +} + +bool ShaderGraphEditorPlugin::handles(Object *p_object) const { + + return p_object->is_type("ShaderGraph"); +} + +void ShaderGraphEditorPlugin::make_visible(bool p_visible) { if (p_visible) { shader_editor->show(); - shader_editor->set_process(true); } else { shader_editor->hide(); - shader_editor->set_process(false); } } -ShaderEditorPlugin::ShaderEditorPlugin(EditorNode *p_node) { +ShaderGraphEditorPlugin::ShaderGraphEditorPlugin(EditorNode *p_node) { editor=p_node; - shader_editor = memnew( ShaderEditor ); - editor->get_viewport()->add_child(shader_editor); - shader_editor->set_area_as_parent_rect(); + shader_editor = memnew( ShaderGraphEditor ); shader_editor->hide(); + SpatialEditor::get_singleton()->get_shader_split()->add_child(shader_editor); +// editor->get_viewport()->add_child(shader_editor); +// shader_editor->set_area_as_parent_rect(); +// shader_editor->hide(); } -ShaderEditorPlugin::~ShaderEditorPlugin() +ShaderGraphEditorPlugin::~ShaderGraphEditorPlugin() { } -#endif + diff --git a/tools/editor/plugins/shader_graph_editor_plugin.h b/tools/editor/plugins/shader_graph_editor_plugin.h index 5b0767dc82b..26dbd1ac6eb 100644 --- a/tools/editor/plugins/shader_graph_editor_plugin.h +++ b/tools/editor/plugins/shader_graph_editor_plugin.h @@ -29,122 +29,121 @@ #ifndef SHADER_GRAPH_EDITOR_PLUGIN_H #define SHADER_GRAPH_EDITOR_PLUGIN_H -#if 0 + #include "tools/editor/editor_plugin.h" #include "tools/editor/editor_node.h" #include "scene/resources/shader.h" #include "servers/visual/shader_graph.h" #include "scene/gui/tree.h" #include "scene/gui/button.h" +#include "scene/gui/graph_edit.h" #include "scene/gui/popup.h" #include "tools/editor/property_editor.h" +#include "scene/resources/shader_graph.h" /** @author Juan Linietsky */ -class ShaderEditor : public Control { - OBJ_TYPE(ShaderEditor, Control ); +class ShaderGraphView : public Node { - enum MenuAction { + OBJ_TYPE(ShaderGraphView,Node); - GRAPH_ADD_NODE, - GRAPH_CLEAR, - NODE_DISCONNECT, - NODE_ERASE, - }; - enum ClickType { - CLICK_NONE, - CLICK_NODE, - CLICK_INPUT_SLOT, - CLICK_OUTPUT_SLOT, - CLICK_PARAMETER - }; + CustomPropertyEditor *ped_popup; + bool block_update; - PopupMenu *node_popup; - Popup *add_popup; - PopupMenu *vertex_popup; - PopupMenu *fragment_popup; - PopupMenu *post_popup; - Tree *add_types; - Button *add_confirm; - HScrollBar *h_scroll; - VScrollBar *v_scroll; + GraphEdit *graph_edit; + Ref graph; + int edited_id; - Ref shader; - List order; - Set active_nodes; - ShaderGraph shader_graph; - int last_x,last_y; - uint32_t last_id; + ShaderGraph::ShaderType type; - CustomPropertyEditor *property_editor; + void _update_graph(); + void _create_node(int p_id); - Point2 offset; - ClickType click_type; - Point2 click_pos; - int click_node; - int click_slot; - Point2 click_motion; - ClickType rclick_type; - int rclick_node; - int rclick_slot; - Size2 _get_maximum_size(); - Size2 get_node_size(int p_node) const; - void _draw_node(int p_node); - void _add_node_from_text(const String& p_text); - void _update_scrollbars(); - void _scroll_moved(); - void _node_param_changed(); - void _node_add_callback(); - void _node_add(VisualServer::ShaderNodeType p_type); - void _node_edit_property(int p_node); - void _node_menu_item(int p_item); - void _vertex_item(int p_item); - void _fragment_item(int p_item); - void _post_item(int p_item); + void _connection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot); + void _node_removed(int p_id); + void _node_moved(const Vector2& p_from, const Vector2& p_to,int p_id); + void _move_node(int p_id,const Vector2& p_to); - ClickType _locate_click(const Point2& p_click,int *p_node_id,int *p_slot_index) const; - Point2 _get_slot_pos(int p_node_id,bool p_input,int p_slot); + void _scalar_const_changed(double p_value,int p_id); + void _vec_const_changed(double p_value, int p_id, Array p_arr); + void _rgb_const_changed(const Color& p_color, int p_id); + void _xform_const_changed(int p_id,Node* p_button); + void _scalar_op_changed(int p_op, int p_id); + void _vec_op_changed(int p_op, int p_id); + void _vec_scalar_op_changed(int p_op, int p_id); + void _rgb_op_changed(int p_op, int p_id); + void _xform_inv_rev_changed(bool p_enabled, int p_id); + void _scalar_func_changed(int p_func, int p_id); + void _vec_func_changed(int p_func, int p_id); + void _scalar_input_changed(double p_value,int p_id); + void _vec_input_changed(double p_value, int p_id, Array p_arr); + void _xform_input_changed(int p_id,Node* p_button); + void _rgb_input_changed(const Color& p_color, int p_id); + void _tex_input_change(int p_id,Node* p_button); + void _cube_input_change(int p_id); + void _input_name_changed(const String& p_name,int p_id,Node* p_line_edit); + void _tex_edited(int p_id,Node* p_button); + void _cube_edited(int p_id,Node* p_button); + void _variant_edited(); + void _comment_edited(int p_id,Node* p_button); - Error validate_graph(); - void _read_shader_graph(); - void _write_shader_graph(); - - virtual bool has_point(const Point2& p_point) const; + Map node_map; protected: void _notification(int p_what); - void _input_event(InputEvent p_event); static void _bind_methods(); public: - void edit(Ref p_shader); - ShaderEditor(); + void add_node(int p_type); + GraphEdit *get_graph_edit() { return graph_edit; } + void set_graph(Ref p_graph); + + ShaderGraphView(ShaderGraph::ShaderType p_type=ShaderGraph::SHADER_TYPE_FRAGMENT); }; -class ShaderEditorPlugin : public EditorPlugin { +class ShaderGraphEditor : public VBoxContainer { - OBJ_TYPE( ShaderEditorPlugin, EditorPlugin ); + OBJ_TYPE(ShaderGraphEditor,VBoxContainer); - ShaderEditor *shader_editor; + MenuButton *menu; + TabContainer *tabs; + ShaderGraphView *graph_edits[ShaderGraph::SHADER_TYPE_MAX]; + static const char* node_names[ShaderGraph::NODE_TYPE_MAX]; + + void _add_node(int p_type); +protected: + void _notification(int p_what); + static void _bind_methods(); +public: + + void edit(Ref p_shader); + ShaderGraphEditor(); +}; + +class ShaderGraphEditorPlugin : public EditorPlugin { + + OBJ_TYPE( ShaderGraphEditorPlugin, EditorPlugin ); + + ShaderGraphEditor *shader_editor; EditorNode *editor; public: - virtual String get_name() const { return "Shader"; } + virtual String get_name() const { return "ShaderGraph"; } bool has_main_screen() const { return false; } virtual void edit(Object *p_node); virtual bool handles(Object *p_node) const; virtual void make_visible(bool p_visible); - ShaderEditorPlugin(EditorNode *p_node); - ~ShaderEditorPlugin(); + ShaderGraphEditorPlugin(EditorNode *p_node); + ~ShaderGraphEditorPlugin(); }; #endif -#endif // SHADER_GRAPH_EDITOR_PLUGIN_H + diff --git a/tools/editor/property_editor.cpp b/tools/editor/property_editor.cpp index 777694481b8..195d3c01a50 100644 --- a/tools/editor/property_editor.cpp +++ b/tools/editor/property_editor.cpp @@ -142,7 +142,7 @@ void CustomPropertyEditor::_menu_option(int p_which) { } String orig_type = res_orig->get_type(); - print_line("orig type: "+orig_type); + Object *inst = ObjectTypeDB::instance( orig_type ); Ref res = Ref( inst->cast_to() ); @@ -187,6 +187,7 @@ void CustomPropertyEditor::_menu_option(int p_which) { ERR_FAIL_COND( inheritors_array.empty() ); + String intype=inheritors_array[p_which-TYPE_BASE_ID]; Object *obj = ObjectTypeDB::instance(intype); @@ -603,6 +604,7 @@ bool CustomPropertyEditor::edit(Object* p_owner,const String& p_name,Variant::Ty if (hint_text!="") { + int idx=0; for(int i=0;inext(); } - int idx=0; for(Set::Element *E=valid_inheritors.front();E;E=E->next()) { String t = E->get(); if (!ObjectTypeDB::can_instance(t)) continue; inheritors_array.push_back(t); + int id = TYPE_BASE_ID+idx; if (has_icon(t,"EditorIcons")) { - menu->add_icon_item(get_icon(t,"EditorIcons"),"New "+t,TYPE_BASE_ID+idx); + menu->add_icon_item(get_icon(t,"EditorIcons"),"New "+t,id); } else { - menu->add_item("New "+t,TYPE_BASE_ID+idx); + menu->add_item("New "+t,id); } idx++; @@ -970,9 +972,11 @@ void CustomPropertyEditor::_action_pressed(int p_which) { if (p_which==0) { + ERR_FAIL_COND( inheritors_array.empty() ); String intype=inheritors_array[0]; + if (hint==PROPERTY_HINT_RESOURCE_TYPE) { From 0e1d70f637c31aa107f109a2e21ec9cd5e82d047 Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 3 Jan 2015 16:55:07 -0300 Subject: [PATCH 33/37] -removed empty control --- scene/gui/empty_control.cpp | 59 ------------------------------------- scene/gui/empty_control.h | 48 ------------------------------ 2 files changed, 107 deletions(-) delete mode 100644 scene/gui/empty_control.cpp delete mode 100644 scene/gui/empty_control.h diff --git a/scene/gui/empty_control.cpp b/scene/gui/empty_control.cpp deleted file mode 100644 index 1e377b2b731..00000000000 --- a/scene/gui/empty_control.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/*************************************************************************/ -/* empty_control.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#include "empty_control.h" - -Size2 EmptyControl::get_minimum_size() const { - - return minsize; -} - -void EmptyControl::set_minsize(const Size2& p_size) { - - minsize=p_size; - minimum_size_changed(); -} - -Size2 EmptyControl::get_minsize() const { - - return minsize; -} - - -void EmptyControl::_bind_methods() { - - - ObjectTypeDB::bind_method(_MD("set_minsize","minsize"),&EmptyControl::set_minsize); - ObjectTypeDB::bind_method(_MD("get_minsize"),&EmptyControl::get_minsize); - - ADD_PROPERTY( PropertyInfo(Variant::VECTOR2,"minsize"), _SCS("set_minsize"),_SCS("get_minsize") ); -} - -EmptyControl::EmptyControl() -{ -} diff --git a/scene/gui/empty_control.h b/scene/gui/empty_control.h deleted file mode 100644 index 993af45ac48..00000000000 --- a/scene/gui/empty_control.h +++ /dev/null @@ -1,48 +0,0 @@ -/*************************************************************************/ -/* empty_control.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* http://www.godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ -#ifndef EMPTY_CONTROL_H -#define EMPTY_CONTROL_H - -#include "scene/gui/control.h" - -class EmptyControl : public Control { - - OBJ_TYPE(EmptyControl,Control); - Size2 minsize; -protected: - static void _bind_methods(); -public: - virtual Size2 get_minimum_size() const; - void set_minsize(const Size2& p_size); - Size2 get_minsize() const; - - EmptyControl(); -}; - -#endif // EMPTY_CONTROL_H From dc7ac86b798f40e1472871391af49a562879eadc Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Sat, 3 Jan 2015 17:24:16 -0300 Subject: [PATCH 34/37] -Completely removed EmptyControl (but added fallback), closes #1017 --- modules/gridmap/grid_map_editor_plugin.cpp | 4 ++-- scene/register_scene_types.cpp | 4 ++-- tools/editor/animation_editor.cpp | 8 ++++---- tools/editor/animation_editor.h | 4 ++-- tools/editor/editor_help.cpp | 4 ++-- tools/editor/editor_log.cpp | 4 ++-- tools/editor/editor_log.h | 4 ++-- tools/editor/editor_node.cpp | 16 ++++++++-------- tools/editor/plugins/tile_map_editor_plugin.cpp | 4 ++-- tools/editor/progress_dialog.cpp | 6 +++--- tools/editor/project_export.cpp | 4 ++-- tools/editor/project_export.h | 2 +- tools/editor/project_manager.cpp | 6 +++--- 13 files changed, 35 insertions(+), 35 deletions(-) diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index 140718a91a4..e621a5e061b 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -1192,8 +1192,8 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { undo_redo=p_editor->get_undo_redo(); int mw = EDITOR_DEF("grid_map/palette_min_width",230); - EmptyControl *ec = memnew( EmptyControl); - ec->set_minsize(Size2(mw,0)); + Control *ec = memnew( Control); + ec->set_custom_minimum_size(Size2(mw,0)); add_child(ec); diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index ee6b481a9fb..cf499791189 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -39,7 +39,6 @@ #include "scene/main/viewport.h" #include "scene/gui/control.h" #include "scene/gui/texture_progress.h" -#include "scene/gui/empty_control.h" #include "scene/gui/button.h" #include "scene/gui/button_array.h" #include "scene/gui/button_group.h" @@ -272,7 +271,8 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init ObjectTypeDB::register_type(); - ObjectTypeDB::register_type(); +// ObjectTypeDB::register_type(); + ObjectTypeDB::add_compatibility_type("EmptyControl","control"); ObjectTypeDB::register_type