diff options
author | Anton Yabchinskiy <arn@bestmx.ru> | 2015-11-02 20:25:01 +0300 |
---|---|---|
committer | Anton Yabchinskiy <arn@bestmx.ru> | 2015-11-02 20:25:01 +0300 |
commit | 3b9868d2e44740c03861c64020a8b5d4d6da031d (patch) | |
tree | 8ff5f9671122f946487848ce286d336c9b650c2c /tools/editor/plugins | |
parent | dc8df8a91a995796f0f330bf6bb6b209f6dfce08 (diff) | |
parent | b2f9acb8c96aed0505cbac21661e21e4acef710f (diff) |
Merge branch 'master' of github.com:okamstudio/godot
Diffstat (limited to 'tools/editor/plugins')
20 files changed, 2964 insertions, 1414 deletions
diff --git a/tools/editor/plugins/animation_player_editor_plugin.cpp b/tools/editor/plugins/animation_player_editor_plugin.cpp index 05b12543d2..f8c484e886 100644 --- a/tools/editor/plugins/animation_player_editor_plugin.cpp +++ b/tools/editor/plugins/animation_player_editor_plugin.cpp @@ -549,6 +549,49 @@ void AnimationPlayerEditor::ensure_visibility() { _animation_edit(); } +Dictionary AnimationPlayerEditor::get_state() const { + + Dictionary d; + + d["visible"]=is_visible(); + if (is_visible() && player) { + d["player"]=EditorNode::get_singleton()->get_edited_scene()->get_path_to(player); + d["animation"]=player->get_current_animation(); + d["editing"]=edit_anim->is_pressed(); + } + + return d; + +} +void AnimationPlayerEditor::set_state(const Dictionary& p_state) { + + if (p_state.has("visible") && p_state["visible"]) { + + Node *n = EditorNode::get_singleton()->get_edited_scene()->get_node(p_state["player"]); + if (n && n->cast_to<AnimationPlayer>()) { + player=n->cast_to<AnimationPlayer>(); + _update_player(); + show(); + set_process(true); + ensure_visibility(); + EditorNode::get_singleton()->animation_panel_make_visible(true); + + if (p_state.has("animation")) { + String anim = p_state["animation"]; + _select_anim_by_name(anim); + if (p_state.has("editing") && p_state["editing"]) { + + edit_anim->set_pressed(true); + _animation_edit(); + } + } + + } + } + +} + + void AnimationPlayerEditor::_animation_resource_edit() { if (animation->get_item_count()) { @@ -1350,6 +1393,7 @@ AnimationPlayerEditorPlugin::AnimationPlayerEditorPlugin(EditorNode *p_node) { editor=p_node; anim_editor = memnew( AnimationPlayerEditor(editor) ); + anim_editor->set_undo_redo(editor->get_undo_redo()); editor->get_animation_panel()->add_child(anim_editor); /* editor->get_viewport()->add_child(anim_editor); diff --git a/tools/editor/plugins/animation_player_editor_plugin.h b/tools/editor/plugins/animation_player_editor_plugin.h index 9f0413088d..5705742565 100644 --- a/tools/editor/plugins/animation_player_editor_plugin.h +++ b/tools/editor/plugins/animation_player_editor_plugin.h @@ -151,6 +151,10 @@ protected: static void _bind_methods(); public: + Dictionary get_state() const; + void set_state(const Dictionary& p_state); + + void ensure_visibility(); void set_undo_redo(UndoRedo *p_undo_redo) { undo_redo=p_undo_redo; } @@ -167,6 +171,9 @@ class AnimationPlayerEditorPlugin : public EditorPlugin { public: + virtual Dictionary get_state() const { return anim_editor->get_state(); } + virtual void set_state(const Dictionary& p_state) { anim_editor->set_state(p_state); } + virtual String get_name() const { return "Anim"; } bool has_main_screen() const { return false; } virtual void edit(Object *p_node); diff --git a/tools/editor/plugins/canvas_item_editor_plugin.cpp b/tools/editor/plugins/canvas_item_editor_plugin.cpp index f2738f0a62..d318f6f6fa 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.cpp +++ b/tools/editor/plugins/canvas_item_editor_plugin.cpp @@ -144,6 +144,9 @@ void CanvasItemEditor::_unhandled_key_input(const InputEvent& p_ev) { if (!is_visible()) return; + if (p_ev.key.mod.control) + // prevent to change tool mode when control key is pressed + return; if (p_ev.key.pressed && !p_ev.key.echo && p_ev.key.scancode==KEY_Q) _tool_select(TOOL_SELECT); if (p_ev.key.pressed && !p_ev.key.echo && p_ev.key.scancode==KEY_W) @@ -1281,7 +1284,7 @@ void CanvasItemEditor::_viewport_input_event(const InputEvent& p_event) { if (p_event.type==InputEvent::MOUSE_MOTION) { - if (!viewport->has_focus()) + if (!viewport->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) viewport->call_deferred("grab_focus"); const InputEventMouseMotion &m=p_event.mouse_motion; @@ -1910,12 +1913,20 @@ void CanvasItemEditor::_notification(int p_what) { List<Node*> &selection = editor_selection->get_selected_node_list(); + bool all_control=true; + bool has_control=false; + for(List<Node*>::Element *E=selection.front();E;E=E->next()) { CanvasItem *canvas_item = E->get()->cast_to<CanvasItem>(); if (!canvas_item || !canvas_item->is_visible()) continue; + if (canvas_item->cast_to<Control>()) + has_control=true; + else + all_control=false; + CanvasItemEditorSelectedItem *se=editor_selection->get_node_editor_data<CanvasItemEditorSelectedItem>(canvas_item); if (!se) continue; @@ -1932,6 +1943,13 @@ void CanvasItemEditor::_notification(int p_what) { } + bool show_anchor = all_control && has_control; + if (show_anchor != !anchor_menu->is_hidden()) { + if (show_anchor) + anchor_menu->show(); + else + anchor_menu->hide(); + } for(Map<ObjectID,BoneList>::Element *E=bone_list.front();E;E=E->next()) { @@ -1974,6 +1992,32 @@ void CanvasItemEditor::_notification(int p_what) { ungroup_button->set_icon(get_icon("Ungroup","EditorIcons")); key_insert_button->set_icon(get_icon("Key","EditorIcons")); + + //anchor_menu->add_icon_override("Align Top Left"); + anchor_menu->set_icon(get_icon("Anchor","EditorIcons")); + PopupMenu *p=anchor_menu->get_popup(); + + p->add_icon_item(get_icon("ControlAlignTopLeft","EditorIcons"),"Top Left",ANCHOR_ALIGN_TOP_LEFT); + p->add_icon_item(get_icon("ControlAlignTopRight","EditorIcons"),"Top Right",ANCHOR_ALIGN_TOP_RIGHT); + p->add_icon_item(get_icon("ControlAlignBottomRight","EditorIcons"),"Bottom Right",ANCHOR_ALIGN_BOTTOM_RIGHT); + p->add_icon_item(get_icon("ControlAlignBottomLeft","EditorIcons"),"Bottom Left",ANCHOR_ALIGN_BOTTOM_LEFT); + p->add_separator(); + p->add_icon_item(get_icon("ControlAlignLeftCenter","EditorIcons"),"Center Left",ANCHOR_ALIGN_CENTER_LEFT); + p->add_icon_item(get_icon("ControlAlignTopCenter","EditorIcons"),"Center Top",ANCHOR_ALIGN_CENTER_TOP); + p->add_icon_item(get_icon("ControlAlignRightCenter","EditorIcons"),"Center Right",ANCHOR_ALIGN_CENTER_RIGHT); + p->add_icon_item(get_icon("ControlAlignBottomCenter","EditorIcons"),"Center Bottom",ANCHOR_ALIGN_CENTER_BOTTOM); + p->add_icon_item(get_icon("ControlAlignCenter","EditorIcons"),"Center",ANCHOR_ALIGN_CENTER); + p->add_separator(); + p->add_icon_item(get_icon("ControlAlignLeftWide","EditorIcons"),"Left Wide",ANCHOR_ALIGN_LEFT_WIDE); + p->add_icon_item(get_icon("ControlAlignTopWide","EditorIcons"),"Top Wide",ANCHOR_ALIGN_TOP_WIDE); + p->add_icon_item(get_icon("ControlAlignRightWide","EditorIcons"),"Right Wide",ANCHOR_ALIGN_RIGHT_WIDE); + p->add_icon_item(get_icon("ControlAlignBottomWide","EditorIcons"),"Bottom Wide",ANCHOR_ALIGN_BOTTOM_WIDE); + p->add_icon_item(get_icon("ControlVcenterWide","EditorIcons"),"VCenter Wide ",ANCHOR_ALIGN_VCENTER_WIDE); + p->add_icon_item(get_icon("ControlHcenterWide","EditorIcons"),"HCenter Wide ",ANCHOR_ALIGN_HCENTER_WIDE); + p->add_separator(); + p->add_icon_item(get_icon("ControlAlignWide","EditorIcons"),"Full Rect",ANCHOR_ALIGN_WIDE); + + } if (p_what==NOTIFICATION_READY) { @@ -2179,6 +2223,27 @@ void CanvasItemEditor::_update_scroll(float) { } +void CanvasItemEditor::_set_anchor(Control::AnchorType p_left,Control::AnchorType p_top,Control::AnchorType p_right,Control::AnchorType p_bottom) { + List<Node*> &selection = editor_selection->get_selected_node_list(); + + undo_redo->create_action("Change Anchors"); + for(List<Node*>::Element *E=selection.front();E;E=E->next()) { + + Control *c = E->get()->cast_to<Control>(); + + undo_redo->add_do_method(c,"set_anchor",MARGIN_LEFT,p_left); + undo_redo->add_do_method(c,"set_anchor",MARGIN_TOP,p_top); + undo_redo->add_do_method(c,"set_anchor",MARGIN_RIGHT,p_right); + undo_redo->add_do_method(c,"set_anchor",MARGIN_BOTTOM,p_bottom); + undo_redo->add_undo_method(c,"set_anchor",MARGIN_LEFT,c->get_anchor(MARGIN_LEFT)); + undo_redo->add_undo_method(c,"set_anchor",MARGIN_TOP,c->get_anchor(MARGIN_TOP)); + undo_redo->add_undo_method(c,"set_anchor",MARGIN_RIGHT,c->get_anchor(MARGIN_RIGHT)); + undo_redo->add_undo_method(c,"set_anchor",MARGIN_BOTTOM,c->get_anchor(MARGIN_BOTTOM)); + } + + undo_redo->commit_action(); + +} void CanvasItemEditor::_popup_callback(int p_op) { @@ -2381,6 +2446,56 @@ void CanvasItemEditor::_popup_callback(int p_op) { case SPACE_VERTICAL: { //space_selected_items< proj_vector2_y, compare_items_y >(); } break; + case ANCHOR_ALIGN_TOP_LEFT: { + _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_BEGIN); + } break; + case ANCHOR_ALIGN_TOP_RIGHT: { + _set_anchor(ANCHOR_END,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_BEGIN); + } break; + case ANCHOR_ALIGN_BOTTOM_LEFT: { + _set_anchor(ANCHOR_BEGIN,ANCHOR_END,ANCHOR_BEGIN,ANCHOR_END); + } break; + case ANCHOR_ALIGN_BOTTOM_RIGHT: { + _set_anchor(ANCHOR_END,ANCHOR_END,ANCHOR_END,ANCHOR_END); + } break; + case ANCHOR_ALIGN_CENTER_LEFT: { + _set_anchor(ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_BEGIN,ANCHOR_CENTER); + } break; + case ANCHOR_ALIGN_CENTER_RIGHT: { + + _set_anchor(ANCHOR_END,ANCHOR_CENTER,ANCHOR_END,ANCHOR_CENTER); + } break; + case ANCHOR_ALIGN_CENTER_TOP: { + _set_anchor(ANCHOR_CENTER,ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_BEGIN); + } break; + case ANCHOR_ALIGN_CENTER_BOTTOM: { + _set_anchor(ANCHOR_CENTER,ANCHOR_END,ANCHOR_CENTER,ANCHOR_END); + } break; + case ANCHOR_ALIGN_CENTER: { + _set_anchor(ANCHOR_CENTER,ANCHOR_CENTER,ANCHOR_CENTER,ANCHOR_CENTER); + } break; + case ANCHOR_ALIGN_TOP_WIDE: { + _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_BEGIN); + } break; + case ANCHOR_ALIGN_LEFT_WIDE: { + _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_END); + } break; + case ANCHOR_ALIGN_RIGHT_WIDE: { + _set_anchor(ANCHOR_END,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_END); + } break; + case ANCHOR_ALIGN_BOTTOM_WIDE: { + _set_anchor(ANCHOR_BEGIN,ANCHOR_END,ANCHOR_END,ANCHOR_END); + } break; + case ANCHOR_ALIGN_VCENTER_WIDE: { + _set_anchor(ANCHOR_CENTER,ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_END); + } break; + case ANCHOR_ALIGN_HCENTER_WIDE: { + _set_anchor(ANCHOR_BEGIN,ANCHOR_CENTER,ANCHOR_END,ANCHOR_CENTER); + } break; + case ANCHOR_ALIGN_WIDE: { + _set_anchor(ANCHOR_BEGIN,ANCHOR_BEGIN,ANCHOR_END,ANCHOR_END); + } break; + case ANIM_INSERT_KEY: case ANIM_INSERT_KEY_EXISTING: { @@ -2999,6 +3114,14 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p->add_item("Center Selection", VIEW_CENTER_TO_SELECTION, KEY_F); p->add_item("Frame Selection", VIEW_FRAME_TO_SELECTION, KEY_MASK_CMD|KEY_F); + anchor_menu = memnew( MenuButton ); + anchor_menu->set_text("Anchor"); + hb->add_child(anchor_menu); + anchor_menu->get_popup()->connect("item_pressed", this,"_popup_callback"); + anchor_menu->hide(); + + //p = anchor_menu->get_popup(); + animation_hb = memnew( HBoxContainer ); diff --git a/tools/editor/plugins/canvas_item_editor_plugin.h b/tools/editor/plugins/canvas_item_editor_plugin.h index 48a34e2d07..485422028e 100644 --- a/tools/editor/plugins/canvas_item_editor_plugin.h +++ b/tools/editor/plugins/canvas_item_editor_plugin.h @@ -90,6 +90,23 @@ class CanvasItemEditor : public VBoxContainer { UNGROUP_SELECTED, ALIGN_HORIZONTAL, ALIGN_VERTICAL, + ANCHOR_ALIGN_TOP_LEFT, + ANCHOR_ALIGN_TOP_RIGHT, + ANCHOR_ALIGN_BOTTOM_LEFT, + ANCHOR_ALIGN_BOTTOM_RIGHT, + ANCHOR_ALIGN_CENTER_LEFT, + ANCHOR_ALIGN_CENTER_RIGHT, + ANCHOR_ALIGN_CENTER_TOP, + ANCHOR_ALIGN_CENTER_BOTTOM, + ANCHOR_ALIGN_CENTER, + ANCHOR_ALIGN_TOP_WIDE, + ANCHOR_ALIGN_LEFT_WIDE, + ANCHOR_ALIGN_RIGHT_WIDE, + ANCHOR_ALIGN_BOTTOM_WIDE, + ANCHOR_ALIGN_VCENTER_WIDE, + ANCHOR_ALIGN_HCENTER_WIDE, + ANCHOR_ALIGN_WIDE, + SPACE_HORIZONTAL, SPACE_VERTICAL, EXPAND_TO_PARENT, @@ -225,6 +242,7 @@ class CanvasItemEditor : public VBoxContainer { MenuButton *view_menu; HBoxContainer *animation_hb; MenuButton *animation_menu; + MenuButton *anchor_menu; Button *key_loc_button; Button *key_rot_button; @@ -305,6 +323,8 @@ class CanvasItemEditor : public VBoxContainer { void _viewport_input_event(const InputEvent& p_event); void _viewport_draw(); + void _set_anchor(Control::AnchorType p_left,Control::AnchorType p_top,Control::AnchorType p_right,Control::AnchorType p_bottom); + HSplitContainer *palette_split; VSplitContainer *bottom_split; diff --git a/tools/editor/plugins/editor_preview_plugins.cpp b/tools/editor/plugins/editor_preview_plugins.cpp index a77ba9a605..c2b3ecfcda 100644 --- a/tools/editor/plugins/editor_preview_plugins.cpp +++ b/tools/editor/plugins/editor_preview_plugins.cpp @@ -25,7 +25,7 @@ Ref<Texture> EditorTexturePreviewPlugin::generate(const RES& p_from) { if (img.is_compressed()) { if (img.decompress()!=OK) return Ref<Texture>(); - } else if (img.get_format()!=Image::FORMAT_RGB && img.get_format()!=Image::FORMAT_RGB) { + } else if (img.get_format()!=Image::FORMAT_RGB && img.get_format()!=Image::FORMAT_RGBA) { img.convert(Image::FORMAT_RGBA); } diff --git a/tools/editor/plugins/mesh_editor_plugin.cpp b/tools/editor/plugins/mesh_editor_plugin.cpp index 2c64b2eb6b..13d4c8db5a 100644 --- a/tools/editor/plugins/mesh_editor_plugin.cpp +++ b/tools/editor/plugins/mesh_editor_plugin.cpp @@ -216,6 +216,8 @@ MeshInstanceEditor::MeshInstanceEditor() { SpatialEditor::get_singleton()->add_control_to_menu_panel(options); options->set_text("Mesh"); + options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("MeshInstance","EditorIcons")); + options->get_popup()->add_item("Create Trimesh Static Body",MENU_OPTION_CREATE_STATIC_TRIMESH_BODY); options->get_popup()->add_item("Create Convex Static Body",MENU_OPTION_CREATE_STATIC_CONVEX_BODY); options->get_popup()->add_separator(); diff --git a/tools/editor/plugins/multimesh_editor_plugin.cpp b/tools/editor/plugins/multimesh_editor_plugin.cpp index 0df906117e..3c88b1d3a8 100644 --- a/tools/editor/plugins/multimesh_editor_plugin.cpp +++ b/tools/editor/plugins/multimesh_editor_plugin.cpp @@ -330,6 +330,8 @@ MultiMeshEditor::MultiMeshEditor() { options->set_area_as_parent_rect(); options->set_text("MultiMesh"); + options->set_icon(EditorNode::get_singleton()->get_gui_base()->get_icon("MultiMeshInstance","EditorIcons")); + options->get_popup()->add_item("Populate Surface"); options->get_popup()->connect("item_pressed", this,"_menu_option"); diff --git a/tools/editor/plugins/particles_2d_editor_plugin.cpp b/tools/editor/plugins/particles_2d_editor_plugin.cpp index fdf534a3a8..dadfa8bfdc 100644 --- a/tools/editor/plugins/particles_2d_editor_plugin.cpp +++ b/tools/editor/plugins/particles_2d_editor_plugin.cpp @@ -146,6 +146,7 @@ void Particles2DEditorPlugin::_notification(int p_what) { if (p_what==NOTIFICATION_ENTER_TREE) { menu->get_popup()->connect("item_pressed",this,"_menu_callback"); + menu->set_icon(menu->get_popup()->get_icon("Particles2D","EditorIcons")); file->connect("file_selected",this,"_file_selected"); } } diff --git a/tools/editor/plugins/particles_editor_plugin.cpp b/tools/editor/plugins/particles_editor_plugin.cpp index f6f01d82ca..5c84d9a86a 100644 --- a/tools/editor/plugins/particles_editor_plugin.cpp +++ b/tools/editor/plugins/particles_editor_plugin.cpp @@ -111,6 +111,7 @@ void ParticlesEditor::_populate() { void ParticlesEditor::_notification(int p_notification) { if (p_notification==NOTIFICATION_ENTER_TREE) { + options->set_icon(options->get_popup()->get_icon("Particles","EditorIcons")); } } diff --git a/tools/editor/plugins/path_editor_plugin.cpp b/tools/editor/plugins/path_editor_plugin.cpp index 4af22e956f..f4bdf50fe9 100644 --- a/tools/editor/plugins/path_editor_plugin.cpp +++ b/tools/editor/plugins/path_editor_plugin.cpp @@ -1,597 +1,597 @@ -/*************************************************************************/
-/* path_editor_plugin.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2015 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 "path_editor_plugin.h"
-#include "spatial_editor_plugin.h"
-#include "scene/resources/curve.h"
-#include "os/keyboard.h"
-
-String PathSpatialGizmo::get_handle_name(int p_idx) const {
-
- Ref<Curve3D> c = path->get_curve();
- if (c.is_null())
- return "";
-
- if (p_idx<c->get_point_count()) {
-
- return "Curve Point #"+itos(p_idx);
- }
-
- p_idx=p_idx-c->get_point_count()+1;
-
- int idx=p_idx/2;
- int t=p_idx%2;
- String n = "Curve Point #"+itos(idx);
- if (t==0)
- n+=" In";
- else
- n+=" Out";
-
- return n;
-
-
-}
-Variant PathSpatialGizmo::get_handle_value(int p_idx) const{
-
- Ref<Curve3D> c = path->get_curve();
- if (c.is_null())
- return Variant();
-
- if (p_idx<c->get_point_count()) {
-
- original=c->get_point_pos(p_idx);
- return original;
- }
-
- p_idx=p_idx-c->get_point_count()+1;
-
- int idx=p_idx/2;
- int t=p_idx%2;
-
- Vector3 ofs;
- if (t==0)
- ofs=c->get_point_in(idx);
- else
- ofs= c->get_point_out(idx);
-
- original=ofs+c->get_point_pos(idx);
-
- return ofs;
-
-}
-void PathSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){
-
- Ref<Curve3D> c = path->get_curve();
- if (c.is_null())
- return;
-
- Transform gt = path->get_global_transform();
- Transform gi = gt.affine_inverse();
- Vector3 ray_from = p_camera->project_ray_origin(p_point);
- Vector3 ray_dir = p_camera->project_ray_normal(p_point);
-
- if (p_idx<c->get_point_count()) {
-
- Plane p(gt.xform(original),p_camera->get_transform().basis.get_axis(2));
-
- Vector3 inters;
-
- if (p.intersects_ray(ray_from,ray_dir,&inters)) {
-
- Vector3 local = gi.xform(inters);
- c->set_point_pos(p_idx,local);
- }
-
- return;
- }
-
- p_idx=p_idx-c->get_point_count()+1;
-
- int idx=p_idx/2;
- int t=p_idx%2;
-
- Vector3 base = c->get_point_pos(idx);
-
- Plane p(gt.xform(original),p_camera->get_transform().basis.get_axis(2));
-
- Vector3 inters;
-
- if (p.intersects_ray(ray_from,ray_dir,&inters)) {
-
- Vector3 local = gi.xform(inters)-base;
- if (t==0) {
- c->set_point_in(idx,local);
- } else {
- c->set_point_out(idx,local);
- }
- }
-
-}
-
-void PathSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){
-
- Ref<Curve3D> c = path->get_curve();
- if (c.is_null())
- return;
-
- UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo();
-
- if (p_idx<c->get_point_count()) {
-
- if (p_cancel) {
-
- c->set_point_pos(p_idx,p_restore);
- return;
- }
- ur->create_action("Set Curve Point Pos");
- ur->add_do_method(c.ptr(),"set_point_pos",p_idx,c->get_point_pos(p_idx));
- ur->add_undo_method(c.ptr(),"set_point_pos",p_idx,p_restore);
- ur->commit_action();
-
- return;
- }
-
- p_idx=p_idx-c->get_point_count()+1;
-
- int idx=p_idx/2;
- int t=p_idx%2;
-
- Vector3 ofs;
-
- if (p_cancel) {
-
-
-
- return;
- }
-
-
-
- if (t==0) {
-
- if (p_cancel) {
-
- c->set_point_in(p_idx,p_restore);
- return;
- }
- ur->create_action("Set Curve In Pos");
- ur->add_do_method(c.ptr(),"set_point_in",idx,c->get_point_in(idx));
- ur->add_undo_method(c.ptr(),"set_point_in",idx,p_restore);
- ur->commit_action();
-
-
- } else {
- if (p_cancel) {
-
- c->set_point_out(idx,p_restore);
- return;
- }
- ur->create_action("Set Curve Out Pos");
- ur->add_do_method(c.ptr(),"set_point_out",idx,c->get_point_out(idx));
- ur->add_undo_method(c.ptr(),"set_point_out",idx,p_restore);
- ur->commit_action();
-
- }
-
-}
-
-
-void PathSpatialGizmo::redraw(){
-
- clear();
-
- Ref<Curve3D> c = path->get_curve();
- if (c.is_null())
- return;
-
- Vector3Array v3a=c->tesselate();
- //Vector3Array v3a=c->get_baked_points();
-
- int v3s = v3a.size();
- if (v3s==0)
- return;
- Vector<Vector3> v3p;
- Vector3Array::Read r = v3a.read();
-
- for(int i=0;i<v3s-1;i++) {
-
- v3p.push_back(r[i]);
- v3p.push_back(r[i+1]);
- //v3p.push_back(r[i]);
- //v3p.push_back(r[i]+Vector3(0,0.2,0));
- }
-
- add_lines(v3p,PathEditorPlugin::singleton->path_material);
- add_collision_segments(v3p);
-
- if (PathEditorPlugin::singleton->get_edited_path()==path) {
- v3p.clear();
- Vector<Vector3> handles;
- Vector<Vector3> sec_handles;
-
- for(int i=0;i<c->get_point_count();i++) {
-
- Vector3 p = c->get_point_pos(i);
- handles.push_back(p);
- if (i>0) {
- v3p.push_back(p);
- v3p.push_back(p+c->get_point_in(i));
- sec_handles.push_back(p+c->get_point_in(i));
- }
-
- if (i<c->get_point_count()-1) {
- v3p.push_back(p);
- v3p.push_back(p+c->get_point_out(i));
- sec_handles.push_back(p+c->get_point_out(i));
- }
- }
-
- add_lines(v3p,PathEditorPlugin::singleton->path_thin_material);
- add_handles(handles);
- add_handles(sec_handles,false,true);
- }
-
-}
-
-PathSpatialGizmo::PathSpatialGizmo(Path* p_path){
-
- path=p_path;
- set_spatial_node(p_path);
-
-
-
-}
-
-bool PathEditorPlugin::create_spatial_gizmo(Spatial* p_spatial) {
-
- if (p_spatial->cast_to<Path>()) {
-
-
- Ref<PathSpatialGizmo> psg = memnew( PathSpatialGizmo(p_spatial->cast_to<Path>()));
- p_spatial->set_gizmo(psg);
- return true;
- }
-
- return false;
-}
-
-bool PathEditorPlugin::forward_spatial_input_event(Camera* p_camera,const InputEvent& p_event) {
-
- if (!path)
- return false;
- Ref<Curve3D> c=path->get_curve();
- if (c.is_null())
- return false;
- Transform gt = path->get_global_transform();
- Transform it = gt.affine_inverse();
-
- static const int click_dist = 10; //should make global
-
-
- if (p_event.type==InputEvent::MOUSE_BUTTON) {
-
- const InputEventMouseButton &mb=p_event.mouse_button;
- Point2 mbpos(mb.x,mb.y);
-
- if (mb.pressed && mb.button_index==BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb.mod.control))) {
- //click into curve, break it down
- Vector3Array v3a = c->tesselate();
- int idx=0;
- int rc=v3a.size();
- int closest_seg=-1;
- Vector3 closest_seg_point;
- float closest_d=1e20;
-
- if (rc>=2) {
- Vector3Array::Read r = v3a.read();
-
- if (p_camera->unproject_position(gt.xform(c->get_point_pos(0))).distance_to(mbpos)<click_dist)
- return false; //nope, existing
-
-
- for(int i=0;i<c->get_point_count()-1;i++) {
- //find the offset and point index of the place to break up
- int j=idx;
- if (p_camera->unproject_position(gt.xform(c->get_point_pos(i+1))).distance_to(mbpos)<click_dist)
- return false; //nope, existing
-
-
- while(j<rc && c->get_point_pos(i+1)!=r[j]) {
-
- Vector3 from =r[j];
- Vector3 to =r[j+1];
- real_t cdist = from.distance_to(to);
- from=gt.xform(from);
- to=gt.xform(to);
- if (cdist>0) {
- Vector2 s[2];
- s[0] = p_camera->unproject_position(from);
- s[1] = p_camera->unproject_position(to);
- Vector2 inters = Geometry::get_closest_point_to_segment_2d(mbpos,s);
- float d = inters.distance_to(mbpos);
-
- if (d<10 && d<closest_d) {
-
-
- closest_d=d;
- closest_seg=i;
- Vector3 ray_from=p_camera->project_ray_origin(mbpos);
- Vector3 ray_dir=p_camera->project_ray_normal(mbpos);
-
- Vector3 ra,rb;
- Geometry::get_closest_points_between_segments(ray_from,ray_from+ray_dir*4096,from,to,ra,rb);
-
- closest_seg_point=it.xform(rb);
- }
-
- }
- j++;
-
- }
- if (idx==j)
- idx++; //force next
- else
- idx=j; //swap
-
-
- if (j==rc)
- break;
- }
- }
-
- UndoRedo *ur = editor->get_undo_redo();
- if (closest_seg!=-1) {
- //subdivide
-
- ur->create_action("Split Path");
- ur->add_do_method(c.ptr(),"add_point",closest_seg_point,Vector3(),Vector3(),closest_seg+1);
- ur->add_undo_method(c.ptr(),"remove_point",closest_seg+1);
- ur->commit_action();;
- return true;
-
- } else {
-
- Vector3 org;
- if (c->get_point_count()==0)
- org=path->get_transform().get_origin();
- else
- org=gt.xform(c->get_point_pos(c->get_point_count()));
- Plane p(org,p_camera->get_transform().basis.get_axis(2));
- Vector3 ray_from=p_camera->project_ray_origin(mbpos);
- Vector3 ray_dir=p_camera->project_ray_normal(mbpos);
-
- Vector3 inters;
- if (p.intersects_ray(ray_from,ray_dir,&inters)) {
-
- ur->create_action("Add Point to Curve");
- ur->add_do_method(c.ptr(),"add_point",it.xform(inters),Vector3(),Vector3(),-1);
- ur->add_undo_method(c.ptr(),"remove_point",c->get_point_count());
- ur->commit_action();;
- return true;
- }
-
- //add new at pos
- }
-
- } else if (mb.pressed && ((mb.button_index==BUTTON_LEFT && curve_del->is_pressed()) || (mb.button_index==BUTTON_RIGHT && curve_edit->is_pressed()))) {
-
- int erase_idx=-1;
- for(int i=0;i<c->get_point_count();i++) {
- //find the offset and point index of the place to break up
- if (p_camera->unproject_position(gt.xform(c->get_point_pos(i))).distance_to(mbpos)<click_dist) {
-
- erase_idx=i;
- break;
- }
- }
-
- if (erase_idx!=-1) {
-
- UndoRedo *ur = editor->get_undo_redo();
- ur->create_action("Remove Path Point");
- ur->add_do_method(c.ptr(),"remove_point",erase_idx);
- ur->add_undo_method(c.ptr(),"add_point",c->get_point_pos(erase_idx),c->get_point_in(erase_idx),c->get_point_out(erase_idx),erase_idx);
- ur->commit_action();
- return true;
- }
- }
-
- }
-
- return false;
-}
-
-
-void PathEditorPlugin::edit(Object *p_object) {
-
- if (p_object) {
- path=p_object->cast_to<Path>();
- if (path) {
-
- if (path->get_curve().is_valid()) {
- path->get_curve()->emit_signal("changed");
- }
- }
- } else {
- Path *pre=path;
- path=NULL;
- if (pre) {
- pre->get_curve()->emit_signal("changed");
- }
- }
-// collision_polygon_editor->edit(p_object->cast_to<Node>());
-}
-
-bool PathEditorPlugin::handles(Object *p_object) const {
-
- return p_object->is_type("Path");
-}
-
-void PathEditorPlugin::make_visible(bool p_visible) {
-
- if (p_visible) {
-
- curve_create->show();
- curve_edit->show();
- curve_del->show();
- curve_close->show();
- sep->show();
- } else {
-
- curve_create->hide();
- curve_edit->hide();
- curve_del->hide();
- curve_close->hide();
- sep->hide();
-
- {
- Path *pre=path;
- path=NULL;
- if (pre && pre->get_curve().is_valid()) {
- pre->get_curve()->emit_signal("changed");
- }
- }
- }
-
-}
-
-void PathEditorPlugin::_mode_changed(int p_idx) {
-
- curve_create->set_pressed(p_idx==0);
- curve_edit->set_pressed(p_idx==1);
- curve_del->set_pressed(p_idx==2);
-}
-
-void PathEditorPlugin::_close_curve() {
-
- Ref<Curve3D> c = path->get_curve();
- if (c.is_null())
- return ;
- if (c->get_point_count()<2)
- return;
- c->add_point(c->get_point_pos(0),c->get_point_in(0),c->get_point_out(0));
-
-}
-
-void PathEditorPlugin::_notification(int p_what) {
-
- if (p_what==NOTIFICATION_ENTER_TREE) {
-
- curve_create->connect("pressed",this,"_mode_changed",make_binds(0));
- curve_edit->connect("pressed",this,"_mode_changed",make_binds(1));
- curve_del->connect("pressed",this,"_mode_changed",make_binds(2));
- curve_close->connect("pressed",this,"_close_curve");
- }
-}
-
-void PathEditorPlugin::_bind_methods() {
-
- ObjectTypeDB::bind_method(_MD("_mode_changed"),&PathEditorPlugin::_mode_changed);
- ObjectTypeDB::bind_method(_MD("_close_curve"),&PathEditorPlugin::_close_curve);
-}
-
-PathEditorPlugin* PathEditorPlugin::singleton=NULL;
-
-
-PathEditorPlugin::PathEditorPlugin(EditorNode *p_node) {
-
- path=NULL;
- editor=p_node;
- singleton=this;
-
- path_material = Ref<FixedMaterial>( memnew( FixedMaterial ));
- path_material->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(0.5,0.5,1.0,0.8) );
- path_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
- path_material->set_line_width(3);
- path_material->set_flag(Material::FLAG_DOUBLE_SIDED,true);
- path_material->set_flag(Material::FLAG_UNSHADED,true);
-
- path_thin_material = Ref<FixedMaterial>( memnew( FixedMaterial ));
- path_thin_material->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(0.5,0.5,1.0,0.4) );
- path_thin_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true);
- path_thin_material->set_line_width(1);
- path_thin_material->set_flag(Material::FLAG_DOUBLE_SIDED,true);
- path_thin_material->set_flag(Material::FLAG_UNSHADED,true);
-
- SpatialEditor::get_singleton()->add_gizmo_plugin(this);
-
- sep = memnew( VSeparator);
- sep->hide();
- SpatialEditor::get_singleton()->add_control_to_menu_panel(sep);
- curve_edit = memnew( ToolButton );
- curve_edit->set_icon(SpatialEditor::get_singleton()->get_icon("CurveEdit","EditorIcons"));
- curve_edit->set_toggle_mode(true);
- curve_edit->hide();
- curve_edit->set_focus_mode(Control::FOCUS_NONE);
- curve_edit->set_tooltip("Select Points\nShift+Drag: Select Control Points\n"+keycode_get_string(KEY_MASK_CMD)+"Click: Add Point\nRight Click: Delete Point.");
- SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_edit);
- curve_create = memnew( ToolButton );
- curve_create->set_icon(SpatialEditor::get_singleton()->get_icon("CurveCreate","EditorIcons"));
- curve_create->set_toggle_mode(true);
- curve_create->hide();
- curve_create->set_focus_mode(Control::FOCUS_NONE);
- curve_create->set_tooltip("Add Point (in empty space)\nSplit Segment (in curve).");
- SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_create);
- curve_del = memnew( ToolButton );
- curve_del->set_icon(SpatialEditor::get_singleton()->get_icon("CurveDelete","EditorIcons"));
- curve_del->set_toggle_mode(true);
- curve_del->hide();
- curve_del->set_focus_mode(Control::FOCUS_NONE);
- curve_del->set_tooltip("Delete Point.");
- SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_del);
- curve_close = memnew( ToolButton );
- curve_close->set_icon(SpatialEditor::get_singleton()->get_icon("CurveClose","EditorIcons"));
- curve_close->hide();
- curve_close->set_focus_mode(Control::FOCUS_NONE);
- curve_close->set_tooltip("Close Curve");
- SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_close);
-
-
-
- curve_edit->set_pressed(true);
- /*
- collision_polygon_editor = memnew( PathEditor(p_node) );
- editor->get_viewport()->add_child(collision_polygon_editor);
-
- collision_polygon_editor->set_margin(MARGIN_LEFT,200);
- collision_polygon_editor->set_margin(MARGIN_RIGHT,230);
- collision_polygon_editor->set_margin(MARGIN_TOP,0);
- collision_polygon_editor->set_margin(MARGIN_BOTTOM,10);
-
-
- collision_polygon_editor->hide();
- */
-
-
-}
-
-
-PathEditorPlugin::~PathEditorPlugin()
-{
-}
-
+/*************************************************************************/ +/* path_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2015 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 "path_editor_plugin.h" +#include "spatial_editor_plugin.h" +#include "scene/resources/curve.h" +#include "os/keyboard.h" + +String PathSpatialGizmo::get_handle_name(int p_idx) const { + + Ref<Curve3D> c = path->get_curve(); + if (c.is_null()) + return ""; + + if (p_idx<c->get_point_count()) { + + return "Curve Point #"+itos(p_idx); + } + + p_idx=p_idx-c->get_point_count()+1; + + int idx=p_idx/2; + int t=p_idx%2; + String n = "Curve Point #"+itos(idx); + if (t==0) + n+=" In"; + else + n+=" Out"; + + return n; + + +} +Variant PathSpatialGizmo::get_handle_value(int p_idx) const{ + + Ref<Curve3D> c = path->get_curve(); + if (c.is_null()) + return Variant(); + + if (p_idx<c->get_point_count()) { + + original=c->get_point_pos(p_idx); + return original; + } + + p_idx=p_idx-c->get_point_count()+1; + + int idx=p_idx/2; + int t=p_idx%2; + + Vector3 ofs; + if (t==0) + ofs=c->get_point_in(idx); + else + ofs= c->get_point_out(idx); + + original=ofs+c->get_point_pos(idx); + + return ofs; + +} +void PathSpatialGizmo::set_handle(int p_idx,Camera *p_camera, const Point2& p_point){ + + Ref<Curve3D> c = path->get_curve(); + if (c.is_null()) + return; + + Transform gt = path->get_global_transform(); + Transform gi = gt.affine_inverse(); + Vector3 ray_from = p_camera->project_ray_origin(p_point); + Vector3 ray_dir = p_camera->project_ray_normal(p_point); + + if (p_idx<c->get_point_count()) { + + Plane p(gt.xform(original),p_camera->get_transform().basis.get_axis(2)); + + Vector3 inters; + + if (p.intersects_ray(ray_from,ray_dir,&inters)) { + + Vector3 local = gi.xform(inters); + c->set_point_pos(p_idx,local); + } + + return; + } + + p_idx=p_idx-c->get_point_count()+1; + + int idx=p_idx/2; + int t=p_idx%2; + + Vector3 base = c->get_point_pos(idx); + + Plane p(gt.xform(original),p_camera->get_transform().basis.get_axis(2)); + + Vector3 inters; + + if (p.intersects_ray(ray_from,ray_dir,&inters)) { + + Vector3 local = gi.xform(inters)-base; + if (t==0) { + c->set_point_in(idx,local); + } else { + c->set_point_out(idx,local); + } + } + +} + +void PathSpatialGizmo::commit_handle(int p_idx,const Variant& p_restore,bool p_cancel){ + + Ref<Curve3D> c = path->get_curve(); + if (c.is_null()) + return; + + UndoRedo *ur = SpatialEditor::get_singleton()->get_undo_redo(); + + if (p_idx<c->get_point_count()) { + + if (p_cancel) { + + c->set_point_pos(p_idx,p_restore); + return; + } + ur->create_action("Set Curve Point Pos"); + ur->add_do_method(c.ptr(),"set_point_pos",p_idx,c->get_point_pos(p_idx)); + ur->add_undo_method(c.ptr(),"set_point_pos",p_idx,p_restore); + ur->commit_action(); + + return; + } + + p_idx=p_idx-c->get_point_count()+1; + + int idx=p_idx/2; + int t=p_idx%2; + + Vector3 ofs; + + if (p_cancel) { + + + + return; + } + + + + if (t==0) { + + if (p_cancel) { + + c->set_point_in(p_idx,p_restore); + return; + } + ur->create_action("Set Curve In Pos"); + ur->add_do_method(c.ptr(),"set_point_in",idx,c->get_point_in(idx)); + ur->add_undo_method(c.ptr(),"set_point_in",idx,p_restore); + ur->commit_action(); + + + } else { + if (p_cancel) { + + c->set_point_out(idx,p_restore); + return; + } + ur->create_action("Set Curve Out Pos"); + ur->add_do_method(c.ptr(),"set_point_out",idx,c->get_point_out(idx)); + ur->add_undo_method(c.ptr(),"set_point_out",idx,p_restore); + ur->commit_action(); + + } + +} + + +void PathSpatialGizmo::redraw(){ + + clear(); + + Ref<Curve3D> c = path->get_curve(); + if (c.is_null()) + return; + + Vector3Array v3a=c->tesselate(); + //Vector3Array v3a=c->get_baked_points(); + + int v3s = v3a.size(); + if (v3s==0) + return; + Vector<Vector3> v3p; + Vector3Array::Read r = v3a.read(); + + for(int i=0;i<v3s-1;i++) { + + v3p.push_back(r[i]); + v3p.push_back(r[i+1]); + //v3p.push_back(r[i]); + //v3p.push_back(r[i]+Vector3(0,0.2,0)); + } + + add_lines(v3p,PathEditorPlugin::singleton->path_material); + add_collision_segments(v3p); + + if (PathEditorPlugin::singleton->get_edited_path()==path) { + v3p.clear(); + Vector<Vector3> handles; + Vector<Vector3> sec_handles; + + for(int i=0;i<c->get_point_count();i++) { + + Vector3 p = c->get_point_pos(i); + handles.push_back(p); + if (i>0) { + v3p.push_back(p); + v3p.push_back(p+c->get_point_in(i)); + sec_handles.push_back(p+c->get_point_in(i)); + } + + if (i<c->get_point_count()-1) { + v3p.push_back(p); + v3p.push_back(p+c->get_point_out(i)); + sec_handles.push_back(p+c->get_point_out(i)); + } + } + + add_lines(v3p,PathEditorPlugin::singleton->path_thin_material); + add_handles(handles); + add_handles(sec_handles,false,true); + } + +} + +PathSpatialGizmo::PathSpatialGizmo(Path* p_path){ + + path=p_path; + set_spatial_node(p_path); + + + +} + +bool PathEditorPlugin::create_spatial_gizmo(Spatial* p_spatial) { + + if (p_spatial->cast_to<Path>()) { + + + Ref<PathSpatialGizmo> psg = memnew( PathSpatialGizmo(p_spatial->cast_to<Path>())); + p_spatial->set_gizmo(psg); + return true; + } + + return false; +} + +bool PathEditorPlugin::forward_spatial_input_event(Camera* p_camera,const InputEvent& p_event) { + + if (!path) + return false; + Ref<Curve3D> c=path->get_curve(); + if (c.is_null()) + return false; + Transform gt = path->get_global_transform(); + Transform it = gt.affine_inverse(); + + static const int click_dist = 10; //should make global + + + if (p_event.type==InputEvent::MOUSE_BUTTON) { + + const InputEventMouseButton &mb=p_event.mouse_button; + Point2 mbpos(mb.x,mb.y); + + if (mb.pressed && mb.button_index==BUTTON_LEFT && (curve_create->is_pressed() || (curve_edit->is_pressed() && mb.mod.control))) { + //click into curve, break it down + Vector3Array v3a = c->tesselate(); + int idx=0; + int rc=v3a.size(); + int closest_seg=-1; + Vector3 closest_seg_point; + float closest_d=1e20; + + if (rc>=2) { + Vector3Array::Read r = v3a.read(); + + if (p_camera->unproject_position(gt.xform(c->get_point_pos(0))).distance_to(mbpos)<click_dist) + return false; //nope, existing + + + for(int i=0;i<c->get_point_count()-1;i++) { + //find the offset and point index of the place to break up + int j=idx; + if (p_camera->unproject_position(gt.xform(c->get_point_pos(i+1))).distance_to(mbpos)<click_dist) + return false; //nope, existing + + + while(j<rc && c->get_point_pos(i+1)!=r[j]) { + + Vector3 from =r[j]; + Vector3 to =r[j+1]; + real_t cdist = from.distance_to(to); + from=gt.xform(from); + to=gt.xform(to); + if (cdist>0) { + Vector2 s[2]; + s[0] = p_camera->unproject_position(from); + s[1] = p_camera->unproject_position(to); + Vector2 inters = Geometry::get_closest_point_to_segment_2d(mbpos,s); + float d = inters.distance_to(mbpos); + + if (d<10 && d<closest_d) { + + + closest_d=d; + closest_seg=i; + Vector3 ray_from=p_camera->project_ray_origin(mbpos); + Vector3 ray_dir=p_camera->project_ray_normal(mbpos); + + Vector3 ra,rb; + Geometry::get_closest_points_between_segments(ray_from,ray_from+ray_dir*4096,from,to,ra,rb); + + closest_seg_point=it.xform(rb); + } + + } + j++; + + } + if (idx==j) + idx++; //force next + else + idx=j; //swap + + + if (j==rc) + break; + } + } + + UndoRedo *ur = editor->get_undo_redo(); + if (closest_seg!=-1) { + //subdivide + + ur->create_action("Split Path"); + ur->add_do_method(c.ptr(),"add_point",closest_seg_point,Vector3(),Vector3(),closest_seg+1); + ur->add_undo_method(c.ptr(),"remove_point",closest_seg+1); + ur->commit_action();; + return true; + + } else { + + Vector3 org; + if (c->get_point_count()==0) + org=path->get_transform().get_origin(); + else + org=gt.xform(c->get_point_pos(c->get_point_count())); + Plane p(org,p_camera->get_transform().basis.get_axis(2)); + Vector3 ray_from=p_camera->project_ray_origin(mbpos); + Vector3 ray_dir=p_camera->project_ray_normal(mbpos); + + Vector3 inters; + if (p.intersects_ray(ray_from,ray_dir,&inters)) { + + ur->create_action("Add Point to Curve"); + ur->add_do_method(c.ptr(),"add_point",it.xform(inters),Vector3(),Vector3(),-1); + ur->add_undo_method(c.ptr(),"remove_point",c->get_point_count()); + ur->commit_action();; + return true; + } + + //add new at pos + } + + } else if (mb.pressed && ((mb.button_index==BUTTON_LEFT && curve_del->is_pressed()) || (mb.button_index==BUTTON_RIGHT && curve_edit->is_pressed()))) { + + int erase_idx=-1; + for(int i=0;i<c->get_point_count();i++) { + //find the offset and point index of the place to break up + if (p_camera->unproject_position(gt.xform(c->get_point_pos(i))).distance_to(mbpos)<click_dist) { + + erase_idx=i; + break; + } + } + + if (erase_idx!=-1) { + + UndoRedo *ur = editor->get_undo_redo(); + ur->create_action("Remove Path Point"); + ur->add_do_method(c.ptr(),"remove_point",erase_idx); + ur->add_undo_method(c.ptr(),"add_point",c->get_point_pos(erase_idx),c->get_point_in(erase_idx),c->get_point_out(erase_idx),erase_idx); + ur->commit_action(); + return true; + } + } + + } + + return false; +} + + +void PathEditorPlugin::edit(Object *p_object) { + + if (p_object) { + path=p_object->cast_to<Path>(); + if (path) { + + if (path->get_curve().is_valid()) { + path->get_curve()->emit_signal("changed"); + } + } + } else { + Path *pre=path; + path=NULL; + if (pre) { + pre->get_curve()->emit_signal("changed"); + } + } +// collision_polygon_editor->edit(p_object->cast_to<Node>()); +} + +bool PathEditorPlugin::handles(Object *p_object) const { + + return p_object->is_type("Path"); +} + +void PathEditorPlugin::make_visible(bool p_visible) { + + if (p_visible) { + + curve_create->show(); + curve_edit->show(); + curve_del->show(); + curve_close->show(); + sep->show(); + } else { + + curve_create->hide(); + curve_edit->hide(); + curve_del->hide(); + curve_close->hide(); + sep->hide(); + + { + Path *pre=path; + path=NULL; + if (pre && pre->get_curve().is_valid()) { + pre->get_curve()->emit_signal("changed"); + } + } + } + +} + +void PathEditorPlugin::_mode_changed(int p_idx) { + + curve_create->set_pressed(p_idx==0); + curve_edit->set_pressed(p_idx==1); + curve_del->set_pressed(p_idx==2); +} + +void PathEditorPlugin::_close_curve() { + + Ref<Curve3D> c = path->get_curve(); + if (c.is_null()) + return ; + if (c->get_point_count()<2) + return; + c->add_point(c->get_point_pos(0),c->get_point_in(0),c->get_point_out(0)); + +} + +void PathEditorPlugin::_notification(int p_what) { + + if (p_what==NOTIFICATION_ENTER_TREE) { + + curve_create->connect("pressed",this,"_mode_changed",make_binds(0)); + curve_edit->connect("pressed",this,"_mode_changed",make_binds(1)); + curve_del->connect("pressed",this,"_mode_changed",make_binds(2)); + curve_close->connect("pressed",this,"_close_curve"); + } +} + +void PathEditorPlugin::_bind_methods() { + + ObjectTypeDB::bind_method(_MD("_mode_changed"),&PathEditorPlugin::_mode_changed); + ObjectTypeDB::bind_method(_MD("_close_curve"),&PathEditorPlugin::_close_curve); +} + +PathEditorPlugin* PathEditorPlugin::singleton=NULL; + + +PathEditorPlugin::PathEditorPlugin(EditorNode *p_node) { + + path=NULL; + editor=p_node; + singleton=this; + + path_material = Ref<FixedMaterial>( memnew( FixedMaterial )); + path_material->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(0.5,0.5,1.0,0.8) ); + path_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true); + path_material->set_line_width(3); + path_material->set_flag(Material::FLAG_DOUBLE_SIDED,true); + path_material->set_flag(Material::FLAG_UNSHADED,true); + + path_thin_material = Ref<FixedMaterial>( memnew( FixedMaterial )); + path_thin_material->set_parameter( FixedMaterial::PARAM_DIFFUSE,Color(0.5,0.5,1.0,0.4) ); + path_thin_material->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA, true); + path_thin_material->set_line_width(1); + path_thin_material->set_flag(Material::FLAG_DOUBLE_SIDED,true); + path_thin_material->set_flag(Material::FLAG_UNSHADED,true); + + SpatialEditor::get_singleton()->add_gizmo_plugin(this); + + sep = memnew( VSeparator); + sep->hide(); + SpatialEditor::get_singleton()->add_control_to_menu_panel(sep); + curve_edit = memnew( ToolButton ); + curve_edit->set_icon(SpatialEditor::get_singleton()->get_icon("CurveEdit","EditorIcons")); + curve_edit->set_toggle_mode(true); + curve_edit->hide(); + curve_edit->set_focus_mode(Control::FOCUS_NONE); + curve_edit->set_tooltip("Select Points\nShift+Drag: Select Control Points\n"+keycode_get_string(KEY_MASK_CMD)+"Click: Add Point\nRight Click: Delete Point."); + SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_edit); + curve_create = memnew( ToolButton ); + curve_create->set_icon(SpatialEditor::get_singleton()->get_icon("CurveCreate","EditorIcons")); + curve_create->set_toggle_mode(true); + curve_create->hide(); + curve_create->set_focus_mode(Control::FOCUS_NONE); + curve_create->set_tooltip("Add Point (in empty space)\nSplit Segment (in curve)."); + SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_create); + curve_del = memnew( ToolButton ); + curve_del->set_icon(SpatialEditor::get_singleton()->get_icon("CurveDelete","EditorIcons")); + curve_del->set_toggle_mode(true); + curve_del->hide(); + curve_del->set_focus_mode(Control::FOCUS_NONE); + curve_del->set_tooltip("Delete Point."); + SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_del); + curve_close = memnew( ToolButton ); + curve_close->set_icon(SpatialEditor::get_singleton()->get_icon("CurveClose","EditorIcons")); + curve_close->hide(); + curve_close->set_focus_mode(Control::FOCUS_NONE); + curve_close->set_tooltip("Close Curve"); + SpatialEditor::get_singleton()->add_control_to_menu_panel(curve_close); + + + + curve_edit->set_pressed(true); + /* + collision_polygon_editor = memnew( PathEditor(p_node) ); + editor->get_viewport()->add_child(collision_polygon_editor); + + collision_polygon_editor->set_margin(MARGIN_LEFT,200); + collision_polygon_editor->set_margin(MARGIN_RIGHT,230); + collision_polygon_editor->set_margin(MARGIN_TOP,0); + collision_polygon_editor->set_margin(MARGIN_BOTTOM,10); + + + collision_polygon_editor->hide(); + */ + + +} + + +PathEditorPlugin::~PathEditorPlugin() +{ +} + diff --git a/tools/editor/plugins/polygon_2d_editor_plugin.cpp b/tools/editor/plugins/polygon_2d_editor_plugin.cpp index d25880fdff..3029dcf2ab 100644 --- a/tools/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/tools/editor/plugins/polygon_2d_editor_plugin.cpp @@ -50,6 +50,9 @@ void Polygon2DEditor::_notification(int p_what) { uv_button[UV_MODE_ROTATE]->set_icon(get_icon("ToolRotate","EditorIcons")); uv_button[UV_MODE_SCALE]->set_icon(get_icon("ToolScale","EditorIcons")); + b_snap_grid->set_icon( get_icon("Grid", "EditorIcons")); + b_snap_enable->set_icon( get_icon("Snap", "EditorIcons")); + uv_icon_zoom->set_texture( get_icon("Zoom", "EditorIcons")); } break; case NOTIFICATION_FIXED_PROCESS: { @@ -158,6 +161,41 @@ void Polygon2DEditor::_menu_option(int p_option) { } } +void Polygon2DEditor::_set_use_snap(bool p_use) +{ + use_snap=p_use; +} + +void Polygon2DEditor::_set_show_grid(bool p_show) +{ + snap_show_grid=p_show; + uv_edit_draw->update(); +} + +void Polygon2DEditor::_set_snap_off_x(float p_val) +{ + snap_offset.x=p_val; + uv_edit_draw->update(); +} + +void Polygon2DEditor::_set_snap_off_y(float p_val) +{ + snap_offset.y=p_val; + uv_edit_draw->update(); +} + +void Polygon2DEditor::_set_snap_step_x(float p_val) +{ + snap_step.x=p_val; + uv_edit_draw->update(); +} + +void Polygon2DEditor::_set_snap_step_y(float p_val) +{ + snap_step.y=p_val; + uv_edit_draw->update(); +} + void Polygon2DEditor::_wip_close() { undo_redo->create_action("Create Poly"); @@ -494,7 +532,7 @@ void Polygon2DEditor::_uv_input(const InputEvent& p_input) { Vector2 tuv=mtx.xform(uv_prev[i]); if (tuv.distance_to(Vector2(mb.x,mb.y))<8) { - + uv_drag_from=tuv; uv_drag_index=i; } } @@ -545,7 +583,7 @@ void Polygon2DEditor::_uv_input(const InputEvent& p_input) { } else if (uv_drag) { - Vector2 uv_drag_to(mm.x,mm.y); + Vector2 uv_drag_to=snap_point(Vector2(mm.x,mm.y)); Vector2 drag = mtx.affine_inverse().xform(uv_drag_to) - mtx.affine_inverse().xform(uv_drag_from); @@ -649,6 +687,33 @@ void Polygon2DEditor::_uv_draw() { uv_edit_draw->draw_texture(base_tex,Point2()); VS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(),Matrix32()); + if (snap_show_grid) { + Size2 s = uv_edit_draw->get_size(); + int last_cell; + + if (snap_step.x!=0) { + for(int i=0;i<s.width;i++) { + int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(i,0)).x-snap_offset.x)/snap_step.x)); + if (i==0) + last_cell=cell; + if (last_cell!=cell) + uv_edit_draw->draw_line(Point2(i,0),Point2(i,s.height),Color(0.3,0.7,1,0.3)); + last_cell=cell; + } + } + + if (snap_step.y!=0) { + for(int i=0;i<s.height;i++) { + int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(0,i)).y-snap_offset.y)/snap_step.y)); + if (i==0) + last_cell=cell; + if (last_cell!=cell) + uv_edit_draw->draw_line(Point2(0,i),Point2(s.width,i),Color(0.3,0.7,1,0.3)); + last_cell=cell; + } + } + } + DVector<Vector2> uvs = node->get_uv(); Ref<Texture> handle = get_icon("EditorHandle","EditorIcons"); @@ -720,8 +785,27 @@ void Polygon2DEditor::_bind_methods() { ObjectTypeDB::bind_method(_MD("_uv_input"),&Polygon2DEditor::_uv_input); ObjectTypeDB::bind_method(_MD("_uv_scroll_changed"),&Polygon2DEditor::_uv_scroll_changed); ObjectTypeDB::bind_method(_MD("_node_removed"),&Polygon2DEditor::_node_removed); + ObjectTypeDB::bind_method(_MD("_set_use_snap"),&Polygon2DEditor::_set_use_snap); + ObjectTypeDB::bind_method(_MD("_set_show_grid"),&Polygon2DEditor::_set_show_grid); + ObjectTypeDB::bind_method(_MD("_set_snap_off_x"),&Polygon2DEditor::_set_snap_off_x); + ObjectTypeDB::bind_method(_MD("_set_snap_off_y"),&Polygon2DEditor::_set_snap_off_y); + ObjectTypeDB::bind_method(_MD("_set_snap_step_x"),&Polygon2DEditor::_set_snap_step_x); + ObjectTypeDB::bind_method(_MD("_set_snap_step_y"),&Polygon2DEditor::_set_snap_step_y); + +} +inline float _snap_scalar(float p_offset, float p_step, float p_target) { + return p_step != 0 ? Math::stepify(p_target - p_offset, p_step) + p_offset : p_target; +} + +Vector2 Polygon2DEditor::snap_point(Vector2 p_target) const { + if (use_snap) { + p_target.x = _snap_scalar(snap_offset.x*uv_draw_zoom-uv_draw_ofs.x, snap_step.x*uv_draw_zoom, p_target.x); + p_target.y = _snap_scalar(snap_offset.y*uv_draw_zoom-uv_draw_ofs.y, snap_step.y*uv_draw_zoom, p_target.y); + } + + return p_target; } Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) { @@ -731,6 +815,10 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) { editor=p_editor; undo_redo = editor->get_undo_redo(); + snap_step=Vector2(10,10); + use_snap=false; + snap_show_grid=false; + add_child( memnew( VSeparator )); button_create = memnew( ToolButton ); add_child(button_create); @@ -800,9 +888,72 @@ Polygon2DEditor::Polygon2DEditor(EditorNode *p_editor) { uv_menu->get_popup()->add_separator(); uv_menu->get_popup()->add_item("Clear UV",UVEDIT_UV_CLEAR); uv_menu->get_popup()->connect("item_pressed",this,"_menu_option"); + + uv_mode_hb->add_child( memnew( VSeparator )); + + b_snap_enable = memnew( ToolButton ); + uv_mode_hb->add_child(b_snap_enable); + b_snap_enable->set_text("Snap"); + b_snap_enable->set_focus_mode(FOCUS_NONE); + b_snap_enable->set_toggle_mode(true); + b_snap_enable->set_pressed(use_snap); + b_snap_enable->set_tooltip("Enable Snap"); + b_snap_enable->connect("toggled",this,"_set_use_snap"); + + b_snap_grid = memnew( ToolButton ); + uv_mode_hb->add_child(b_snap_grid); + b_snap_grid->set_text("Grid"); + b_snap_grid->set_focus_mode(FOCUS_NONE); + b_snap_grid->set_toggle_mode(true); + b_snap_grid->set_pressed(snap_show_grid); + b_snap_grid->set_tooltip("Show Grid"); + b_snap_grid->connect("toggled",this,"_set_show_grid"); + + uv_mode_hb->add_child( memnew( VSeparator )); + uv_mode_hb->add_child( memnew( Label("Grid Offset:") ) ); + + SpinBox *sb_off_x = memnew( SpinBox ); + sb_off_x->set_min(-256); + sb_off_x->set_max(256); + sb_off_x->set_step(1); + sb_off_x->set_val(snap_offset.x); + sb_off_x->set_suffix("px"); + sb_off_x->connect("value_changed", this, "_set_snap_off_x"); + uv_mode_hb->add_child(sb_off_x); + + SpinBox *sb_off_y = memnew( SpinBox ); + sb_off_y->set_min(-256); + sb_off_y->set_max(256); + sb_off_y->set_step(1); + sb_off_y->set_val(snap_offset.y); + sb_off_y->set_suffix("px"); + sb_off_y->connect("value_changed", this, "_set_snap_off_y"); + uv_mode_hb->add_child(sb_off_y); + + uv_mode_hb->add_child( memnew( VSeparator )); + uv_mode_hb->add_child( memnew( Label("Grid Step:") ) ); + + SpinBox *sb_step_x = memnew( SpinBox ); + sb_step_x->set_min(-256); + sb_step_x->set_max(256); + sb_step_x->set_step(1); + sb_step_x->set_val(snap_step.x); + sb_step_x->set_suffix("px"); + sb_step_x->connect("value_changed", this, "_set_snap_step_x"); + uv_mode_hb->add_child(sb_step_x); + + SpinBox *sb_step_y = memnew( SpinBox ); + sb_step_y->set_min(-256); + sb_step_y->set_max(256); + sb_step_y->set_step(1); + sb_step_y->set_val(snap_step.y); + sb_step_y->set_suffix("px"); + sb_step_y->connect("value_changed", this, "_set_snap_step_y"); + uv_mode_hb->add_child(sb_step_y); + uv_mode_hb->add_child( memnew( VSeparator )); uv_icon_zoom = memnew( TextureFrame ); - uv_main_hb->add_child( uv_icon_zoom ); + uv_mode_hb->add_child( uv_icon_zoom ); uv_zoom = memnew( HSlider ); uv_zoom->set_min(0.01); uv_zoom->set_max(4); diff --git a/tools/editor/plugins/polygon_2d_editor_plugin.h b/tools/editor/plugins/polygon_2d_editor_plugin.h index 8f807cb7e8..0939c44264 100644 --- a/tools/editor/plugins/polygon_2d_editor_plugin.h +++ b/tools/editor/plugins/polygon_2d_editor_plugin.h @@ -41,6 +41,8 @@ class Polygon2DEditor : public HBoxContainer { UVMode uv_mode; AcceptDialog *uv_edit; ToolButton *uv_button[4]; + ToolButton *b_snap_enable; + ToolButton *b_snap_grid; Control *uv_edit_draw; HSlider *uv_zoom; SpinBox *uv_zoom_value; @@ -78,6 +80,11 @@ class Polygon2DEditor : public HBoxContainer { Vector<Vector2> wip; bool wip_active; + bool use_snap; + bool snap_show_grid; + Vector2 snap_offset; + Vector2 snap_step; + void _uv_scroll_changed(float); void _uv_input(const InputEvent& p_input); void _uv_draw(); @@ -86,10 +93,20 @@ class Polygon2DEditor : public HBoxContainer { void _canvas_draw(); void _menu_option(int p_option); + void _set_use_snap(bool p_use); + void _set_show_grid(bool p_show); + void _set_snap_off_x(float p_val); + void _set_snap_off_y(float p_val); + void _set_snap_step_x(float p_val); + void _set_snap_step_y(float p_val); + protected: void _notification(int p_what); void _node_removed(Node *p_node); static void _bind_methods(); + + Vector2 snap_point(Vector2 p_target) const; + public: bool forward_input_event(const InputEvent& p_event); diff --git a/tools/editor/plugins/script_editor_plugin.cpp b/tools/editor/plugins/script_editor_plugin.cpp index 3ef240e74c..bd0f580a34 100644 --- a/tools/editor/plugins/script_editor_plugin.cpp +++ b/tools/editor/plugins/script_editor_plugin.cpp @@ -211,7 +211,6 @@ void ScriptEditorQuickOpen::_bind_methods() { ObjectTypeDB::bind_method(_MD("_confirmed"),&ScriptEditorQuickOpen::_confirmed); ObjectTypeDB::bind_method(_MD("_sbox_input"),&ScriptEditorQuickOpen::_sbox_input); - ADD_SIGNAL(MethodInfo("goto_line",PropertyInfo(Variant::INT,"line"))); } @@ -547,6 +546,10 @@ void ScriptEditor::_show_debugger(bool p_show) { } +void ScriptEditor::_script_created(Ref<Script> p_script) { + editor->push_item(p_script.operator->()); +} + void ScriptEditor::_goto_script_line2(int p_line) { int selected = tab_container->get_current_tab(); @@ -574,7 +577,7 @@ void ScriptEditor::_close_current_tab() { int selected = tab_container->get_current_tab(); if (selected<0 || selected>=tab_container->get_child_count()) return; - + ScriptTextEditor *current = tab_container->get_child(selected)->cast_to<ScriptTextEditor>(); if (!current) return; @@ -753,7 +756,6 @@ void ScriptEditor::_menu_option(int p_option) { if (p_option==FILE_OPEN) { - editor->open_resource("Script"); return; } @@ -766,8 +768,11 @@ void ScriptEditor::_menu_option(int p_option) { return; switch(p_option) { + case FILE_NEW: { + script_create_dialog->config("Node", ".gd"); + script_create_dialog->popup_centered(Size2(300, 300)); + } break; case FILE_SAVE: { - if (!_test_script_times_on_disk()) return; editor->save_resource( current->get_edited_script() ); @@ -1101,6 +1106,7 @@ void ScriptEditor::_menu_option(int p_option) { int line=current->get_text_edit()->cursor_get_line(); bool dobreak = !current->get_text_edit()->is_line_set_as_breakpoint(line); current->get_text_edit()->set_line_as_breakpoint(line,dobreak); + get_debugger()->set_breakpoint(current->get_edited_script()->get_path(),line+1,dobreak); } break; case DEBUG_NEXT: { @@ -1418,6 +1424,7 @@ void ScriptEditor::_bind_methods() { ObjectTypeDB::bind_method("_update_script_names",&ScriptEditor::_update_script_names); ObjectTypeDB::bind_method("_tree_changed",&ScriptEditor::_tree_changed); ObjectTypeDB::bind_method("_script_selected",&ScriptEditor::_script_selected); + ObjectTypeDB::bind_method("_script_created",&ScriptEditor::_script_created); ObjectTypeDB::bind_method("_script_split_dragged",&ScriptEditor::_script_split_dragged); } @@ -1802,6 +1809,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { file_menu = memnew( MenuButton ); menu_hb->add_child(file_menu); file_menu->set_text("File"); + file_menu->get_popup()->add_item("New",FILE_NEW); file_menu->get_popup()->add_item("Open",FILE_OPEN); file_menu->get_popup()->add_separator(); file_menu->get_popup()->add_item("Save",FILE_SAVE,KEY_MASK_ALT|KEY_MASK_CMD|KEY_S); @@ -1898,6 +1906,10 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { add_child(erase_tab_confirm); erase_tab_confirm->connect("confirmed", this,"_close_current_tab"); + script_create_dialog = memnew(ScriptCreateDialog); + script_create_dialog->set_title("Create Script"); + add_child(script_create_dialog); + script_create_dialog->connect("script_created", this, "_script_created"); goto_line_dialog = memnew(GotoLineDialog); add_child(goto_line_dialog); diff --git a/tools/editor/plugins/script_editor_plugin.h b/tools/editor/plugins/script_editor_plugin.h index 0dd152cb25..e635a1974b 100644 --- a/tools/editor/plugins/script_editor_plugin.h +++ b/tools/editor/plugins/script_editor_plugin.h @@ -30,6 +30,7 @@ #define SCRIPT_EDITOR_PLUGIN_H #include "tools/editor/editor_plugin.h" +#include "tools/editor/script_create_dialog.h" #include "scene/gui/tab_container.h" #include "scene/gui/text_edit.h" #include "scene/gui/menu_button.h" @@ -115,7 +116,7 @@ class ScriptEditor : public VBoxContainer { EditorNode *editor; enum { - + FILE_NEW, FILE_OPEN, FILE_SAVE, FILE_SAVE_AS, @@ -167,6 +168,7 @@ class ScriptEditor : public VBoxContainer { FindReplaceDialog *find_replace_dialog; GotoLineDialog *goto_line_dialog; ConfirmationDialog *erase_tab_confirm; + ScriptCreateDialog *script_create_dialog; ScriptEditorDebugger* debugger; ToolButton *scripts_visible; @@ -207,6 +209,7 @@ class ScriptEditor : public VBoxContainer { void _breaked(bool p_breaked,bool p_can_debug); void _show_debugger(bool p_show); void _update_window_menu(); + void _script_created(Ref<Script> p_script); void _editor_settings_changed(); void _autosave_scripts(); @@ -250,6 +253,8 @@ public: void set_window_layout(Ref<ConfigFile> p_layout); void get_window_layout(Ref<ConfigFile> p_layout); + ScriptEditorDebugger *get_debugger() { return debugger; } + ScriptEditor(EditorNode *p_editor); ~ScriptEditor(); }; diff --git a/tools/editor/plugins/shader_graph_editor_plugin.cpp b/tools/editor/plugins/shader_graph_editor_plugin.cpp index 03fcbffa24..684e7e32ef 100644 --- a/tools/editor/plugins/shader_graph_editor_plugin.cpp +++ b/tools/editor/plugins/shader_graph_editor_plugin.cpp @@ -29,6 +29,7 @@ #include "shader_graph_editor_plugin.h" +#include "scene/gui/check_box.h" #include "scene/gui/menu_button.h" #include "scene/gui/panel.h" #include "spatial_editor_plugin.h" @@ -454,43 +455,43 @@ void GraphCurveMapEdit::_plot_curve(const Vector2& p_a,const Vector2& p_b,const d3 = d * d * d; /* construct a temporary matrix for determining the forward differencing deltas */ - tmp2[0][0] = 0; tmp2[0][1] = 0; tmp2[0][2] = 0; tmp2[0][3] = 1; - tmp2[1][0] = d3; tmp2[1][1] = d2; tmp2[1][2] = d; tmp2[1][3] = 0; - tmp2[2][0] = 6*d3; tmp2[2][1] = 2*d2; tmp2[2][2] = 0; tmp2[2][3] = 0; - tmp2[3][0] = 6*d3; tmp2[3][1] = 0; tmp2[3][2] = 0; tmp2[3][3] = 0; + tmp2[0][0] = 0; tmp2[0][1] = 0; tmp2[0][2] = 0; tmp2[0][3] = 1; + tmp2[1][0] = d3; tmp2[1][1] = d2; tmp2[1][2] = d; tmp2[1][3] = 0; + tmp2[2][0] = 6*d3; tmp2[2][1] = 2*d2; tmp2[2][2] = 0; tmp2[2][3] = 0; + tmp2[3][0] = 6*d3; tmp2[3][1] = 0; tmp2[3][2] = 0; tmp2[3][3] = 0; /* compose the basis and geometry matrices */ static const float CR_basis[4][4] = { - { -0.5, 1.5, -1.5, 0.5 }, - { 1.0, -2.5, 2.0, -0.5 }, - { -0.5, 0.0, 0.5, 0.0 }, - { 0.0, 1.0, 0.0, 0.0 }, + { -0.5, 1.5, -1.5, 0.5 }, + { 1.0, -2.5, 2.0, -0.5 }, + { -0.5, 0.0, 0.5, 0.0 }, + { 0.0, 1.0, 0.0, 0.0 }, }; for (i = 0; i < 4; i++) - { - for (j = 0; j < 4; j++) + { + for (j = 0; j < 4; j++) { - tmp1[i][j] = (CR_basis[i][0] * geometry[0][j] + - CR_basis[i][1] * geometry[1][j] + - CR_basis[i][2] * geometry[2][j] + - CR_basis[i][3] * geometry[3][j]); + tmp1[i][j] = (CR_basis[i][0] * geometry[0][j] + + CR_basis[i][1] * geometry[1][j] + + CR_basis[i][2] * geometry[2][j] + + CR_basis[i][3] * geometry[3][j]); } - } + } /* compose the above results to get the deltas matrix */ for (i = 0; i < 4; i++) - { - for (j = 0; j < 4; j++) + { + for (j = 0; j < 4; j++) { - deltas[i][j] = (tmp2[i][0] * tmp1[0][j] + - tmp2[i][1] * tmp1[1][j] + - tmp2[i][2] * tmp1[2][j] + - tmp2[i][3] * tmp1[3][j]); + deltas[i][j] = (tmp2[i][0] * tmp1[0][j] + + tmp2[i][1] * tmp1[1][j] + + tmp2[i][2] * tmp1[2][j] + + tmp2[i][3] * tmp1[3][j]); } - } + } /* extract the x deltas */ @@ -509,15 +510,15 @@ void GraphCurveMapEdit::_plot_curve(const Vector2& p_a,const Vector2& p_b,const lastx = CLAMP (x, 0, xmax); lasty = CLAMP (y, 0, ymax); -/* if (fix255) - { - cd->curve[cd->outline][lastx] = lasty; - } - else - { - cd->curve_ptr[cd->outline][lastx] = lasty; - if(gb_debug) printf("bender_plot_curve xmax:%d ymax:%d\n", (int)xmax, (int)ymax); - } + /* if (fix255) + { + cd->curve[cd->outline][lastx] = lasty; + } + else + { + cd->curve_ptr[cd->outline][lastx] = lasty; + if(gb_debug) printf("bender_plot_curve xmax:%d ymax:%d\n", (int)xmax, (int)ymax); + } */ /* loop over the curve */ for (i = 0; i < ntimes; i++) @@ -590,9 +591,9 @@ void GraphCurveMapEdit::_notification(int p_what){ } /*if (i==-1 && prev.offset==next.offset) { - prev=next; - continue; - }*/ + prev=next; + continue; + }*/ _plot_curve(prev2,prev,next,next2); @@ -608,10 +609,10 @@ void GraphCurveMapEdit::_notification(int p_what){ draw_rect(Rect2( Vector2(points[i].offset,1.0-points[i].height)*get_size()-Vector2(2,2),Vector2(5,5)),col); } -/* if (grabbed!=-1) { + /* if (grabbed!=-1) { - draw_rect(Rect2(total_w+3,0,h,h),points[grabbed].color); - } + draw_rect(Rect2(total_w+3,0,h,h),points[grabbed].color); + } */ if (has_focus()) { @@ -840,6 +841,7 @@ void ShaderGraphView::_xform_input_changed(int p_id, Node *p_button){ 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; + edited_def=-1; ped_popup->edit(NULL,"",Variant::TRANSFORM,graph->xform_input_node_get_value(type,p_id),PROPERTY_HINT_NONE,""); ped_popup->popup(); @@ -850,6 +852,7 @@ void ShaderGraphView::_xform_const_changed(int p_id, Node *p_button){ 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; + edited_def=-1; ped_popup->edit(NULL,"",Variant::TRANSFORM,graph->xform_const_node_get_value(type,p_id),PROPERTY_HINT_NONE,""); ped_popup->popup(); @@ -879,6 +882,35 @@ void ShaderGraphView::_cube_input_change(int p_id){ void ShaderGraphView::_variant_edited() { + if (edited_def != -1) { + + Variant v = ped_popup->get_variant(); + Variant v2 = graph->default_get_value(type,edited_id,edited_def); + if (v2.get_type() == Variant::NIL) + switch (v.get_type()) { + case Variant::VECTOR3: + v2=Vector3(); + break; + case Variant::REAL: + v2=0.0; + break; + case Variant::TRANSFORM: + v2=Transform(); + break; + case Variant::COLOR: + v2=Color(); + break; + } + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Change default value"); + ur->add_do_method(graph.ptr(),"default_set_value",type,edited_id,edited_def, v); + ur->add_undo_method(graph.ptr(),"default_set_value",type,edited_id,edited_def, v2); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); + return; + } + if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_XFORM_CONST) { UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); @@ -1043,6 +1075,7 @@ void ShaderGraphView::_tex_edited(int p_id,Node* p_button) { 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; + edited_def=-1; ped_popup->edit(NULL,"",Variant::OBJECT,graph->texture_input_node_get_value(type,p_id),PROPERTY_HINT_RESOURCE_TYPE,"Texture"); } @@ -1052,6 +1085,7 @@ void ShaderGraphView::_cube_edited(int p_id,Node* p_button) { 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; + edited_def=-1; ped_popup->edit(NULL,"",Variant::OBJECT,graph->cubemap_input_node_get_value(type,p_id),PROPERTY_HINT_RESOURCE_TYPE,"CubeMap"); } @@ -1156,14 +1190,24 @@ void ShaderGraphView::_node_removed(int p_id) { } +void ShaderGraphView::_begin_node_move() +{ + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Move Shader Graph Node"); +} + void ShaderGraphView::_node_moved(const Vector2& p_from, const Vector2& p_to,int p_id) { ERR_FAIL_COND(!node_map.has(p_id)); UndoRedo *ur=EditorNode::get_singleton()->get_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); +} + +void ShaderGraphView::_end_node_move() +{ + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); ur->commit_action(); } @@ -1174,860 +1218,1244 @@ void ShaderGraphView::_move_node(int p_id,const Vector2& p_to) { graph->node_set_pos(type,p_id,p_to); } +void ShaderGraphView::_duplicate_nodes_request() +{ + Array s_id; + + for(Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) { + ShaderGraph::NodeType t=graph->node_get_type(type, E->key()); + if (t==ShaderGraph::NODE_OUTPUT || t==ShaderGraph::NODE_INPUT) + continue; + GraphNode *gn = E->get(); + if (gn && gn->is_selected()) + s_id.push_back(E->key()); + } -void ShaderGraphView::_create_node(int p_id) { - - - GraphNode *gn = memnew( GraphNode ); - gn->set_show_close_button(true); - Color typecol[4]={ - Color(0.9,0.4,1), - Color(0.8,1,0.2), - Color(1,0.2,0.2), - Color(0,1,1) - }; - - - switch(graph->node_get_type(type,p_id)) { - - case ShaderGraph::NODE_INPUT: { + if (s_id.size()==0) + return; - gn->set_title("Input"); + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Duplicate Graph Node(s)"); + ur->add_do_method(this,"_duplicate_nodes",s_id); + List<int> n_ids = graph->generate_ids(type, s_id.size()); + for (List<int>::Element *E=n_ids.front();E;E=E->next()) + ur->add_undo_method(graph.ptr(),"node_remove",type,E->get()); + ur->add_do_method(this,"_update_graph"); + ur->add_undo_method(this,"_update_graph"); + ur->commit_action(); - List<ShaderGraph::SlotInfo> si; - ShaderGraph::get_input_output_node_slot_info(graph->get_mode(),type,&si); +} - int idx=0; - for (List<ShaderGraph::SlotInfo>::Element *E=si.front();E;E=E->next()) { - ShaderGraph::SlotInfo& s=E->get(); - if (s.dir==ShaderGraph::SLOT_IN) { +void ShaderGraphView::_duplicate_nodes(const Array &p_nodes) +{ + List<int> n = List<int>(); + for (int i=0; i<p_nodes.size();i++) + n.push_back(p_nodes.get(i)); + graph->duplicate_nodes(type, n); + call_deferred("_update_graph"); +} - 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++; - } - } +void ShaderGraphView::_delete_nodes_request() +{ + List<int> s_id=List<int>(); + + for(Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) { + ShaderGraph::NodeType t=graph->node_get_type(type, E->key()); + if (t==ShaderGraph::NODE_OUTPUT) + continue; + GraphNode *gn = E->get(); + if (gn && gn->is_selected()) + s_id.push_back(E->key()); + } - } 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]); + if (s_id.size()==0) + return; - } break; //vec3 constant - case ShaderGraph::NODE_RGB_CONST: { + UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo(); + ur->create_action("Delete Shader Graph Node(s)"); - 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]); + for (List<int>::Element *N=s_id.front();N;N=N->next()) { + ur->add_do_method(graph.ptr(),"node_remove",type,N->get()); + ur->add_undo_method(graph.ptr(),"node_add",type,graph->node_get_type(type,N->get()),N->get()); + ur->add_undo_method(graph.ptr(),"node_set_state",type,N->get(),graph->node_get_state(type,N->get())); + List<ShaderGraph::Connection> conns; - } break; // time in seconds - case ShaderGraph::NODE_SCREEN_TEX: { + graph->get_node_connections(type,&conns); + for(List<ShaderGraph::Connection>::Element *E=conns.front();E;E=E->next()) { - 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;i<ShaderGraph::SCALAR_MAX_OP;i++) { - - ob->add_item(op_name[i],i); + if (E->get().dst_id==N->get() || E->get().src_id==N->get()) { + 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(); - 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;i<ShaderGraph::VEC_MAX_OP;i++) { - - ob->add_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); +void ShaderGraphView::_default_changed(int p_id, Node *p_button, int p_param, int v_type, String p_hint) +{ + ToolButton *tb = p_button->cast_to<ToolButton>(); + 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; + edited_def=p_param; + Variant::Type vt = (Variant::Type)v_type; + Variant v = graph->default_get_value(type,p_id,edited_def); + int h=PROPERTY_HINT_NONE; + if (v.get_type() == Variant::NIL) + switch (vt) { + case Variant::VECTOR3: + v=Vector3(); + break; + case Variant::REAL: + h=PROPERTY_HINT_RANGE; + v=0.0; + break; + case Variant::TRANSFORM: + v=Transform(); + break; + case Variant::COLOR: + h=PROPERTY_HINT_COLOR_NO_ALPHA; + v=Color(); + break; + } - 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"))); + ped_popup->edit(NULL,"",vt,v,h,p_hint); - 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()); + ped_popup->popup(); +} +ToolButton *ShaderGraphView::make_label(String text, Variant::Type v_type) { + ToolButton *l = memnew( ToolButton ); + l->set_text(text); + l->set_text_align(ToolButton::ALIGN_LEFT); + l->add_style_override("hover", l->get_stylebox("normal", "ToolButton")); + l->add_style_override("pressed", l->get_stylebox("normal", "ToolButton")); + l->add_style_override("focus", l->get_stylebox("normal", "ToolButton")); + switch (v_type) { + case Variant::REAL: + l->set_icon(ped_popup->get_icon("Real", "EditorIcons")); + break; + case Variant::VECTOR3: + l->set_icon(ped_popup->get_icon("Vector", "EditorIcons")); + break; + case Variant::TRANSFORM: + l->set_icon(ped_popup->get_icon("Matrix", "EditorIcons")); + break; + case Variant::COLOR: + l->set_icon(ped_popup->get_icon("Color", "EditorIcons")); + } + return l; +} - } break; // vec3 vs vec3 op (mul: { } break;ad: { } break;div: { } break;crossprod: { } break;etc) - case ShaderGraph::NODE_VEC_SCALAR_OP: { +ToolButton *ShaderGraphView::make_editor(String text,GraphNode* gn,int p_id,int param,Variant::Type v_type, String p_hint) { + ToolButton *edit = memnew( ToolButton ); + edit->set_text(text); + edit->set_text_align(ToolButton::ALIGN_LEFT); + edit->set_flat(false); + edit->add_style_override("normal", gn->get_stylebox("defaultframe", "GraphNode")); + edit->add_style_override("hover", gn->get_stylebox("defaultframe", "GraphNode")); + edit->add_style_override("pressed", gn->get_stylebox("defaultframe", "GraphNode")); + edit->add_style_override("focus", gn->get_stylebox("defaultfocus", "GraphNode")); + edit->connect("pressed",this,"_default_changed",varray(p_id,edit,param,v_type,p_hint)); + + switch (v_type) { + case Variant::REAL: + edit->set_icon(ped_popup->get_icon("Real", "EditorIcons")); + break; + case Variant::VECTOR3: + edit->set_icon(ped_popup->get_icon("Vector", "EditorIcons")); + break; + case Variant::TRANSFORM: + edit->set_icon(ped_popup->get_icon("Matrix", "EditorIcons")); + break; + case Variant::COLOR: + Image icon_color = Image(15,15,false,Image::FORMAT_RGB); + Color c = graph->default_get_value(type,p_id,param); + for (int x=1;x<14;x++) + for (int y=1;y<14;y++) + icon_color.put_pixel(x,y,c); + Ref<ImageTexture> t; + t.instance(); + t->create_from_image(icon_color); + edit->set_icon(t); + break; + } + return edit; +} - gn->set_title("VecScalarOp"); - static const char* op_name[ShaderGraph::VEC_SCALAR_MAX_OP]={ - "Mul", - "Div", - "Pow", - }; +void ShaderGraphView::_create_node(int p_id) { - OptionButton *ob = memnew( OptionButton ); - for(int i=0;i<ShaderGraph::VEC_SCALAR_MAX_OP;i++) { - ob->add_item(op_name[i],i); - } + GraphNode *gn = memnew( GraphNode ); + gn->set_show_close_button(true); + Color typecol[4]={ + Color(0.9,0.4,1), + Color(0.8,1,0.2), + Color(1,0.2,0.2), + Color(0,1,1) + }; - 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); + const String hint_spin = "-65536,65535,0.001"; + const String hint_slider = "0.0,1.0,0.01,slider"; - 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()); + switch(graph->node_get_type(type,p_id)) { + case ShaderGraph::NODE_INPUT: { - } break; // vec3 vs scalar op (mul: { } break; add: { } break; div: { } break; etc) - case ShaderGraph::NODE_RGB_OP: { + gn->set_title("Input"); - gn->set_title("RGB Op"); - static const char* op_name[ShaderGraph::RGB_MAX_OP]={ - "Screen", - "Difference", - "Darken", - "Lighten", - "Overlay", - "Dodge", - "Burn", - "SoftLight", - "HardLight" - }; + List<ShaderGraph::SlotInfo> si; + ShaderGraph::get_input_output_node_slot_info(graph->get_mode(),type,&si); - OptionButton *ob = memnew( OptionButton ); - for(int i=0;i<ShaderGraph::RGB_MAX_OP;i++) { + int idx=0; + for (List<ShaderGraph::SlotInfo>::Element *E=si.front();E;E=E->next()) { + ShaderGraph::SlotInfo& s=E->get(); + if (s.dir==ShaderGraph::SLOT_IN) { - ob->add_item(op_name[i],i); + 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++; } + } - 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); - + } 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 ); - hbc->add_constant_override("separation",0); - hbc->add_child( memnew(Label("a"))); - hbc->add_spacer(); - hbc->add_child( memnew(Label("out"))); + 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->add_child( memnew(Label("b"))); + } + 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); + if (!graph->is_slot_connected(type,p_id,0)) { + Vector3 v = graph->default_get_value(type, p_id, 0); + hbc->add_child(make_editor("UV: " + v,gn,p_id,0,Variant::VECTOR3)); + } else { + hbc->add_child(make_label("UV",Variant::VECTOR3)); + } + 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;i<ShaderGraph::SCALAR_MAX_OP;i++) { + + ob->add_item(op_name[i],i); + } - 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()); + 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); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("a",Variant::REAL)); + } else { + float v = graph->default_get_value(type,p_id,0); + hbc->add_child(make_editor(String("a: ")+Variant(v),gn,p_id,0,Variant::REAL,hint_spin)); + } + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + if (graph->is_slot_connected(type, p_id, 1)) { + gn->add_child(make_label("b",Variant::REAL)); + } else { + float v = graph->default_get_value(type,p_id,1); + gn->add_child(make_editor(String("b: ")+Variant(v),gn,p_id,1,Variant::REAL,hint_spin)); + } - } 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_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()); - 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; // 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" + }; - } break; // mat4 x mat4 - case ShaderGraph::NODE_XFORM_VEC_MULT: { + OptionButton *ob = memnew( OptionButton ); + for(int i=0;i<ShaderGraph::VEC_MAX_OP;i++) { - gn->set_title("XFVecMult"); + ob->add_item(op_name[i],i); + } - 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)); + 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); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("a",Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,0); + hbc->add_child(make_editor(String("a: ")+v,gn,p_id,0,Variant::VECTOR3)); + } + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + if (graph->is_slot_connected(type, p_id, 1)) { + gn->add_child(make_label("b",Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,1); + gn->add_child(make_editor(String("b: ")+v,gn,p_id,1,Variant::VECTOR3)); + } - gn->add_child(button); + 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()); - 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; // vec3 vs vec3 op (mul: { } break;ad: { } break;div: { } break;crossprod: { } break;etc) + case ShaderGraph::NODE_VEC_SCALAR_OP: { - } break; - case ShaderGraph::NODE_XFORM_VEC_INV_MULT: { + gn->set_title("VecScalarOp"); + static const char* op_name[ShaderGraph::VEC_SCALAR_MAX_OP]={ + "Mul", + "Div", + "Pow", + }; - gn->set_title("XFVecInvMult"); + OptionButton *ob = memnew( OptionButton ); + for(int i=0;i<ShaderGraph::VEC_SCALAR_MAX_OP;i++) { + ob->add_item(op_name[i],i); + } - 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)); + 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); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("a",Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,0); + hbc->add_child(make_editor(String("a: ")+v,gn,p_id,0,Variant::VECTOR3)); + } + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + + if (graph->is_slot_connected(type, p_id, 1)) { + gn->add_child(make_label("b",Variant::REAL)); + } else { + float v = graph->default_get_value(type,p_id,1); + gn->add_child(make_editor(String("b: ")+Variant(v),gn,p_id,1,Variant::REAL,hint_spin)); + } + 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;i<ShaderGraph::RGB_MAX_OP;i++) { + + ob->add_item(op_name[i],i); + } - gn->add_child(button); + 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); - gn->add_child( memnew(Label("vec"))); - 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); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("a",Variant::COLOR)); + } else { + hbc->add_child(make_editor(String("a: "),gn,p_id,0,Variant::COLOR)); + } + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + if (graph->is_slot_connected(type, p_id, 1)) { + gn->add_child(make_label("b",Variant::COLOR)); + } else { + gn->add_child(make_editor(String("b: "),gn,p_id,1,Variant::COLOR)); + } - 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_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); - - - } 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;i<ShaderGraph::SCALAR_MAX_FUNC;i++) { - - ob->add_item(func_name[i],i); - } + 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()); - 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); + } 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: { - 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_title("XFMult"); + HBoxContainer *hbc = memnew( HBoxContainer ); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("a",Variant::TRANSFORM)); + } else { + hbc->add_child(make_editor(String("a: edit..."),gn,p_id,0,Variant::TRANSFORM)); + } + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); + if (graph->is_slot_connected(type, p_id, 1)) { + gn->add_child(make_label("b",Variant::TRANSFORM)); + } else { + gn->add_child(make_editor(String("b: edit..."),gn,p_id,1,Variant::TRANSFORM)); + } - 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(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; // scalar function (sin: { } break; cos: { } break; etc) - case ShaderGraph::NODE_VEC_FUNC: { + } break; // mat4 x mat4 + case ShaderGraph::NODE_XFORM_VEC_MULT: { + gn->set_title("XFVecMult"); + CheckBox *button = memnew (CheckBox("RotOnly")); + 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->set_title("VecFunc"); - static const char* func_name[ShaderGraph::VEC_MAX_FUNC]={ - "Normalize", - "Saturate", - "Negate", - "Reciprocal", - "RGB to HSV", - "HSV to RGB", - }; + gn->add_child(button); - OptionButton *ob = memnew( OptionButton ); - for(int i=0;i<ShaderGraph::VEC_MAX_FUNC;i++) { + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("xf",Variant::TRANSFORM)); + } else { + hbc->add_child(make_editor(String("xf: edit..."),gn,p_id,0,Variant::TRANSFORM)); + } + hbc->add_spacer(); + Label *l = memnew(Label("out")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + if (graph->is_slot_connected(type, p_id, 1)) { + gn->add_child(make_label("a",Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,1); + gn->add_child(make_editor(String("a: ")+v,gn,p_id,1,Variant::VECTOR3)); + } - ob->add_item(func_name[i],i); - } + 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()); - 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); + } break; + case ShaderGraph::NODE_XFORM_VEC_INV_MULT: { - 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_title("XFVecInvMult"); - 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); + CheckBox *button = memnew( CheckBox("RotOnly")); + 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->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + gn->add_child(button); - } break; // vec3 length - case ShaderGraph::NODE_DOT_PROD: { + if (graph->is_slot_connected(type, p_id, 0)) { + gn->add_child(make_label("a",Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,0); + gn->add_child(make_editor(String("a: ")+v,gn,p_id,0,Variant::VECTOR3)); + } + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + if (graph->is_slot_connected(type, p_id, 1)) { + hbc->add_child(make_label("xf", Variant::TRANSFORM)); + } else { + hbc->add_child(make_editor(String("xf: edit..."),gn,p_id,1,Variant::TRANSFORM)); + } + hbc->add_spacer(); + Label *l = memnew(Label("out")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + + 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_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + + + } 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;i<ShaderGraph::SCALAR_MAX_FUNC;i++) { + + ob->add_item(func_name[i],i); + } - 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"))); + 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); - 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()); + HBoxContainer *hbc = memnew( HBoxContainer ); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("in", Variant::REAL)); + } else { + float v = graph->default_get_value(type,p_id,0); + hbc->add_child(make_editor(String("in: ")+Variant(v),gn,p_id,0,Variant::REAL,hint_spin)); + } + hbc->add_spacer(); + hbc->add_child( memnew(Label("out"))); + gn->add_child(hbc); - } break; // vec3 . vec3 (dot product -> scalar output) - case ShaderGraph::NODE_VEC_TO_SCALAR: { + 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_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; // 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", + }; - } break; // 1 vec3 input: { } break; 3 scalar outputs - case ShaderGraph::NODE_SCALAR_TO_VEC: { + OptionButton *ob = memnew( OptionButton ); + for(int i=0;i<ShaderGraph::VEC_MAX_FUNC;i++) { - 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"))); + ob->add_item(func_name[i],i); + } - 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()); + 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); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("in", Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,0); + hbc->add_child(make_editor(String("in: ")+v,gn,p_id,0,Variant::VECTOR3)); + } + 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 ); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("in", Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,0); + hbc->add_child(make_editor(String("in: ")+v,gn,p_id,0,Variant::VECTOR3)); + } + 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); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("a", Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,0); + hbc->add_child(make_editor(String("a: ")+v,gn,p_id,0,Variant::VECTOR3)); + } + hbc->add_spacer(); + hbc->add_child( memnew(Label("dp"))); + gn->add_child(hbc); + if (graph->is_slot_connected(type, p_id, 1)) { + gn->add_child(make_label("b", Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,1); + gn->add_child(make_editor(String("b: ")+v,gn,p_id,1,Variant::VECTOR3)); + } - } break; // 3 scalar input: { } break; 1 vec3 output - case ShaderGraph::NODE_VEC_TO_XFORM: { + 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()); - 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"))); + } break; // vec3 . vec3 (dot product -> scalar output) + case ShaderGraph::NODE_VEC_TO_SCALAR: { - 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()); + gn->set_title("Vec2Scalar"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("vec", Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,0); + hbc->add_child(make_editor(String("vec: ")+v,gn,p_id,0,Variant::VECTOR3)); + } + 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 ); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("x", Variant::REAL)); + } else { + float v = graph->default_get_value(type,p_id,0); + hbc->add_child(make_editor(String("x: ")+Variant(v),gn,p_id,0,Variant::REAL)); + } + hbc->add_spacer(); + hbc->add_child( memnew(Label("vec"))); + gn->add_child(hbc); + if (graph->is_slot_connected(type, p_id, 1)) { + gn->add_child(make_label("y", Variant::REAL)); + } else { + float v = graph->default_get_value(type,p_id,1); + gn->add_child(make_editor(String("y: ")+Variant(v),gn,p_id,1,Variant::REAL)); + } + if (graph->is_slot_connected(type, p_id, 2)) { + gn->add_child(make_label("in", Variant::REAL)); + } else { + float v = graph->default_get_value(type,p_id,2); + gn->add_child(make_editor(String("in: ")+Variant(v),gn,p_id,2,Variant::REAL)); + } - } break; // 3 vec input: { } break; 1 xform output - case ShaderGraph::NODE_XFORM_TO_VEC: { + 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); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("x", Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,0); + hbc->add_child(make_editor(String("x: ")+v,gn,p_id,0,Variant::VECTOR3)); + } + hbc->add_spacer(); + hbc->add_child( memnew(Label("xf"))); + gn->add_child(hbc); + if (graph->is_slot_connected(type, p_id, 1)) { + gn->add_child(make_label("y", Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,1); + gn->add_child(make_editor(String("y: ")+v,gn,p_id,1,Variant::VECTOR3)); + } + if (graph->is_slot_connected(type, p_id, 2)) { + gn->add_child(make_label("z", Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,2); + gn->add_child(make_editor(String("z: ")+v,gn,p_id,2,Variant::VECTOR3)); + } + if (graph->is_slot_connected(type, p_id, 3)) { + gn->add_child(make_label("ofs", Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,3); + gn->add_child(make_editor(String("ofs: ")+v,gn,p_id,3,Variant::VECTOR3)); + } - gn->set_title("XForm2Vec"); + 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()); - 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"))); + } break; // 3 vec input: { } break; 1 xform output + case ShaderGraph::NODE_XFORM_TO_VEC: { - 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()); + gn->set_title("XForm2Vec"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("fx", Variant::TRANSFORM)); + } else { + hbc->add_child(make_editor(String("fx: edit..."),gn,p_id,0,Variant::TRANSFORM)); + } + 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); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("a", Variant::REAL)); + } else { + float v = graph->default_get_value(type,p_id,0); + hbc->add_child(make_editor(String("a: ")+Variant(v),gn,p_id,0,Variant::REAL,hint_spin)); + } + hbc->add_spacer(); + hbc->add_child( memnew(Label("interp"))); + gn->add_child(hbc); + if (graph->is_slot_connected(type, p_id, 1)) { + gn->add_child(make_label("b", Variant::REAL)); + } else { + float v = graph->default_get_value(type,p_id,1); + gn->add_child(make_editor(String("b: ")+Variant(v),gn,p_id,1,Variant::REAL,hint_spin)); + } + if (graph->is_slot_connected(type, p_id, 2)) { + gn->add_child(make_label("c", Variant::REAL)); + } else { + float v = graph->default_get_value(type,p_id,2); + gn->add_child(make_editor(String("c: ")+Variant(v),gn,p_id,2,Variant::REAL,hint_slider)); + } - } break; // scalar interpolation (with optional curve) - case ShaderGraph::NODE_VEC_INTERP: { + 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()); - 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_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); + } break; // scalar interpolation (with optional curve) + case ShaderGraph::NODE_VEC_INTERP: { - } break; // vec3 interpolation (with optional curve) - case ShaderGraph::NODE_COLOR_RAMP: { + gn->set_title("VecInterp"); + HBoxContainer *hbc = memnew( HBoxContainer ); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("a", Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,0); + hbc->add_child(make_editor(String("a: ")+v,gn,p_id,0,Variant::VECTOR3)); + } + hbc->add_spacer(); + hbc->add_child( memnew(Label("interp"))); + gn->add_child(hbc); + if (graph->is_slot_connected(type, p_id, 1)) { + gn->add_child(make_label("b", Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,1); + gn->add_child(make_editor(String("b: ")+v,gn,p_id,1,Variant::VECTOR3)); + } + if (graph->is_slot_connected(type, p_id, 2)) { + gn->add_child(make_label("c", Variant::REAL)); + } else { + float v = graph->default_get_value(type,p_id,2); + gn->add_child(make_editor(String("c: ")+Variant(v),gn,p_id,2,Variant::REAL,hint_slider)); + } - gn->set_title("ColorRamp"); - GraphColorRampEdit * ramp = memnew( GraphColorRampEdit ); + 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_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color()); - DVector<real_t> offsets = graph->color_ramp_node_get_offsets(type,p_id); - DVector<Color> colors = graph->color_ramp_node_get_colors(type,p_id); + } break; // vec3 interpolation (with optional curve) + case ShaderGraph::NODE_COLOR_RAMP: { - int oc = offsets.size(); + gn->set_title("ColorRamp"); + GraphColorRampEdit * ramp = memnew( GraphColorRampEdit ); - if (oc) { - DVector<real_t>::Read rofs = offsets.read(); - DVector<Color>::Read rcol = colors.read(); + DVector<real_t> offsets = graph->color_ramp_node_get_offsets(type,p_id); + DVector<Color> colors = graph->color_ramp_node_get_colors(type,p_id); - Vector<float> ofsv; - Vector<Color> colorv; - for(int i=0;i<oc;i++) { - ofsv.push_back(rofs[i]); - colorv.push_back(rcol[i]); - } + int oc = offsets.size(); - ramp->set_ramp(ofsv,colorv); + if (oc) { + DVector<real_t>::Read rofs = offsets.read(); + DVector<Color>::Read rcol = colors.read(); + Vector<float> ofsv; + Vector<Color> colorv; + for(int i=0;i<oc;i++) { + ofsv.push_back(rofs[i]); + colorv.push_back(rcol[i]); } - ramp->connect("ramp_changed",this,"_color_ramp_changed",varray(p_id,ramp)); - ramp->set_custom_minimum_size(Size2(128,1)); - gn->add_child(ramp); + ramp->set_ramp(ofsv,colorv); + } - HBoxContainer *hbc = memnew( HBoxContainer ); - hbc->add_constant_override("separation",0); - hbc->add_child( memnew(Label("c"))); - hbc->add_spacer(); - Label *l=memnew(Label("rgb")); - l->set_align(Label::ALIGN_RIGHT); - hbc->add_child( l); - gn->add_child(hbc); - l=memnew(Label("alpha")); - l->set_align(Label::ALIGN_RIGHT); - gn->add_child( l); + ramp->connect("ramp_changed",this,"_color_ramp_changed",varray(p_id,ramp)); + ramp->set_custom_minimum_size(Size2(128,1)); + gn->add_child(ramp); - gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); - gn->set_slot(2,false,ShaderGraph::SLOT_MAX,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("c", Variant::REAL)); + } else { + float v = graph->default_get_value(type,p_id,0); + hbc->add_child(make_editor(String("c: ")+Variant(v),gn,p_id,0,Variant::REAL,hint_slider)); + } + hbc->add_spacer(); + Label *l=memnew(Label("rgb")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + l=memnew(Label("alpha")); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child( l); - } break; // scalar interpolation (with optional curve) - case ShaderGraph::NODE_CURVE_MAP: { + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(2,false,ShaderGraph::SLOT_MAX,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); - gn->set_title("CurveMap"); - GraphCurveMapEdit * map = memnew( GraphCurveMapEdit ); - DVector<Vector2> points = graph->curve_map_node_get_points(type,p_id); + } break; // scalar interpolation (with optional curve) + case ShaderGraph::NODE_CURVE_MAP: { - int oc = points.size(); + gn->set_title("CurveMap"); + GraphCurveMapEdit * map = memnew( GraphCurveMapEdit ); - if (oc) { - DVector<Vector2>::Read rofs = points.read(); + DVector<Vector2> points = graph->curve_map_node_get_points(type,p_id); + int oc = points.size(); - Vector<Vector2> ofsv; - for(int i=0;i<oc;i++) { - ofsv.push_back(rofs[i]); - } + if (oc) { + DVector<Vector2>::Read rofs = points.read(); - map->set_points(ofsv); + Vector<Vector2> ofsv; + for(int i=0;i<oc;i++) { + ofsv.push_back(rofs[i]); } - map->connect("curve_changed",this,"_curve_changed",varray(p_id,map)); - //map->connect("map_changed",this,"_curve_map_changed",varray(p_id,map)); - map->set_custom_minimum_size(Size2(128,64)); - gn->add_child(map); + map->set_points(ofsv); + } + map->connect("curve_changed",this,"_curve_changed",varray(p_id,map)); + + //map->connect("map_changed",this,"_curve_map_changed",varray(p_id,map)); + map->set_custom_minimum_size(Size2(128,64)); + gn->add_child(map); + + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("c", Variant::REAL)); + } else { + float v = graph->default_get_value(type,p_id,0); + hbc->add_child(make_editor(String("c: ")+Variant(v),gn,p_id,0,Variant::REAL,hint_slider)); + } + hbc->add_spacer(); + Label *l=memnew(Label("cmap")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child( l); + gn->add_child(hbc); + + + gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + + } break; // scalar interpolation (with optional curve) + + case ShaderGraph::NODE_SCALAR_INPUT: { + + gn->set_title("ScalarUniform"); + 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 ); - hbc->add_constant_override("separation",0); - hbc->add_child( memnew(Label("c"))); - hbc->add_spacer(); - Label *l=memnew(Label("cmap")); - l->set_align(Label::ALIGN_RIGHT); - hbc->add_child( l); - gn->add_child(hbc); - - - gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); - - - } break; // scalar interpolation (with optional curve) - - case ShaderGraph::NODE_SCALAR_INPUT: { - - gn->set_title("ScalarUniform"); - 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)); + 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->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); + 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); - 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_DEFAULT_TEXTURE: { - - gn->set_title("CanvasItemTex"); - HBoxContainer *hbc = memnew( HBoxContainer ); - hbc->add_constant_override("separation",0); - hbc->add_child( memnew(Label("UV"))); - hbc->add_spacer(); - Label *l=memnew(Label("RGB")); - l->set_align(Label::ALIGN_RIGHT); - hbc->add_child(l); - gn->add_child(hbc); - l = memnew( Label ); - l->set_text("Alpha"); - l->set_align(Label::ALIGN_RIGHT); - gn->add_child(l); - - gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); - gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); - - - } break; // screen texture sampler (takes UV) (only usable in fragment case Shader) - - case ShaderGraph::NODE_OUTPUT: { - gn->set_title("Output"); - - List<ShaderGraph::SlotInfo> si; - ShaderGraph::get_input_output_node_slot_info(graph->get_mode(),type,&si); - - int idx=0; - for (List<ShaderGraph::SlotInfo>::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++; - } + } + 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); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("UV", Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,0); + hbc->add_child(make_editor(String("UV: ")+v,gn,p_id,0,Variant::VECTOR3)); + } + 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); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("UV", Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,0); + hbc->add_child(make_editor(String("UV: ")+v,gn,p_id,0,Variant::VECTOR3)); + } + 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_DEFAULT_TEXTURE: { + + gn->set_title("CanvasItemTex"); + HBoxContainer *hbc = memnew( HBoxContainer ); + hbc->add_constant_override("separation",0); + if (graph->is_slot_connected(type, p_id, 0)) { + hbc->add_child(make_label("UV", Variant::VECTOR3)); + } else { + Vector3 v = graph->default_get_value(type,p_id,0); + hbc->add_child(make_editor(String("UV: ")+v,gn,p_id,0,Variant::VECTOR3)); + } + hbc->add_spacer(); + Label *l=memnew(Label("RGB")); + l->set_align(Label::ALIGN_RIGHT); + hbc->add_child(l); + gn->add_child(hbc); + l = memnew( Label ); + l->set_text("Alpha"); + l->set_align(Label::ALIGN_RIGHT); + gn->add_child(l); + + gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]); + gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]); + + + } break; // screen texture sampler (takes UV) (only usable in fragment case Shader) + + case ShaderGraph::NODE_OUTPUT: { + gn->set_title("Output"); + gn->set_show_close_button(false); + + List<ShaderGraph::SlotInfo> si; + ShaderGraph::get_input_output_node_slot_info(graph->get_mode(),type,&si); + + Array colors; + colors.push_back("Color"); + colors.push_back("LightColor"); + colors.push_back("Light"); + colors.push_back("Diffuse"); + colors.push_back("Specular"); + colors.push_back("Emmision"); + Array reals; + reals.push_back("Alpha"); + reals.push_back("DiffuseAlpha"); + reals.push_back("NormalMapDepth"); + reals.push_back("SpecExp"); + reals.push_back("Glow"); + reals.push_back("ShadeParam"); + reals.push_back("SpecularExp"); + reals.push_back("LightAlpha"); + reals.push_back("PointSize"); + reals.push_back("Discard"); + + int idx=0; + for (List<ShaderGraph::SlotInfo>::Element *E=si.front();E;E=E->next()) { + ShaderGraph::SlotInfo& s=E->get(); + if (s.dir==ShaderGraph::SLOT_OUT) { + Variant::Type v; + if (colors.find(s.name)>=0) + v=Variant::COLOR; + else if (reals.find(s.name)>=0) + v=Variant::REAL; + else + v=Variant::VECTOR3; + gn->add_child(make_label(s.name, v)); + 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; // 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 + } break; // comment @@ -2076,8 +2504,6 @@ void ShaderGraphView::_update_graph() { 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 ShaderGraphView::_sg_updated() { @@ -2085,9 +2511,9 @@ void ShaderGraphView::_sg_updated() { if (!graph.is_valid()) return; switch(graph->get_graph_error(type)) { - case ShaderGraph::GRAPH_OK: status->set_text(""); break; - case ShaderGraph::GRAPH_ERROR_CYCLIC: status->set_text("Error: Cyclic Connection Link"); break; - case ShaderGraph::GRAPH_ERROR_MISSING_CONNECTIONS: status->set_text("Error: Missing Input Connections"); break; + case ShaderGraph::GRAPH_OK: status->set_text(""); break; + case ShaderGraph::GRAPH_ERROR_CYCLIC: status->set_text("Error: Cyclic Connection Link"); break; + case ShaderGraph::GRAPH_ERROR_MISSING_CONNECTIONS: status->set_text("Error: Missing Input Connections"); break; } } @@ -2112,9 +2538,12 @@ void ShaderGraphView::_notification(int p_what) { ped_popup->connect("variant_changed",this,"_variant_edited"); } - } +} + +void ShaderGraphView::add_node(int p_type, const Vector2 &location) { -void ShaderGraphView::add_node(int p_type) { + if ((p_type==ShaderGraph::NODE_INPUT||p_type==ShaderGraph::NODE_INPUT) && graph->node_count(type, p_type)>0) + return; List<int> existing; graph->get_node_list(type,&existing); @@ -2127,7 +2556,7 @@ void ShaderGraphView::add_node(int p_type) { } } - Vector2 init_ofs(20,20); + Vector2 init_ofs = location; while(true) { bool valid=true; for(List<int>::Element *E=existing.front();E;E=E->next()) { @@ -2157,12 +2586,18 @@ void ShaderGraphView::add_node(int p_type) { void ShaderGraphView::_bind_methods() { ObjectTypeDB::bind_method("_update_graph",&ShaderGraphView::_update_graph); + ObjectTypeDB::bind_method("_begin_node_move", &ShaderGraphView::_begin_node_move); ObjectTypeDB::bind_method("_node_moved",&ShaderGraphView::_node_moved); + ObjectTypeDB::bind_method("_end_node_move", &ShaderGraphView::_end_node_move); 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("_disconnection_request",&ShaderGraphView::_disconnection_request); + ObjectTypeDB::bind_method("_duplicate_nodes_request", &ShaderGraphView::_duplicate_nodes_request); + ObjectTypeDB::bind_method("_duplicate_nodes", &ShaderGraphView::_duplicate_nodes); + ObjectTypeDB::bind_method("_delete_nodes_request", &ShaderGraphView::_delete_nodes_request); + ObjectTypeDB::bind_method("_default_changed",&ShaderGraphView::_default_changed); 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); @@ -2200,6 +2635,8 @@ ShaderGraphView::ShaderGraphView(ShaderGraph::ShaderType p_type) { graph_edit->add_child(ped_popup); status = memnew( Label ); graph_edit->get_top_layer()->add_child(status); + graph_edit->connect("_begin_node_move", this, "_begin_node_move"); + graph_edit->connect("_end_node_move", this, "_end_node_move"); status->set_pos(Vector2(5,5)); status->add_color_override("font_color_shadow",Color(0,0,0)); status->add_color_override("font_color",Color(1,0.4,0.3)); @@ -2222,9 +2659,18 @@ void ShaderGraphEditor::_add_node(int p_type) { ShaderGraph::ShaderType shader_type=ShaderGraph::ShaderType(tabs->get_current_tab()); - graph_edits[shader_type]->add_node(p_type); + graph_edits[shader_type]->add_node(p_type, next_location); } +void ShaderGraphEditor::_popup_requested(const Vector2 &p_position) +{ + next_location = get_local_mouse_pos(); + popup->set_global_pos(p_position); + popup->set_size( Size2( 200, 0) ); + popup->popup(); + popup->call_deferred("grab_click_focus"); + popup->set_invalidate_click_until_motion(); +} void ShaderGraphEditor::_notification(int p_what) { if (p_what==NOTIFICATION_ENTER_TREE) { @@ -2243,11 +2689,11 @@ void ShaderGraphEditor::_notification(int p_what) { if (nn.ends_with(":")) { addsep=true; } - menu->get_popup()->add_icon_item(get_icon(ic,"EditorIcons"),v,i); + popup->add_icon_item(get_icon(ic,"EditorIcons"),v,i); if (addsep) - menu->get_popup()->add_separator(); + popup->add_separator(); } - menu->get_popup()->connect("item_pressed",this,"_add_node"); + popup->connect("item_pressed",this,"_add_node"); } @@ -2256,7 +2702,7 @@ void ShaderGraphEditor::_notification(int p_what) { void ShaderGraphEditor::_bind_methods() { ObjectTypeDB::bind_method("_add_node",&ShaderGraphEditor::_add_node); - + ObjectTypeDB::bind_method("_popup_requested",&ShaderGraphEditor::_popup_requested); } @@ -2285,16 +2731,16 @@ const char* ShaderGraphEditor::node_names[ShaderGraph::NODE_TYPE_MAX]={ "GraphVecsToXform:Vectors -> XForm:", // 3 vec input", 1 xform output "GraphScalarInterp:Scalar Interpolate", // scalar interpolation (with optional curve) "GraphVecInterp:Vector Interpolate:", // vec3 interpolation (with optional curve) - "GraphColorRamp:Color Ramp", // vec3 interpolation (with optional curve) - "GraphCurveMap:Curve Remap:", // vec3 interpolation (with optional curve) - "GraphScalarUniform:Scalar Uniform", // scalar uniform (assignable in material) + "GraphColorRamp:Color Ramp", // vec3 interpolation (with optional curve) + "GraphCurveMap:Curve Remap:", // vec3 interpolation (with optional curve) + "GraphScalarUniform:Scalar Uniform", // scalar uniform (assignable in material) "GraphVectorUniform:Vector Uniform", // vec3 uniform (assignable in material) "GraphRgbUniform:RGB Uniform", // color uniform (assignable in material) "GraphXformUniform:XForm Uniform", // mat4 uniform (assignable in material) "GraphTextureUniform:Texture Uniform", // texture input (assignable in material) "GraphCubeUniform:CubeMap Uniform:", // cubemap input (assignable in material) - "GraphDefaultTexture:CanvasItem Texture:", // cubemap input (assignable in material) - "Output", // output (shader type dependent) + "GraphDefaultTexture:CanvasItem Texture:", // cubemap input (assignable in material) + "Output", // output (shader type dependent) "GraphComment:Comment", // comment @@ -2302,11 +2748,8 @@ const char* ShaderGraphEditor::node_names[ShaderGraph::NODE_TYPE_MAX]={ ShaderGraphEditor::ShaderGraphEditor(bool p_2d) { _2d=p_2d; - HBoxContainer *hbc = memnew( HBoxContainer ); - menu = memnew( MenuButton ); - menu->set_text("Add Node.."); - hbc->add_child(menu); - add_child(hbc); + popup = memnew( PopupMenu ); + add_child(popup); tabs = memnew(TabContainer); @@ -2325,8 +2768,10 @@ ShaderGraphEditor::ShaderGraphEditor(bool p_2d) { tabs->add_child(graph_edits[i]->get_graph_edit()); graph_edits[i]->get_graph_edit()->connect("connection_request",graph_edits[i],"_connection_request"); graph_edits[i]->get_graph_edit()->connect("disconnection_request",graph_edits[i],"_disconnection_request"); + graph_edits[i]->get_graph_edit()->connect("duplicate_nodes_request", graph_edits[i], "_duplicate_nodes_request"); + graph_edits[i]->get_graph_edit()->connect("popup_request",this,"_popup_requested"); + graph_edits[i]->get_graph_edit()->connect("delete_nodes_request",graph_edits[i],"_delete_nodes_request"); graph_edits[i]->get_graph_edit()->set_right_disconnects(true); - } tabs->set_current_tab(1); @@ -2374,9 +2819,9 @@ ShaderGraphEditorPlugin::ShaderGraphEditorPlugin(EditorNode *p_node, bool p_2d) 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(); + // editor->get_viewport()->add_child(shader_editor); + // shader_editor->set_area_as_parent_rect(); + // shader_editor->hide(); } diff --git a/tools/editor/plugins/shader_graph_editor_plugin.h b/tools/editor/plugins/shader_graph_editor_plugin.h index 0051fbfd74..39e9b29d45 100644 --- a/tools/editor/plugins/shader_graph_editor_plugin.h +++ b/tools/editor/plugins/shader_graph_editor_plugin.h @@ -129,6 +129,7 @@ class ShaderGraphView : public Node { GraphEdit *graph_edit; Ref<ShaderGraph> graph; int edited_id; + int edited_def; ShaderGraph::ShaderType type; @@ -136,13 +137,23 @@ class ShaderGraphView : public Node { void _create_node(int p_id); + ToolButton *make_label(String text, Variant::Type v_type = Variant::NIL); + ToolButton *make_editor(String text, GraphNode* gn, int p_id, int param, Variant::Type type, String p_hint=""); void _connection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot); void _disconnection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot); void _node_removed(int p_id); + void _begin_node_move(); void _node_moved(const Vector2& p_from, const Vector2& p_to,int p_id); + void _end_node_move(); void _move_node(int p_id,const Vector2& p_to); + void _duplicate_nodes_request(); + void _duplicate_nodes(const Array &p_nodes); + void _delete_nodes_request(); + + + void _default_changed(int p_id, Node* p_button, int p_param, int v_type, String p_hint); void _scalar_const_changed(double p_value,int p_id); void _vec_const_changed(double p_value, int p_id, Array p_arr); @@ -175,7 +186,7 @@ protected: static void _bind_methods(); public: - void add_node(int p_type); + void add_node(int p_type, const Vector2 &location); GraphEdit *get_graph_edit() { return graph_edit; } void set_graph(Ref<ShaderGraph> p_graph); @@ -186,13 +197,15 @@ class ShaderGraphEditor : public VBoxContainer { OBJ_TYPE(ShaderGraphEditor,VBoxContainer); - MenuButton *menu; + PopupMenu *popup; TabContainer *tabs; ShaderGraphView *graph_edits[ShaderGraph::SHADER_TYPE_MAX]; static const char* node_names[ShaderGraph::NODE_TYPE_MAX]; + Vector2 next_location; bool _2d; void _add_node(int p_type); + void _popup_requested(const Vector2 &p_position); protected: void _notification(int p_what); static void _bind_methods(); diff --git a/tools/editor/plugins/spatial_editor_plugin.cpp b/tools/editor/plugins/spatial_editor_plugin.cpp index 77663f39c0..3ab9339265 100644 --- a/tools/editor/plugins/spatial_editor_plugin.cpp +++ b/tools/editor/plugins/spatial_editor_plugin.cpp @@ -677,7 +677,8 @@ bool SpatialEditorViewport::_gizmo_select(const Vector2& p_screenpos,bool p_hili void SpatialEditorViewport::_smouseenter() { - surface->grab_focus(); + if (!surface->has_focus() && (!get_focus_owner() || !get_focus_owner()->is_text_field())) + surface->grab_focus(); } void SpatialEditorViewport::_sinput(const InputEvent &p_event) { @@ -2168,7 +2169,18 @@ void SpatialEditorViewport::set_state(const Dictionary& p_state) { view_menu->get_popup()->set_item_checked( idx, listener ); } - + if (p_state.has("previewing")) { + Node *pv = EditorNode::get_singleton()->get_edited_scene()->get_node(p_state["previewing"]); + if (pv && pv->cast_to<Camera>()) { + previewing=pv->cast_to<Camera>(); + previewing->connect("exit_tree",this,"_preview_exited_scene"); + VS::get_singleton()->viewport_attach_camera( viewport->get_viewport(), previewing->get_camera() ); //replace + view_menu->hide(); + surface->update(); + preview_camera->set_pressed(true); + preview_camera->show(); + } + } } Dictionary SpatialEditorViewport::get_state() const { @@ -2181,6 +2193,10 @@ Dictionary SpatialEditorViewport::get_state() const { d["use_environment"]=camera->get_environment().is_valid(); d["use_orthogonal"]=camera->get_projection()==Camera::PROJECTION_ORTHOGONAL; d["listener"]=viewport->is_audio_listener(); + if (previewing) { + d["previewing"]=EditorNode::get_singleton()->get_edited_scene()->get_path_to(previewing); + } + return d; } diff --git a/tools/editor/plugins/sprite_region_editor_plugin.cpp b/tools/editor/plugins/sprite_region_editor_plugin.cpp new file mode 100644 index 0000000000..35c53cf562 --- /dev/null +++ b/tools/editor/plugins/sprite_region_editor_plugin.cpp @@ -0,0 +1,565 @@ +/*************************************************************************/ +/* sprite_region_editor_plugin.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Author: Mariano Suligoy */ +/* */ +/* 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 "sprite_region_editor_plugin.h" +#include "scene/gui/check_box.h" +#include "os/input.h" +#include "os/keyboard.h" + +void SpriteRegionEditor::_region_draw() +{ + Ref<Texture> base_tex = node->get_texture(); + if (base_tex.is_null()) + return; + + Matrix32 mtx; + mtx.elements[2]=-draw_ofs; + mtx.scale_basis(Vector2(draw_zoom,draw_zoom)); + + VS::get_singleton()->canvas_item_set_clip(edit_draw->get_canvas_item(),true); + VS::get_singleton()->canvas_item_add_set_transform(edit_draw->get_canvas_item(),mtx); + edit_draw->draw_texture(base_tex,Point2()); + VS::get_singleton()->canvas_item_add_set_transform(edit_draw->get_canvas_item(),Matrix32()); + + if (snap_show_grid) { + Size2 s = edit_draw->get_size(); + int last_cell; + + if (snap_step.x!=0) { + for(int i=0;i<s.width;i++) { + int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(i,0)).x-snap_offset.x)/snap_step.x)); + if (i==0) + last_cell=cell; + if (last_cell!=cell) + edit_draw->draw_line(Point2(i,0),Point2(i,s.height),Color(0.3,0.7,1,0.3)); + last_cell=cell; + } + } + + if (snap_step.y!=0) { + for(int i=0;i<s.height;i++) { + int cell = Math::fast_ftoi(Math::floor((mtx.affine_inverse().xform(Vector2(0,i)).y-snap_offset.y)/snap_step.y)); + if (i==0) + last_cell=cell; + if (last_cell!=cell) + edit_draw->draw_line(Point2(0,i),Point2(s.width,i),Color(0.3,0.7,1,0.3)); + last_cell=cell; + } + } + } + + Ref<Texture> select_handle = get_icon("EditorHandle","EditorIcons"); + + Rect2 scroll_rect(Point2(),mtx.basis_xform(base_tex->get_size())); + scroll_rect.expand_to(mtx.basis_xform(edit_draw->get_size())); + + Vector2 endpoints[4]={ + mtx.basis_xform(rect.pos), + mtx.basis_xform(rect.pos+Vector2(rect.size.x,0)), + mtx.basis_xform(rect.pos+rect.size), + mtx.basis_xform(rect.pos+Vector2(0,rect.size.y)) + }; + + for(int i=0;i<4;i++) { + + int prev = (i+3)%4; + int next = (i+1)%4; + + Vector2 ofs = ((endpoints[i] - endpoints[prev]).normalized() + ((endpoints[i] - endpoints[next]).normalized())).normalized(); + ofs*=1.4144*(select_handle->get_size().width/2); + + edit_draw->draw_line(endpoints[i]-draw_ofs, endpoints[next]-draw_ofs, Color(0.9,0.5,0.5), 2); + + edit_draw->draw_texture(select_handle,(endpoints[i]+ofs-(select_handle->get_size()/2)).floor()-draw_ofs); + + ofs = (endpoints[next]-endpoints[i])/2; + ofs += (endpoints[next]-endpoints[i]).tangent().normalized()*(select_handle->get_size().width/2); + + edit_draw->draw_texture(select_handle,(endpoints[i]+ofs-(select_handle->get_size()/2)).floor()-draw_ofs); + + scroll_rect.expand_to(endpoints[i]); + } + + scroll_rect=scroll_rect.grow(200); + updating_scroll=true; + hscroll->set_min(scroll_rect.pos.x); + hscroll->set_max(scroll_rect.pos.x+scroll_rect.size.x); + hscroll->set_page(edit_draw->get_size().x); + hscroll->set_val(draw_ofs.x); + hscroll->set_step(0.001); + + vscroll->set_min(scroll_rect.pos.y); + vscroll->set_max(scroll_rect.pos.y+scroll_rect.size.y); + vscroll->set_page(edit_draw->get_size().y); + vscroll->set_val(draw_ofs.y); + vscroll->set_step(0.001); + updating_scroll=false; +} + +void SpriteRegionEditor::_region_input(const InputEvent& p_input) +{ + Matrix32 mtx; + mtx.elements[2]=-draw_ofs; + mtx.scale_basis(Vector2(draw_zoom,draw_zoom)); + + Vector2 endpoints[8]={ + mtx.xform(rect.pos)+Vector2(-4,-4), + mtx.xform(rect.pos+Vector2(rect.size.x/2,0))+Vector2(0,-4), + mtx.xform(rect.pos+Vector2(rect.size.x,0))+Vector2(4,-4), + mtx.xform(rect.pos+Vector2(rect.size.x,rect.size.y/2))+Vector2(4,0), + mtx.xform(rect.pos+rect.size)+Vector2(4,4), + mtx.xform(rect.pos+Vector2(rect.size.x/2,rect.size.y))+Vector2(0,4), + mtx.xform(rect.pos+Vector2(0,rect.size.y))+Vector2(-4,4), + mtx.xform(rect.pos+Vector2(0,rect.size.y/2))+Vector2(-4,0) + }; + + if (p_input.type==InputEvent::MOUSE_BUTTON) { + + + const InputEventMouseButton &mb=p_input.mouse_button; + + if (mb.button_index==BUTTON_LEFT) { + + + if (mb.pressed) { + + drag_from=mtx.affine_inverse().xform(Vector2(mb.x,mb.y)); + drag_from=snap_point(drag_from); + drag=true; + rect_prev=node->get_region_rect(); + + drag_index=-1; + for(int i=0;i<8;i++) { + + Vector2 tuv=endpoints[i]; + if (tuv.distance_to(Vector2(mb.x,mb.y))<8) { + drag_index=i; + creating = false; + } + } + + if (drag_index==-1) { + creating = true; + rect = Rect2(drag_from,Size2()); + } + + } else if (drag) { + + undo_redo->create_action("Set region_rect"); + undo_redo->add_do_method(node,"set_region_rect",node->get_region_rect()); + undo_redo->add_undo_method(node,"set_region_rect",rect_prev); + undo_redo->add_do_method(edit_draw,"update"); + undo_redo->add_undo_method(edit_draw,"update"); + undo_redo->commit_action(); + + drag=false; + } + + } else if (mb.button_index==BUTTON_RIGHT && mb.pressed) { + + if (drag) { + drag=false; + node->set_region_rect(rect_prev); + rect=rect_prev; + edit_draw->update(); + } + + } else if (mb.button_index==BUTTON_WHEEL_UP && mb.pressed) { + + zoom->set_val( zoom->get_val()/0.9 ); + } else if (mb.button_index==BUTTON_WHEEL_DOWN && mb.pressed) { + + zoom->set_val( zoom->get_val()*0.9); + } + + } else if (p_input.type==InputEvent::MOUSE_MOTION) { + + const InputEventMouseMotion &mm=p_input.mouse_motion; + + if (mm.button_mask&BUTTON_MASK_MIDDLE || Input::get_singleton()->is_key_pressed(KEY_SPACE)) { + + Vector2 draged(mm.relative_x,mm.relative_y); + hscroll->set_val( hscroll->get_val()-draged.x ); + vscroll->set_val( vscroll->get_val()-draged.y ); + + } else if (drag) { + + Vector2 new_pos = mtx.affine_inverse().xform(Vector2(mm.x,mm.y)); + new_pos = snap_point(new_pos); + + if (creating) { + rect = Rect2(drag_from,Size2()); + rect.expand_to(new_pos); + node->set_region_rect(rect); + edit_draw->update(); + return; + } + + switch(drag_index) { + case 0: { + Vector2 p=rect_prev.pos+rect_prev.size; + rect = Rect2(p,Size2()); + rect.expand_to(new_pos); + node->set_region_rect(rect); + } break; + case 1: { + Vector2 p=rect_prev.pos+Vector2(0,rect_prev.size.y); + rect = Rect2(p,Size2(rect_prev.size.x,0)); + rect.expand_to(new_pos); + node->set_region_rect(rect); + } break; + case 2: { + Vector2 p=rect_prev.pos+Vector2(0,rect_prev.size.y); + rect = Rect2(p,Size2()); + rect.expand_to(new_pos); + node->set_region_rect(rect); + } break; + case 3: { + Vector2 p=rect_prev.pos; + rect = Rect2(p,Size2(0,rect_prev.size.y)); + rect.expand_to(new_pos); + node->set_region_rect(rect); + } break; + case 4: { + Vector2 p=rect_prev.pos; + rect = Rect2(p,Size2()); + rect.expand_to(new_pos); + node->set_region_rect(rect); + } break; + case 5: { + Vector2 p=rect_prev.pos; + rect = Rect2(p,Size2(rect_prev.size.x,0)); + rect.expand_to(new_pos); + node->set_region_rect(rect); + } break; + case 6: { + Vector2 p=rect_prev.pos+Vector2(rect_prev.size.x,0); + rect = Rect2(p,Size2()); + rect.expand_to(new_pos); + node->set_region_rect(rect); + } break; + case 7: { + Vector2 p=rect_prev.pos+Vector2(rect_prev.size.x,0); + rect = Rect2(p,Size2(0,rect_prev.size.y)); + rect.expand_to(new_pos); + node->set_region_rect(rect); + } break; + + } + edit_draw->update(); + } + + } +} + +void SpriteRegionEditor::_scroll_changed(float) +{ + if (updating_scroll) + return; + + draw_ofs.x=hscroll->get_val(); + draw_ofs.y=vscroll->get_val(); + draw_zoom=zoom->get_val(); + print_line("_scroll_changed"); + edit_draw->update(); +} + +void SpriteRegionEditor::_set_use_snap(bool p_use) +{ + use_snap=p_use; +} + +void SpriteRegionEditor::_set_show_grid(bool p_show) +{ + snap_show_grid=p_show; + edit_draw->update(); +} + +void SpriteRegionEditor::_set_snap_off_x(float p_val) +{ + snap_offset.x=p_val; + edit_draw->update(); +} + +void SpriteRegionEditor::_set_snap_off_y(float p_val) +{ + snap_offset.y=p_val; + edit_draw->update(); +} + +void SpriteRegionEditor::_set_snap_step_x(float p_val) +{ + snap_step.x=p_val; + edit_draw->update(); +} + +void SpriteRegionEditor::_set_snap_step_y(float p_val) +{ + snap_step.y=p_val; + edit_draw->update(); +} + +void SpriteRegionEditor::_notification(int p_what) +{ + switch(p_what) { + + case NOTIFICATION_READY: { + edit_node->set_icon( get_icon("RegionEdit","EditorIcons")); + b_snap_grid->set_icon( get_icon("Grid", "EditorIcons")); + b_snap_enable->set_icon( get_icon("Snap", "EditorIcons")); + icon_zoom->set_texture( get_icon("Zoom", "EditorIcons")); + } break; + } +} + +void SpriteRegionEditor::_node_removed(Node *p_node) +{ + if(p_node==node) { + node=NULL; + hide(); + } +} + +void SpriteRegionEditor::_bind_methods() +{ + ObjectTypeDB::bind_method(_MD("_edit_node"),&SpriteRegionEditor::_edit_node); + ObjectTypeDB::bind_method(_MD("_region_draw"),&SpriteRegionEditor::_region_draw); + ObjectTypeDB::bind_method(_MD("_region_input"),&SpriteRegionEditor::_region_input); + ObjectTypeDB::bind_method(_MD("_scroll_changed"),&SpriteRegionEditor::_scroll_changed); + ObjectTypeDB::bind_method(_MD("_node_removed"),&SpriteRegionEditor::_node_removed); + ObjectTypeDB::bind_method(_MD("_set_use_snap"),&SpriteRegionEditor::_set_use_snap); + ObjectTypeDB::bind_method(_MD("_set_show_grid"),&SpriteRegionEditor::_set_show_grid); + ObjectTypeDB::bind_method(_MD("_set_snap_off_x"),&SpriteRegionEditor::_set_snap_off_x); + ObjectTypeDB::bind_method(_MD("_set_snap_off_y"),&SpriteRegionEditor::_set_snap_off_y); + ObjectTypeDB::bind_method(_MD("_set_snap_step_x"),&SpriteRegionEditor::_set_snap_step_x); + ObjectTypeDB::bind_method(_MD("_set_snap_step_y"),&SpriteRegionEditor::_set_snap_step_y); +} + +void SpriteRegionEditor::edit(Node *p_sprite) +{ + if (p_sprite) { + node=p_sprite->cast_to<Sprite>(); + node->connect("exit_tree",this,"_node_removed",varray(),CONNECT_ONESHOT); + } else { + if (node) + node->disconnect("exit_tree",this,"_node_removed"); + node=NULL; + } + +} +void SpriteRegionEditor::_edit_node() +{ + if (node->get_texture().is_null()) { + + error->set_text("No texture in this sprite.\nSet a texture to be able to edit Region."); + error->popup_centered_minsize(); + return; + } + + rect=node->get_region_rect(); + dlg_editor->popup_centered_ratio(0.85); +} + +inline float _snap_scalar(float p_offset, float p_step, float p_target) { + return p_step != 0 ? Math::stepify(p_target - p_offset, p_step) + p_offset : p_target; +} + +Vector2 SpriteRegionEditor::snap_point(Vector2 p_target) const { + if (use_snap) { + p_target.x = _snap_scalar(snap_offset.x, snap_step.x, p_target.x); + p_target.y = _snap_scalar(snap_offset.y, snap_step.y, p_target.y); + } + p_target = p_target.snapped(Size2(1, 1)); + + return p_target; +} + +SpriteRegionEditor::SpriteRegionEditor(EditorNode* p_editor) +{ + node=NULL; + editor=p_editor; + undo_redo = editor->get_undo_redo(); + + snap_step=Vector2(10,10); + use_snap=false; + snap_show_grid=false; + + add_child( memnew( VSeparator )); + edit_node = memnew( ToolButton ); + add_child(edit_node); + edit_node->connect("pressed",this,"_edit_node"); + + dlg_editor = memnew( AcceptDialog ); + add_child(dlg_editor); + dlg_editor->set_title("Sprite Region Editor"); + dlg_editor->set_self_opacity(0.9); + + VBoxContainer *main_vb = memnew( VBoxContainer ); + dlg_editor->add_child(main_vb); + dlg_editor->set_child_rect(main_vb); + HBoxContainer *hb_tools = memnew( HBoxContainer ); + main_vb->add_child(hb_tools); + + b_snap_enable = memnew( ToolButton ); + hb_tools->add_child(b_snap_enable); + b_snap_enable->set_text("Snap"); + b_snap_enable->set_focus_mode(FOCUS_NONE); + b_snap_enable->set_toggle_mode(true); + b_snap_enable->set_pressed(use_snap); + b_snap_enable->set_tooltip("Enable Snap"); + b_snap_enable->connect("toggled",this,"_set_use_snap"); + + b_snap_grid = memnew( ToolButton ); + hb_tools->add_child(b_snap_grid); + b_snap_grid->set_text("Grid"); + b_snap_grid->set_focus_mode(FOCUS_NONE); + b_snap_grid->set_toggle_mode(true); + b_snap_grid->set_pressed(snap_show_grid); + b_snap_grid->set_tooltip("Show Grid"); + b_snap_grid->connect("toggled",this,"_set_show_grid"); + + hb_tools->add_child( memnew( VSeparator )); + hb_tools->add_child( memnew( Label("Grid Offset:") ) ); + + SpinBox *sb_off_x = memnew( SpinBox ); + sb_off_x->set_min(-256); + sb_off_x->set_max(256); + sb_off_x->set_step(1); + sb_off_x->set_val(snap_offset.x); + sb_off_x->set_suffix("px"); + sb_off_x->connect("value_changed", this, "_set_snap_off_x"); + hb_tools->add_child(sb_off_x); + + SpinBox *sb_off_y = memnew( SpinBox ); + sb_off_y->set_min(-256); + sb_off_y->set_max(256); + sb_off_y->set_step(1); + sb_off_y->set_val(snap_offset.y); + sb_off_y->set_suffix("px"); + sb_off_y->connect("value_changed", this, "_set_snap_off_y"); + hb_tools->add_child(sb_off_y); + + hb_tools->add_child( memnew( VSeparator )); + hb_tools->add_child( memnew( Label("Grid Step:") ) ); + + SpinBox *sb_step_x = memnew( SpinBox ); + sb_step_x->set_min(-256); + sb_step_x->set_max(256); + sb_step_x->set_step(1); + sb_step_x->set_val(snap_step.x); + sb_step_x->set_suffix("px"); + sb_step_x->connect("value_changed", this, "_set_snap_step_x"); + hb_tools->add_child(sb_step_x); + + SpinBox *sb_step_y = memnew( SpinBox ); + sb_step_y->set_min(-256); + sb_step_y->set_max(256); + sb_step_y->set_step(1); + sb_step_y->set_val(snap_step.y); + sb_step_y->set_suffix("px"); + sb_step_y->connect("value_changed", this, "_set_snap_step_y"); + hb_tools->add_child(sb_step_y); + +// MARIANOGNU::TODO: Add more tools? + + HBoxContainer *main_hb = memnew( HBoxContainer ); + main_vb->add_child(main_hb); + edit_draw = memnew( Control ); + main_hb->add_child(edit_draw); + main_hb->set_v_size_flags(SIZE_EXPAND_FILL); + edit_draw->set_h_size_flags(SIZE_EXPAND_FILL); + + + hb_tools->add_child( memnew( VSeparator )); + icon_zoom = memnew( TextureFrame ); + hb_tools->add_child(icon_zoom); + + zoom = memnew( HSlider ); + zoom->set_min(0.01); + zoom->set_max(4); + zoom->set_val(1); + zoom->set_step(0.01); + hb_tools->add_child(zoom); + zoom->set_custom_minimum_size(Size2(200,0)); + zoom_value = memnew( SpinBox ); + zoom->share(zoom_value); + zoom_value->set_custom_minimum_size(Size2(50,0)); + hb_tools->add_child(zoom_value); + zoom->connect("value_changed",this,"_scroll_changed"); + + + + vscroll = memnew( VScrollBar); + main_hb->add_child(vscroll); + vscroll->connect("value_changed",this,"_scroll_changed"); + hscroll = memnew( HScrollBar ); + main_vb->add_child(hscroll); + hscroll->connect("value_changed",this,"_scroll_changed"); + + edit_draw->connect("draw",this,"_region_draw"); + edit_draw->connect("input_event",this,"_region_input"); + draw_zoom=1.0; + updating_scroll=false; + + error = memnew( AcceptDialog); + add_child(error); + +} + +void SpriteRegionEditorPlugin::edit(Object *p_node) +{ + region_editor->edit(p_node->cast_to<Node>()); +} + +bool SpriteRegionEditorPlugin::handles(Object *p_node) const +{ + return p_node->is_type("Sprite"); +} + +void SpriteRegionEditorPlugin::make_visible(bool p_visible) +{ + if (p_visible) { + region_editor->show(); + } else { + region_editor->hide(); + region_editor->edit(NULL); + } +} + +SpriteRegionEditorPlugin::SpriteRegionEditorPlugin(EditorNode *p_node) +{ + editor = p_node; + region_editor= memnew ( SpriteRegionEditor(p_node) ); + CanvasItemEditor::get_singleton()->add_control_to_menu_panel(region_editor); + + region_editor->hide(); +} + diff --git a/tools/editor/plugins/sprite_region_editor_plugin.h b/tools/editor/plugins/sprite_region_editor_plugin.h new file mode 100644 index 0000000000..cf69395f40 --- /dev/null +++ b/tools/editor/plugins/sprite_region_editor_plugin.h @@ -0,0 +1,125 @@ +/*************************************************************************/ +/* sprite_region_editor_plugin.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2015 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Author: Mariano Suligoy */ +/* */ +/* 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 SPRITE_REGION_EDITOR_PLUGIN_H +#define SPRITE_REGION_EDITOR_PLUGIN_H + +#include "canvas_item_editor_plugin.h" +#include "tools/editor/editor_plugin.h" +#include "tools/editor/editor_node.h" +#include "scene/2d/sprite.h" + +class SpriteRegionEditor : public HBoxContainer { + + OBJ_TYPE(SpriteRegionEditor, HBoxContainer ); + + ToolButton *edit_node; +// Button *use_region; + ToolButton *b_snap_enable; + ToolButton *b_snap_grid; + TextureFrame *icon_zoom; + HSlider *zoom; + SpinBox *zoom_value; + Control *edit_draw; + + VScrollBar *vscroll; + HScrollBar *hscroll; + + Sprite *node; + EditorNode *editor; + AcceptDialog *dlg_editor; + UndoRedo* undo_redo; + + Vector2 draw_ofs; + float draw_zoom; + bool updating_scroll; + + bool use_snap; + bool snap_show_grid; + Vector2 snap_offset; + Vector2 snap_step; + + Rect2 rect; + Rect2 rect_prev; + bool drag; + bool creating; + Vector2 drag_from; + int drag_index; + + AcceptDialog *error; + + void _set_use_snap(bool p_use); + void _set_show_grid(bool p_show); + void _set_snap_off_x(float p_val); + void _set_snap_off_y(float p_val); + void _set_snap_step_x(float p_val); + void _set_snap_step_y(float p_val); + +protected: + + void _notification(int p_what); + void _node_removed(Node *p_node); + static void _bind_methods(); + + Vector2 snap_point(Vector2 p_target) const; + +public: + + void edit(); + void _edit_node(); + void _region_draw(); + void _region_input(const InputEvent &p_input); + void _scroll_changed(float); + + void edit(Node *p_sprite); + SpriteRegionEditor(EditorNode* p_editor); + +}; + +class SpriteRegionEditorPlugin : public EditorPlugin +{ + + OBJ_TYPE( SpriteRegionEditorPlugin, EditorPlugin ); + + SpriteRegionEditor *region_editor; + EditorNode *editor; +public: + + virtual String get_name() const { return "Sprite"; } + 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); + + SpriteRegionEditorPlugin(EditorNode *p_node); +}; + +#endif // SPRITE_REGION_EDITOR_PLUGIN_H diff --git a/tools/editor/plugins/tile_map_editor_plugin.cpp b/tools/editor/plugins/tile_map_editor_plugin.cpp index 017a26441d..66c7a39096 100644 --- a/tools/editor/plugins/tile_map_editor_plugin.cpp +++ b/tools/editor/plugins/tile_map_editor_plugin.cpp @@ -107,8 +107,8 @@ void TileMapEditor::_set_cell(const Point2i& p_pos,int p_value,bool p_flip_h, bo if (p_with_undo) { - undo_redo->add_do_method(this,"_set_cell_shortened",Point2(p_pos),p_value,p_flip_h,p_flip_v,p_transpose); - undo_redo->add_undo_method(this,"_set_cell_shortened",Point2(p_pos),prev_val,prev_flip_h,prev_flip_v,prev_transpose); + undo_redo->add_do_method(node,"set_cellv",Point2(p_pos),p_value,p_flip_h,p_flip_v,p_transpose); + undo_redo->add_undo_method(node,"set_cellv",Point2(p_pos),prev_val,prev_flip_h,prev_flip_v,prev_transpose); } else { node->set_cell(p_pos.x,p_pos.y,p_value,p_flip_h,p_flip_v,p_transpose); @@ -314,8 +314,8 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { for(Map<Point2i,CellOp>::Element *E=paint_undo.front();E;E=E->next()) { Point2i p=E->key(); - undo_redo->add_do_method(this,"_set_cell_shortened",Point2(p),node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y),node->is_cell_transposed(p.x,p.y)); - undo_redo->add_undo_method(this,"_set_cell_shortened",Point2(p),E->get().idx,E->get().xf,E->get().yf,E->get().tr); + undo_redo->add_do_method(node,"set_cellv",Point2(p),node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y),node->is_cell_transposed(p.x,p.y)); + undo_redo->add_undo_method(node,"set_cellv",Point2(p),E->get().idx,E->get().xf,E->get().yf,E->get().tr); } undo_redo->commit_action(); @@ -344,7 +344,7 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { //return true; _set_cell(local,TileMap::INVALID_CELL); return true; - } else { + } else if (!mb.pressed) { if (tool==TOOL_ERASING) { @@ -353,9 +353,10 @@ bool TileMapEditor::forward_input_event(const InputEvent& p_event) { for(Map<Point2i,CellOp>::Element *E=paint_undo.front();E;E=E->next()) { Point2i p=E->key(); - //undo_redo->add_do_method(node,"set_cell",p.x,p.y,node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y),node->is_cell_transposed(p.x,p.y)); - _set_cell(p,TileMap::INVALID_CELL,false,false,false,true); - undo_redo->add_undo_method(this,"_set_cell_shortened",Point2(p),E->get().idx,E->get().xf,E->get().yf,E->get().tr); + //undo_redo->add_do_method(node,"set_cell",p,node->get_cell(p.x,p.y),node->is_cell_x_flipped(p.x,p.y),node->is_cell_y_flipped(p.x,p.y),node->is_cell_transposed(p.x,p.y)); + //_set_cell(p,TileMap::INVALID_CELL,false,false,false,true); + undo_redo->add_do_method(node,"set_cellv",Point2(p),TileMap::INVALID_CELL,false,false,false); + undo_redo->add_undo_method(node,"set_cellv",Point2(p),E->get().idx,E->get().xf,E->get().yf,E->get().tr); } undo_redo->commit_action(); |