summaryrefslogtreecommitdiff
path: root/scene/gui
diff options
context:
space:
mode:
Diffstat (limited to 'scene/gui')
-rw-r--r--scene/gui/control.cpp9
-rw-r--r--scene/gui/control.h6
-rw-r--r--scene/gui/graph_edit.cpp196
-rw-r--r--scene/gui/graph_edit.h9
-rw-r--r--scene/gui/graph_node.cpp77
-rw-r--r--scene/gui/graph_node.h14
6 files changed, 256 insertions, 55 deletions
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 71ec508c81..97133a2a3b 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -2214,7 +2214,7 @@ void Control::grab_click_focus() {
void Control::minimum_size_changed() {
- if (!is_inside_tree())
+ if (!is_inside_tree() || data.block_minimum_size_adjust)
return;
if (data.pending_min_size_update)
@@ -2374,8 +2374,14 @@ Control *Control::get_root_parent_control() const {
return const_cast<Control*>(root);
}
+void Control::set_block_minimum_size_adjust(bool p_block) {
+ data.block_minimum_size_adjust=p_block;
+}
+bool Control::is_minimum_size_adjust_blocked() const {
+ return data.block_minimum_size_adjust;
+}
void Control::_bind_methods() {
@@ -2603,6 +2609,7 @@ Control::Control() {
data.scale=Vector2(1,1);
data.drag_owner=0;
data.modal_frame=0;
+ data.block_minimum_size_adjust=false;
for (int i=0;i<4;i++) {
diff --git a/scene/gui/control.h b/scene/gui/control.h
index b9ac53067a..e6b0844869 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -128,6 +128,8 @@ private:
bool ignore_mouse;
bool stop_mouse;
+ bool block_minimum_size_adjust;
+
Control *parent;
ObjectID drag_owner;
bool modal;
@@ -396,6 +398,10 @@ public:
Control *get_root_parent_control() const;
+
+ void set_block_minimum_size_adjust(bool p_block);
+ bool is_minimum_size_adjust_blocked() const;
+
Control();
~Control();
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 458e51b4fd..a7a813d335 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -61,6 +61,7 @@ Error GraphEdit::connect_node(const StringName& p_from, int p_from_port,const St
c.to_port=p_to_port;
connections.push_back(c);
top_layer->update();
+ update();
return OK;
}
@@ -85,6 +86,7 @@ void GraphEdit::disconnect_node(const StringName& p_from, int p_from_port,const
connections.erase(E);
top_layer->update();
+ update();
return;
}
}
@@ -118,10 +120,7 @@ void GraphEdit::_scroll_moved(double) {
_update_scroll_offset();
top_layer->update();
- if (is_using_snap()) {
- //must redraw grid
- update();
- }
+ update();
if (!setting_scroll_ofs) {//in godot, signals on change value are avoided as a convention
emit_signal("scroll_offset_changed",get_scroll_ofs());
@@ -194,6 +193,9 @@ void GraphEdit::_graph_node_raised(Node* p_gn) {
GraphNode *gn=p_gn->cast_to<GraphNode>();
ERR_FAIL_COND(!gn);
gn->raise();
+ if (gn->is_comment()) {
+ move_child(gn,0);
+ }
top_layer->raise();
emit_signal("node_selected",p_gn);
@@ -205,6 +207,7 @@ void GraphEdit::_graph_node_moved(Node *p_gn) {
GraphNode *gn=p_gn->cast_to<GraphNode>();
ERR_FAIL_COND(!gn);
top_layer->update();
+ update();
}
void GraphEdit::add_child_notify(Node *p_child) {
@@ -261,6 +264,7 @@ void GraphEdit::_notification(int p_what) {
}
if (p_what==NOTIFICATION_DRAW) {
+
draw_style_box( get_stylebox("bg"),Rect2(Point2(),get_size()) );
VS::get_singleton()->canvas_item_set_clip(get_canvas_item(),true);
@@ -306,11 +310,60 @@ void GraphEdit::_notification(int p_what) {
}
+ {
+ //draw connections
+ 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();
+ Color tocolor = gto->get_connection_input_color(E->get().to_port);
+ _draw_cos_line(this,frompos,topos,color,tocolor);
+
+ }
+
+ while(to_erase.size()) {
+ connections.erase(to_erase.front()->get());
+ to_erase.pop_front();
+ }
+ }
+
}
if (p_what==NOTIFICATION_RESIZED) {
_update_scroll();
top_layer->update();
+
}
}
@@ -466,7 +519,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) {
connecting_to=Vector2(p_ev.mouse_motion.x,p_ev.mouse_motion.y);
connecting_target=false;
- top_layer->update();
+ top_layer->update();
Ref<Texture> port =get_icon("port","GraphNode");
Vector2 mpos(p_ev.mouse_button.x,p_ev.mouse_button.y);
@@ -526,18 +579,90 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) {
}
emit_signal("connection_request",from,from_slot,to,to_slot);
+ } else {
+ String from = connecting_from;
+ int from_slot = connecting_index;
+ Vector2 ofs = Vector2(p_ev.mouse_button.x,p_ev.mouse_button.y);
+ emit_signal("connection_to_empty",from,from_slot,ofs);
}
connecting=false;
top_layer->update();
+ update();
}
}
-void GraphEdit::_draw_cos_line(const Vector2& p_from, const Vector2& p_to,const Color& p_color,const Color& p_to_color) {
+
+template<class Vector2>
+static _FORCE_INLINE_ Vector2 _bezier_interp(real_t t, Vector2 start, Vector2 control_1, Vector2 control_2, Vector2 end) {
+ /* Formula from Wikipedia article on Bezier curves. */
+ real_t omt = (1.0 - t);
+ real_t omt2 = omt*omt;
+ real_t omt3 = omt2*omt;
+ real_t t2 = t*t;
+ real_t t3 = t2*t;
+
+ return start * omt3
+ + control_1 * omt2 * t * 3.0
+ + control_2 * omt * t2 * 3.0
+ + end * t3;
+}
+
+
+void GraphEdit::_bake_segment2d(CanvasItem* p_where,float p_begin, float p_end,const Vector2& p_a,const Vector2& p_out,const Vector2& p_b, const Vector2& p_in,int p_depth,int p_min_depth,int p_max_depth,float p_tol,const Color& p_color,const Color& p_to_color,int &lines) const {
+
+ float mp = p_begin+(p_end-p_begin)*0.5;
+ Vector2 beg = _bezier_interp(p_begin,p_a,p_a+p_out,p_b+p_in,p_b);
+ Vector2 mid = _bezier_interp(mp,p_a,p_a+p_out,p_b+p_in,p_b);
+ Vector2 end = _bezier_interp(p_end,p_a,p_a+p_out,p_b+p_in,p_b);
+
+ Vector2 na = (mid-beg).normalized();
+ Vector2 nb = (end-mid).normalized();
+ float dp = Math::rad2deg(Math::acos(na.dot(nb)));
+
+ if (p_depth>=p_min_depth && ( dp<p_tol || p_depth>=p_max_depth)) {
+
+
+
+ p_where->draw_line(beg,end,p_color.linear_interpolate(p_to_color,mp),2);
+ lines++;
+ } else {
+ _bake_segment2d(p_where,p_begin,mp,p_a,p_out,p_b,p_in,p_depth+1,p_min_depth,p_max_depth,p_tol,p_color,p_to_color,lines);
+ _bake_segment2d(p_where,mp,p_end,p_a,p_out,p_b,p_in,p_depth+1,p_min_depth,p_max_depth,p_tol,p_color,p_to_color,lines);
+ }
+}
+
+
+void GraphEdit::_draw_cos_line(CanvasItem* p_where,const Vector2& p_from, const Vector2& p_to,const Color& p_color,const Color& p_to_color) {
+
+#if 1
+
+ //cubic bezier code
+ float diff = p_to.x-p_from.x;
+ float cp_offset;
+ int cp_len = get_constant("bezier_len_pos");
+ int cp_neg_len = get_constant("bezier_len_neg");
+
+ if (diff>0) {
+ cp_offset=MAX(cp_len,diff*0.5);
+ } else {
+ cp_offset=MAX(MIN(cp_len-diff,cp_neg_len),-diff*0.5);
+ }
+
+ Vector2 c1 = Vector2(cp_offset,0);
+ Vector2 c2 = Vector2(-cp_offset,0);
+
+ int lines=0;
+ _bake_segment2d(p_where,0,1,p_from,c1,p_to,c2,0,5,12,8,p_color,p_to_color,lines);
+ //print_line("used lines: "+itos(lines));
+
+
+#else
static const int steps = 20;
+ //old cosine code
Rect2 r;
r.pos=p_from;
r.expand_to(p_to);
@@ -547,6 +672,7 @@ void GraphEdit::_draw_cos_line(const Vector2& p_from, const Vector2& p_to,const
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)
@@ -555,11 +681,12 @@ void GraphEdit::_draw_cos_line(const Vector2& p_from, const Vector2& p_to,const
if (i>0) {
- top_layer->draw_line(prev,p,p_color.linear_interpolate(p_to_color,d),2);
+ p_where->draw_line(prev,p,p_color.linear_interpolate(p_to_color,d),2);
}
prev=p;
}
+#endif
}
void GraphEdit::_top_layer_draw() {
@@ -589,53 +716,14 @@ void GraphEdit::_top_layer_draw() {
col.g+=0.4;
col.b+=0.4;
}
- _draw_cos_line(pos,topos,col,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;
+ if (!connecting_out) {
+ SWAP(pos,topos);
}
-
- 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();
- Color tocolor = gto->get_connection_input_color(E->get().to_port);
- _draw_cos_line(frompos,topos,color,tocolor);
-
+ _draw_cos_line(top_layer,pos,topos,col,col);
}
- while(to_erase.size()) {
- connections.erase(to_erase.front()->get());
- to_erase.pop_front();
- }
+
if (box_selecting)
top_layer->draw_rect(box_selecting_rect,Color(0.7,0.7,1.0,0.3));
}
@@ -765,6 +853,7 @@ void GraphEdit::_input_event(const InputEvent& p_ev) {
dragging = false;
top_layer->update();
+ update();
}
if (b.button_index==BUTTON_LEFT && b.pressed) {
@@ -775,6 +864,10 @@ void GraphEdit::_input_event(const InputEvent& p_ev) {
gn=get_child(i)->cast_to<GraphNode>();
if (gn) {
+
+ if (gn->is_resizing())
+ continue;
+
Rect2 r = gn->get_rect();
r.size*=zoom;
if (r.has_point(get_local_mouse_pos()))
@@ -1090,6 +1183,7 @@ void GraphEdit::_bind_methods() {
ADD_SIGNAL(MethodInfo("popup_request", PropertyInfo(Variant::VECTOR2,"p_position")));
ADD_SIGNAL(MethodInfo("duplicate_nodes_request"));
ADD_SIGNAL(MethodInfo("node_selected",PropertyInfo(Variant::OBJECT,"node")));
+ ADD_SIGNAL(MethodInfo("connection_to_empty",PropertyInfo(Variant::STRING,"from"),PropertyInfo(Variant::INT,"from_slot"),PropertyInfo(Variant::VECTOR2,"release_pos")));
ADD_SIGNAL(MethodInfo("delete_nodes_request"));
ADD_SIGNAL(MethodInfo("_begin_node_move"));
ADD_SIGNAL(MethodInfo("_end_node_move"));
@@ -1173,4 +1267,6 @@ GraphEdit::GraphEdit() {
setting_scroll_ofs=false;
+
+
}
diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h
index 6d35e1518f..c3276ceacc 100644
--- a/scene/gui/graph_edit.h
+++ b/scene/gui/graph_edit.h
@@ -112,7 +112,9 @@ private:
bool updating;
List<Connection> connections;
- void _draw_cos_line(const Vector2& p_from, const Vector2& p_to, const Color& p_color, const Color &p_to_color);
+ void _bake_segment2d(CanvasItem* p_where,float p_begin, float p_end, const Vector2& p_a, const Vector2& p_out, const Vector2& p_b, const Vector2& p_in, int p_depth, int p_min_depth, int p_max_depth, float p_tol, const Color& p_color, const Color& p_to_color, int &lines) const;
+
+ void _draw_cos_line(CanvasItem* p_where,const Vector2& p_from, const Vector2& p_to, const Color& p_color, const Color &p_to_color);
void _graph_node_raised(Node* p_gn);
void _graph_node_moved(Node *p_gn);
@@ -128,6 +130,10 @@ private:
Array _get_connection_list() const;
+ bool lines_on_bg;
+
+
+
struct ConnType {
union {
@@ -200,6 +206,7 @@ public:
int get_snap() const;
void set_snap(int p_snap);
+
GraphEdit();
};
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 66d2725ad2..5ece970936 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -188,11 +188,13 @@ void GraphNode::_notification(int p_what) {
if (p_what==NOTIFICATION_DRAW) {
- Ref<StyleBox> sb=get_stylebox(selected ? "selectedframe" : "frame");
+ Ref<StyleBox> sb=get_stylebox(comment? "comment": (selected ? "selectedframe" : "frame"));
+
sb=sb->duplicate();
sb->call("set_modulate",modulate);
Ref<Texture> port =get_icon("port");
Ref<Texture> close =get_icon("close");
+ Ref<Texture> resizer =get_icon("resizer");
int close_offset = get_constant("close_offset");
Ref<Font> title_font = get_font("title_font");
int title_offset = get_constant("title_offset");
@@ -258,6 +260,11 @@ void GraphNode::_notification(int p_what) {
}
}
+
+
+ if (resizeable) {
+ draw_texture(resizer,get_size()-resizer->get_size());
+ }
}
if (p_what==NOTIFICATION_SORT_CHILDREN) {
@@ -594,19 +601,49 @@ void GraphNode::_input_event(const InputEvent& p_ev) {
ERR_EXPLAIN("GraphNode must be the child of a GraphEdit node.");
ERR_FAIL_COND(get_parent_control() == NULL);
- get_parent_control()->grab_focus();
-
if(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");
+ accept_event();
+ return;
+ }
+
+ Ref<Texture> resizer =get_icon("resizer");
+
+ if (resizeable && mpos.x > get_size().x-resizer->get_width() && mpos.y > get_size().y-resizer->get_height()) {
+
+ resizing=true;
+ resizing_from=mpos;
+ resizing_from_size=get_size();
+ accept_event();
return;
}
+
+ //send focus to parent
emit_signal("raise_request");
+ get_parent_control()->grab_focus();
+
}
+
+ if(!p_ev.mouse_button.pressed && p_ev.mouse_button.button_index==BUTTON_LEFT) {
+ resizing=false;
+ }
+
+ }
+
+
+ if (resizing && p_ev.type==InputEvent::MOUSE_MOTION) {
+ Vector2 mpos = Vector2(p_ev.mouse_motion.x,p_ev.mouse_motion.y);
+
+ Vector2 diff = mpos - resizing_from;
+
+ emit_signal("resize_request",resizing_from_size+diff);
+
}
+
}
void GraphNode::set_modulate(const Color &p_color) {
@@ -630,6 +667,30 @@ GraphNode::Overlay GraphNode::get_overlay() const{
return overlay;
}
+void GraphNode::set_comment(bool p_enable) {
+
+ comment=p_enable;
+ update();
+}
+
+bool GraphNode::is_comment() const{
+
+ return comment;
+}
+
+
+void GraphNode::set_resizeable(bool p_enable) {
+
+ resizeable=p_enable;
+ update();
+}
+
+bool GraphNode::is_resizeable() const{
+
+ return resizeable;
+}
+
+
void GraphNode::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_title","title"),&GraphNode::set_title);
@@ -649,6 +710,12 @@ void GraphNode::_bind_methods() {
ObjectTypeDB::bind_method(_MD("set_offset","offset"),&GraphNode::set_offset);
ObjectTypeDB::bind_method(_MD("get_offset"),&GraphNode::get_offset);
+ ObjectTypeDB::bind_method(_MD("set_comment","comment"),&GraphNode::set_comment);
+ ObjectTypeDB::bind_method(_MD("is_comment"),&GraphNode::is_comment);
+
+ ObjectTypeDB::bind_method(_MD("set_resizeable","resizeable"),&GraphNode::set_resizeable);
+ ObjectTypeDB::bind_method(_MD("is_resizeable"),&GraphNode::is_resizeable);
+
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);
@@ -675,6 +742,7 @@ void GraphNode::_bind_methods() {
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("resize_request",PropertyInfo(Variant::VECTOR2,"new_minsize")));
BIND_CONSTANT( OVERLAY_DISABLED );
BIND_CONSTANT( OVERLAY_BREAKPOINT );
@@ -688,4 +756,7 @@ GraphNode::GraphNode() {
connpos_dirty=true;
set_stop_mouse(false);
modulate=Color(1,1,1,1);
+ comment=false;
+ resizeable=false;
+ resizing=false;
}
diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h
index e87fb15b93..7357ab5a45 100644
--- a/scene/gui/graph_node.h
+++ b/scene/gui/graph_node.h
@@ -60,6 +60,12 @@ private:
String title;
bool show_close;
Vector2 offset;
+ bool comment;
+ bool resizeable;
+
+ bool resizing;
+ Vector2 resizing_from;
+ Vector2 resizing_from_size;
Rect2 close_rect;
@@ -144,8 +150,16 @@ public:
void set_overlay(Overlay p_overlay);
Overlay get_overlay() const;
+ void set_comment(bool p_enable);
+ bool is_comment() const;
+
+ void set_resizeable(bool p_enable);
+ bool is_resizeable() const;
+
virtual Size2 get_minimum_size() const;
+ bool is_resizing() const { return resizing; }
+
GraphNode();
};