Browse Source

Select and move multiple nodes at once

Mariano Javier Suligoy 10 years ago
parent
commit
bdd12744fe

+ 475 - 386
scene/gui/graph_edit.cpp

@@ -3,388 +3,385 @@
 #include "os/keyboard.h"
 #include "os/keyboard.h"
 bool GraphEditFilter::has_point(const Point2& p_point) const {
 bool GraphEditFilter::has_point(const Point2& p_point) const {
 
 
-	return ge->_filter_input(p_point);
+    return ge->_filter_input(p_point);
 }
 }
 
 
 
 
 GraphEditFilter::GraphEditFilter(GraphEdit *p_edit) {
 GraphEditFilter::GraphEditFilter(GraphEdit *p_edit) {
 
 
-	ge=p_edit;
+    ge=p_edit;
 }
 }
 
 
 
 
 Error GraphEdit::connect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port) {
 Error GraphEdit::connect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port) {
 
 
-	if (is_node_connected(p_from,p_from_port,p_to,p_to_port))
-		return OK;
-	Connection c;
-	c.from=p_from;
-	c.from_port=p_from_port;
-	c.to=p_to;
-	c.to_port=p_to_port;
-	connections.push_back(c);
-	top_layer->update();
-
-	return OK;
+    if (is_node_connected(p_from,p_from_port,p_to,p_to_port))
+        return OK;
+    Connection c;
+    c.from=p_from;
+    c.from_port=p_from_port;
+    c.to=p_to;
+    c.to_port=p_to_port;
+    connections.push_back(c);
+    top_layer->update();
+
+    return OK;
 }
 }
 
 
 bool GraphEdit::is_node_connected(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port) {
 bool GraphEdit::is_node_connected(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port) {
 
 
-	for(List<Connection>::Element *E=connections.front();E;E=E->next()) {
+    for(List<Connection>::Element *E=connections.front();E;E=E->next()) {
 
 
-		if (E->get().from==p_from && E->get().from_port==p_from_port && E->get().to==p_to && E->get().to_port==p_to_port)
-			return true;
-	}
+        if (E->get().from==p_from && E->get().from_port==p_from_port && E->get().to==p_to && E->get().to_port==p_to_port)
+            return true;
+    }
 
 
-	return false;
+    return false;
 
 
 }
 }
 
 
 void GraphEdit::disconnect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port){
 void GraphEdit::disconnect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port){
 
 
 
 
-	for(List<Connection>::Element *E=connections.front();E;E=E->next()) {
+    for(List<Connection>::Element *E=connections.front();E;E=E->next()) {
 
 
-		if (E->get().from==p_from && E->get().from_port==p_from_port && E->get().to==p_to && E->get().to_port==p_to_port) {
+        if (E->get().from==p_from && E->get().from_port==p_from_port && E->get().to==p_to && E->get().to_port==p_to_port) {
 
 
-			connections.erase(E);
-			top_layer->update();
-			return;
-		}
-	}
+            connections.erase(E);
+            top_layer->update();
+            return;
+        }
+    }
 }
 }
 
 
 void GraphEdit::get_connection_list(List<Connection> *r_connections) const {
 void GraphEdit::get_connection_list(List<Connection> *r_connections) const {
 
 
-	*r_connections=connections;
+    *r_connections=connections;
 }
 }
 
 
 
 
 void GraphEdit::_scroll_moved(double) {
 void GraphEdit::_scroll_moved(double) {
 
 
 
 
-	_update_scroll_offset();
-	top_layer->update();
+    _update_scroll_offset();
+    top_layer->update();
 }
 }
 
 
 void GraphEdit::_update_scroll_offset() {
 void GraphEdit::_update_scroll_offset() {
 
 
-	for(int i=0;i<get_child_count();i++) {
+    for(int i=0;i<get_child_count();i++) {
 
 
-		GraphNode *gn=get_child(i)->cast_to<GraphNode>();
-		if (!gn)
-			continue;
+        GraphNode *gn=get_child(i)->cast_to<GraphNode>();
+        if (!gn)
+            continue;
 
 
-		Point2 pos=gn->get_offset();
-		pos-=Point2(h_scroll->get_val(),v_scroll->get_val());
-		gn->set_pos(pos);
-	}
+        Point2 pos=gn->get_offset();
+        pos-=Point2(h_scroll->get_val(),v_scroll->get_val());
+        gn->set_pos(pos);
+    }
 
 
 }
 }
 
 
 void GraphEdit::_update_scroll() {
 void GraphEdit::_update_scroll() {
 
 
-	if (updating)
-		return;
+    if (updating)
+        return;
 
 
-	updating=true;
-	Rect2 screen;
-	for(int i=0;i<get_child_count();i++) {
+    updating=true;
+    Rect2 screen;
+    for(int i=0;i<get_child_count();i++) {
 
 
-		GraphNode *gn=get_child(i)->cast_to<GraphNode>();
-		if (!gn)
-			continue;
+        GraphNode *gn=get_child(i)->cast_to<GraphNode>();
+        if (!gn)
+            continue;
 
 
-		Rect2 r;
-		r.pos=gn->get_offset();
-		r.size=gn->get_size();
-		screen = screen.merge(r);
-	}
+        Rect2 r;
+        r.pos=gn->get_offset();
+        r.size=gn->get_size();
+        screen = screen.merge(r);
+    }
 
 
-	screen.pos-=get_size();
-	screen.size+=get_size()*2.0;
+    screen.pos-=get_size();
+    screen.size+=get_size()*2.0;
 
 
 
 
-	h_scroll->set_min(screen.pos.x);
-	h_scroll->set_max(screen.pos.x+screen.size.x);
-	h_scroll->set_page(get_size().x);
-	if (h_scroll->get_max() - h_scroll->get_min() <= h_scroll->get_page())
-		h_scroll->hide();
-	else
-		h_scroll->show();
+    h_scroll->set_min(screen.pos.x);
+    h_scroll->set_max(screen.pos.x+screen.size.x);
+    h_scroll->set_page(get_size().x);
+    if (h_scroll->get_max() - h_scroll->get_min() <= h_scroll->get_page())
+        h_scroll->hide();
+    else
+        h_scroll->show();
 
 
-	v_scroll->set_min(screen.pos.y);
-	v_scroll->set_max(screen.pos.y+screen.size.y);
-	v_scroll->set_page(get_size().y);
+    v_scroll->set_min(screen.pos.y);
+    v_scroll->set_max(screen.pos.y+screen.size.y);
+    v_scroll->set_page(get_size().y);
 
 
-	if (v_scroll->get_max() - v_scroll->get_min() <= v_scroll->get_page())
-		v_scroll->hide();
-	else
-		v_scroll->show();
+    if (v_scroll->get_max() - v_scroll->get_min() <= v_scroll->get_page())
+        v_scroll->hide();
+    else
+        v_scroll->show();
 
 
-	_update_scroll_offset();
-	updating=false;
+    _update_scroll_offset();
+    updating=false;
 }
 }
 
 
 
 
 void GraphEdit::_graph_node_raised(Node* p_gn) {
 void GraphEdit::_graph_node_raised(Node* p_gn) {
 
 
-	GraphNode *gn=p_gn->cast_to<GraphNode>();
-	ERR_FAIL_COND(!gn);
-	gn->raise();
-	top_layer->raise();
+    GraphNode *gn=p_gn->cast_to<GraphNode>();
+    ERR_FAIL_COND(!gn);
+    gn->raise();
+    top_layer->raise();
 
 
 }
 }
 
 
 
 
 void GraphEdit::_graph_node_moved(Node *p_gn) {
 void GraphEdit::_graph_node_moved(Node *p_gn) {
 
 
-	GraphNode *gn=p_gn->cast_to<GraphNode>();
-	ERR_FAIL_COND(!gn);
-
-	//gn->set_pos(gn->get_offset()+scroll_offset);
-
-	top_layer->update();
+    GraphNode *gn=p_gn->cast_to<GraphNode>();
+    ERR_FAIL_COND(!gn);
+    top_layer->update();
 }
 }
 
 
 void GraphEdit::add_child_notify(Node *p_child) {
 void GraphEdit::add_child_notify(Node *p_child) {
 
 
-	top_layer->call_deferred("raise"); //top layer always on top!
-	GraphNode *gn = p_child->cast_to<GraphNode>();
-	if (gn) {
-		gn->connect("offset_changed",this,"_graph_node_moved",varray(gn));
-		gn->connect("raise_request",this,"_graph_node_raised",varray(gn));
-		_graph_node_moved(gn);
-		gn->set_stop_mouse(false);
-	}
+    top_layer->call_deferred("raise"); //top layer always on top!
+    GraphNode *gn = p_child->cast_to<GraphNode>();
+    if (gn) {
+        gn->connect("offset_changed",this,"_graph_node_moved",varray(gn));
+        gn->connect("raise_request",this,"_graph_node_raised",varray(gn));
+        _graph_node_moved(gn);
+        gn->set_stop_mouse(false);
+    }
 }
 }
 
 
 void GraphEdit::remove_child_notify(Node *p_child) {
 void GraphEdit::remove_child_notify(Node *p_child) {
 
 
-	top_layer->call_deferred("raise"); //top layer always on top!
-	GraphNode *gn = p_child->cast_to<GraphNode>();
-	if (gn) {
-		gn->disconnect("offset_changed",this,"_graph_node_moved");
-		gn->disconnect("raise_request",this,"_graph_node_raised");
-	}
+    top_layer->call_deferred("raise"); //top layer always on top!
+    GraphNode *gn = p_child->cast_to<GraphNode>();
+    if (gn) {
+        gn->disconnect("offset_changed",this,"_graph_node_moved");
+        gn->disconnect("raise_request",this,"_graph_node_raised");
+    }
 }
 }
 
 
 void GraphEdit::_notification(int p_what) {
 void GraphEdit::_notification(int p_what) {
 
 
-	if (p_what==NOTIFICATION_READY) {
-		Size2 size = top_layer->get_size();
-		Size2 hmin = h_scroll->get_combined_minimum_size();
-		Size2 vmin = v_scroll->get_combined_minimum_size();
+    if (p_what==NOTIFICATION_READY) {
+        Size2 size = top_layer->get_size();
+        Size2 hmin = h_scroll->get_combined_minimum_size();
+        Size2 vmin = v_scroll->get_combined_minimum_size();
 
 
-		v_scroll->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,vmin.width);
-		v_scroll->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,0);
-		v_scroll->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,0);
-		v_scroll->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,0);
+        v_scroll->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_END,vmin.width);
+        v_scroll->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,0);
+        v_scroll->set_anchor_and_margin(MARGIN_TOP,ANCHOR_BEGIN,0);
+        v_scroll->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,0);
 
 
-		h_scroll->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,0);
-		h_scroll->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,0);
-		h_scroll->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,hmin.height);
-		h_scroll->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,0);
+        h_scroll->set_anchor_and_margin(MARGIN_LEFT,ANCHOR_BEGIN,0);
+        h_scroll->set_anchor_and_margin(MARGIN_RIGHT,ANCHOR_END,0);
+        h_scroll->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,hmin.height);
+        h_scroll->set_anchor_and_margin(MARGIN_BOTTOM,ANCHOR_END,0);
 
 
-	}
-	if (p_what==NOTIFICATION_DRAW) {
-		VS::get_singleton()->canvas_item_set_clip(get_canvas_item(),true);
+    }
+    if (p_what==NOTIFICATION_DRAW) {
+        VS::get_singleton()->canvas_item_set_clip(get_canvas_item(),true);
 
 
-	}
+    }
 
 
-	if (p_what==NOTIFICATION_RESIZED) {
-		_update_scroll();
-		top_layer->update();
-	}
+    if (p_what==NOTIFICATION_RESIZED) {
+        _update_scroll();
+        top_layer->update();
+    }
 }
 }
 
 
 bool GraphEdit::_filter_input(const Point2& p_point) {
 bool GraphEdit::_filter_input(const Point2& p_point) {
 
 
-	Ref<Texture> port =get_icon("port","GraphNode");
+    Ref<Texture> port =get_icon("port","GraphNode");
 
 
-	float grab_r=port->get_width()*0.5;
-	for(int i=get_child_count()-1;i>=0;i--) {
+    float grab_r=port->get_width()*0.5;
+    for(int i=get_child_count()-1;i>=0;i--) {
 
 
-		GraphNode *gn=get_child(i)->cast_to<GraphNode>();
-		if (!gn)
-			continue;
+        GraphNode *gn=get_child(i)->cast_to<GraphNode>();
+        if (!gn)
+            continue;
 
 
-		for(int j=0;j<gn->get_connection_output_count();j++) {
+        for(int j=0;j<gn->get_connection_output_count();j++) {
 
 
-			Vector2 pos = gn->get_connection_output_pos(j)+gn->get_pos();
-			if (pos.distance_to(p_point)<grab_r)
-				return true;
+            Vector2 pos = gn->get_connection_output_pos(j)+gn->get_pos();
+            if (pos.distance_to(p_point)<grab_r)
+                return true;
 
 
 
 
-		}
+        }
 
 
-		for(int j=0;j<gn->get_connection_input_count();j++) {
+        for(int j=0;j<gn->get_connection_input_count();j++) {
 
 
-			Vector2 pos = gn->get_connection_input_pos(j)+gn->get_pos();
-			if (pos.distance_to(p_point)<grab_r)
-				return true;
+            Vector2 pos = gn->get_connection_input_pos(j)+gn->get_pos();
+            if (pos.distance_to(p_point)<grab_r)
+                return true;
 
 
 
 
-		}
+        }
 
 
-	}
+    }
 
 
-	return false;
+    return false;
 }
 }
 
 
 void GraphEdit::_top_layer_input(const InputEvent& p_ev) {
 void GraphEdit::_top_layer_input(const InputEvent& p_ev) {
 
 
-	if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index==BUTTON_LEFT && p_ev.mouse_button.pressed) {
+    if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index==BUTTON_LEFT && p_ev.mouse_button.pressed) {
 
 
-		Ref<Texture> port =get_icon("port","GraphNode");
-		Vector2 mpos(p_ev.mouse_button.x,p_ev.mouse_button.y);
-		float grab_r=port->get_width()*0.5;
-		for(int i=get_child_count()-1;i>=0;i--) {
+        Ref<Texture> port =get_icon("port","GraphNode");
+        Vector2 mpos(p_ev.mouse_button.x,p_ev.mouse_button.y);
+        float grab_r=port->get_width()*0.5;
+        for(int i=get_child_count()-1;i>=0;i--) {
 
 
-			GraphNode *gn=get_child(i)->cast_to<GraphNode>();
-			if (!gn)
-				continue;
+            GraphNode *gn=get_child(i)->cast_to<GraphNode>();
+            if (!gn)
+                continue;
 
 
-			for(int j=0;j<gn->get_connection_output_count();j++) {
+            for(int j=0;j<gn->get_connection_output_count();j++) {
 
 
-				Vector2 pos = gn->get_connection_output_pos(j)+gn->get_pos();
-				if (pos.distance_to(mpos)<grab_r) {
+                Vector2 pos = gn->get_connection_output_pos(j)+gn->get_pos();
+                if (pos.distance_to(mpos)<grab_r) {
 
 
-					connecting=true;
-					connecting_from=gn->get_name();
-					connecting_index=j;
-					connecting_out=true;
-					connecting_type=gn->get_connection_output_type(j);
-					connecting_color=gn->get_connection_output_color(j);
-					connecting_target=false;
-					connecting_to=pos;
-					return;
-				}
+                    connecting=true;
+                    connecting_from=gn->get_name();
+                    connecting_index=j;
+                    connecting_out=true;
+                    connecting_type=gn->get_connection_output_type(j);
+                    connecting_color=gn->get_connection_output_color(j);
+                    connecting_target=false;
+                    connecting_to=pos;
+                    return;
+                }
 
 
 
 
-			}
+            }
 
 
-			for(int j=0;j<gn->get_connection_input_count();j++) {
+            for(int j=0;j<gn->get_connection_input_count();j++) {
 
 
-				Vector2 pos = gn->get_connection_input_pos(j)+gn->get_pos();
+                Vector2 pos = gn->get_connection_input_pos(j)+gn->get_pos();
 
 
-				if (pos.distance_to(mpos)<grab_r) {
+                if (pos.distance_to(mpos)<grab_r) {
 
 
-					if (right_disconnects) {
-						//check disconnect
-						for (List<Connection>::Element*E=connections.front();E;E=E->next()) {
+                    if (right_disconnects) {
+                        //check disconnect
+                        for (List<Connection>::Element*E=connections.front();E;E=E->next()) {
 
 
-							if (E->get().to==gn->get_name() && E->get().to_port==j) {
+                            if (E->get().to==gn->get_name() && E->get().to_port==j) {
 
 
-								Node*fr = get_node(String(E->get().from));
-								if (fr && fr->cast_to<GraphNode>()) {
+                                Node*fr = get_node(String(E->get().from));
+                                if (fr && fr->cast_to<GraphNode>()) {
 
 
-									connecting_from=E->get().from;
-									connecting_index=E->get().from_port;
-									connecting_out=true;
-									connecting_type=fr->cast_to<GraphNode>()->get_connection_output_type(E->get().from_port);
-									connecting_color=fr->cast_to<GraphNode>()->get_connection_output_color(E->get().from_port);
-									connecting_target=false;
-									connecting_to=pos;
+                                    connecting_from=E->get().from;
+                                    connecting_index=E->get().from_port;
+                                    connecting_out=true;
+                                    connecting_type=fr->cast_to<GraphNode>()->get_connection_output_type(E->get().from_port);
+                                    connecting_color=fr->cast_to<GraphNode>()->get_connection_output_color(E->get().from_port);
+                                    connecting_target=false;
+                                    connecting_to=pos;
 
 
-									emit_signal("disconnection_request",E->get().from,E->get().from_port,E->get().to,E->get().to_port);
-									fr = get_node(String(connecting_from)); //maybe it was erased
-									if (fr && fr->cast_to<GraphNode>()) {
-										connecting=true;
-									}
-									return;
-								}
+                                    emit_signal("disconnection_request",E->get().from,E->get().from_port,E->get().to,E->get().to_port);
+                                    fr = get_node(String(connecting_from)); //maybe it was erased
+                                    if (fr && fr->cast_to<GraphNode>()) {
+                                        connecting=true;
+                                    }
+                                    return;
+                                }
 
 
-							}
-						}
-					}
+                            }
+                        }
+                    }
 
 
 
 
-					connecting=true;
-					connecting_from=gn->get_name();
-					connecting_index=j;
-					connecting_out=false;
-					connecting_type=gn->get_connection_input_type(j);
-					connecting_color=gn->get_connection_input_color(j);
-					connecting_target=false;
-					connecting_to=pos;
-					return;
-				}
+                    connecting=true;
+                    connecting_from=gn->get_name();
+                    connecting_index=j;
+                    connecting_out=false;
+                    connecting_type=gn->get_connection_input_type(j);
+                    connecting_color=gn->get_connection_input_color(j);
+                    connecting_target=false;
+                    connecting_to=pos;
+                    return;
+                }
 
 
 
 
-			}
-		}
-	}
+            }
+        }
+    }
 
 
-	if (p_ev.type==InputEvent::MOUSE_MOTION && connecting) {
+    if (p_ev.type==InputEvent::MOUSE_MOTION && connecting) {
 
 
-		connecting_to=Vector2(p_ev.mouse_motion.x,p_ev.mouse_motion.y);
-		connecting_target=false;
-		top_layer->update();
+        connecting_to=Vector2(p_ev.mouse_motion.x,p_ev.mouse_motion.y);
+        connecting_target=false;
+        top_layer->update();
 
 
-		Ref<Texture> port =get_icon("port","GraphNode");
-		Vector2 mpos(p_ev.mouse_button.x,p_ev.mouse_button.y);
-		float grab_r=port->get_width()*0.5;
-		for(int i=get_child_count()-1;i>=0;i--) {
+        Ref<Texture> port =get_icon("port","GraphNode");
+        Vector2 mpos(p_ev.mouse_button.x,p_ev.mouse_button.y);
+        float grab_r=port->get_width()*0.5;
+        for(int i=get_child_count()-1;i>=0;i--) {
 
 
-			GraphNode *gn=get_child(i)->cast_to<GraphNode>();
-			if (!gn)
-				continue;
+            GraphNode *gn=get_child(i)->cast_to<GraphNode>();
+            if (!gn)
+                continue;
 
 
-			if (!connecting_out) {
-				for(int j=0;j<gn->get_connection_output_count();j++) {
+            if (!connecting_out) {
+                for(int j=0;j<gn->get_connection_output_count();j++) {
 
 
-					Vector2 pos = gn->get_connection_output_pos(j)+gn->get_pos();
-					int type =gn->get_connection_output_type(j);
-					if (type==connecting_type && pos.distance_to(mpos)<grab_r) {
+                    Vector2 pos = gn->get_connection_output_pos(j)+gn->get_pos();
+                    int type =gn->get_connection_output_type(j);
+                    if (type==connecting_type && pos.distance_to(mpos)<grab_r) {
 
 
-						connecting_target=true;
-						connecting_to=pos;
-						connecting_target_to=gn->get_name();
-						connecting_target_index=j;
-						return;
-					}
+                        connecting_target=true;
+                        connecting_to=pos;
+                        connecting_target_to=gn->get_name();
+                        connecting_target_index=j;
+                        return;
+                    }
 
 
 
 
-				}
-			} else {
+                }
+            } else {
 
 
-				for(int j=0;j<gn->get_connection_input_count();j++) {
+                for(int j=0;j<gn->get_connection_input_count();j++) {
 
 
-					Vector2 pos = gn->get_connection_input_pos(j)+gn->get_pos();
-					int type =gn->get_connection_input_type(j);
-					if (type==connecting_type && pos.distance_to(mpos)<grab_r) {
-						connecting_target=true;
-						connecting_to=pos;
-						connecting_target_to=gn->get_name();
-						connecting_target_index=j;
-						return;
-					}
-				}
-			}
-		}
-	}
+                    Vector2 pos = gn->get_connection_input_pos(j)+gn->get_pos();
+                    int type =gn->get_connection_input_type(j);
+                    if (type==connecting_type && pos.distance_to(mpos)<grab_r) {
+                        connecting_target=true;
+                        connecting_to=pos;
+                        connecting_target_to=gn->get_name();
+                        connecting_target_index=j;
+                        return;
+                    }
+                }
+            }
+        }
+    }
 
 
-	if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index==BUTTON_LEFT && !p_ev.mouse_button.pressed) {
+    if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.button_index==BUTTON_LEFT && !p_ev.mouse_button.pressed) {
 
 
-		if (connecting && connecting_target) {
+        if (connecting && connecting_target) {
 
 
-			String from = connecting_from;
-			int from_slot = connecting_index;
-			String to =connecting_target_to;
-			int to_slot = connecting_target_index;
+            String from = connecting_from;
+            int from_slot = connecting_index;
+            String to =connecting_target_to;
+            int to_slot = connecting_target_index;
 
 
-			if (!connecting_out) {
-				SWAP(from,to);
-				SWAP(from_slot,to_slot);
-			}
-			emit_signal("connection_request",from,from_slot,to,to_slot);
-
-		}
-		connecting=false;
-		top_layer->update();
+            if (!connecting_out) {
+                SWAP(from,to);
+                SWAP(from_slot,to_slot);
+            }
+            emit_signal("connection_request",from,from_slot,to,to_slot);
 
 
-	}
+        }
+        connecting=false;
+        top_layer->update();
+
+    }
 
 
 
 
 
 
@@ -392,203 +389,295 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) {
 
 
 void GraphEdit::_draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color) {
 void GraphEdit::_draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color) {
 
 
-	static const int steps = 20;
+    static const int steps = 20;
 
 
-	Rect2 r;
-	r.pos=p_from;
-	r.expand_to(p_to);
-	Vector2 sign=Vector2((p_from.x < p_to.x) ? 1 : -1,(p_from.y < p_to.y) ? 1 : -1);
-	bool flip = sign.x * sign.y < 0;
+    Rect2 r;
+    r.pos=p_from;
+    r.expand_to(p_to);
+    Vector2 sign=Vector2((p_from.x < p_to.x) ? 1 : -1,(p_from.y < p_to.y) ? 1 : -1);
+    bool flip = sign.x * sign.y < 0;
 
 
-	Vector2 prev;
-	for(int i=0;i<=steps;i++) {
+    Vector2 prev;
+    for(int i=0;i<=steps;i++) {
 
 
-		float d = i/float(steps);
-		float c=-Math::cos(d*Math_PI) * 0.5+0.5;
-		if (flip)
-			c=1.0-c;
-		Vector2 p = r.pos+Vector2(d*r.size.width,c*r.size.height);
+        float d = i/float(steps);
+        float c=-Math::cos(d*Math_PI) * 0.5+0.5;
+        if (flip)
+            c=1.0-c;
+        Vector2 p = r.pos+Vector2(d*r.size.width,c*r.size.height);
 
 
-		if (i>0) {
+        if (i>0) {
 
 
-			top_layer->draw_line(prev,p,p_color,2);
-		}
+            top_layer->draw_line(prev,p,p_color,2);
+        }
 
 
-		prev=p;
-	}
+        prev=p;
+    }
 }
 }
 
 
 void GraphEdit::_top_layer_draw() {
 void GraphEdit::_top_layer_draw() {
 
 
-	_update_scroll();
-
-	if (connecting) {
-
-		Node *fromn = get_node(connecting_from);
-		ERR_FAIL_COND(!fromn);
-		GraphNode *from = fromn->cast_to<GraphNode>();
-		ERR_FAIL_COND(!from);
-		Vector2 pos;
-		if (connecting_out)
-			pos=from->get_connection_output_pos(connecting_index);
-		else
-			pos=from->get_connection_input_pos(connecting_index);
-		pos+=from->get_pos();
-
-		Vector2 topos;
-		topos=connecting_to;
-
-		Color col=connecting_color;
-
-		if (connecting_target) {
-			col.r+=0.4;
-			col.g+=0.4;
-			col.b+=0.4;
-		}
-		_draw_cos_line(pos,topos,col);
-	}
-
-	List<List<Connection>::Element* > to_erase;
-	for(List<Connection>::Element *E=connections.front();E;E=E->next()) {
-
-		NodePath fromnp(E->get().from);
-
-		Node * from = get_node(fromnp);
-		if (!from) {
-			to_erase.push_back(E);
-			continue;
-		}
-
-		GraphNode *gfrom = from->cast_to<GraphNode>();
-
-		if (!gfrom) {
-			to_erase.push_back(E);
-			continue;
-		}
-
-		NodePath tonp(E->get().to);
-		Node * to = get_node(tonp);
-		if (!to) {
-			to_erase.push_back(E);
-			continue;
-		}
-
-		GraphNode *gto = to->cast_to<GraphNode>();
-
-		if (!gto) {
-			to_erase.push_back(E);
-			continue;
-		}
-
-		Vector2 frompos=gfrom->get_connection_output_pos(E->get().from_port)+gfrom->get_pos();
-		Color color = gfrom->get_connection_output_color(E->get().from_port);
-		Vector2 topos=gto->get_connection_input_pos(E->get().to_port)+gto->get_pos();
-		_draw_cos_line(frompos,topos,color);
-
-	}
-
-	while(to_erase.size()) {
-		connections.erase(to_erase.front()->get());
-		to_erase.pop_front();
-	}
-	//draw connections
+    _update_scroll();
+
+    if (connecting) {
+
+        Node *fromn = get_node(connecting_from);
+        ERR_FAIL_COND(!fromn);
+        GraphNode *from = fromn->cast_to<GraphNode>();
+        ERR_FAIL_COND(!from);
+        Vector2 pos;
+        if (connecting_out)
+            pos=from->get_connection_output_pos(connecting_index);
+        else
+            pos=from->get_connection_input_pos(connecting_index);
+        pos+=from->get_pos();
+
+        Vector2 topos;
+        topos=connecting_to;
+
+        Color col=connecting_color;
+
+        if (connecting_target) {
+            col.r+=0.4;
+            col.g+=0.4;
+            col.b+=0.4;
+        }
+        _draw_cos_line(pos,topos,col);
+    }
+
+    List<List<Connection>::Element* > to_erase;
+    for(List<Connection>::Element *E=connections.front();E;E=E->next()) {
+
+        NodePath fromnp(E->get().from);
+
+        Node * from = get_node(fromnp);
+        if (!from) {
+            to_erase.push_back(E);
+            continue;
+        }
+
+        GraphNode *gfrom = from->cast_to<GraphNode>();
+
+        if (!gfrom) {
+            to_erase.push_back(E);
+            continue;
+        }
+
+        NodePath tonp(E->get().to);
+        Node * to = get_node(tonp);
+        if (!to) {
+            to_erase.push_back(E);
+            continue;
+        }
+
+        GraphNode *gto = to->cast_to<GraphNode>();
+
+        if (!gto) {
+            to_erase.push_back(E);
+            continue;
+        }
+
+        Vector2 frompos=gfrom->get_connection_output_pos(E->get().from_port)+gfrom->get_pos();
+        Color color = gfrom->get_connection_output_color(E->get().from_port);
+        Vector2 topos=gto->get_connection_input_pos(E->get().to_port)+gto->get_pos();
+        _draw_cos_line(frompos,topos,color);
+
+    }
+
+    while(to_erase.size()) {
+        connections.erase(to_erase.front()->get());
+        to_erase.pop_front();
+    }
+    //draw connections
 }
 }
 
 
 void GraphEdit::_input_event(const InputEvent& p_ev) {
 void GraphEdit::_input_event(const InputEvent& p_ev) {
 
 
-	if (p_ev.type==InputEvent::MOUSE_MOTION && (p_ev.mouse_motion.button_mask&BUTTON_MASK_MIDDLE || (p_ev.mouse_motion.button_mask&BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE)))) {
-		h_scroll->set_val( h_scroll->get_val() - p_ev.mouse_motion.relative_x );
-		v_scroll->set_val( v_scroll->get_val() - p_ev.mouse_motion.relative_y );
-    } else if (p_ev.type== InputEvent::MOUSE_BUTTON) {
+    if (p_ev.type==InputEvent::MOUSE_MOTION && (p_ev.mouse_motion.button_mask&BUTTON_MASK_MIDDLE || (p_ev.mouse_motion.button_mask&BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE)))) {
+        h_scroll->set_val( h_scroll->get_val() - p_ev.mouse_motion.relative_x );
+        v_scroll->set_val( v_scroll->get_val() - p_ev.mouse_motion.relative_y );
+    }
+
+    if (p_ev.type==InputEvent::MOUSE_MOTION && dragging) {
+
+        just_selected=true;
+        drag_accum+=Vector2(p_ev.mouse_motion.relative_x,p_ev.mouse_motion.relative_y);
+        for(int i=get_child_count()-1;i>=0;i--) {
+            GraphNode *gn=get_child(i)->cast_to<GraphNode>();
+            if (gn && gn->is_selected())
+                gn->set_offset(gn->get_drag_from()+drag_accum);
+        }
+    }
+
+    if (p_ev.type== InputEvent::MOUSE_BUTTON) {
 
 
         const InputEventMouseButton &b=p_ev.mouse_button;
         const InputEventMouseButton &b=p_ev.mouse_button;
 
 
-        if (b.button_index==2 && b.pressed)
+        if (b.button_index==BUTTON_RIGHT && b.pressed)
         {
         {
             emit_signal("popup_request", Vector2(b.global_x, b.global_y));
             emit_signal("popup_request", Vector2(b.global_x, b.global_y));
         }
         }
+
+        if (b.button_index==BUTTON_LEFT && !b.pressed && dragging) {
+            if (!just_selected && drag_accum==Vector2() && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+                //deselect current node
+                for(int i=get_child_count()-1;i>=0;i--) {
+                    GraphNode *gn=get_child(i)->cast_to<GraphNode>();
+
+                    if (gn && gn->get_rect().has_point(get_local_mouse_pos()))
+                        gn->set_selected(false);
+                }
+            }
+
+            if (drag_accum!=Vector2()) {
+
+                emit_signal("_begin_node_move");
+
+                for(int i=get_child_count()-1;i>=0;i--) {
+                    GraphNode *gn=get_child(i)->cast_to<GraphNode>();
+                    if (gn && gn->is_selected())
+                        gn->set_drag(false);
+                }
+
+                emit_signal("_end_node_move");
+            }
+
+            dragging = false;
+
+            top_layer->update();
+        }
+
+        if (b.button_index==BUTTON_LEFT && b.pressed) {
+
+            GraphNode *gn;
+            for(int i=get_child_count()-1;i>=0;i--) {
+
+                gn=get_child(i)->cast_to<GraphNode>();
+
+                if (gn && gn->get_rect().has_point(get_local_mouse_pos()))
+                    break;
+            }
+
+            if (gn) {
+
+                if (_filter_input(Vector2(b.x,b.y)))
+                    return;
+
+                dragging = true;
+                drag_accum = Vector2();
+                just_selected = !gn->is_selected();
+                if(!gn->is_selected() && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+                    for (int i = 0; i < get_child_count(); i++) {
+                        GraphNode *o_gn = get_child(i)->cast_to<GraphNode>();
+                        if (o_gn)
+                            o_gn->set_selected(o_gn == gn);
+                    }
+                }
+
+                gn->set_selected(true);
+                for (int i = 0; i < get_child_count(); i++) {
+                    GraphNode *o_gn = get_child(i)->cast_to<GraphNode>();
+                    if (!o_gn)
+                        continue;
+                    if (o_gn->is_selected())
+                        o_gn->set_drag(true);
+                }
+
+            } else {
+                for(int i=get_child_count()-1;i>=0;i--) {
+
+                    GraphNode *gn=get_child(i)->cast_to<GraphNode>();
+                    if (!gn)
+                        continue;
+
+                    gn->set_selected(false);
+                }
+            }
+        }
     }
     }
 }
 }
 
 
 void GraphEdit::clear_connections() {
 void GraphEdit::clear_connections() {
 
 
-	connections.clear();
-	update();
+    connections.clear();
+    update();
 }
 }
 
 
 
 
 void GraphEdit::set_right_disconnects(bool p_enable) {
 void GraphEdit::set_right_disconnects(bool p_enable) {
 
 
-	right_disconnects=p_enable;
+    right_disconnects=p_enable;
 }
 }
 
 
 bool GraphEdit::is_right_disconnects_enabled() const{
 bool GraphEdit::is_right_disconnects_enabled() const{
 
 
-	return right_disconnects;
+    return right_disconnects;
 }
 }
 
 
 Array GraphEdit::_get_connection_list() const {
 Array GraphEdit::_get_connection_list() const {
 
 
-	List<Connection> conns;
-	get_connection_list(&conns);
-	Array arr;
-	for(List<Connection>::Element *E=conns.front();E;E=E->next()) {
-		Dictionary d;
-		d["from"]=E->get().from;
-		d["from_port"]=E->get().from_port;
-		d["to"]=E->get().to;
-		d["to_port"]=E->get().to_port;
-		arr.push_back(d);
-	}
-	return arr;
+    List<Connection> conns;
+    get_connection_list(&conns);
+    Array arr;
+    for(List<Connection>::Element *E=conns.front();E;E=E->next()) {
+        Dictionary d;
+        d["from"]=E->get().from;
+        d["from_port"]=E->get().from_port;
+        d["to"]=E->get().to;
+        d["to_port"]=E->get().to_port;
+        arr.push_back(d);
+    }
+    return arr;
 }
 }
 void GraphEdit::_bind_methods() {
 void GraphEdit::_bind_methods() {
 
 
-	ObjectTypeDB::bind_method(_MD("connect_node:Error","from","from_port","to","to_port"),&GraphEdit::connect_node);
-	ObjectTypeDB::bind_method(_MD("is_node_connected","from","from_port","to","to_port"),&GraphEdit::is_node_connected);
-	ObjectTypeDB::bind_method(_MD("disconnect_node","from","from_port","to","to_port"),&GraphEdit::disconnect_node);
-	ObjectTypeDB::bind_method(_MD("get_connection_list"),&GraphEdit::_get_connection_list);
+    ObjectTypeDB::bind_method(_MD("connect_node:Error","from","from_port","to","to_port"),&GraphEdit::connect_node);
+    ObjectTypeDB::bind_method(_MD("is_node_connected","from","from_port","to","to_port"),&GraphEdit::is_node_connected);
+    ObjectTypeDB::bind_method(_MD("disconnect_node","from","from_port","to","to_port"),&GraphEdit::disconnect_node);
+    ObjectTypeDB::bind_method(_MD("get_connection_list"),&GraphEdit::_get_connection_list);
 
 
-	ObjectTypeDB::bind_method(_MD("set_right_disconnects","enable"),&GraphEdit::set_right_disconnects);
-	ObjectTypeDB::bind_method(_MD("is_right_disconnects_enabled"),&GraphEdit::is_right_disconnects_enabled);
+    ObjectTypeDB::bind_method(_MD("set_right_disconnects","enable"),&GraphEdit::set_right_disconnects);
+    ObjectTypeDB::bind_method(_MD("is_right_disconnects_enabled"),&GraphEdit::is_right_disconnects_enabled);
 
 
-	ObjectTypeDB::bind_method(_MD("_graph_node_moved"),&GraphEdit::_graph_node_moved);
-	ObjectTypeDB::bind_method(_MD("_graph_node_raised"),&GraphEdit::_graph_node_raised);
+    ObjectTypeDB::bind_method(_MD("_graph_node_moved"),&GraphEdit::_graph_node_moved);
+    ObjectTypeDB::bind_method(_MD("_graph_node_raised"),&GraphEdit::_graph_node_raised);
 
 
-	ObjectTypeDB::bind_method(_MD("_top_layer_input"),&GraphEdit::_top_layer_input);
-	ObjectTypeDB::bind_method(_MD("_top_layer_draw"),&GraphEdit::_top_layer_draw);
-	ObjectTypeDB::bind_method(_MD("_scroll_moved"),&GraphEdit::_scroll_moved);
+    ObjectTypeDB::bind_method(_MD("_top_layer_input"),&GraphEdit::_top_layer_input);
+    ObjectTypeDB::bind_method(_MD("_top_layer_draw"),&GraphEdit::_top_layer_draw);
+    ObjectTypeDB::bind_method(_MD("_scroll_moved"),&GraphEdit::_scroll_moved);
 
 
-	ObjectTypeDB::bind_method(_MD("_input_event"),&GraphEdit::_input_event);
+    ObjectTypeDB::bind_method(_MD("_input_event"),&GraphEdit::_input_event);
 
 
-	ADD_SIGNAL(MethodInfo("connection_request",PropertyInfo(Variant::STRING,"from"),PropertyInfo(Variant::INT,"from_slot"),PropertyInfo(Variant::STRING,"to"),PropertyInfo(Variant::INT,"to_slot")));
+    ADD_SIGNAL(MethodInfo("connection_request",PropertyInfo(Variant::STRING,"from"),PropertyInfo(Variant::INT,"from_slot"),PropertyInfo(Variant::STRING,"to"),PropertyInfo(Variant::INT,"to_slot")));
     ADD_SIGNAL(MethodInfo("disconnection_request",PropertyInfo(Variant::STRING,"from"),PropertyInfo(Variant::INT,"from_slot"),PropertyInfo(Variant::STRING,"to"),PropertyInfo(Variant::INT,"to_slot")));
     ADD_SIGNAL(MethodInfo("disconnection_request",PropertyInfo(Variant::STRING,"from"),PropertyInfo(Variant::INT,"from_slot"),PropertyInfo(Variant::STRING,"to"),PropertyInfo(Variant::INT,"to_slot")));
     ADD_SIGNAL(MethodInfo("popup_request", PropertyInfo(Variant::VECTOR2,"p_position")));
     ADD_SIGNAL(MethodInfo("popup_request", PropertyInfo(Variant::VECTOR2,"p_position")));
+    ADD_SIGNAL(MethodInfo("_begin_node_move"));
+    ADD_SIGNAL(MethodInfo("_end_node_move"));
 }
 }
 
 
 
 
 
 
 GraphEdit::GraphEdit() {
 GraphEdit::GraphEdit() {
-	top_layer=NULL;
-	top_layer=memnew(GraphEditFilter(this));
-	add_child(top_layer);
-	top_layer->set_stop_mouse(false);
-	top_layer->set_area_as_parent_rect();
-	top_layer->connect("draw",this,"_top_layer_draw");
+    top_layer=NULL;
+    top_layer=memnew(GraphEditFilter(this));
+    add_child(top_layer);
+    top_layer->set_stop_mouse(false);
+    top_layer->set_area_as_parent_rect();
+    top_layer->connect("draw",this,"_top_layer_draw");
 	top_layer->set_stop_mouse(false);
 	top_layer->set_stop_mouse(false);
-	top_layer->connect("input_event",this,"_top_layer_input");
+    top_layer->connect("input_event",this,"_top_layer_input");
 
 
-	h_scroll = memnew(HScrollBar);
-	h_scroll->set_name("_h_scroll");
-	top_layer->add_child(h_scroll);
+    h_scroll = memnew(HScrollBar);
+    h_scroll->set_name("_h_scroll");
+    top_layer->add_child(h_scroll);
 
 
-	v_scroll = memnew(VScrollBar);
-	v_scroll->set_name("_v_scroll");
-	top_layer->add_child(v_scroll);
-	updating=false;
-	connecting=false;
-	right_disconnects=false;
+    v_scroll = memnew(VScrollBar);
+    v_scroll->set_name("_v_scroll");
+    top_layer->add_child(v_scroll);
+    updating=false;
+    connecting=false;
+    right_disconnects=false;
 
 
-	h_scroll->connect("value_changed", this,"_scroll_moved");
-	v_scroll->connect("value_changed", this,"_scroll_moved");
+    h_scroll->connect("value_changed", this,"_scroll_moved");
+    v_scroll->connect("value_changed", this,"_scroll_moved");
 }
 }

