diff options
Diffstat (limited to 'scene/gui')
-rw-r--r-- | scene/gui/base_button.cpp | 11 | ||||
-rw-r--r-- | scene/gui/control.cpp | 58 | ||||
-rw-r--r-- | scene/gui/control.h | 11 | ||||
-rw-r--r-- | scene/gui/dialogs.cpp | 2 | ||||
-rw-r--r-- | scene/gui/graph_edit.cpp | 277 | ||||
-rw-r--r-- | scene/gui/graph_edit.h | 13 | ||||
-rw-r--r-- | scene/gui/graph_node.cpp | 104 | ||||
-rw-r--r-- | scene/gui/graph_node.h | 17 | ||||
-rw-r--r-- | scene/gui/item_list.cpp | 20 | ||||
-rw-r--r-- | scene/gui/item_list.h | 6 | ||||
-rw-r--r-- | scene/gui/line_edit.cpp | 79 | ||||
-rw-r--r-- | scene/gui/line_edit.h | 8 | ||||
-rw-r--r-- | scene/gui/slider.cpp | 9 | ||||
-rw-r--r-- | scene/gui/texture_progress.cpp | 1 | ||||
-rw-r--r-- | scene/gui/tree.cpp | 93 | ||||
-rw-r--r-- | scene/gui/tree.h | 10 |
16 files changed, 594 insertions, 125 deletions
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 41d766c1b7..6479dd2d02 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -55,6 +55,8 @@ void BaseButton::_input_event(InputEvent p_event) { if (b.pressed) { + emit_signal("button_down"); + if (!toggle_mode) { //mouse press attempt status.press_attempt=true; @@ -86,6 +88,8 @@ void BaseButton::_input_event(InputEvent p_event) { } else { + emit_signal("button_up"); + if (status.press_attempt && status.pressing_inside) { // released(); emit_signal("released"); @@ -100,9 +104,11 @@ void BaseButton::_input_event(InputEvent p_event) { status.press_attempt=true; status.pressing_inside=true; + emit_signal("button_down"); } else { + emit_signal("button_up"); if (status.press_attempt &&status.pressing_inside) { @@ -173,6 +179,7 @@ void BaseButton::_input_event(InputEvent p_event) { status.pressing_button++; status.press_attempt=true; status.pressing_inside=true; + emit_signal("button_down"); } else if (status.press_attempt) { @@ -185,6 +192,8 @@ void BaseButton::_input_event(InputEvent p_event) { status.press_attempt=false; status.pressing_inside=false; + emit_signal("button_up"); + if (!toggle_mode) { //mouse press attempt pressed(); @@ -467,6 +476,8 @@ void BaseButton::_bind_methods() { ADD_SIGNAL( MethodInfo("pressed" ) ); ADD_SIGNAL( MethodInfo("released" ) ); + ADD_SIGNAL( MethodInfo("button_up") ); + ADD_SIGNAL( MethodInfo("button_down") ); ADD_SIGNAL( MethodInfo("toggled", PropertyInfo( Variant::BOOL,"pressed") ) ); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "disabled"), _SCS("set_disabled"), _SCS("is_disabled")); ADD_PROPERTY( PropertyInfo( Variant::BOOL, "toggle_mode"), _SCS("set_toggle_mode"), _SCS("is_toggle_mode")); diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 71ec508c81..bf35fd25bd 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -449,6 +449,13 @@ void Control::remove_child_notify(Node *p_child) { } +void Control::_update_canvas_item_transform() { + + Matrix32 xform=Matrix32(data.rotation,get_pos()); + xform.scale_basis(data.scale); + VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(),xform); + +} void Control::_notification(int p_notification) { @@ -600,10 +607,9 @@ void Control::_notification(int p_notification) { } break; case NOTIFICATION_DRAW: { - Matrix32 xform=Matrix32(data.rotation,get_pos()); - xform.scale_basis(data.scale); - VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(),xform); - VisualServer::get_singleton()->canvas_item_set_custom_rect( get_canvas_item(),true, Rect2(Point2(),get_size())); + _update_canvas_item_transform(); + VisualServer::get_singleton()->canvas_item_set_custom_rect( get_canvas_item(),!data.disable_visibility_clip, Rect2(Point2(),get_size())); + //emit_signal(SceneStringNames::get_singleton()->draw); } break; @@ -1272,17 +1278,24 @@ void Control::_size_changed() { new_size_cache.x = MAX( minimum_size.x, new_size_cache.x ); new_size_cache.y = MAX( minimum_size.y, new_size_cache.y ); - - if (new_pos_cache == data.pos_cache && new_size_cache == data.size_cache) - return; // did not change, don't emit signal + bool pos_changed = new_pos_cache != data.pos_cache; + bool size_changed = new_size_cache != data.size_cache; data.pos_cache=new_pos_cache; data.size_cache=new_size_cache; - notification(NOTIFICATION_RESIZED); - item_rect_changed(); - _change_notify_margins(); - _notify_transform(); + if (size_changed) { + notification(NOTIFICATION_RESIZED); + } + if (pos_changed || size_changed) { + item_rect_changed(size_changed); + _change_notify_margins(); + _notify_transform(); + } + + if (pos_changed && !size_changed) { + _update_canvas_item_transform(); //move because it won't be updated + } } float Control::_get_parent_range(int p_idx) const { @@ -2214,7 +2227,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,7 +2387,26 @@ 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::set_disable_visibility_clip(bool p_ignore) { + + data.disable_visibility_clip=p_ignore; + update(); +} + +bool Control::is_visibility_clip_disabled() const { + + return data.disable_visibility_clip; +} void Control::_bind_methods() { @@ -2603,6 +2635,8 @@ Control::Control() { data.scale=Vector2(1,1); data.drag_owner=0; data.modal_frame=0; + data.block_minimum_size_adjust=false; + data.disable_visibility_clip=false; for (int i=0;i<4;i++) { diff --git a/scene/gui/control.h b/scene/gui/control.h index b9ac53067a..558439efbf 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -128,6 +128,9 @@ private: bool ignore_mouse; bool stop_mouse; + bool block_minimum_size_adjust; + bool disable_visibility_clip; + Control *parent; ObjectID drag_owner; bool modal; @@ -193,6 +196,7 @@ private: void _unref_font( Ref<Font> p_sc); void _font_changed(); + void _update_canvas_item_transform(); friend class Viewport; @@ -396,6 +400,13 @@ public: Control *get_root_parent_control() const; + + void set_block_minimum_size_adjust(bool p_block); + bool is_minimum_size_adjust_blocked() const; + + void set_disable_visibility_clip(bool p_ignore); + bool is_visibility_clip_disabled() const; + Control(); ~Control(); diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 4dbc106834..93e46da82b 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -399,8 +399,6 @@ AcceptDialog::AcceptDialog() { add_child(label); hbc = memnew( HBoxContainer ); - hbc->set_area_as_parent_rect(margin); - hbc->set_anchor_and_margin(MARGIN_TOP,ANCHOR_END,button_margin); add_child(hbc); hbc->add_spacer(); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index 458e51b4fd..0de6add8cb 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -61,6 +61,8 @@ 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(); + connections_layer->update(); return OK; } @@ -85,6 +87,8 @@ void GraphEdit::disconnect_node(const StringName& p_from, int p_from_port,const connections.erase(E); top_layer->update(); + update(); + connections_layer->update(); return; } } @@ -116,12 +120,13 @@ Vector2 GraphEdit::get_scroll_ofs() const{ void GraphEdit::_scroll_moved(double) { - _update_scroll_offset(); - top_layer->update(); - if (is_using_snap()) { - //must redraw grid - update(); + + if (!awaiting_scroll_offset_update) { + call_deferred("_update_scroll_offset"); + awaiting_scroll_offset_update=true; } + top_layer->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()); @@ -130,6 +135,8 @@ void GraphEdit::_scroll_moved(double) { void GraphEdit::_update_scroll_offset() { + set_block_minimum_size_adjust(true); + for(int i=0;i<get_child_count();i++) { GraphNode *gn=get_child(i)->cast_to<GraphNode>(); @@ -139,9 +146,15 @@ void GraphEdit::_update_scroll_offset() { Point2 pos=gn->get_offset()*zoom; pos-=Point2(h_scroll->get_val(),v_scroll->get_val()); gn->set_pos(pos); - gn->set_scale(Vector2(zoom,zoom)); + if (gn->get_scale()!=Vector2(zoom,zoom)) { + gn->set_scale(Vector2(zoom,zoom)); + } } + connections_layer->set_pos(-Point2(h_scroll->get_val(),v_scroll->get_val())*zoom); + set_block_minimum_size_adjust(false); + awaiting_scroll_offset_update=false; + } void GraphEdit::_update_scroll() { @@ -150,6 +163,9 @@ void GraphEdit::_update_scroll() { return; updating=true; + + set_block_minimum_size_adjust(true); + Rect2 screen; for(int i=0;i<get_child_count();i++) { @@ -184,7 +200,13 @@ void GraphEdit::_update_scroll() { else v_scroll->show(); - _update_scroll_offset(); + set_block_minimum_size_adjust(false); + + if (!awaiting_scroll_offset_update) { + call_deferred("_update_scroll_offset"); + awaiting_scroll_offset_update=true; + } + updating=false; } @@ -194,6 +216,19 @@ 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); + } + int first_not_comment=0; + for(int i=0;i<get_child_count();i++) { + GraphNode *gn=get_child(i)->cast_to<GraphNode>(); + if (gn && !gn->is_comment()) { + first_not_comment=i; + break; + } + } + + move_child(connections_layer,first_not_comment); top_layer->raise(); emit_signal("node_selected",p_gn); @@ -205,6 +240,8 @@ void GraphEdit::_graph_node_moved(Node *p_gn) { GraphNode *gn=p_gn->cast_to<GraphNode>(); ERR_FAIL_COND(!gn); top_layer->update(); + update(); + connections_layer->update(); } void GraphEdit::add_child_notify(Node *p_child) { @@ -261,6 +298,8 @@ 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 +345,14 @@ void GraphEdit::_notification(int p_what) { } + + } if (p_what==NOTIFICATION_RESIZED) { _update_scroll(); top_layer->update(); + } } @@ -318,7 +360,8 @@ bool GraphEdit::_filter_input(const Point2& p_point) { Ref<Texture> port =get_icon("port","GraphNode"); - float grab_r=port->get_width()*0.5; + float grab_r_extend = 2.0; + float grab_r=port->get_width()*0.5*grab_r_extend; for(int i=get_child_count()-1;i>=0;i--) { GraphNode *gn=get_child(i)->cast_to<GraphNode>(); @@ -337,8 +380,9 @@ bool GraphEdit::_filter_input(const Point2& p_point) { 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) + if (pos.distance_to(p_point)<grab_r) { return true; + } } @@ -350,11 +394,13 @@ bool GraphEdit::_filter_input(const Point2& p_point) { void GraphEdit::_top_layer_input(const InputEvent& p_ev) { + + float grab_r_extend = 2.0; 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; + float grab_r=port->get_width()*0.5*grab_r_extend; for(int i=get_child_count()-1;i>=0;i--) { GraphNode *gn=get_child(i)->cast_to<GraphNode>(); @@ -383,6 +429,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { connecting_color=to->cast_to<GraphNode>()->get_connection_input_color(E->get().to_port); connecting_target=false; connecting_to=pos; + just_disconected=true; emit_signal("disconnection_request",E->get().from,E->get().from_port,E->get().to,E->get().to_port); to = get_node(String(connecting_from)); //maybe it was erased @@ -404,6 +451,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { connecting_color=gn->get_connection_output_color(j); connecting_target=false; connecting_to=pos; + just_disconected=false; return; } @@ -432,6 +480,7 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { connecting_color=fr->cast_to<GraphNode>()->get_connection_output_color(E->get().from_port); connecting_target=false; connecting_to=pos; + just_disconected=true; 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 @@ -454,6 +503,8 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { connecting_color=gn->get_connection_input_color(j); connecting_target=false; connecting_to=pos; + just_disconected=true; + return; } @@ -466,11 +517,11 @@ 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); - float grab_r=port->get_width()*0.5; + float grab_r=port->get_width()*0.5*grab_r_extend; for(int i=get_child_count()-1;i>=0;i--) { GraphNode *gn=get_child(i)->cast_to<GraphNode>(); @@ -526,18 +577,91 @@ void GraphEdit::_top_layer_input(const InputEvent& p_ev) { } emit_signal("connection_request",from,from_slot,to,to_slot); + } else if (!just_disconected) { + 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(); + connections_layer->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,true); + 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,3,9,8,p_color,p_to_color,lines); + + +#else static const int steps = 20; + //old cosine code Rect2 r; r.pos=p_from; r.expand_to(p_to); @@ -547,6 +671,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 +680,65 @@ 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::_connections_layer_draw() { + + + { + //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_offset(); + Color color = gfrom->get_connection_output_color(E->get().from_port); + Vector2 topos=gto->get_connection_input_pos(E->get().to_port)+gto->get_offset(); + Color tocolor = gto->get_connection_input_color(E->get().to_port); + _draw_cos_line(connections_layer,frompos,topos,color,tocolor); + + } + + while(to_erase.size()) { + connections.erase(to_erase.front()->get()); + to_erase.pop_front(); + } + } } void GraphEdit::_top_layer_draw() { @@ -589,53 +768,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 +905,8 @@ void GraphEdit::_input_event(const InputEvent& p_ev) { dragging = false; top_layer->update(); + update(); + connections_layer->update(); } if (b.button_index==BUTTON_LEFT && b.pressed) { @@ -775,6 +917,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())) @@ -886,6 +1032,7 @@ void GraphEdit::clear_connections() { connections.clear(); update(); + connections_layer->update(); } void GraphEdit::set_zoom(float p_zoom) { @@ -1019,6 +1166,7 @@ void GraphEdit::set_use_snap(bool p_enable) { snap_button->set_pressed(p_enable); update(); + } bool GraphEdit::is_using_snap() const{ @@ -1082,6 +1230,10 @@ void GraphEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("_snap_value_changed"),&GraphEdit::_snap_value_changed); ObjectTypeDB::bind_method(_MD("_input_event"),&GraphEdit::_input_event); + ObjectTypeDB::bind_method(_MD("_update_scroll_offset"),&GraphEdit::_update_scroll_offset); + ObjectTypeDB::bind_method(_MD("_connections_layer_draw"),&GraphEdit::_connections_layer_draw); + + ObjectTypeDB::bind_method(_MD("set_selected","node"),&GraphEdit::set_selected); @@ -1090,6 +1242,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")); @@ -1101,6 +1254,7 @@ void GraphEdit::_bind_methods() { GraphEdit::GraphEdit() { set_focus_mode(FOCUS_ALL); + awaiting_scroll_offset_update=false; top_layer=NULL; top_layer=memnew(GraphEditFilter(this)); add_child(top_layer); @@ -1110,6 +1264,12 @@ GraphEdit::GraphEdit() { top_layer->set_stop_mouse(false); top_layer->connect("input_event",this,"_top_layer_input"); + connections_layer = memnew( Control ); + add_child(connections_layer); + connections_layer->connect("draw",this,"_connections_layer_draw"); + connections_layer->set_name("CLAYER"); + connections_layer->set_disable_visibility_clip(true); // so it can draw freely and be offseted + h_scroll = memnew(HScrollBar); h_scroll->set_name("_h_scroll"); top_layer->add_child(h_scroll); @@ -1172,5 +1332,8 @@ GraphEdit::GraphEdit() { zoom_hb->add_child(snap_amount); setting_scroll_ofs=false; + just_disconected=false; + + } diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index 6d35e1518f..c5174f6699 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -92,6 +92,7 @@ private: Vector2 connecting_to; String connecting_target_to; int connecting_target_index; + bool just_disconected; bool dragging; bool just_selected; @@ -110,9 +111,12 @@ private: bool setting_scroll_ofs; bool right_disconnects; bool updating; + bool awaiting_scroll_offset_update; 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); @@ -121,13 +125,19 @@ private: void _scroll_moved(double); void _input_event(const InputEvent& p_ev); + Control *connections_layer; GraphEditFilter *top_layer; void _top_layer_input(const InputEvent& p_ev); void _top_layer_draw(); + void _connections_layer_draw(); void _update_scroll_offset(); Array _get_connection_list() const; + bool lines_on_bg; + + + struct ConnType { union { @@ -200,6 +210,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..da298a795a 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -183,16 +183,45 @@ void GraphNode::_resort() { } +bool GraphNode::has_point(const Point2& p_point) const { + + if (comment) { + Ref<StyleBox> comment = get_stylebox("comment"); + Ref<Texture> resizer =get_icon("resizer"); + + if (Rect2(get_size()-resizer->get_size(), resizer->get_size()).has_point(p_point)) { + return true; + } + if (Rect2(0,0,get_size().width,comment->get_margin(MARGIN_TOP)).has_point(p_point)) { + return true; + } + + return false; + + } else { + return Control::has_point(p_point); + } +} void GraphNode::_notification(int p_what) { if (p_what==NOTIFICATION_DRAW) { - Ref<StyleBox> sb=get_stylebox(selected ? "selectedframe" : "frame"); + Ref<StyleBox> sb; + + if (comment) { + sb = get_stylebox( selected? "commentfocus" : "comment"); + + } else { + + sb = get_stylebox( 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 +287,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 +628,51 @@ 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(); + print_line("INPUT EVENT BUTTON"); 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 +696,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 +739,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 +771,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 +785,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..cbfd34f556 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; @@ -87,6 +93,9 @@ private: Overlay overlay; Color modulate; + + bool has_point(const Point2& p_point) const; + protected: @@ -144,8 +153,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(); }; diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 105d919338..89cd509fbd 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -40,6 +40,7 @@ void ItemList::add_item(const String& p_item,const Ref<Texture>& p_texture,bool item.selectable=p_selectable; item.selected=false; item.disabled=false; + item.tooltip_enabled=true; item.custom_bg=Color(0,0,0,0); items.push_back(item); @@ -57,6 +58,7 @@ void ItemList::add_icon_item(const Ref<Texture>& p_item,bool p_selectable){ item.selectable=p_selectable; item.selected=false; item.disabled=false; + item.tooltip_enabled=true; item.custom_bg=Color(0,0,0,0); items.push_back(item); @@ -82,6 +84,16 @@ String ItemList::get_item_text(int p_idx) const{ } +void ItemList::set_item_tooltip_enabled(int p_idx, const bool p_enabled) { + ERR_FAIL_INDEX(p_idx,items.size()); + items[p_idx].tooltip_enabled = p_enabled; +} + +bool ItemList::is_item_tooltip_enabled(int p_idx) const { + ERR_FAIL_INDEX_V(p_idx,items.size(), false); + return items[p_idx].tooltip_enabled; +} + void ItemList::set_item_tooltip(int p_idx,const String& p_tooltip){ ERR_FAIL_INDEX(p_idx,items.size()); @@ -1198,6 +1210,9 @@ String ItemList::get_tooltip(const Point2& p_pos) const { int closest = get_item_at_pos(p_pos); if (closest!=-1) { + if (!items[closest].tooltip_enabled) { + return ""; + } if (items[closest].tooltip!="") { return items[closest].tooltip; } @@ -1294,6 +1309,9 @@ void ItemList::_bind_methods(){ ObjectTypeDB::bind_method(_MD("set_item_custom_bg_color","idx","custom_bg_color"),&ItemList::set_item_custom_bg_color); ObjectTypeDB::bind_method(_MD("get_item_custom_bg_color","idx"),&ItemList::get_item_custom_bg_color); + ObjectTypeDB::bind_method(_MD("set_item_tooltip_enabled","idx","enable"),&ItemList::set_item_tooltip_enabled); + ObjectTypeDB::bind_method(_MD("is_item_tooltip_enabled","idx"),&ItemList::is_item_tooltip_enabled); + ObjectTypeDB::bind_method(_MD("set_item_tooltip","idx","tooltip"),&ItemList::set_item_tooltip); ObjectTypeDB::bind_method(_MD("get_item_tooltip","idx"),&ItemList::get_item_tooltip); @@ -1340,6 +1358,8 @@ void ItemList::_bind_methods(){ ObjectTypeDB::bind_method(_MD("ensure_current_is_visible"),&ItemList::ensure_current_is_visible); + ObjectTypeDB::bind_method(_MD("get_v_scroll"),&ItemList::get_v_scroll); + ObjectTypeDB::bind_method(_MD("_scroll_changed"),&ItemList::_scroll_changed); ObjectTypeDB::bind_method(_MD("_input_event"),&ItemList::_input_event); diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index e1902d1c1f..cb5908bc79 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -56,6 +56,7 @@ private: bool selectable; bool selected; bool disabled; + bool tooltip_enabled; Variant metadata; String tooltip; Color custom_bg; @@ -135,6 +136,9 @@ public: void set_item_tag_icon(int p_idx,const Ref<Texture>& p_tag_icon); Ref<Texture> get_item_tag_icon(int p_idx) const; + void set_item_tooltip_enabled(int p_idx, const bool p_enabled); + bool is_item_tooltip_enabled(int p_idx) const; + void set_item_tooltip(int p_idx,const String& p_tooltip); String get_item_tooltip(int p_idx) const; @@ -191,6 +195,8 @@ public: void set_icon_scale(real_t p_scale); real_t get_icon_scale() const; + VScrollBar *get_v_scroll() { return scroll_bar; } + ItemList(); ~ItemList(); }; diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index fcea12fd6b..90a8af9238 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -193,8 +193,8 @@ void LineEdit::_input_event(InputEvent p_event) { } set_cursor_pos(0); - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); + } @@ -215,8 +215,7 @@ void LineEdit::_input_event(InputEvent p_event) { selection_clear(); undo_text = text; text = text.substr(0,cursor_pos); - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); } } break; @@ -475,9 +474,7 @@ void LineEdit::_input_event(InputEvent p_event) { selection_delete(); CharType ucodestr[2]={(CharType)k.unicode,0}; append_at_cursor(ucodestr); - emit_signal("text_changed",text); - _change_notify("text"); - + _text_changed(); accept_event(); } @@ -725,8 +722,7 @@ void LineEdit::paste_text() { if(selection.enabled) selection_delete(); append_at_cursor(paste_buffer); - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); } @@ -750,9 +746,7 @@ void LineEdit::undo() { set_cursor_pos(old_cursor_pos); } - emit_signal("text_changed",text); - _change_notify("text"); - + _text_changed(); } void LineEdit::shift_selection_check_pre(bool p_shift) { @@ -806,16 +800,6 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) { pixel_ofs+=char_w; if (pixel_ofs > p_x) { //found what we look for - - - if ( (pixel_ofs-p_x) < (char_w >> 1 ) ) { - - ofs+=1; - } else if ( (pixel_ofs-p_x) > (char_w >> 1 ) ) { - - ofs-=1; - } - break; } @@ -891,8 +875,7 @@ void LineEdit::delete_char() { // set_window_pos(cursor_pos-get_window_length()); } - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); } void LineEdit::delete_text(int p_from_column, int p_to_column) { @@ -924,8 +907,7 @@ void LineEdit::delete_text(int p_from_column, int p_to_column) { window_pos=cursor_pos; } - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); } void LineEdit::set_text(String p_text) { @@ -940,8 +922,7 @@ void LineEdit::set_text(String p_text) { void LineEdit::clear() { clear_internal(); - emit_signal("text_changed",text); - _change_notify("text"); + _text_changed(); } String LineEdit::get_text() const { @@ -1080,7 +1061,17 @@ Size2 LineEdit::get_minimum_size() const { Size2 min=style->get_minimum_size(); min.height+=font->get_height(); - min.width+=get_constant("minimum_spaces")*font->get_char_size(' ').x; + + //minimum size of text + int space_size = font->get_char_size(' ').x; + int mstext = get_constant("minimum_spaces")*space_size; + + if (expand_to_text_length) { + mstext=MAX(mstext,font->get_string_size(text).x+space_size); //add a spce because some fonts are too exact + } + + min.width+=mstext; + return min; } @@ -1236,6 +1227,29 @@ PopupMenu *LineEdit::get_menu() const { } #endif + +void LineEdit::set_expand_to_text_length(bool p_enabled) { + + expand_to_text_length = p_enabled; + minimum_size_changed(); +} + +bool LineEdit::get_expand_to_text_length() const{ + + return expand_to_text_length; +} + + +void LineEdit::_text_changed() { + + if (expand_to_text_length) + minimum_size_changed(); + + emit_signal("text_changed",text); + _change_notify("text"); + +} + void LineEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("_toggle_draw_caret"),&LineEdit::_toggle_draw_caret); @@ -1258,7 +1272,9 @@ void LineEdit::_bind_methods() { ObjectTypeDB::bind_method(_MD("get_placeholder_alpha"),&LineEdit::get_placeholder_alpha); ObjectTypeDB::bind_method(_MD("set_cursor_pos","pos"),&LineEdit::set_cursor_pos); ObjectTypeDB::bind_method(_MD("get_cursor_pos"),&LineEdit::get_cursor_pos); - ObjectTypeDB::bind_method(_MD("cursor_set_blink_enabled", "enable"),&LineEdit::cursor_set_blink_enabled); + ObjectTypeDB::bind_method(_MD("set_expand_to_text_length","enabled"),&LineEdit::set_expand_to_text_length); + ObjectTypeDB::bind_method(_MD("get_expand_to_text_length"),&LineEdit::get_expand_to_text_length); + ObjectTypeDB::bind_method(_MD("cursor_set_blink_enabled", "enabled"),&LineEdit::cursor_set_blink_enabled); ObjectTypeDB::bind_method(_MD("cursor_get_blink_enabled"),&LineEdit::cursor_get_blink_enabled); ObjectTypeDB::bind_method(_MD("cursor_set_blink_speed", "blink_speed"),&LineEdit::cursor_set_blink_speed); ObjectTypeDB::bind_method(_MD("cursor_get_blink_speed"),&LineEdit::cursor_get_blink_speed); @@ -1296,6 +1312,7 @@ void LineEdit::_bind_methods() { ADD_PROPERTYNZ( PropertyInfo( Variant::INT, "max_length" ), _SCS("set_max_length"),_SCS("get_max_length") ); ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "editable" ), _SCS("set_editable"),_SCS("is_editable") ); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "secret" ), _SCS("set_secret"),_SCS("is_secret") ); + ADD_PROPERTYNO( PropertyInfo( Variant::BOOL, "expand_to_len" ), _SCS("set_expand_to_text_length"),_SCS("get_expand_to_text_length") ); ADD_PROPERTY( PropertyInfo( Variant::INT,"focus_mode", PROPERTY_HINT_ENUM, "None,Click,All" ), _SCS("set_focus_mode"), _SCS("get_focus_mode") ); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "caret/caret_blink"), _SCS("cursor_set_blink_enabled"), _SCS("cursor_get_blink_enabled"));; ADD_PROPERTYNZ(PropertyInfo(Variant::REAL, "caret/caret_blink_speed",PROPERTY_HINT_RANGE,"0.1,10,0.1"), _SCS("cursor_set_blink_speed"),_SCS("cursor_get_blink_speed") ); @@ -1337,7 +1354,7 @@ LineEdit::LineEdit() { menu->add_separator(); menu->add_item(TTR("Undo"),MENU_UNDO,KEY_MASK_CMD|KEY_Z); menu->connect("item_pressed",this,"menu_option"); - + expand_to_text_length=false; } diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 112e4ad55e..47d5706bbe 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -90,6 +90,11 @@ private: } selection; Timer *caret_blink_timer; + + + void _text_changed(); + bool expand_to_text_length; + bool caret_blink_enabled; bool draw_caret; bool window_has_focus; @@ -169,6 +174,9 @@ public: virtual Size2 get_minimum_size() const; + void set_expand_to_text_length(bool p_len); + bool get_expand_to_text_length() const; + virtual bool is_text_field() const; LineEdit(); ~LineEdit(); diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index d5d14ad649..3b9ca40bd8 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -47,12 +47,15 @@ void Slider::_input_event(InputEvent p_event) { if (mb.button_index==BUTTON_LEFT) { if (mb.pressed) { + Ref<Texture> grabber = get_icon(mouse_inside||has_focus()?"grabber_hilite":"grabber"); grab.pos=orientation==VERTICAL?mb.y:mb.x; - double max = orientation==VERTICAL ? get_size().height : get_size().width ; + double grab_width = (double)grabber->get_size().width; + double grab_height = (double)grabber->get_size().height; + double max = orientation==VERTICAL ? get_size().height - grab_height : get_size().width - grab_width; if (orientation==VERTICAL) - set_unit_value( 1 - ((double)grab.pos / max) ); + set_unit_value( 1 - (((double)grab.pos - (grab_height / 2.0)) / max) ); else - set_unit_value((double)grab.pos / max); + set_unit_value(((double)grab.pos - (grab_width/2.0)) / max); grab.active=true; grab.uvalue=get_unit_value(); } else { diff --git a/scene/gui/texture_progress.cpp b/scene/gui/texture_progress.cpp index 923a35031c..2c576b6ba5 100644 --- a/scene/gui/texture_progress.cpp +++ b/scene/gui/texture_progress.cpp @@ -297,6 +297,7 @@ void TextureProgress::_bind_methods() { TextureProgress::TextureProgress() { mode=FILL_LEFT_TO_RIGHT; + rad_init_angle=0; rad_center_off=Point2(); rad_max_degrees=360; } diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 487f62ed44..20794b2faa 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -171,6 +171,21 @@ String TreeItem::get_text(int p_column) const { } +void TreeItem::set_suffix(int p_column,String p_suffix) { + + ERR_FAIL_INDEX( p_column, cells.size() ); + cells[p_column].suffix=p_suffix; + + _changed_notify(p_column); + +} + +String TreeItem::get_suffix(int p_column) const { + + ERR_FAIL_INDEX_V( p_column, cells.size(), "" ); + return cells[p_column].suffix; + +} void TreeItem::set_icon(int p_column,const Ref<Texture>& p_icon) { @@ -927,8 +942,12 @@ void Tree::draw_item_rect(const TreeItem::Cell& p_cell,const Rect2i& p_rect,cons Ref<Font> font = cache.font; + String text = p_cell.text; + if (p_cell.suffix!=String()) + text+=" "+p_cell.suffix; + rect.pos.y+=Math::floor((rect.size.y-font->get_height())/2.0) +font->get_ascent(); - font->draw(ci,rect.pos,p_cell.text,p_color,rect.size.x); + font->draw(ci,rect.pos,text,p_color,rect.size.x); } @@ -1072,11 +1091,21 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& if (p_item->cells[i].selected && select_mode!=SELECT_ROW) { Rect2i r(item_rect.pos,item_rect.size); + if (p_item->cells[i].text.size() > 0){ + float icon_width = p_item->cells[i].get_icon_size().width; + r.pos.x += icon_width; + r.size.x -= icon_width; + } //r.grow(cache.selected->get_margin(MARGIN_LEFT)); - if (has_focus()) + if (has_focus()){ cache.selected_focus->draw(ci,r ); - else + p_item->set_meta("__focus_rect", Rect2(r.pos,r.size)); + } else { cache.selected->draw(ci,r ); + } + if (text_editor->is_visible()){ + text_editor->set_pos(get_global_pos() + r.pos); + } } if (p_item->cells[i].custom_bg_color) { @@ -1165,6 +1194,9 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& String s = p_item->cells[i].text; s=s.get_slicec(',',option); + if (p_item->cells[i].suffix!=String()) + s+=" "+p_item->cells[i].suffix; + Ref<Texture> downarrow = cache.select_arrow; font->draw(ci, text_pos, s, col,item_rect.size.x-downarrow->get_width() ); @@ -1181,6 +1213,10 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& String valtext = String::num( p_item->cells[i].val, Math::step_decimals( p_item->cells[i].step ) ); //String valtext = rtos( p_item->cells[i].val ); + + if (p_item->cells[i].suffix!=String()) + valtext+=" "+p_item->cells[i].suffix; + font->draw( ci, text_pos, valtext, col, item_rect.size.x-updown->get_width()); if (!p_item->cells[i].editable) @@ -2328,9 +2364,22 @@ void Tree::_input_event(InputEvent p_event) { range_drag_enabled=false; Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); warp_mouse(range_drag_capture_pos); - } else - edit_selected(); + } else { + if (delayed_text_editor) { + uint64_t diff = OS::get_singleton()->get_ticks_msec() - first_selection_time; + if (diff >= 400 && diff <= 800) + edit_selected(); + // fast double click + else if (diff < 400) { + emit_signal("item_double_clicked"); + } + + first_selection_time = OS::get_singleton()->get_ticks_msec(); + } else { + edit_selected(); + } + } pressing_for_editor=false; } @@ -2468,16 +2517,7 @@ bool Tree::edit_selected() { if (!s->cells[col].editable) return false; - Rect2 rect; - rect.pos.y = get_item_offset(s) - get_scroll().y; - - for(int i=0;i<col;i++) { - - rect.pos.x+=get_column_width(i); - } - - rect.size.width=get_column_width(col); - rect.size.height=compute_item_height(s)+cache.vseparation; + Rect2 rect = s->get_meta("__focus_rect"); popup_edited_item=s; popup_edited_item_col=col; @@ -2848,7 +2888,6 @@ void Tree::item_changed(int p_column,TreeItem *p_item) { void Tree::item_selected(int p_column,TreeItem *p_item) { - if (select_mode==SELECT_MULTI) { if (!p_item->cells[p_column].selectable) @@ -2856,8 +2895,11 @@ void Tree::item_selected(int p_column,TreeItem *p_item) { p_item->cells[p_column].selected=true; //emit_signal("multi_selected",p_item,p_column,true); - NO this is for TreeItem::select + if (delayed_text_editor) + first_selection_time = OS::get_singleton()->get_ticks_msec(); } else { + select_single_item(p_item,root,p_column); } update(); @@ -3128,7 +3170,7 @@ void Tree::ensure_cursor_is_visible() { int screenh=get_size().height-h_scroll->get_combined_minimum_size().height; if (ofs+h>v_scroll->get_val()+screenh) - v_scroll->set_val(ofs-screenh+h); + v_scroll->call_deferred("set_val", ofs-screenh+h); else if (ofs < v_scroll->get_val()) v_scroll->set_val(ofs); } @@ -3503,6 +3545,16 @@ bool Tree::get_allow_rmb_select() const{ return allow_rmb_select; } + +void Tree::set_delayed_text_editor(bool enabled) { + delayed_text_editor = enabled; +} + +bool Tree::is_delayed_text_editor_enabled() const { + return delayed_text_editor; +} + + void Tree::_bind_methods() { ObjectTypeDB::bind_method(_MD("_range_click_timeout"),&Tree::_range_click_timeout); @@ -3556,6 +3608,9 @@ void Tree::_bind_methods() { ObjectTypeDB::bind_method(_MD("set_allow_rmb_select","allow"),&Tree::set_allow_rmb_select); ObjectTypeDB::bind_method(_MD("get_allow_rmb_select"),&Tree::get_allow_rmb_select); + ObjectTypeDB::bind_method(_MD("set_delayed_text_editor","enable"),&Tree::set_delayed_text_editor); + ObjectTypeDB::bind_method(_MD("is_delayed_text_editor_enabled"),&Tree::is_delayed_text_editor_enabled); + ObjectTypeDB::bind_method(_MD("set_single_select_cell_editing_only_when_already_selected","enable"),&Tree::set_single_select_cell_editing_only_when_already_selected); ObjectTypeDB::bind_method(_MD("get_single_select_cell_editing_only_when_already_selected"),&Tree::get_single_select_cell_editing_only_when_already_selected); @@ -3566,6 +3621,7 @@ void Tree::_bind_methods() { ADD_SIGNAL( MethodInfo("item_rmb_selected",PropertyInfo(Variant::VECTOR2,"pos"))); ADD_SIGNAL( MethodInfo("empty_tree_rmb_selected",PropertyInfo(Variant::VECTOR2,"pos"))); ADD_SIGNAL( MethodInfo("item_edited")); + ADD_SIGNAL( MethodInfo("item_double_clicked")); ADD_SIGNAL( MethodInfo("item_collapsed",PropertyInfo(Variant::OBJECT,"item"))); //ADD_SIGNAL( MethodInfo("item_doubleclicked" ) ); ADD_SIGNAL( MethodInfo("button_pressed",PropertyInfo(Variant::OBJECT,"item"),PropertyInfo(Variant::INT,"column"),PropertyInfo(Variant::INT,"id"))); @@ -3669,6 +3725,9 @@ Tree::Tree() { force_select_on_already_selected=false; allow_rmb_select=false; + + first_selection_time = 0; + delayed_text_editor = false; } diff --git a/scene/gui/tree.h b/scene/gui/tree.h index f5100ab5b6..2124dce749 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -69,6 +69,7 @@ friend class Tree; Ref<Texture> icon; Rect2i icon_region; String text; + String suffix; double min,max,step,val; int icon_max_w; bool expr; @@ -168,6 +169,9 @@ public: void set_text(int p_column,String p_text); String get_text(int p_column) const; + void set_suffix(int p_column,String p_suffix); + String get_suffix(int p_column) const; + void set_icon(int p_column,const Ref<Texture>& p_icon); Ref<Texture> get_icon(int p_column) const; @@ -433,6 +437,9 @@ friend class TreeItem; float last_drag_time; float time_since_motion;*/ + bool delayed_text_editor; + uint64_t first_selection_time; + float drag_speed; float drag_from; float drag_accum; @@ -527,6 +534,9 @@ public: void set_value_evaluator(ValueEvaluator *p_evaluator); + void set_delayed_text_editor(bool enabled); + bool is_delayed_text_editor_enabled() const; + Tree(); ~Tree(); |