diff options
Diffstat (limited to 'scene/main')
| -rw-r--r--[-rwxr-xr-x] | scene/main/node.cpp | 109 | ||||
| -rw-r--r-- | scene/main/node.h | 2 | ||||
| -rw-r--r-- | scene/main/scene_tree.cpp | 24 | ||||
| -rw-r--r-- | scene/main/scene_tree.h | 7 | ||||
| -rw-r--r-- | scene/main/viewport.cpp | 37 | ||||
| -rw-r--r-- | scene/main/viewport.h | 2 |
6 files changed, 120 insertions, 61 deletions
diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 01e11962ff..cae368aeca 100755..100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -1198,7 +1198,7 @@ void Node::_validate_child_name(Node *p_child, bool p_force_human_readable) { unique = false; } else { //check if exists - Node **childs = data.children.ptr(); + Node **childs = data.children.ptrw(); int cc = data.children.size(); for (int i = 0; i < cc; i++) { @@ -2104,37 +2104,65 @@ Node *Node::_duplicate(int p_flags, Map<const Node *, Node *> *r_duplimap) const ERR_FAIL_COND_V(!node, NULL); } - List<PropertyInfo> plist; - - get_property_list(&plist); + if (get_filename() != "") { //an instance + node->set_filename(get_filename()); + } StringName script_property_name = CoreStringNames::get_singleton()->_script; - if (p_flags & DUPLICATE_SCRIPTS) { - bool is_valid = false; - Variant script = get(script_property_name, &is_valid); - if (is_valid) { - node->set(script_property_name, script); + 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 + + for (List<const Node *>::Element *N = node_tree.front(); N; N = N->next()) { + for (int i = 0; i < N->get()->get_child_count(); ++i) { + + // Skip nodes not really belonging to the instanced hierarchy; they'll be processed normally later + if (N->get()->get_child(i)->data.owner != this) + continue; + + node_tree.push_back(N->get()->get_child(i)); + } } } - for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) { + for (List<const Node *>::Element *N = node_tree.front(); N; N = N->next()) { - if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) - continue; - String name = E->get().name; - if (name == script_property_name) - continue; + Node *current_node = node->get_node(get_path_to(N->get())); + ERR_CONTINUE(!current_node); - Variant value = get(name); - // Duplicate dictionaries and arrays, mainly needed for __meta__ - if (value.get_type() == Variant::DICTIONARY) { - value = Dictionary(value).copy(); - } else if (value.get_type() == Variant::ARRAY) { - value = Array(value).duplicate(); + if (p_flags & DUPLICATE_SCRIPTS) { + bool is_valid = false; + Variant script = N->get()->get(script_property_name, &is_valid); + if (is_valid) { + current_node->set(script_property_name, script); + } } - node->set(name, value); + List<PropertyInfo> plist; + N->get()->get_property_list(&plist); + + for (List<PropertyInfo>::Element *E = plist.front(); E; E = E->next()) { + + if (!(E->get().usage & PROPERTY_USAGE_STORAGE)) + continue; + String name = E->get().name; + if (name == script_property_name) + continue; + + Variant value = N->get()->get(name); + // Duplicate dictionaries and arrays, mainly needed for __meta__ + if (value.get_type() == Variant::DICTIONARY) { + value = Dictionary(value).copy(); + } else if (value.get_type() == Variant::ARRAY) { + value = Array(value).duplicate(); + } + + current_node->set(name, value); + } } node->set_name(get_name()); @@ -2502,24 +2530,19 @@ bool Node::has_node_and_resource(const NodePath &p_path) const { return false; Node *node = get_node(p_path); - if (p_path.get_subname_count()) { + bool result = false; - RES r; - for (int j = 0; j < p_path.get_subname_count(); j++) { - r = j == 0 ? node->get(p_path.get_subname(j)) : r->get(p_path.get_subname(j)); - if (r.is_null()) - return false; - } - } + node->get_indexed(p_path.get_subnames(), &result); - return true; + return result; } Array Node::_get_node_and_resource(const NodePath &p_path) { Node *node; RES res; - node = get_node_and_resource(p_path, res); + Vector<StringName> leftover_path; + node = get_node_and_resource(p_path, res, leftover_path); Array result; if (node) @@ -2532,21 +2555,35 @@ Array Node::_get_node_and_resource(const NodePath &p_path) { else result.push_back(Variant()); + result.push_back(NodePath(Vector<StringName>(), leftover_path, false)); + return result; } -Node *Node::get_node_and_resource(const NodePath &p_path, RES &r_res) const { +Node *Node::get_node_and_resource(const NodePath &p_path, RES &r_res, Vector<StringName> &r_leftover_subpath, bool p_last_is_property) const { Node *node = get_node(p_path); r_res = RES(); + r_leftover_subpath = Vector<StringName>(); if (!node) return NULL; if (p_path.get_subname_count()) { - for (int j = 0; j < p_path.get_subname_count(); j++) { - r_res = j == 0 ? node->get(p_path.get_subname(j)) : r_res->get(p_path.get_subname(j)); - ERR_FAIL_COND_V(r_res.is_null(), node); + int j = 0; + // If not p_last_is_property, we shouldn't consider the last one as part of the resource + for (; j < p_path.get_subname_count() - p_last_is_property; j++) { + RES new_res = j == 0 ? node->get(p_path.get_subname(j)) : r_res->get(p_path.get_subname(j)); + + if (new_res.is_null()) { + break; + } + + r_res = new_res; + } + for (; j < p_path.get_subname_count(); j++) { + // Put the rest of the subpath in the leftover path + r_leftover_subpath.push_back(p_path.get_subname(j)); } } diff --git a/scene/main/node.h b/scene/main/node.h index bd0b18c87a..2b71b71c8d 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -245,7 +245,7 @@ public: Node *get_node(const NodePath &p_path) const; Node *find_node(const String &p_mask, bool p_recursive = true, bool p_owned = true) const; bool has_node_and_resource(const NodePath &p_path) const; - Node *get_node_and_resource(const NodePath &p_path, RES &r_res) const; + Node *get_node_and_resource(const NodePath &p_path, RES &r_res, Vector<StringName> &r_leftover_subpath, bool p_last_is_property = true) const; Node *get_parent() const; _FORCE_INLINE_ SceneTree *get_tree() const { diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index d4be683a2b..deb40800bc 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -127,7 +127,7 @@ void SceneTree::remove_from_group(const StringName &p_group, Node *p_node) { group_map.erase(E); } -void SceneTree::_flush_transform_notifications() { +void SceneTree::flush_transform_notifications() { SelfList<Node> *n = xform_change_list.first(); while (n) { @@ -418,12 +418,12 @@ void SceneTree::input_event(const Ref<InputEvent> &p_event) { if (!input_handled) { call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_vp_unhandled_input", ev); //special one for GUI, as controls use their own process check - input_handled = true; _flush_ugc(); + // input_handled = true; - no reason to set this as handled root_lock--; //MessageQueue::get_singleton()->flush(); //flushing here causes UI and other places slowness } else { - input_handled = true; + // input_handled = true; - no reason to set this as handled root_lock--; } @@ -448,7 +448,7 @@ bool SceneTree::iteration(float p_time) { current_frame++; - _flush_transform_notifications(); + flush_transform_notifications(); MainLoop::iteration(p_time); physics_process_time = p_time; @@ -459,7 +459,7 @@ bool SceneTree::iteration(float p_time) { _notify_group_pause("physics_process", Node::NOTIFICATION_PHYSICS_PROCESS); _flush_ugc(); MessageQueue::get_singleton()->flush(); //small little hack - _flush_transform_notifications(); + flush_transform_notifications(); call_group_flags(GROUP_CALL_REALTIME, "_viewports", "update_worlds"); root_lock--; @@ -487,7 +487,7 @@ bool SceneTree::idle(float p_time) { MessageQueue::get_singleton()->flush(); //small little hack - _flush_transform_notifications(); + flush_transform_notifications(); _notify_group_pause("idle_process_internal", Node::NOTIFICATION_INTERNAL_PROCESS); _notify_group_pause("idle_process", Node::NOTIFICATION_PROCESS); @@ -503,7 +503,7 @@ bool SceneTree::idle(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 + flush_transform_notifications(); //transforms after world update, to avoid unnecessary enter/exit notifications call_group_flags(GROUP_CALL_REALTIME, "_viewports", "update_worlds"); root_lock--; @@ -794,6 +794,7 @@ Ref<ArrayMesh> SceneTree::get_debug_contact_mesh() { Vector3(0, 0, 1) }; + /* clang-format off */ int diamond_faces[8 * 3] = { 0, 2, 4, 0, 3, 4, @@ -804,6 +805,7 @@ Ref<ArrayMesh> SceneTree::get_debug_contact_mesh() { 1, 2, 5, 1, 3, 5, }; + /* clang-format on */ PoolVector<int> indices; for (int i = 0; i < 8 * 3; i++) @@ -1001,7 +1003,7 @@ Array SceneTree::_get_nodes_in_group(const StringName &p_group) { ret.resize(nc); - Node **ptr = E->get().nodes.ptr(); + Node **ptr = E->get().nodes.ptrw(); for (int i = 0; i < nc; i++) { ret[i] = ptr[i]; @@ -1024,7 +1026,7 @@ void SceneTree::get_nodes_in_group(const StringName &p_group, List<Node *> *p_li int nc = E->get().nodes.size(); if (nc == 0) return; - Node **ptr = E->get().nodes.ptr(); + Node **ptr = E->get().nodes.ptrw(); for (int i = 0; i < nc; i++) { p_list->push_back(ptr[i]); @@ -1997,9 +1999,9 @@ void SceneTree::_network_process_packet(int p_from, const uint8_t *p_packet, int Variant::CallError ce; - node->call(name, argp.ptr(), argc, ce); + node->call(name, (const Variant **)argp.ptr(), argc, ce); if (ce.error != Variant::CallError::CALL_OK) { - String error = Variant::get_call_error_text(node, name, argp.ptr(), argc, ce); + String error = Variant::get_call_error_text(node, name, (const Variant **)argp.ptr(), argc, ce); error = "RPC - " + error; ERR_PRINTS(error); } diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index bc3efdc42f..244fc8da62 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -157,7 +157,6 @@ private: Map<UGCall, Vector<Variant> > unique_group_calls; bool ugc_locked; void _flush_ugc(); - void _flush_transform_notifications(); _FORCE_INLINE_ void _update_group_order(Group &g); void _update_listener(); @@ -344,6 +343,8 @@ public: void notify_group(const StringName &p_group, int p_notification); void set_group(const StringName &p_group, const String &p_name, const Variant &p_value); + void flush_transform_notifications(); + virtual void input_text(const String &p_text); virtual void input_event(const Ref<InputEvent> &p_event); virtual void init(); @@ -419,8 +420,8 @@ public: void set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 p_minsize, real_t p_shrink = 1); -//void change_scene(const String& p_path); -//Node *get_loaded_scene(); + //void change_scene(const String& p_path); + //Node *get_loaded_scene(); #ifdef TOOLS_ENABLED void set_edited_scene_root(Node *p_node); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 1f539041fd..4635de81e8 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -69,6 +69,8 @@ void ViewportTexture::setup_local_to_scene() { ERR_FAIL_COND(!vp); vp->viewport_textures.insert(this); + + VS::get_singleton()->texture_set_proxy(proxy, vp->texture_rid); } void ViewportTexture::set_viewport_path_in_scene(const NodePath &p_path) { @@ -105,8 +107,8 @@ Size2 ViewportTexture::get_size() const { } RID ViewportTexture::get_rid() const { - ERR_FAIL_COND_V(!vp, RID()); - return vp->texture_rid; + //ERR_FAIL_COND_V(!vp, RID()); + return proxy; } bool ViewportTexture::has_alpha() const { @@ -147,6 +149,7 @@ ViewportTexture::ViewportTexture() { vp = NULL; set_local_to_scene(true); + proxy = VS::get_singleton()->texture_create(); } ViewportTexture::~ViewportTexture() { @@ -154,6 +157,8 @@ ViewportTexture::~ViewportTexture() { if (vp) { vp->viewport_textures.erase(this); } + + VS::get_singleton()->free(proxy); } ///////////////////////////////////// @@ -539,7 +544,7 @@ void Viewport::_notification(int p_what) { Vector2 point = get_canvas_transform().affine_inverse().xform(pos); Physics2DDirectSpaceState::ShapeResult res[64]; - int rc = ss2d->intersect_point(point, res, 64, Set<RID>(), 0xFFFFFFFF, 0xFFFFFFFF, true); + int rc = ss2d->intersect_point(point, res, 64, Set<RID>(), 0xFFFFFFFF, true); for (int i = 0; i < rc; i++) { if (res[i].collider_id && res[i].collider) { @@ -622,7 +627,7 @@ void Viewport::_notification(int p_what) { PhysicsDirectSpaceState *space = PhysicsServer::get_singleton()->space_get_direct_state(find_world()->get_space()); if (space) { - bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, 0xFFFFFFFF, true); + bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, true); ObjectID new_collider = 0; if (col) { @@ -658,7 +663,7 @@ void Viewport::_notification(int p_what) { PhysicsDirectSpaceState *space = PhysicsServer::get_singleton()->space_get_direct_state(find_world()->get_space()); if (space) { - bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, 0xFFFFFFFF, true); + bool col = space->intersect_ray(from, from + dir * 10000, result, Set<RID>(), 0xFFFFFFFF, true); ObjectID new_collider = 0; if (col) { CollisionObject *co = Object::cast_to<CollisionObject>(result.collider); @@ -931,6 +936,9 @@ void Viewport::_camera_remove(Camera *p_camera) { cameras.erase(p_camera); if (camera == p_camera) { + if (camera && find_world().is_valid()) { + camera->notification(Camera::NOTIFICATION_LOST_CURRENT); + } camera = NULL; } } @@ -1261,12 +1269,9 @@ Transform2D Viewport::_get_input_pre_xform() const { Vector2 Viewport::_get_window_offset() const { - /* - if (parent_control) { - return (parent_control->get_viewport()->get_final_transform() * parent_control->get_global_transform_with_canvas()).get_origin(); + if (get_parent() && get_parent()->has_method("get_global_position")) { + return get_parent()->call("get_global_position"); } - */ - return Vector2(); } @@ -1641,6 +1646,8 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { } else { + bool is_handled = false; + _gui_sort_modal_stack(); while (!gui.modal_stack.empty()) { @@ -1658,11 +1665,20 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { top->notification(Control::NOTIFICATION_MODAL_CLOSE); top->_modal_stack_remove(); top->hide(); + + if (!top->pass_on_modal_close_click()) { + is_handled = true; + } } else { break; } } + if (is_handled) { + get_tree()->set_input_as_handled(); + return; + } + //Matrix32 parent_xform; /* @@ -2813,6 +2829,7 @@ Viewport::Viewport() { default_texture.instance(); default_texture->vp = const_cast<Viewport *>(this); viewport_textures.insert(default_texture.ptr()); + VS::get_singleton()->texture_set_proxy(default_texture->proxy, texture_rid); //internal_listener = SpatialSoundServer::get_singleton()->listener_create(); audio_listener = false; diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 6bbd4b26b5..0835e3f69a 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -59,6 +59,8 @@ class ViewportTexture : public Texture { friend class Viewport; Viewport *vp; + RID proxy; + protected: static void _bind_methods(); |