+ 54 - 52
scene/gui/graph_edit.h

@@ -8,93 +8,95 @@ class GraphEdit;
 
 
 class GraphEditFilter : public Control {
 class GraphEditFilter : public Control {
 
 
-	OBJ_TYPE(GraphEditFilter,Control);
+    OBJ_TYPE(GraphEditFilter,Control);
 
 
 friend class GraphEdit;
 friend class GraphEdit;
-	GraphEdit *ge;
-	virtual bool has_point(const Point2& p_point) const;
+    GraphEdit *ge;
+    virtual bool has_point(const Point2& p_point) const;
 
 
 public:
 public:
 
 
 
 
-	GraphEditFilter(GraphEdit *p_edit);
+    GraphEditFilter(GraphEdit *p_edit);
 };
 };
 
 
 class GraphEdit : public Control {
 class GraphEdit : public Control {
 
 
-	OBJ_TYPE(GraphEdit,Control);
+    OBJ_TYPE(GraphEdit,Control);
 public:
 public:
 
 
-	struct Connection {
-		StringName from;
-		StringName to;
-		int from_port;
-		int to_port;
+    struct Connection {
+        StringName from;
+        StringName to;
+        int from_port;
+        int to_port;
 
 
-	};
+    };
 private:
 private:
 
 
-	HScrollBar* h_scroll;
-	VScrollBar* v_scroll;
+    HScrollBar* h_scroll;
+    VScrollBar* v_scroll;
 
 
 
 
-	bool connecting;
-	String connecting_from;
-	bool connecting_out;
-	int connecting_index;
-	int connecting_type;
-	Color connecting_color;
-	bool connecting_target;
-	Vector2 connecting_to;
-	String connecting_target_to;
-	int connecting_target_index;
+    bool connecting;
+    String connecting_from;
+    bool connecting_out;
+    int connecting_index;
+    int connecting_type;
+    Color connecting_color;
+    bool connecting_target;
+    Vector2 connecting_to;
+    String connecting_target_to;
+    int connecting_target_index;
 
 
+    bool dragging;
+    bool just_selected;
+    Vector2 drag_accum;
 
 
+    bool right_disconnects;
+    bool updating;
+    List<Connection> connections;
 
 
-	bool right_disconnects;
-	bool updating;
-	List<Connection> connections;
+    void _draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color);
 
 
-	void _draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color);
+    void _graph_node_raised(Node* p_gn);
+    void _graph_node_moved(Node *p_gn);
 
 
-	void _graph_node_raised(Node* p_gn);
-	void _graph_node_moved(Node *p_gn);
+    void _update_scroll();
+    void _scroll_moved(double);
+    void _input_event(const InputEvent& p_ev);
 
 
-	void _update_scroll();
-	void _scroll_moved(double);
-	void _input_event(const InputEvent& p_ev);
+    GraphEditFilter *top_layer;
+    void _top_layer_input(const InputEvent& p_ev);
+    void _top_layer_draw();
+    void _update_scroll_offset();
 
 
-	GraphEditFilter *top_layer;
-	void _top_layer_input(const InputEvent& p_ev);
-	void _top_layer_draw();
-	void _update_scroll_offset();
-
-	Array _get_connection_list() const;
+    Array _get_connection_list() const;
 
 
 friend class GraphEditFilter;
 friend class GraphEditFilter;
