From 66f2357d014e71ed59c73dcded1cce4121e7c3af Mon Sep 17 00:00:00 2001 From: Relintai Date: Tue, 30 Aug 2022 14:08:27 +0200 Subject: [PATCH] Now Cameras use Worlds directly instead of Viewports. --- scene/3d/camera.cpp | 54 ++++++++++++------------- scene/3d/camera.h | 3 +- scene/main/viewport.cpp | 54 ------------------------- scene/main/viewport.h | 16 +------- scene/main/world.cpp | 89 +++++++++++++++++++++++++++++++++++++++++ scene/main/world.h | 20 +++++++++ 6 files changed, 140 insertions(+), 96 deletions(-) diff --git a/scene/3d/camera.cpp b/scene/3d/camera.cpp index 23ccc1dad..67ab092d1 100644 --- a/scene/3d/camera.cpp +++ b/scene/3d/camera.cpp @@ -89,14 +89,14 @@ void Camera::_update_camera() { // here goes listener stuff /* if (viewport_ptr && is_inside_scene() && is_current()) - get_viewport()->_camera_transform_changed_notify(); + get_world()->_camera_transform_changed_notify(); */ if (get_tree()->is_node_being_edited(this) || !is_current()) { return; } - get_viewport()->_camera_transform_changed_notify(); + get_world()->_camera_transform_changed_notify(); if (get_world_3d().is_valid()) { get_world_3d()->_update_camera(this); @@ -113,12 +113,12 @@ void Camera::_notification(int p_what) { // Needs to track the Viewport because it's needed on NOTIFICATION_EXIT_WORLD // and Spatial will handle it first, including clearing its reference to the Viewport, // therefore making it impossible to subclasses to access it - viewport = get_viewport(); - ERR_FAIL_COND(!viewport); + world = get_world(); + ERR_FAIL_COND(!world); - bool first_camera = viewport->_camera_add(this); + bool first_camera = world->_camera_add(this); if (current || first_camera) { - viewport->_camera_set(this); + world->_camera_set(this); } ERR_FAIL_COND(get_world_3d().is_null()); @@ -149,20 +149,20 @@ void Camera::_notification(int p_what) { } } - if (viewport) { - viewport->_camera_remove(this); - viewport = nullptr; + if (world) { + world->_camera_remove(this); + world = nullptr; } } break; case NOTIFICATION_BECAME_CURRENT: { - if (viewport) { - viewport->_world_3d_register_camera(this); + if (world) { + world->_world_3d_register_camera(this); } } break; case NOTIFICATION_LOST_CURRENT: { - if (viewport) { - viewport->_world_3d_remove_camera(this); + if (world) { + world->_world_3d_remove_camera(this); } } break; } @@ -241,7 +241,7 @@ void Camera::make_current() { return; } - get_viewport()->_camera_set(this); + get_world()->_camera_set(this); //get_scene()->call_group(SceneMainLoop::GROUP_CALL_REALTIME,camera_group,"_camera_make_current",this); } @@ -252,11 +252,11 @@ void Camera::clear_current(bool p_enable_next) { return; } - if (get_viewport()->get_camera() == this) { - get_viewport()->_camera_set(nullptr); + if (get_world()->get_camera() == this) { + get_world()->_camera_set(nullptr); if (p_enable_next) { - get_viewport()->_camera_make_next_current(this); + get_world()->_camera_make_next_current(this); } } } @@ -271,7 +271,7 @@ void Camera::set_current(bool p_current) { bool Camera::is_current() const { if (is_inside_tree() && !get_tree()->is_node_being_edited(this)) { - return get_viewport()->get_camera() == this; + return get_world()->get_camera() == this; } else { return current; } @@ -285,8 +285,8 @@ Vector3 Camera::project_ray_normal(const Point2 &p_pos) const { Vector3 Camera::project_local_ray_normal(const Point2 &p_pos) const { ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene."); - Size2 viewport_size = get_viewport()->get_camera_rect_size(); - Vector2 cpos = get_viewport()->get_camera_coords(p_pos); + Size2 viewport_size = get_world()->get_camera_rect_size(); + Vector2 cpos = get_world()->get_camera_coords(p_pos); Vector3 ray; if (mode == PROJECTION_ORTHOGONAL) { @@ -304,8 +304,8 @@ Vector3 Camera::project_local_ray_normal(const Point2 &p_pos) const { Vector3 Camera::project_ray_origin(const Point2 &p_pos) const { ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector3(), "Camera is not inside scene."); - Size2 viewport_size = get_viewport()->get_camera_rect_size(); - Vector2 cpos = get_viewport()->get_camera_coords(p_pos); + Size2 viewport_size = get_world()->get_camera_rect_size(); + Vector2 cpos = get_world()->get_camera_coords(p_pos); ERR_FAIL_COND_V(viewport_size.y == 0, Vector3()); if (mode == PROJECTION_PERSPECTIVE) { @@ -339,7 +339,7 @@ bool Camera::is_position_behind(const Vector3 &p_pos) const { Vector Camera::get_near_plane_points() const { ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector(), "Camera is not inside scene."); - Size2 viewport_size = get_viewport()->get_visible_rect().size; + Size2 viewport_size = get_world()->get_visible_rect().size; Projection cm; @@ -363,7 +363,7 @@ Vector Camera::get_near_plane_points() const { Point2 Camera::unproject_position(const Vector3 &p_pos) const { ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector2(), "Camera is not inside scene."); - Size2 viewport_size = get_viewport()->get_visible_rect().size; + Size2 viewport_size = get_world()->get_visible_rect().size; Projection cm; @@ -391,7 +391,7 @@ Vector3 Camera::project_position(const Point2 &p_point, float p_z_depth) const { if (p_z_depth == 0 && mode != PROJECTION_ORTHOGONAL) { return get_global_transform().origin; } - Size2 viewport_size = get_viewport()->get_visible_rect().size; + Size2 viewport_size = get_world()->get_visible_rect().size; Projection cm; @@ -627,7 +627,7 @@ bool Camera::get_cull_mask_bit(int p_layer) const { Vector Camera::get_frustum() const { ERR_FAIL_COND_V(!is_inside_world(), Vector()); - Size2 viewport_size = get_viewport()->get_visible_rect().size; + Size2 viewport_size = get_world()->get_visible_rect().size; Projection cm; if (mode == PROJECTION_PERSPECTIVE) { cm.set_perspective(fov, viewport_size.aspect(), near, far, keep_aspect == KEEP_WIDTH); @@ -671,7 +671,7 @@ Camera::Camera() { near = 0; far = 0; current = false; - viewport = nullptr; + world = nullptr; force_change = false; mode = PROJECTION_PERSPECTIVE; set_perspective(70.0, 0.05, 100.0); diff --git a/scene/3d/camera.h b/scene/3d/camera.h index 16465b449..34efa6505 100644 --- a/scene/3d/camera.h +++ b/scene/3d/camera.h @@ -36,6 +36,7 @@ class SpatialVelocityTracker; class Viewport; class Environment3D; +class World; class Camera : public Spatial { GDCLASS(Camera, Spatial); @@ -62,7 +63,7 @@ public: private: bool force_change; bool current; - Viewport *viewport; + World *world; ProjectionMode mode; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index be17f43f0..bbc57af41 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -990,14 +990,6 @@ void Viewport::_listener_make_next_current(Listener *p_exclude) { } #endif -void Viewport::_camera_transform_changed_notify() { -#ifndef _3D_DISABLED -// If there is an active listener in the scene, it takes priority over the camera -// if (camera && !listener) -// SpatialSoundServer::get_singleton()->listener_set_transform(internal_listener, camera->get_camera_transform()); -#endif -} - void Viewport::_camera_set(Camera *p_camera) { #ifndef _3D_DISABLED @@ -1030,37 +1022,6 @@ void Viewport::_camera_2d_set(Camera2D *p_camera_2d) { camera_2d = p_camera_2d; } -bool Viewport::_camera_add(Camera *p_camera) { - cameras.insert(p_camera); - return cameras.size() == 1; -} - -void Viewport::_camera_remove(Camera *p_camera) { - cameras.erase(p_camera); - if (camera == p_camera) { - camera->notification(Camera::NOTIFICATION_LOST_CURRENT); - camera = nullptr; - } -} - -#ifndef _3D_DISABLED -void Viewport::_camera_make_next_current(Camera *p_exclude) { - for (Set::Element *E = cameras.front(); E; E = E->next()) { - if (p_exclude == E->get()) { - continue; - } - if (!E->get()->is_inside_tree()) { - continue; - } - if (camera != nullptr) { - return; - } - - E->get()->make_current(); - } -} -#endif - void Viewport::_listener_2d_set(Listener2D *p_listener) { if (listener_2d == p_listener) { return; @@ -1108,10 +1069,6 @@ Listener *Viewport::get_listener() const { return listener; } -Camera *Viewport::get_camera() const { - return camera; -} - Camera2D *Viewport::get_camera_2d() const { return camera_2d; } @@ -2873,15 +2830,6 @@ bool Viewport::get_physics_object_picking() { return physics_object_picking; } -Vector2 Viewport::get_camera_coords(const Vector2 &p_viewport_coords) const { - Transform2D xf = get_final_transform(); - return xf.xform(p_viewport_coords); -} - -Vector2 Viewport::get_camera_rect_size() const { - return size; -} - bool Viewport::gui_has_modal_stack() const { return gui.modal_stack.size(); } @@ -3167,7 +3115,6 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("input", "local_event"), &Viewport::input); ClassDB::bind_method(D_METHOD("unhandled_input", "local_event"), &Viewport::unhandled_input); - ClassDB::bind_method(D_METHOD("get_camera"), &Viewport::get_camera); ClassDB::bind_method(D_METHOD("get_camera_2d"), &Viewport::get_camera_2d); ClassDB::bind_method(D_METHOD("set_as_audio_listener", "enable"), &Viewport::set_as_audio_listener); @@ -3330,7 +3277,6 @@ Viewport::Viewport() { transparent_bg = false; parent = nullptr; listener = nullptr; - camera = nullptr; camera_2d = nullptr; override_canvas_transform = false; canvas_layers.insert(NULL); // This eases picking code (interpreted as the canvas of the Viewport) diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 61788bf70..1697d83ac 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -155,7 +155,6 @@ public: public: Listener *get_listener() const; - Camera *get_camera() const; Camera2D *get_camera_2d() const; void enable_camera_override(bool p_enable); @@ -239,9 +238,6 @@ public: void set_use_32_bpc_depth(bool p_enable); bool is_using_32_bpc_depth() const; - Vector2 get_camera_coords(const Vector2 &p_viewport_coords) const; - Vector2 get_camera_rect_size() const; - void input(const Ref &p_event); void unhandled_input(const Ref &p_event); @@ -301,6 +297,8 @@ public: Viewport(); ~Viewport(); + void _camera_set(Camera *p_camera); + protected: void _notification(int p_what); void _process_picking(bool p_ignore_paused); @@ -343,9 +341,7 @@ private: } } camera_override; - Camera *camera; Camera2D *camera_2d; - Set cameras; Listener2D *listener_2d = nullptr; Set canvas_layers; @@ -365,7 +361,6 @@ private: Transform2D global_canvas_transform; Transform2D stretch_transform; - Size2 size; Rect2 to_screen_rect; bool render_direct_to_screen; @@ -555,13 +550,6 @@ private: void _listener_remove(Listener *p_listener); void _listener_make_next_current(Listener *p_exclude); - friend class Camera; - void _camera_transform_changed_notify(); - void _camera_set(Camera *p_camera); - bool _camera_add(Camera *p_camera); //true if first - void _camera_remove(Camera *p_camera); - void _camera_make_next_current(Camera *p_exclude); - friend class Camera2D; void _camera_2d_set(Camera2D *p_camera_2d); diff --git a/scene/main/world.cpp b/scene/main/world.cpp index 8a46040cc..1b0fcef0f 100644 --- a/scene/main/world.cpp +++ b/scene/main/world.cpp @@ -9,6 +9,10 @@ #include "scene/resources/world_3d.h" #include "viewport.h" +Camera *World::get_camera() const { + return camera; +} + Ref World::get_world_2d() const { return world_2d; } @@ -341,6 +345,15 @@ RID World::get_viewport_rid() const { return RID(); } +Vector2 World::get_camera_coords(const Vector2 &p_viewport_coords) const { + Transform2D xf = get_final_transform(); + return xf.xform(p_viewport_coords); +} + +Vector2 World::get_camera_rect_size() const { + return size; +} + void World::update_worlds() { if (!is_inside_tree()) { return; @@ -415,10 +428,84 @@ World::World() { world_2d = Ref(memnew(World2D)); _override_world = NULL; _override_in_parent_viewport = false; + camera = nullptr; } World::~World() { } +void World::_camera_transform_changed_notify() { +#ifndef _3D_DISABLED +// If there is an active listener in the scene, it takes priority over the camera +// if (camera && !listener) +// SpatialSoundServer::get_singleton()->listener_set_transform(internal_listener, camera->get_camera_transform()); +#endif +} + +void World::_camera_set(Camera *p_camera) { +#ifndef _3D_DISABLED + + if (camera == p_camera) { + return; + } + + if (camera) { + camera->notification(Camera::NOTIFICATION_LOST_CURRENT); + } + camera = p_camera; + + /* + if (!camera_override) { + if (camera) { + RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera()); + } else { + RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID()); + } + } + */ + + if (camera) { + camera->notification(Camera::NOTIFICATION_BECAME_CURRENT); + } + + _update_listener(); + _camera_transform_changed_notify(); +#endif +} + +bool World::_camera_add(Camera *p_camera) { + cameras.insert(p_camera); + return cameras.size() == 1; +} + +void World::_camera_remove(Camera *p_camera) { + cameras.erase(p_camera); + if (camera == p_camera) { + camera->notification(Camera::NOTIFICATION_LOST_CURRENT); + camera = nullptr; + } +} + +#ifndef _3D_DISABLED +void World::_camera_make_next_current(Camera *p_exclude) { + for (Set::Element *E = cameras.front(); E; E = E->next()) { + if (p_exclude == E->get()) { + continue; + } + if (!E->get()->is_inside_tree()) { + continue; + } + if (camera != nullptr) { + return; + } + + E->get()->make_current(); + } +} +#endif + +void World::_update_listener() {} +void World::_update_listener_2d() {} + void World::_propagate_enter_world(Node *p_node) { if (p_node != this) { if (!p_node->is_inside_tree()) { //may not have entered scene yet @@ -548,6 +635,8 @@ void World::_notification(int p_what) { } void World::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_camera"), &World::get_camera); + ClassDB::bind_method(D_METHOD("get_world_2d"), &World::get_world_2d); ClassDB::bind_method(D_METHOD("set_world_2d", "world_2d"), &World::set_world_2d); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_2d", PROPERTY_HINT_RESOURCE_TYPE, "World2D", 0), "set_world_2d", "get_world_2d"); diff --git a/scene/main/world.h b/scene/main/world.h index ae93ad4ba..f749b7786 100644 --- a/scene/main/world.h +++ b/scene/main/world.h @@ -14,6 +14,8 @@ class World : public Node { GDCLASS(World, Node); public: + Camera *get_camera() const; + Ref get_world_2d() const; void set_world_2d(const Ref &p_world_2d); @@ -57,6 +59,9 @@ public: virtual RID get_viewport_rid() const; + Vector2 get_camera_coords(const Vector2 &p_viewport_coords) const; + Vector2 get_camera_rect_size() const; + void update_worlds(); void _world_3d_register_camera(Camera *p_camera); @@ -71,6 +76,16 @@ public: World(); ~World(); + //friend class Camera; + void _camera_transform_changed_notify(); + virtual void _camera_set(Camera *p_camera); + bool _camera_add(Camera *p_camera); //true if first + void _camera_remove(Camera *p_camera); + void _camera_make_next_current(Camera *p_exclude); + + virtual void _update_listener(); + virtual void _update_listener_2d(); + protected: void _add_overridden_world(World *p_world); void _remove_overridden_world(World *p_world); @@ -101,6 +116,11 @@ protected: Vector _overriding_worlds; Vector _override_cameras; + + Camera *camera; + Set cameras; + + Size2 size; }; #endif