summaryrefslogtreecommitdiff
path: root/tools/editor/plugins
diff options
context:
space:
mode:
authorJuan Linietsky <reduzio@gmail.com>2015-01-03 16:52:37 -0300
committerJuan Linietsky <reduzio@gmail.com>2015-01-03 16:52:37 -0300
commitfbdd925d9be1c4c96d05089d7d5a58cd938b002c (patch)
tree9f4eb2ae7c61450dffb4a86bb5e82cf66e23d496 /tools/editor/plugins
parenteb1f978b1c1693018e9a6d353ca914f8e6586b4e (diff)
-Work in progress visual shader editor *DOES NOT WORK YET*
Diffstat (limited to 'tools/editor/plugins')
-rw-r--r--tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp2
-rw-r--r--tools/editor/plugins/shader_graph_editor_plugin.cpp2041
-rw-r--r--tools/editor/plugins/shader_graph_editor_plugin.h171
3 files changed, 1280 insertions, 934 deletions
diff --git a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp
index 6bae0d2fd0..ed228e9a1c 100644
--- a/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp
+++ b/tools/editor/plugins/collision_polygon_2d_editor_plugin.cpp
@@ -398,11 +398,13 @@ CollisionPolygon2DEditor::CollisionPolygon2DEditor(EditorNode *p_editor) {
add_child(button_create);
button_create->connect("pressed",this,"_menu_option",varray(MODE_CREATE));
button_create->set_toggle_mode(true);
+ button_create->set_tooltip("Create a new polygon from scratch");
button_edit = memnew( ToolButton );
add_child(button_edit);
button_edit->connect("pressed",this,"_menu_option",varray(MODE_EDIT));
button_edit->set_toggle_mode(true);
+ button_edit->set_tooltip("Edit existing polygon:\nLMB: Move Point.\nCtrl+LMB: Split Segment.\nRMB: Erase Point.");
//add_constant_override("separation",0);
diff --git a/tools/editor/plugins/shader_graph_editor_plugin.cpp b/tools/editor/plugins/shader_graph_editor_plugin.cpp
index 2686ca895e..710f11e726 100644
--- a/tools/editor/plugins/shader_graph_editor_plugin.cpp
+++ b/tools/editor/plugins/shader_graph_editor_plugin.cpp
@@ -28,1082 +28,1427 @@
/*************************************************************************/
#include "shader_graph_editor_plugin.h"
-#if 0
+
#include "scene/gui/menu_button.h"
#include "scene/gui/panel.h"
+#include "spatial_editor_plugin.h"
+
+////cbacks
+///
+void ShaderGraphView::_scalar_const_changed(double p_value,int p_id) {
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change Scalar Constant",true);
+ ur->add_do_method(graph.ptr(),"scalar_const_node_set_value",type,p_id,p_value);
+ ur->add_undo_method(graph.ptr(),"scalar_const_node_set_value",type,p_id,graph->scalar_const_node_get_value(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+}
-class _ShaderTester : public ShaderCodeGenerator {
-public:
-
- Set<int> *_set;
-
- virtual void begin() {}
- virtual Error add_node(VS::ShaderNodeType p_type,int p_node_pos,int p_id,const Variant& p_param,const Vector<int>& p_in_connections,const Vector<int>& p_out_connections,const Vector<int>& p_out_connection_outputs) { if (_set) _set->insert(p_id); return OK; }
- virtual void end() {}
-
- _ShaderTester() { _set=NULL; }
-};
+void ShaderGraphView::_vec_const_changed(double p_value, int p_id,Array p_arr){
+ Vector3 val;
+ for(int i=0;i<p_arr.size();i++) {
+ val[i]=p_arr[i].call("get_val");
+ }
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change Vec Constant",true);
+ ur->add_do_method(graph.ptr(),"vec_const_node_set_value",type,p_id,val);
+ ur->add_undo_method(graph.ptr(),"vec_const_node_set_value",type,p_id,graph->vec_const_node_get_value(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
-void ShaderEditor::edit(Ref<Shader> p_shader) {
+}
+void ShaderGraphView::_rgb_const_changed(const Color& p_color, int p_id){
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change RGB Constant",true);
+ ur->add_do_method(graph.ptr(),"rgb_const_node_set_value",type,p_id,p_color);
+ ur->add_undo_method(graph.ptr(),"rgb_const_node_set_value",type,p_id,graph->rgb_const_node_get_value(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+}
+void ShaderGraphView::_scalar_op_changed(int p_op, int p_id){
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change Scalar Operator");
+ ur->add_do_method(graph.ptr(),"scalar_op_node_set_op",type,p_id,p_op);
+ ur->add_undo_method(graph.ptr(),"scalar_op_node_set_op",type,p_id,graph->scalar_op_node_get_op(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
- shader=p_shader;
+}
+void ShaderGraphView::_vec_op_changed(int p_op, int p_id){
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change Vec Operator");
+ ur->add_do_method(graph.ptr(),"vec_op_node_set_op",type,p_id,p_op);
+ ur->add_undo_method(graph.ptr(),"vec_op_node_set_op",type,p_id,graph->vec_op_node_get_op(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+}
+void ShaderGraphView::_vec_scalar_op_changed(int p_op, int p_id){
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change VecxScalar Operator");
+ ur->add_do_method(graph.ptr(),"vec_scalar_op_node_set_op",type,p_id,p_op);
+ ur->add_undo_method(graph.ptr(),"vec_scalar_op_node_set_op",type,p_id,graph->vec_scalar_op_node_get_op(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
- if (shader.is_null())
- hide();
- else {
- _read_shader_graph();
- }
+}
+void ShaderGraphView::_rgb_op_changed(int p_op, int p_id){
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change RGB Operator");
+ ur->add_do_method(graph.ptr(),"rgb_op_node_set_op",type,p_id,p_op);
+ ur->add_undo_method(graph.ptr(),"rgb_op_node_set_op",type,p_id,graph->rgb_op_node_get_op(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+}
+void ShaderGraphView::_xform_inv_rev_changed(bool p_enabled, int p_id){
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Toggle Rot Only");
+ ur->add_do_method(graph.ptr(),"xform_vec_mult_node_set_no_translation",type,p_id,p_enabled);
+ ur->add_undo_method(graph.ptr(),"xform_vec_mult_node_set_no_translation",type,p_id,graph->xform_vec_mult_node_get_no_translation(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+}
+void ShaderGraphView::_scalar_func_changed(int p_func, int p_id){
+
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change Scalar Function");
+ ur->add_do_method(graph.ptr(),"scalar_func_node_set_function",type,p_id,p_func);
+ ur->add_undo_method(graph.ptr(),"scalar_func_node_set_function",type,p_id,graph->scalar_func_node_get_function(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+}
+void ShaderGraphView::_vec_func_changed(int p_func, int p_id){
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change Vec Function");
+ ur->add_do_method(graph.ptr(),"vec_func_node_set_function",type,p_id,p_func);
+ ur->add_undo_method(graph.ptr(),"vec_func_node_set_function",type,p_id,graph->vec_func_node_get_function(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
}
+void ShaderGraphView::_scalar_input_changed(double p_value,int p_id){
+
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change Scalar Uniform",true);
+ ur->add_do_method(graph.ptr(),"scalar_input_node_set_value",type,p_id,p_value);
+ ur->add_undo_method(graph.ptr(),"scalar_input_node_set_value",type,p_id,graph->scalar_input_node_get_value(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
-Size2 ShaderEditor::_get_maximum_size() {
+}
+void ShaderGraphView::_vec_input_changed(double p_value, int p_id,Array p_arr){
- Size2 max;
+ Vector3 val;
+ for(int i=0;i<p_arr.size();i++) {
+ val[i]=p_arr[i].call("get_val");
+ }
- for(List<int>::Element *E=order.front();E;E=E->next()) {
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change Vec Uniform",true);
+ ur->add_do_method(graph.ptr(),"vec_input_node_set_value",type,p_id,val);
+ ur->add_undo_method(graph.ptr(),"vec_input_node_set_value",type,p_id,graph->vec_input_node_get_value(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
- Point2 pos = Point2( shader_graph.node_get_pos_x(E->get()), shader_graph.node_get_pos_y(E->get()) );
+}
+void ShaderGraphView::_xform_input_changed(int p_id, Node *p_button){
- if (click_type==CLICK_NODE && click_node==E->get()) {
+ print_line("XFIC");
+ 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;
+ ped_popup->edit(NULL,"",Variant::TRANSFORM,graph->xform_input_node_get_value(type,p_id),PROPERTY_HINT_NONE,"");
+ ped_popup->popup();
- pos+=click_motion-click_pos;
- }
- pos+=get_node_size(E->get());
- if (pos.x>max.x)
- max.x=pos.x;
- if (pos.y>max.y)
- max.y=pos.y;
+}
+void ShaderGraphView::_xform_const_changed(int p_id, Node *p_button){
- }
+ 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;
+ ped_popup->edit(NULL,"",Variant::TRANSFORM,graph->xform_const_node_get_value(type,p_id),PROPERTY_HINT_NONE,"");
+ ped_popup->popup();
- return max;
}
-Size2 ShaderEditor::get_node_size(int p_node) const {
+void ShaderGraphView::_rgb_input_changed(const Color& p_color, int p_id){
- VisualServer::ShaderNodeType type=shader_graph.node_get_type(p_node);
- Ref<StyleBox> style = get_stylebox("panel","PopupMenu");
- Ref<Font> font = get_font("font","PopupMenu");
- Color font_color = get_color("font_color","PopupMenu");
- Size2 size = style->get_minimum_size();
-
- int count=1; // title
- count += VisualServer::shader_get_input_count( type) + VisualServer::shader_get_output_count( type);
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change RGB Uniform",true);
+ ur->add_do_method(graph.ptr(),"rgb_input_node_set_value",type,p_id,p_color);
+ ur->add_undo_method(graph.ptr(),"rgb_input_node_set_value",type,p_id,graph->rgb_input_node_get_value(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+}
+void ShaderGraphView::_tex_input_change(int p_id, Node *p_button){
- float max_w=font->get_string_size( VisualServer::shader_node_get_type_info(type).name ).width;
- for(int i=0;i<VisualServer::shader_get_input_count(type);i++)
- max_w = MAX( max_w, font->get_string_size( VisualServer::shader_get_input_name(type,i) ).width );
+}
+void ShaderGraphView::_cube_input_change(int p_id){
- for(int i=0;i<VisualServer::shader_get_output_count(type);i++)
- max_w = MAX( max_w, font->get_string_size( VisualServer::shader_get_output_name(type,i) ).width );
+}
+void ShaderGraphView::_variant_edited() {
+ if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_XFORM_CONST) {
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change XForm Uniform");
+ ur->add_do_method(graph.ptr(),"xform_const_node_set_value",type,edited_id,ped_popup->get_variant());
+ ur->add_undo_method(graph.ptr(),"xform_const_node_set_value",type,edited_id,graph->xform_const_node_get_value(type,edited_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
+ }
- switch(type) {
- case VS::NODE_IN:
- case VS::NODE_OUT:
- case VS::NODE_VEC_IN:
- case VS::NODE_VEC_OUT:
- case VS::NODE_PARAMETER:
- case VS::NODE_VEC_PARAMETER:
- case VS::NODE_COLOR_PARAMETER:
- case VS::NODE_TEXTURE_PARAMETER:
- case VS::NODE_TEXTURE_2D_PARAMETER:
- case VS::NODE_TEXTURE_CUBE_PARAMETER:
- case VS::NODE_TRANSFORM_PARAMETER:
- case VS::NODE_LABEL: {
+ if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_XFORM_INPUT) {
- max_w=MAX( max_w, font->get_string_size( shader_graph.node_get_param(p_node) ).width );
- count++;
- } break;
- case VS::NODE_TIME:
- case VS::NODE_CONSTANT:
- case VS::NODE_VEC_CONSTANT:
- case VS::NODE_COLOR_CONSTANT:
- case VS::NODE_TRANSFORM_CONSTANT: {
- count++;
- } break;
- case VS::NODE_TEXTURE:
- case VS::NODE_VEC_TEXTURE_2D:
- case VS::NODE_VEC_TEXTURE_CUBE: {
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change XForm Uniform");
+ ur->add_do_method(graph.ptr(),"xform_input_node_set_value",type,edited_id,ped_popup->get_variant());
+ ur->add_undo_method(graph.ptr(),"xform_input_node_set_value",type,edited_id,graph->xform_input_node_get_value(type,edited_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
+ }
- RefPtr res = shader_graph.node_get_param(p_node);
- Ref<Texture> texture = res;
- if (texture.is_null() || texture->get_width()==0) {
+ if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_TEXTURE_INPUT) {
- size.y+=max_w;
- } else {
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change Texture Uniform");
+ ur->add_do_method(graph.ptr(),"texture_input_node_set_value",type,edited_id,ped_popup->get_variant());
+ ur->add_undo_method(graph.ptr(),"texture_input_node_set_value",type,edited_id,graph->texture_input_node_get_value(type,edited_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
+ }
- size.y+=max_w * texture->get_height() / texture->get_width();
- }
- } break;
- default: {}
+ if (graph->node_get_type(type,edited_id)==ShaderGraph::NODE_CUBEMAP_INPUT) {
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change Cubemap Uniform");
+ ur->add_do_method(graph.ptr(),"cubemap_input_node_set_value",type,edited_id,ped_popup->get_variant());
+ ur->add_undo_method(graph.ptr(),"cubemap_input_node_set_value",type,edited_id,graph->cubemap_input_node_get_value(type,edited_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
}
- size.x+=max_w;
- size.y+=count*(font->get_height()+get_constant("vseparation","PopupMenu"));
-
- return size;
}
+void ShaderGraphView::_comment_edited(int p_id,Node* p_button) {
-Error ShaderEditor::validate_graph() {
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ TextEdit *te=p_button->cast_to<TextEdit>();
+ ur->create_action("Change Comment",true);
+ ur->add_do_method(graph.ptr(),"comment_node_set_text",type,p_id,te->get_text());
+ ur->add_undo_method(graph.ptr(),"comment_node_set_text",type,p_id,graph->comment_node_get_text(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
- _ShaderTester st;
- active_nodes.clear();
- st._set=&active_nodes;
- return shader_graph.generate(&st);
}
-void ShaderEditor::_draw_node(int p_node) {
- VisualServer::ShaderNodeType type=shader_graph.node_get_type(p_node);
- Ref<StyleBox> style = active_nodes.has(p_node)?get_stylebox("panel","PopupMenu"):get_stylebox("panel_disabled","PopupMenu");
- Ref<Font> font = get_font("font","PopupMenu");
- Color font_color = get_color("font_color","PopupMenu");
- Color font_color_title = get_color("font_color_hover","PopupMenu");
- Size2 size=get_node_size(p_node);
- Point2 pos = Point2( shader_graph.node_get_pos_x(p_node), shader_graph.node_get_pos_y(p_node) )-offset;
+void ShaderGraphView::_input_name_changed(const String& p_name, int p_id, Node *p_line_edit) {
- if (click_type==CLICK_NODE && click_node==p_node) {
+ LineEdit *le=p_line_edit->cast_to<LineEdit>();
+ ERR_FAIL_COND(!le);
- pos+=click_motion-click_pos;
- }
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Change Input Name");
+ ur->add_do_method(graph.ptr(),"input_node_set_name",type,p_id,p_name);
+ ur->add_undo_method(graph.ptr(),"input_node_set_name",type,p_id,graph->input_node_get_name(type,p_id));
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ block_update=true;
+ ur->commit_action();
+ block_update=false;
+ le->set_text(graph->input_node_get_name(type,p_id));
+}
- RID ci = get_canvas_item();
- style->draw(ci,Rect2(pos,size));
+void ShaderGraphView::_tex_edited(int p_id,Node* p_button) {
- Point2 ofs=style->get_offset()+pos;
- Point2 ascent=Point2(0,font->get_ascent());
- float w = size.width-style->get_minimum_size().width;
- float h = font->get_height()+get_constant("vseparation","PopupMenu");
+ 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;
+ ped_popup->edit(NULL,"",Variant::OBJECT,graph->texture_input_node_get_value(type,p_id),PROPERTY_HINT_RESOURCE_TYPE,"Texture");
+}
- font->draw_halign( ci, ofs+ascent, HALIGN_CENTER,w, VisualServer::shader_node_get_type_info(type).name,font_color_title);
- ofs.y+=h;
+void ShaderGraphView::_cube_edited(int p_id,Node* p_button) {
- Ref<Texture> vec_icon = get_icon("NodeVecSlot","EditorIcons");
- Ref<Texture> real_icon = get_icon("NodeRealSlot","EditorIcons");
- float icon_h_ofs = Math::floor(( font->get_height()-vec_icon->get_height())/2.0 )+1;
+ 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;
+ ped_popup->edit(NULL,"",Variant::OBJECT,graph->cubemap_input_node_get_value(type,p_id),PROPERTY_HINT_RESOURCE_TYPE,"CubeMap");
+}
- for(int i=0;i<VisualServer::shader_get_input_count(type);i++) {
+//////////////view/////////////
- String name = VisualServer::shader_get_input_name(type,i);
- font->draw_halign( ci, ofs+ascent, HALIGN_LEFT,w, name,font_color);
- Ref<Texture> icon = VisualServer::shader_is_input_vector(type,i)?vec_icon:real_icon;
- icon->draw(ci,ofs+Point2(-real_icon->get_width(),icon_h_ofs));
- ofs.y+=h;
- }
- for(int i=0;i<VisualServer::shader_get_output_count(type);i++) {
+void ShaderGraphView::_connection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot) {
- String name = VisualServer::shader_get_output_name(type,i);
- font->draw_halign( ci, ofs+ascent, HALIGN_RIGHT,w, name,font_color);
- Ref<Texture> icon = VisualServer::shader_is_output_vector(type,i)?vec_icon:real_icon;
- icon->draw(ci,ofs+Point2(w,icon_h_ofs));
- ofs.y+=h;
- }
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
- switch(type) {
-
- case VS::NODE_IN:
- case VS::NODE_OUT:
- case VS::NODE_PARAMETER:
- case VS::NODE_VEC_IN:
- case VS::NODE_COLOR_PARAMETER:
- case VS::NODE_VEC_OUT:
- case VS::NODE_TEXTURE_PARAMETER:
- case VS::NODE_TEXTURE_2D_PARAMETER:
- case VS::NODE_TEXTURE_CUBE_PARAMETER:
- case VS::NODE_TRANSFORM_CONSTANT:
- case VS::NODE_TRANSFORM_PARAMETER:
- case VS::NODE_VEC_PARAMETER:
- case VS::NODE_LABEL: {
- String text = shader_graph.node_get_param(p_node);
- font->draw_halign( ci, ofs+ascent, HALIGN_CENTER,w, text,font_color);
- } break;
- case VS::NODE_TIME:
- case VS::NODE_CONSTANT: {
- String text = rtos(shader_graph.node_get_param(p_node));
- font->draw_halign( ci, ofs+ascent, HALIGN_CENTER,w, text,font_color);
-
- } break;
- case VS::NODE_VEC_CONSTANT: {
- String text = Vector3(shader_graph.node_get_param(p_node));
- font->draw_halign( ci, ofs+ascent, HALIGN_CENTER,w, text,font_color);
- } break;
- case VS::NODE_COLOR_CONSTANT: {
-
- Color color = shader_graph.node_get_param(p_node);
- Rect2 r(ofs,Size2(w,h));
- VisualServer::get_singleton()->canvas_item_add_rect(ci,r,color);
- } break;
- case VS::NODE_TEXTURE:
- case VS::NODE_VEC_TEXTURE_2D:
- case VS::NODE_VEC_TEXTURE_CUBE: {
-
- Rect2 r(ofs,Size2(w,(pos.y+size.y-style->get_margin(MARGIN_BOTTOM))-ofs.y));
- Vector<Point2> points;
- Vector<Point2> uvs;
- points.resize(4);
- uvs.resize(4);
- points[0]=r.pos;
- points[1]=r.pos+Point2(r.size.x,0);
- points[2]=r.pos+r.size;
- points[3]=r.pos+Point2(0,r.size.y);
- uvs[0]=Point2(0,0);
- uvs[1]=Point2(1,0);
- uvs[2]=Point2(1,1);
- uvs[3]=Point2(0,1);
-
- Ref<Texture> texture = shader_graph.node_get_param(p_node).operator RefPtr();
- if (texture.is_null() || texture->get_width()==0) {
- texture=get_icon("Click2Edit","EditorIcons");
- }
+ int from_idx=-1;
+ int to_idx=-1;
+ for (Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) {
- VisualServer::get_singleton()->canvas_item_add_primitive(ci,points,Vector<Color>(),uvs,texture->get_rid());
- } break;
- default: {}
+ if (p_from==E->get()->get_name())
+ from_idx=E->key();
+ if (p_to==E->get()->get_name())
+ to_idx=E->key();
}
-}
-
-void ShaderEditor::_node_param_changed() {
-
- shader_graph.node_set_param( click_node,property_editor->get_variant() );
- update();
- _write_shader_graph();
-}
-
-ShaderEditor::ClickType ShaderEditor::_locate_click(const Point2& p_click,int *p_node_id,int *p_slot_index) const {
-
- Ref<StyleBox> style = get_stylebox("panel","PopupMenu");
- Ref<Texture> real_icon = get_icon("NodeRealSlot","EditorIcons");
- Ref<Font> font = get_font("font","PopupMenu");
- float h = font->get_height()+get_constant("vseparation","PopupMenu");
- float extra_left=MAX( real_icon->get_width()-style->get_margin(MARGIN_LEFT), 0 );
- float extra_right=MAX( real_icon->get_width()-style->get_margin(MARGIN_RIGHT), 0 );
+ ERR_FAIL_COND(from_idx==-1);
+ ERR_FAIL_COND(to_idx==-1);
- for(const List<int>::Element *E=order.back();E;E=E->prev()) {
+ ur->create_action("Connect Graph Nodes");
- Size2 size=get_node_size(E->get());
- size.width+=extra_left+extra_right;
- Point2 pos = Point2( shader_graph.node_get_pos_x(E->get()), shader_graph.node_get_pos_y(E->get()) )-offset;
- pos.x-=extra_left;
+ List<ShaderGraph::Connection> conns;
- Rect2 rect( pos, size );
- if (!rect.has_point(p_click))
- continue;
- VisualServer::ShaderNodeType type=shader_graph.node_get_type(E->get());
- if (p_node_id)
- *p_node_id=E->get();
- float y=p_click.y-(pos.y+style->get_margin(MARGIN_TOP));
- if (y<h)
- return CLICK_NODE;
- y-=h;
-
- for(int i=0;i<VisualServer::shader_get_input_count(type);i++) {
-
- if (y<h) {
- if (p_slot_index)
- *p_slot_index=i;
- return CLICK_INPUT_SLOT;
- }
- y-=h;
- }
+ graph->get_node_connections(type,&conns);
+ //disconnect/reconnect dependencies
+ ur->add_undo_method(graph.ptr(),"disconnect_node",type,from_idx,p_from_slot,to_idx,p_to_slot);
+ for(List<ShaderGraph::Connection>::Element *E=conns.front();E;E=E->next()) {
- for(int i=0;i<VisualServer::shader_get_output_count(type);i++) {
-
- if (y<h) {
- if (p_slot_index)
- *p_slot_index=i;
- return CLICK_OUTPUT_SLOT;
- }
- y-=h;
+ if (E->get().dst_id==to_idx && E->get().dst_slot==p_to_slot) {
+ ur->add_do_method(graph.ptr(),"disconnect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot);
+ ur->add_undo_method(graph.ptr(),"connect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot);
}
-
- if (p_click.y<(rect.pos.y+rect.size.height-style->get_margin(MARGIN_BOTTOM)))
- return CLICK_PARAMETER;
- else
- return CLICK_NODE;
-
}
+ ur->add_do_method(graph.ptr(),"connect_node",type,from_idx,p_from_slot,to_idx,p_to_slot);
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
- return CLICK_NONE;
}
-Point2 ShaderEditor::_get_slot_pos(int p_node_id,bool p_input,int p_slot) {
+void ShaderGraphView::_node_removed(int p_id) {
- Ref<StyleBox> style = get_stylebox("panel","PopupMenu");
- float w = get_node_size(p_node_id).width;
- Ref<Font> font = get_font("font","PopupMenu");
- float h = font->get_height()+get_constant("vseparation","PopupMenu");
- Ref<Texture> vec_icon = get_icon("NodeVecSlot","EditorIcons");
- Point2 pos = Point2( shader_graph.node_get_pos_x(p_node_id), shader_graph.node_get_pos_y(p_node_id) )-offset;
- pos+=style->get_offset();
- pos.y+=h;
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Remove Shader Graph Node");
- if(p_input) {
+ ur->add_do_method(graph.ptr(),"node_remove",type,p_id);
+ ur->add_undo_method(graph.ptr(),"node_add",type,graph->node_get_type(type,p_id),p_id);
+ ur->add_undo_method(graph.ptr(),"node_set_state",type,p_id,graph->node_get_state(type,p_id));
+ List<ShaderGraph::Connection> conns;
- pos.y+=p_slot*h;
- pos+=Point2( -vec_icon->get_width()/2.0, h/2.0).floor();
- return pos;
- } else {
+ graph->get_node_connections(type,&conns);
+ for(List<ShaderGraph::Connection>::Element *E=conns.front();E;E=E->next()) {
- pos.y+=VisualServer::shader_get_input_count( shader_graph.node_get_type(p_node_id ) )*h;
+ if (E->get().dst_id==p_id || E->get().src_id==p_id) {
+ ur->add_undo_method(graph.ptr(),"connect_node",type,E->get().src_id,E->get().src_slot,E->get().dst_id,E->get().dst_slot);
+ }
}
-
- pos.y+=p_slot*h;
- pos+=Point2( w-style->get_minimum_size().width+vec_icon->get_width()/2.0, h/2.0).floor();
-
- return pos;
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
}
-void ShaderEditor::_node_edit_property(int p_node) {
-
- Ref<StyleBox> style = get_stylebox("panel","PopupMenu");
- Size2 size = get_node_size(p_node);
- Point2 pos = Point2( shader_graph.node_get_pos_x(p_node), shader_graph.node_get_pos_y(p_node) )-offset;
-
- VisualServer::ShaderNodeType type=shader_graph.node_get_type(p_node);
-
- PropertyInfo ph = VisualServer::get_singleton()->shader_node_get_type_info(type);
- if (ph.type==Variant::NIL)
- return;
- if (ph.type==Variant::_RID)
- ph.type=Variant::OBJECT;
-
- property_editor->edit(NULL,ph.name,ph.type,shader_graph.node_get_param(p_node),ph.hint,ph.hint_string);
-
- Point2 popup_pos=Point2( pos.x+(size.width-property_editor->get_size().width)/2.0,pos.y+(size.y-style->get_margin(MARGIN_BOTTOM))).floor();
- popup_pos+=get_global_pos();
- property_editor->set_pos(popup_pos);
-
- property_editor->popup();
+void ShaderGraphView::_node_moved(const Vector2& p_from, const Vector2& p_to,int p_id) {
+ print_line("moved from "+p_from+" to "+p_to);
+ 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);
+ ur->commit_action();
}
-bool ShaderEditor::has_point(const Point2& p_point) const {
-
- int n,si;
+void ShaderGraphView::_move_node(int p_id,const Vector2& p_to) {
- return _locate_click(p_point,&n,&si)!=CLICK_NONE;
+ ERR_FAIL_COND(!node_map.has(p_id));
+ node_map[p_id]->set_offset(p_to);
+ graph->node_set_pos(type,p_id,p_to);
}
-void ShaderEditor::_input_event(InputEvent p_event) {
-
- switch(p_event.type) {
-
- case InputEvent::MOUSE_BUTTON: {
-
- if (p_event.mouse_button.pressed) {
-
-
- if (p_event.mouse_button.button_index==1) {
- click_pos=Point2(p_event.mouse_button.x,p_event.mouse_button.y);
- click_motion=click_pos;
- click_type = _locate_click(click_pos,&click_node,&click_slot);
- if( click_type!=CLICK_NONE) {
-
- order.erase(click_node);
- order.push_back(click_node);
- update();
- }
- switch(click_type) {
- case CLICK_INPUT_SLOT: {
- click_pos=_get_slot_pos(click_node,true,click_slot);
- } break;
- case CLICK_OUTPUT_SLOT: {
- click_pos=_get_slot_pos(click_node,false,click_slot);
- } break;
- case CLICK_PARAMETER: {
- //open editor
- _node_edit_property(click_node);
- } break;
- }
- }
- if (p_event.mouse_button.button_index==2) {
-
- if (click_type!=CLICK_NONE) {
- click_type=CLICK_NONE;
- update();
- } else {
- // try to disconnect/remove
-
- Point2 rclick_pos=Point2(p_event.mouse_button.x,p_event.mouse_button.y);
- rclick_type = _locate_click(rclick_pos,&rclick_node,&rclick_slot);
- if (rclick_type==CLICK_INPUT_SLOT || rclick_type==CLICK_OUTPUT_SLOT) {
- node_popup->clear();
- node_popup->add_item("Disconnect",NODE_DISCONNECT);
- node_popup->set_pos(rclick_pos);
- node_popup->popup();
+void ShaderGraphView::_create_node(int p_id) {
- }
- if (rclick_type==CLICK_NODE) {
- node_popup->clear();
- node_popup->add_item("Remove",NODE_ERASE);
- node_popup->set_pos(rclick_pos);
- node_popup->popup();
- }
+ GraphNode *gn = memnew( GraphNode );
+ gn->set_show_close_button(true);
+ Color typecol[4]={
+ Color(0.2,1,0.2),
+ Color(0.7,0.1,1),
+ Color(1,0.2,0.2),
+ Color(0,1,1)
+ };
- }
- }
- } else {
-
- if (p_event.mouse_button.button_index==1 && click_type!=CLICK_NONE) {
-
- switch(click_type) {
- case CLICK_INPUT_SLOT:
- case CLICK_OUTPUT_SLOT: {
-
- Point2 dst_click_pos=Point2(p_event.mouse_button.x,p_event.mouse_button.y);
- int id;
- int slot;
- ClickType dst_click_type = _locate_click(dst_click_pos,&id,&slot);
- if (dst_click_type==CLICK_INPUT_SLOT && click_type==CLICK_OUTPUT_SLOT) {
-
- shader_graph.connect(click_node,click_slot,id,slot);
-
- Error err = validate_graph();
- if (err==ERR_CYCLIC_LINK)
- shader_graph.disconnect(click_node,click_slot,id,slot);
- _write_shader_graph();
+ switch(graph->node_get_type(type,p_id)) {
- }
- if (click_type==CLICK_INPUT_SLOT && dst_click_type==CLICK_OUTPUT_SLOT) {
+ case ShaderGraph::NODE_INPUT: {
- shader_graph.connect(id,slot,click_node,click_slot);
+ gn->set_title("Input");
- Error err = validate_graph();
- if (err==ERR_CYCLIC_LINK)
- shader_graph.disconnect(id,slot,click_node,click_slot);
- _write_shader_graph();
- }
+ List<ShaderGraph::SlotInfo> si;
+ ShaderGraph::get_input_output_node_slot_info(graph->get_mode(),type,&si);
- } break;
- case CLICK_NODE: {
- int new_x=shader_graph.node_get_pos_x(click_node)+(click_motion.x-click_pos.x);
- int new_y=shader_graph.node_get_pos_y(click_node)+(click_motion.y-click_pos.y);
- shader_graph.node_set_pos(click_node,new_x,new_y);
- _write_shader_graph();
+ 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) {
- } break;
- }
-
- click_type=CLICK_NONE;
- update();
+ 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++;
}
}
- }
-
- case InputEvent::MOUSE_MOTION: {
-
- if (p_event.mouse_motion.button_mask&1 && click_type!=CLICK_NONE) {
+ } break; // all inputs (case Shader type dependent)
+ case ShaderGraph::NODE_SCALAR_CONST: {
+ gn->set_title("Scalar");
+ SpinBox *sb = memnew( SpinBox );
+ sb->set_min(-100000);
+ sb->set_max(100000);
+ sb->set_step(0.001);
+ sb->set_val(graph->scalar_const_node_get_value(type,p_id));
+ sb->connect("value_changed",this,"_scalar_const_changed",varray(p_id));
+ gn->add_child(sb);
+ gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+ } break; //scalar constant
+ case ShaderGraph::NODE_VEC_CONST: {
+
+ gn->set_title("Vector");
+ Array v3p(true);
+ for(int i=0;i<3;i++) {
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ Label *l = memnew( Label );
+ l->set_text(String::chr('X'+i));
+ hbc->add_child(l);
+ SpinBox *sb = memnew( SpinBox );
+ sb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ sb->set_min(-100000);
+ sb->set_max(100000);
+ sb->set_step(0.001);
+ sb->set_val(graph->vec_const_node_get_value(type,p_id)[i]);
+ sb->connect("value_changed",this,"_vec_const_changed",varray(p_id,v3p));
+ v3p.push_back(sb);
+ hbc->add_child(sb);
+ gn->add_child(hbc);
+ }
+ gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+
+ } break; //vec3 constant
+ case ShaderGraph::NODE_RGB_CONST: {
+
+ gn->set_title("Color");
+ ColorPickerButton *cpb = memnew( ColorPickerButton );
+ cpb->set_color(graph->rgb_const_node_get_value(type,p_id));
+ cpb->connect("color_changed",this,"_rgb_const_changed",varray(p_id));
+ gn->add_child(cpb);
+ Label *l = memnew( Label );
+ l->set_text("RGB");
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child(l);
+ l = memnew( Label );
+ l->set_text("Alpha");
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child(l);
+
+ gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+ } break; //rgb constant (shows a color picker instead)
+ case ShaderGraph::NODE_XFORM_CONST: {
+ gn->set_title("XForm");
+ ToolButton *edit = memnew( ToolButton );
+ edit->set_text("edit..");
+ edit->connect("pressed",this,"_xform_const_changed",varray(p_id,edit));
+ gn->add_child(edit);
+ gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]);
+
+ } break; // 4x4 matrix constant
+ case ShaderGraph::NODE_TIME: {
+
+ gn->set_title("Time");
+ Label *l = memnew( Label );
+ l->set_text("(s)");
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child(l);
+ gn->set_slot(0,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+ } break; // time in seconds
+ case ShaderGraph::NODE_SCREEN_TEX: {
+
+ gn->set_title("ScreenTex");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ hbc->add_child( memnew(Label("UV")));
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("RGB")));
+ gn->add_child(hbc);
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+
+ } break; // screen texture sampler (takes UV) (only usable in fragment case Shader)
+ case ShaderGraph::NODE_SCALAR_OP: {
+
+ gn->set_title("ScalarOp");
+ static const char* op_name[ShaderGraph::SCALAR_MAX_OP]={
+ "Add",
+ "Sub",
+ "Mul",
+ "Div",
+ "Mod",
+ "Pow",
+ "Max",
+ "Min",
+ "Atan2"
+ };
+
+ OptionButton *ob = memnew( OptionButton );
+ for(int i=0;i<ShaderGraph::SCALAR_MAX_OP;i++) {
+
+ ob->add_item(op_name[i],i);
+ }
- click_motion=Point2(p_event.mouse_button.x,p_event.mouse_button.y);
- update();
+ 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);
}
- } break;
- }
-}
+ 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 ShaderEditor::_notification(int p_what) {
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ hbc->add_child( memnew(Label("a")));
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("out")));
+ gn->add_child(hbc);
+ gn->add_child( memnew(Label("b")));
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
- switch(p_what) {
- case NOTIFICATION_DRAW: {
+ } break; // vec3 vs vec3 op (mul: { } break;ad: { } break;div: { } break;crossprod: { } break;etc)
+ case ShaderGraph::NODE_VEC_SCALAR_OP: {
- _update_scrollbars();
- //VisualServer::get_singleton()->canvas_item_add_rect(get_canvas_item(),Rect2(Point2(),get_size()),Color(0,0,0,1));
+ gn->set_title("VecScalarOp");
+ static const char* op_name[ShaderGraph::VEC_SCALAR_MAX_OP]={
+ "Mul",
+ "Div",
+ "Pow",
+ };
- for(List<int>::Element *E=order.front();E;E=E->next()) {
+ OptionButton *ob = memnew( OptionButton );
+ for(int i=0;i<ShaderGraph::VEC_SCALAR_MAX_OP;i++) {
- _draw_node(E->get());
+ ob->add_item(op_name[i],i);
}
- if (click_type==CLICK_INPUT_SLOT || click_type==CLICK_OUTPUT_SLOT) {
+ ob->select(graph->vec_scalar_op_node_get_op(type,p_id));
+ ob->connect("item_selected",this,"_vec_scalar_op_changed",varray(p_id));
+ gn->add_child(ob);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ hbc->add_child( memnew(Label("a")));
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("out")));
+ gn->add_child(hbc);
+ gn->add_child( memnew(Label("b")));
+
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
+
+
+ } break; // vec3 vs scalar op (mul: { } break; add: { } break; div: { } break; etc)
+ case ShaderGraph::NODE_RGB_OP: {
+
+ gn->set_title("RGB Op");
+ static const char* op_name[ShaderGraph::RGB_MAX_OP]={
+ "Screen",
+ "Difference",
+ "Darken",
+ "Lighten",
+ "Overlay",
+ "Dodge",
+ "Burn",
+ "SoftLight",
+ "HardLight"
+ };
+
+ OptionButton *ob = memnew( OptionButton );
+ for(int i=0;i<ShaderGraph::RGB_MAX_OP;i++) {
+
+ ob->add_item(op_name[i],i);
+ }
- VisualServer::get_singleton()->canvas_item_add_line(get_canvas_item(),click_pos,click_motion,Color(0.5,1,0.5,0.8),2);
+ ob->select(graph->rgb_op_node_get_op(type,p_id));
+ ob->connect("item_selected",this,"_rgb_op_changed",varray(p_id));
+ gn->add_child(ob);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ hbc->add_child( memnew(Label("a")));
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("out")));
+ gn->add_child(hbc);
+ gn->add_child( memnew(Label("b")));
+
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
+
+ } break; // vec3 vs vec3 rgb op (with scalar amount): { } break; like brighten: { } break; darken: { } break; burn: { } break; dodge: { } break; multiply: { } break; etc.
+ case ShaderGraph::NODE_XFORM_MULT: {
+
+ gn->set_title("XFMult");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_child( memnew(Label("a")));
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("out")));
+ gn->add_child(hbc);
+ gn->add_child( memnew(Label("b")));
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]);
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],false,0,Color());
+
+
+ } break; // mat4 x mat4
+ case ShaderGraph::NODE_XFORM_VEC_MULT:
+ case ShaderGraph::NODE_XFORM_VEC_INV_MULT: {
+
+ if (graph->node_get_type(type,p_id)==ShaderGraph::NODE_XFORM_VEC_INV_MULT)
+ gn->set_title("XFVecMult");
+ else
+ gn->set_title("XFVecInvMult");
+
+
+ Button *button = memnew( Button("RotOnly"));
+ button->set_toggle_mode(true);
+ button->set_pressed(graph->xform_vec_mult_node_get_no_translation(type,p_id));
+ button->connect("toggled",this,"_xform_inv_rev_changed",varray(p_id));
+
+ gn->add_child(button);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ hbc->add_child( memnew(Label("xf")));
+ hbc->add_spacer();
+ Label *l = memnew(Label("out"));
+ l->set_align(Label::ALIGN_RIGHT);
+ hbc->add_child( l);
+ gn->add_child(hbc);
+ gn->add_child( memnew(Label("vec")));
+
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
+
+
+ } break; // mat4 x vec3 inverse mult (with no-translation option)
+ case ShaderGraph::NODE_SCALAR_FUNC: {
+
+ gn->set_title("ScalarFunc");
+ static const char* func_name[ShaderGraph::SCALAR_MAX_FUNC]={
+ "Sin",
+ "Cos",
+ "Tan",
+ "ASin",
+ "ACos",
+ "ATan",
+ "SinH",
+ "CosH",
+ "TanH",
+ "Log",
+ "Exp",
+ "Sqrt",
+ "Abs",
+ "Sign",
+ "Floor",
+ "Round",
+ "Ceil",
+ "Frac",
+ "Satr",
+ "Neg"
+ };
+
+ OptionButton *ob = memnew( OptionButton );
+ for(int i=0;i<ShaderGraph::SCALAR_MAX_FUNC;i++) {
+
+ ob->add_item(func_name[i],i);
}
- List<ShaderGraph::Connection> connections = shader_graph.get_connection_list();
- for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) {
+ 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);
- const ShaderGraph::Connection &c=E->get();
- Point2 source = _get_slot_pos(c.src_id,false,c.src_slot);
- Point2 dest = _get_slot_pos(c.dst_id,true,c.dst_slot);
- bool vec = VisualServer::shader_is_input_vector( shader_graph.node_get_type(c.dst_id), c.dst_slot );
- Color col = vec?Color(1,0.5,0.5,0.8):Color(1,1,0.5,0.8);
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_child( memnew(Label("in")));
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("out")));
+ gn->add_child(hbc);
- if (click_type==CLICK_NODE && click_node==c.src_id) {
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
- source+=click_motion-click_pos;
- }
- if (click_type==CLICK_NODE && click_node==c.dst_id) {
+ } break; // scalar function (sin: { } break; cos: { } break; etc)
+ case ShaderGraph::NODE_VEC_FUNC: {
- dest+=click_motion-click_pos;
- }
- VisualServer::get_singleton()->canvas_item_add_line(get_canvas_item(),source,dest,col,2);
-
- }
- } break;
- }
-
-}
-void ShaderEditor::_update_scrollbars() {
+ gn->set_title("VecFunc");
+ static const char* func_name[ShaderGraph::VEC_MAX_FUNC]={
+ "Normalize",
+ "Saturate",
+ "Negate",
+ "Reciprocal",
+ "RGB to HSV",
+ "HSV to RGB",
+ };
- Size2 size = get_size();
- Size2 hmin = h_scroll->get_minimum_size();
- Size2 vmin = v_scroll->get_minimum_size();
+ OptionButton *ob = memnew( OptionButton );
+ for(int i=0;i<ShaderGraph::VEC_MAX_FUNC;i++) {
- v_scroll->set_begin( Point2(size.width - vmin.width, 0) );
- v_scroll->set_end( Point2(size.width, size.height) );
-
- h_scroll->set_begin( Point2( 0, size.height - hmin.height) );
- h_scroll->set_end( Point2(size.width-vmin.width, size.height) );
-
-
- Size2 min = _get_maximum_size();
+ ob->add_item(func_name[i],i);
+ }
- if (min.height < size.height - hmin.height) {
+ ob->select(graph->vec_func_node_get_function(type,p_id));
+ ob->connect("item_selected",this,"_vec_func_changed",varray(p_id));
+ gn->add_child(ob);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ hbc->add_child( memnew(Label("in")));
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("out")));
+ gn->add_child(hbc);
+
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+
+ } break; // vector function (normalize: { } break; negate: { } break; reciprocal: { } break; rgb2hsv: { } break; hsv2rgb: { } break; etc: { } break; etc)
+ case ShaderGraph::NODE_VEC_LEN: {
+ gn->set_title("VecLength");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_child( memnew(Label("in")));
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("len")));
+ gn->add_child(hbc);
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+ } break; // vec3 length
+ case ShaderGraph::NODE_DOT_PROD: {
+
+ gn->set_title("DotProduct");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ hbc->add_child( memnew(Label("a")));
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("dp")));
+ gn->add_child(hbc);
+ gn->add_child( memnew(Label("b")));
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
+
+ } break; // vec3 . vec3 (dot product -> scalar output)
+ case ShaderGraph::NODE_VEC_TO_SCALAR: {
+
+ gn->set_title("Vec2Scalar");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ hbc->add_child( memnew(Label("vec")));
+ hbc->add_spacer();
+ Label *l=memnew(Label("x"));
+ l->set_align(Label::ALIGN_RIGHT);
+ hbc->add_child( l);
+ gn->add_child(hbc);
+ l=memnew(Label("y"));
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child( l );
+ l=memnew(Label("z"));
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child( l);
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+ gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+ gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+
+
+
+ } break; // 1 vec3 input: { } break; 3 scalar outputs
+ case ShaderGraph::NODE_SCALAR_TO_VEC: {
+
+ gn->set_title("Scalar2Vec");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_child( memnew(Label("x")));
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("vec")));
+ gn->add_child(hbc);
+ gn->add_child( memnew(Label("y")));
+ gn->add_child( memnew(Label("z")));
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
+
+ } break; // 3 scalar input: { } break; 1 vec3 output
+ case ShaderGraph::NODE_VEC_TO_XFORM: {
+
+ gn->set_title("Vec2XForm");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ hbc->add_child( memnew(Label("x")));
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("xf")));
+ gn->add_child(hbc);
+ gn->add_child( memnew(Label("y")));
+ gn->add_child( memnew(Label("z")));
+ gn->add_child( memnew(Label("ofs")));
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]);
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
+ gn->set_slot(3,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
+
+ } break; // 3 vec input: { } break; 1 xform output
+ case ShaderGraph::NODE_XFORM_TO_VEC: {
+
+ gn->set_title("XForm2Vec");
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ hbc->add_child( memnew(Label("xf")));
+ hbc->add_spacer();
+ Label *l=memnew(Label("x"));
+ l->set_align(Label::ALIGN_RIGHT);
+ hbc->add_child( l);
+ gn->add_child(hbc);
+ l=memnew(Label("y"));
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child( l );
+ l=memnew(Label("z"));
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child( l);
+ l=memnew(Label("ofs"));
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child( l);
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+
+ } break; // 3 vec input: { } break; 1 xform output
+ case ShaderGraph::NODE_SCALAR_INTERP: {
+
+ gn->set_title("ScalarInterp");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ hbc->add_child( memnew(Label("a")));
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("interp")));
+ gn->add_child(hbc);
+ gn->add_child( memnew(Label("b")));
+ gn->add_child( memnew(Label("c")));
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR],false,0,Color());
+
+
+ } break; // scalar interpolation (with optional curve)
+ case ShaderGraph::NODE_VEC_INTERP: {
+
+ gn->set_title("VecInterp");
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_child( memnew(Label("a")));
+ hbc->add_spacer();
+ hbc->add_child( memnew(Label("interp")));
+ gn->add_child(hbc);
+ gn->add_child( memnew(Label("b")));
+ gn->add_child( memnew(Label("c")));
+
+ gn->set_slot(0,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(1,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],false,0,Color());
+
+ } break; // vec3 interpolation (with optional curve)
+ case ShaderGraph::NODE_SCALAR_INPUT: {
+
+ gn->set_title("ScalarUniform");
+ LineEdit *le = memnew( LineEdit );
+ gn->add_child(le);
+ le->set_text(graph->input_node_get_name(type,p_id));
+ le->connect("text_entered",this,"_input_name_changed",varray(p_id,le));
+ SpinBox *sb = memnew( SpinBox );
+ sb->set_min(-100000);
+ sb->set_max(100000);
+ sb->set_step(0.001);
+ sb->set_val(graph->scalar_input_node_get_value(type,p_id));
+ sb->connect("value_changed",this,"_scalar_input_changed",varray(p_id));
+ gn->add_child(sb);
+ gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+ } break; // scalar uniform (assignable in material)
+ case ShaderGraph::NODE_VEC_INPUT: {
+
+ gn->set_title("VectorUniform");
+ LineEdit *le = memnew( LineEdit );
+ gn->add_child(le);
+ le->set_text(graph->input_node_get_name(type,p_id));
+ le->connect("text_entered",this,"_input_name_changed",varray(p_id,le));
+ Array v3p(true);
+ for(int i=0;i<3;i++) {
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ Label *l = memnew( Label );
+ l->set_text(String::chr('X'+i));
+ hbc->add_child(l);
+ SpinBox *sb = memnew( SpinBox );
+ sb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
+ sb->set_min(-100000);
+ sb->set_max(100000);
+ sb->set_step(0.001);
+ sb->set_val(graph->vec_input_node_get_value(type,p_id)[i]);
+ sb->connect("value_changed",this,"_vec_input_changed",varray(p_id,v3p));
+ v3p.push_back(sb);
+ hbc->add_child(sb);
+ gn->add_child(hbc);
+ }
+ gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+
+ } break; // vec3 uniform (assignable in material)
+ case ShaderGraph::NODE_RGB_INPUT: {
+
+ gn->set_title("ColorUniform");
+ LineEdit *le = memnew( LineEdit );
+ gn->add_child(le);
+ le->set_text(graph->input_node_get_name(type,p_id));
+ le->connect("text_entered",this,"_input_name_changed",varray(p_id,le));
+ ColorPickerButton *cpb = memnew( ColorPickerButton );
+ cpb->set_color(graph->rgb_input_node_get_value(type,p_id));
+ cpb->connect("color_changed",this,"_rgb_input_changed",varray(p_id));
+ gn->add_child(cpb);
+ Label *l = memnew( Label );
+ l->set_text("RGB");
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child(l);
+ l = memnew( Label );
+ l->set_text("Alpha");
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child(l);
+
+ gn->set_slot(2,false,0,Color(),true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+
+ } break; // color uniform (assignable in material)
+ case ShaderGraph::NODE_XFORM_INPUT: {
+ gn->set_title("XFUniform");
+ LineEdit *le = memnew( LineEdit );
+ gn->add_child(le);
+ le->set_text(graph->input_node_get_name(type,p_id));
+ le->connect("text_entered",this,"_input_name_changed",varray(p_id,le));
+ ToolButton *edit = memnew( ToolButton );
+ edit->set_text("edit..");
+ edit->connect("pressed",this,"_xform_input_changed",varray(p_id,edit));
+ gn->add_child(edit);
+ gn->set_slot(1,false,0,Color(),true,ShaderGraph::SLOT_TYPE_XFORM,typecol[ShaderGraph::SLOT_TYPE_XFORM]);
+
+ } break; // mat4 uniform (assignable in material)
+ case ShaderGraph::NODE_TEXTURE_INPUT: {
+
+ gn->set_title("TexUniform");
+ LineEdit *le = memnew( LineEdit );
+ gn->add_child(le);
+ le->set_text(graph->input_node_get_name(type,p_id));
+ le->connect("text_entered",this,"_input_name_changed",varray(p_id,le));
+ TextureFrame *tex = memnew( TextureFrame );
+ tex->set_expand(true);
+ tex->set_custom_minimum_size(Size2(80,80));
+ gn->add_child(tex);
+ tex->set_texture(graph->texture_input_node_get_value(type,p_id));
+ ToolButton *edit = memnew( ToolButton );
+ edit->set_text("edit..");
+ edit->connect("pressed",this,"_tex_edited",varray(p_id,edit));
+ gn->add_child(edit);
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ hbc->add_child( memnew(Label("UV")));
+ hbc->add_spacer();
+ Label *l=memnew(Label("RGB"));
+ l->set_align(Label::ALIGN_RIGHT);
+ hbc->add_child(l);
+ gn->add_child(hbc);
+ l = memnew( Label );
+ l->set_text("Alpha");
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child(l);
+
+ gn->set_slot(3,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(4,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+ } break; // texture input (assignable in material)
+ case ShaderGraph::NODE_CUBEMAP_INPUT: {
+
+ gn->set_title("TexUniform");
+ LineEdit *le = memnew( LineEdit );
+ gn->add_child(le);
+ le->set_text(graph->input_node_get_name(type,p_id));
+ le->connect("text_entered",this,"_input_name_changed",varray(p_id,le));
+
+ ToolButton *edit = memnew( ToolButton );
+ edit->set_text("edit..");
+ edit->connect("pressed",this,"_cube_edited",varray(p_id,edit));
+ gn->add_child(edit);
+
+
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ hbc->add_constant_override("separation",0);
+ hbc->add_child( memnew(Label("UV")));
+ hbc->add_spacer();
+ Label *l=memnew(Label("RGB"));
+ l->set_align(Label::ALIGN_RIGHT);
+ hbc->add_child(l);
+ gn->add_child(hbc);
+ l = memnew( Label );
+ l->set_text("Alpha");
+ l->set_align(Label::ALIGN_RIGHT);
+ gn->add_child(l);
+
+ gn->set_slot(2,true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC],true,ShaderGraph::SLOT_TYPE_VEC,typecol[ShaderGraph::SLOT_TYPE_VEC]);
+ gn->set_slot(3,false,0,Color(),true,ShaderGraph::SLOT_TYPE_SCALAR,typecol[ShaderGraph::SLOT_TYPE_SCALAR]);
+
+ } break; // cubemap input (assignable in material)
+ case ShaderGraph::NODE_OUTPUT: {
+ gn->set_title("Output");
+
+ List<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++;
+ }
+ }
- v_scroll->hide();
- offset.y=0;
- } else {
+ } 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));
- v_scroll->show();
- v_scroll->set_max(min.height);
- v_scroll->set_page(size.height - hmin.height);
- offset.y=v_scroll->get_val();
- }
+ } break; // comment
- if (min.width < size.width - vmin.width) {
- h_scroll->hide();
- offset.x=0;
- } else {
- h_scroll->show();
- h_scroll->set_max(min.width);
- h_scroll->set_page(size.width - vmin.width);
- offset.x=h_scroll->get_val();
}
-}
-void ShaderEditor::_scroll_moved() {
+ gn->connect("dragged",this,"_node_moved",varray(p_id));
+ gn->connect("close_request",this,"_node_removed",varray(p_id),CONNECT_DEFERRED);
+ graph_edit->add_child(gn);
+ node_map[p_id]=gn;
+ gn->set_offset(graph->node_get_pos(type,p_id));
+ print_line("NODE "+itos(p_id)+" OFS "+gn->get_offset());
- offset.x=h_scroll->get_val();
- offset.y=v_scroll->get_val();
- update();
}
-void ShaderEditor::_bind_methods() {
+void ShaderGraphView::_update_graph() {
- ObjectTypeDB::bind_method( "_node_menu_item", &ShaderEditor::_node_menu_item );
- ObjectTypeDB::bind_method( "_node_add_callback", &ShaderEditor::_node_add_callback );
- ObjectTypeDB::bind_method( "_input_event", &ShaderEditor::_input_event );
- ObjectTypeDB::bind_method( "_node_param_changed", &ShaderEditor::_node_param_changed );
- ObjectTypeDB::bind_method( "_scroll_moved", &ShaderEditor::_scroll_moved );
- ObjectTypeDB::bind_method( "_vertex_item", &ShaderEditor::_vertex_item );
- ObjectTypeDB::bind_method( "_fragment_item", &ShaderEditor::_fragment_item );
- ObjectTypeDB::bind_method( "_post_item", &ShaderEditor::_post_item );
-}
-
-void ShaderEditor::_read_shader_graph() {
- shader_graph.clear();;
- order.clear();
- List<int> nodes;
- shader->get_node_list(&nodes);
- int larger_id=0;
- for(List<int>::Element *E=nodes.front();E;E=E->next()) {
+ if (block_update)
+ return;
- if (E->get() > larger_id)
- larger_id = E->get();
+ for (Map<int,GraphNode*>::Element *E=node_map.front();E;E=E->next()) {
- shader_graph.node_add( (VS::ShaderNodeType)shader->node_get_type(E->get()), E->get() );
- shader_graph.node_set_param( E->get(), shader->node_get_param( E->get() ) );
- Point2 pos = shader->node_get_pos(E->get());
- shader_graph.node_set_pos( E->get(), pos.x,pos.y );
- order.push_back(E->get());
+ memdelete(E->get());
}
- last_id=larger_id+1;
+ node_map.clear();
- List<Shader::Connection> connections;
- shader->get_connections(&connections);
-
- for(List<Shader::Connection>::Element *E=connections.front();E;E=E->next()) {
-
- Shader::Connection &c=E->get();
- shader_graph.connect(c.src_id,c.src_slot,c.dst_id,c.dst_slot);
- }
-
- validate_graph();
- update();
-}
+ if (!graph.is_valid())
+ return;
-void ShaderEditor::_write_shader_graph() {
- shader->clear();
- List<int> nodes;
- shader_graph.get_node_list(&nodes);
- for(List<int>::Element *E=nodes.front();E;E=E->next()) {
+ List<int> nl;
+ graph->get_node_list(type,&nl);
+ print_line("graph nodes: "+itos(nl.size()));
+ for(List<int>::Element *E=nl.front();E;E=E->next()) {
- shader->node_add((Shader::NodeType)shader_graph.node_get_type(E->get()),E->get());
- shader->node_set_param(E->get(),shader_graph.node_get_param(E->get()));
- shader->node_set_pos(E->get(),Point2( shader_graph.node_get_pos_x(E->get()),shader_graph.node_get_pos_y(E->get()) ) );
+ _create_node(E->get());
}
+ graph_edit->clear_connections();
- List<ShaderGraph::Connection> connections = shader_graph.get_connection_list();
+ List<ShaderGraph::Connection> connections;
+ graph->get_node_connections(type,&connections);
for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) {
- const ShaderGraph::Connection &c=E->get();
- shader->connect(c.src_id,c.src_slot,c.dst_id,c.dst_slot);
+ ERR_CONTINUE(!node_map.has(E->get().src_id) || !node_map.has(E->get().dst_id));
+ graph_edit->connect_node(node_map[E->get().src_id]->get_name(),E->get().src_slot,node_map[E->get().dst_id]->get_name(),E->get().dst_slot);
}
-}
-
-void ShaderEditor::_add_node_from_text(const String& p_text) {
- ERR_FAIL_COND( p_text.get_slice_count(" ") != 3 );
- bool input = p_text.get_slice(" ",0)=="In:";
- String name = p_text.get_slice(" ",1);
- bool vec = p_text.get_slice(" ",2)=="(vec3)";
- _node_add( input?
- ( vec? VisualServer::NODE_VEC_IN : VisualServer::NODE_IN ) :
- ( vec? VisualServer::NODE_VEC_OUT : VisualServer::NODE_OUT ) );
- shader_graph.node_set_param( last_id-1,name );
- _write_shader_graph();
}
-void ShaderEditor::_vertex_item(int p_item) {
+void ShaderGraphView::set_graph(Ref<ShaderGraph> p_graph){
- _add_node_from_text(vertex_popup->get_item_text(p_item));
-}
-void ShaderEditor::_fragment_item(int p_item) {
-
- _add_node_from_text(fragment_popup->get_item_text(p_item));
-}
-void ShaderEditor::_post_item(int p_item) {
+ print_line("GRAPH EDIT: "+itos(p_graph.is_valid()));
+ graph=p_graph;
+ _update_graph();
- _add_node_from_text(post_popup->get_item_text(p_item));
}
+void ShaderGraphView::_notification(int p_what) {
-void ShaderEditor::_node_menu_item(int p_item) {
-
- switch(p_item) {
-
- case GRAPH_ADD_NODE: {
- add_popup->popup_centered_ratio();
- validate_graph();
- } break;
- case NODE_DISCONNECT: {
-
- if (rclick_type==CLICK_INPUT_SLOT) {
-
- List<ShaderGraph::Connection> connections = shader_graph.get_connection_list();
- for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) {
-
- const ShaderGraph::Connection &c=E->get();
- if( c.dst_id==rclick_node && c.dst_slot==rclick_slot) {
-
- shader_graph.disconnect(c.src_id,c.src_slot,c.dst_id,c.dst_slot);
- }
- }
- update();
- _write_shader_graph();
- validate_graph();
- }
-
- if (rclick_type==CLICK_OUTPUT_SLOT) {
-
- List<ShaderGraph::Connection> connections = shader_graph.get_connection_list();
- for(List<ShaderGraph::Connection>::Element *E=connections.front();E;E=E->next()) {
-
- const ShaderGraph::Connection &c=E->get();
- if( c.src_id==rclick_node && c.src_slot==rclick_slot) {
-
- shader_graph.disconnect(c.src_id,c.src_slot,c.dst_id,c.dst_slot);
- }
- }
- update();
- _write_shader_graph();
- validate_graph();
- }
+ if (p_what==NOTIFICATION_ENTER_TREE) {
- } break;
- case NODE_ERASE: {
-
- order.erase(rclick_node);
- shader_graph.node_remove(rclick_node);
- update();
- _write_shader_graph();
- validate_graph();
- } break;
- case GRAPH_CLEAR: {
-
- order.clear();
- shader_graph.clear();
- last_id=1;
- last_x=20;
- last_y=20;
- update();
- _write_shader_graph();
- validate_graph();
-
- } break;
+ ped_popup->connect("variant_changed",this,"_variant_edited");
}
-}
-
-void ShaderEditor::_node_add(VisualServer::ShaderNodeType p_type) {
-
- shader_graph.node_add(p_type,last_id );
- shader_graph.node_set_pos(last_id ,last_x,last_y);
- String test_param;
-
- switch(p_type) {
- case VS::NODE_PARAMETER: {
-
- test_param="param";
- } break;
- case VS::NODE_VEC_PARAMETER: {
-
- test_param="vec";
- } break;
- case VS::NODE_COLOR_PARAMETER: {
-
- test_param="color";
- } break;
- case VS::NODE_TEXTURE_PARAMETER: {
-
- test_param="tex";
- } break;
- case VS::NODE_TEXTURE_2D_PARAMETER: {
-
- test_param="tex2D";
- } break;
- case VS::NODE_TEXTURE_CUBE_PARAMETER: {
-
- test_param="cubemap";
- } break;
- case VS::NODE_TRANSFORM_PARAMETER: {
- test_param="xform";
- } break;
- case VS::NODE_LABEL: {
-
- test_param="label";
- } break;
+ }
+
+void ShaderGraphView::add_node(int p_type) {
+
+ List<int> existing;
+ graph->get_node_list(type,&existing);
+ existing.sort();
+ int newid=1;
+ for(List<int>::Element *E=existing.front();E;E=E->next()) {
+ if (!E->next() || (E->get()+1!=E->next()->get())){
+ newid=E->get()+1;
+ break;
+ }
}
- if(test_param!="") {
-
- int iter=0;
- List<int> l;
-
- shader_graph.get_node_list(&l);
-
- bool found;
- String test;
- do {
- iter++;
- test=test_param;
- if (iter>1)
- test+="_"+itos(iter);
- found=false;
- for(List<int>::Element *E=l.front();E;E=E->next()) {
-
+ Vector2 init_ofs(20,20);
+ while(true) {
+ bool valid=true;
+ for(List<int>::Element *E=existing.front();E;E=E->next()) {
+ Vector2 pos = graph->node_get_pos(type,E->get());
+ if (init_ofs==pos) {
+ init_ofs+=Vector2(20,20);
+ valid=false;
+ break;
- String param = shader_graph.node_get_param( E->get() );
- if (param==test) {
- found=true;
- break;
- }
}
+ }
- } while (found);
-
-
- shader_graph.node_set_param(last_id,test);
-
+ if (valid)
+ break;
}
- order.push_back(last_id);
- last_x+=10;
- last_y+=10;
- last_id++;
- last_x=last_x % (int)get_size().width;
- last_y=last_y % (int)get_size().height;
- update();
- add_popup->hide();;
- _write_shader_graph();
+ UndoRedo *ur=EditorNode::get_singleton()->get_undo_redo();
+ ur->create_action("Add Shader Graph Node");
+ ur->add_do_method(graph.ptr(),"node_add",type,p_type,newid);
+ ur->add_do_method(graph.ptr(),"node_set_pos",type,newid,init_ofs);
+ ur->add_undo_method(graph.ptr(),"node_remove",type,newid);
+ ur->add_do_method(this,"_update_graph");
+ ur->add_undo_method(this,"_update_graph");
+ ur->commit_action();
}
-void ShaderEditor::_node_add_callback() {
+void ShaderGraphView::_bind_methods() {
+
+ ObjectTypeDB::bind_method("_update_graph",&ShaderGraphView::_update_graph);
+ ObjectTypeDB::bind_method("_node_moved",&ShaderGraphView::_node_moved);
+ ObjectTypeDB::bind_method("_move_node",&ShaderGraphView::_move_node);
+ ObjectTypeDB::bind_method("_node_removed",&ShaderGraphView::_node_removed);
+ ObjectTypeDB::bind_method("_connection_request",&ShaderGraphView::_connection_request);
+
+ ObjectTypeDB::bind_method("_scalar_const_changed",&ShaderGraphView::_scalar_const_changed);
+ ObjectTypeDB::bind_method("_vec_const_changed",&ShaderGraphView::_vec_const_changed);
+ ObjectTypeDB::bind_method("_rgb_const_changed",&ShaderGraphView::_rgb_const_changed);
+ ObjectTypeDB::bind_method("_xform_const_changed",&ShaderGraphView::_xform_const_changed);
+ ObjectTypeDB::bind_method("_scalar_op_changed",&ShaderGraphView::_scalar_op_changed);
+ ObjectTypeDB::bind_method("_vec_op_changed",&ShaderGraphView::_vec_op_changed);
+ ObjectTypeDB::bind_method("_vec_scalar_op_changed",&ShaderGraphView::_vec_scalar_op_changed);
+ ObjectTypeDB::bind_method("_rgb_op_changed",&ShaderGraphView::_rgb_op_changed);
+ ObjectTypeDB::bind_method("_xform_inv_rev_changed",&ShaderGraphView::_xform_inv_rev_changed);
+ ObjectTypeDB::bind_method("_scalar_func_changed",&ShaderGraphView::_scalar_func_changed);
+ ObjectTypeDB::bind_method("_vec_func_changed",&ShaderGraphView::_vec_func_changed);
+ ObjectTypeDB::bind_method("_scalar_input_changed",&ShaderGraphView::_scalar_input_changed);
+ ObjectTypeDB::bind_method("_vec_input_changed",&ShaderGraphView::_vec_input_changed);
+ ObjectTypeDB::bind_method("_xform_input_changed",&ShaderGraphView::_xform_input_changed);
+ ObjectTypeDB::bind_method("_rgb_input_changed",&ShaderGraphView::_rgb_input_changed);
+ ObjectTypeDB::bind_method("_tex_input_change",&ShaderGraphView::_tex_input_change);
+ ObjectTypeDB::bind_method("_cube_input_change",&ShaderGraphView::_cube_input_change);
+ ObjectTypeDB::bind_method("_input_name_changed",&ShaderGraphView::_input_name_changed);
+ ObjectTypeDB::bind_method("_tex_edited",&ShaderGraphView::_tex_edited);
+ ObjectTypeDB::bind_method("_variant_edited",&ShaderGraphView::_variant_edited);
+ ObjectTypeDB::bind_method("_cube_edited",&ShaderGraphView::_cube_edited);
+ ObjectTypeDB::bind_method("_comment_edited",&ShaderGraphView::_comment_edited);
- TreeItem * item = add_types->get_selected();
- ERR_FAIL_COND(!item);
- _node_add((VisualServer::ShaderNodeType)(int)item->get_metadata(0));
- add_popup->hide() ;
}
-ShaderEditor::ShaderEditor() {
-
- set_focus_mode(FOCUS_ALL);
-
- Panel* menu_panel = memnew( Panel );
- menu_panel->set_anchor( MARGIN_RIGHT, Control::ANCHOR_END );
- menu_panel->set_end( Point2(0,22) );
-
- add_child( menu_panel );
-
- PopupMenu *p;
- List<PropertyInfo> defaults;
-
- MenuButton* node_menu = memnew( MenuButton );
- node_menu->set_text("Graph");
- node_menu->set_pos( Point2( 5,0) );
- menu_panel->add_child( node_menu );
-
- p=node_menu->get_popup();
- p->add_item("Add Node",GRAPH_ADD_NODE);
- p->add_separator();
- p->add_item("Clear",GRAPH_CLEAR);
- p->connect("item_pressed", this,"_node_menu_item");
+ShaderGraphView::ShaderGraphView(ShaderGraph::ShaderType p_type) {
- MenuButton* vertex_menu = memnew( MenuButton );
- vertex_menu->set_text("Vertex");
- vertex_menu->set_pos( Point2( 49,0) );
- menu_panel->add_child( vertex_menu );
+ type=p_type;
+ graph_edit = memnew( GraphEdit );
+ block_update=false;
+ ped_popup = memnew( CustomPropertyEditor );
+ graph_edit->add_child(ped_popup);
- p=vertex_menu->get_popup();
- defaults.clear();
- VisualServer::shader_get_default_input_nodes(VisualServer::SHADER_VERTEX,&defaults);
- int id=0;
- for(int i=0;i<defaults.size();i++) {
-
- p->add_item("In: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++);
- }
- p->add_separator();
- id++;
-
- defaults.clear();
- VisualServer::shader_get_default_output_nodes(VisualServer::SHADER_VERTEX,&defaults);
-
- for(int i=0;i<defaults.size();i++) {
-
- p->add_item("Out: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++);
- }
+}
- vertex_popup=p;
- vertex_popup->connect("item_pressed", this,"_vertex_item");
- MenuButton* fragment_menu = memnew( MenuButton );
- fragment_menu->set_text("Fragment");
- fragment_menu->set_pos( Point2( 95 ,0) );
- menu_panel->add_child( fragment_menu );
- p=fragment_menu->get_popup();
- defaults.clear();
- VisualServer::shader_get_default_input_nodes(VisualServer::SHADER_FRAGMENT,&defaults);
- id=0;
- for(int i=0;i<defaults.size();i++) {
+//////////////edit//////////////
+void ShaderGraphEditor::edit(Ref<ShaderGraph> p_shader) {
- p->add_item("In: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++);
- }
- p->add_separator();
- id++;
- defaults.clear();
- VisualServer::shader_get_default_output_nodes(VisualServer::SHADER_FRAGMENT,&defaults);
-
- for(int i=0;i<defaults.size();i++) {
-
- p->add_item("Out: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++);
+ for(int i=0;i<ShaderGraph::SHADER_TYPE_MAX;i++) {
+ graph_edits[i]->set_graph(p_shader);
}
+}
- fragment_popup=p;
- fragment_popup->connect("item_pressed", this,"_fragment_item");
+void ShaderGraphEditor::_add_node(int p_type) {
- MenuButton* post_menu = memnew( MenuButton );
- post_menu->set_text("Post");
- post_menu->set_pos( Point2( 161,0) );
- menu_panel->add_child( post_menu );
+ ShaderGraph::ShaderType shader_type=ShaderGraph::ShaderType(tabs->get_current_tab());
- p=post_menu->get_popup();
- defaults.clear();
- VisualServer::shader_get_default_input_nodes(VisualServer::SHADER_POST_PROCESS,&defaults);
- id=0;
- for(int i=0;i<defaults.size();i++) {
+ graph_edits[shader_type]->add_node(p_type);
+}
- p->add_item("In: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++);
- }
- p->add_separator();
- id++;
- defaults.clear();
- VisualServer::shader_get_default_output_nodes(VisualServer::SHADER_POST_PROCESS,&defaults);
+void ShaderGraphEditor::_notification(int p_what) {
+ if (p_what==NOTIFICATION_ENTER_TREE) {
+ menu->get_popup()->connect("item_pressed",this,"_add_node");
- for(int i=0;i<defaults.size();i++) {
- p->add_item("Out: "+defaults[i].name+(defaults[i].type==Variant::VECTOR3?" (vec3)":" (real)"),id++);
}
+}
- post_popup=p;
- post_popup->connect("item_pressed", this,"_post_item");
-
+void ShaderGraphEditor::_bind_methods() {
- /* add popup */
+ ObjectTypeDB::bind_method("_add_node",&ShaderGraphEditor::_add_node);
- add_popup = memnew( Popup );
- add_child(add_popup);
- add_popup->set_as_toplevel(true);
- Panel *add_panel = memnew( Panel );
- add_popup->add_child(add_panel);
- add_panel->set_area_as_parent_rect();
+}
- Label *add_label = memnew (Label );
- add_label->set_pos(Point2(5,5));
- add_label->set_text("Available Nodes:");
- add_panel->add_child(add_label);
+const char* ShaderGraphEditor::node_names[ShaderGraph::NODE_TYPE_MAX]={
+ "Input", // all inputs (shader type dependent)
+ "Scalar Constant", //scalar constant
+ "Vector Constant", //vec3 constant
+ "RGB Constant", //rgb constant (shows a color picker instead)
+ "XForm Constant", // 4x4 matrix constant
+ "Time:", // time in seconds
+ "Screen Sample", // screen texture sampler (takes uv) (only usable in fragment shader)
+ "Scalar Operator", // scalar vs scalar op (mul", add", div", etc)
+ "Vector Operator", // vec3 vs vec3 op (mul",ad",div",crossprod",etc)
+ "Scalar+Vector Operator", // vec3 vs scalar op (mul", add", div", etc)
+ "RGB Operator:", // vec3 vs vec3 rgb op (with scalar amount)", like brighten", darken", burn", dodge", multiply", etc.
+ "XForm Multiply", // mat4 x mat4
+ "XForm+Vector Multiply", // mat4 x vec3 mult (with no-translation option)
+ "XForm+Vector InvMultiply:", // mat4 x vec3 inverse mult (with no-translation option)
+ "Scalar Function", // scalar function (sin", cos", etc)
+ "Vector Function", // vector function (normalize", negate", reciprocal", rgb2hsv", hsv2rgb", etc", etc)
+ "Vector Length", // vec3 length
+ "Dot Product:", // vec3 . vec3 (dot product -> scalar output)
+ "Vector -> Scalars", // 1 vec3 input", 3 scalar outputs
+ "Scalars -> Vector", // 3 scalar input", 1 vec3 output
+ "XForm -> Vectors", // 3 vec input", 1 xform output
+ "Vectors -> XForm:", // 3 vec input", 1 xform output
+ "Scalar Interpolate", // scalar interpolation (with optional curve)
+ "Vector Interpolate:", // vec3 interpolation (with optional curve)
+ "Scalar Uniform", // scalar uniform (assignable in material)
+ "Vector Uniform", // vec3 uniform (assignable in material)
+ "RGB Uniform", // color uniform (assignable in material)
+ "XForm Uniform", // mat4 uniform (assignable in material)
+ "Texture Uniform", // texture input (assignable in material)
+ "CubeMap Uniform:", // cubemap input (assignable in material)
+ "Output", // output (shader type dependent)
+ "Comment", // comment
- add_types = memnew( Tree );
- add_types->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- add_types->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
- add_types->set_begin( Point2( 20,25 ) );
- add_types->set_end( Point2( 10, 30 ) );
- add_types->set_hide_root(true);
- add_types->set_columns(4);
- add_types->set_select_mode(Tree::SELECT_ROW);
+};
+ShaderGraphEditor::ShaderGraphEditor() {
- TreeItem *add_types_root = add_types->create_item(NULL);
- TreeItem *info_item = add_types->create_item(add_types_root);
+ HBoxContainer *hbc = memnew( HBoxContainer );
+ menu = memnew( MenuButton );
+ menu->set_text("Add..");
+ hbc->add_child(menu);
+ add_child(hbc);
+ for(int i=0;i<ShaderGraph::NODE_TYPE_MAX;i++) {
- for(int i=0;i<VisualServer::NODE_TYPE_MAX;i++) {
+ if (i==ShaderGraph::NODE_OUTPUT)
+ continue;
+ String v = node_names[i];
+ bool addsep=false;
+ if (v.ends_with(":")) {
+ addsep=true;
+ v=v.substr(0,v.length()-1);
+ }
+ menu->get_popup()->add_item(v,i);
+ if (addsep)
+ menu->get_popup()->add_separator();
+ }
- TreeItem *item = add_types->create_item(add_types_root);
- PropertyInfo prop = VisualServer::shader_node_get_type_info((VisualServer::ShaderNodeType)i);
- item->set_text(0,prop.name);
- item->set_text(1,itos(VisualServer::shader_get_input_count((VisualServer::ShaderNodeType)i)));
- item->set_text(2,itos(VisualServer::shader_get_output_count((VisualServer::ShaderNodeType)i)));
- String hint = (prop.type==Variant::_RID)?prop.hint_string:Variant::get_type_name(prop.type);
- item->set_text(3,hint);
- item->set_metadata(0,i);
+ tabs = memnew(TabContainer);
+ tabs->set_v_size_flags(SIZE_EXPAND_FILL);
+ add_child(tabs);
+ const char* sname[ShaderGraph::SHADER_TYPE_MAX]={
+ "Vertex",
+ "Fragment",
+ "Light"
+ };
+ for(int i=0;i<ShaderGraph::SHADER_TYPE_MAX;i++) {
+
+ graph_edits[i]= memnew( ShaderGraphView(ShaderGraph::ShaderType(i)) );
+ add_child(graph_edits[i]);
+ graph_edits[i]->get_graph_edit()->set_name(sname[i]);
+ tabs->add_child(graph_edits[i]->get_graph_edit());
+ graph_edits[i]->get_graph_edit()->connect("connection_request",graph_edits[i],"_connection_request");
}
- info_item->set_text(0,"::NODE::");
- info_item->set_custom_color(0,Color(0.6,0.1,0.1));
- info_item->set_text(1,"::INPUTS::");
- info_item->set_custom_color(1,Color(0.6,0.1,0.1));
- info_item->set_text(2,"::OUTPUTS::");
- info_item->set_custom_color(2,Color(0.6,0.1,0.1));
- info_item->set_text(3,"::PARAM::");
- info_item->set_custom_color(3,Color(0.6,0.1,0.1));
- info_item->set_selectable(0,false);
- info_item->set_selectable(1,false);
- info_item->set_selectable(2,false);
- info_item->set_selectable(3,false);
-
- add_panel->add_child(add_types);
-
- add_confirm = memnew( Button );
- add_confirm->set_anchor( MARGIN_LEFT, ANCHOR_END );
- add_confirm->set_anchor( MARGIN_TOP, ANCHOR_END );
- add_confirm->set_anchor( MARGIN_RIGHT, ANCHOR_END );
- add_confirm->set_anchor( MARGIN_BOTTOM, ANCHOR_END );
- add_confirm->set_begin( Point2( 75, 29 ) );
- add_confirm->set_end( Point2( 10, 15 ) );
- add_confirm->set_text("Add");
- add_panel->add_child(add_confirm);
- add_confirm->connect("pressed", this,"_node_add_callback");
-
- last_id=1;
- last_x=20;
- last_y=20;
-
- property_editor = memnew( CustomPropertyEditor );
- add_child(property_editor);
- property_editor->connect("variant_changed", this,"_node_param_changed");
-
- h_scroll = memnew( HScrollBar );
- v_scroll = memnew( VScrollBar );
-
- add_child(h_scroll);
- add_child(v_scroll);
-
- h_scroll->connect("value_changed", this,"_scroll_moved");
- v_scroll->connect("value_changed", this,"_scroll_moved");
-
- node_popup= memnew(PopupMenu );
- add_child(node_popup);
- node_popup->set_as_toplevel(true);
-
- node_popup->connect("item_pressed", this,"_node_menu_item");
+ set_custom_minimum_size(Size2(100,300));
}
-void ShaderEditorPlugin::edit(Object *p_object) {
+void ShaderGraphEditorPlugin::edit(Object *p_object) {
- shader_editor->edit(p_object->cast_to<Shader>());
+ shader_editor->edit(p_object->cast_to<ShaderGraph>());
}
-bool ShaderEditorPlugin::handles(Object *p_object) const {
+bool ShaderGraphEditorPlugin::handles(Object *p_object) const {
- return p_object->is_type("Shader");
+ return p_object->is_type("ShaderGraph");
}
-void ShaderEditorPlugin::make_visible(bool p_visible) {
+void ShaderGraphEditorPlugin::make_visible(bool p_visible) {
if (p_visible) {
shader_editor->show();
- shader_editor->set_process(true);
} else {
shader_editor->hide();
- shader_editor->set_process(false);
}
}
-ShaderEditorPlugin::ShaderEditorPlugin(EditorNode *p_node) {
+ShaderGraphEditorPlugin::ShaderGraphEditorPlugin(EditorNode *p_node) {
editor=p_node;
- shader_editor = memnew( ShaderEditor );
- editor->get_viewport()->add_child(shader_editor);
- shader_editor->set_area_as_parent_rect();
+ shader_editor = memnew( ShaderGraphEditor );
shader_editor->hide();
+ SpatialEditor::get_singleton()->get_shader_split()->add_child(shader_editor);
+// editor->get_viewport()->add_child(shader_editor);
+// shader_editor->set_area_as_parent_rect();
+// shader_editor->hide();
}
-ShaderEditorPlugin::~ShaderEditorPlugin()
+ShaderGraphEditorPlugin::~ShaderGraphEditorPlugin()
{
}
-#endif
+
diff --git a/tools/editor/plugins/shader_graph_editor_plugin.h b/tools/editor/plugins/shader_graph_editor_plugin.h
index 5b0767dc82..26dbd1ac6e 100644
--- a/tools/editor/plugins/shader_graph_editor_plugin.h
+++ b/tools/editor/plugins/shader_graph_editor_plugin.h
@@ -29,122 +29,121 @@
#ifndef SHADER_GRAPH_EDITOR_PLUGIN_H
#define SHADER_GRAPH_EDITOR_PLUGIN_H
-#if 0
+
#include "tools/editor/editor_plugin.h"
#include "tools/editor/editor_node.h"
#include "scene/resources/shader.h"
#include "servers/visual/shader_graph.h"
#include "scene/gui/tree.h"
#include "scene/gui/button.h"
+#include "scene/gui/graph_edit.h"
#include "scene/gui/popup.h"
#include "tools/editor/property_editor.h"
+#include "scene/resources/shader_graph.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
-class ShaderEditor : public Control {
-
- OBJ_TYPE(ShaderEditor, Control );
-
- enum MenuAction {
-
- GRAPH_ADD_NODE,
- GRAPH_CLEAR,
- NODE_DISCONNECT,
- NODE_ERASE,
-
- };
-
- enum ClickType {
- CLICK_NONE,
- CLICK_NODE,
- CLICK_INPUT_SLOT,
- CLICK_OUTPUT_SLOT,
- CLICK_PARAMETER
- };
-
- PopupMenu *node_popup;
- Popup *add_popup;
- PopupMenu *vertex_popup;
- PopupMenu *fragment_popup;
- PopupMenu *post_popup;
- Tree *add_types;
- Button *add_confirm;
- HScrollBar *h_scroll;
- VScrollBar *v_scroll;
-
- Ref<Shader> shader;
- List<int> order;
- Set<int> active_nodes;
- ShaderGraph shader_graph;
- int last_x,last_y;
- uint32_t last_id;
-
- CustomPropertyEditor *property_editor;
-
- Point2 offset;
- ClickType click_type;
- Point2 click_pos;
- int click_node;
- int click_slot;
- Point2 click_motion;
- ClickType rclick_type;
- int rclick_node;
- int rclick_slot;
-
- Size2 _get_maximum_size();
- Size2 get_node_size(int p_node) const;
- void _draw_node(int p_node);
-
- void _add_node_from_text(const String& p_text);
- void _update_scrollbars();
- void _scroll_moved();
- void _node_param_changed();
- void _node_add_callback();
- void _node_add(VisualServer::ShaderNodeType p_type);
- void _node_edit_property(int p_node);
- void _node_menu_item(int p_item);
- void _vertex_item(int p_item);
- void _fragment_item(int p_item);
- void _post_item(int p_item);
-
- ClickType _locate_click(const Point2& p_click,int *p_node_id,int *p_slot_index) const;
- Point2 _get_slot_pos(int p_node_id,bool p_input,int p_slot);
-
- Error validate_graph();
-
- void _read_shader_graph();
- void _write_shader_graph();
-
- virtual bool has_point(const Point2& p_point) const;
+
+class ShaderGraphView : public Node {
+
+ OBJ_TYPE(ShaderGraphView,Node);
+
+
+
+ CustomPropertyEditor *ped_popup;
+ bool block_update;
+
+ GraphEdit *graph_edit;
+ Ref<ShaderGraph> graph;
+ int edited_id;
+
+ ShaderGraph::ShaderType type;
+
+ void _update_graph();
+ void _create_node(int p_id);
+
+
+
+ void _connection_request(const String& p_from, int p_from_slot,const String& p_to,int p_to_slot);
+ void _node_removed(int p_id);
+ void _node_moved(const Vector2& p_from, const Vector2& p_to,int p_id);
+ void _move_node(int p_id,const Vector2& p_to);
+
+ void _scalar_const_changed(double p_value,int p_id);
+ void _vec_const_changed(double p_value, int p_id, Array p_arr);
+ void _rgb_const_changed(const Color& p_color, int p_id);
+ void _xform_const_changed(int p_id,Node* p_button);
+ void _scalar_op_changed(int p_op, int p_id);
+ void _vec_op_changed(int p_op, int p_id);
+ void _vec_scalar_op_changed(int p_op, int p_id);
+ void _rgb_op_changed(int p_op, int p_id);
+ void _xform_inv_rev_changed(bool p_enabled, int p_id);
+ void _scalar_func_changed(int p_func, int p_id);
+ void _vec_func_changed(int p_func, int p_id);
+ void _scalar_input_changed(double p_value,int p_id);
+ void _vec_input_changed(double p_value, int p_id, Array p_arr);
+ void _xform_input_changed(int p_id,Node* p_button);
+ void _rgb_input_changed(const Color& p_color, int p_id);
+ void _tex_input_change(int p_id,Node* p_button);
+ void _cube_input_change(int p_id);
+ void _input_name_changed(const String& p_name,int p_id,Node* p_line_edit);
+ void _tex_edited(int p_id,Node* p_button);
+ void _cube_edited(int p_id,Node* p_button);
+ void _variant_edited();
+ void _comment_edited(int p_id,Node* p_button);
+
+
+ Map<int,GraphNode*> node_map;
protected:
void _notification(int p_what);
- void _input_event(InputEvent p_event);
static void _bind_methods();
public:
- void edit(Ref<Shader> p_shader);
- ShaderEditor();
+ void add_node(int p_type);
+ GraphEdit *get_graph_edit() { return graph_edit; }
+ void set_graph(Ref<ShaderGraph> p_graph);
+
+ ShaderGraphView(ShaderGraph::ShaderType p_type=ShaderGraph::SHADER_TYPE_FRAGMENT);
};
-class ShaderEditorPlugin : public EditorPlugin {
+class ShaderGraphEditor : public VBoxContainer {
- OBJ_TYPE( ShaderEditorPlugin, EditorPlugin );
+ OBJ_TYPE(ShaderGraphEditor,VBoxContainer);
- ShaderEditor *shader_editor;
+ MenuButton *menu;
+ TabContainer *tabs;
+ ShaderGraphView *graph_edits[ShaderGraph::SHADER_TYPE_MAX];
+ static const char* node_names[ShaderGraph::NODE_TYPE_MAX];
+
+ void _add_node(int p_type);
+protected:
+ void _notification(int p_what);
+ static void _bind_methods();
+public:
+
+ void edit(Ref<ShaderGraph> p_shader);
+ ShaderGraphEditor();
+};
+
+class ShaderGraphEditorPlugin : public EditorPlugin {
+
+ OBJ_TYPE( ShaderGraphEditorPlugin, EditorPlugin );
+
+ ShaderGraphEditor *shader_editor;
EditorNode *editor;
public:
- virtual String get_name() const { return "Shader"; }
+ virtual String get_name() const { return "ShaderGraph"; }
bool has_main_screen() const { return false; }
virtual void edit(Object *p_node);
virtual bool handles(Object *p_node) const;
virtual void make_visible(bool p_visible);
- ShaderEditorPlugin(EditorNode *p_node);
- ~ShaderEditorPlugin();
+ ShaderGraphEditorPlugin(EditorNode *p_node);
+ ~ShaderGraphEditorPlugin();
};
#endif
-#endif // SHADER_GRAPH_EDITOR_PLUGIN_H
+