-	bool _filter_input(const Point2& p_point);
+    bool _filter_input(const Point2& p_point);
 protected:
 protected:
 
 
-	static void _bind_methods();
-	virtual void add_child_notify(Node *p_child);
-	virtual void remove_child_notify(Node *p_child);
-	void _notification(int p_what);
+    static void _bind_methods();
+    virtual void add_child_notify(Node *p_child);
+    virtual void remove_child_notify(Node *p_child);
+    void _notification(int p_what);
 
 
 public:
 public:
 
 
-	Error connect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port);
-	bool is_node_connected(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port);
-	void disconnect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port);
-	void clear_connections();
+    Error connect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port);
+    bool is_node_connected(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port);
+    void disconnect_node(const StringName& p_from, int p_from_port,const StringName& p_to,int p_to_port);
+    void clear_connections();
 
 
-	GraphEditFilter *get_top_layer() const { return top_layer; }
-	void get_connection_list(List<Connection> *r_connections) const;
+    GraphEditFilter *get_top_layer() const { return top_layer; }
+    void get_connection_list(List<Connection> *r_connections) const;
 
 
-	void set_right_disconnects(bool p_enable);
-	bool is_right_disconnects_enabled() const;
+    void set_right_disconnects(bool p_enable);
+    bool is_right_disconnects_enabled() const;
 
 
 
 
-	GraphEdit();
+    GraphEdit();
 };
 };
 
 
 #endif // GRAPHEdit_H
 #endif // GRAPHEdit_H

