diff options
Diffstat (limited to 'scene/main')
-rw-r--r-- | scene/main/canvas_item.cpp | 15 | ||||
-rw-r--r-- | scene/main/canvas_item.h | 2 | ||||
-rw-r--r-- | scene/main/canvas_layer.cpp | 2 | ||||
-rw-r--r-- | scene/main/http_request.cpp | 5 | ||||
-rw-r--r-- | scene/main/http_request.h | 2 | ||||
-rw-r--r-- | scene/main/instance_placeholder.cpp | 2 | ||||
-rw-r--r-- | scene/main/node.cpp | 338 | ||||
-rw-r--r-- | scene/main/node.h | 56 | ||||
-rw-r--r-- | scene/main/scene_tree.cpp | 75 | ||||
-rw-r--r-- | scene/main/scene_tree.h | 9 | ||||
-rw-r--r-- | scene/main/shader_globals_override.cpp | 2 | ||||
-rw-r--r-- | scene/main/timer.cpp | 6 | ||||
-rw-r--r-- | scene/main/viewport.cpp | 77 | ||||
-rw-r--r-- | scene/main/viewport.h | 18 |
14 files changed, 220 insertions, 389 deletions
diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 181fe606c8..361f584a5d 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -876,6 +876,17 @@ void CanvasItem::draw_set_transform_matrix(const Transform2D &p_matrix) { RenderingServer::get_singleton()->canvas_item_add_set_transform(canvas_item, p_matrix); } +void CanvasItem::draw_animation_slice(double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset) { + ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); + + RenderingServer::get_singleton()->canvas_item_add_animation_slice(canvas_item, p_animation_length, p_slice_begin, p_slice_end, p_offset); +} + +void CanvasItem::draw_end_animation() { + ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); + + RenderingServer::get_singleton()->canvas_item_add_animation_slice(canvas_item, 1, 0, 2, 0); +} void CanvasItem::draw_polygon(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."); @@ -1159,6 +1170,8 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_multimesh", "multimesh", "texture"), &CanvasItem::draw_multimesh); ClassDB::bind_method(D_METHOD("draw_set_transform", "position", "rotation", "scale"), &CanvasItem::draw_set_transform, DEFVAL(0.0), DEFVAL(Size2(1.0, 1.0))); ClassDB::bind_method(D_METHOD("draw_set_transform_matrix", "xform"), &CanvasItem::draw_set_transform_matrix); + ClassDB::bind_method(D_METHOD("draw_animation_slice", "animation_length", "slice_begin", "slice_end", "offset"), &CanvasItem::draw_animation_slice, DEFVAL(0.0)); + ClassDB::bind_method(D_METHOD("draw_end_animation"), &CanvasItem::draw_end_animation); ClassDB::bind_method(D_METHOD("get_transform"), &CanvasItem::get_transform); ClassDB::bind_method(D_METHOD("get_global_transform"), &CanvasItem::get_global_transform); ClassDB::bind_method(D_METHOD("get_global_transform_with_canvas"), &CanvasItem::get_global_transform_with_canvas); @@ -1205,7 +1218,7 @@ void CanvasItem::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::COLOR, "self_modulate"), "set_self_modulate", "get_self_modulate"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_behind_parent"), "set_draw_behind_parent", "is_draw_behind_parent_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "top_level"), "set_as_top_level", "is_set_as_top_level"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_on_top", PROPERTY_HINT_NONE, "", 0), "_set_on_top", "_is_on_top"); //compatibility + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_on_top", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "_set_on_top", "_is_on_top"); //compatibility ADD_PROPERTY(PropertyInfo(Variant::BOOL, "clip_children"), "set_clip_children", "is_clipping_children"); ADD_PROPERTY(PropertyInfo(Variant::INT, "light_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_light_mask", "get_light_mask"); diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h index 1c64cafab8..afdd18d76b 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -356,6 +356,8 @@ public: void draw_set_transform(const Point2 &p_offset, real_t p_rot = 0.0, const Size2 &p_scale = Size2(1.0, 1.0)); void draw_set_transform_matrix(const Transform2D &p_matrix); + void draw_animation_slice(double p_animation_length, double p_slice_begin, double p_slice_end, double p_offset = 0); + void draw_end_animation(); static CanvasItem *get_current_item_drawn(); diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp index 85d7edd64b..f699e68715 100644 --- a/scene/main/canvas_layer.cpp +++ b/scene/main/canvas_layer.cpp @@ -303,7 +303,7 @@ void CanvasLayer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "scale"), "set_scale", "get_scale"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform"), "set_transform", "get_transform"); ADD_GROUP("", ""); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_viewport", PROPERTY_HINT_RESOURCE_TYPE, "Viewport", 0), "set_custom_viewport", "get_custom_viewport"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_viewport", PROPERTY_HINT_RESOURCE_TYPE, "Viewport", PROPERTY_USAGE_NONE), "set_custom_viewport", "get_custom_viewport"); ADD_GROUP("Follow Viewport", "follow_viewport"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "follow_viewport_enable"), "set_follow_viewport", "is_following_viewport"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "follow_viewport_scale", PROPERTY_HINT_RANGE, "0.001,1000,0.001,or_greater,or_lesser"), "set_follow_viewport_scale", "get_follow_viewport_scale"); diff --git a/scene/main/http_request.cpp b/scene/main/http_request.cpp index 927b114fbc..775dfa4c46 100644 --- a/scene/main/http_request.cpp +++ b/scene/main/http_request.cpp @@ -322,7 +322,8 @@ bool HTTPRequest::_update_connection() { } else { // Did not request yet, do request - Error err = client->request_raw(method, request_string, headers, request_data); + int size = request_data.size(); + Error err = client->request(method, request_string, headers, size > 0 ? request_data.ptr() : nullptr, size); if (err != OK) { call_deferred("_request_done", RESULT_CONNECTION_ERROR, 0, PackedStringArray(), PackedByteArray()); return true; @@ -627,7 +628,7 @@ void HTTPRequest::_bind_methods() { } HTTPRequest::HTTPRequest() { - client.instance(); + client = Ref<HTTPClient>(HTTPClient::create()); timer = memnew(Timer); timer->set_one_shot(true); timer->connect("timeout", callable_mp(this, &HTTPRequest::_timeout)); diff --git a/scene/main/http_request.h b/scene/main/http_request.h index 92b0ff28e9..22e822253f 100644 --- a/scene/main/http_request.h +++ b/scene/main/http_request.h @@ -31,8 +31,8 @@ #ifndef HTTPREQUEST_H #define HTTPREQUEST_H +#include "core/io/file_access.h" #include "core/io/http_client.h" -#include "core/os/file_access.h" #include "core/os/thread.h" #include "core/templates/safe_refcount.h" #include "node.h" diff --git a/scene/main/instance_placeholder.cpp b/scene/main/instance_placeholder.cpp index 1661984e30..89dac5f5a8 100644 --- a/scene/main/instance_placeholder.cpp +++ b/scene/main/instance_placeholder.cpp @@ -88,7 +88,7 @@ Node *InstancePlaceholder::create_instance(bool p_replace, const Ref<PackedScene if (!ps.is_valid()) { return nullptr; } - Node *scene = ps->instance(); + Node *scene = ps->instantiate(); if (!scene) { return nullptr; } diff --git a/scene/main/node.cpp b/scene/main/node.cpp index dc7057f339..9479b1339d 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -35,6 +35,7 @@ #include "core/object/message_queue.h" #include "core/string/print_string.h" #include "instance_placeholder.h" +#include "scene/animation/tween.h" #include "scene/debugger/scene_debugger.h" #include "scene/resources/packed_scene.h" #include "scene/scene_string_names.h" @@ -292,7 +293,7 @@ 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, "Invalid new child position: " + itos(p_pos) + "."); + 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."); 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)."); @@ -491,36 +492,24 @@ bool Node::is_network_master() const { /***** RPC CONFIG ********/ -uint16_t Node::rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_mode) { - uint16_t mid = get_node_rpc_method_id(p_method); - if (mid == UINT16_MAX) { - // It's new - NetData nd; - nd.name = p_method; - nd.mode = p_mode; - data.rpc_methods.push_back(nd); - return ((uint16_t)data.rpc_methods.size() - 1) | (1 << 15); - } else { - int c_mid = (~(1 << 15)) & mid; - data.rpc_methods.write[c_mid].mode = p_mode; - return mid; - } -} - -uint16_t Node::rset_config(const StringName &p_property, MultiplayerAPI::RPCMode p_mode) { - uint16_t pid = get_node_rset_property_id(p_property); - if (pid == UINT16_MAX) { - // It's new - NetData nd; - nd.name = p_property; - nd.mode = p_mode; - data.rpc_properties.push_back(nd); - return ((uint16_t)data.rpc_properties.size() - 1) | (1 << 15); - } else { - int c_pid = (~(1 << 15)) & pid; - data.rpc_properties.write[c_pid].mode = p_mode; - return pid; +uint16_t Node::rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, NetworkedMultiplayerPeer::TransferMode p_transfer_mode, int p_channel) { + for (int i = 0; i < data.rpc_methods.size(); i++) { + if (data.rpc_methods[i].name == p_method) { + MultiplayerAPI::RPCConfig &nd = data.rpc_methods.write[i]; + nd.rpc_mode = p_rpc_mode; + nd.transfer_mode = p_transfer_mode; + nd.channel = p_channel; + return i | (1 << 15); + } } + // New method + MultiplayerAPI::RPCConfig nd; + nd.name = p_method; + nd.rpc_mode = p_rpc_mode; + nd.transfer_mode = p_transfer_mode; + nd.channel = p_channel; + data.rpc_methods.push_back(nd); + return ((uint16_t)data.rpc_methods.size() - 1) | (1 << 15); } /***** RPC FUNCTIONS ********/ @@ -536,7 +525,7 @@ void Node::rpc(const StringName &p_method, VARIANT_ARG_DECLARE) { argc++; } - rpcp(0, false, p_method, argptr, argc); + rpcp(0, p_method, argptr, argc); } void Node::rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_DECLARE) { @@ -550,35 +539,7 @@ void Node::rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_DECLARE argc++; } - rpcp(p_peer_id, false, p_method, argptr, argc); -} - -void Node::rpc_unreliable(const StringName &p_method, VARIANT_ARG_DECLARE) { - VARIANT_ARGPTRS; - - int argc = 0; - for (int i = 0; i < VARIANT_ARG_MAX; i++) { - if (argptr[i]->get_type() == Variant::NIL) { - break; - } - argc++; - } - - rpcp(0, true, p_method, argptr, argc); -} - -void Node::rpc_unreliable_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_DECLARE) { - VARIANT_ARGPTRS; - - int argc = 0; - for (int i = 0; i < VARIANT_ARG_MAX; i++) { - if (argptr[i]->get_type() == Variant::NIL) { - break; - } - argc++; - } - - rpcp(p_peer_id, true, p_method, argptr, argc); + rpcp(p_peer_id, p_method, argptr, argc); } Variant Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { @@ -597,7 +558,7 @@ Variant Node::_rpc_bind(const Variant **p_args, int p_argcount, Callable::CallEr StringName method = *p_args[0]; - rpcp(0, false, method, &p_args[1], p_argcount - 1); + rpcp(0, method, &p_args[1], p_argcount - 1); r_error.error = Callable::CallError::CALL_OK; return Variant(); @@ -627,92 +588,17 @@ Variant Node::_rpc_id_bind(const Variant **p_args, int p_argcount, Callable::Cal int peer_id = *p_args[0]; StringName method = *p_args[1]; - rpcp(peer_id, false, method, &p_args[2], p_argcount - 2); + rpcp(peer_id, method, &p_args[2], p_argcount - 2); r_error.error = Callable::CallError::CALL_OK; return Variant(); } -Variant Node::_rpc_unreliable_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - if (p_argcount < 1) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 1; - return Variant(); - } - - if (p_args[0]->get_type() != Variant::STRING_NAME) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::STRING_NAME; - return Variant(); - } - - StringName method = *p_args[0]; - - rpcp(0, true, method, &p_args[1], p_argcount - 1); - - r_error.error = Callable::CallError::CALL_OK; - return Variant(); -} - -Variant Node::_rpc_unreliable_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error) { - if (p_argcount < 2) { - r_error.error = Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS; - r_error.argument = 2; - return Variant(); - } - - if (p_args[0]->get_type() != Variant::INT) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 0; - r_error.expected = Variant::INT; - return Variant(); - } - - if (p_args[1]->get_type() != Variant::STRING_NAME) { - r_error.error = Callable::CallError::CALL_ERROR_INVALID_ARGUMENT; - r_error.argument = 1; - r_error.expected = Variant::STRING_NAME; - return Variant(); - } - - int peer_id = *p_args[0]; - StringName method = *p_args[1]; - - rpcp(peer_id, true, method, &p_args[2], p_argcount - 2); - - r_error.error = Callable::CallError::CALL_OK; - return Variant(); -} - -void Node::rpcp(int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount) { - ERR_FAIL_COND(!is_inside_tree()); - get_multiplayer()->rpcp(this, p_peer_id, p_unreliable, p_method, p_arg, p_argcount); -} - -void Node::rsetp(int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value) { +void Node::rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount) { ERR_FAIL_COND(!is_inside_tree()); - get_multiplayer()->rsetp(this, p_peer_id, p_unreliable, p_property, p_value); -} - -/******** RSET *********/ -void Node::rset(const StringName &p_property, const Variant &p_value) { - rsetp(0, false, p_property, p_value); + get_multiplayer()->rpcp(this, p_peer_id, true, p_method, p_arg, p_argcount); } -void Node::rset_id(int p_peer_id, const StringName &p_property, const Variant &p_value) { - rsetp(p_peer_id, false, p_property, p_value); -} - -void Node::rset_unreliable(const StringName &p_property, const Variant &p_value) { - rsetp(0, true, p_property, p_value); -} - -void Node::rset_unreliable_id(int p_peer_id, const StringName &p_property, const Variant &p_value) { - rsetp(p_peer_id, true, p_property, p_value); -} - -//////////// end of rpc Ref<MultiplayerAPI> Node::get_multiplayer() const { if (multiplayer.is_valid()) { return multiplayer; @@ -731,99 +617,11 @@ void Node::set_custom_multiplayer(Ref<MultiplayerAPI> p_multiplayer) { multiplayer = p_multiplayer; } -uint16_t Node::get_node_rpc_method_id(const StringName &p_method) const { - for (int i = 0; i < data.rpc_methods.size(); i++) { - if (data.rpc_methods[i].name == p_method) { - // Returns `i` with the high bit set to 1 so we know that this id comes - // from the node and not the script. - return i | (1 << 15); - } - } - return UINT16_MAX; -} - -StringName Node::get_node_rpc_method(const uint16_t p_rpc_method_id) const { - // Make sure this is a node generated ID. - if (((1 << 15) & p_rpc_method_id) > 0) { - int mid = (~(1 << 15)) & p_rpc_method_id; - if (mid < data.rpc_methods.size()) { - return data.rpc_methods[mid].name; - } - } - return StringName(); -} - -MultiplayerAPI::RPCMode Node::get_node_rpc_mode_by_id(const uint16_t p_rpc_method_id) const { - // Make sure this is a node generated ID. - if (((1 << 15) & p_rpc_method_id) > 0) { - int mid = (~(1 << 15)) & p_rpc_method_id; - if (mid < data.rpc_methods.size()) { - return data.rpc_methods[mid].mode; - } - } - return MultiplayerAPI::RPC_MODE_DISABLED; -} - -MultiplayerAPI::RPCMode Node::get_node_rpc_mode(const StringName &p_method) const { - return get_node_rpc_mode_by_id(get_node_rpc_method_id(p_method)); -} - -uint16_t Node::get_node_rset_property_id(const StringName &p_property) const { - for (int i = 0; i < data.rpc_properties.size(); i++) { - if (data.rpc_properties[i].name == p_property) { - // Returns `i` with the high bit set to 1 so we know that this id comes - // from the node and not the script. - return i | (1 << 15); - } - } - return UINT16_MAX; -} - -StringName Node::get_node_rset_property(const uint16_t p_rset_property_id) const { - // Make sure this is a node generated ID. - if (((1 << 15) & p_rset_property_id) > 0) { - int mid = (~(1 << 15)) & p_rset_property_id; - if (mid < data.rpc_properties.size()) { - return data.rpc_properties[mid].name; - } - } - return StringName(); -} - -MultiplayerAPI::RPCMode Node::get_node_rset_mode_by_id(const uint16_t p_rset_property_id) const { - if (((1 << 15) & p_rset_property_id) > 0) { - int mid = (~(1 << 15)) & p_rset_property_id; - if (mid < data.rpc_properties.size()) { - return data.rpc_properties[mid].mode; - } - } - return MultiplayerAPI::RPC_MODE_DISABLED; -} - -MultiplayerAPI::RPCMode Node::get_node_rset_mode(const StringName &p_property) const { - return get_node_rset_mode_by_id(get_node_rset_property_id(p_property)); +Vector<MultiplayerAPI::RPCConfig> Node::get_node_rpc_methods() const { + return data.rpc_methods; } -String Node::get_rpc_md5() const { - String rpc_list; - for (int i = 0; i < data.rpc_methods.size(); i += 1) { - rpc_list += String(data.rpc_methods[i].name); - } - for (int i = 0; i < data.rpc_properties.size(); i += 1) { - rpc_list += String(data.rpc_properties[i].name); - } - if (get_script_instance()) { - Vector<ScriptNetData> rpc = get_script_instance()->get_rpc_methods(); - for (int i = 0; i < rpc.size(); i += 1) { - rpc_list += String(rpc[i].name); - } - rpc = get_script_instance()->get_rset_properties(); - for (int i = 0; i < rpc.size(); i += 1) { - rpc_list += String(rpc[i].name); - } - } - return rpc_list.md5_text(); -} +//////////// end of rpc bool Node::can_process_notification(int p_what) const { switch (p_what) { @@ -1240,8 +1038,11 @@ void Node::_add_child_nocheck(Node *p_child, const StringName &p_name) { void Node::add_child(Node *p_child, bool p_legible_unique_name) { ERR_FAIL_NULL(p_child); - ERR_FAIL_COND_MSG(p_child == this, "Can't add child '" + p_child->get_name() + "' to itself."); // adding to itself! - ERR_FAIL_COND_MSG(p_child->data.parent, "Can't add child '" + p_child->get_name() + "' to '" + get_name() + "', already has a parent '" + p_child->data.parent->get_name() + "'."); //Fail if node has a parent + 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 +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_MSG(p_child->is_ancestor_of(this), vformat("Can't add child '%s' to '%s' as it would result in a cyclic dependency since '%s' is already a parent of '%s'.", p_child->get_name(), get_name(), p_child->get_name(), get_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 */ @@ -1252,7 +1053,7 @@ void Node::add_child(Node *p_child, bool p_legible_unique_name) { void Node::add_sibling(Node *p_sibling, bool p_legible_unique_name) { ERR_FAIL_NULL(p_sibling); - ERR_FAIL_COND_MSG(p_sibling == this, "Can't add sibling '" + p_sibling->get_name() + "' to itself."); // adding to itself! + 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); @@ -1307,7 +1108,7 @@ void Node::remove_child(Node *p_child) { } } - ERR_FAIL_COND_MSG(idx == -1, "Cannot remove child node " + p_child->get_name() + " as it is not a child of this node."); + 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 @@ -1483,7 +1284,7 @@ Node *Node::find_parent(const String &p_mask) const { return nullptr; } -bool Node::is_a_parent_of(const Node *p_node) const { +bool Node::is_ancestor_of(const Node *p_node) const { ERR_FAIL_NULL_V(p_node, false); Node *p = p_node->data.parent; while (p) { @@ -1886,6 +1687,13 @@ int Node::get_index() const { return data.pos; } +Ref<Tween> Node::create_tween() { + ERR_FAIL_COND_V_MSG(!data.tree, nullptr, "Can't create Tween when not inside scene tree."); + Ref<Tween> tween = get_tree()->create_tween(); + tween->bind_node(this); + return tween; +} + void Node::remove_and_skip() { ERR_FAIL_COND(!data.parent); @@ -1941,7 +1749,7 @@ String Node::get_editor_description() const { void Node::set_editable_instance(Node *p_node, bool p_editable) { ERR_FAIL_NULL(p_node); - ERR_FAIL_COND(!is_a_parent_of(p_node)); + ERR_FAIL_COND(!is_ancestor_of(p_node)); if (!p_editable) { p_node->data.editable_instance = false; // Avoid this flag being needlessly saved; @@ -1956,13 +1764,13 @@ bool Node::is_editable_instance(const Node *p_node) const { if (!p_node) { return false; // Easier, null is never editable. :) } - ERR_FAIL_COND_V(!is_a_parent_of(p_node), false); + ERR_FAIL_COND_V(!is_ancestor_of(p_node), false); return p_node->data.editable_instance; } Node *Node::get_deepest_editable_node(Node *p_start_node) const { ERR_FAIL_NULL_V(p_start_node, nullptr); - ERR_FAIL_COND_V(!is_a_parent_of(p_start_node), p_start_node); + ERR_FAIL_COND_V(!is_ancestor_of(p_start_node), p_start_node); Node const *iterated_item = p_start_node; Node *node = p_start_node; @@ -2005,7 +1813,7 @@ bool Node::get_scene_instance_load_placeholder() const { Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const { Node *node = nullptr; - bool instanced = false; + bool instantiated = false; if (Object::cast_to<InstancePlaceholder>(this)) { const InstancePlaceholder *ip = Object::cast_to<const InstancePlaceholder>(this); @@ -2022,13 +1830,13 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const ges = PackedScene::GEN_EDIT_STATE_INSTANCE; } #endif - node = res->instance(ges); + node = res->instantiate(ges); ERR_FAIL_COND_V(!node, nullptr); - instanced = true; + instantiated = true; } else { - Object *obj = ClassDB::instance(get_class()); + Object *obj = ClassDB::instantiate(get_class()); ERR_FAIL_COND_V(!obj, nullptr); node = Object::cast_to<Node>(obj); if (!node) { @@ -2048,9 +1856,9 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const List<const Node *> node_tree; node_tree.push_front(this); - if (instanced) { - // Since nodes in the instanced hierarchy won't be duplicated explicitly, we need to make an inventory - // of all the nodes in the tree of the instanced scene in order to transfer the values of the properties + if (instantiated) { + // Since nodes in the instantiated hierarchy won't be duplicated explicitly, we need to make an inventory + // of all the nodes in the tree of the instantiated scene in order to transfer the values of the properties Vector<const Node *> instance_roots; instance_roots.push_back(this); @@ -2058,8 +1866,8 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const for (List<const Node *>::Element *N = node_tree.front(); N; N = N->next()) { for (int i = 0; i < N->get()->get_child_count(); ++i) { Node *descendant = N->get()->get_child(i); - // Skip nodes not really belonging to the instanced hierarchy; they'll be processed normally later - // but remember non-instanced nodes that are hidden below instanced ones + // Skip nodes not really belonging to the instantiated hierarchy; they'll be processed normally later + // but remember non-instantiated nodes that are hidden below instantiated ones if (!instance_roots.has(descendant->get_owner())) { if (descendant->get_parent() && descendant->get_parent() != this && descendant->data.owner != descendant->get_parent()) { hidden_roots.push_back(descendant); @@ -2142,7 +1950,7 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const if (get_child(i)->data.parent_owned) { continue; } - if (instanced && get_child(i)->data.owner == this) { + if (instantiated && get_child(i)->data.owner == this) { continue; //part of instance } @@ -2266,7 +2074,7 @@ void Node::remap_nested_resources(RES p_resource, const Map<RES, RES> &p_resourc // because re-targeting of connections from some descendant to another is not possible // if the emitter node comes later in tree order than the receiver void Node::_duplicate_signals(const Node *p_original, Node *p_copy) const { - if ((this != p_original) && !(p_original->is_a_parent_of(this))) { + if ((this != p_original) && !(p_original->is_ancestor_of(this))) { return; } @@ -2391,7 +2199,7 @@ void Node::_replace_connections_target(Node *p_new_target) { if (c.flags & CONNECT_PERSIST) { c.signal.get_object()->disconnect(c.signal.get_name(), Callable(this, c.callable.get_method())); bool valid = p_new_target->has_method(c.callable.get_method()) || Ref<Script>(p_new_target->get_script()).is_null() || Ref<Script>(p_new_target->get_script())->has_method(c.callable.get_method()); - ERR_CONTINUE_MSG(!valid, "Attempt to connect signal '" + c.signal.get_object()->get_class() + "." + c.signal.get_name() + "' to nonexistent method '" + c.callable.get_object()->get_class() + "." + c.callable.get_method() + "'."); + ERR_CONTINUE_MSG(!valid, vformat("Attempt to connect signal '%s.%s' to nonexistent method '%s.%s'.", c.signal.get_object()->get_class(), c.signal.get_name(), c.callable.get_object()->get_class(), c.callable.get_method())); c.signal.get_object()->connect(c.signal.get_name(), Callable(p_new_target, c.callable.get_method()), c.binds, c.flags); } } @@ -2659,7 +2467,7 @@ void Node::update_configuration_warnings() { if (!is_inside_tree()) { return; } - if (get_tree()->get_edited_scene_root() && (get_tree()->get_edited_scene_root() == this || get_tree()->get_edited_scene_root()->is_a_parent_of(this))) { + if (get_tree()->get_edited_scene_root() && (get_tree()->get_edited_scene_root() == this || get_tree()->get_edited_scene_root()->is_ancestor_of(this))) { get_tree()->emit_signal(SceneStringNames::get_singleton()->node_configuration_warning_changed, this); } #endif @@ -2706,7 +2514,7 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("get_node_and_resource", "path"), &Node::_get_node_and_resource); ClassDB::bind_method(D_METHOD("is_inside_tree"), &Node::is_inside_tree); - ClassDB::bind_method(D_METHOD("is_a_parent_of", "node"), &Node::is_a_parent_of); + ClassDB::bind_method(D_METHOD("is_ancestor_of", "node"), &Node::is_ancestor_of); ClassDB::bind_method(D_METHOD("is_greater_than", "node"), &Node::is_greater_than); ClassDB::bind_method(D_METHOD("get_path"), &Node::get_path); ClassDB::bind_method(D_METHOD("get_path_to", "node"), &Node::get_path_to); @@ -2755,6 +2563,7 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("is_physics_processing_internal"), &Node::is_physics_processing_internal); ClassDB::bind_method(D_METHOD("get_tree"), &Node::get_tree); + ClassDB::bind_method(D_METHOD("create_tween"), &Node::create_tween); ClassDB::bind_method(D_METHOD("duplicate", "flags"), &Node::duplicate, DEFVAL(DUPLICATE_USE_INSTANCING | DUPLICATE_SIGNALS | DUPLICATE_GROUPS | DUPLICATE_SCRIPTS)); ClassDB::bind_method(D_METHOD("replace_by", "node", "keep_groups"), &Node::replace_by, DEFVAL(false)); @@ -2776,8 +2585,7 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("get_multiplayer"), &Node::get_multiplayer); ClassDB::bind_method(D_METHOD("get_custom_multiplayer"), &Node::get_custom_multiplayer); ClassDB::bind_method(D_METHOD("set_custom_multiplayer", "api"), &Node::set_custom_multiplayer); - ClassDB::bind_method(D_METHOD("rpc_config", "method", "mode"), &Node::rpc_config); - ClassDB::bind_method(D_METHOD("rset_config", "property", "mode"), &Node::rset_config); + ClassDB::bind_method(D_METHOD("rpc_config", "method", "rpc_mode", "transfer_mode", "channel"), &Node::rpc_config, DEFVAL(NetworkedMultiplayerPeer::TRANSFER_MODE_RELIABLE), DEFVAL(0)); ClassDB::bind_method(D_METHOD("set_editor_description", "editor_description"), &Node::set_editor_description); ClassDB::bind_method(D_METHOD("get_editor_description"), &Node::get_editor_description); @@ -2794,22 +2602,13 @@ void Node::_bind_methods() { mi.name = "rpc"; ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "rpc", &Node::_rpc_bind, mi); - mi.name = "rpc_unreliable"; - ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "rpc_unreliable", &Node::_rpc_unreliable_bind, mi); mi.arguments.push_front(PropertyInfo(Variant::INT, "peer_id")); mi.name = "rpc_id"; ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "rpc_id", &Node::_rpc_id_bind, mi); - mi.name = "rpc_unreliable_id"; - ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "rpc_unreliable_id", &Node::_rpc_unreliable_id_bind, mi); } - ClassDB::bind_method(D_METHOD("rset", "property", "value"), &Node::rset); - ClassDB::bind_method(D_METHOD("rset_id", "peer_id", "property", "value"), &Node::rset_id); - ClassDB::bind_method(D_METHOD("rset_unreliable", "property", "value"), &Node::rset_unreliable); - ClassDB::bind_method(D_METHOD("rset_unreliable_id", "peer_id", "property", "value"), &Node::rset_unreliable_id); - ClassDB::bind_method(D_METHOD("update_configuration_warnings"), &Node::update_configuration_warnings); BIND_CONSTANT(NOTIFICATION_ENTER_TREE); @@ -2830,6 +2629,9 @@ void Node::_bind_methods() { BIND_CONSTANT(NOTIFICATION_INTERNAL_PHYSICS_PROCESS); BIND_CONSTANT(NOTIFICATION_POST_ENTER_TREE); + BIND_CONSTANT(NOTIFICATION_EDITOR_PRE_SAVE); + BIND_CONSTANT(NOTIFICATION_EDITOR_POST_SAVE); + BIND_CONSTANT(NOTIFICATION_WM_MOUSE_ENTER); BIND_CONSTANT(NOTIFICATION_WM_MOUSE_EXIT); BIND_CONSTANT(NOTIFICATION_WM_WINDOW_FOCUS_IN); @@ -2865,11 +2667,11 @@ void Node::_bind_methods() { ADD_SIGNAL(MethodInfo("tree_exiting")); ADD_SIGNAL(MethodInfo("tree_exited")); - ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "name", PROPERTY_HINT_NONE, "", 0), "set_name", "get_name"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "filename", PROPERTY_HINT_NONE, "", 0), "set_filename", "get_filename"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "owner", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_owner", "get_owner"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", 0), "", "get_multiplayer"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", 0), "set_custom_multiplayer", "get_custom_multiplayer"); + ADD_PROPERTY(PropertyInfo(Variant::STRING_NAME, "name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_name", "get_name"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "filename", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_filename", "get_filename"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "owner", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_owner", "get_owner"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", PROPERTY_USAGE_NONE), "", "get_multiplayer"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "custom_multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", PROPERTY_USAGE_NONE), "set_custom_multiplayer", "get_custom_multiplayer"); ADD_GROUP("Process", "process_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "process_mode", PROPERTY_HINT_ENUM, "Inherit,Pausable,When Paused,Always,Disabled"), "set_process_mode", "get_process_mode"); diff --git a/scene/main/node.h b/scene/main/node.h index 6ca2317d9e..f685eac86a 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -41,6 +41,9 @@ class Viewport; class SceneState; +class Tween; +class PropertyTweener; + class Node : public Object { GDCLASS(Node, Object); OBJ_CATEGORY("Nodes"); @@ -80,11 +83,6 @@ private: SceneTree::Group *group = nullptr; }; - struct NetData { - StringName name; - MultiplayerAPI::RPCMode mode = MultiplayerAPI::RPCMode::RPC_MODE_DISABLED; - }; - struct Data { String filename; Ref<SceneState> instance_state; @@ -116,8 +114,7 @@ private: Node *process_owner = nullptr; int network_master = 1; // Server by default. - Vector<NetData> rpc_methods; - Vector<NetData> rpc_properties; + Vector<MultiplayerAPI::RPCConfig> rpc_methods; // Variables used to properly sort the node when processing, ignored otherwise. // TODO: Should move all the stuff below to bits. @@ -179,9 +176,7 @@ private: Array _get_groups() const; Variant _rpc_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); - Variant _rpc_unreliable_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); - Variant _rpc_unreliable_id_bind(const Variant **p_args, int p_argcount, Callable::CallError &r_error); friend class SceneTree; @@ -253,6 +248,10 @@ public: NOTIFICATION_APPLICATION_FOCUS_IN = MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN, NOTIFICATION_APPLICATION_FOCUS_OUT = MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT, NOTIFICATION_TEXT_SERVER_CHANGED = MainLoop::NOTIFICATION_TEXT_SERVER_CHANGED, + + // Editor specific node notifications + NOTIFICATION_EDITOR_PRE_SAVE = 9001, + NOTIFICATION_EDITOR_POST_SAVE = 9002, }; /* NODE/TREE */ @@ -283,7 +282,7 @@ public: _FORCE_INLINE_ bool is_inside_tree() const { return data.inside_tree; } - bool is_a_parent_of(const Node *p_node) const; + bool is_ancestor_of(const Node *p_node) const; bool is_greater_than(const Node *p_node) const; NodePath get_path() const; @@ -312,6 +311,8 @@ public: void remove_and_skip(); int get_index() const; + Ref<Tween> create_tween(); + void print_tree(); void print_tree_pretty(); @@ -425,42 +426,17 @@ public: int get_network_master() const; bool is_network_master() const; - uint16_t rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_mode); // config a local method for RPC - uint16_t rset_config(const StringName &p_property, MultiplayerAPI::RPCMode p_mode); // config a local property for RPC - - void rpc(const StringName &p_method, VARIANT_ARG_LIST); //rpc call, honors RPCMode - void rpc_unreliable(const StringName &p_method, VARIANT_ARG_LIST); //rpc call, honors RPCMode - void rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_LIST); //rpc call, honors RPCMode - void rpc_unreliable_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_LIST); //rpc call, honors RPCMode + uint16_t rpc_config(const StringName &p_method, MultiplayerAPI::RPCMode p_rpc_mode, NetworkedMultiplayerPeer::TransferMode p_transfer_mode, int p_channel = 0); // config a local method for RPC + Vector<MultiplayerAPI::RPCConfig> get_node_rpc_methods() const; - void rset(const StringName &p_property, const Variant &p_value); //remote set call, honors RPCMode - void rset_unreliable(const StringName &p_property, const Variant &p_value); //remote set call, honors RPCMode - void rset_id(int p_peer_id, const StringName &p_property, const Variant &p_value); //remote set call, honors RPCMode - void rset_unreliable_id(int p_peer_id, const StringName &p_property, const Variant &p_value); //remote set call, honors RPCMode - - void rpcp(int p_peer_id, bool p_unreliable, const StringName &p_method, const Variant **p_arg, int p_argcount); - void rsetp(int p_peer_id, bool p_unreliable, const StringName &p_property, const Variant &p_value); + void rpc(const StringName &p_method, VARIANT_ARG_LIST); // RPC, honors RPCMode, TransferMode, channel + void rpc_id(int p_peer_id, const StringName &p_method, VARIANT_ARG_LIST); // RPC to specific peer(s), honors RPCMode, TransferMode, channel + void rpcp(int p_peer_id, const StringName &p_method, const Variant **p_arg, int p_argcount); Ref<MultiplayerAPI> get_multiplayer() const; Ref<MultiplayerAPI> get_custom_multiplayer() const; void set_custom_multiplayer(Ref<MultiplayerAPI> p_multiplayer); - /// Returns the rpc method ID, otherwise UINT32_MAX - uint16_t get_node_rpc_method_id(const StringName &p_method) const; - StringName get_node_rpc_method(const uint16_t p_rpc_method_id) const; - MultiplayerAPI::RPCMode get_node_rpc_mode_by_id(const uint16_t p_rpc_method_id) const; - MultiplayerAPI::RPCMode get_node_rpc_mode(const StringName &p_method) const; - - /// Returns the rpc property ID, otherwise UINT32_MAX - uint16_t get_node_rset_property_id(const StringName &p_property) const; - StringName get_node_rset_property(const uint16_t p_rset_property_id) const; - MultiplayerAPI::RPCMode get_node_rset_mode_by_id(const uint16_t p_rpc_method_id) const; - MultiplayerAPI::RPCMode get_node_rset_mode(const StringName &p_property) const; - - /// Can be used to check if the rpc methods and the rset properties are the - /// same across the peers. - String get_rpc_md5() const; - Node(); ~Node(); }; diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 3e08f86fc9..4b52c4e99f 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -33,14 +33,15 @@ #include "core/config/project_settings.h" #include "core/debugger/engine_debugger.h" #include "core/input/input.h" +#include "core/io/dir_access.h" #include "core/io/marshalls.h" #include "core/io/resource_loader.h" #include "core/object/message_queue.h" -#include "core/os/dir_access.h" #include "core/os/keyboard.h" #include "core/os/os.h" #include "core/string/print_string.h" #include "node.h" +#include "scene/animation/tween.h" #include "scene/debugger/scene_debugger.h" #include "scene/resources/font.h" #include "scene/resources/material.h" @@ -412,8 +413,10 @@ bool SceneTree::physics_process(float p_time) { _notify_group_pause("physics_process", Node::NOTIFICATION_PHYSICS_PROCESS); _flush_ugc(); MessageQueue::get_singleton()->flush(); //small little hack + + process_tweens(p_time, true); + flush_transform_notifications(); - call_group_flags(GROUP_CALL_REALTIME, "_viewports", "update_worlds"); root_lock--; _flush_delete_queue(); @@ -445,7 +448,6 @@ bool SceneTree::process(float p_time) { _flush_ugc(); MessageQueue::get_singleton()->flush(); //small little hack flush_transform_notifications(); //transforms after world update, to avoid unnecessary enter/exit notifications - call_group_flags(GROUP_CALL_REALTIME, "_viewports", "update_worlds"); root_lock--; @@ -478,6 +480,8 @@ bool SceneTree::process(float p_time) { E = N; } + process_tweens(p_time, false); + flush_transform_notifications(); //additional transforms after timers update _call_idle_callbacks(); @@ -512,6 +516,32 @@ bool SceneTree::process(float p_time) { return _quit; } +void SceneTree::process_tweens(float p_delta, bool p_physics) { + // This methods works similarly to how SceneTreeTimers are handled. + List<Ref<Tween>>::Element *L = tweens.back(); + + for (List<Ref<Tween>>::Element *E = tweens.front(); E;) { + List<Ref<Tween>>::Element *N = E->next(); + // Don't process if paused or process mode doesn't match. + if ((paused && E->get()->should_pause()) || (p_physics == (E->get()->get_process_mode() == Tween::TWEEN_PROCESS_IDLE))) { + if (E == L) { + break; + } + E = N; + continue; + } + + if (!E->get()->step(p_delta)) { + E->get()->set_valid(false); + tweens.erase(E); + } + if (E == L) { + break; + } + E = N; + } +} + void SceneTree::finalize() { _flush_delete_queue(); @@ -593,7 +623,7 @@ void SceneTree::set_quit_on_go_back(bool p_enable) { #ifdef TOOLS_ENABLED bool SceneTree::is_node_being_edited(const Node *p_node) const { - return Engine::get_singleton()->is_editor_hint() && edited_scene_root && (edited_scene_root->is_a_parent_of(p_node) || edited_scene_root == p_node); + return Engine::get_singleton()->is_editor_hint() && edited_scene_root && (edited_scene_root->is_ancestor_of(p_node) || edited_scene_root == p_node); } #endif @@ -1063,7 +1093,7 @@ Error SceneTree::change_scene(const String &p_path) { Error SceneTree::change_scene_to(const Ref<PackedScene> &p_scene) { Node *new_scene = nullptr; if (p_scene.is_valid()) { - new_scene = p_scene->instance(); + new_scene = p_scene->instantiate(); ERR_FAIL_COND_V(!new_scene, ERR_CANT_CREATE); } @@ -1084,13 +1114,34 @@ void SceneTree::add_current_scene(Node *p_current) { Ref<SceneTreeTimer> SceneTree::create_timer(float p_delay_sec, bool p_process_always) { Ref<SceneTreeTimer> stt; - stt.instance(); + stt.instantiate(); stt->set_process_always(p_process_always); stt->set_time_left(p_delay_sec); timers.push_back(stt); return stt; } +Ref<Tween> SceneTree::create_tween() { + Ref<Tween> tween; + tween.instantiate(); + tween->set_valid(true); + tweens.push_back(tween); + return tween; +} + +Array SceneTree::get_processed_tweens() { + Array ret; + ret.resize(tweens.size()); + + int i = 0; + for (List<Ref<Tween>>::Element *E = tweens.front(); E; E = E->next()) { + ret[i] = E->get(); + i++; + } + + return ret; +} + void SceneTree::_network_peer_connected(int p_id) { emit_signal("network_peer_connected", p_id); } @@ -1199,6 +1250,8 @@ void SceneTree::_bind_methods() { ClassDB::bind_method(D_METHOD("is_paused"), &SceneTree::is_paused); ClassDB::bind_method(D_METHOD("create_timer", "time_sec", "process_always"), &SceneTree::create_timer, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("create_tween"), &SceneTree::create_tween); + ClassDB::bind_method(D_METHOD("get_processed_tweens"), &SceneTree::get_processed_tweens); ClassDB::bind_method(D_METHOD("get_node_count"), &SceneTree::get_node_count); ClassDB::bind_method(D_METHOD("get_frame"), &SceneTree::get_frame); @@ -1259,11 +1312,11 @@ void SceneTree::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_pause", "is_paused"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_network_connections"), "set_refuse_new_network_connections", "is_refusing_new_network_connections"); ADD_PROPERTY_DEFAULT("refuse_new_network_connections", false); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_edited_scene_root", "get_edited_scene_root"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "current_scene", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_current_scene", "get_current_scene"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", 0), "set_network_peer", "get_network_peer"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "", "get_root"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", 0), "set_multiplayer", "get_multiplayer"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_edited_scene_root", "get_edited_scene_root"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "current_scene", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "set_current_scene", "get_current_scene"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", PROPERTY_USAGE_NONE), "set_network_peer", "get_network_peer"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "root", PROPERTY_HINT_RESOURCE_TYPE, "Node", PROPERTY_USAGE_NONE), "", "get_root"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "multiplayer", PROPERTY_HINT_RESOURCE_TYPE, "MultiplayerAPI", PROPERTY_USAGE_NONE), "set_multiplayer", "get_multiplayer"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multiplayer_poll"), "set_multiplayer_poll_enabled", "is_multiplayer_poll_enabled"); ADD_SIGNAL(MethodInfo("tree_changed")); diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index a2f2adb8f8..0e9ffb0f5f 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -47,9 +47,10 @@ class Window; class Material; class Mesh; class SceneDebugger; +class Tween; -class SceneTreeTimer : public Reference { - GDCLASS(SceneTreeTimer, Reference); +class SceneTreeTimer : public RefCounted { + GDCLASS(SceneTreeTimer, RefCounted); float time_left = 0.0; bool process_always = true; @@ -151,6 +152,7 @@ private: //void _call_group(uint32_t p_call_flags,const StringName& p_group,const StringName& p_function,const Variant& p_arg1,const Variant& p_arg2); List<Ref<SceneTreeTimer>> timers; + List<Ref<Tween>> tweens; ///network/// @@ -171,6 +173,7 @@ private: void node_added(Node *p_node); void node_removed(Node *p_node); void node_renamed(Node *p_node); + void process_tweens(float p_delta, bool p_physics_frame); Group *add_to_group(const StringName &p_group, Node *p_node); void remove_from_group(const StringName &p_group, Node *p_node); @@ -318,6 +321,8 @@ public: Error reload_current_scene(); Ref<SceneTreeTimer> create_timer(float p_delay_sec, bool p_process_always = true); + Ref<Tween> create_tween(); + Array get_processed_tweens(); //used by Main::start, don't use otherwise void add_current_scene(Node *p_current); diff --git a/scene/main/shader_globals_override.cpp b/scene/main/shader_globals_override.cpp index cb3b2cb392..3d65c12cb7 100644 --- a/scene/main/shader_globals_override.cpp +++ b/scene/main/shader_globals_override.cpp @@ -169,7 +169,7 @@ void ShaderGlobalsOverride::_get_property_list(List<PropertyInfo> *p_list) const pinfo.type = Variant::TRANSFORM2D; } break; case RS::GLOBAL_VAR_TYPE_TRANSFORM: { - pinfo.type = Variant::TRANSFORM; + pinfo.type = Variant::TRANSFORM3D; } break; case RS::GLOBAL_VAR_TYPE_MAT4: { pinfo.type = Variant::PACKED_INT32_ARRAY; diff --git a/scene/main/timer.cpp b/scene/main/timer.cpp index 4bc159f6aa..ea9f51aa5d 100644 --- a/scene/main/timer.cpp +++ b/scene/main/timer.cpp @@ -37,7 +37,7 @@ void Timer::_notification(int p_what) { case NOTIFICATION_READY: { if (autostart) { #ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && (get_tree()->get_edited_scene_root() == this || get_tree()->get_edited_scene_root()->is_a_parent_of(this))) { + if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && (get_tree()->get_edited_scene_root() == this || get_tree()->get_edited_scene_root()->is_ancestor_of(this))) { break; } #endif @@ -210,8 +210,8 @@ void Timer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "wait_time", PROPERTY_HINT_EXP_RANGE, "0.001,4096,0.001,or_greater"), "set_wait_time", "get_wait_time"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "one_shot"), "set_one_shot", "is_one_shot"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "autostart"), "set_autostart", "has_autostart"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused", PROPERTY_HINT_NONE, "", 0), "set_paused", "is_paused"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_left", PROPERTY_HINT_NONE, "", 0), "", "get_time_left"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_paused", "is_paused"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_left", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "", "get_time_left"); BIND_ENUM_CONSTANT(TIMER_PROCESS_PHYSICS); BIND_ENUM_CONSTANT(TIMER_PROCESS_IDLE); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 77667cf188..cc56d6a49e 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -183,22 +183,9 @@ public: ///////////////////////////////////// -void Viewport::update_worlds() { - if (!is_inside_tree()) { - return; - } - - Rect2 abstracted_rect = Rect2(Vector2(), get_visible_rect().size); - Rect2 xformed_rect = (global_canvas_transform * canvas_transform).affine_inverse().xform(abstracted_rect); - find_world_2d()->_update_viewport(this, xformed_rect); - find_world_2d()->_update(); - - find_world_3d()->_update(get_tree()->get_frame()); -} - void Viewport::_collision_object_input_event(CollisionObject3D *p_object, Camera3D *p_camera, const Ref<InputEvent> &p_input_event, const Vector3 &p_pos, const Vector3 &p_normal, int p_shape) { - Transform object_transform = p_object->get_global_transform(); - Transform camera_transform = p_camera->get_global_transform(); + Transform3D object_transform = p_object->get_global_transform(); + Transform3D camera_transform = p_camera->get_global_transform(); ObjectID id = p_object->get_instance_id(); //avoid sending the fake event unnecessarily if nothing really changed in the context @@ -441,8 +428,6 @@ void Viewport::_notification(int p_what) { _update_listener(); _update_listener_2d(); - find_world_2d()->_register_viewport(this, Rect2()); - add_to_group("_viewports"); if (get_tree()->is_debugging_collisions_hint()) { //2D @@ -499,9 +484,6 @@ void Viewport::_notification(int p_what) { } break; case NOTIFICATION_EXIT_TREE: { _gui_cancel_tooltip(); - if (world_2d.is_valid()) { - world_2d->_remove_viewport(this); - } RenderingServer::get_singleton()->viewport_set_scenario(viewport, RID()); RenderingServer::get_singleton()->viewport_remove_canvas(viewport, current_canvas); @@ -553,7 +535,7 @@ void Viewport::_notification(int p_what) { RS::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, point_count); for (int i = 0; i < point_count; i++) { - Transform point_transform; + Transform3D point_transform; point_transform.origin = points[i]; RS::get_singleton()->multimesh_instance_set_transform(contact_3d_debug_multimesh, i, point_transform); } @@ -612,7 +594,7 @@ void Viewport::_process_picking() { if (!has_mouse_event) { Ref<InputEventMouseMotion> mm; - mm.instance(); + mm.instantiate(); mm->set_device(InputEvent::DEVICE_ID_INTERNAL); mm->set_global_position(physics_last_mousepos); @@ -662,9 +644,9 @@ void Viewport::_process_picking() { physics_last_mouse_state.meta = mb->is_meta_pressed(); if (mb->is_pressed()) { - physics_last_mouse_state.mouse_mask |= (1 << (mb->get_button_index() - 1)); + physics_last_mouse_state.mouse_mask |= (MouseButton)(1 << (mb->get_button_index() - 1)); } else { - physics_last_mouse_state.mouse_mask &= ~(1 << (mb->get_button_index() - 1)); + physics_last_mouse_state.mouse_mask &= (MouseButton) ~(1 << (mb->get_button_index() - 1)); // If touch mouse raised, assume we don't know last mouse pos until new events come if (mb->get_device() == InputEvent::DEVICE_ID_TOUCH_MOUSE) { @@ -1156,7 +1138,6 @@ void Viewport::set_world_2d(const Ref<World2D> &p_world_2d) { } if (is_inside_tree()) { - find_world_2d()->_remove_viewport(this); RenderingServer::get_singleton()->viewport_remove_canvas(viewport, current_canvas); } @@ -1172,7 +1153,6 @@ void Viewport::set_world_2d(const Ref<World2D> &p_world_2d) { if (is_inside_tree()) { current_canvas = find_world_2d()->get_canvas(); RenderingServer::get_singleton()->viewport_attach_canvas(viewport, current_canvas); - find_world_2d()->_register_viewport(this, Rect2()); } } @@ -1341,19 +1321,19 @@ bool Viewport::is_camera_override_enabled() const { return camera_override; } -void Viewport::set_camera_override_transform(const Transform &p_transform) { +void Viewport::set_camera_override_transform(const Transform3D &p_transform) { if (camera_override) { camera_override.transform = p_transform; RenderingServer::get_singleton()->camera_set_transform(camera_override.rid, p_transform); } } -Transform Viewport::get_camera_override_transform() const { +Transform3D Viewport::get_camera_override_transform() const { if (camera_override) { return camera_override.transform; } - return Transform(); + return Transform3D(); } void Viewport::set_camera_override_perspective(float p_fovy_degrees, float p_z_near, float p_z_far) { @@ -1766,7 +1746,7 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_ Control *c = Object::cast_to<Control>(p_node); - if (!c || !c->clips_input() || c->has_point(matrix.affine_inverse().xform(p_global))) { + if (!c || !c->is_clipping_contents() || c->has_point(matrix.affine_inverse().xform(p_global))) { for (int i = p_node->get_child_count() - 1; i >= 0; i--) { CanvasItem *ci = Object::cast_to<CanvasItem>(p_node->get_child(i)); if (!ci || ci->is_set_as_top_level()) { @@ -1790,7 +1770,7 @@ 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_a_parent_of(c))) { + if (!drag_preview || (c != drag_preview && !drag_preview->is_ancestor_of(c))) { r_inv_xform = matrix; return c; } @@ -2547,6 +2527,8 @@ void Viewport::_gui_remove_control(Control *p_control) { } Window *Viewport::get_base_window() const { + ERR_FAIL_COND_V(!is_inside_tree(), nullptr); + Viewport *v = const_cast<Viewport *>(this); Window *w = Object::cast_to<Window>(v); while (!w) { @@ -2603,10 +2585,10 @@ void Viewport::_drop_mouse_focus() { for (int i = 0; i < 3; i++) { if (mask & (1 << i)) { Ref<InputEventMouseButton> mb; - mb.instance(); + mb.instantiate(); mb->set_position(c->get_local_mouse_position()); mb->set_global_position(c->get_local_mouse_position()); - mb->set_button_index(i + 1); + mb->set_button_index(MouseButton(i + 1)); mb->set_pressed(false); c->call(SceneStringNames::get_singleton()->_gui_input, mb); } @@ -2679,12 +2661,12 @@ void Viewport::_post_gui_grab_click_focus() { for (int i = 0; i < 3; i++) { if (mask & (1 << i)) { Ref<InputEventMouseButton> mb; - mb.instance(); + mb.instantiate(); //send unclick mb->set_position(click); - mb->set_button_index(i + 1); + mb->set_button_index(MouseButton(i + 1)); mb->set_pressed(false); gui.mouse_focus->call(SceneStringNames::get_singleton()->_gui_input, mb); } @@ -2697,12 +2679,12 @@ void Viewport::_post_gui_grab_click_focus() { for (int i = 0; i < 3; i++) { if (mask & (1 << i)) { Ref<InputEventMouseButton> mb; - mb.instance(); + mb.instantiate(); //send click mb->set_position(click); - mb->set_button_index(i + 1); + mb->set_button_index(MouseButton(i + 1)); mb->set_pressed(true); gui.mouse_focus->call_deferred(SceneStringNames::get_singleton()->_gui_input, mb); } @@ -3041,7 +3023,7 @@ void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) { return; } - if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) { + if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this)) { return; } @@ -3083,7 +3065,7 @@ void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coor return; } - if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) { + if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this)) { return; } @@ -3336,6 +3318,7 @@ bool Viewport::is_input_handled() const { return local_input_handled; } else { const Viewport *vp = this; + ERR_FAIL_COND_V(!is_inside_tree(), false); while (true) { if (Object::cast_to<Window>(vp)) { break; @@ -3522,8 +3505,6 @@ void Viewport::_bind_methods() { 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("update_worlds"), &Viewport::update_worlds); - ClassDB::bind_method(D_METHOD("set_use_own_world_3d", "enable"), &Viewport::set_use_own_world_3d); ClassDB::bind_method(D_METHOD("is_using_own_world_3d"), &Viewport::is_using_own_world_3d); @@ -3595,7 +3576,7 @@ void Viewport::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_xr"), "set_use_xr", "is_using_xr"); 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"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_2d", PROPERTY_HINT_RESOURCE_TYPE, "World2D", 0), "set_world_2d", "get_world_2d"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_2d", PROPERTY_HINT_RESOURCE_TYPE, "World2D", PROPERTY_USAGE_NONE), "set_world_2d", "get_world_2d"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "transparent_bg"), "set_transparent_background", "has_transparent_background"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "handle_input_locally"), "set_handle_input_locally", "is_handling_input_locally"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "snap_2d_transforms_to_pixel"), "set_snap_2d_transforms_to_pixel", "is_snap_2d_transforms_to_pixel_enabled"); @@ -3629,8 +3610,8 @@ void Viewport::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_1", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 1); ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_2", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 2); ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_3", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 3); - ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "canvas_transform", PROPERTY_HINT_NONE, "", 0), "set_canvas_transform", "get_canvas_transform"); - ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_canvas_transform", PROPERTY_HINT_NONE, "", 0), "set_global_canvas_transform", "get_global_canvas_transform"); + ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "canvas_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_canvas_transform", "get_canvas_transform"); + ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_canvas_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NONE), "set_global_canvas_transform", "get_global_canvas_transform"); ADD_SIGNAL(MethodInfo("size_changed")); ADD_SIGNAL(MethodInfo("gui_focus_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Control"))); @@ -3669,9 +3650,9 @@ void Viewport::_bind_methods() { BIND_ENUM_CONSTANT(DEBUG_DRAW_OVERDRAW); BIND_ENUM_CONSTANT(DEBUG_DRAW_WIREFRAME); BIND_ENUM_CONSTANT(DEBUG_DRAW_NORMAL_BUFFER); - BIND_ENUM_CONSTANT(DEBUG_DRAW_GI_PROBE_ALBEDO); - BIND_ENUM_CONSTANT(DEBUG_DRAW_GI_PROBE_LIGHTING); - BIND_ENUM_CONSTANT(DEBUG_DRAW_GI_PROBE_EMISSION); + BIND_ENUM_CONSTANT(DEBUG_DRAW_VOXEL_GI_ALBEDO); + BIND_ENUM_CONSTANT(DEBUG_DRAW_VOXEL_GI_LIGHTING); + BIND_ENUM_CONSTANT(DEBUG_DRAW_VOXEL_GI_EMISSION); BIND_ENUM_CONSTANT(DEBUG_DRAW_SHADOW_ATLAS); BIND_ENUM_CONSTANT(DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS); BIND_ENUM_CONSTANT(DEBUG_DRAW_SCENE_LUMINANCE); @@ -3717,7 +3698,7 @@ Viewport::Viewport() { viewport = RenderingServer::get_singleton()->viewport_create(); texture_rid = RenderingServer::get_singleton()->viewport_get_texture(viewport); - default_texture.instance(); + default_texture.instantiate(); default_texture->vp = const_cast<Viewport *>(this); viewport_textures.insert(default_texture.ptr()); default_texture->proxy = RS::get_singleton()->texture_proxy_create(texture_rid); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index a55df4fbc2..d905e44a82 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -130,9 +130,9 @@ public: DEBUG_DRAW_OVERDRAW, DEBUG_DRAW_WIREFRAME, DEBUG_DRAW_NORMAL_BUFFER, - DEBUG_DRAW_GI_PROBE_ALBEDO, - DEBUG_DRAW_GI_PROBE_LIGHTING, - DEBUG_DRAW_GI_PROBE_EMISSION, + DEBUG_DRAW_VOXEL_GI_ALBEDO, + DEBUG_DRAW_VOXEL_GI_LIGHTING, + DEBUG_DRAW_VOXEL_GI_EMISSION, DEBUG_DRAW_SHADOW_ATLAS, DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS, DEBUG_DRAW_SCENE_LUMINANCE, @@ -193,7 +193,7 @@ private: Set<Listener3D *> listeners; struct CameraOverrideData { - Transform transform; + Transform3D transform; enum Projection { PROJECTION_PERSPECTIVE, PROJECTION_ORTHOGONAL @@ -254,8 +254,8 @@ private: List<Ref<InputEvent>> physics_picking_events; ObjectID physics_object_capture; ObjectID physics_object_over; - Transform physics_last_object_transform; - Transform physics_last_camera_transform; + Transform3D physics_last_object_transform; + Transform3D physics_last_camera_transform; ObjectID physics_last_id; bool physics_has_last_mousepos = false; Vector2 physics_last_mousepos = Vector2(Math_INF, Math_INF); @@ -397,8 +397,6 @@ private: void _gui_input_event(Ref<InputEvent> p_event); - void update_worlds(); - _FORCE_INLINE_ Transform2D _get_input_pre_xform() const; Ref<InputEvent> _make_input_local(const Ref<InputEvent> &ev); @@ -493,8 +491,8 @@ public: void enable_camera_override(bool p_enable); bool is_camera_override_enabled() const; - void set_camera_override_transform(const Transform &p_transform); - Transform get_camera_override_transform() const; + void set_camera_override_transform(const Transform3D &p_transform); + Transform3D get_camera_override_transform() const; void set_camera_override_perspective(float p_fovy_degrees, float p_z_near, float p_z_far); void set_camera_override_orthogonal(float p_size, float p_z_near, float p_z_far); |