summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/path_2d.cpp25
-rw-r--r--scene/2d/path_2d.h5
-rw-r--r--scene/animation/animation_player.cpp2
-rw-r--r--scene/animation/tween.cpp20
-rw-r--r--scene/animation/tween.h2
-rw-r--r--scene/gui/code_edit.cpp8
-rw-r--r--scene/gui/control.cpp4
-rw-r--r--scene/gui/graph_edit.cpp1
-rw-r--r--scene/gui/tree.cpp98
-rw-r--r--scene/gui/tree.h22
-rw-r--r--scene/main/canvas_item.cpp20
-rw-r--r--scene/main/canvas_item.h12
-rw-r--r--scene/main/scene_tree.cpp1
-rw-r--r--scene/main/viewport.cpp40
-rw-r--r--scene/main/viewport.h3
-rw-r--r--scene/main/window.cpp20
-rw-r--r--scene/main/window.h5
-rw-r--r--scene/resources/convex_polygon_shape_2d.cpp2
-rw-r--r--scene/resources/tile_set.cpp1
19 files changed, 175 insertions, 116 deletions
diff --git a/scene/2d/path_2d.cpp b/scene/2d/path_2d.cpp
index 09f4406ffe..5036dd30b1 100644
--- a/scene/2d/path_2d.cpp
+++ b/scene/2d/path_2d.cpp
@@ -31,6 +31,7 @@
#include "path_2d.h"
#include "core/math/geometry_2d.h"
+#include "scene/main/timer.h"
#ifdef TOOLS_ENABLED
#include "editor/editor_scale.h"
@@ -171,6 +172,12 @@ void Path2D::_curve_changed() {
}
queue_redraw();
+ for (int i = 0; i < get_child_count(); i++) {
+ PathFollow2D *follow = Object::cast_to<PathFollow2D>(get_child(i));
+ if (follow) {
+ follow->path_changed();
+ }
+ }
}
void Path2D::set_curve(const Ref<Curve2D> &p_curve) {
@@ -200,6 +207,14 @@ void Path2D::_bind_methods() {
/////////////////////////////////////////////////////////////////////////////////
+void PathFollow2D::path_changed() {
+ if (update_timer && !update_timer->is_stopped()) {
+ update_timer->start();
+ } else {
+ _update_transform();
+ }
+}
+
void PathFollow2D::_update_transform() {
if (!path) {
return;
@@ -230,6 +245,16 @@ void PathFollow2D::_update_transform() {
void PathFollow2D::_notification(int p_what) {
switch (p_what) {
+ case NOTIFICATION_READY: {
+ if (Engine::get_singleton()->is_editor_hint()) {
+ update_timer = memnew(Timer);
+ update_timer->set_wait_time(0.2);
+ update_timer->set_one_shot(true);
+ update_timer->connect("timeout", callable_mp(this, &PathFollow2D::_update_transform));
+ add_child(update_timer, false, Node::INTERNAL_MODE_BACK);
+ }
+ } break;
+
case NOTIFICATION_ENTER_TREE: {
path = Object::cast_to<Path2D>(get_parent());
if (path) {
diff --git a/scene/2d/path_2d.h b/scene/2d/path_2d.h
index 884743dd2a..89c77c49eb 100644
--- a/scene/2d/path_2d.h
+++ b/scene/2d/path_2d.h
@@ -34,6 +34,8 @@
#include "scene/2d/node_2d.h"
#include "scene/resources/curve.h"
+class Timer;
+
class Path2D : public Node2D {
GDCLASS(Path2D, Node2D);
@@ -65,6 +67,7 @@ public:
private:
Path2D *path = nullptr;
real_t progress = 0.0;
+ Timer *update_timer = nullptr;
real_t h_offset = 0.0;
real_t v_offset = 0.0;
real_t lookahead = 4.0;
@@ -81,6 +84,8 @@ protected:
static void _bind_methods();
public:
+ void path_changed();
+
void set_progress(real_t p_progress);
real_t get_progress() const;
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index d0875c2ba6..0771c7ef06 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -2100,7 +2100,7 @@ Ref<AnimatedValuesBackup> AnimationPlayer::apply_reset(bool p_user_initiated) {
Ref<AnimatedValuesBackup> new_values = aux_player->backup_animated_values();
old_values->restore();
- Ref<EditorUndoRedoManager> &ur = EditorNode::get_undo_redo();
+ EditorUndoRedoManager *ur = EditorUndoRedoManager::get_singleton();
ur->create_action(TTR("Animation Apply Reset"));
ur->add_do_method(new_values.ptr(), "restore");
ur->add_undo_method(old_values.ptr(), "restore");
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index be8c23844f..39d1793368 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -280,7 +280,16 @@ bool Tween::step(double p_delta) {
}
if (!started) {
- ERR_FAIL_COND_V_MSG(tweeners.is_empty(), false, "Tween started, but has no Tweeners.");
+ if (tweeners.is_empty()) {
+ String tween_id;
+ Node *node = get_bound_node();
+ if (node) {
+ tween_id = vformat("Tween (bound to %s)", node->is_inside_tree() ? (String)node->get_path() : (String)node->get_name());
+ } else {
+ tween_id = to_string();
+ }
+ ERR_FAIL_V_MSG(false, tween_id + ": started with no Tweeners.");
+ }
current_step = 0;
loops_done = 0;
total_time = 0;
@@ -393,6 +402,15 @@ Variant Tween::interpolate_variant(Variant p_initial_val, Variant p_delta_val, d
return ret;
}
+String Tween::to_string() {
+ String ret = Object::to_string();
+ Node *node = get_bound_node();
+ if (node) {
+ ret += vformat(" (bound to %s)", node->get_name());
+ }
+ return ret;
+}
+
void Tween::_bind_methods() {
ClassDB::bind_method(D_METHOD("tween_property", "object", "property", "final_val", "duration"), &Tween::tween_property);
ClassDB::bind_method(D_METHOD("tween_interval", "time"), &Tween::tween_interval);
diff --git a/scene/animation/tween.h b/scene/animation/tween.h
index 08911d6623..58217db535 100644
--- a/scene/animation/tween.h
+++ b/scene/animation/tween.h
@@ -130,6 +130,8 @@ protected:
static void _bind_methods();
public:
+ virtual String to_string() override;
+
Ref<PropertyTweener> tween_property(Object *p_target, NodePath p_property, Variant p_to, double p_duration);
Ref<IntervalTweener> tween_interval(double p_time);
Ref<CallbackTweener> tween_callback(Callable p_callback);
diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp
index 7539810feb..4356e91e41 100644
--- a/scene/gui/code_edit.cpp
+++ b/scene/gui/code_edit.cpp
@@ -2086,9 +2086,11 @@ void CodeEdit::confirm_code_completion(bool p_replace) {
int post_brace_pair = get_caret_column(i) < get_line(caret_line).length() ? _get_auto_brace_pair_close_at_pos(caret_line, get_caret_column(i)) : -1;
// Strings do not nest like brackets, so ensure we don't add an additional closing pair.
- if (has_string_delimiter(String::chr(last_completion_char)) && post_brace_pair != -1 && last_char_matches) {
- remove_text(caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
- adjust_carets_after_edit(i, caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
+ if (has_string_delimiter(String::chr(last_completion_char))) {
+ if (post_brace_pair != -1 && last_char_matches) {
+ remove_text(caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
+ adjust_carets_after_edit(i, caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
+ }
} else {
if (pre_brace_pair != -1 && pre_brace_pair != post_brace_pair && last_char_matches) {
remove_text(caret_line, get_caret_column(i), caret_line, get_caret_column(i) + 1);
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 4188946494..10dbad232a 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -758,6 +758,7 @@ void Control::set_anchor_and_offset(Side p_side, real_t p_anchor, real_t p_pos,
}
void Control::set_begin(const Size2 &p_point) {
+ ERR_FAIL_COND(!isfinite(p_point.x) || !isfinite(p_point.y));
if (data.offset[0] == p_point.x && data.offset[1] == p_point.y) {
return;
}
@@ -1405,6 +1406,7 @@ void Control::_set_size(const Size2 &p_size) {
}
void Control::set_size(const Size2 &p_size, bool p_keep_offsets) {
+ ERR_FAIL_COND(!isfinite(p_size.x) || !isfinite(p_size.y));
Size2 new_size = p_size;
Size2 min = get_combined_minimum_size();
if (new_size.x < min.x) {
@@ -1595,7 +1597,7 @@ void Control::set_custom_minimum_size(const Size2 &p_custom) {
return;
}
- if (isnan(p_custom.x) || isnan(p_custom.y)) {
+ if (!isfinite(p_custom.x) || !isfinite(p_custom.y)) {
// Prevent infinite loop.
return;
}
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 2fd6d666e5..6c495ab2c9 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -1496,6 +1496,7 @@ float GraphEdit::get_zoom() const {
void GraphEdit::set_zoom_step(float p_zoom_step) {
p_zoom_step = abs(p_zoom_step);
+ ERR_FAIL_COND(!isfinite(p_zoom_step));
if (zoom_step == p_zoom_step) {
return;
}
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 3458b87b8d..2138f10ad0 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -657,7 +657,7 @@ int TreeItem::get_custom_minimum_height() const {
/* Item manipulation */
-TreeItem *TreeItem::create_child(int p_idx) {
+TreeItem *TreeItem::create_child(int p_index) {
TreeItem *ti = memnew(TreeItem(tree));
if (tree) {
ti->cells.resize(tree->columns.size());
@@ -669,7 +669,7 @@ TreeItem *TreeItem::create_child(int p_idx) {
int idx = 0;
while (c) {
- if (idx++ == p_idx) {
+ if (idx++ == p_index) {
c->prev = ti;
ti->next = c;
break;
@@ -683,7 +683,7 @@ TreeItem *TreeItem::create_child(int p_idx) {
ti->prev = l_prev;
if (!children_cache.is_empty()) {
if (ti->next) {
- children_cache.insert(p_idx, ti);
+ children_cache.insert(p_index, ti);
} else {
children_cache.append(ti);
}
@@ -826,15 +826,15 @@ TreeItem *TreeItem::get_next_visible(bool p_wrap) {
return next_item;
}
-TreeItem *TreeItem::get_child(int p_idx) {
+TreeItem *TreeItem::get_child(int p_index) {
_create_children_cache();
- if (p_idx < 0) {
- p_idx += children_cache.size();
+ if (p_index < 0) {
+ p_index += children_cache.size();
}
- ERR_FAIL_INDEX_V(p_idx, children_cache.size(), nullptr);
+ ERR_FAIL_INDEX_V(p_index, children_cache.size(), nullptr);
- return children_cache.get(p_idx);
+ return children_cache.get(p_index);
}
int TreeItem::get_visible_child_count() {
@@ -1058,28 +1058,28 @@ int TreeItem::get_button_count(int p_column) const {
return cells[p_column].buttons.size();
}
-Ref<Texture2D> TreeItem::get_button(int p_column, int p_idx) const {
+Ref<Texture2D> TreeItem::get_button(int p_column, int p_index) const {
ERR_FAIL_INDEX_V(p_column, cells.size(), Ref<Texture2D>());
- ERR_FAIL_INDEX_V(p_idx, cells[p_column].buttons.size(), Ref<Texture2D>());
- return cells[p_column].buttons[p_idx].texture;
+ ERR_FAIL_INDEX_V(p_index, cells[p_column].buttons.size(), Ref<Texture2D>());
+ return cells[p_column].buttons[p_index].texture;
}
-String TreeItem::get_button_tooltip_text(int p_column, int p_idx) const {
+String TreeItem::get_button_tooltip_text(int p_column, int p_index) const {
ERR_FAIL_INDEX_V(p_column, cells.size(), String());
- ERR_FAIL_INDEX_V(p_idx, cells[p_column].buttons.size(), String());
- return cells[p_column].buttons[p_idx].tooltip;
+ ERR_FAIL_INDEX_V(p_index, cells[p_column].buttons.size(), String());
+ return cells[p_column].buttons[p_index].tooltip;
}
-int TreeItem::get_button_id(int p_column, int p_idx) const {
+int TreeItem::get_button_id(int p_column, int p_index) const {
ERR_FAIL_INDEX_V(p_column, cells.size(), -1);
- ERR_FAIL_INDEX_V(p_idx, cells[p_column].buttons.size(), -1);
- return cells[p_column].buttons[p_idx].id;
+ ERR_FAIL_INDEX_V(p_index, cells[p_column].buttons.size(), -1);
+ return cells[p_column].buttons[p_index].id;
}
-void TreeItem::erase_button(int p_column, int p_idx) {
+void TreeItem::erase_button(int p_column, int p_index) {
ERR_FAIL_INDEX(p_column, cells.size());
- ERR_FAIL_INDEX(p_idx, cells[p_column].buttons.size());
- cells.write[p_column].buttons.remove_at(p_idx);
+ ERR_FAIL_INDEX(p_index, cells[p_column].buttons.size());
+ cells.write[p_column].buttons.remove_at(p_index);
_changed_notify(p_column);
}
@@ -1094,52 +1094,52 @@ int TreeItem::get_button_by_id(int p_column, int p_id) const {
return -1;
}
-void TreeItem::set_button(int p_column, int p_idx, const Ref<Texture2D> &p_button) {
+void TreeItem::set_button(int p_column, int p_index, const Ref<Texture2D> &p_button) {
ERR_FAIL_COND(p_button.is_null());
ERR_FAIL_INDEX(p_column, cells.size());
- ERR_FAIL_INDEX(p_idx, cells[p_column].buttons.size());
+ ERR_FAIL_INDEX(p_index, cells[p_column].buttons.size());
- if (cells[p_column].buttons[p_idx].texture == p_button) {
+ if (cells[p_column].buttons[p_index].texture == p_button) {
return;
}
- cells.write[p_column].buttons.write[p_idx].texture = p_button;
+ cells.write[p_column].buttons.write[p_index].texture = p_button;
cells.write[p_column].cached_minimum_size_dirty = true;
_changed_notify(p_column);
}
-void TreeItem::set_button_color(int p_column, int p_idx, const Color &p_color) {
+void TreeItem::set_button_color(int p_column, int p_index, const Color &p_color) {
ERR_FAIL_INDEX(p_column, cells.size());
- ERR_FAIL_INDEX(p_idx, cells[p_column].buttons.size());
+ ERR_FAIL_INDEX(p_index, cells[p_column].buttons.size());
- if (cells[p_column].buttons[p_idx].color == p_color) {
+ if (cells[p_column].buttons[p_index].color == p_color) {
return;
}
- cells.write[p_column].buttons.write[p_idx].color = p_color;
+ cells.write[p_column].buttons.write[p_index].color = p_color;
_changed_notify(p_column);
}
-void TreeItem::set_button_disabled(int p_column, int p_idx, bool p_disabled) {
+void TreeItem::set_button_disabled(int p_column, int p_index, bool p_disabled) {
ERR_FAIL_INDEX(p_column, cells.size());
- ERR_FAIL_INDEX(p_idx, cells[p_column].buttons.size());
+ ERR_FAIL_INDEX(p_index, cells[p_column].buttons.size());
- if (cells[p_column].buttons[p_idx].disabled == p_disabled) {
+ if (cells[p_column].buttons[p_index].disabled == p_disabled) {
return;
}
- cells.write[p_column].buttons.write[p_idx].disabled = p_disabled;
+ cells.write[p_column].buttons.write[p_index].disabled = p_disabled;
cells.write[p_column].cached_minimum_size_dirty = true;
_changed_notify(p_column);
}
-bool TreeItem::is_button_disabled(int p_column, int p_idx) const {
+bool TreeItem::is_button_disabled(int p_column, int p_index) const {
ERR_FAIL_INDEX_V(p_column, cells.size(), false);
- ERR_FAIL_INDEX_V(p_idx, cells[p_column].buttons.size(), false);
+ ERR_FAIL_INDEX_V(p_index, cells[p_column].buttons.size(), false);
- return cells[p_column].buttons[p_idx].disabled;
+ return cells[p_column].buttons[p_index].disabled;
}
void TreeItem::set_editable(int p_column, bool p_editable) {
@@ -1497,15 +1497,15 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("add_button", "column", "button", "id", "disabled", "tooltip_text"), &TreeItem::add_button, DEFVAL(-1), DEFVAL(false), DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_button_count", "column"), &TreeItem::get_button_count);
- ClassDB::bind_method(D_METHOD("get_button_tooltip_text", "column", "button_idx"), &TreeItem::get_button_tooltip_text);
- ClassDB::bind_method(D_METHOD("get_button_id", "column", "button_idx"), &TreeItem::get_button_id);
+ ClassDB::bind_method(D_METHOD("get_button_tooltip_text", "column", "button_index"), &TreeItem::get_button_tooltip_text);
+ ClassDB::bind_method(D_METHOD("get_button_id", "column", "button_index"), &TreeItem::get_button_id);
ClassDB::bind_method(D_METHOD("get_button_by_id", "column", "id"), &TreeItem::get_button_by_id);
- ClassDB::bind_method(D_METHOD("get_button", "column", "button_idx"), &TreeItem::get_button);
- ClassDB::bind_method(D_METHOD("set_button", "column", "button_idx", "button"), &TreeItem::set_button);
- ClassDB::bind_method(D_METHOD("erase_button", "column", "button_idx"), &TreeItem::erase_button);
- ClassDB::bind_method(D_METHOD("set_button_disabled", "column", "button_idx", "disabled"), &TreeItem::set_button_disabled);
- ClassDB::bind_method(D_METHOD("set_button_color", "column", "button_idx", "color"), &TreeItem::set_button_color);
- ClassDB::bind_method(D_METHOD("is_button_disabled", "column", "button_idx"), &TreeItem::is_button_disabled);
+ ClassDB::bind_method(D_METHOD("get_button", "column", "button_index"), &TreeItem::get_button);
+ ClassDB::bind_method(D_METHOD("set_button", "column", "button_index", "button"), &TreeItem::set_button);
+ ClassDB::bind_method(D_METHOD("erase_button", "column", "button_index"), &TreeItem::erase_button);
+ ClassDB::bind_method(D_METHOD("set_button_disabled", "column", "button_index", "disabled"), &TreeItem::set_button_disabled);
+ ClassDB::bind_method(D_METHOD("set_button_color", "column", "button_index", "color"), &TreeItem::set_button_color);
+ ClassDB::bind_method(D_METHOD("is_button_disabled", "column", "button_index"), &TreeItem::is_button_disabled);
ClassDB::bind_method(D_METHOD("set_tooltip_text", "column", "tooltip"), &TreeItem::set_tooltip_text);
ClassDB::bind_method(D_METHOD("get_tooltip_text", "column"), &TreeItem::get_tooltip_text);
@@ -1518,7 +1518,7 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_disable_folding", "disable"), &TreeItem::set_disable_folding);
ClassDB::bind_method(D_METHOD("is_folding_disabled"), &TreeItem::is_folding_disabled);
- ClassDB::bind_method(D_METHOD("create_child", "idx"), &TreeItem::create_child, DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("create_child", "index"), &TreeItem::create_child, DEFVAL(-1));
ClassDB::bind_method(D_METHOD("get_tree"), &TreeItem::get_tree);
ClassDB::bind_method(D_METHOD("get_next"), &TreeItem::get_next);
@@ -1529,7 +1529,7 @@ void TreeItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_next_visible", "wrap"), &TreeItem::get_next_visible, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_prev_visible", "wrap"), &TreeItem::get_prev_visible, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("get_child", "idx"), &TreeItem::get_child);
+ ClassDB::bind_method(D_METHOD("get_child", "index"), &TreeItem::get_child);
ClassDB::bind_method(D_METHOD("get_child_count"), &TreeItem::get_child_count);
ClassDB::bind_method(D_METHOD("get_children"), &TreeItem::get_children);
ClassDB::bind_method(D_METHOD("get_index"), &TreeItem::get_index);
@@ -4108,14 +4108,14 @@ Size2 Tree::get_minimum_size() const {
}
}
-TreeItem *Tree::create_item(TreeItem *p_parent, int p_idx) {
+TreeItem *Tree::create_item(TreeItem *p_parent, int p_index) {
ERR_FAIL_COND_V(blocked > 0, nullptr);
TreeItem *ti = nullptr;
if (p_parent) {
ERR_FAIL_COND_V_MSG(p_parent->tree != this, nullptr, "A different tree owns the given parent");
- ti = p_parent->create_child(p_idx);
+ ti = p_parent->create_child(p_index);
} else {
if (!root) {
// No root exists, make the given item the new root.
@@ -4126,7 +4126,7 @@ TreeItem *Tree::create_item(TreeItem *p_parent, int p_idx) {
root = ti;
} else {
// Root exists, append or insert to root.
- ti = create_item(root, p_idx);
+ ti = create_item(root, p_index);
}
}
@@ -5162,7 +5162,7 @@ bool Tree::get_allow_reselect() const {
void Tree::_bind_methods() {
ClassDB::bind_method(D_METHOD("clear"), &Tree::clear);
- ClassDB::bind_method(D_METHOD("create_item", "parent", "idx"), &Tree::create_item, DEFVAL(Variant()), DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("create_item", "parent", "index"), &Tree::create_item, DEFVAL(Variant()), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("get_root"), &Tree::get_root);
ClassDB::bind_method(D_METHOD("set_column_custom_minimum_width", "column", "min_width"), &Tree::set_column_custom_minimum_width);
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index e0ed5fdfb5..ec639ce439 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -247,15 +247,15 @@ public:
void add_button(int p_column, const Ref<Texture2D> &p_button, int p_id = -1, bool p_disabled = false, const String &p_tooltip = "");
int get_button_count(int p_column) const;
- String get_button_tooltip_text(int p_column, int p_idx) const;
- Ref<Texture2D> get_button(int p_column, int p_idx) const;
- int get_button_id(int p_column, int p_idx) const;
- void erase_button(int p_column, int p_idx);
+ String get_button_tooltip_text(int p_column, int p_index) const;
+ Ref<Texture2D> get_button(int p_column, int p_index) const;
+ int get_button_id(int p_column, int p_index) const;
+ void erase_button(int p_column, int p_index);
int get_button_by_id(int p_column, int p_id) const;
- void set_button(int p_column, int p_idx, const Ref<Texture2D> &p_button);
- void set_button_color(int p_column, int p_idx, const Color &p_color);
- void set_button_disabled(int p_column, int p_idx, bool p_disabled);
- bool is_button_disabled(int p_column, int p_idx) const;
+ void set_button(int p_column, int p_index, const Ref<Texture2D> &p_button);
+ void set_button_color(int p_column, int p_index, const Color &p_color);
+ void set_button_disabled(int p_column, int p_index, bool p_disabled);
+ bool is_button_disabled(int p_column, int p_index) const;
/* range works for mode number or mode combo */
@@ -329,7 +329,7 @@ public:
/* Item manipulation */
- TreeItem *create_child(int p_idx = -1);
+ TreeItem *create_child(int p_index = -1);
Tree *get_tree() const;
@@ -341,7 +341,7 @@ public:
TreeItem *get_prev_visible(bool p_wrap = false);
TreeItem *get_next_visible(bool p_wrap = false);
- TreeItem *get_child(int p_idx);
+ TreeItem *get_child(int p_index);
int get_visible_child_count();
int get_child_count();
TypedArray<TreeItem> get_children();
@@ -647,7 +647,7 @@ public:
void clear();
- TreeItem *create_item(TreeItem *p_parent = nullptr, int p_idx = -1);
+ TreeItem *create_item(TreeItem *p_parent = nullptr, int p_index = -1);
TreeItem *get_root() const;
TreeItem *get_last_item() const;
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index 05caad78a0..9be1a6431b 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -558,7 +558,7 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
if (p_filled) {
- if (p_width != 1.0) {
+ if (p_width != -1.0) {
WARN_PRINT("The draw_rect() \"width\" argument has no effect when \"filled\" is \"true\".");
}
@@ -567,7 +567,7 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil
// Thick lines are offset depending on their width to avoid partial overlapping.
// Thin lines don't require an offset, so don't apply one in this case
real_t offset;
- if (p_width >= 2) {
+ if (p_width >= 0) {
offset = p_width / 2.0;
} else {
offset = 0.0;
@@ -647,11 +647,11 @@ void CanvasItem::draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p
p_style_box->draw(canvas_item, p_rect);
}
-void CanvasItem::draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture, real_t p_width) {
+void CanvasItem::draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID();
- RenderingServer::get_singleton()->canvas_item_add_primitive(canvas_item, p_points, p_colors, p_uvs, rid, p_width);
+ RenderingServer::get_singleton()->canvas_item_add_primitive(canvas_item, p_points, p_colors, p_uvs, rid);
}
void CanvasItem::draw_set_transform(const Point2 &p_offset, real_t p_rot, const Size2 &p_scale) {
@@ -968,14 +968,14 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_draw_behind_parent", "enable"), &CanvasItem::set_draw_behind_parent);
ClassDB::bind_method(D_METHOD("is_draw_behind_parent_enabled"), &CanvasItem::is_draw_behind_parent_enabled);
- ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width", "antialiased"), &CanvasItem::draw_line, DEFVAL(1.0), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("draw_dashed_line", "from", "to", "color", "width", "dash", "aligned"), &CanvasItem::draw_dashed_line, DEFVAL(1.0), DEFVAL(2.0), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("draw_line", "from", "to", "color", "width", "antialiased"), &CanvasItem::draw_line, DEFVAL(-1.0), DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("draw_dashed_line", "from", "to", "color", "width", "dash", "aligned"), &CanvasItem::draw_dashed_line, DEFVAL(-1.0), DEFVAL(2.0), DEFVAL(true));
ClassDB::bind_method(D_METHOD("draw_polyline", "points", "color", "width", "antialiased"), &CanvasItem::draw_polyline, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_polyline_colors", "points", "colors", "width", "antialiased"), &CanvasItem::draw_polyline_colors, DEFVAL(1.0), DEFVAL(false));
ClassDB::bind_method(D_METHOD("draw_arc", "center", "radius", "start_angle", "end_angle", "point_count", "color", "width", "antialiased"), &CanvasItem::draw_arc, DEFVAL(1.0), DEFVAL(false));
- ClassDB::bind_method(D_METHOD("draw_multiline", "points", "color", "width"), &CanvasItem::draw_multiline, DEFVAL(1.0));
- ClassDB::bind_method(D_METHOD("draw_multiline_colors", "points", "colors", "width"), &CanvasItem::draw_multiline_colors, DEFVAL(1.0));
- ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled", "width"), &CanvasItem::draw_rect, DEFVAL(true), DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("draw_multiline", "points", "color", "width"), &CanvasItem::draw_multiline, DEFVAL(-1.0));
+ ClassDB::bind_method(D_METHOD("draw_multiline_colors", "points", "colors", "width"), &CanvasItem::draw_multiline_colors, DEFVAL(-1.0));
+ ClassDB::bind_method(D_METHOD("draw_rect", "rect", "color", "filled", "width"), &CanvasItem::draw_rect, DEFVAL(true), DEFVAL(-1.0));
ClassDB::bind_method(D_METHOD("draw_circle", "position", "radius", "color"), &CanvasItem::draw_circle);
ClassDB::bind_method(D_METHOD("draw_texture", "texture", "position", "modulate"), &CanvasItem::draw_texture, DEFVAL(Color(1, 1, 1, 1)));
ClassDB::bind_method(D_METHOD("draw_texture_rect", "texture", "rect", "tile", "modulate", "transpose"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false));
@@ -983,7 +983,7 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("draw_msdf_texture_rect_region", "texture", "rect", "src_rect", "modulate", "outline", "pixel_range", "scale"), &CanvasItem::draw_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(0.0), DEFVAL(4.0), DEFVAL(1.0));
ClassDB::bind_method(D_METHOD("draw_lcd_texture_rect_region", "texture", "rect", "src_rect", "modulate"), &CanvasItem::draw_lcd_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)));
ClassDB::bind_method(D_METHOD("draw_style_box", "style_box", "rect"), &CanvasItem::draw_style_box);
- ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture", "width"), &CanvasItem::draw_primitive, DEFVAL(Ref<Texture2D>()), DEFVAL(1.0));
+ ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture"), &CanvasItem::draw_primitive, DEFVAL(Ref<Texture2D>()));
ClassDB::bind_method(D_METHOD("draw_polygon", "points", "colors", "uvs", "texture"), &CanvasItem::draw_polygon, DEFVAL(PackedVector2Array()), DEFVAL(Ref<Texture2D>()));
ClassDB::bind_method(D_METHOD("draw_colored_polygon", "points", "color", "uvs", "texture"), &CanvasItem::draw_colored_polygon, DEFVAL(PackedVector2Array()), DEFVAL(Ref<Texture2D>()));
ClassDB::bind_method(D_METHOD("draw_string", "font", "pos", "text", "alignment", "width", "font_size", "modulate", "jst_flags", "direction", "orientation"), &CanvasItem::draw_string, DEFVAL(HORIZONTAL_ALIGNMENT_LEFT), DEFVAL(-1), DEFVAL(Font::DEFAULT_FONT_SIZE), DEFVAL(Color(1.0, 1.0, 1.0)), DEFVAL(TextServer::JUSTIFICATION_KASHIDA | TextServer::JUSTIFICATION_WORD_BOUND), DEFVAL(TextServer::DIRECTION_AUTO), DEFVAL(TextServer::ORIENTATION_HORIZONTAL));
diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h
index 62357a1834..b2c12b2ea2 100644
--- a/scene/main/canvas_item.h
+++ b/scene/main/canvas_item.h
@@ -247,14 +247,14 @@ public:
/* DRAWING API */
- void draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = 1.0, real_t p_dash = 2.0, bool p_aligned = true);
- void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = 1.0, bool p_antialiased = false);
+ void draw_dashed_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = -1.0, real_t p_dash = 2.0, bool p_aligned = true);
+ void draw_line(const Point2 &p_from, const Point2 &p_to, const Color &p_color, real_t p_width = -1.0, bool p_antialiased = false);
void draw_polyline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width = 1.0, bool p_antialiased = false);
void draw_polyline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width = 1.0, bool p_antialiased = false);
void draw_arc(const Vector2 &p_center, real_t p_radius, real_t p_start_angle, real_t p_end_angle, int p_point_count, const Color &p_color, real_t p_width = 1.0, bool p_antialiased = false);
- void draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width = 1.0);
- void draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width = 1.0);
- void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true, real_t p_width = 1.0);
+ void draw_multiline(const Vector<Point2> &p_points, const Color &p_color, real_t p_width = -1.0);
+ void draw_multiline_colors(const Vector<Point2> &p_points, const Vector<Color> &p_colors, real_t p_width = -1.0);
+ void draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled = true, real_t p_width = -1.0);
void draw_circle(const Point2 &p_pos, real_t p_radius, const Color &p_color);
void draw_texture(const Ref<Texture2D> &p_texture, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1, 1));
void draw_texture_rect(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false);
@@ -262,7 +262,7 @@ public:
void draw_msdf_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), double p_outline = 0.0, double p_pixel_range = 4.0, double p_scale = 1.0);
void draw_lcd_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1));
void draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect);
- void draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture = Ref<Texture2D>(), real_t p_width = 1);
+ void draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture = Ref<Texture2D>());
void draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture2D> p_texture = Ref<Texture2D>());
void draw_colored_polygon(const Vector<Point2> &p_points, const Color &p_color, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture2D> p_texture = Ref<Texture2D>());
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index b5c587c0aa..fbe11c94d1 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -1134,7 +1134,6 @@ Error SceneTree::change_scene_to_packed(const Ref<PackedScene> &p_scene) {
ERR_FAIL_COND_V_MSG(p_scene.is_null(), ERR_INVALID_PARAMETER, "Can't change to a null scene. Use unload_current_scene() if you wish to unload it.");
Node *new_scene = p_scene->instantiate();
- new_scene = p_scene->instantiate();
ERR_FAIL_COND_V(!new_scene, ERR_CANT_CREATE);
call_deferred(SNAME("_change_scene"), new_scene);
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 7ca1f9d3ec..ef58386b45 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -1256,6 +1256,7 @@ void Viewport::_gui_show_tooltip() {
panel->set_transient(true);
panel->set_flag(Window::FLAG_NO_FOCUS, true);
panel->set_flag(Window::FLAG_POPUP, false);
+ panel->set_flag(Window::FLAG_MOUSE_PASSTHROUGH, true);
panel->set_wrap_controls(true);
panel->add_child(base_tooltip);
panel->gui_parent = this;
@@ -1401,7 +1402,7 @@ Control *Viewport::gui_find_control(const Point2 &p_global) {
xform = sw->get_canvas_transform();
}
- Control *ret = _gui_find_control_at_pos(sw, p_global, xform, gui.focus_inv_xform);
+ Control *ret = _gui_find_control_at_pos(sw, p_global, xform);
if (ret) {
return ret;
}
@@ -1410,7 +1411,7 @@ Control *Viewport::gui_find_control(const Point2 &p_global) {
return nullptr;
}
-Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_global, const Transform2D &p_xform, Transform2D &r_inv_xform) {
+Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_global, const Transform2D &p_xform) {
if (!p_node->is_visible()) {
return nullptr; // Canvas item hidden, discard.
}
@@ -1430,7 +1431,7 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_
continue;
}
- Control *ret = _gui_find_control_at_pos(ci, p_global, matrix, r_inv_xform);
+ Control *ret = _gui_find_control_at_pos(ci, p_global, matrix);
if (ret) {
return ret;
}
@@ -1448,7 +1449,6 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_
Control *drag_preview = _gui_get_drag_preview();
if (!drag_preview || (c != drag_preview && !drag_preview->is_ancestor_of(c))) {
- r_inv_xform = matrix;
return c;
}
@@ -1495,12 +1495,11 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Point2 mpos = mb->get_position();
if (mb->is_pressed()) {
- Size2 pos = mpos;
if (!gui.mouse_focus_mask.is_empty()) {
// Do not steal mouse focus and stuff while a focus mask exists.
gui.mouse_focus_mask.set_flag(mouse_button_to_mask(mb->get_button_index()));
} else {
- gui.mouse_focus = gui_find_control(pos);
+ gui.mouse_focus = gui_find_control(mpos);
gui.last_mouse_focus = gui.mouse_focus;
if (!gui.mouse_focus) {
@@ -1519,10 +1518,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
mb = mb->xformed_by(Transform2D()); // Make a copy of the event.
- mb->set_global_position(pos);
-
- pos = gui.focus_inv_xform.xform(pos);
-
+ Point2 pos = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse().xform(mpos);
mb->set_position(pos);
#ifdef DEBUG_ENABLED
@@ -1586,11 +1582,8 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
return;
}
- Size2 pos = mpos;
-
mb = mb->xformed_by(Transform2D()); // Make a copy.
- mb->set_global_position(pos);
- pos = gui.focus_inv_xform.xform(pos);
+ Point2 pos = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse().xform(mpos);
mb->set_position(pos);
Control *mouse_focus = gui.mouse_focus;
@@ -1893,11 +1886,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
bool stopped = false;
if (over->can_process()) {
touch_event = touch_event->xformed_by(Transform2D()); // Make a copy.
- if (over == gui.mouse_focus) {
- pos = gui.focus_inv_xform.xform(pos);
- } else {
- pos = over->get_global_transform_with_canvas().affine_inverse().xform(pos);
- }
+ pos = over->get_global_transform_with_canvas().affine_inverse().xform(pos);
touch_event->set_position(pos);
stopped = _gui_call_input(over, touch_event);
}
@@ -1912,11 +1901,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
Control *over = control_id.is_valid() ? Object::cast_to<Control>(ObjectDB::get_instance(control_id)) : nullptr;
if (over && over->can_process()) {
touch_event = touch_event->xformed_by(Transform2D()); // Make a copy.
- if (over == gui.last_mouse_focus) {
- pos = gui.focus_inv_xform.xform(pos);
- } else {
- pos = over->get_global_transform_with_canvas().affine_inverse().xform(pos);
- }
+ pos = gui.last_mouse_focus->get_global_transform_with_canvas().affine_inverse().xform(pos);
touch_event->set_position(pos);
stopped = _gui_call_input(over, touch_event);
@@ -1942,11 +1927,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
bool stopped = false;
if (over->can_process()) {
gesture_event = gesture_event->xformed_by(Transform2D()); // Make a copy.
- if (over == gui.mouse_focus) {
- pos = gui.focus_inv_xform.xform(pos);
- } else {
- pos = over->get_global_transform_with_canvas().affine_inverse().xform(pos);
- }
+ pos = over->get_global_transform_with_canvas().affine_inverse().xform(pos);
gesture_event->set_position(pos);
stopped = _gui_call_input(over, gesture_event);
}
@@ -2393,7 +2374,6 @@ void Viewport::_post_gui_grab_click_focus() {
}
gui.mouse_focus = focus_grabber;
- gui.focus_inv_xform = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse();
click = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse().xform(gui.last_mouse_pos);
for (int i = 0; i < 3; i++) {
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 9f182682d7..603e92b071 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -374,7 +374,6 @@ private:
ObjectID drag_preview_id;
Ref<SceneTreeTimer> tooltip_timer;
double tooltip_delay = 0.0;
- Transform2D focus_inv_xform;
bool roots_order_dirty = false;
List<Control *> roots;
int canvas_sort_index = 0; //for sorting items with canvas as root
@@ -403,7 +402,7 @@ private:
void _gui_call_notification(Control *p_control, int p_what);
void _gui_sort_roots();
- Control *_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_global, const Transform2D &p_xform, Transform2D &r_inv_xform);
+ Control *_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_global, const Transform2D &p_xform);
void _gui_input_event(Ref<InputEvent> p_event);
void _perform_drop(Control *p_control = nullptr, Point2 p_pos = Point2());
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index c5dbfffd7b..4baedc8c14 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -489,6 +489,7 @@ void Window::_make_window() {
ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID);
DisplayServer::get_singleton()->window_set_max_size(Size2i(), window_id);
DisplayServer::get_singleton()->window_set_min_size(Size2i(), window_id);
+ DisplayServer::get_singleton()->window_set_mouse_passthrough(mpath, window_id);
String tr_title = atr(title);
#ifdef DEBUG_ENABLED
if (window_id == DisplayServer::MAIN_WINDOW_ID) {
@@ -1235,6 +1236,18 @@ DisplayServer::WindowID Window::get_window_id() const {
return window_id;
}
+void Window::set_mouse_passthrough_polygon(const Vector<Vector2> &p_region) {
+ mpath = p_region;
+ if (window_id == DisplayServer::INVALID_WINDOW_ID) {
+ return;
+ }
+ DisplayServer::get_singleton()->window_set_mouse_passthrough(mpath, window_id);
+}
+
+Vector<Vector2> Window::get_mouse_passthrough_polygon() const {
+ return mpath;
+}
+
void Window::set_wrap_controls(bool p_enable) {
wrap_controls = p_enable;
if (wrap_controls) {
@@ -2163,6 +2176,9 @@ void Window::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_use_font_oversampling", "enable"), &Window::set_use_font_oversampling);
ClassDB::bind_method(D_METHOD("is_using_font_oversampling"), &Window::is_using_font_oversampling);
+ ClassDB::bind_method(D_METHOD("set_mouse_passthrough_polygon", "polygon"), &Window::set_mouse_passthrough_polygon);
+ ClassDB::bind_method(D_METHOD("get_mouse_passthrough_polygon"), &Window::get_mouse_passthrough_polygon);
+
ClassDB::bind_method(D_METHOD("set_wrap_controls", "enable"), &Window::set_wrap_controls);
ClassDB::bind_method(D_METHOD("is_wrapping_controls"), &Window::is_wrapping_controls);
ClassDB::bind_method(D_METHOD("child_controls_changed"), &Window::child_controls_changed);
@@ -2243,6 +2259,8 @@ void Window::_bind_methods() {
}
ADD_PROPERTY(PropertyInfo(Variant::INT, "current_screen", PROPERTY_HINT_ENUM, screen_hints), "set_current_screen", "get_current_screen");
+ ADD_PROPERTY(PropertyInfo(Variant::PACKED_VECTOR2_ARRAY, "mouse_passthrough_polygon"), "set_mouse_passthrough_polygon", "get_mouse_passthrough_polygon");
+
ADD_GROUP("Flags", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "wrap_controls"), "set_wrap_controls", "is_wrapping_controls");
@@ -2255,6 +2273,7 @@ void Window::_bind_methods() {
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "unfocusable"), "set_flag", "get_flag", FLAG_NO_FOCUS);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "popup_window"), "set_flag", "get_flag", FLAG_POPUP);
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "extend_to_title"), "set_flag", "get_flag", FLAG_EXTEND_TO_TITLE);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "mouse_passthrough"), "set_flag", "get_flag", FLAG_MOUSE_PASSTHROUGH);
ADD_GROUP("Limits", "");
ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "min_size", PROPERTY_HINT_NONE, "suffix:px"), "set_min_size", "get_min_size");
@@ -2302,6 +2321,7 @@ void Window::_bind_methods() {
BIND_ENUM_CONSTANT(FLAG_NO_FOCUS);
BIND_ENUM_CONSTANT(FLAG_POPUP);
BIND_ENUM_CONSTANT(FLAG_EXTEND_TO_TITLE);
+ BIND_ENUM_CONSTANT(FLAG_MOUSE_PASSTHROUGH);
BIND_ENUM_CONSTANT(FLAG_MAX);
BIND_ENUM_CONSTANT(CONTENT_SCALE_MODE_DISABLED);
diff --git a/scene/main/window.h b/scene/main/window.h
index b4887437a1..d819ca7c60 100644
--- a/scene/main/window.h
+++ b/scene/main/window.h
@@ -59,6 +59,7 @@ public:
FLAG_NO_FOCUS = DisplayServer::WINDOW_FLAG_NO_FOCUS,
FLAG_POPUP = DisplayServer::WINDOW_FLAG_POPUP,
FLAG_EXTEND_TO_TITLE = DisplayServer::WINDOW_FLAG_EXTEND_TO_TITLE,
+ FLAG_MOUSE_PASSTHROUGH = DisplayServer::WINDOW_FLAG_MOUSE_PASSTHROUGH,
FLAG_MAX = DisplayServer::WINDOW_FLAG_MAX,
};
@@ -101,6 +102,7 @@ private:
mutable Size2i size = Size2i(DEFAULT_WINDOW_SIZE, DEFAULT_WINDOW_SIZE);
mutable Size2i min_size;
mutable Size2i max_size;
+ mutable Vector<Vector2> mpath;
mutable Mode mode = MODE_WINDOWED;
mutable bool flags[FLAG_MAX] = {};
bool visible = true;
@@ -281,6 +283,9 @@ public:
void set_use_font_oversampling(bool p_oversampling);
bool is_using_font_oversampling() const;
+ void set_mouse_passthrough_polygon(const Vector<Vector2> &p_region);
+ Vector<Vector2> get_mouse_passthrough_polygon() const;
+
void set_wrap_controls(bool p_enable);
bool is_wrapping_controls() const;
void child_controls_changed();
diff --git a/scene/resources/convex_polygon_shape_2d.cpp b/scene/resources/convex_polygon_shape_2d.cpp
index d92d4fa4a4..e51b48a4b1 100644
--- a/scene/resources/convex_polygon_shape_2d.cpp
+++ b/scene/resources/convex_polygon_shape_2d.cpp
@@ -82,7 +82,7 @@ void ConvexPolygonShape2D::draw(const RID &p_to_rid, const Color &p_color) {
if (is_collision_outline_enabled()) {
RenderingServer::get_singleton()->canvas_item_add_polyline(p_to_rid, points, col);
// Draw the last segment as it's not drawn by `canvas_item_add_polyline()`.
- RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color, 1.0, true);
+ RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, points[points.size() - 1], points[0], p_color, 1.0);
}
}
diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp
index 4043b73b71..94e78fc3aa 100644
--- a/scene/resources/tile_set.cpp
+++ b/scene/resources/tile_set.cpp
@@ -473,6 +473,7 @@ void TileSet::_compute_next_source_id() {
int TileSet::add_source(Ref<TileSetSource> p_tile_set_source, int p_atlas_source_id_override) {
ERR_FAIL_COND_V(!p_tile_set_source.is_valid(), TileSet::INVALID_SOURCE);
ERR_FAIL_COND_V_MSG(p_atlas_source_id_override >= 0 && (sources.has(p_atlas_source_id_override)), TileSet::INVALID_SOURCE, vformat("Cannot create TileSet atlas source. Another atlas source exists with id %d.", p_atlas_source_id_override));
+ ERR_FAIL_COND_V_MSG(p_atlas_source_id_override < 0 && p_atlas_source_id_override != TileSet::INVALID_SOURCE, TileSet::INVALID_SOURCE, vformat("Provided source ID %d is not valid. Negative source IDs are not allowed.", p_atlas_source_id_override));
int new_source_id = p_atlas_source_id_override >= 0 ? p_atlas_source_id_override : next_source_id;
sources[new_source_id] = p_tile_set_source;