diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml
index 58608a3299a..bff558e5a5b 100644
--- a/doc/classes/Viewport.xml
+++ b/doc/classes/Viewport.xml
@@ -49,12 +49,14 @@
Returns the currently active 2D camera. Returns [code]null[/code] if there are no active cameras.
+ [b]Note:[/b] If called while the [i]Camera Override[/i] system is active in editor, this will return the internally managed override camera. It is therefore advised to avoid caching the return value, or to check that the cached value is still a valid instance and is the current camera before use. See [method @GlobalScope.is_instance_valid] and [method Camera2D.is_current].
- Returns the currently active 3D camera.
+ Returns the currently active 3D camera. Returns [code]null[/code] if there are no active cameras.
+ [b]Note:[/b] If called while the [i]Camera Override[/i] system is active in editor, this will return the internally managed override camera. It is therefore advised to avoid caching the return value, or to check that the cached value is a valid instance and is the current camera before use. See [method @GlobalScope.is_instance_valid] and [member Camera3D.current].
diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp
index bfa34973222..b5372d9b01d 100644
--- a/scene/debugger/scene_debugger.cpp
+++ b/scene/debugger/scene_debugger.cpp
@@ -38,6 +38,7 @@
#include "core/object/script_language.h"
#include "core/os/time.h"
#include "core/templates/local_vector.h"
+#include "scene/2d/camera_2d.h"
#include "scene/gui/popup_menu.h"
#include "scene/main/canvas_layer.h"
#include "scene/main/scene_tree.h"
@@ -196,7 +197,7 @@ Error SceneDebugger::_msg_override_cameras(const Array &p_args) {
ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA);
bool enable = p_args[0];
bool from_editor = p_args[1];
- SceneTree::get_singleton()->get_root()->enable_canvas_transform_override(enable);
+ SceneTree::get_singleton()->get_root()->enable_camera_2d_override(enable);
#ifndef _3D_DISABLED
SceneTree::get_singleton()->get_root()->enable_camera_3d_override(enable);
#endif // _3D_DISABLED
@@ -206,8 +207,9 @@ Error SceneDebugger::_msg_override_cameras(const Array &p_args) {
Error SceneDebugger::_msg_transform_camera_2d(const Array &p_args) {
ERR_FAIL_COND_V(p_args.is_empty(), ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(!SceneTree::get_singleton()->get_root()->is_camera_2d_override_enabled(), ERR_BUG);
Transform2D transform = p_args[0];
- SceneTree::get_singleton()->get_root()->set_canvas_transform_override(transform);
+ SceneTree::get_singleton()->get_root()->get_override_camera_2d()->set_transform(transform);
RuntimeNodeSelect::get_singleton()->_queue_selection_update();
return OK;
}
@@ -215,17 +217,20 @@ Error SceneDebugger::_msg_transform_camera_2d(const Array &p_args) {
#ifndef _3D_DISABLED
Error SceneDebugger::_msg_transform_camera_3d(const Array &p_args) {
ERR_FAIL_COND_V(p_args.size() < 5, ERR_INVALID_DATA);
+ ERR_FAIL_COND_V(!SceneTree::get_singleton()->get_root()->is_camera_3d_override_enabled(), ERR_BUG);
Transform3D transform = p_args[0];
bool is_perspective = p_args[1];
float size_or_fov = p_args[2];
float depth_near = p_args[3];
float depth_far = p_args[4];
+
+ Camera3D *override_camera = SceneTree::get_singleton()->get_root()->get_override_camera_3d();
if (is_perspective) {
- SceneTree::get_singleton()->get_root()->set_camera_3d_override_perspective(size_or_fov, depth_near, depth_far);
+ override_camera->set_perspective(size_or_fov, depth_near, depth_far);
} else {
- SceneTree::get_singleton()->get_root()->set_camera_3d_override_orthogonal(size_or_fov, depth_near, depth_far);
+ override_camera->set_orthogonal(size_or_fov, depth_near, depth_far);
}
- SceneTree::get_singleton()->get_root()->set_camera_3d_override_transform(transform);
+ override_camera->set_transform(transform);
RuntimeNodeSelect::get_singleton()->_queue_selection_update();
return OK;
}
@@ -1598,23 +1603,24 @@ void RuntimeNodeSelect::_select_set_mode(SelectMode p_mode) {
void RuntimeNodeSelect::_set_camera_override_enabled(bool p_enabled) {
camera_override = p_enabled;
- if (p_enabled) {
- _update_view_2d();
- }
-
-#ifndef _3D_DISABLED
+ Window *root = SceneTree::get_singleton()->get_root();
if (camera_first_override) {
_reset_camera_2d();
+#ifndef _3D_DISABLED
_reset_camera_3d();
+#endif // _3D_DISABLED
camera_first_override = false;
} else if (p_enabled) {
_update_view_2d();
- SceneTree::get_singleton()->get_root()->set_camera_3d_override_transform(_get_cursor_transform());
- SceneTree::get_singleton()->get_root()->set_camera_3d_override_perspective(camera_fov * cursor.fov_scale, camera_znear, camera_zfar);
- }
+#ifndef _3D_DISABLED
+ ERR_FAIL_COND(!root->is_camera_3d_override_enabled());
+ Camera3D *override_camera = root->get_override_camera_3d();
+ override_camera->set_transform(_get_cursor_transform());
+ override_camera->set_perspective(camera_fov * cursor.fov_scale, camera_znear, camera_zfar);
#endif // _3D_DISABLED
+ }
}
void RuntimeNodeSelect::_root_window_input(const Ref &p_event) {
@@ -1756,13 +1762,16 @@ void RuntimeNodeSelect::_process_frame() {
}
if (direction != Vector3()) {
+ Window *root = SceneTree::get_singleton()->get_root();
+ ERR_FAIL_COND(!root->is_camera_3d_override_enabled());
+
// Calculate the process time manually, as the time scale is frozen.
const double process_time = (1.0 / Engine::get_singleton()->get_frames_per_second()) * Engine::get_singleton()->get_unfrozen_time_scale();
const Vector3 motion = direction * speed * process_time;
cursor.pos += motion;
cursor.eye_pos += motion;
- SceneTree::get_singleton()->get_root()->set_camera_3d_override_transform(_get_cursor_transform());
+ root->get_override_camera_3d()->set_transform(_get_cursor_transform());
}
}
#endif // _3D_DISABLED
@@ -2091,8 +2100,6 @@ void RuntimeNodeSelect::_queue_selection_update() {
}
void RuntimeNodeSelect::_update_selection() {
- Window *root = SceneTree::get_singleton()->get_root();
-
RS::get_singleton()->canvas_item_clear(sbox_2d_ci);
RS::get_singleton()->canvas_item_set_visible(sbox_2d_ci, selection_visible);
@@ -2109,13 +2116,7 @@ void RuntimeNodeSelect::_update_selection() {
continue;
}
- Transform2D xform;
- // Cameras (overridden or not) don't affect `CanvasLayer`s.
- if (root->is_canvas_transform_override_enabled() && !(ci->get_canvas_layer_node() && !ci->get_canvas_layer_node()->is_following_viewport())) {
- xform = root->get_canvas_transform_override() * ci->get_global_transform();
- } else {
- xform = ci->get_global_transform_with_canvas();
- }
+ Transform2D xform = ci->get_global_transform_with_canvas();
// Fallback.
Rect2 rect = Rect2(Vector2(), Vector2(10, 10));
@@ -2247,27 +2248,8 @@ void RuntimeNodeSelect::_update_selection_drag(const Point2 &p_end_pos) {
return;
}
- Window *root = SceneTree::get_singleton()->get_root();
- Rect2 selection_drawing;
- int thickness;
- if (root->is_canvas_transform_override_enabled()) {
- Transform2D xform = root->get_canvas_transform_override();
- RS::get_singleton()->canvas_item_set_transform(sel_drag_ci, xform);
- RS::get_singleton()->canvas_item_reset_physics_interpolation(sel_drag_ci);
-
- selection_drawing.position = xform.affine_inverse().xform(selection_drag_area.position);
- selection_drawing.size = xform.affine_inverse().xform(p_end_pos);
- thickness = MAX(1, Math::ceil(1 / view_2d_zoom));
- } else {
- RS::get_singleton()->canvas_item_set_transform(sel_drag_ci, Transform2D());
- RS::get_singleton()->canvas_item_reset_physics_interpolation(sel_drag_ci);
-
- selection_drawing.position = selection_drag_area.position;
- selection_drawing.size = p_end_pos;
- thickness = 1;
- }
- selection_drawing.size -= selection_drawing.position;
- selection_drawing = selection_drawing.abs();
+ Rect2 selection_drawing = selection_drag_area.abs();
+ int thickness = 1;
const Vector2 endpoints[4] = {
selection_drawing.position,
@@ -2352,9 +2334,10 @@ void RuntimeNodeSelect::_find_canvas_items_at_pos(const Point2 &p_pos, Node *p_n
Window *root = SceneTree::get_singleton()->get_root();
Point2 pos;
- // Cameras (overridden or not) don't affect `CanvasLayer`s.
+
+ // Cameras don't affect `CanvasLayer`s.
if (!ci->get_canvas_layer_node() || ci->get_canvas_layer_node()->is_following_viewport()) {
- pos = (root->is_canvas_transform_override_enabled() ? root->get_canvas_transform_override() : root->get_canvas_transform()).affine_inverse().xform(p_pos);
+ pos = root->get_canvas_transform().affine_inverse().xform(p_pos);
} else {
pos = p_pos;
}
@@ -2414,9 +2397,9 @@ void RuntimeNodeSelect::_find_canvas_items_at_rect(const Rect2 &p_rect, Node *p_
Window *root = SceneTree::get_singleton()->get_root();
Rect2 rect;
- // Cameras (overridden or not) don't affect `CanvasLayer`s.
+ // Cameras don't affect `CanvasLayer`s.
if (!ci->get_canvas_layer_node() || ci->get_canvas_layer_node()->is_following_viewport()) {
- rect = (root->is_canvas_transform_override_enabled() ? root->get_canvas_transform_override() : root->get_canvas_transform()).affine_inverse().xform(p_rect);
+ rect = root->get_canvas_transform().affine_inverse().xform(p_rect);
} else {
rect = p_rect;
}
@@ -2475,18 +2458,30 @@ void RuntimeNodeSelect::_zoom_callback(float p_zoom_factor, Vector2 p_origin, Re
}
void RuntimeNodeSelect::_reset_camera_2d() {
- view_2d_offset = -SceneTree::get_singleton()->get_root()->get_canvas_transform().get_origin();
+ Window *root = SceneTree::get_singleton()->get_root();
+ Camera2D *game_camera = root->is_camera_2d_override_enabled() ? root->get_overridden_camera_2d() : root->get_camera_2d();
+ if (game_camera) {
+ // Ideally we should be using Camera2D::get_camera_transform() but it's not so this hack will have to do for now.
+ view_2d_offset = game_camera->get_camera_screen_center() - (0.5 * root->get_visible_rect().size);
+ } else {
+ view_2d_offset = Vector2();
+ }
+
view_2d_zoom = 1;
- _update_view_2d();
+ if (root->is_camera_2d_override_enabled()) {
+ _update_view_2d();
+ }
}
void RuntimeNodeSelect::_update_view_2d() {
- Transform2D transform = Transform2D();
- transform.scale_basis(Size2(view_2d_zoom, view_2d_zoom));
- transform.columns[2] = -view_2d_offset * view_2d_zoom;
+ Window *root = SceneTree::get_singleton()->get_root();
+ ERR_FAIL_COND(!root->is_camera_2d_override_enabled());
- SceneTree::get_singleton()->get_root()->set_canvas_transform_override(transform);
+ Camera2D *override_camera = root->get_override_camera_2d();
+ override_camera->set_anchor_mode(Camera2D::ANCHOR_MODE_FIXED_TOP_LEFT);
+ override_camera->set_zoom(Vector2(view_2d_zoom, view_2d_zoom));
+ override_camera->set_position(view_2d_offset);
_queue_selection_update();
}
@@ -2496,21 +2491,15 @@ void RuntimeNodeSelect::_find_3d_items_at_pos(const Point2 &p_pos, Vector