diff options
Diffstat (limited to 'scene')
28 files changed, 269 insertions, 153 deletions
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index 17e5503a2d..8864459dfb 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -1042,7 +1042,9 @@ void CanvasItem::_bind_methods() { ObjectTypeDB::bind_method(_MD("edit_rotate","degrees"),&CanvasItem::edit_rotate); ObjectTypeDB::bind_method(_MD("get_item_rect"),&CanvasItem::get_item_rect); + ObjectTypeDB::bind_method(_MD("get_item_and_children_rect"),&CanvasItem::get_item_and_children_rect); //ObjectTypeDB::bind_method(_MD("get_transform"),&CanvasItem::get_transform); + ObjectTypeDB::bind_method(_MD("get_canvas_item"),&CanvasItem::get_canvas_item); ObjectTypeDB::bind_method(_MD("is_visible"),&CanvasItem::is_visible); @@ -1195,6 +1197,23 @@ int CanvasItem::get_canvas_layer() const { return 0; } + +Rect2 CanvasItem::get_item_and_children_rect() const { + + Rect2 rect = get_item_rect(); + + + for(int i=0;i<get_child_count();i++) { + CanvasItem *c=get_child(i)->cast_to<CanvasItem>(); + if (c) { + Rect2 sir = c->get_transform().xform(c->get_item_and_children_rect()); + rect = rect.merge(sir); + } + } + + return rect; +} + CanvasItem::CanvasItem() : xform_change(this) { diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h index 05a2e725e9..d915f742ec 100644 --- a/scene/2d/canvas_item.h +++ b/scene/2d/canvas_item.h @@ -240,6 +240,8 @@ public: virtual Matrix32 get_global_transform() const; virtual Matrix32 get_global_transform_with_canvas() const; + Rect2 get_item_and_children_rect() const; + CanvasItem *get_toplevel() const; _FORCE_INLINE_ RID get_canvas_item() const { return canvas_item; } diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp index 6a9c655141..920e56130c 100644 --- a/scene/3d/spatial.cpp +++ b/scene/3d/spatial.cpp @@ -712,6 +712,15 @@ void Spatial::look_at(const Vector3& p_target, const Vector3& p_up_normal) { Transform lookat; lookat.origin=get_global_transform().origin; + if (lookat.origin==p_target) { + ERR_EXPLAIN("Node origin and target are in the same position, look_at() failed"); + ERR_FAIL(); + } + + if (p_up_normal.cross(p_target-lookat.origin)==Vector3()) { + ERR_EXPLAIN("Up vector and direction between node origin and target are aligned, look_at() failed"); + ERR_FAIL(); + } lookat=lookat.looking_at(p_target,p_up_normal); set_global_transform(lookat); } diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp index e35ba11e84..7d134a070e 100644 --- a/scene/3d/vehicle_body.cpp +++ b/scene/3d/vehicle_body.cpp @@ -990,7 +990,7 @@ float VehicleBody::get_steering() const{ return m_steeringValue; } -Vector3 VehicleBody::get_linear_velocity() +Vector3 VehicleBody::get_linear_velocity() const { return linear_velocity; } diff --git a/scene/3d/vehicle_body.h b/scene/3d/vehicle_body.h index b6ad88f15e..31c61ff99d 100644 --- a/scene/3d/vehicle_body.h +++ b/scene/3d/vehicle_body.h @@ -178,7 +178,7 @@ public: void set_steering(float p_steering); float get_steering() const; - Vector3 get_linear_velocity(); + Vector3 get_linear_velocity() const; VehicleBody(); }; diff --git a/scene/audio/sample_player.cpp b/scene/audio/sample_player.cpp index b4a237c60f..bcd4354975 100644 --- a/scene/audio/sample_player.cpp +++ b/scene/audio/sample_player.cpp @@ -290,7 +290,7 @@ void SamplePlayer::stop_all() { #define _GET_VOICE\ uint32_t voice=p_voice&0xFFFF;\ - ERR_FAIL_COND(voice > (uint32_t)voices.size());\ + ERR_FAIL_COND(voice >= (uint32_t)voices.size());\ Voice &v=voices[voice];\ if (v.check!=uint32_t(p_voice>>16))\ return;\ @@ -381,7 +381,7 @@ void SamplePlayer::set_reverb(VoiceID p_voice,ReverbRoomType p_room,float p_send #define _GET_VOICE_V(m_ret)\ uint32_t voice=p_voice&0xFFFF;\ - ERR_FAIL_COND_V(voice > (uint32_t)voices.size(),m_ret);\ + ERR_FAIL_COND_V(voice >= (uint32_t)voices.size(),m_ret);\ const Voice &v=voices[voice];\ if (v.check!=(p_voice>>16))\ return m_ret;\ diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 2200cac5da..bc498f47bc 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -418,8 +418,13 @@ void BaseButton::_unhandled_input(InputEvent p_event) { String BaseButton::get_tooltip(const Point2& p_pos) const { String tooltip=Control::get_tooltip(p_pos); - if (shortcut.is_valid() && shortcut->is_valid()) - tooltip+=" ("+shortcut->get_as_text()+")"; + if (shortcut.is_valid() && shortcut->is_valid()) { + if (tooltip.find("$sc")!=-1) { + tooltip=tooltip.replace_first("$sc","("+shortcut->get_as_text()+")"); + } else { + tooltip+=" ("+shortcut->get_as_text()+")"; + } + } return tooltip; } diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index bd56369746..666ac88055 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -223,7 +223,7 @@ bool Control::_get(const StringName& p_name,Variant &r_ret) const { String sname=p_name; - if (!sname.begins_with("custom")) + if (!sname.begins_with("custom")) { if (sname.begins_with("margin/")) { String dname = sname.get_slicec('/', 1); if (dname == "left") { @@ -248,6 +248,7 @@ bool Control::_get(const StringName& p_name,Variant &r_ret) const { } else { return false; } + } if (sname.begins_with("custom_icons/")) { String name = sname.get_slicec('/',1); @@ -436,11 +437,17 @@ void Control::_notification(int p_notification) { if (is_set_as_toplevel()) { data.SI=get_viewport()->_gui_add_subwindow_control(this); + + if (data.theme.is_null() && data.parent && data.parent->data.theme_owner) { + data.theme_owner=data.parent->data.theme_owner; + notification(NOTIFICATION_THEME_CHANGED); + } + } else { Node *parent=this; //meh - Node *parent_control=NULL; + Control *parent_control=NULL; bool subwindow=false; while(parent) { @@ -456,8 +463,9 @@ void Control::_notification(int p_notification) { break; } - if (parent->cast_to<Control>()) { - parent_control=parent->cast_to<Control>(); + parent_control=parent->cast_to<Control>(); + + if (parent_control) { break; } else if (ci) { @@ -469,6 +477,10 @@ void Control::_notification(int p_notification) { if (parent_control) { //do nothing, has a parent control + if (data.theme.is_null() && parent_control->data.theme_owner) { + data.theme_owner=parent_control->data.theme_owner; + notification(NOTIFICATION_THEME_CHANGED); + } } else if (subwindow) { //is a subwindow (process input before other controls for that canvas) data.SI=get_viewport()->_gui_add_subwindow_control(this); @@ -489,6 +501,10 @@ void Control::_notification(int p_notification) { } + if (data.theme.is_null() && data.parent && data.parent->data.theme_owner) { + data.theme_owner=data.parent->data.theme_owner; + notification(NOTIFICATION_THEME_CHANGED); + } } break; case NOTIFICATION_EXIT_CANVAS: { @@ -520,26 +536,9 @@ void Control::_notification(int p_notification) { data.parent=NULL; data.parent_canvas_item=NULL; - - } break; - - - case NOTIFICATION_PARENTED: { - - Control * parent = get_parent()->cast_to<Control>(); - - //make children reference them theme - - if (parent && data.theme.is_null() && parent->data.theme_owner) { - _propagate_theme_changed(parent->data.theme_owner); - } - - } break; - case NOTIFICATION_UNPARENTED: { - - //make children unreference the theme - if (data.theme.is_null() && data.theme_owner) { - _propagate_theme_changed(NULL); + if (data.theme_owner && data.theme.is_null()) { + data.theme_owner=NULL; + //notification(NOTIFICATION_THEME_CHANGED); } } break; @@ -785,7 +784,7 @@ Ref<Texture> Control::get_icon(const StringName& p_name,const StringName& p_type while(theme_owner) { if (theme_owner->data.theme->has_icon(p_name, type ) ) - return data.theme_owner->data.theme->get_icon(p_name, type ); + return theme_owner->data.theme->get_icon(p_name, type ); Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL; if (parent) @@ -815,7 +814,7 @@ Ref<Shader> Control::get_shader(const StringName& p_name,const StringName& p_typ while(theme_owner) { if (theme_owner->data.theme->has_shader(p_name, type)) - return data.theme_owner->data.theme->get_shader(p_name, type ); + return theme_owner->data.theme->get_shader(p_name, type ); Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL; if (parent) @@ -843,8 +842,9 @@ Ref<StyleBox> Control::get_stylebox(const StringName& p_name,const StringName& p while(theme_owner) { - if (theme_owner->data.theme->has_stylebox(p_name, type ) ) - return data.theme_owner->data.theme->get_stylebox(p_name, type ); + if (theme_owner->data.theme->has_stylebox(p_name, type ) ) { + return theme_owner->data.theme->get_stylebox(p_name, type ); + } Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL; if (parent) @@ -872,7 +872,7 @@ Ref<Font> Control::get_font(const StringName& p_name,const StringName& p_type) c while(theme_owner) { if (theme_owner->data.theme->has_font(p_name, type ) ) - return data.theme_owner->data.theme->get_font(p_name, type ); + return theme_owner->data.theme->get_font(p_name, type ); if (theme_owner->data.theme->get_default_theme_font().is_valid()) return theme_owner->data.theme->get_default_theme_font(); Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL; @@ -902,7 +902,7 @@ Color Control::get_color(const StringName& p_name,const StringName& p_type) cons while(theme_owner) { if (theme_owner->data.theme->has_color(p_name, type ) ) - return data.theme_owner->data.theme->get_color(p_name, type ); + return theme_owner->data.theme->get_color(p_name, type ); Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL; if (parent) @@ -931,7 +931,7 @@ int Control::get_constant(const StringName& p_name,const StringName& p_type) con while(theme_owner) { if (theme_owner->data.theme->has_constant(p_name, type ) ) - return data.theme_owner->data.theme->get_constant(p_name, type ); + return theme_owner->data.theme->get_constant(p_name, type ); Control *parent = theme_owner->get_parent()?theme_owner->get_parent()->cast_to<Control>():NULL; if (parent) @@ -1840,18 +1840,29 @@ void Control::_modal_stack_remove() { } -void Control::_propagate_theme_changed(Control *p_owner) { +void Control::_propagate_theme_changed(CanvasItem *p_at,Control *p_owner) { - for(int i=0;i<get_child_count();i++) { + Control *c = p_at->cast_to<Control>(); + + if (c && c!=p_owner && c->data.theme.is_valid()) // has a theme, this can't be propagated + return; + + for(int i=0;i<p_at->get_child_count();i++) { + + CanvasItem *child = p_at->get_child(i)->cast_to<CanvasItem>(); + if (child) { + _propagate_theme_changed(child,p_owner); + } - Control *child = get_child(i)->cast_to<Control>(); - if (child && child->data.theme.is_null()) //has no theme, propagate - child->_propagate_theme_changed(p_owner); } - data.theme_owner=p_owner; - _notification(NOTIFICATION_THEME_CHANGED); - update(); + + if (c) { + + c->data.theme_owner=p_owner; + c->_notification(NOTIFICATION_THEME_CHANGED); + c->update(); + } } void Control::set_theme(const Ref<Theme>& p_theme) { @@ -1860,15 +1871,15 @@ void Control::set_theme(const Ref<Theme>& p_theme) { data.theme=p_theme; if (!p_theme.is_null()) { - _propagate_theme_changed(this); + _propagate_theme_changed(this,this); } else { Control *parent = get_parent()?get_parent()->cast_to<Control>():NULL; if (parent && parent->data.theme_owner) { - _propagate_theme_changed(parent->data.theme_owner); + _propagate_theme_changed(this,parent->data.theme_owner); } else { - _propagate_theme_changed(NULL); + _propagate_theme_changed(this,NULL); } } diff --git a/scene/gui/control.h b/scene/gui/control.h index 59704ae29b..69ee41f180 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -169,7 +169,7 @@ private: float _get_range(int p_idx) const; float _s2a(float p_val, AnchorType p_anchor,float p_range) const; float _a2s(float p_val, AnchorType p_anchor,float p_range) const; - void _propagate_theme_changed(Control *p_owner); + void _propagate_theme_changed(CanvasItem *p_at, Control *p_owner); void _change_notify_margins(); void _update_minimum_size(); diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index fc4ab5f8ca..66e8fe10ff 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -384,27 +384,16 @@ ItemList::IconMode ItemList::get_icon_mode() const{ return icon_mode; } -void ItemList::set_min_icon_size(const Size2& p_size) { - min_icon_size=p_size; - update(); -} - -Size2 ItemList::get_min_icon_size() const { - - return min_icon_size; -} +void ItemList::set_fixed_icon_size(const Size2& p_size) { - -void ItemList::set_max_icon_size(const Size2& p_size) { - - max_icon_size=p_size; + fixed_icon_size=p_size; update(); } -Size2 ItemList::get_max_icon_size() const { +Size2 ItemList::get_fixed_icon_size() const { - return max_icon_size; + return fixed_icon_size; } Size2 ItemList::Item::get_icon_size() const { @@ -732,51 +721,21 @@ void ItemList::ensure_current_is_visible() { update(); } -static Size2 _adjust_to_max_size(Size2 p_size, Size2 p_max_size) { - - if (p_max_size.x<=0) - p_max_size.x=1e20; - if (p_max_size.y<=0) - p_max_size.y=1e20; - +static Rect2 _adjust_to_max_size(Size2 p_size, Size2 p_max_size) { - Size2 new_size; + Size2 size=p_max_size; + int tex_width = p_size.width * size.height / p_size.height; + int tex_height = size.height; - if (p_size.x > p_max_size.x) { - - new_size.width=p_max_size.x; - new_size.height=p_size.height * p_max_size.width / p_size.width; - - if (new_size.height > p_max_size.height) { - new_size=Size2(); //invalid - } + if (tex_width>size.width) { + tex_width=size.width; + tex_height=p_size.height * tex_width / p_size.width; } + int ofs_x=(size.width - tex_width)/2; + int ofs_y=(size.height - tex_height)/2; - if (p_size.y > p_max_size.y) { - - Size2 new_size2; - new_size2.height=p_max_size.y; - new_size2.width=p_size.width * p_max_size.height / p_size.height; - - if (new_size2.width < p_max_size.width) { - - if (new_size!=Size2()) { - - if (new_size2.x*new_size2.y > new_size.x*new_size.y) { - new_size=new_size2; - } - } else { - new_size=new_size2; - } - } - - } - - if (new_size==Size2()) - return p_size; - else - return new_size; + return Rect2(ofs_x,ofs_y,tex_width,tex_height); } @@ -845,7 +804,11 @@ void ItemList::_notification(int p_what) { Size2 minsize; if (items[i].icon.is_valid()) { - minsize=_adjust_to_max_size(items[i].get_icon_size(),max_icon_size) * icon_scale; + if (fixed_icon_size.x>0 && fixed_icon_size.y>0) { + minsize=fixed_icon_size* icon_scale; + } else { + minsize=items[i].get_icon_size() *icon_scale; + } if (items[i].text!="") { if (icon_mode==ICON_MODE_TOP) { @@ -1001,13 +964,18 @@ void ItemList::_notification(int p_what) { Vector2 text_ofs; if (items[i].icon.is_valid()) { - Size2 icon_size = _adjust_to_max_size(items[i].get_icon_size(),max_icon_size) * icon_scale; + Size2 icon_size; + //= _adjust_to_max_size(items[i].get_icon_size(),fixed_icon_size) * icon_scale; + + if (fixed_icon_size.x>0 && fixed_icon_size.y>0) { + icon_size=fixed_icon_size* icon_scale; + } else { + icon_size=items[i].get_icon_size() *icon_scale; - Vector2 icon_ofs; - if (min_icon_size!=Vector2()) { - icon_ofs = (min_icon_size - icon_size)/2; } + Vector2 icon_ofs; + Point2 pos = items[i].rect_cache.pos + icon_ofs + base_ofs; if (icon_mode==ICON_MODE_TOP) { @@ -1017,18 +985,26 @@ void ItemList::_notification(int p_what) { Math::floor((items[i].rect_cache.size.height - icon_size.height)/2), items[i].rect_cache.size.height - items[i].min_rect_cache.size.height ); - text_ofs.y = MAX(icon_size.height, min_icon_size.y) + icon_margin; + text_ofs.y = icon_size.height + icon_margin; text_ofs.y += items[i].rect_cache.size.height - items[i].min_rect_cache.size.height; } else { pos.y += Math::floor((items[i].rect_cache.size.height - icon_size.height)/2); - text_ofs.x = MAX(icon_size.width, min_icon_size.x) + icon_margin; + text_ofs.x = icon_size.width + icon_margin; + } + + Rect2 draw_rect=Rect2(pos,icon_size); + + if (fixed_icon_size.x>0 && fixed_icon_size.y>0) { + Rect2 adj = _adjust_to_max_size(items[i].get_icon_size() * icon_scale,icon_size); + draw_rect.pos+=adj.pos; + draw_rect.size=adj.size; } if (items[i].icon_region.has_no_area()) - draw_texture_rect(items[i].icon, Rect2(pos,icon_size) ); + draw_texture_rect(items[i].icon, draw_rect ); else - draw_texture_rect_region(items[i].icon, Rect2(pos, icon_size), items[i].icon_region); + draw_texture_rect_region(items[i].icon, draw_rect, items[i].icon_region); } @@ -1298,11 +1274,9 @@ void ItemList::_bind_methods(){ ObjectTypeDB::bind_method(_MD("set_icon_mode","mode"),&ItemList::set_icon_mode); ObjectTypeDB::bind_method(_MD("get_icon_mode"),&ItemList::get_icon_mode); - ObjectTypeDB::bind_method(_MD("set_min_icon_size","size"),&ItemList::set_min_icon_size); - ObjectTypeDB::bind_method(_MD("get_min_icon_size"),&ItemList::get_min_icon_size); - ObjectTypeDB::bind_method(_MD("set_max_icon_size","size"),&ItemList::set_max_icon_size); - ObjectTypeDB::bind_method(_MD("get_max_icon_size"),&ItemList::get_max_icon_size); + ObjectTypeDB::bind_method(_MD("set_fixed_icon_size","size"),&ItemList::set_fixed_icon_size); + ObjectTypeDB::bind_method(_MD("get_fixed_icon_size"),&ItemList::get_fixed_icon_size); ObjectTypeDB::bind_method(_MD("set_icon_scale","scale"),&ItemList::set_icon_scale); ObjectTypeDB::bind_method(_MD("get_icon_scale"),&ItemList::get_icon_scale); diff --git a/scene/gui/item_list.h b/scene/gui/item_list.h index 087c585128..a4909205ef 100644 --- a/scene/gui/item_list.h +++ b/scene/gui/item_list.h @@ -62,8 +62,7 @@ private: int max_text_lines; int max_columns; - Size2 min_icon_size; - Size2 max_icon_size; + Size2 fixed_icon_size; Size2 max_item_size_cache; @@ -75,6 +74,8 @@ private: void _scroll_changed(double); void _input_event(const InputEvent& p_event); + + protected: void _notification(int p_what); @@ -144,11 +145,8 @@ public: void set_icon_mode(IconMode p_mode); IconMode get_icon_mode() const; - void set_min_icon_size(const Size2& p_size); - Size2 get_min_icon_size() const; - - void set_max_icon_size(const Size2& p_size); - Size2 get_max_icon_size() const; + void set_fixed_icon_size(const Size2& p_size); + Size2 get_fixed_icon_size() const; void set_allow_rmb_select(bool p_allow); bool get_allow_rmb_select() const; diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 2a4e82a8e7..ab556ede0c 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -731,14 +731,21 @@ void LineEdit::set_cursor_pos(int p_pos) { int width_to_cursor=0; int wp=window_pos; - if (font != NULL) { - for (int i=window_pos;i<cursor_pos;i++) - width_to_cursor+=font->get_char_size( text[i] ).width; + if (font.is_valid()) { + + int accum_width=0; + + for(int i=cursor_pos;i>=window_pos;i--) { - while (width_to_cursor >= window_width && wp < text.length()) { + if (i>=text.length()) { + accum_width=font->get_char_size(' ').width; //anything should do + } else { + accum_width+=font->get_char_size(text[i],i+1<text.length()?text[i+1]:0).width; //anything should do + } + if (accum_width>=window_width) + break; - width_to_cursor -= font->get_char_size(text[wp]).width; - wp++; + wp=i; } } diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 98bc0b9434..786ce27a0c 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -278,6 +278,11 @@ if (m_height > line_height) {\ if (c[end]=='\t') { cw=tab_size*font->get_char_size(' ').width; } + + if (end>0 && w+cw+begin > p_width ) { + break; //don't allow lines longer than assigned width + } + w+=cw; if (c[end]==' ') { @@ -340,10 +345,12 @@ if (m_height > line_height) {\ int cw=font->get_char_size(c[i],c[i+1]).x; + if (c[i]=='\t') { cw=tab_size*font->get_char_size(' ').width; } + if (p_click_pos.x-cw/2>p_ofs.x+align_ofs+pofs) { rchar=int((&c[i])-cf); @@ -374,6 +381,8 @@ if (m_height > line_height) {\ int cw=0; bool visible = visible_characters<0 || p_char_count<visible_characters; + if (c[i]=='\t') + visible=false; if (selected) { diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index d22f6a0229..6b36a60ea2 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -351,7 +351,7 @@ void SplitContainer::_input_event(const InputEvent& p_event) { } -Control::CursorShape SplitContainer::get_cursor_shape(const Point2& p_pos) { +Control::CursorShape SplitContainer::get_cursor_shape(const Point2& p_pos) const { if (collapsed) return Control::get_cursor_shape(p_pos); diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h index f721d16310..d2dc42165e 100644 --- a/scene/gui/split_container.h +++ b/scene/gui/split_container.h @@ -75,7 +75,7 @@ public: void set_dragger_visibility(DraggerVisibility p_visibility); DraggerVisibility get_dragger_visibility() const; - virtual CursorShape get_cursor_shape(const Point2& p_pos=Point2i()); + virtual CursorShape get_cursor_shape(const Point2& p_pos=Point2i()) const; virtual Size2 get_minimum_size() const; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 3e374ef888..49d7527786 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -2892,7 +2892,7 @@ int TextEdit::get_char_count() { return totalsize; // omit last \n } -Size2 TextEdit::get_minimum_size() { +Size2 TextEdit::get_minimum_size() const { return cache.style_normal->get_minimum_size(); } @@ -3825,12 +3825,16 @@ void TextEdit::undo() { _do_text_op(op, true); current_op.version=op.prev_version; if(undo_stack_pos->get().chain_backward) { - do { + while(true) { + ERR_BREAK(!undo_stack_pos->prev()); undo_stack_pos = undo_stack_pos->prev(); op = undo_stack_pos->get(); _do_text_op(op, true); current_op.version = op.prev_version; - } while(!undo_stack_pos->get().chain_forward); + if (undo_stack_pos->get().chain_forward) { + break; + } + } } cursor_set_line(undo_stack_pos->get().from_line); @@ -3849,12 +3853,16 @@ void TextEdit::redo() { _do_text_op(op, false); current_op.version = op.version; if(undo_stack_pos->get().chain_forward) { - do { + + while(true) { + ERR_BREAK(!undo_stack_pos->next()); undo_stack_pos=undo_stack_pos->next(); op = undo_stack_pos->get(); _do_text_op(op, false); current_op.version = op.version; - } while(!undo_stack_pos->get().chain_backward); + if (undo_stack_pos->get().chain_backward) + break; + } } cursor_set_line(undo_stack_pos->get().to_line); cursor_set_column(undo_stack_pos->get().to_column); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 24a72afd48..22f024c491 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -278,7 +278,7 @@ class TextEdit : public Control { void _scroll_lines_down(); // void mouse_motion(const Point& p_pos, const Point& p_rel, int p_button_mask); - Size2 get_minimum_size(); + Size2 get_minimum_size() const; int get_row_height() const; diff --git a/scene/gui/texture_frame.cpp b/scene/gui/texture_frame.cpp index 2fe8735fda..143f0e83b8 100644 --- a/scene/gui/texture_frame.cpp +++ b/scene/gui/texture_frame.cpp @@ -60,6 +60,29 @@ void TextureFrame::_notification(int p_what) { Vector2 ofs = (get_size() - texture->get_size())/2; draw_texture_rect(texture,Rect2(ofs,texture->get_size()),false,modulate); } break; + case STRETCH_KEEP_ASPECT_CENTERED: + case STRETCH_KEEP_ASPECT: { + + Size2 size=get_size(); + int tex_width = texture->get_width() * size.height / texture ->get_height(); + int tex_height = size.height; + + if (tex_width>size.width) { + tex_width=size.width; + tex_height=texture->get_height() * tex_width / texture->get_width(); + } + + int ofs_x = 0; + int ofs_y = 0; + + if (stretch_mode==STRETCH_KEEP_ASPECT_CENTERED) { + ofs_x+=(size.width - tex_width)/2; + ofs_y+=(size.height - tex_height)/2; + } + + draw_texture_rect(texture,Rect2(ofs_x,ofs_y,tex_width,tex_height)); + } break; + } @@ -104,13 +127,16 @@ void TextureFrame::_bind_methods() { ADD_PROPERTYNZ( PropertyInfo( Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), _SCS("set_texture"),_SCS("get_texture") ); ADD_PROPERTYNO( PropertyInfo( Variant::COLOR, "modulate"), _SCS("set_modulate"),_SCS("get_modulate") ); ADD_PROPERTYNZ( PropertyInfo( Variant::BOOL, "expand" ), _SCS("set_expand"),_SCS("has_expand") ); - ADD_PROPERTYNO( PropertyInfo( Variant::INT, "stretch_mode",PROPERTY_HINT_ENUM,"Scale On Expand (Compat),Scale,Tile,Keep,Keep Centered"), _SCS("set_stretch_mode"),_SCS("get_stretch_mode") ); + ADD_PROPERTYNO( PropertyInfo( Variant::INT, "stretch_mode",PROPERTY_HINT_ENUM,"Scale On Expand (Compat),Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered"), _SCS("set_stretch_mode"),_SCS("get_stretch_mode") ); BIND_CONSTANT( STRETCH_SCALE_ON_EXPAND ); BIND_CONSTANT( STRETCH_SCALE ); BIND_CONSTANT( STRETCH_TILE ); BIND_CONSTANT( STRETCH_KEEP ); BIND_CONSTANT( STRETCH_KEEP_CENTERED ); + BIND_CONSTANT( STRETCH_KEEP_ASPECT ); + BIND_CONSTANT( STRETCH_KEEP_ASPECT_CENTERED ); + } diff --git a/scene/gui/texture_frame.h b/scene/gui/texture_frame.h index a4acf588ea..0b47202532 100644 --- a/scene/gui/texture_frame.h +++ b/scene/gui/texture_frame.h @@ -43,6 +43,9 @@ public: STRETCH_TILE, STRETCH_KEEP, STRETCH_KEEP_CENTERED, + STRETCH_KEEP_ASPECT, + STRETCH_KEEP_ASPECT_CENTERED, + }; private: bool expand; diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 2c39aea08c..08fe847a33 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1186,7 +1186,8 @@ int Tree::draw_item(const Point2i& p_pos,const Point2& p_draw_ofs, const Size2& Ref<Texture> updown = cache.updown; - String valtext = String::num( p_item->cells[i].val, Math::decimals( p_item->cells[i].step ) ); + //String valtext = String::num( p_item->cells[i].val, Math::decimals( p_item->cells[i].step ) ); + String valtext = rtos( p_item->cells[i].val ); font->draw( ci, text_pos, valtext, col, item_rect.size.x-updown->get_width()); if (!p_item->cells[i].editable) diff --git a/scene/main/node.cpp b/scene/main/node.cpp index f8af83e23b..50b0fe224e 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -283,7 +283,11 @@ void Node::move_child(Node *p_child,int p_pos) { ERR_FAIL_INDEX( p_pos, data.children.size()+1 ); ERR_EXPLAIN("child is not a child of this node."); ERR_FAIL_COND(p_child->data.parent!=this); - ERR_FAIL_COND(data.blocked>0); + if (data.blocked>0) { + ERR_EXPLAIN("Parent node is busy setting up children, move_child() failed. Consider using call_deferred(\"move_child\") instead (or \"popup\" if this is from a popup)."); + ERR_FAIL_COND(data.blocked>0); + } + data.children.remove( p_child->data.pos ); data.children.insert( p_pos, p_child ); @@ -739,6 +743,12 @@ void Node::add_child(Node *p_child, bool p_legible_unique_name) { } ERR_EXPLAIN("Can't add child, already has a parent"); ERR_FAIL_COND( p_child->data.parent ); + + if (data.blocked>0) { + ERR_EXPLAIN("Parent node is busy setting up children, add_node() failed. Consider using call_deferred(\"add_child\",child) instead."); + ERR_FAIL_COND(data.blocked>0); + } + ERR_EXPLAIN("Can't add child while a notification is happening"); ERR_FAIL_COND( data.blocked > 0 ); @@ -800,7 +810,10 @@ void Node::_propagate_validate_owner() { void Node::remove_child(Node *p_child) { ERR_FAIL_NULL(p_child); - ERR_FAIL_COND( data.blocked > 0 ); + if (data.blocked>0) { + ERR_EXPLAIN("Parent node is busy setting up children, remove_node() failed. Consider using call_deferred(\"remove_child\",child) instead."); + ERR_FAIL_COND(data.blocked>0); + } int idx=-1; for (int i=0;i<data.children.size();i++) { @@ -1770,6 +1783,8 @@ void Node::replace_by(Node* p_node,bool p_keep_data) { } } + _replace_connections_target(p_node); + if (data.owner) { for(int i=0;i<get_child_count();i++) find_owned_by(data.owner,get_child(i),&owned_by_owner); @@ -1808,6 +1823,20 @@ void Node::replace_by(Node* p_node,bool p_keep_data) { } +void Node::_replace_connections_target(Node* p_new_target) { + + List<Connection> cl; + get_signals_connected_to_this(&cl); + + for(List<Connection>::Element *E=cl.front();E;E=E->next()) { + + Connection &c=E->get(); + + c.source->disconnect(c.signal,this,c.method); + c.source->connect(c.signal,p_new_target,c.method,c.binds,c.flags); + } +} + Vector<Variant> Node::make_binds(VARIANT_ARG_DECLARE) { diff --git a/scene/main/node.h b/scene/main/node.h index d099f6e773..a3b8d8de81 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -121,7 +121,7 @@ private: Node *_get_node(const NodePath& p_path) const; Node *_get_child_by_name(const StringName& p_name) const; - + void _replace_connections_target(Node* p_new_target); void _validate_child_name(Node *p_name, bool p_force_human_readable=false); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index aef53ea230..79502c74ce 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -500,7 +500,7 @@ void Viewport::_notification(int p_what) { - if (physics_object_picking) { + if (physics_object_picking && (render_target || Input::get_singleton()->get_mouse_mode()!=Input::MOUSE_MODE_CAPTURED)) { Vector2 last_pos(1e20,1e20); CollisionObject *last_object; diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index 78a5571bf0..1edae01754 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -573,7 +573,11 @@ DynamicFontAtSize::~DynamicFontAtSize(){ void DynamicFont::set_font_data(const Ref<DynamicFontData>& p_data) { data=p_data; - data_at_size=data->_get_dynamic_font_at_size(size); + if (data.is_valid()) + data_at_size=data->_get_dynamic_font_at_size(size); + else + data_at_size=Ref<DynamicFontAtSize>(); + emit_changed(); } diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 5df22ba8cc..5ac7946391 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -545,9 +545,19 @@ https://github.com/godotengine/godot/issues/3127 } #endif - if (exists && bool(Variant::evaluate(Variant::OP_EQUAL,value,original))) { - //exists and did not change - continue; + if (exists) { + + //check if already exists and did not change + if (value.get_type()==Variant::REAL && original.get_type()==Variant::REAL) { + //this must be done because, as some scenes save as text, there might be a tiny difference in floats due to numerical error + float a = value; + float b = original; + + if (Math::abs(a-b)<CMP_EPSILON) + continue; + } else if (bool(Variant::evaluate(Variant::OP_EQUAL,value,original))) { + continue; + } } if (!exists && isdefault) { diff --git a/scene/resources/room.cpp b/scene/resources/room.cpp index 4024e2f45c..d1fc614c90 100644 --- a/scene/resources/room.cpp +++ b/scene/resources/room.cpp @@ -31,7 +31,7 @@ #include "servers/visual_server.h" -RID RoomBounds::get_rid() { +RID RoomBounds::get_rid() const { return area; } diff --git a/scene/resources/room.h b/scene/resources/room.h index a9f159cd46..3ed41a3e61 100644 --- a/scene/resources/room.h +++ b/scene/resources/room.h @@ -50,7 +50,7 @@ protected: public: - virtual RID get_rid(); + virtual RID get_rid() const; void set_bounds( const BSP_Tree& p_bounds ); BSP_Tree get_bounds() const; diff --git a/scene/resources/theme.cpp b/scene/resources/theme.cpp index 8d0aedbf93..2f4d37053e 100644 --- a/scene/resources/theme.cpp +++ b/scene/resources/theme.cpp @@ -240,7 +240,7 @@ Ref<Texture> Theme::get_icon(const StringName& p_name,const StringName& p_type) bool Theme::has_icon(const StringName& p_name,const StringName& p_type) const { - return (icon_map.has(p_type) && icon_map[p_type].has(p_name)); + return (icon_map.has(p_type) && icon_map[p_type].has(p_name) && icon_map[p_type][p_name].is_valid()); } @@ -337,12 +337,13 @@ Ref<StyleBox> Theme::get_stylebox(const StringName& p_name,const StringName& p_t return style_map[p_type][p_name]; } else { return default_style; + } } bool Theme::has_stylebox(const StringName& p_name,const StringName& p_type) const { - return (style_map.has(p_type) && style_map[p_type].has(p_name) ); + return (style_map.has(p_type) && style_map[p_type].has(p_name) && style_map[p_type][p_name].is_valid()); } void Theme::clear_stylebox(const StringName& p_name,const StringName& p_type) { @@ -402,7 +403,7 @@ Ref<Font> Theme::get_font(const StringName& p_name,const StringName& p_type) con bool Theme::has_font(const StringName& p_name,const StringName& p_type) const { - return (font_map.has(p_type) && font_map[p_type].has(p_name)); + return (font_map.has(p_type) && font_map[p_type].has(p_name) && font_map[p_type][p_name].is_valid()); } void Theme::clear_font(const StringName& p_name,const StringName& p_type) { |