Now Cameras use Worlds directly instead of Viewports.

This commit is contained in:
Relintai 2022-08-30 14:08:27 +02:00
parent 786e20b159
commit 66f2357d01
6 changed files with 140 additions and 96 deletions

View File

@ -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<Vector3> Camera::get_near_plane_points() const {
ERR_FAIL_COND_V_MSG(!is_inside_tree(), Vector<Vector3>(), "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<Vector3> 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<Plane> Camera::get_frustum() const {
ERR_FAIL_COND_V(!is_inside_world(), Vector<Plane>());
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);

View File

@ -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;

View File

@ -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<Camera *>::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)

View File

@ -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<InputEvent> &p_event);
void unhandled_input(const Ref<InputEvent> &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<Camera *> cameras;
Listener2D *listener_2d = nullptr;
Set<CanvasLayer *> 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);

View File

@ -9,6 +9,10 @@
#include "scene/resources/world_3d.h"
#include "viewport.h"
Camera *World::get_camera() const {
return camera;
}
Ref<World2D> 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<World2D>(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<Camera *>::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");

View File

@ -14,6 +14,8 @@ class World : public Node {
GDCLASS(World, Node);
public:
Camera *get_camera() const;
Ref<World2D> get_world_2d() const;
void set_world_2d(const Ref<World2D> &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<World *> _overriding_worlds;
Vector<Camera *> _override_cameras;
Camera *camera;
Set<Camera *> cameras;
Size2 size;
};
#endif