+ 345 - 341
scene/gui/graph_node.cpp

@@ -4,91 +4,91 @@
 
 
 bool GraphNode::_set(const StringName& p_name, const Variant& p_value) {
 bool GraphNode::_set(const StringName& p_name, const Variant& p_value) {
 
 
-	if (!p_name.operator String().begins_with("slot/"))
-		return false;
+    if (!p_name.operator String().begins_with("slot/"))
+        return false;
 
 
-	int idx=p_name.operator String().get_slice("/",1).to_int();
-	String what = p_name.operator String().get_slice("/",2);
+    int idx=p_name.operator String().get_slice("/",1).to_int();
+    String what = p_name.operator String().get_slice("/",2);
 
 
 
 
-	Slot si;
-	if (slot_info.has(idx))
-		si=slot_info[idx];
+    Slot si;
+    if (slot_info.has(idx))
+        si=slot_info[idx];
 
 
 
 
-	if (what=="left_enabled")
-		si.enable_left=p_value;
-	else if (what=="left_type")
-		si.type_left=p_value;
-	else if (what=="left_color")
-		si.color_left=p_value;
-	else if (what=="right_enabled")
-		si.enable_right=p_value;
-	else if (what=="right_type")
-		si.type_right=p_value;
-	else if (what=="right_color")
-		si.color_right=p_value;
-	else
-		return false;
+    if (what=="left_enabled")
+        si.enable_left=p_value;
+    else if (what=="left_type")
+        si.type_left=p_value;
+    else if (what=="left_color")
+        si.color_left=p_value;
+    else if (what=="right_enabled")
+        si.enable_right=p_value;
+    else if (what=="right_type")
+        si.type_right=p_value;
+    else if (what=="right_color")
+        si.color_right=p_value;
+    else
+        return false;
 
 
-	set_slot(idx,si.enable_left,si.type_left,si.color_left,si.enable_right,si.type_right,si.color_right);
-	update();
-	return true;
+    set_slot(idx,si.enable_left,si.type_left,si.color_left,si.enable_right,si.type_right,si.color_right);
+    update();
+    return true;
 }
 }
 
 
 bool GraphNode::_get(const StringName& p_name,Variant &r_ret) const{
 bool GraphNode::_get(const StringName& p_name,Variant &r_ret) const{
 
 
 
 
 
 
-	if (!p_name.operator String().begins_with("slot/")) {		
-		return false;
-	}
+    if (!p_name.operator String().begins_with("slot/")) {
+        return false;
+    }
 
 
-	int idx=p_name.operator String().get_slice("/",1).to_int();
-	String what = p_name.operator String().get_slice("/",2);
+    int idx=p_name.operator String().get_slice("/",1).to_int();
+    String what = p_name.operator String().get_slice("/",2);
 
 
 
 
 
 
-	Slot si;
-	if (slot_info.has(idx))
-		si=slot_info[idx];
+    Slot si;
+    if (slot_info.has(idx))
+        si=slot_info[idx];
 
 
-	if (what=="left_enabled")
-		r_ret=si.enable_left;
-	else if (what=="left_type")
-		r_ret=si.type_left;
-	else if (what=="left_color")
-		r_ret=si.color_left;
-	else if (what=="right_enabled")
-		r_ret=si.enable_right;
-	else if (what=="right_type")
-		r_ret=si.type_right;
-	else if (what=="right_color")
-		r_ret=si.color_right;
-	else
-		return false;
+    if (what=="left_enabled")
+        r_ret=si.enable_left;
+    else if (what=="left_type")
+        r_ret=si.type_left;
+    else if (what=="left_color")
+        r_ret=si.color_left;
+    else if (what=="right_enabled")
+        r_ret=si.enable_right;
+    else if (what=="right_type")
+        r_ret=si.type_right;
+    else if (what=="right_color")
+        r_ret=si.color_right;
+    else
+        return false;
 
 
-	return true;
+    return true;
 }
 }
 void GraphNode::_get_property_list( List<PropertyInfo> *p_list) const{
 void GraphNode::_get_property_list( List<PropertyInfo> *p_list) const{
 
 
-	int idx=0;
-	for(int i=0;i<get_child_count();i++) {
-		Control *c=get_child(i)->cast_to<Control>();
-		if (!c || c->is_set_as_toplevel() )
-			continue;
+    int idx=0;
+    for(int i=0;i<get_child_count();i++) {
+        Control *c=get_child(i)->cast_to<Control>();
+        if (!c || c->is_set_as_toplevel() )
+            continue;
 
 
-		String base="slot/"+itos(idx)+"/";
+        String base="slot/"+itos(idx)+"/";
 
 
-		p_list->push_back(PropertyInfo(Variant::BOOL,base+"left_enabled"));
-		p_list->push_back(PropertyInfo(Variant::INT,base+"left_type"));
-		p_list->push_back(PropertyInfo(Variant::COLOR,base+"left_color"));
-		p_list->push_back(PropertyInfo(Variant::BOOL,base+"right_enabled"));
-		p_list->push_back(PropertyInfo(Variant::INT,base+"right_type"));
-		p_list->push_back(PropertyInfo(Variant::COLOR,base+"right_color"));
+        p_list->push_back(PropertyInfo(Variant::BOOL,base+"left_enabled"));
+        p_list->push_back(PropertyInfo(Variant::INT,base+"left_type"));
+        p_list->push_back(PropertyInfo(Variant::COLOR,base+"left_color"));
+        p_list->push_back(PropertyInfo(Variant::BOOL,base+"right_enabled"));
+        p_list->push_back(PropertyInfo(Variant::INT,base+"right_type"));
+        p_list->push_back(PropertyInfo(Variant::COLOR,base+"right_color"));
 
 
-		idx++;
-	}
+        idx++;
+    }
 }
 }
 
 
 
 
