summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/tile_map.cpp33
-rw-r--r--scene/2d/tile_map.h6
-rw-r--r--scene/gui/button.cpp26
-rw-r--r--scene/gui/button.h2
-rw-r--r--scene/gui/check_box.cpp43
-rw-r--r--scene/gui/check_box.h2
-rw-r--r--scene/gui/check_button.cpp36
-rw-r--r--scene/gui/check_button.h1
-rw-r--r--scene/gui/control.cpp11
-rw-r--r--scene/gui/control.h5
-rw-r--r--scene/gui/menu_button.cpp1
-rw-r--r--scene/gui/option_button.cpp1
-rw-r--r--scene/gui/popup_menu.cpp95
-rw-r--r--scene/gui/popup_menu.h17
-rw-r--r--scene/gui/rich_text_label.cpp2
-rw-r--r--scene/gui/rich_text_label.h4
-rw-r--r--scene/main/viewport.cpp11
-rw-r--r--scene/resources/default_theme/default_theme.cpp10
-rw-r--r--scene/resources/sky_box.cpp4
-rw-r--r--scene/resources/tile_set.cpp4
20 files changed, 233 insertions, 81 deletions
diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp
index 5a32a3d0f0..1e34372d1e 100644
--- a/scene/2d/tile_map.cpp
+++ b/scene/2d/tile_map.cpp
@@ -28,6 +28,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "tile_map.h"
+
#include "io/marshalls.h"
#include "method_bind_ext.gen.inc"
#include "os/os.h"
@@ -169,10 +170,12 @@ void TileMap::set_cell_size(Size2 p_size) {
_recreate_quadrants();
emit_signal("settings_changed");
}
+
Size2 TileMap::get_cell_size() const {
return cell_size;
}
+
void TileMap::set_quadrant_size(int p_size) {
ERR_FAIL_COND(p_size < 1);
@@ -182,32 +185,12 @@ void TileMap::set_quadrant_size(int p_size) {
_recreate_quadrants();
emit_signal("settings_changed");
}
+
int TileMap::get_quadrant_size() const {
return quadrant_size;
}
-void TileMap::set_center_x(bool p_enable) {
-
- center_x = p_enable;
- _recreate_quadrants();
- emit_signal("settings_changed");
-}
-bool TileMap::get_center_x() const {
-
- return center_x;
-}
-void TileMap::set_center_y(bool p_enable) {
-
- center_y = p_enable;
- _recreate_quadrants();
- emit_signal("settings_changed");
-}
-bool TileMap::get_center_y() const {
-
- return center_y;
-}
-
void TileMap::_fix_cell_transform(Transform2D &xform, const Cell &p_cell, const Vector2 &p_offset, const Size2 &p_sc) {
Size2 s = p_sc;
@@ -1473,12 +1456,6 @@ void TileMap::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_tile_origin", "origin"), &TileMap::set_tile_origin);
ClassDB::bind_method(D_METHOD("get_tile_origin"), &TileMap::get_tile_origin);
- ClassDB::bind_method(D_METHOD("set_center_x", "enable"), &TileMap::set_center_x);
- ClassDB::bind_method(D_METHOD("get_center_x"), &TileMap::get_center_x);
-
- ClassDB::bind_method(D_METHOD("set_center_y", "enable"), &TileMap::set_center_y);
- ClassDB::bind_method(D_METHOD("get_center_y"), &TileMap::get_center_y);
-
ClassDB::bind_method(D_METHOD("set_clip_uv", "enable"), &TileMap::set_clip_uv);
ClassDB::bind_method(D_METHOD("get_clip_uv"), &TileMap::get_clip_uv);
@@ -1580,8 +1557,6 @@ TileMap::TileMap() {
quadrant_order_dirty = false;
quadrant_size = 16;
cell_size = Size2(64, 64);
- center_x = false;
- center_y = false;
collision_layer = 1;
collision_mask = 1;
friction = 1;
diff --git a/scene/2d/tile_map.h b/scene/2d/tile_map.h
index 11d9915cb6..e5608884c4 100644
--- a/scene/2d/tile_map.h
+++ b/scene/2d/tile_map.h
@@ -68,7 +68,6 @@ private:
Ref<TileSet> tile_set;
Size2i cell_size;
int quadrant_size;
- bool center_x, center_y;
Mode mode;
Transform2D custom_transform;
HalfOffset half_offset;
@@ -231,11 +230,6 @@ public:
void set_quadrant_size(int p_size);
int get_quadrant_size() const;
- void set_center_x(bool p_enable);
- bool get_center_x() const;
- void set_center_y(bool p_enable);
- bool get_center_y() const;
-
void set_cell(int p_x, int p_y, int p_tile, bool p_flip_x = false, bool p_flip_y = false, bool p_transpose = false, Vector2 p_autotile_coord = Vector2());
int get_cell(int p_x, int p_y) const;
bool is_cell_x_flipped(int p_x, int p_y) const;
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index 1fa03f81f4..47977f0283 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -55,6 +55,10 @@ Size2 Button::get_minimum_size() const {
return get_stylebox("normal")->get_minimum_size() + minsize;
}
+void Button::_set_internal_margin(Margin p_margin, float p_value) {
+ _internal_margin[p_margin] = p_value;
+}
+
void Button::_notification(int p_what) {
if (p_what == NOTIFICATION_TRANSLATION_CHANGED) {
@@ -136,11 +140,11 @@ void Button::_notification(int p_what) {
Point2 icon_ofs = (!_icon.is_null()) ? Point2(_icon->get_width() + get_constant("hseparation"), 0) : Point2();
int text_clip = size.width - style->get_minimum_size().width - icon_ofs.width;
- Point2 text_ofs = (size - style->get_minimum_size() - icon_ofs - font->get_string_size(xl_text)) / 2.0;
+ Point2 text_ofs = (size - style->get_minimum_size() - icon_ofs - font->get_string_size(xl_text) - Point2(_internal_margin[MARGIN_RIGHT] - _internal_margin[MARGIN_LEFT], 0)) / 2.0;
switch (align) {
case ALIGN_LEFT: {
- text_ofs.x = style->get_margin(MARGIN_LEFT) + icon_ofs.x;
+ text_ofs.x = style->get_margin(MARGIN_LEFT) + icon_ofs.x + _internal_margin[MARGIN_LEFT] + get_constant("hseparation");
text_ofs.y += style->get_offset().y;
} break;
case ALIGN_CENTER: {
@@ -150,7 +154,11 @@ void Button::_notification(int p_what) {
text_ofs += style->get_offset();
} break;
case ALIGN_RIGHT: {
- text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - font->get_string_size(xl_text).x;
+ if (_internal_margin[MARGIN_RIGHT] > 0) {
+ text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - font->get_string_size(xl_text).x - _internal_margin[MARGIN_RIGHT] - get_constant("hseparation");
+ } else {
+ text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - font->get_string_size(xl_text).x;
+ }
text_ofs.y += style->get_offset().y;
} break;
}
@@ -162,7 +170,11 @@ void Button::_notification(int p_what) {
int valign = size.height - style->get_minimum_size().y;
if (is_disabled())
color_icon.a = 0.4;
- _icon->draw(ci, style->get_offset() + Point2(0, Math::floor((valign - _icon->get_height()) / 2.0)), color_icon);
+ if (_internal_margin[MARGIN_LEFT] > 0) {
+ _icon->draw(ci, style->get_offset() + Point2(_internal_margin[MARGIN_LEFT] + get_constant("hseparation"), Math::floor((valign - _icon->get_height()) / 2.0)), color_icon);
+ } else {
+ _icon->draw(ci, style->get_offset() + Point2(0, Math::floor((valign - _icon->get_height()) / 2.0)), color_icon);
+ }
}
}
}
@@ -253,7 +265,7 @@ void Button::_bind_methods() {
ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "icon", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_button_icon", "get_button_icon");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "flat"), "set_flat", "is_flat");
ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "clip_text"), "set_clip_text", "get_clip_text");
- ADD_PROPERTYNO(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_text_align", "get_text_align");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "align", PROPERTY_HINT_ENUM, "Left,Center,Right"), "set_text_align", "get_text_align");
}
Button::Button(const String &p_text) {
@@ -263,6 +275,10 @@ Button::Button(const String &p_text) {
set_mouse_filter(MOUSE_FILTER_STOP);
set_text(p_text);
align = ALIGN_CENTER;
+
+ for (int i = 0; i < 4; i++) {
+ _internal_margin[i] = 0;
+ }
}
Button::~Button() {
diff --git a/scene/gui/button.h b/scene/gui/button.h
index dd6e730b86..35488582de 100644
--- a/scene/gui/button.h
+++ b/scene/gui/button.h
@@ -53,9 +53,11 @@ private:
Ref<Texture> icon;
bool clip_text;
TextAlign align;
+ float _internal_margin[4];
protected:
virtual Size2 get_minimum_size() const;
+ void _set_internal_margin(Margin p_margin, float p_value);
void _notification(int p_what);
static void _bind_methods();
diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp
index 00f6153062..bf8156b92b 100644
--- a/scene/gui/check_box.cpp
+++ b/scene/gui/check_box.cpp
@@ -31,18 +31,54 @@
#include "servers/visual_server.h"
+Size2 CheckBox::get_icon_size() const {
+ Ref<Texture> checked = Control::get_icon("checked");
+ Ref<Texture> unchecked = Control::get_icon("unchecked");
+ Ref<Texture> radio_checked = Control::get_icon("radio_checked");
+ Ref<Texture> radio_unchecked = Control::get_icon("radio_unchecked");
+
+ Size2 tex_size = Size2(0, 0);
+ if (!checked.is_null())
+ tex_size = Size2(checked->get_width(), checked->get_height());
+ if (!unchecked.is_null())
+ tex_size = Size2(MAX(tex_size.width, unchecked->get_width()), MAX(tex_size.height, unchecked->get_height()));
+ if (!radio_checked.is_null())
+ tex_size = Size2(MAX(tex_size.width, radio_checked->get_width()), MAX(tex_size.height, radio_checked->get_height()));
+ if (!radio_unchecked.is_null())
+ tex_size = Size2(MAX(tex_size.width, radio_unchecked->get_width()), MAX(tex_size.height, radio_unchecked->get_height()));
+ return tex_size;
+}
+
+Size2 CheckBox::get_minimum_size() const {
+
+ Size2 minsize = Button::get_minimum_size();
+ Size2 tex_size = get_icon_size();
+ minsize.width += tex_size.width;
+ if (get_text().length() > 0) {
+ minsize.width += get_constant("hseparation");
+ }
+ Ref<StyleBox> sb = get_stylebox("normal");
+ minsize.height = MAX(minsize.height, tex_size.height + sb->get_margin(MARGIN_TOP) + sb->get_margin(MARGIN_BOTTOM));
+
+ return minsize;
+}
+
void CheckBox::_notification(int p_what) {
- if (p_what == NOTIFICATION_DRAW) {
+ if (p_what == NOTIFICATION_THEME_CHANGED) {
+
+ _set_internal_margin(MARGIN_LEFT, get_icon_size().width);
+ } else if (p_what == NOTIFICATION_DRAW) {
RID ci = get_canvas_item();
Ref<Texture> on = Control::get_icon(is_radio() ? "radio_checked" : "checked");
Ref<Texture> off = Control::get_icon(is_radio() ? "radio_unchecked" : "unchecked");
+ Ref<StyleBox> sb = get_stylebox("normal");
Vector2 ofs;
- ofs.x = 0;
- ofs.y = int((get_size().height - on->get_height()) / 2);
+ ofs.x = sb->get_margin(MARGIN_LEFT);
+ ofs.y = int((get_size().height - get_icon_size().height) / 2);
if (is_pressed())
on->draw(ci, ofs);
@@ -60,6 +96,7 @@ CheckBox::CheckBox(const String &p_text) :
Button(p_text) {
set_toggle_mode(true);
set_text_align(ALIGN_LEFT);
+ _set_internal_margin(MARGIN_LEFT, get_icon_size().width);
}
CheckBox::~CheckBox() {
diff --git a/scene/gui/check_box.h b/scene/gui/check_box.h
index 4da06be8d1..3d3f170e8c 100644
--- a/scene/gui/check_box.h
+++ b/scene/gui/check_box.h
@@ -39,6 +39,8 @@ class CheckBox : public Button {
GDCLASS(CheckBox, Button);
protected:
+ Size2 get_icon_size() const;
+ Size2 get_minimum_size() const;
void _notification(int p_what);
bool is_radio();
diff --git a/scene/gui/check_button.cpp b/scene/gui/check_button.cpp
index 77fdedd5e5..641d2d4f01 100644
--- a/scene/gui/check_button.cpp
+++ b/scene/gui/check_button.cpp
@@ -32,10 +32,7 @@
#include "print_string.h"
#include "servers/visual_server.h"
-Size2 CheckButton::get_minimum_size() const {
-
- Size2 minsize = Button::get_minimum_size();
-
+Size2 CheckButton::get_icon_size() const {
Ref<Texture> on = Control::get_icon("on");
Ref<Texture> off = Control::get_icon("off");
Size2 tex_size = Size2(0, 0);
@@ -43,15 +40,29 @@ Size2 CheckButton::get_minimum_size() const {
tex_size = Size2(on->get_width(), on->get_height());
if (!off.is_null())
tex_size = Size2(MAX(tex_size.width, off->get_width()), MAX(tex_size.height, off->get_height()));
- minsize += Size2(tex_size.width + get_constant("hseparation"), 0);
- minsize.height = MAX(minsize.height, tex_size.height);
+ return tex_size;
+}
+
+Size2 CheckButton::get_minimum_size() const {
- return get_stylebox("normal")->get_minimum_size() + minsize;
+ Size2 minsize = Button::get_minimum_size();
+ Size2 tex_size = get_icon_size();
+ minsize.width += tex_size.width;
+ if (get_text().length() > 0) {
+ minsize.width += get_constant("hseparation");
+ }
+ Ref<StyleBox> sb = get_stylebox("normal");
+ minsize.height = MAX(minsize.height, tex_size.height + sb->get_margin(MARGIN_TOP) + sb->get_margin(MARGIN_BOTTOM));
+
+ return minsize;
}
void CheckButton::_notification(int p_what) {
- if (p_what == NOTIFICATION_DRAW) {
+ if (p_what == NOTIFICATION_THEME_CHANGED) {
+
+ _set_internal_margin(MARGIN_RIGHT, get_icon_size().width);
+ } else if (p_what == NOTIFICATION_DRAW) {
RID ci = get_canvas_item();
@@ -59,10 +70,11 @@ void CheckButton::_notification(int p_what) {
Ref<Texture> off = Control::get_icon("off");
Ref<StyleBox> sb = get_stylebox("normal");
- Size2 sb_ofs = Size2(sb->get_margin(MARGIN_RIGHT), sb->get_margin(MARGIN_TOP));
Vector2 ofs;
- ofs.x = get_minimum_size().width - (on->get_width() + sb_ofs.width);
- ofs.y = sb_ofs.height;
+ Size2 tex_size = get_icon_size();
+
+ ofs.x = get_size().width - (tex_size.width + sb->get_margin(MARGIN_RIGHT));
+ ofs.y = (get_size().height - tex_size.height) / 2;
if (is_pressed())
on->draw(ci, ofs);
@@ -75,6 +87,8 @@ CheckButton::CheckButton() {
set_toggle_mode(true);
set_text_align(ALIGN_LEFT);
+
+ _set_internal_margin(MARGIN_RIGHT, get_icon_size().width);
}
CheckButton::~CheckButton() {
diff --git a/scene/gui/check_button.h b/scene/gui/check_button.h
index eb68943fe7..3103a40d3c 100644
--- a/scene/gui/check_button.h
+++ b/scene/gui/check_button.h
@@ -39,6 +39,7 @@ class CheckButton : public Button {
GDCLASS(CheckButton, Button);
protected:
+ Size2 get_icon_size() const;
virtual Size2 get_minimum_size() const;
void _notification(int p_what);
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index adca78d1d4..81d2b6731f 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -2470,6 +2470,16 @@ Control::MouseFilter Control::get_mouse_filter() const {
return data.mouse_filter;
}
+void Control::set_pass_on_modal_close_click(bool p_pass_on) {
+
+ data.pass_on_modal_close_click = p_pass_on;
+}
+
+bool Control::pass_on_modal_close_click() const {
+
+ return data.pass_on_modal_close_click;
+}
+
Control *Control::get_focus_owner() const {
ERR_FAIL_COND_V(!is_inside_tree(), NULL);
@@ -2934,6 +2944,7 @@ Control::Control() {
data.parent = NULL;
data.mouse_filter = MOUSE_FILTER_STOP;
+ data.pass_on_modal_close_click = true;
data.SI = NULL;
data.MI = NULL;
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 92d1c969fc..9ac0eb0be3 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -165,6 +165,8 @@ private:
bool pending_min_size_update;
Point2 custom_minimum_size;
+ bool pass_on_modal_close_click;
+
MouseFilter mouse_filter;
bool clip_contents;
@@ -401,6 +403,9 @@ public:
void set_mouse_filter(MouseFilter p_filter);
MouseFilter get_mouse_filter() const;
+ void set_pass_on_modal_close_click(bool p_pass_on);
+ bool pass_on_modal_close_click() const;
+
/* SKINNING */
void add_icon_override(const StringName &p_name, const Ref<Texture> &p_icon);
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index ac450616d6..d850553957 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -111,6 +111,7 @@ MenuButton::MenuButton() {
popup->hide();
add_child(popup);
popup->set_as_toplevel(true);
+ popup->set_pass_on_modal_close_click(false);
connect("button_up", popup, "call_deferred", make_binds("grab_click_focus"));
set_process_unhandled_key_input(true);
set_action_mode(ACTION_MODE_BUTTON_PRESS);
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index b4d0799945..70f3d9ca83 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -323,6 +323,7 @@ OptionButton::OptionButton() {
popup = memnew(PopupMenu);
popup->hide();
popup->set_as_toplevel(true);
+ popup->set_pass_on_modal_close_click(false);
add_child(popup);
popup->connect("id_pressed", this, "_selected");
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 4ee6f93c9a..e37cdd5cc9 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -624,6 +624,20 @@ void PopupMenu::add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_ID, bo
update();
}
+void PopupMenu::add_statable_item(const String &p_label, int p_max_states, int p_default_state, int p_ID, uint32_t p_accel) {
+
+ Item item;
+ item.text = p_label;
+ item.xl_text = tr(p_label);
+ item.accel = p_accel;
+ item.ID = p_ID;
+ item.checkable = false;
+ item.max_states = p_max_states;
+ item.state = p_default_state;
+ items.push_back(item);
+ update();
+}
+
void PopupMenu::set_item_text(int p_idx, const String &p_text) {
ERR_FAIL_INDEX(p_idx, items.size());
@@ -772,6 +786,11 @@ Ref<ShortCut> PopupMenu::get_item_shortcut(int p_idx) const {
return items[p_idx].shortcut;
}
+int PopupMenu::get_item_state(int p_idx) const {
+ ERR_FAIL_INDEX_V(p_idx, items.size(), -1);
+ return items[p_idx].state;
+}
+
void PopupMenu::set_item_as_separator(int p_idx, bool p_separator) {
ERR_FAIL_INDEX(p_idx, items.size());
@@ -820,6 +839,27 @@ void PopupMenu::set_item_h_offset(int p_idx, int p_offset) {
update();
}
+void PopupMenu::set_item_statable(int p_idx, int p_state) {
+
+ ERR_FAIL_INDEX(p_idx, items.size());
+ items[p_idx].state = p_state;
+ update();
+}
+
+void PopupMenu::toggle_item_statable(int p_idx) {
+
+ ERR_FAIL_INDEX(p_idx, items.size());
+ if (0 >= items[p_idx].max_states) {
+ return;
+ }
+
+ ++items[p_idx].state;
+ if (items[p_idx].max_states <= items[p_idx].state)
+ items[p_idx].state = 0;
+
+ update();
+}
+
bool PopupMenu::is_item_checkable(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, items.size(), false);
return items[p_idx].checkable;
@@ -895,21 +935,34 @@ void PopupMenu::activate_item(int p_item) {
while (pop) {
// We close all parents that are chained together,
// with hide_on_item_selection enabled
- if ((items[p_item].checkable && hide_on_checkable_item_selection && pop->is_hide_on_checkable_item_selection()) || (!items[p_item].checkable && hide_on_item_selection && pop->is_hide_on_item_selection())) {
- pop->hide();
- next = next->get_parent();
- pop = Object::cast_to<PopupMenu>(next);
- } else {
- // Break out of loop when the next parent has
- // hide_on_item_selection disabled
+
+ if (items[p_item].checkable) {
+ if (!hide_on_checkable_item_selection || !pop->is_hide_on_checkable_item_selection())
+ break;
+ } else if (0 < items[p_item].max_states) {
+ if (!hide_on_statable_item_selection || !pop->is_hide_on_statable_item_selection())
+ break;
+ } else if (!hide_on_item_selection || !pop->is_hide_on_item_selection())
break;
- }
+
+ pop->hide();
+ next = next->get_parent();
+ pop = Object::cast_to<PopupMenu>(next);
}
+
// Hides popup by default; unless otherwise specified
// by using set_hide_on_item_selection and set_hide_on_checkable_item_selection
- if ((items[p_item].checkable && hide_on_checkable_item_selection) || (!items[p_item].checkable && hide_on_item_selection)) {
- hide();
- }
+
+ if (items[p_item].checkable) {
+ if (!hide_on_checkable_item_selection)
+ return;
+ } else if (0 < items[p_item].max_states) {
+ if (!hide_on_statable_item_selection)
+ return;
+ } else if (!hide_on_item_selection)
+ return;
+
+ hide();
}
void PopupMenu::remove_item(int p_idx) {
@@ -1025,7 +1078,7 @@ void PopupMenu::set_hide_on_item_selection(bool p_enabled) {
hide_on_item_selection = p_enabled;
}
-bool PopupMenu::is_hide_on_item_selection() {
+bool PopupMenu::is_hide_on_item_selection() const {
return hide_on_item_selection;
}
@@ -1035,11 +1088,21 @@ void PopupMenu::set_hide_on_checkable_item_selection(bool p_enabled) {
hide_on_checkable_item_selection = p_enabled;
}
-bool PopupMenu::is_hide_on_checkable_item_selection() {
+bool PopupMenu::is_hide_on_checkable_item_selection() const {
return hide_on_checkable_item_selection;
}
+void PopupMenu::set_hide_on_statable_item_selection(bool p_enabled) {
+
+ hide_on_statable_item_selection = p_enabled;
+}
+
+bool PopupMenu::is_hide_on_statable_item_selection() const {
+
+ return hide_on_statable_item_selection;
+}
+
String PopupMenu::get_tooltip(const Point2 &p_pos) const {
int over = _get_mouse_over(p_pos);
@@ -1098,8 +1161,10 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_item_as_checkable", "idx", "enable"), &PopupMenu::set_item_as_checkable);
ClassDB::bind_method(D_METHOD("set_item_tooltip", "idx", "tooltip"), &PopupMenu::set_item_tooltip);
ClassDB::bind_method(D_METHOD("set_item_shortcut", "idx", "shortcut", "global"), &PopupMenu::set_item_shortcut, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("set_item_statable", "idx", "state"), &PopupMenu::set_item_statable);
ClassDB::bind_method(D_METHOD("toggle_item_checked", "idx"), &PopupMenu::toggle_item_checked);
+ ClassDB::bind_method(D_METHOD("toggle_item_statable", "idx"), &PopupMenu::toggle_item_statable);
ClassDB::bind_method(D_METHOD("get_item_text", "idx"), &PopupMenu::get_item_text);
ClassDB::bind_method(D_METHOD("get_item_icon", "idx"), &PopupMenu::get_item_icon);
@@ -1131,6 +1196,9 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_hide_on_checkable_item_selection", "enable"), &PopupMenu::set_hide_on_checkable_item_selection);
ClassDB::bind_method(D_METHOD("is_hide_on_checkable_item_selection"), &PopupMenu::is_hide_on_checkable_item_selection);
+ ClassDB::bind_method(D_METHOD("set_hide_on_state_item_selection", "enable"), &PopupMenu::set_hide_on_statable_item_selection);
+ ClassDB::bind_method(D_METHOD("is_hide_on_state_item_selection"), &PopupMenu::is_hide_on_statable_item_selection);
+
ClassDB::bind_method(D_METHOD("_submenu_timeout"), &PopupMenu::_submenu_timeout);
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "_set_items", "_get_items");
@@ -1154,6 +1222,7 @@ PopupMenu::PopupMenu() {
set_as_toplevel(true);
set_hide_on_item_selection(true);
set_hide_on_checkable_item_selection(true);
+ set_hide_on_statable_item_selection(false);
submenu_timer = memnew(Timer);
submenu_timer->set_wait_time(0.3);
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index c9e9c8e311..5a10bf0765 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -46,6 +46,8 @@ class PopupMenu : public Popup {
String xl_text;
bool checked;
bool checkable;
+ int max_states;
+ int state;
bool separator;
bool disabled;
int ID;
@@ -62,6 +64,8 @@ class PopupMenu : public Popup {
checked = false;
checkable = false;
separator = false;
+ max_states = 0;
+ state = 0;
accel = 0;
disabled = false;
_ofs_cache = 0;
@@ -86,6 +90,7 @@ class PopupMenu : public Popup {
bool invalidated_click;
bool hide_on_item_selection;
bool hide_on_checkable_item_selection;
+ bool hide_on_statable_item_selection;
Vector2 moved;
Array _get_items() const;
@@ -115,6 +120,8 @@ public:
void add_icon_check_shortcut(const Ref<Texture> &p_icon, const Ref<ShortCut> &p_shortcut, int p_ID = -1, bool p_global = false);
void add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_ID = -1, bool p_global = false);
+ void add_statable_item(const String &p_label, int p_max_states, int p_default_state, int p_ID = -1, uint32_t p_accel = 0);
+
void set_item_text(int p_idx, const String &p_text);
void set_item_icon(int p_idx, const Ref<Texture> &p_icon);
void set_item_checked(int p_idx, bool p_checked);
@@ -128,6 +135,8 @@ public:
void set_item_tooltip(int p_idx, const String &p_tooltip);
void set_item_shortcut(int p_idx, const Ref<ShortCut> &p_shortcut, bool p_global = false);
void set_item_h_offset(int p_idx, int p_offset);
+ void set_item_statable(int p_idx, int p_state);
+ void toggle_item_statable(int p_idx);
void toggle_item_checked(int p_idx);
@@ -145,6 +154,7 @@ public:
bool is_item_checkable(int p_idx) const;
String get_item_tooltip(int p_idx) const;
Ref<ShortCut> get_item_shortcut(int p_idx) const;
+ int get_item_state(int p_idx) const;
int get_item_count() const;
@@ -168,10 +178,13 @@ public:
void set_invalidate_click_until_motion();
void set_hide_on_item_selection(bool p_enabled);
- bool is_hide_on_item_selection();
+ bool is_hide_on_item_selection() const;
void set_hide_on_checkable_item_selection(bool p_enabled);
- bool is_hide_on_checkable_item_selection();
+ bool is_hide_on_checkable_item_selection() const;
+
+ void set_hide_on_statable_item_selection(bool p_enabled);
+ bool is_hide_on_statable_item_selection() const;
PopupMenu();
~PopupMenu();
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index 9cf4c105b4..45188c3a52 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -1822,7 +1822,7 @@ bool RichTextLabel::search(const String &p_string, bool p_from_selection) {
void RichTextLabel::selection_copy() {
- if (!selection.enabled)
+ if (!selection.active || !selection.enabled)
return;
String text;
diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h
index 1096e3f650..b9a719dd10 100644
--- a/scene/gui/rich_text_label.h
+++ b/scene/gui/rich_text_label.h
@@ -256,8 +256,8 @@ private:
Item *to;
int to_char;
- bool active;
- bool enabled;
+ bool active; // anything selected? i.e. from, to, etc. valid?
+ bool enabled; // allow selections?
};
Selection selection;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index ea8adc58cd..4635de81e8 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -1646,6 +1646,8 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
} else {
+ bool is_handled = false;
+
_gui_sort_modal_stack();
while (!gui.modal_stack.empty()) {
@@ -1663,11 +1665,20 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
top->notification(Control::NOTIFICATION_MODAL_CLOSE);
top->_modal_stack_remove();
top->hide();
+
+ if (!top->pass_on_modal_close_click()) {
+ is_handled = true;
+ }
} else {
break;
}
}
+ if (is_handled) {
+ get_tree()->set_input_as_handled();
+ return;
+ }
+
//Matrix32 parent_xform;
/*
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index bb2c8750e3..f4e6c5e247 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -350,15 +350,15 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
// CheckBox
Ref<StyleBox> cbx_empty = memnew(StyleBoxEmpty);
- cbx_empty->set_default_margin(MARGIN_LEFT, 22 * scale);
+ cbx_empty->set_default_margin(MARGIN_LEFT, 4 * scale);
cbx_empty->set_default_margin(MARGIN_RIGHT, 4 * scale);
cbx_empty->set_default_margin(MARGIN_TOP, 4 * scale);
- cbx_empty->set_default_margin(MARGIN_BOTTOM, 5 * scale);
+ cbx_empty->set_default_margin(MARGIN_BOTTOM, 4 * scale);
Ref<StyleBox> cbx_focus = focus;
cbx_focus->set_default_margin(MARGIN_LEFT, 4 * scale);
- cbx_focus->set_default_margin(MARGIN_RIGHT, 22 * scale);
+ cbx_focus->set_default_margin(MARGIN_RIGHT, 4 * scale);
cbx_focus->set_default_margin(MARGIN_TOP, 4 * scale);
- cbx_focus->set_default_margin(MARGIN_BOTTOM, 5 * scale);
+ cbx_focus->set_default_margin(MARGIN_BOTTOM, 4 * scale);
theme->set_stylebox("normal", "CheckBox", cbx_empty);
theme->set_stylebox("pressed", "CheckBox", cbx_empty);
@@ -385,7 +385,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
Ref<StyleBox> cb_empty = memnew(StyleBoxEmpty);
cb_empty->set_default_margin(MARGIN_LEFT, 6 * scale);
- cb_empty->set_default_margin(MARGIN_RIGHT, 70 * scale);
+ cb_empty->set_default_margin(MARGIN_RIGHT, 6 * scale);
cb_empty->set_default_margin(MARGIN_TOP, 4 * scale);
cb_empty->set_default_margin(MARGIN_BOTTOM, 4 * scale);
diff --git a/scene/resources/sky_box.cpp b/scene/resources/sky_box.cpp
index 2ef20f67f5..a2c3f1f111 100644
--- a/scene/resources/sky_box.cpp
+++ b/scene/resources/sky_box.cpp
@@ -180,7 +180,7 @@ Ref<Image> ProceduralSky::_generate_sky() {
normal.normalize();
- float v_angle = Math::acos(normal.y);
+ float v_angle = Math::acos(CLAMP(normal.y, -1.0, 1.0));
Color color;
@@ -193,7 +193,7 @@ Ref<Image> ProceduralSky::_generate_sky() {
float c = v_angle / (Math_PI * 0.5);
color = sky_horizon_linear.linear_interpolate(sky_top_linear, Math::ease(1.0 - c, sky_curve));
- float sun_angle = Math::rad2deg(Math::acos(sun.dot(normal)));
+ float sun_angle = Math::rad2deg(Math::acos(CLAMP(sun.dot(normal), -1.0, 1.0)));
if (sun_angle < sun_angle_min) {
color = color.blend(sun_color);
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 1a46353fe3..bd6b917d4e 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -932,8 +932,8 @@ void TileSet::_bind_methods() {
ClassDB::bind_method(D_METHOD("find_tile_by_name", "name"), &TileSet::find_tile_by_name);
ClassDB::bind_method(D_METHOD("get_tiles_ids"), &TileSet::_get_tiles_ids);
- BIND_VMETHOD(MethodInfo("_is_tile_bound", PropertyInfo(Variant::INT, "drawn_id"), PropertyInfo(Variant::INT, "neighbor_id")));
- BIND_VMETHOD(MethodInfo("_forward_subtile_selection", PropertyInfo(Variant::INT, "autotile_id"), PropertyInfo(Variant::INT, "bitmask"), PropertyInfo(Variant::OBJECT, "tilemap", PROPERTY_HINT_NONE, "TileMap"), PropertyInfo(Variant::VECTOR2, "tile_location")));
+ BIND_VMETHOD(MethodInfo(Variant::BOOL, "_is_tile_bound", PropertyInfo(Variant::INT, "drawn_id"), PropertyInfo(Variant::INT, "neighbor_id")));
+ BIND_VMETHOD(MethodInfo(Variant::VECTOR2, "_forward_subtile_selection", PropertyInfo(Variant::INT, "autotile_id"), PropertyInfo(Variant::INT, "bitmask"), PropertyInfo(Variant::OBJECT, "tilemap", PROPERTY_HINT_NONE, "TileMap"), PropertyInfo(Variant::VECTOR2, "tile_location")));
BIND_ENUM_CONSTANT(BITMASK_2X2);
BIND_ENUM_CONSTANT(BITMASK_3X3);