summaryrefslogtreecommitdiff
path: root/scene/main
diff options
context:
space:
mode:
Diffstat (limited to 'scene/main')
-rw-r--r--scene/main/canvas_item.cpp13
-rw-r--r--scene/main/canvas_item.h2
-rw-r--r--scene/main/node.cpp250
-rw-r--r--scene/main/node.h53
-rw-r--r--scene/main/scene_tree.cpp23
-rw-r--r--scene/main/scene_tree.h8
-rw-r--r--scene/main/viewport.cpp101
-rw-r--r--scene/main/viewport.h19
-rw-r--r--scene/main/window.cpp10
9 files changed, 327 insertions, 152 deletions
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp
index f2415eaf71..64b169b1fb 100644
--- a/scene/main/canvas_item.cpp
+++ b/scene/main/canvas_item.cpp
@@ -151,9 +151,7 @@ void CanvasItem::_update_callback() {
current_item_drawn = this;
notification(NOTIFICATION_DRAW);
emit_signal(SceneStringNames::get_singleton()->draw);
- if (get_script_instance()) {
- get_script_instance()->call(SceneStringNames::get_singleton()->_draw);
- }
+ GDVIRTUAL_CALL(_draw);
current_item_drawn = nullptr;
drawing = false;
}
@@ -573,6 +571,12 @@ void CanvasItem::draw_texture_rect_region(const Ref<Texture2D> &p_texture, const
p_texture->draw_rect_region(canvas_item, p_rect, p_src_rect, p_modulate, p_transpose, p_clip_uv);
}
+void CanvasItem::draw_msdf_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, double p_outline, double p_pixel_range) {
+ ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
+ ERR_FAIL_COND(p_texture.is_null());
+ RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(canvas_item, p_rect, p_texture->get_rid(), p_src_rect, p_modulate, p_outline, p_pixel_range);
+}
+
void CanvasItem::draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect) {
ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal.");
@@ -883,6 +887,7 @@ void CanvasItem::_bind_methods() {
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));
ClassDB::bind_method(D_METHOD("draw_texture_rect_region", "texture", "rect", "src_rect", "modulate", "transpose", "clip_uv"), &CanvasItem::draw_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false), DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("draw_msdf_texture_rect_region", "texture", "rect", "src_rect", "modulate", "outline", "pixel_range"), &CanvasItem::draw_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(0.0), DEFVAL(4.0));
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_polygon", "points", "colors", "uvs", "texture"), &CanvasItem::draw_polygon, DEFVAL(PackedVector2Array()), DEFVAL(Ref<Texture2D>()));
@@ -934,7 +939,7 @@ void CanvasItem::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_clip_children", "enable"), &CanvasItem::set_clip_children);
ClassDB::bind_method(D_METHOD("is_clipping_children"), &CanvasItem::is_clipping_children);
- BIND_VMETHOD(MethodInfo("_draw"));
+ GDVIRTUAL_BIND(_draw);
ADD_GROUP("Visibility", "");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h
index dc7ad2bf5d..01ed47d4dc 100644
--- a/scene/main/canvas_item.h
+++ b/scene/main/canvas_item.h
@@ -142,6 +142,7 @@ protected:
void _notification(int p_what);
static void _bind_methods();
+ GDVIRTUAL0(_draw)
public:
enum {
NOTIFICATION_TRANSFORM_CHANGED = SceneTree::NOTIFICATION_TRANSFORM_CHANGED, //unique
@@ -225,6 +226,7 @@ public:
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);
void draw_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), bool p_transpose = false, bool p_clip_uv = false);
+ 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);
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_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture2D> p_texture = Ref<Texture2D>());
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 155af30a6d..f2a2648140 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -48,22 +48,18 @@
#include <stdint.h>
VARIANT_ENUM_CAST(Node::ProcessMode);
+VARIANT_ENUM_CAST(Node::InternalMode);
int Node::orphan_node_count = 0;
void Node::_notification(int p_notification) {
switch (p_notification) {
case NOTIFICATION_PROCESS: {
- if (get_script_instance()) {
- Variant time = get_process_delta_time();
- get_script_instance()->call(SceneStringNames::get_singleton()->_process, time);
- }
+ GDVIRTUAL_CALL(_process, get_process_delta_time());
+
} break;
case NOTIFICATION_PHYSICS_PROCESS: {
- if (get_script_instance()) {
- Variant time = get_physics_process_delta_time();
- get_script_instance()->call(SceneStringNames::get_singleton()->_physics_process, time);
- }
+ GDVIRTUAL_CALL(_physics_process, get_physics_process_delta_time());
} break;
case NOTIFICATION_ENTER_TREE: {
@@ -128,27 +124,26 @@ void Node::_notification(int p_notification) {
} break;
case NOTIFICATION_READY: {
if (get_script_instance()) {
- if (get_script_instance()->has_method(SceneStringNames::get_singleton()->_input)) {
+ if (GDVIRTUAL_IS_OVERRIDDEN(_input)) {
set_process_input(true);
}
- if (get_script_instance()->has_method(SceneStringNames::get_singleton()->_unhandled_input)) {
+ if (GDVIRTUAL_IS_OVERRIDDEN(_unhandled_input)) {
set_process_unhandled_input(true);
}
- if (get_script_instance()->has_method(SceneStringNames::get_singleton()->_unhandled_key_input)) {
+ if (GDVIRTUAL_IS_OVERRIDDEN(_unhandled_key_input)) {
set_process_unhandled_key_input(true);
}
- if (get_script_instance()->has_method(SceneStringNames::get_singleton()->_process)) {
+ if (GDVIRTUAL_IS_OVERRIDDEN(_process)) {
set_process(true);
}
-
- if (get_script_instance()->has_method(SceneStringNames::get_singleton()->_physics_process)) {
+ if (GDVIRTUAL_IS_OVERRIDDEN(_physics_process)) {
set_physics_process(true);
}
- get_script_instance()->call(SceneStringNames::get_singleton()->_ready);
+ GDVIRTUAL_CALL(_ready);
}
if (data.filename.length()) {
ERR_FAIL_COND(!is_inside_tree());
@@ -221,9 +216,7 @@ void Node::_propagate_enter_tree() {
notification(NOTIFICATION_ENTER_TREE);
- if (get_script_instance()) {
- get_script_instance()->call(SceneStringNames::get_singleton()->_enter_tree);
- }
+ GDVIRTUAL_CALL(_enter_tree);
emit_signal(SceneStringNames::get_singleton()->tree_entered);
@@ -269,9 +262,8 @@ void Node::_propagate_exit_tree() {
data.blocked--;
- if (get_script_instance()) {
- get_script_instance()->call(SceneStringNames::get_singleton()->_exit_tree);
- }
+ GDVIRTUAL_CALL(_exit_tree);
+
emit_signal(SceneStringNames::get_singleton()->tree_exiting);
notification(NOTIFICATION_EXIT_TREE, true);
@@ -300,14 +292,40 @@ void Node::_propagate_exit_tree() {
void Node::move_child(Node *p_child, int p_pos) {
ERR_FAIL_NULL(p_child);
- ERR_FAIL_INDEX_MSG(p_pos, data.children.size() + 1, vformat("Invalid new child position: %d.", p_pos));
ERR_FAIL_COND_MSG(p_child->data.parent != this, "Child is not a child of this node.");
+
+ // We need to check whether node is internal and move it only in the relevant node range.
+ if (p_child->_is_internal_front()) {
+ ERR_FAIL_INDEX_MSG(p_pos, data.internal_children_front, vformat("Invalid new child position: %d. Child is internal.", p_pos));
+ _move_child(p_child, p_pos);
+ } else if (p_child->_is_internal_back()) {
+ ERR_FAIL_INDEX_MSG(p_pos, data.internal_children_back, vformat("Invalid new child position: %d. Child is internal.", p_pos));
+ _move_child(p_child, data.children.size() - data.internal_children_back + p_pos);
+ } else {
+ ERR_FAIL_INDEX_MSG(p_pos, data.children.size() + 1 - data.internal_children_front - data.internal_children_back, vformat("Invalid new child position: %d.", p_pos));
+ _move_child(p_child, p_pos + data.internal_children_front);
+ }
+}
+
+void Node::_move_child(Node *p_child, int p_pos, bool p_ignore_end) {
ERR_FAIL_COND_MSG(data.blocked > 0, "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).");
// Specifying one place beyond the end
// means the same as moving to the last position
- if (p_pos == data.children.size()) {
- p_pos--;
+ if (!p_ignore_end) { // p_ignore_end is a little hack to make back internal children work properly.
+ if (p_child->_is_internal_front()) {
+ if (p_pos == data.internal_children_front) {
+ p_pos--;
+ }
+ } else if (p_child->_is_internal_back()) {
+ if (p_pos == data.children.size()) {
+ p_pos--;
+ }
+ } else {
+ if (p_pos == data.children.size() - data.internal_children_back) {
+ p_pos--;
+ }
+ }
}
if (p_child->data.pos == p_pos) {
@@ -348,7 +366,14 @@ void Node::raise() {
return;
}
- data.parent->move_child(this, data.parent->data.children.size() - 1);
+ // Internal children move within a different index range.
+ if (_is_internal_front()) {
+ data.parent->move_child(this, data.parent->data.internal_children_front - 1);
+ } else if (_is_internal_back()) {
+ data.parent->move_child(this, data.parent->data.internal_children_back - 1);
+ } else {
+ data.parent->move_child(this, data.parent->get_child_count(false) - 1);
+ }
}
void Node::add_child_notify(Node *p_child) {
@@ -492,24 +517,24 @@ void Node::_propagate_process_owner(Node *p_owner, int p_pause_notification, int
}
}
-void Node::set_network_master(int p_peer_id, bool p_recursive) {
- data.network_master = p_peer_id;
+void Node::set_network_authority(int p_peer_id, bool p_recursive) {
+ data.network_authority = p_peer_id;
if (p_recursive) {
for (int i = 0; i < data.children.size(); i++) {
- data.children[i]->set_network_master(p_peer_id, true);
+ data.children[i]->set_network_authority(p_peer_id, true);
}
}
}
-int Node::get_network_master() const {
- return data.network_master;
+int Node::get_network_authority() const {
+ return data.network_authority;
}
-bool Node::is_network_master() const {
+bool Node::is_network_authority() const {
ERR_FAIL_COND_V(!is_inside_tree(), false);
- return get_multiplayer()->get_network_unique_id() == data.network_master;
+ return get_multiplayer()->get_network_unique_id() == data.network_authority;
}
/***** RPC CONFIG ********/
@@ -1067,6 +1092,10 @@ void Node::_add_child_nocheck(Node *p_child, const StringName &p_name) {
p_child->data.pos = data.children.size();
data.children.push_back(p_child);
p_child->data.parent = this;
+
+ if (data.internal_children_back > 0) {
+ _move_child(p_child, data.children.size() - data.internal_children_back - 1);
+ }
p_child->notification(NOTIFICATION_PARENTED);
if (data.tree) {
@@ -1079,7 +1108,7 @@ void Node::_add_child_nocheck(Node *p_child, const StringName &p_name) {
add_child_notify(p_child);
}
-void Node::add_child(Node *p_child, bool p_legible_unique_name) {
+void Node::add_child(Node *p_child, bool p_legible_unique_name, InternalMode p_internal) {
ERR_FAIL_NULL(p_child);
ERR_FAIL_COND_MSG(p_child == this, vformat("Can't add child '%s' to itself.", p_child->get_name())); // adding to itself!
ERR_FAIL_COND_MSG(p_child->data.parent, vformat("Can't add child '%s' to '%s', already has a parent '%s'.", p_child->get_name(), get_name(), p_child->data.parent->get_name())); //Fail if node has a parent
@@ -1088,19 +1117,35 @@ void Node::add_child(Node *p_child, bool p_legible_unique_name) {
#endif
ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, add_node() failed. Consider using call_deferred(\"add_child\", child) instead.");
- /* Validate name */
_validate_child_name(p_child, p_legible_unique_name);
-
_add_child_nocheck(p_child, p_child->data.name);
+
+ if (p_internal == INTERNAL_MODE_FRONT) {
+ _move_child(p_child, data.internal_children_front);
+ data.internal_children_front++;
+ } else if (p_internal == INTERNAL_MODE_BACK) {
+ if (data.internal_children_back > 0) {
+ _move_child(p_child, data.children.size() - 1, true);
+ }
+ data.internal_children_back++;
+ }
}
void Node::add_sibling(Node *p_sibling, bool p_legible_unique_name) {
ERR_FAIL_NULL(p_sibling);
+ ERR_FAIL_NULL(data.parent);
ERR_FAIL_COND_MSG(p_sibling == this, vformat("Can't add sibling '%s' to itself.", p_sibling->get_name())); // adding to itself!
ERR_FAIL_COND_MSG(data.blocked > 0, "Parent node is busy setting up children, add_sibling() failed. Consider using call_deferred(\"add_sibling\", sibling) instead.");
- get_parent()->add_child(p_sibling, p_legible_unique_name);
- get_parent()->move_child(p_sibling, this->get_index() + 1);
+ InternalMode internal = INTERNAL_MODE_DISABLED;
+ if (_is_internal_front()) { // The sibling will have the same internal status.
+ internal = INTERNAL_MODE_FRONT;
+ } else if (_is_internal_back()) {
+ internal = INTERNAL_MODE_BACK;
+ }
+
+ data.parent->add_child(p_sibling, p_legible_unique_name, internal);
+ data.parent->_move_child(p_sibling, get_index() + 1);
}
void Node::_propagate_validate_owner() {
@@ -1154,7 +1199,12 @@ void Node::remove_child(Node *p_child) {
ERR_FAIL_COND_MSG(idx == -1, vformat("Cannot remove child node '%s' as it is not a child of this node.", p_child->get_name()));
//ERR_FAIL_COND( p_child->data.blocked > 0 );
- //if (data.scene) { does not matter
+ // If internal child, update the counter.
+ if (p_child->_is_internal_front()) {
+ data.internal_children_front--;
+ } else if (p_child->_is_internal_back()) {
+ data.internal_children_back--;
+ }
p_child->_set_tree(nullptr);
//}
@@ -1184,17 +1234,29 @@ void Node::remove_child(Node *p_child) {
}
}
-int Node::get_child_count() const {
- return data.children.size();
+int Node::get_child_count(bool p_include_internal) const {
+ if (p_include_internal) {
+ return data.children.size();
+ } else {
+ return data.children.size() - data.internal_children_front - data.internal_children_back;
+ }
}
-Node *Node::get_child(int p_index) const {
- if (p_index < 0) {
- p_index += data.children.size();
+Node *Node::get_child(int p_index, bool p_include_internal) const {
+ if (p_include_internal) {
+ if (p_index < 0) {
+ p_index += data.children.size();
+ }
+ ERR_FAIL_INDEX_V(p_index, data.children.size(), nullptr);
+ return data.children[p_index];
+ } else {
+ if (p_index < 0) {
+ p_index += data.children.size() - data.internal_children_front - data.internal_children_back;
+ }
+ ERR_FAIL_INDEX_V(p_index, data.children.size() - data.internal_children_front - data.internal_children_back, nullptr);
+ p_index += data.internal_children_front;
+ return data.children[p_index];
}
- ERR_FAIL_INDEX_V(p_index, data.children.size(), nullptr);
-
- return data.children[p_index];
}
Node *Node::_get_child_by_name(const StringName &p_name) const {
@@ -1726,7 +1788,13 @@ void Node::_propagate_replace_owner(Node *p_owner, Node *p_by_owner) {
data.blocked--;
}
-int Node::get_index() const {
+int Node::get_index(bool p_include_internal) const {
+ // p_include_internal = false doesn't make sense if the node is internal.
+ ERR_FAIL_COND_V_MSG(!p_include_internal && (_is_internal_front() || _is_internal_back()), -1, "Node is internal. Can't get index with 'include_internal' being false.");
+
+ if (data.parent && !p_include_internal) {
+ return data.pos - data.parent->data.internal_children_front;
+ }
return data.pos;
}
@@ -2438,12 +2506,12 @@ void Node::queue_delete() {
}
}
-TypedArray<Node> Node::_get_children() const {
+TypedArray<Node> Node::_get_children(bool p_include_internal) const {
TypedArray<Node> arr;
- int cc = get_child_count();
+ int cc = get_child_count(p_include_internal);
arr.resize(cc);
for (int i = 0; i < cc; i++) {
- arr[i] = get_child(i);
+ arr[i] = get_child(i, p_include_internal);
}
return arr;
@@ -2496,9 +2564,14 @@ void Node::clear_internal_tree_resource_paths() {
}
TypedArray<String> Node::get_configuration_warnings() const {
- if (get_script_instance() && get_script_instance()->get_script().is_valid() &&
- get_script_instance()->get_script()->is_tool() && get_script_instance()->has_method("_get_configuration_warnings")) {
- return get_script_instance()->call("_get_configuration_warnings");
+ Vector<String> warnings;
+ if (GDVIRTUAL_CALL(_get_configuration_warnings, warnings)) {
+ TypedArray<String> ret;
+ ret.resize(warnings.size());
+ for (int i = 0; i < warnings.size(); i++) {
+ ret[i] = warnings[i];
+ }
+ return ret;
}
return Array();
}
@@ -2544,6 +2617,37 @@ void Node::request_ready() {
data.ready_first = true;
}
+void Node::_call_input(const Ref<InputEvent> &p_event) {
+ GDVIRTUAL_CALL(_input, p_event);
+ if (!is_inside_tree() || !get_viewport() || get_viewport()->is_input_handled()) {
+ return;
+ }
+ input(p_event);
+}
+void Node::_call_unhandled_input(const Ref<InputEvent> &p_event) {
+ GDVIRTUAL_CALL(_unhandled_input, p_event);
+ if (!is_inside_tree() || !get_viewport() || get_viewport()->is_input_handled()) {
+ return;
+ }
+ unhandled_input(p_event);
+}
+void Node::_call_unhandled_key_input(const Ref<InputEvent> &p_event) {
+ GDVIRTUAL_CALL(_unhandled_key_input, p_event);
+ if (!is_inside_tree() || !get_viewport() || get_viewport()->is_input_handled()) {
+ return;
+ }
+ unhandled_key_input(p_event);
+}
+
+void Node::input(const Ref<InputEvent> &p_event) {
+}
+
+void Node::unhandled_input(const Ref<InputEvent> &p_event) {
+}
+
+void Node::unhandled_key_input(const Ref<InputEvent> &p_key_event) {
+}
+
void Node::_bind_methods() {
GLOBAL_DEF("editor/node_naming/name_num_separator", 0);
ProjectSettings::get_singleton()->set_custom_property_info("editor/node_naming/name_num_separator", PropertyInfo(Variant::INT, "editor/node_naming/name_num_separator", PROPERTY_HINT_ENUM, "None,Space,Underscore,Dash"));
@@ -2554,11 +2658,11 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_name", "name"), &Node::set_name);
ClassDB::bind_method(D_METHOD("get_name"), &Node::get_name);
- ClassDB::bind_method(D_METHOD("add_child", "node", "legible_unique_name"), &Node::add_child, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("add_child", "node", "legible_unique_name", "internal"), &Node::add_child, DEFVAL(false), DEFVAL(0));
ClassDB::bind_method(D_METHOD("remove_child", "node"), &Node::remove_child);
- ClassDB::bind_method(D_METHOD("get_child_count"), &Node::get_child_count);
- ClassDB::bind_method(D_METHOD("get_children"), &Node::_get_children);
- ClassDB::bind_method(D_METHOD("get_child", "idx"), &Node::get_child);
+ ClassDB::bind_method(D_METHOD("get_child_count", "include_internal"), &Node::get_child_count, DEFVAL(false)); // Note that the default value bound for include_internal is false, while the method is declared with true. This is because internal nodes are irrelevant for GDSCript.
+ ClassDB::bind_method(D_METHOD("get_children", "include_internal"), &Node::_get_children, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("get_child", "idx", "include_internal"), &Node::get_child, DEFVAL(false));
ClassDB::bind_method(D_METHOD("has_node", "path"), &Node::has_node);
ClassDB::bind_method(D_METHOD("get_node", "path"), &Node::get_node);
ClassDB::bind_method(D_METHOD("get_node_or_null", "path"), &Node::get_node_or_null);
@@ -2582,7 +2686,7 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_owner", "owner"), &Node::set_owner);
ClassDB::bind_method(D_METHOD("get_owner"), &Node::get_owner);
ClassDB::bind_method(D_METHOD("remove_and_skip"), &Node::remove_and_skip);
- ClassDB::bind_method(D_METHOD("get_index"), &Node::get_index);
+ ClassDB::bind_method(D_METHOD("get_index", "include_internal"), &Node::get_index, DEFVAL(false));
ClassDB::bind_method(D_METHOD("print_tree"), &Node::print_tree);
ClassDB::bind_method(D_METHOD("print_tree_pretty"), &Node::print_tree_pretty);
ClassDB::bind_method(D_METHOD("set_filename", "filename"), &Node::set_filename);
@@ -2625,6 +2729,8 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_scene_instance_load_placeholder", "load_placeholder"), &Node::set_scene_instance_load_placeholder);
ClassDB::bind_method(D_METHOD("get_scene_instance_load_placeholder"), &Node::get_scene_instance_load_placeholder);
+ ClassDB::bind_method(D_METHOD("set_editable_instance", "node", "is_editable"), &Node::set_editable_instance);
+ ClassDB::bind_method(D_METHOD("is_editable_instance", "node"), &Node::is_editable_instance);
ClassDB::bind_method(D_METHOD("get_viewport"), &Node::get_viewport);
@@ -2632,10 +2738,10 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("request_ready"), &Node::request_ready);
- ClassDB::bind_method(D_METHOD("set_network_master", "id", "recursive"), &Node::set_network_master, DEFVAL(true));
- ClassDB::bind_method(D_METHOD("get_network_master"), &Node::get_network_master);
+ ClassDB::bind_method(D_METHOD("set_network_authority", "id", "recursive"), &Node::set_network_authority, DEFVAL(true));
+ ClassDB::bind_method(D_METHOD("get_network_authority"), &Node::get_network_authority);
- ClassDB::bind_method(D_METHOD("is_network_master"), &Node::is_network_master);
+ ClassDB::bind_method(D_METHOD("is_network_authority"), &Node::is_network_authority);
ClassDB::bind_method(D_METHOD("get_multiplayer"), &Node::get_multiplayer);
ClassDB::bind_method(D_METHOD("get_custom_multiplayer"), &Node::get_custom_multiplayer);
@@ -2718,6 +2824,10 @@ void Node::_bind_methods() {
BIND_ENUM_CONSTANT(DUPLICATE_SCRIPTS);
BIND_ENUM_CONSTANT(DUPLICATE_USE_INSTANCING);
+ BIND_ENUM_CONSTANT(INTERNAL_MODE_DISABLED);
+ BIND_ENUM_CONSTANT(INTERNAL_MODE_FRONT);
+ BIND_ENUM_CONSTANT(INTERNAL_MODE_BACK);
+
ADD_SIGNAL(MethodInfo("ready"));
ADD_SIGNAL(MethodInfo("renamed"));
ADD_SIGNAL(MethodInfo("tree_entered"));
@@ -2737,15 +2847,15 @@ void Node::_bind_methods() {
ADD_GROUP("Editor Description", "editor_");
ADD_PROPERTY(PropertyInfo(Variant::STRING, "editor_description", PROPERTY_HINT_MULTILINE_TEXT, "", PROPERTY_USAGE_EDITOR | PROPERTY_USAGE_INTERNAL), "set_editor_description", "get_editor_description");
- BIND_VMETHOD(MethodInfo("_process", PropertyInfo(Variant::FLOAT, "delta")));
- BIND_VMETHOD(MethodInfo("_physics_process", PropertyInfo(Variant::FLOAT, "delta")));
- BIND_VMETHOD(MethodInfo("_enter_tree"));
- BIND_VMETHOD(MethodInfo("_exit_tree"));
- BIND_VMETHOD(MethodInfo("_ready"));
- BIND_VMETHOD(MethodInfo("_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
- BIND_VMETHOD(MethodInfo("_unhandled_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
- BIND_VMETHOD(MethodInfo("_unhandled_key_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEventKey")));
- BIND_VMETHOD(MethodInfo(PropertyInfo(Variant::ARRAY, "", PROPERTY_HINT_ARRAY_TYPE, "String"), "_get_configuration_warnings"));
+ GDVIRTUAL_BIND(_process, "delta");
+ GDVIRTUAL_BIND(_physics_process, "delta");
+ GDVIRTUAL_BIND(_enter_tree);
+ GDVIRTUAL_BIND(_exit_tree);
+ GDVIRTUAL_BIND(_ready);
+ GDVIRTUAL_BIND(_get_configuration_warnings);
+ GDVIRTUAL_BIND(_input, "event");
+ GDVIRTUAL_BIND(_unhandled_input, "event");
+ GDVIRTUAL_BIND(_unhandled_key_input, "event");
}
String Node::_get_name_num_separator() {
diff --git a/scene/main/node.h b/scene/main/node.h
index 9997f4e055..d0246ebe84 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -73,6 +73,12 @@ public:
NAME_CASING_SNAKE_CASE
};
+ enum InternalMode {
+ INTERNAL_MODE_DISABLED,
+ INTERNAL_MODE_FRONT,
+ INTERNAL_MODE_BACK,
+ };
+
struct Comparator {
bool operator()(const Node *p_a, const Node *p_b) const { return p_b->is_greater_than(p_a); }
};
@@ -97,6 +103,8 @@ private:
Node *parent = nullptr;
Node *owner = nullptr;
Vector<Node *> children;
+ int internal_children_front = 0;
+ int internal_children_back = 0;
int pos = -1;
int depth = -1;
int blocked = 0; // Safeguard that throws an error when attempting to modify the tree in a harmful way while being traversed.
@@ -119,7 +127,7 @@ private:
ProcessMode process_mode = PROCESS_MODE_INHERIT;
Node *process_owner = nullptr;
- int network_master = 1; // Server by default.
+ int network_authority = 1; // Server by default.
Vector<MultiplayerAPI::RPCConfig> rpc_methods;
// Variables used to properly sort the node when processing, ignored otherwise.
@@ -172,12 +180,15 @@ private:
void _duplicate_signals(const Node *p_original, Node *p_copy) const;
Node *_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap = nullptr) const;
- TypedArray<Node> _get_children() const;
+ TypedArray<Node> _get_children(bool p_include_internal = true) const;
Array _get_groups() const;
Variant _rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
Variant _rpc_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
+ _FORCE_INLINE_ bool _is_internal_front() const { return data.parent && data.pos < data.parent->data.internal_children_front; }
+ _FORCE_INLINE_ bool _is_internal_back() const { return data.parent && data.pos >= data.parent->data.children.size() - data.parent->data.internal_children_back; }
+
friend class SceneTree;
void _set_tree(SceneTree *p_tree);
@@ -202,12 +213,33 @@ protected:
static String _get_name_num_separator();
friend class SceneState;
- friend class MultiplayerAPI;
+ friend class MultiplayerReplicator;
void _add_child_nocheck(Node *p_child, const StringName &p_name);
void _set_owner_nocheck(Node *p_owner);
void _set_name_nocheck(const StringName &p_name);
+ //call from SceneTree
+ void _call_input(const Ref<InputEvent> &p_event);
+ void _call_unhandled_input(const Ref<InputEvent> &p_event);
+ void _call_unhandled_key_input(const Ref<InputEvent> &p_event);
+
+protected:
+ virtual void input(const Ref<InputEvent> &p_event);
+ virtual void unhandled_input(const Ref<InputEvent> &p_event);
+ virtual void unhandled_key_input(const Ref<InputEvent> &p_key_event);
+
+ GDVIRTUAL1(_process, double)
+ GDVIRTUAL1(_physics_process, double)
+ GDVIRTUAL0(_enter_tree)
+ GDVIRTUAL0(_exit_tree)
+ GDVIRTUAL0(_ready)
+ GDVIRTUAL0RC(Vector<String>, _get_configuration_warnings)
+
+ GDVIRTUAL1(_input, Ref<InputEvent>)
+ GDVIRTUAL1(_unhandled_input, Ref<InputEvent>)
+ GDVIRTUAL1(_unhandled_key_input, Ref<InputEvent>)
+
public:
enum {
// you can make your own, but don't use the same numbers as other notifications in other nodes
@@ -263,12 +295,12 @@ public:
StringName get_name() const;
void set_name(const String &p_name);
- void add_child(Node *p_child, bool p_legible_unique_name = false);
+ void add_child(Node *p_child, bool p_legible_unique_name = false, InternalMode p_internal = INTERNAL_MODE_DISABLED);
void add_sibling(Node *p_sibling, bool p_legible_unique_name = false);
void remove_child(Node *p_child);
- int get_child_count() const;
- Node *get_child(int p_index) const;
+ int get_child_count(bool p_include_internal = true) const;
+ Node *get_child(int p_index, bool p_include_internal = true) const;
bool has_node(const NodePath &p_path) const;
Node *get_node(const NodePath &p_path) const;
Node *get_node_or_null(const NodePath &p_path) const;
@@ -306,6 +338,7 @@ public:
int get_persistent_group_count() const;
void move_child(Node *p_child, int p_pos);
+ void _move_child(Node *p_child, int p_pos, bool p_ignore_end = false);
void raise();
void set_owner(Node *p_owner);
@@ -313,7 +346,7 @@ public:
void get_owned_by(Node *p_by, List<Node *> *p_owned);
void remove_and_skip();
- int get_index() const;
+ int get_index(bool p_include_internal = true) const;
Ref<Tween> create_tween();
@@ -429,9 +462,9 @@ public:
bool is_displayed_folded() const;
/* NETWORK */
- void set_network_master(int p_peer_id, bool p_recursive = true);
- int get_network_master() const;
- bool is_network_master() const;
+ void set_network_authority(int p_peer_id, bool p_recursive = true);
+ int get_network_authority() const;
+ bool is_network_authority() const;
uint16_t rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, MultiplayerPeer::TransferMode p_transfer_mode, int p_channel = 0); // config a local method for RPC
Vector<MultiplayerAPI::RPCConfig> get_node_rpc_methods() const;
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 5b707498a7..8260d0dff5 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -867,7 +867,7 @@ void SceneMainLoop::_update_listener_2d() {
*/
-void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input, Viewport *p_viewport) {
+void SceneTree::_call_input_pause(const StringName &p_group, CallInputType p_call_type, const Ref<InputEvent> &p_input, Viewport *p_viewport) {
Map<StringName, Group>::Element *E = group_map.find(p_group);
if (!E) {
return;
@@ -886,9 +886,6 @@ void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p
int node_count = nodes_copy.size();
Node **nodes = nodes_copy.ptrw();
- Variant arg = p_input;
- const Variant *v[1] = { &arg };
-
call_lock++;
for (int i = node_count - 1; i >= 0; i--) {
@@ -905,14 +902,16 @@ void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p
continue;
}
- Callable::CallError err;
- // Call both script and native method.
- if (n->get_script_instance()) {
- n->get_script_instance()->call(p_method, (const Variant **)v, 1, err);
- }
- MethodBind *method = ClassDB::get_method(n->get_class_name(), p_method);
- if (method) {
- method->call(n, (const Variant **)v, 1, err);
+ switch (p_call_type) {
+ case CALL_INPUT_TYPE_INPUT:
+ n->_call_input(p_input);
+ break;
+ case CALL_INPUT_TYPE_UNHANDLED_INPUT:
+ n->_call_unhandled_input(p_input);
+ break;
+ case CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT:
+ n->_call_unhandled_key_input(p_input);
+ break;
}
}
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index cfb95bd6b5..b1b94ae910 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -204,8 +204,14 @@ private:
void _main_window_close();
void _main_window_go_back();
+ enum CallInputType {
+ CALL_INPUT_TYPE_INPUT,
+ CALL_INPUT_TYPE_UNHANDLED_INPUT,
+ CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT,
+ };
+
//used by viewport
- void _call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input, Viewport *p_viewport);
+ void _call_input_pause(const StringName &p_group, CallInputType p_call_type, const Ref<InputEvent> &p_input, Viewport *p_viewport);
protected:
void _notification(int p_notification);
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 78fa0985a9..8ec8c193fb 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -32,6 +32,7 @@
#include "core/core_string_names.h"
#include "core/debugger/engine_debugger.h"
+#include "core/object/message_queue.h"
#include "core/string/translation.h"
#include "core/templates/pair.h"
#include "scene/2d/camera_2d.h"
@@ -45,12 +46,14 @@
#include "scene/gui/control.h"
#include "scene/gui/label.h"
#include "scene/gui/popup.h"
+#include "scene/gui/popup_menu.h"
#include "scene/main/canvas_layer.h"
#include "scene/main/window.h"
#include "scene/resources/mesh.h"
#include "scene/resources/text_line.h"
#include "scene/resources/world_2d.h"
#include "scene/scene_string_names.h"
+#include "servers/audio_server.h"
void ViewportTexture::setup_local_to_scene() {
if (vp) {
@@ -662,7 +665,7 @@ void Viewport::_process_picking() {
}
if (send_event) {
- co->_input_event(this, ev, res[i].shape);
+ co->_input_event_call(this, ev, res[i].shape);
}
}
}
@@ -819,12 +822,7 @@ Rect2 Viewport::get_visible_rect() const {
}
void Viewport::_update_listener_2d() {
- /*
- if (is_inside_tree() && audio_listener_3d && (!get_parent() || (Object::cast_to<Control>(get_parent()) && Object::cast_to<Control>(get_parent())->is_visible_in_tree())))
- SpatialSound2DServer::get_singleton()->listener_set_space(internal_listener_2d, find_world_2d()->get_sound_space());
- else
- SpatialSound2DServer::get_singleton()->listener_set_space(internal_listener_2d, RID());
-*/
+ AudioServer::get_singleton()->notify_listener_changed();
}
void Viewport::set_as_audio_listener_2d(bool p_enable) {
@@ -1104,6 +1102,12 @@ String Viewport::_gui_get_tooltip(Control *p_control, const Vector2 &p_pos, Cont
while (p_control) {
tooltip = p_control->get_tooltip(pos);
+ //Temporary solution for PopupMenus
+ PopupMenu *menu = Object::cast_to<PopupMenu>(this);
+ if (menu) {
+ tooltip = menu->get_tooltip(pos);
+ }
+
if (r_tooltip_owner) {
*r_tooltip_owner = p_control;
}
@@ -1234,27 +1238,7 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu
Control *control = Object::cast_to<Control>(ci);
if (control) {
if (control->data.mouse_filter != Control::MOUSE_FILTER_IGNORE) {
- control->emit_signal(SceneStringNames::get_singleton()->gui_input, ev); //signal should be first, so it's possible to override an event (and then accept it)
- }
- if (gui.key_event_accepted) {
- break;
- }
- if (!control->is_inside_tree()) {
- break;
- }
-
- if (control->data.mouse_filter != Control::MOUSE_FILTER_IGNORE) {
- // Call both script and native methods.
- Callable::CallError error;
- Variant event = ev;
- const Variant *args[1] = { &event };
- if (control->get_script_instance()) {
- control->get_script_instance()->call(SceneStringNames::get_singleton()->_gui_input, args, 1, error);
- }
- MethodBind *method = ClassDB::get_method(control->get_class_name(), SceneStringNames::get_singleton()->_gui_input);
- if (method) {
- method->call(control, args, 1, error);
- }
+ control->_call_gui_input(ev);
}
if (!control->is_inside_tree() || control->is_set_as_top_level()) {
@@ -1982,10 +1966,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (gui.key_focus) {
gui.key_event_accepted = false;
if (gui.key_focus->can_process()) {
- gui.key_focus->call(SceneStringNames::get_singleton()->_gui_input, p_event);
- if (gui.key_focus) { //maybe lost it
- gui.key_focus->emit_signal(SceneStringNames::get_singleton()->gui_input, p_event);
- }
+ gui.key_focus->_call_gui_input(p_event);
}
if (gui.key_event_accepted) {
@@ -2205,7 +2186,7 @@ void Viewport::_drop_mouse_focus() {
mb->set_global_position(c->get_local_mouse_position());
mb->set_button_index(MouseButton(i + 1));
mb->set_pressed(false);
- c->call(SceneStringNames::get_singleton()->_gui_input, mb);
+ c->_call_gui_input(mb);
}
}
}
@@ -2317,7 +2298,7 @@ void Viewport::_post_gui_grab_click_focus() {
mb->set_position(click);
mb->set_button_index(MouseButton(i + 1));
mb->set_pressed(false);
- gui.mouse_focus->call(SceneStringNames::get_singleton()->_gui_input, mb);
+ gui.mouse_focus->_call_gui_input(mb);
}
}
@@ -2335,7 +2316,7 @@ void Viewport::_post_gui_grab_click_focus() {
mb->set_position(click);
mb->set_button_index(MouseButton(i + 1));
mb->set_pressed(true);
- gui.mouse_focus->call_deferred(SceneStringNames::get_singleton()->_gui_input, mb);
+ MessageQueue::get_singleton()->push_callable(callable_mp(gui.mouse_focus, &Control::_call_gui_input), mb);
}
}
}
@@ -2343,9 +2324,9 @@ void Viewport::_post_gui_grab_click_focus() {
///////////////////////////////
-void Viewport::input_text(const String &p_text) {
+void Viewport::push_text_input(const String &p_text) {
if (gui.subwindow_focused) {
- gui.subwindow_focused->input_text(p_text);
+ gui.subwindow_focused->push_text_input(p_text);
return;
}
@@ -2665,7 +2646,7 @@ bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
return true;
}
-void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) {
+void Viewport::push_input(const Ref<InputEvent> &p_event, bool p_local_coords) {
ERR_FAIL_COND(!is_inside_tree());
if (disable_input) {
@@ -2695,7 +2676,7 @@ void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) {
}
if (!is_input_handled()) {
- get_tree()->_call_input_pause(input_group, "_input", ev, this); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input
+ get_tree()->_call_input_pause(input_group, SceneTree::CALL_INPUT_TYPE_INPUT, ev, this); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input
}
if (!is_input_handled()) {
@@ -2703,10 +2684,9 @@ void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) {
}
event_count++;
- //get_tree()->call_group(SceneTree::GROUP_CALL_REVERSE|SceneTree::GROUP_CALL_REALTIME|SceneTree::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",ev); //special one for GUI, as controls use their own process check
}
-void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords) {
+void Viewport::push_unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords) {
ERR_FAIL_COND(p_event.is_null());
ERR_FAIL_COND(!is_inside_tree());
local_input_handled = false;
@@ -2727,11 +2707,11 @@ void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coor
}
// Unhandled Input
- get_tree()->_call_input_pause(unhandled_input_group, "_unhandled_input", ev, this);
+ get_tree()->_call_input_pause(unhandled_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_INPUT, ev, this);
// Unhandled key Input - used for performance reasons - This is called a lot less than _unhandled_input since it ignores MouseMotion, etc
if (!is_input_handled() && (Object::cast_to<InputEventKey>(*ev) != nullptr || Object::cast_to<InputEventShortcut>(*ev) != nullptr)) {
- get_tree()->_call_input_pause(unhandled_key_input_group, "_unhandled_key_input", ev, this);
+ get_tree()->_call_input_pause(unhandled_key_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT, ev, this);
}
if (physics_object_picking && !is_input_handled()) {
@@ -3095,6 +3075,7 @@ bool Viewport::is_audio_listener_3d() const {
}
void Viewport::_update_listener_3d() {
+ AudioServer::get_singleton()->notify_listener_changed();
}
void Viewport::_listener_transform_3d_changed_notify() {
@@ -3159,7 +3140,7 @@ void Viewport::_collision_object_3d_input_event(CollisionObject3D *p_object, Cam
return; //discarded
}
}
- p_object->_input_event(camera_3d, p_input_event, p_pos, p_normal, p_shape);
+ p_object->_input_event_call(camera_3d, p_input_event, p_pos, p_normal, p_shape);
physics_last_object_transform = object_transform;
physics_last_camera_transform = camera_transform;
physics_last_id = id;
@@ -3474,6 +3455,17 @@ void Viewport::set_use_xr(bool p_use_xr) {
bool Viewport::is_using_xr() {
return use_xr;
}
+
+void Viewport::set_scale_3d(const Scale3D p_scale_3d) {
+ scale_3d = p_scale_3d;
+
+ RS::get_singleton()->viewport_set_scale_3d(viewport, RS::ViewportScale3D(scale_3d));
+}
+
+Viewport::Scale3D Viewport::get_scale_3d() const {
+ return scale_3d;
+}
+
#endif // _3D_DISABLED
void Viewport::_bind_methods() {
@@ -3515,9 +3507,9 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_physics_object_picking"), &Viewport::get_physics_object_picking);
ClassDB::bind_method(D_METHOD("get_viewport_rid"), &Viewport::get_viewport_rid);
- ClassDB::bind_method(D_METHOD("input_text", "text"), &Viewport::input_text);
- ClassDB::bind_method(D_METHOD("input", "event", "in_local_coords"), &Viewport::input, DEFVAL(false));
- ClassDB::bind_method(D_METHOD("unhandled_input", "event", "in_local_coords"), &Viewport::unhandled_input, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("push_text_input", "text"), &Viewport::push_text_input);
+ ClassDB::bind_method(D_METHOD("push_input", "event", "in_local_coords"), &Viewport::push_input, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("push_unhandled_input", "event", "in_local_coords"), &Viewport::push_unhandled_input, DEFVAL(false));
ClassDB::bind_method(D_METHOD("get_camera_2d"), &Viewport::get_camera_2d);
ClassDB::bind_method(D_METHOD("set_as_audio_listener_2d", "enable"), &Viewport::set_as_audio_listener_2d);
@@ -3598,8 +3590,12 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_use_xr", "use"), &Viewport::set_use_xr);
ClassDB::bind_method(D_METHOD("is_using_xr"), &Viewport::is_using_xr);
+ ClassDB::bind_method(D_METHOD("set_scale_3d", "scale"), &Viewport::set_scale_3d);
+ ClassDB::bind_method(D_METHOD("get_scale_3d"), &Viewport::get_scale_3d);
+
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_xr"), "set_use_xr", "is_using_xr");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "scale_3d", PROPERTY_HINT_ENUM, String::utf8("Disabled,75%,50%,33%,25%")), "set_scale_3d", "get_scale_3d");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "audio_listener_enable_3d"), "set_as_audio_listener_3d", "is_audio_listener_3d");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world_3d"), "set_use_own_world_3d", "is_using_own_world_3d");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_3d", PROPERTY_HINT_RESOURCE_TYPE, "World3D"), "set_world_3d", "get_world_3d");
@@ -3643,6 +3639,12 @@ void Viewport::_bind_methods() {
ADD_SIGNAL(MethodInfo("size_changed"));
ADD_SIGNAL(MethodInfo("gui_focus_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
+ BIND_ENUM_CONSTANT(SCALE_3D_DISABLED);
+ BIND_ENUM_CONSTANT(SCALE_3D_75_PERCENT);
+ BIND_ENUM_CONSTANT(SCALE_3D_50_PERCENT);
+ BIND_ENUM_CONSTANT(SCALE_3D_33_PERCENT);
+ BIND_ENUM_CONSTANT(SCALE_3D_25_PERCENT);
+
BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED);
BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_1);
BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_4);
@@ -3757,6 +3759,11 @@ Viewport::Viewport() {
gui.tooltip_delay = GLOBAL_DEF("gui/timers/tooltip_delay_sec", 0.5);
ProjectSettings::get_singleton()->set_custom_property_info("gui/timers/tooltip_delay_sec", PropertyInfo(Variant::FLOAT, "gui/timers/tooltip_delay_sec", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater")); // No negative numbers
+#ifndef _3D_DISABLED
+ int scale = GLOBAL_GET("rendering/3d/viewport/scale");
+ set_scale_3d((Scale3D)scale);
+#endif // _3D_DISABLED
+
set_sdf_oversize(sdf_oversize); //set to server
}
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 9c51f404d7..d9b21ce6a8 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -88,6 +88,14 @@ class Viewport : public Node {
GDCLASS(Viewport, Node);
public:
+ enum Scale3D {
+ SCALE_3D_DISABLED,
+ SCALE_3D_75_PERCENT,
+ SCALE_3D_50_PERCENT,
+ SCALE_3D_33_PERCENT,
+ SCALE_3D_25_PERCENT
+ };
+
enum ShadowAtlasQuadrantSubdiv {
SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED,
SHADOW_ATLAS_QUADRANT_SUBDIV_1,
@@ -508,9 +516,9 @@ public:
Vector2 get_camera_coords(const Vector2 &p_viewport_coords) const;
Vector2 get_camera_rect_size() const;
- void input_text(const String &p_text);
- void input(const Ref<InputEvent> &p_event, bool p_local_coords = false);
- void unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords = false);
+ void push_text_input(const String &p_text);
+ void push_input(const Ref<InputEvent> &p_event, bool p_local_coords = false);
+ void push_unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords = false);
void set_disable_input(bool p_disable);
bool is_input_disabled() const;
@@ -577,6 +585,7 @@ public:
#ifndef _3D_DISABLED
bool use_xr = false;
+ Scale3D scale_3d = SCALE_3D_DISABLED;
friend class Listener3D;
Listener3D *listener_3d = nullptr;
Set<Listener3D *> listener_3d_set;
@@ -647,6 +656,9 @@ public:
void set_use_xr(bool p_use_xr);
bool is_using_xr();
+
+ void set_scale_3d(const Scale3D p_scale_3d);
+ Scale3D get_scale_3d() const;
#endif // _3D_DISABLED
Viewport();
@@ -705,6 +717,7 @@ VARIANT_ENUM_CAST(SubViewport::UpdateMode);
VARIANT_ENUM_CAST(Viewport::ShadowAtlasQuadrantSubdiv);
VARIANT_ENUM_CAST(Viewport::MSAA);
VARIANT_ENUM_CAST(Viewport::ScreenSpaceAA);
+VARIANT_ENUM_CAST(Viewport::Scale3D);
VARIANT_ENUM_CAST(Viewport::DebugDraw);
VARIANT_ENUM_CAST(Viewport::SDFScale);
VARIANT_ENUM_CAST(Viewport::SDFOversize);
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 73eec73d75..1fcfce2ea9 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -659,8 +659,8 @@ void Window::_update_viewport_size() {
if (!use_font_oversampling) {
font_oversampling = 1.0;
}
- if (TS->font_get_oversampling() != font_oversampling) {
- TS->font_set_oversampling(font_oversampling);
+ if (TS->font_get_global_oversampling() != font_oversampling) {
+ TS->font_set_global_oversampling(font_oversampling);
}
}
@@ -916,14 +916,14 @@ void Window::_window_input(const Ref<InputEvent> &p_ev) {
emit_signal(SceneStringNames::get_singleton()->window_input, p_ev);
- input(p_ev);
+ push_input(p_ev);
if (!is_input_handled()) {
- unhandled_input(p_ev);
+ push_unhandled_input(p_ev);
}
}
void Window::_window_input_text(const String &p_text) {
- input_text(p_text);
+ push_text_input(p_text);
}
void Window::_window_drop_files(const Vector<String> &p_files) {