@@ -96,61 +96,61 @@ void GraphNode::_resort() {
 
 
 
 
 
 
-	int sep=get_constant("separation");
-	Ref<StyleBox> sb=get_stylebox("frame");
-	bool first=true;
+    int sep=get_constant("separation");
+    Ref<StyleBox> sb=get_stylebox("frame");
+    bool first=true;
 
 
-	Size2 minsize;
+    Size2 minsize;
 
 
-	for(int i=0;i<get_child_count();i++) {
-		Control *c=get_child(i)->cast_to<Control>();
-		if (!c)
-			continue;
-		if (c->is_set_as_toplevel())
-			continue;
+    for(int i=0;i<get_child_count();i++) {
+        Control *c=get_child(i)->cast_to<Control>();
+        if (!c)
+            continue;
+        if (c->is_set_as_toplevel())
+            continue;
 
 
-		Size2i size=c->get_combined_minimum_size();
+        Size2i size=c->get_combined_minimum_size();
 
 
-		minsize.y+=size.y;
-		minsize.x=MAX(minsize.x,size.x);
+        minsize.y+=size.y;
+        minsize.x=MAX(minsize.x,size.x);
 
 
-		if (first)
-			first=false;
-		else
-			minsize.y+=sep;
+        if (first)
+            first=false;
+        else
+            minsize.y+=sep;
 
 
-	}
+    }
 
 
 
 
-	int vofs=0;
-	int w = get_size().x - sb->get_minimum_size().x;
+    int vofs=0;
+    int w = get_size().x - sb->get_minimum_size().x;
 
 
 
 
-	cache_y.clear();
-	for(int i=0;i<get_child_count();i++) {
-		Control *c=get_child(i)->cast_to<Control>();
-		if (!c)
-			continue;
-		if (c->is_set_as_toplevel())
-			continue;
+    cache_y.clear();
+    for(int i=0;i<get_child_count();i++) {
+        Control *c=get_child(i)->cast_to<Control>();
+        if (!c)
+            continue;
+        if (c->is_set_as_toplevel())
+            continue;
 
 
-		Size2i size=c->get_combined_minimum_size();
+        Size2i size=c->get_combined_minimum_size();
 
 
-		Rect2 r(sb->get_margin(MARGIN_LEFT),sb->get_margin(MARGIN_TOP)+vofs,w,size.y);
+        Rect2 r(sb->get_margin(MARGIN_LEFT),sb->get_margin(MARGIN_TOP)+vofs,w,size.y);
 
 
-		fit_child_in_rect(c,r);
-		cache_y.push_back(vofs+size.y*0.5);
+        fit_child_in_rect(c,r);
+        cache_y.push_back(vofs+size.y*0.5);
 
 
-		if (vofs>0)
-			vofs+=sep;
-		vofs+=size.y;
+        if (vofs>0)
+            vofs+=sep;
+        vofs+=size.y;
 
 
 
 
-	}
+    }
 
 
-	_change_notify();
-	update();
-	connpos_dirty=true;
+    _change_notify();
+    update();
+    connpos_dirty=true;
 
 
 
 
 }
 }
