summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/canvas_item.cpp19
-rw-r--r--scene/2d/canvas_item.h2
-rw-r--r--scene/3d/spatial.cpp9
-rw-r--r--scene/3d/vehicle_body.cpp2
-rw-r--r--scene/3d/vehicle_body.h2
-rw-r--r--scene/audio/sample_player.cpp4
-rw-r--r--scene/gui/base_button.cpp9
-rw-r--r--scene/gui/control.cpp95
-rw-r--r--scene/gui/control.h2
-rw-r--r--scene/gui/item_list.cpp110
-rw-r--r--scene/gui/item_list.h12
-rw-r--r--scene/gui/line_edit.cpp19
-rw-r--r--scene/gui/rich_text_label.cpp9
-rw-r--r--scene/gui/split_container.cpp2
-rw-r--r--scene/gui/split_container.h2
-rw-r--r--scene/gui/text_edit.cpp18
-rw-r--r--scene/gui/text_edit.h2
-rw-r--r--scene/gui/texture_frame.cpp28
-rw-r--r--scene/gui/texture_frame.h3
-rw-r--r--scene/gui/tree.cpp3
-rw-r--r--scene/main/node.cpp33
-rw-r--r--scene/main/node.h2
-rw-r--r--scene/main/viewport.cpp2
-rw-r--r--scene/resources/dynamic_font.cpp6
-rw-r--r--scene/resources/packed_scene.cpp16
-rw-r--r--scene/resources/room.cpp2
-rw-r--r--scene/resources/room.h2
-rw-r--r--scene/resources/theme.cpp7
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) {