@@ -158,124 +158,124 @@ void GraphNode::_resort() {
 
 
 void GraphNode::_notification(int p_what) {
 void GraphNode::_notification(int p_what) {
 
 
-	if (p_what==NOTIFICATION_DRAW) {
+    if (p_what==NOTIFICATION_DRAW) {
 
 
-		Ref<StyleBox> sb=get_stylebox("frame");
-		Ref<Texture> port =get_icon("port");
-		Ref<Texture> close =get_icon("close");
-		int close_offset = get_constant("close_offset");
-		Ref<Font> title_font = get_font("title_font");
-		int title_offset = get_constant("title_offset");
-		Color title_color = get_color("title_color");
-		Point2i icofs = -port->get_size()*0.5;
-		int edgeofs=get_constant("port_offset");
-		icofs.y+=sb->get_margin(MARGIN_TOP);
-		draw_style_box(sb,Rect2(Point2(),get_size()));
+        Ref<StyleBox> sb=get_stylebox(selected ? "selectedframe" : "frame");
+        Ref<Texture> port =get_icon("port");
+        Ref<Texture> close =get_icon("close");
+        int close_offset = get_constant("close_offset");
+        Ref<Font> title_font = get_font("title_font");
+        int title_offset = get_constant("title_offset");
+        Color title_color = get_color("title_color");
+        Point2i icofs = -port->get_size()*0.5;
+        int edgeofs=get_constant("port_offset");
+        icofs.y+=sb->get_margin(MARGIN_TOP);
+        draw_style_box(sb,Rect2(Point2(),get_size()));
 
 
-		int w = get_size().width-sb->get_minimum_size().x;
+        int w = get_size().width-sb->get_minimum_size().x;
 
 
-		if (show_close)
-			w-=close->get_width();
+        if (show_close)
+            w-=close->get_width();
 
 
-		draw_string(title_font,Point2(sb->get_margin(MARGIN_LEFT),-title_font->get_height()+title_font->get_ascent()+title_offset),title,title_color,w);
-		if (show_close) {
-			Vector2 cpos = Point2(w+sb->get_margin(MARGIN_LEFT),-close->get_height()+close_offset);
-			draw_texture(close,cpos);
-			close_rect.pos=cpos;
-			close_rect.size=close->get_size();
-		} else {
-			close_rect=Rect2();
-		}
+        draw_string(title_font,Point2(sb->get_margin(MARGIN_LEFT),-title_font->get_height()+title_font->get_ascent()+title_offset),title,title_color,w);
+        if (show_close) {
+            Vector2 cpos = Point2(w+sb->get_margin(MARGIN_LEFT),-close->get_height()+close_offset);
+            draw_texture(close,cpos);
+            close_rect.pos=cpos;
+            close_rect.size=close->get_size();
+        } else {
+            close_rect=Rect2();
+        }
 
 
-		for (Map<int,Slot>::Element *E=slot_info.front();E;E=E->next()) {
+        for (Map<int,Slot>::Element *E=slot_info.front();E;E=E->next()) {
 
 
-			if (E->key() < 0 || E->key()>=cache_y.size())
-				continue;
-			if (!slot_info.has(E->key()))
-				continue;
-			const Slot &s=slot_info[E->key()];
-			//left
-			if (s.enable_left)
-				port->draw(get_canvas_item(),icofs+Point2(edgeofs,cache_y[E->key()]),s.color_left);
-			if (s.enable_right)
-				port->draw(get_canvas_item(),icofs+Point2(get_size().x-edgeofs,cache_y[E->key()]),s.color_right);
+            if (E->key() < 0 || E->key()>=cache_y.size())
+                continue;
+            if (!slot_info.has(E->key()))
+                continue;
+            const Slot &s=slot_info[E->key()];
+            //left
+            if (s.enable_left)
+                port->draw(get_canvas_item(),icofs+Point2(edgeofs,cache_y[E->key()]),s.color_left);
+            if (s.enable_right)
+                port->draw(get_canvas_item(),icofs+Point2(get_size().x-edgeofs,cache_y[E->key()]),s.color_right);
 
 
-		}
-	}
+        }
+    }
 
 
-	if (p_what==NOTIFICATION_SORT_CHILDREN) {
+    if (p_what==NOTIFICATION_SORT_CHILDREN) {
 
 
-		_resort();
-	}
+        _resort();
+    }
 
 
 }
 }
 
 
 
 
 void GraphNode::set_slot(int p_idx,bool p_enable_left,int p_type_left,const Color& p_color_left, bool p_enable_right,int p_type_right,const Color& p_color_right) {
 void GraphNode::set_slot(int p_idx,bool p_enable_left,int p_type_left,const Color& p_color_left, bool p_enable_right,int p_type_right,const Color& p_color_right) {
 
 
-	ERR_FAIL_COND(p_idx<0);
+    ERR_FAIL_COND(p_idx<0);
 
 
-	if (!p_enable_left && p_type_left==0 && p_color_left==Color(1,1,1,1) && !p_enable_right && p_type_right==0 && p_color_right==Color(1,1,1,1)) {
-		slot_info.erase(p_idx);
-		return;
-	}
+    if (!p_enable_left && p_type_left==0 && p_color_left==Color(1,1,1,1) && !p_enable_right && p_type_right==0 && p_color_right==Color(1,1,1,1)) {
+        slot_info.erase(p_idx);
+        return;
+    }
 
 
-	Slot s;
-	s.enable_left=p_enable_left;
-	s.type_left=p_type_left;
-	s.color_left=p_color_left;
-	s.enable_right=p_enable_right;
-	s.type_right=p_type_right;
-	s.color_right=p_color_right;
-	slot_info[p_idx]=s;
-	update();
-	connpos_dirty=true;
+    Slot s;
+    s.enable_left=p_enable_left;
+    s.type_left=p_type_left;
+    s.color_left=p_color_left;
+    s.enable_right=p_enable_right;
+    s.type_right=p_type_right;
+    s.color_right=p_color_right;
+    slot_info[p_idx]=s;
+    update();
+    connpos_dirty=true;
 
 
 }
 }
 
 
 void GraphNode::clear_slot(int p_idx){
 void GraphNode::clear_slot(int p_idx){
 
 
-	slot_info.erase(p_idx);
-	update();
-	connpos_dirty=true;
+    slot_info.erase(p_idx);
+    update();
+    connpos_dirty=true;
 
 
 }
 }
 void GraphNode::clear_all_slots(){
 void GraphNode::clear_all_slots(){
 
 
-	slot_info.clear();
-	update();
-	connpos_dirty=true;
+    slot_info.clear();
+    update();
+    connpos_dirty=true;
 
 
 }
 }
 bool GraphNode::is_slot_enabled_left(int p_idx) const{
 bool GraphNode::is_slot_enabled_left(int p_idx) const{
 
 
-	if (!slot_info.has(p_idx))
-		return false;
-	return slot_info[p_idx].enable_left;
+    if (!slot_info.has(p_idx))
+        return false;
+    return slot_info[p_idx].enable_left;
 
 
 }
 }
 
 
 int GraphNode::get_slot_type_left(int p_idx) const{
 int GraphNode::get_slot_type_left(int p_idx) const{
 
 
-	if (!slot_info.has(p_idx))
-		return 0;
-	return slot_info[p_idx].type_left;
+    if (!slot_info.has(p_idx))
+        return 0;
+    return slot_info[p_idx].type_left;
 
 
 }
 }
 
 
 Color GraphNode::get_slot_color_left(int p_idx) const{
 Color GraphNode::get_slot_color_left(int p_idx) const{
 
 
-	if (!slot_info.has(p_idx))
-		return Color(1,1,1,1);
-	return slot_info[p_idx].color_left;
+    if (!slot_info.has(p_idx))
+        return Color(1,1,1,1);
+    return slot_info[p_idx].color_left;
 
 
 }
 }
 
 
 bool GraphNode::is_slot_enabled_right(int p_idx) const{
 bool GraphNode::is_slot_enabled_right(int p_idx) const{
 
 
-	if (!slot_info.has(p_idx))
-		return false;
-	return slot_info[p_idx].enable_right;
+    if (!slot_info.has(p_idx))
+        return false;
+    return slot_info[p_idx].enable_right;
 
 
 }
 }
 
 
@@ -283,301 +283,305 @@ bool GraphNode::is_slot_enabled_right(int p_idx) const{
 
 
 int GraphNode::get_slot_type_right(int p_idx) const{
 int GraphNode::get_slot_type_right(int p_idx) const{
 
 
-	if (!slot_info.has(p_idx))
-		return 0;
-	return slot_info[p_idx].type_right;
+    if (!slot_info.has(p_idx))
+        return 0;
+    return slot_info[p_idx].type_right;
 
 
 }
 }
 
 
 Color GraphNode::get_slot_color_right(int p_idx) const{
 Color GraphNode::get_slot_color_right(int p_idx) const{
 
 
-	if (!slot_info.has(p_idx))
-		return Color(1,1,1,1);
-	return slot_info[p_idx].color_right;
+    if (!slot_info.has(p_idx))
+        return Color(1,1,1,1);
+    return slot_info[p_idx].color_right;
 
 
 }
 }
 
 
 Size2 GraphNode::get_minimum_size() const {
 Size2 GraphNode::get_minimum_size() const {
 
 
-	Ref<Font> title_font = get_font("title_font");
+    Ref<Font> title_font = get_font("title_font");
 
 
-	int sep=get_constant("separation");
-	Ref<StyleBox> sb=get_stylebox("frame");
-	bool first=true;
+    int sep=get_constant("separation");
+    Ref<StyleBox> sb=get_stylebox("frame");
+    bool first=true;
 
 
-	Size2 minsize;
-	minsize.x=title_font->get_string_size(title).x;
-	if (show_close) {
-		Ref<Texture> close =get_icon("close");
-		minsize.x+=sep+close->get_width();
-	}
+    Size2 minsize;
+    minsize.x=title_font->get_string_size(title).x;
+    if (show_close) {
+        Ref<Texture> close =get_icon("close");
+        minsize.x+=sep+close->get_width();
+    }
 
 
 
 
-	for(int i=0;i<get_child_count();i++) {
+    for(int i=0;i<get_child_count();i++) {
 
 
-		Control *c=get_child(i)->cast_to<Control>();
-		if (!c)
-			continue;
-		if (c->is_set_as_toplevel())
-			continue;
+        Control *c=get_child(i)->cast_to<Control>();
+        if (!c)
+            continue;
+        if (c->is_set_as_toplevel())
+            continue;
 
 
-		Size2i size=c->get_combined_minimum_size();
+        Size2i size=c->get_combined_minimum_size();
 
 
-		minsize.y+=size.y;
-		minsize.x=MAX(minsize.x,size.x);
+        minsize.y+=size.y;
+        minsize.x=MAX(minsize.x,size.x);
 
 
-		if (first)
-			first=false;
-		else
-			minsize.y+=sep;
-	}
+        if (first)
+            first=false;
+        else
+            minsize.y+=sep;
+    }
 
 
-	return minsize+sb->get_minimum_size();
+    return minsize+sb->get_minimum_size();
 }
 }
 
 
 void GraphNode::set_title(const String& p_title) {
 void GraphNode::set_title(const String& p_title) {
 
 
-	title=p_title;
-	minimum_size_changed();
-	update();
+    title=p_title;
+    minimum_size_changed();
+    update();
 
 
 }
 }
 
 
 String GraphNode::get_title() const{
 String GraphNode::get_title() const{
 
 
-	return title;
+    return title;
 }
 }
 
 
 void GraphNode::set_offset(const Vector2& p_offset) {
 void GraphNode::set_offset(const Vector2& p_offset) {
 
 
-	offset=p_offset;
-	emit_signal("offset_changed");
-	update();
+    offset=p_offset;
+    emit_signal("offset_changed");
+    update();
 }
 }
 
 
 Vector2 GraphNode::get_offset() const {
 Vector2 GraphNode::get_offset() const {
 
 
-	return offset;
+    return offset;
 }
 }
 
 
+void GraphNode::set_selected(bool p_selected)
+{
+    selected = p_selected;
+    update();
+}
+
+bool GraphNode::is_selected()
+{
+    return selected;
+}
+
+void GraphNode::set_drag(bool p_drag)
+{
+    if (p_drag)
+        drag_from=get_offset();
+    else
+        emit_signal("dragged",drag_from,get_offset()); //useful for undo/redo
+}
+
+Vector2 GraphNode::get_drag_from()
+{
+    return drag_from;
+}
 
 
 
 
 void GraphNode::set_show_close_button(bool p_enable){
 void GraphNode::set_show_close_button(bool p_enable){
 
 
-	show_close=p_enable;
-	update();
+    show_close=p_enable;
+    update();
 }
 }
 bool GraphNode::is_close_button_visible() const{
 bool GraphNode::is_close_button_visible() const{
 
 
-	return show_close;
+    return show_close;
 }
 }
 
 
 void GraphNode::_connpos_update() {
 void GraphNode::_connpos_update() {
 
 
 
 
-	int edgeofs=get_constant("port_offset");
-	int sep=get_constant("separation");
+    int edgeofs=get_constant("port_offset");
+    int sep=get_constant("separation");
 
 
-	Ref<StyleBox> sb=get_stylebox("frame");
-	Ref<Texture> port =get_icon("port");
-	conn_input_cache.clear();
-	conn_output_cache.clear();
-	int vofs=0;
+    Ref<StyleBox> sb=get_stylebox("frame");
+    conn_input_cache.clear();
+    conn_output_cache.clear();
+    int vofs=0;
 
 
-	int idx=0;
+    int idx=0;
 
 
-	for(int i=0;i<get_child_count();i++) {
-		Control *c=get_child(i)->cast_to<Control>();
-		if (!c)
-			continue;
-		if (c->is_set_as_toplevel())
-			continue;
+    for(int i=0;i<get_child_count();i++) {
+        Control *c=get_child(i)->cast_to<Control>();
+        if (!c)
+            continue;
+        if (c->is_set_as_toplevel())
+            continue;
 
 
-		Size2i size=c->get_combined_minimum_size();
+        Size2i size=c->get_combined_minimum_size();
 
 
-		int y = sb->get_margin(MARGIN_TOP)+vofs;
-		int h = size.y;
+        int y = sb->get_margin(MARGIN_TOP)+vofs;
+        int h = size.y;
 
 
 
 
-		if (slot_info.has(idx)) {
+        if (slot_info.has(idx)) {
 
 
-			if (slot_info[idx].enable_left) {
-				ConnCache cc;
-				cc.pos=Point2i(edgeofs,y+h/2);
-				cc.type=slot_info[idx].type_left;
-				cc.color=slot_info[idx].color_left;
-				conn_input_cache.push_back(cc);
-			}
-			if (slot_info[idx].enable_right) {
-				ConnCache cc;
-				cc.pos=Point2i(get_size().width-edgeofs,y+h/2);
-				cc.type=slot_info[idx].type_right;
-				cc.color=slot_info[idx].color_right;
-				conn_output_cache.push_back(cc);
-			}
-		}
+            if (slot_info[idx].enable_left) {
+                ConnCache cc;
+                cc.pos=Point2i(edgeofs,y+h/2);
+                cc.type=slot_info[idx].type_left;
+                cc.color=slot_info[idx].color_left;
+                conn_input_cache.push_back(cc);
+            }
+            if (slot_info[idx].enable_right) {
+                ConnCache cc;
+                cc.pos=Point2i(get_size().width-edgeofs,y+h/2);
+                cc.type=slot_info[idx].type_right;
+                cc.color=slot_info[idx].color_right;
+                conn_output_cache.push_back(cc);
+            }
+        }
 
 
-		if (vofs>0)
-			vofs+=sep;
-		vofs+=size.y;
-		idx++;
+        if (vofs>0)
+            vofs+=sep;
+        vofs+=size.y;
+        idx++;
 
 
-	}
+    }
 
 
 
 
-	connpos_dirty=false;
+    connpos_dirty=false;
 }
 }
 
 
 int GraphNode::get_connection_input_count()  {
 int GraphNode::get_connection_input_count()  {
 
 
-	if (connpos_dirty)
-		_connpos_update();
+    if (connpos_dirty)
+        _connpos_update();
 
 
-	return conn_input_cache.size();
+    return conn_input_cache.size();
 
 
 }
 }
 int GraphNode::get_connection_output_count() {
 int GraphNode::get_connection_output_count() {
 
 
-	if (connpos_dirty)
-		_connpos_update();
+    if (connpos_dirty)
+        _connpos_update();
 
 
-	return conn_output_cache.size();
+    return conn_output_cache.size();
 
 
 }
 }
 
 
 
 
 Vector2 GraphNode::get_connection_input_pos(int p_idx) {
 Vector2 GraphNode::get_connection_input_pos(int p_idx) {
 
 
-	if (connpos_dirty)
-		_connpos_update();
+    if (connpos_dirty)
+        _connpos_update();
 
 
-	ERR_FAIL_INDEX_V(p_idx,conn_input_cache.size(),Vector2());
-	return conn_input_cache[p_idx].pos;
+    ERR_FAIL_INDEX_V(p_idx,conn_input_cache.size(),Vector2());
+    return conn_input_cache[p_idx].pos;
 }
 }
 
 
 int GraphNode::get_connection_input_type(int p_idx) {
 int GraphNode::get_connection_input_type(int p_idx) {
 
 
-	if (connpos_dirty)
-		_connpos_update();
+    if (connpos_dirty)
+        _connpos_update();
 
 
-	ERR_FAIL_INDEX_V(p_idx,conn_input_cache.size(),0);
-	return conn_input_cache[p_idx].type;
+    ERR_FAIL_INDEX_V(p_idx,conn_input_cache.size(),0);
+    return conn_input_cache[p_idx].type;
 }
 }
 
 
 Color GraphNode::get_connection_input_color(int p_idx) {
 Color GraphNode::get_connection_input_color(int p_idx) {
 
 
-	if (connpos_dirty)
-		_connpos_update();
+    if (connpos_dirty)
+        _connpos_update();
 
 
-	ERR_FAIL_INDEX_V(p_idx,conn_input_cache.size(),Color());
-	return conn_input_cache[p_idx].color;
+    ERR_FAIL_INDEX_V(p_idx,conn_input_cache.size(),Color());
+    return conn_input_cache[p_idx].color;
 }
 }
 
 
 Vector2 GraphNode::get_connection_output_pos(int p_idx){
 Vector2 GraphNode::get_connection_output_pos(int p_idx){
 
 
-	if (connpos_dirty)
-		_connpos_update();
+    if (connpos_dirty)
+        _connpos_update();
 
 
-	ERR_FAIL_INDEX_V(p_idx,conn_output_cache.size(),Vector2());
-	return conn_output_cache[p_idx].pos;
+    ERR_FAIL_INDEX_V(p_idx,conn_output_cache.size(),Vector2());
+    return conn_output_cache[p_idx].pos;
 
 
 }
 }
 
 
 int GraphNode::get_connection_output_type(int p_idx) {
 int GraphNode::get_connection_output_type(int p_idx) {
 
 
-	if (connpos_dirty)
-		_connpos_update();
+    if (connpos_dirty)
+        _connpos_update();
 
 
-	ERR_FAIL_INDEX_V(p_idx,conn_output_cache.size(),0);
-	return conn_output_cache[p_idx].type;
+    ERR_FAIL_INDEX_V(p_idx,conn_output_cache.size(),0);
+    return conn_output_cache[p_idx].type;
 }
 }
 
 
 Color GraphNode::get_connection_output_color(int p_idx) {
 Color GraphNode::get_connection_output_color(int p_idx) {
 
 
-	if (connpos_dirty)
-		_connpos_update();
+    if (connpos_dirty)
+        _connpos_update();
 
 
-	ERR_FAIL_INDEX_V(p_idx,conn_output_cache.size(),Color());
-	return conn_output_cache[p_idx].color;
+    ERR_FAIL_INDEX_V(p_idx,conn_output_cache.size(),Color());
+    return conn_output_cache[p_idx].color;
 }
 }
 
 
 void GraphNode::_input_event(const InputEvent& p_ev) {
 void GraphNode::_input_event(const InputEvent& p_ev) {
 
 
-	if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) {
+    if (p_ev.type==InputEvent::MOUSE_BUTTON && p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) {
 
 
-		Vector2 mpos = Vector2(p_ev.mouse_button.x,p_ev.mouse_button.y);
-		if (close_rect.size!=Size2() && close_rect.has_point(mpos)) {
-			emit_signal("close_request");
-			return;
-		}
+        Vector2 mpos = Vector2(p_ev.mouse_button.x,p_ev.mouse_button.y);
+        if (close_rect.size!=Size2() && close_rect.has_point(mpos)) {
+            emit_signal("close_request");
+            return;
+        }
+        emit_signal("raise_request");
 
 
-		drag_from=get_offset();
-		drag_accum=Vector2();
-		dragging=true;
-		emit_signal("raise_request");
-
-	}
-
-	if (p_ev.type==InputEvent::MOUSE_BUTTON && !p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) {
-
-		dragging=false;
-		emit_signal("dragged",drag_from,get_offset()); //useful for undo/redo
-	}
-
-	if (p_ev.type==InputEvent::MOUSE_MOTION && dragging) {
-
-		drag_accum+=Vector2(p_ev.mouse_motion.relative_x,p_ev.mouse_motion.relative_y);
-		set_offset(drag_from+drag_accum);
-	}
+    }
 
 
 }
 }
 
 
 
 
 void GraphNode::_bind_methods() {
 void GraphNode::_bind_methods() {
 
 
-	ObjectTypeDB::bind_method(_MD("set_title","title"),&GraphNode::set_title);
-	ObjectTypeDB::bind_method(_MD("get_title"),&GraphNode::get_title);
-	ObjectTypeDB::bind_method(_MD("_input_event"),&GraphNode::_input_event);
+    ObjectTypeDB::bind_method(_MD("set_title","title"),&GraphNode::set_title);
+    ObjectTypeDB::bind_method(_MD("get_title"),&GraphNode::get_title);
+    ObjectTypeDB::bind_method(_MD("_input_event"),&GraphNode::_input_event);
 
 
-	ObjectTypeDB::bind_method(_MD("set_slot","idx","enable_left","type_left","color_left","enable_right","type_right","color_right"),&GraphNode::set_slot);
-	ObjectTypeDB::bind_method(_MD("clear_slot","idx"),&GraphNode::clear_slot);
-	ObjectTypeDB::bind_method(_MD("clear_all_slots","idx"),&GraphNode::clear_all_slots);
-	ObjectTypeDB::bind_method(_MD("is_slot_enabled_left","idx"),&GraphNode::is_slot_enabled_left);
-	ObjectTypeDB::bind_method(_MD("get_slot_type_left","idx"),&GraphNode::get_slot_type_left);
-	ObjectTypeDB::bind_method(_MD("get_slot_color_left","idx"),&GraphNode::get_slot_color_left);
-	ObjectTypeDB::bind_method(_MD("is_slot_enabled_right","idx"),&GraphNode::is_slot_enabled_right);
-	ObjectTypeDB::bind_method(_MD("get_slot_type_right","idx"),&GraphNode::get_slot_type_right);
-	ObjectTypeDB::bind_method(_MD("get_slot_color_right","idx"),&GraphNode::get_slot_color_right);
+    ObjectTypeDB::bind_method(_MD("set_slot","idx","enable_left","type_left","color_left","enable_right","type_right","color_right"),&GraphNode::set_slot);
+    ObjectTypeDB::bind_method(_MD("clear_slot","idx"),&GraphNode::clear_slot);
+    ObjectTypeDB::bind_method(_MD("clear_all_slots","idx"),&GraphNode::clear_all_slots);
+    ObjectTypeDB::bind_method(_MD("is_slot_enabled_left","idx"),&GraphNode::is_slot_enabled_left);
+    ObjectTypeDB::bind_method(_MD("get_slot_type_left","idx"),&GraphNode::get_slot_type_left);
+    ObjectTypeDB::bind_method(_MD("get_slot_color_left","idx"),&GraphNode::get_slot_color_left);
+    ObjectTypeDB::bind_method(_MD("is_slot_enabled_right","idx"),&GraphNode::is_slot_enabled_right);
+    ObjectTypeDB::bind_method(_MD("get_slot_type_right","idx"),&GraphNode::get_slot_type_right);
+    ObjectTypeDB::bind_method(_MD("get_slot_color_right","idx"),&GraphNode::get_slot_color_right);
 
 
-	ObjectTypeDB::bind_method(_MD("set_offset","offset"),&GraphNode::set_offset);
-	ObjectTypeDB::bind_method(_MD("get_offset"),&GraphNode::get_offset);
+    ObjectTypeDB::bind_method(_MD("set_offset","offset"),&GraphNode::set_offset);
+    ObjectTypeDB::bind_method(_MD("get_offset"),&GraphNode::get_offset);
 
 
-	ObjectTypeDB::bind_method(_MD("get_connection_output_count"),&GraphNode::get_connection_output_count);
-	ObjectTypeDB::bind_method(_MD("get_connection_input_count"),&GraphNode::get_connection_input_count);
+    ObjectTypeDB::bind_method(_MD("get_connection_output_count"),&GraphNode::get_connection_output_count);
+    ObjectTypeDB::bind_method(_MD("get_connection_input_count"),&GraphNode::get_connection_input_count);
 
 
-	ObjectTypeDB::bind_method(_MD("get_connection_output_pos","idx"),&GraphNode::get_connection_output_pos);
-	ObjectTypeDB::bind_method(_MD("get_connection_output_type","idx"),&GraphNode::get_connection_output_type);
-	ObjectTypeDB::bind_method(_MD("get_connection_output_color","idx"),&GraphNode::get_connection_output_color);
-	ObjectTypeDB::bind_method(_MD("get_connection_input_pos","idx"),&GraphNode::get_connection_input_pos);
-	ObjectTypeDB::bind_method(_MD("get_connection_input_type","idx"),&GraphNode::get_connection_input_type);
-	ObjectTypeDB::bind_method(_MD("get_connection_input_color","idx"),&GraphNode::get_connection_input_color);
+    ObjectTypeDB::bind_method(_MD("get_connection_output_pos","idx"),&GraphNode::get_connection_output_pos);
+    ObjectTypeDB::bind_method(_MD("get_connection_output_type","idx"),&GraphNode::get_connection_output_type);
+    ObjectTypeDB::bind_method(_MD("get_connection_output_color","idx"),&GraphNode::get_connection_output_color);
+    ObjectTypeDB::bind_method(_MD("get_connection_input_pos","idx"),&GraphNode::get_connection_input_pos);
+    ObjectTypeDB::bind_method(_MD("get_connection_input_type","idx"),&GraphNode::get_connection_input_type);
+    ObjectTypeDB::bind_method(_MD("get_connection_input_color","idx"),&GraphNode::get_connection_input_color);
 
 
 
 
-	ObjectTypeDB::bind_method(_MD("set_show_close_button","show"),&GraphNode::set_show_close_button);
-	ObjectTypeDB::bind_method(_MD("is_close_button_visible"),&GraphNode::is_close_button_visible);
+    ObjectTypeDB::bind_method(_MD("set_show_close_button","show"),&GraphNode::set_show_close_button);
+    ObjectTypeDB::bind_method(_MD("is_close_button_visible"),&GraphNode::is_close_button_visible);
 
 
-	ADD_PROPERTY( PropertyInfo(Variant::STRING,"title"),_SCS("set_title"),_SCS("get_title"));
-	ADD_PROPERTY( PropertyInfo(Variant::BOOL,"show_close"),_SCS("set_show_close_button"),_SCS("is_close_button_visible"));
+    ADD_PROPERTY( PropertyInfo(Variant::STRING,"title"),_SCS("set_title"),_SCS("get_title"));
+    ADD_PROPERTY( PropertyInfo(Variant::BOOL,"show_close"),_SCS("set_show_close_button"),_SCS("is_close_button_visible"));
 
 
-	ADD_SIGNAL(MethodInfo("offset_changed"));
-	ADD_SIGNAL(MethodInfo("dragged",PropertyInfo(Variant::VECTOR2,"from"),PropertyInfo(Variant::VECTOR2,"to")));
-	ADD_SIGNAL(MethodInfo("raise_request"));
-	ADD_SIGNAL(MethodInfo("close_request"));
+    ADD_SIGNAL(MethodInfo("offset_changed"));
+    ADD_SIGNAL(MethodInfo("dragged",PropertyInfo(Variant::VECTOR2,"from"),PropertyInfo(Variant::VECTOR2,"to")));
+    ADD_SIGNAL(MethodInfo("raise_request"));
+    ADD_SIGNAL(MethodInfo("close_request"));
 }
 }
 
 
 GraphNode::GraphNode() {
 GraphNode::GraphNode() {
-
-	dragging=false;
-	show_close=false;
-	connpos_dirty=true;
+    show_close=false;
+    connpos_dirty=true;
 }
 }

+ 65 - 60
scene/gui/graph_node.h

@@ -5,96 +5,101 @@
 
 
 class GraphNode : public Container {
 class GraphNode : public Container {
 
 
-	OBJ_TYPE(GraphNode,Container);
+    OBJ_TYPE(GraphNode,Container);
 
 
 
 
 
 
-	struct Slot {
-		bool enable_left;
-		int type_left;
-		Color color_left;
-		bool enable_right;
-		int type_right;
-		Color color_right;
+    struct Slot {
+        bool enable_left;
+        int type_left;
+        Color color_left;
+        bool enable_right;
+        int type_right;
+        Color color_right;
 
 
 
 
-		Slot() { enable_left=false; type_left=0; color_left=Color(1,1,1,1); enable_right=false; type_right=0; color_right=Color(1,1,1,1); };
-	};
+        Slot() { enable_left=false; type_left=0; color_left=Color(1,1,1,1); enable_right=false; type_right=0; color_right=Color(1,1,1,1); }
+    };
 
 
-	String title;
-	bool show_close;
-	Vector2 offset;
+    String title;
+    bool show_close;
+    Vector2 offset;
 
 
-	Rect2 close_rect;
+    Rect2 close_rect;
 
 
-	Vector<int> cache_y;
+    Vector<int> cache_y;
 
 
-	struct ConnCache {
-		Vector2 pos;
-		int type;
-		Color color;
-	};
+    struct ConnCache {
+        Vector2 pos;
+        int type;
+        Color color;
+    };
 
 
-	Vector<ConnCache> conn_input_cache;
-	Vector<ConnCache> conn_output_cache;
+    Vector<ConnCache> conn_input_cache;
+    Vector<ConnCache> conn_output_cache;
 
 
-	Map<int,Slot> slot_info;
+    Map<int,Slot> slot_info;
 
 
-	bool connpos_dirty;
+    bool connpos_dirty;
 
 
-	void _connpos_update();
-	void _resort();
+    void _connpos_update();
+    void _resort();
 
 
-	Vector2 drag_from;
-	Vector2 drag_accum;
-	bool dragging;
+    Vector2 drag_from;
+    bool selected;
 protected:
 protected:
 
 
-	void _input_event(const InputEvent& p_ev);
-	void _notification(int p_what);
-	static void _bind_methods();
+    void _input_event(const InputEvent& p_ev);
+    void _notification(int p_what);
+    static void _bind_methods();
 
 
-	bool _set(const StringName& p_name, const Variant& p_value);
-	bool _get(const StringName& p_name,Variant &r_ret) const;
-	void _get_property_list( List<PropertyInfo> *p_list) const;
+    bool _set(const StringName& p_name, const Variant& p_value);
+    bool _get(const StringName& p_name,Variant &r_ret) const;
+    void _get_property_list( List<PropertyInfo> *p_list) const;
 
 
 public:
 public:
 
 
 
 
 
 
 
 
-	void set_slot(int p_idx,bool p_enable_left,int p_type_left,const Color& p_color_left, bool p_enable_right,int p_type_right,const Color& p_color_right);
-	void clear_slot(int p_idx);
-	void clear_all_slots();
-	bool is_slot_enabled_left(int p_idx) const;
-	int get_slot_type_left(int p_idx) const;
-	Color get_slot_color_left(int p_idx) const;
-	bool is_slot_enabled_right(int p_idx) const;
-	int get_slot_type_right(int p_idx) const;
-	Color get_slot_color_right(int p_idx) const;
+    void set_slot(int p_idx,bool p_enable_left,int p_type_left,const Color& p_color_left, bool p_enable_right,int p_type_right,const Color& p_color_right);
+    void clear_slot(int p_idx);
+    void clear_all_slots();
+    bool is_slot_enabled_left(int p_idx) const;
+    int get_slot_type_left(int p_idx) const;
+    Color get_slot_color_left(int p_idx) const;
+    bool is_slot_enabled_right(int p_idx) const;
+    int get_slot_type_right(int p_idx) const;
+    Color get_slot_color_right(int p_idx) const;
 
 
-	void set_title(const String& p_title);
-	String get_title() const;
+    void set_title(const String& p_title);
+    String get_title() const;
 
 
-	void set_offset(const Vector2& p_offset);
-	Vector2 get_offset() const;
+    void set_offset(const Vector2& p_offset);
+    Vector2 get_offset() const;
 
 
-	void set_show_close_button(bool p_enable);
-	bool is_close_button_visible() const;
+    void set_selected(bool p_selected);
+    bool is_selected();
 
 
-	int get_connection_input_count() ;
-	int get_connection_output_count() ;
-	Vector2 get_connection_input_pos(int p_idx);
-	int get_connection_input_type(int p_idx);
-	Color get_connection_input_color(int p_idx);
-	Vector2 get_connection_output_pos(int p_idx);
-	int get_connection_output_type(int p_idx);
-	Color get_connection_output_color(int p_idx);
+    void set_drag(bool p_drag);
+    Vector2 get_drag_from();
 
 
+    void set_show_close_button(bool p_enable);
+    bool is_close_button_visible() const;
 
 
-	virtual Size2 get_minimum_size() const;
+    int get_connection_input_count() ;
+    int get_connection_output_count() ;
+    Vector2 get_connection_input_pos(int p_idx);
+    int get_connection_input_type(int p_idx);
+    Color get_connection_input_color(int p_idx);
+    Vector2 get_connection_output_pos(int p_idx);
+    int get_connection_output_type(int p_idx);
+    Color get_connection_output_color(int p_idx);
 
 
-	GraphNode();
+
+    virtual Size2 get_minimum_size() const;
+
+    GraphNode();
 };
 };
 
 
 
 

+ 2 - 0
scene/resources/default_theme/default_theme.cpp

@@ -558,9 +558,11 @@ void make_default_theme() {
 	// GraphNode
 	// GraphNode
 
 
 	Ref<StyleBoxTexture> graphsb = make_stylebox(graph_node_png,6,24,6,5,16,24,16,5);
 	Ref<StyleBoxTexture> graphsb = make_stylebox(graph_node_png,6,24,6,5,16,24,16,5);
+    Ref<StyleBoxTexture> graphsbselected = make_stylebox(graph_node_selected_png,6,24,6,5,16,24,16,5);
 	//graphsb->set_expand_margin_size(MARGIN_LEFT,10);
 	//graphsb->set_expand_margin_size(MARGIN_LEFT,10);
 	//graphsb->set_expand_margin_size(MARGIN_RIGHT,10);
 	//graphsb->set_expand_margin_size(MARGIN_RIGHT,10);
 	t->set_stylebox("frame","GraphNode", graphsb );
 	t->set_stylebox("frame","GraphNode", graphsb );
+    t->set_stylebox("selectedframe","GraphNode", graphsbselected );
 	t->set_constant("separation","GraphNode", 1 );
 	t->set_constant("separation","GraphNode", 1 );
 	t->set_icon("port","GraphNode", make_icon( graph_port_png ) );
 	t->set_icon("port","GraphNode", make_icon( graph_port_png ) );
 	t->set_icon("close","GraphNode", make_icon( graph_node_close_png ) );
 	t->set_icon("close","GraphNode", make_icon( graph_node_close_png ) );

BIN
scene/resources/default_theme/graph_node_selected.png


File diff suppressed because it is too large
+ 1 - 0
scene/resources/default_theme/theme_data.h


File diff suppressed because it is too large
+ 443 - 443
tools/editor/plugins/shader_graph_editor_plugin.cpp


+ 123 - 121
tools/editor/plugins/shader_graph_editor_plugin.h

@@ -41,187 +41,189 @@
 #include "tools/editor/property_editor.h"
 #include "tools/editor/property_editor.h"
 #include "scene/resources/shader_graph.h"
 #include "scene/resources/shader_graph.h"
 /**
 /**
-	@author Juan Linietsky <[email protected]>
+    @author Juan Linietsky <[email protected]>
 */
 */
 
 
 
 
 class GraphColorRampEdit : public Control {
 class GraphColorRampEdit : public Control {
 
 
-	OBJ_TYPE(GraphColorRampEdit,Control);
+    OBJ_TYPE(GraphColorRampEdit,Control);
 
 
 
 
-	struct Point {
+    struct Point {
 
 
-		float offset;
-		Color color;
-		bool operator<(const Point& p_ponit) const {
-			return offset<p_ponit.offset;
-		}
-	};
+        float offset;
+        Color color;
+        bool operator<(const Point& p_ponit) const {
+            return offset<p_ponit.offset;
+        }
+    };
 
 
-	PopupPanel *popup;
-	ColorPicker *picker;
+    PopupPanel *popup;
+    ColorPicker *picker;
 
 
 
 
-	bool grabbing;
-	int grabbed;
-	float grabbed_at;
-	Vector<Point> points;
+    bool grabbing;
+    int grabbed;
+    float grabbed_at;
+    Vector<Point> points;
 
 
-	void _color_changed(const Color& p_color);
+    void _color_changed(const Color& p_color);
 
 
 protected:
 protected:
-	void _input_event(const InputEvent& p_event);
-	void _notification(int p_what);
-	static void _bind_methods();
+    void _input_event(const InputEvent& p_event);
+    void _notification(int p_what);
+    static void _bind_methods();
 public:
 public:
 
 
-	void set_ramp(const Vector<float>& p_offsets,const Vector<Color>& p_colors);
-	Vector<float> get_offsets() const;
-	Vector<Color> get_colors() const;
-	virtual Size2 get_minimum_size() const;
-	GraphColorRampEdit();
+    void set_ramp(const Vector<float>& p_offsets,const Vector<Color>& p_colors);
+    Vector<float> get_offsets() const;
+    Vector<Color> get_colors() const;
+    virtual Size2 get_minimum_size() const;
+    GraphColorRampEdit();
 };
 };
 
 
 
 
 class GraphCurveMapEdit : public Control {
 class GraphCurveMapEdit : public Control {
 
 
-	OBJ_TYPE(GraphCurveMapEdit,Control);
+    OBJ_TYPE(GraphCurveMapEdit,Control);
 
 
 
 
-	struct Point {
+    struct Point {
 
 
-		float offset;
-		float height;
-		bool operator<(const Point& p_ponit) const {
-			return offset<p_ponit.offset;
-		}
-	};
+        float offset;
+        float height;
+        bool operator<(const Point& p_ponit) const {
+            return offset<p_ponit.offset;
+        }
+    };
 
 
 
 
-	bool grabbing;
-	int grabbed;
-	Vector<Point> points;
+    bool grabbing;
+    int grabbed;
+    Vector<Point> points;
 
 
-	void _plot_curve(const Vector2& p_a,const Vector2& p_b,const Vector2& p_c,const Vector2& p_d);
+    void _plot_curve(const Vector2& p_a,const Vector2& p_b,const Vector2& p_c,const Vector2& p_d);
 protected:
 protected:
-	void _input_event(const InputEvent& p_event);
-	void _notification(int p_what);
-	static void _bind_methods();
+    void _input_event(const InputEvent& p_event);
+    void _notification(int p_what);
+    static void _bind_methods();
 public:
 public:
 
 
-	void set_points(const Vector<Vector2>& p_points);
-	Vector<Vector2> get_points() const;
-	virtual Size2 get_minimum_size() const;
-	GraphCurveMapEdit();
+    void set_points(const Vector<Vector2>& p_points);
+    Vector<Vector2> get_points() const;
+    virtual Size2 get_minimum_size() const;
+    GraphCurveMapEdit();
 };
 };
 
 
 class ShaderGraphView : public Node {
 class ShaderGraphView : public Node {
 
 
-	OBJ_TYPE(ShaderGraphView,Node);
-
-
-
-	CustomPropertyEditor *ped_popup;
-	bool block_update;
-
-	Label *status;
-	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 _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 _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);
-	void _color_ramp_changed(int p_id,Node* p_ramp);
-	void _curve_changed(int p_id,Node* p_curve);
-	void _sg_updated();
-	Map<int,GraphNode*> node_map;
+    OBJ_TYPE(ShaderGraphView,Node);
+
+
+
+    CustomPropertyEditor *ped_popup;
+    bool block_update;
+
+    Label *status;
+    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 _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 _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);
+    void _color_ramp_changed(int p_id,Node* p_ramp);
+    void _curve_changed(int p_id,Node* p_curve);
+    void _sg_updated();
+    Map<int,GraphNode*> node_map;
 protected:
 protected:
-	void _notification(int p_what);
-	static void _bind_methods();
+    void _notification(int p_what);
+    static void _bind_methods();
 public:
 public:
 
 
     void add_node(int p_type, const Vector2 &location);
     void add_node(int p_type, const Vector2 &location);
-	GraphEdit *get_graph_edit() { return graph_edit; }
-	void set_graph(Ref<ShaderGraph> p_graph);
+    GraphEdit *get_graph_edit() { return graph_edit; }
+    void set_graph(Ref<ShaderGraph> p_graph);
 
 
-	ShaderGraphView(ShaderGraph::ShaderType p_type=ShaderGraph::SHADER_TYPE_FRAGMENT);
+    ShaderGraphView(ShaderGraph::ShaderType p_type=ShaderGraph::SHADER_TYPE_FRAGMENT);
 };
 };
 
 
 class ShaderGraphEditor : public VBoxContainer {
 class ShaderGraphEditor : public VBoxContainer {
 
 
-	OBJ_TYPE(ShaderGraphEditor,VBoxContainer);
+    OBJ_TYPE(ShaderGraphEditor,VBoxContainer);
 
 
     PopupMenu *popup;
     PopupMenu *popup;
-	TabContainer *tabs;
-	ShaderGraphView *graph_edits[ShaderGraph::SHADER_TYPE_MAX];
-	static const char* node_names[ShaderGraph::NODE_TYPE_MAX];
+    TabContainer *tabs;
+    ShaderGraphView *graph_edits[ShaderGraph::SHADER_TYPE_MAX];
+    static const char* node_names[ShaderGraph::NODE_TYPE_MAX];
     Vector2 next_location;
     Vector2 next_location;
 
 
-	bool _2d;
-	void _add_node(int p_type);
+    bool _2d;
+    void _add_node(int p_type);
     void _popup_requested(const Vector2 &p_position);
     void _popup_requested(const Vector2 &p_position);
 protected:
 protected:
-	void _notification(int p_what);
-	static void _bind_methods();
+    void _notification(int p_what);
+    static void _bind_methods();
 public:
 public:
 
 
-	void edit(Ref<ShaderGraph> p_shader);
-	ShaderGraphEditor(bool p_2d);
+    void edit(Ref<ShaderGraph> p_shader);
+    ShaderGraphEditor(bool p_2d);
 };
 };
 
 
 class ShaderGraphEditorPlugin : public EditorPlugin {
 class ShaderGraphEditorPlugin : public EditorPlugin {
 
 
-	OBJ_TYPE( ShaderGraphEditorPlugin, EditorPlugin );
+    OBJ_TYPE( ShaderGraphEditorPlugin, EditorPlugin );
 
 
-	bool _2d;
-	ShaderGraphEditor *shader_editor;
-	EditorNode *editor;
+    bool _2d;
+    ShaderGraphEditor *shader_editor;
+    EditorNode *editor;
 
 
 public:
 public:
 
 
-	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);
+    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);
 
 
-	ShaderGraphEditorPlugin(EditorNode *p_node,bool p_2d);
-	~ShaderGraphEditorPlugin();
+    ShaderGraphEditorPlugin(EditorNode *p_node,bool p_2d);
+    ~ShaderGraphEditorPlugin();
 
 
 };
 };
 #endif
 #endif

Some files were not shown because too many files changed in this diff