You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-09 12:50:35 +00:00
Cleanup and simplify camera override API
- Harmonise the camera override 2D and 3D APIs - Switch to using Camera2D/3D nodes to provide override functionality. This makes for simpler code, gets rid of much of copy-pasted camera code and makes code that relies on current viewport camera such as VisibleOnScreenNotifiers and object picking work out of the box. - Make camera override code only accesible within DEBUG_ENABLED builds
This commit is contained in:
@@ -49,12 +49,14 @@
|
||||
<return type="Camera2D" />
|
||||
<description>
|
||||
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].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_camera_3d" qualifiers="const">
|
||||
<return type="Camera3D" />
|
||||
<description>
|
||||
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].
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_canvas_cull_mask_bit" qualifiers="const">
|
||||
|
||||
@@ -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,24 +1603,25 @@ 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<InputEvent> &p_event) {
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
@@ -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;
|
||||
|
||||
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,11 +2491,6 @@ void RuntimeNodeSelect::_find_3d_items_at_pos(const Point2 &p_pos, Vector<Select
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
|
||||
Vector3 ray, pos, to;
|
||||
if (root->is_camera_3d_override_enabled()) {
|
||||
ray = root->camera_3d_override_project_ray_normal(p_pos);
|
||||
pos = root->camera_3d_override_project_ray_origin(p_pos);
|
||||
to = pos + ray * root->get_camera_3d_override_properties()["z_far"];
|
||||
} else {
|
||||
Camera3D *camera = root->get_camera_3d();
|
||||
if (!camera) {
|
||||
return;
|
||||
@@ -2509,7 +2499,6 @@ void RuntimeNodeSelect::_find_3d_items_at_pos(const Point2 &p_pos, Vector<Select
|
||||
ray = camera->project_ray_normal(p_pos);
|
||||
pos = camera->project_ray_origin(p_pos);
|
||||
to = pos + ray * camera->get_far();
|
||||
}
|
||||
|
||||
#ifndef PHYSICS_3D_DISABLED
|
||||
// Start with physical objects.
|
||||
@@ -2585,30 +2574,12 @@ void RuntimeNodeSelect::_find_3d_items_at_rect(const Rect2 &p_rect, Vector<Selec
|
||||
return;
|
||||
}
|
||||
|
||||
bool cam_override = root->is_camera_3d_override_enabled();
|
||||
Vector3 cam_pos;
|
||||
Vector3 dist_pos;
|
||||
if (cam_override) {
|
||||
cam_pos = root->get_camera_3d_override_transform().origin;
|
||||
dist_pos = root->camera_3d_override_project_ray_origin(p_rect.position + p_rect.size / 2);
|
||||
} else {
|
||||
cam_pos = camera->get_global_position();
|
||||
dist_pos = camera->project_ray_origin(p_rect.position + p_rect.size / 2);
|
||||
}
|
||||
Vector3 cam_pos = camera->get_global_position();
|
||||
Vector3 dist_pos = camera->project_ray_origin(p_rect.position + p_rect.size / 2);
|
||||
|
||||
real_t znear, zfar = 0;
|
||||
real_t zofs = 5.0;
|
||||
if (cam_override) {
|
||||
HashMap<StringName, real_t> override_props = root->get_camera_3d_override_properties();
|
||||
znear = override_props["z_near"];
|
||||
zfar = override_props["z_far"];
|
||||
zofs -= znear;
|
||||
} else {
|
||||
znear = camera->get_near();
|
||||
zfar = camera->get_far();
|
||||
zofs -= znear;
|
||||
}
|
||||
zofs = MAX(0.0, zofs);
|
||||
real_t znear = camera->get_near();
|
||||
real_t zfar = camera->get_far();
|
||||
real_t zofs = MAX(0.0, 5.0 - znear);
|
||||
|
||||
const Point2 pos_end = p_rect.position + p_rect.size;
|
||||
Vector3 box[4] = {
|
||||
@@ -2637,13 +2608,9 @@ void RuntimeNodeSelect::_find_3d_items_at_rect(const Rect2 &p_rect, Vector<Selec
|
||||
frustum.push_back(Plane(a, b, cam_pos));
|
||||
}
|
||||
|
||||
Plane near_plane;
|
||||
// Get the camera normal.
|
||||
if (cam_override) {
|
||||
near_plane = Plane(root->get_camera_3d_override_transform().basis.get_column(2), cam_pos);
|
||||
} else {
|
||||
near_plane = Plane(camera->get_global_transform().basis.get_column(2), cam_pos);
|
||||
}
|
||||
Plane near_plane = Plane(camera->get_global_transform().basis.get_column(2), cam_pos);
|
||||
|
||||
near_plane.d -= znear;
|
||||
frustum.push_back(near_plane);
|
||||
|
||||
@@ -2728,27 +2695,10 @@ Vector3 RuntimeNodeSelect::_get_screen_to_space(const Vector3 &p_vector3) {
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
Camera3D *camera = root->get_camera_3d();
|
||||
|
||||
Transform3D camera_transform = camera->get_camera_transform();
|
||||
Size2 size = root->get_size();
|
||||
real_t znear = 0;
|
||||
|
||||
Projection cm;
|
||||
Transform3D camera_transform;
|
||||
if (root->is_camera_3d_override_enabled()) {
|
||||
HashMap<StringName, real_t> override_props = root->get_camera_3d_override_properties();
|
||||
znear = override_props["z_near"];
|
||||
cm.set_perspective(override_props["fov"], size.aspect(), znear + p_vector3.z, override_props["z_far"]);
|
||||
|
||||
camera_transform.translate_local(cursor.pos);
|
||||
camera_transform.basis.rotate(Vector3(1, 0, 0), -cursor.x_rot);
|
||||
camera_transform.basis.rotate(Vector3(0, 1, 0), -cursor.y_rot);
|
||||
camera_transform.translate_local(0, 0, cursor.distance);
|
||||
} else {
|
||||
znear = camera->get_near();
|
||||
cm.set_perspective(camera->get_fov(), size.aspect(), znear + p_vector3.z, camera->get_far());
|
||||
|
||||
camera_transform = camera->get_camera_transform();
|
||||
}
|
||||
|
||||
real_t znear = camera->get_near();
|
||||
Projection cm = Projection::create_perspective(camera->get_fov(), size.aspect(), znear + p_vector3.z, camera->get_far());
|
||||
Vector2 screen_he = cm.get_viewport_half_extents();
|
||||
return camera_transform.xform(Vector3(((p_vector3.x / size.width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (p_vector3.y / size.height)) * 2.0 - 1.0) * screen_he.y, -(znear + p_vector3.z)));
|
||||
}
|
||||
@@ -2808,20 +2758,23 @@ bool RuntimeNodeSelect::_handle_3d_input(const Ref<InputEvent> &p_event) {
|
||||
} else if (k->is_ctrl_pressed()) {
|
||||
switch (k->get_physical_keycode()) {
|
||||
case Key::EQUAL: {
|
||||
ERR_FAIL_COND_V(!SceneTree::get_singleton()->get_root()->is_camera_3d_override_enabled(), false);
|
||||
cursor.fov_scale = CLAMP(cursor.fov_scale - 0.05, CAMERA_MIN_FOV_SCALE, CAMERA_MAX_FOV_SCALE);
|
||||
SceneTree::get_singleton()->get_root()->set_camera_3d_override_perspective(camera_fov * cursor.fov_scale, camera_znear, camera_zfar);
|
||||
SceneTree::get_singleton()->get_root()->get_override_camera_3d()->set_perspective(camera_fov * cursor.fov_scale, camera_znear, camera_zfar);
|
||||
|
||||
return true;
|
||||
} break;
|
||||
case Key::MINUS: {
|
||||
ERR_FAIL_COND_V(!SceneTree::get_singleton()->get_root()->is_camera_3d_override_enabled(), false);
|
||||
cursor.fov_scale = CLAMP(cursor.fov_scale + 0.05, CAMERA_MIN_FOV_SCALE, CAMERA_MAX_FOV_SCALE);
|
||||
SceneTree::get_singleton()->get_root()->set_camera_3d_override_perspective(camera_fov * cursor.fov_scale, camera_znear, camera_zfar);
|
||||
SceneTree::get_singleton()->get_root()->get_override_camera_3d()->set_perspective(camera_fov * cursor.fov_scale, camera_znear, camera_zfar);
|
||||
|
||||
return true;
|
||||
} break;
|
||||
case Key::KEY_0: {
|
||||
ERR_FAIL_COND_V(!SceneTree::get_singleton()->get_root()->is_camera_3d_override_enabled(), false);
|
||||
cursor.fov_scale = 1;
|
||||
SceneTree::get_singleton()->get_root()->set_camera_3d_override_perspective(camera_fov, camera_znear, camera_zfar);
|
||||
SceneTree::get_singleton()->get_root()->get_override_camera_3d()->set_perspective(camera_fov, camera_znear, camera_zfar);
|
||||
|
||||
return true;
|
||||
} break;
|
||||
@@ -2861,11 +2814,12 @@ void RuntimeNodeSelect::_set_camera_freelook_enabled(bool p_enabled) {
|
||||
}
|
||||
|
||||
void RuntimeNodeSelect::_cursor_scale_distance(real_t p_scale) {
|
||||
ERR_FAIL_COND(!SceneTree::get_singleton()->get_root()->is_camera_3d_override_enabled());
|
||||
real_t min_distance = MAX(camera_znear * 4, VIEW_3D_MIN_ZOOM);
|
||||
real_t max_distance = MIN(camera_zfar / 4, VIEW_3D_MAX_ZOOM);
|
||||
cursor.distance = CLAMP(cursor.distance * p_scale, min_distance, max_distance);
|
||||
|
||||
SceneTree::get_singleton()->get_root()->set_camera_3d_override_transform(_get_cursor_transform());
|
||||
SceneTree::get_singleton()->get_root()->get_override_camera_3d()->set_transform(_get_cursor_transform());
|
||||
}
|
||||
|
||||
void RuntimeNodeSelect::_scale_freelook_speed(real_t p_scale) {
|
||||
@@ -2880,6 +2834,8 @@ void RuntimeNodeSelect::_scale_freelook_speed(real_t p_scale) {
|
||||
|
||||
void RuntimeNodeSelect::_cursor_look(Ref<InputEventWithModifiers> p_event) {
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
ERR_FAIL_COND(!root->is_camera_3d_override_enabled());
|
||||
|
||||
const Vector2 relative = _get_warped_mouse_motion(p_event, Rect2(Vector2(), root->get_size()));
|
||||
const Transform3D prev_camera_transform = _get_cursor_transform();
|
||||
|
||||
@@ -2900,11 +2856,13 @@ void RuntimeNodeSelect::_cursor_look(Ref<InputEventWithModifiers> p_event) {
|
||||
Vector3 diff = prev_pos - pos;
|
||||
cursor.pos += diff;
|
||||
|
||||
SceneTree::get_singleton()->get_root()->set_camera_3d_override_transform(_get_cursor_transform());
|
||||
root->get_override_camera_3d()->set_transform(_get_cursor_transform());
|
||||
}
|
||||
|
||||
void RuntimeNodeSelect::_cursor_pan(Ref<InputEventWithModifiers> p_event) {
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
ERR_FAIL_COND(!root->is_camera_3d_override_enabled());
|
||||
|
||||
// Reduce all sides of the area by 1, so warping works when windows are maximized/fullscreen.
|
||||
const Vector2 relative = _get_warped_mouse_motion(p_event, Rect2(Vector2(1, 1), root->get_size() - Vector2(2, 2)));
|
||||
const real_t pan_speed = translation_sensitivity / 150.0;
|
||||
@@ -2919,11 +2877,13 @@ void RuntimeNodeSelect::_cursor_pan(Ref<InputEventWithModifiers> p_event) {
|
||||
camera_transform.translate_local(translation);
|
||||
cursor.pos = camera_transform.origin;
|
||||
|
||||
SceneTree::get_singleton()->get_root()->set_camera_3d_override_transform(_get_cursor_transform());
|
||||
root->get_override_camera_3d()->set_transform(_get_cursor_transform());
|
||||
}
|
||||
|
||||
void RuntimeNodeSelect::_cursor_orbit(Ref<InputEventWithModifiers> p_event) {
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
ERR_FAIL_COND(!root->is_camera_3d_override_enabled());
|
||||
|
||||
// Reduce all sides of the area by 1, so warping works when windows are maximized/fullscreen.
|
||||
const Vector2 relative = _get_warped_mouse_motion(p_event, Rect2(Vector2(1, 1), root->get_size() - Vector2(2, 2)));
|
||||
|
||||
@@ -2941,7 +2901,7 @@ void RuntimeNodeSelect::_cursor_orbit(Ref<InputEventWithModifiers> p_event) {
|
||||
cursor.y_rot += relative.x * orbit_sensitivity;
|
||||
}
|
||||
|
||||
SceneTree::get_singleton()->get_root()->set_camera_3d_override_transform(_get_cursor_transform());
|
||||
root->get_override_camera_3d()->set_transform(_get_cursor_transform());
|
||||
}
|
||||
|
||||
Point2 RuntimeNodeSelect::_get_warped_mouse_motion(const Ref<InputEventMouseMotion> &p_event, Rect2 p_area) const {
|
||||
@@ -2969,22 +2929,25 @@ void RuntimeNodeSelect::_reset_camera_3d() {
|
||||
|
||||
cursor = Cursor();
|
||||
Window *root = SceneTree::get_singleton()->get_root();
|
||||
Camera3D *camera = root->get_camera_3d();
|
||||
if (camera) {
|
||||
Transform3D transform = camera->get_global_transform();
|
||||
Camera3D *game_camera = root->is_camera_3d_override_enabled() ? root->get_overridden_camera_3d() : root->get_camera_3d();
|
||||
if (game_camera) {
|
||||
Transform3D transform = game_camera->get_camera_transform();
|
||||
transform.translate_local(0, 0, -cursor.distance);
|
||||
cursor.pos = transform.origin;
|
||||
|
||||
cursor.x_rot = -camera->get_global_rotation().x;
|
||||
cursor.y_rot = -camera->get_global_rotation().y;
|
||||
cursor.x_rot = -game_camera->get_global_rotation().x;
|
||||
cursor.y_rot = -game_camera->get_global_rotation().y;
|
||||
|
||||
cursor.fov_scale = CLAMP(camera->get_fov() / camera_fov, CAMERA_MIN_FOV_SCALE, CAMERA_MAX_FOV_SCALE);
|
||||
cursor.fov_scale = CLAMP(game_camera->get_fov() / camera_fov, CAMERA_MIN_FOV_SCALE, CAMERA_MAX_FOV_SCALE);
|
||||
} else {
|
||||
cursor.fov_scale = 1.0;
|
||||
}
|
||||
|
||||
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);
|
||||
if (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
|
||||
|
||||
|
||||
@@ -1189,50 +1189,41 @@ void Viewport::canvas_parent_mark_dirty(Node *p_node) {
|
||||
}
|
||||
}
|
||||
|
||||
void Viewport::enable_canvas_transform_override(bool p_enable) {
|
||||
#if DEBUG_ENABLED
|
||||
void Viewport::enable_camera_2d_override(bool p_enable) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
if (override_canvas_transform == p_enable) {
|
||||
return;
|
||||
}
|
||||
|
||||
override_canvas_transform = p_enable;
|
||||
if (p_enable) {
|
||||
RenderingServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform_override);
|
||||
camera_2d_override.enable(this, camera_2d);
|
||||
} else {
|
||||
RenderingServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform);
|
||||
camera_2d_override.disable(camera_2d);
|
||||
}
|
||||
}
|
||||
|
||||
bool Viewport::is_canvas_transform_override_enabled() const {
|
||||
bool Viewport::is_camera_2d_override_enabled() const {
|
||||
ERR_READ_THREAD_GUARD_V(false);
|
||||
return override_canvas_transform;
|
||||
return camera_2d_override.is_enabled();
|
||||
}
|
||||
|
||||
void Viewport::set_canvas_transform_override(const Transform2D &p_transform) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
if (canvas_transform_override == p_transform) {
|
||||
return;
|
||||
Camera2D *Viewport::get_overridden_camera_2d() const {
|
||||
ERR_READ_THREAD_GUARD_V(nullptr);
|
||||
ERR_FAIL_COND_V(!camera_2d_override.is_enabled(), nullptr);
|
||||
return camera_2d_override.get_overridden_camera();
|
||||
}
|
||||
|
||||
canvas_transform_override = p_transform;
|
||||
if (override_canvas_transform) {
|
||||
RenderingServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform_override);
|
||||
}
|
||||
}
|
||||
|
||||
Transform2D Viewport::get_canvas_transform_override() const {
|
||||
ERR_READ_THREAD_GUARD_V(Transform2D());
|
||||
return canvas_transform_override;
|
||||
Camera2D *Viewport::get_override_camera_2d() const {
|
||||
ERR_READ_THREAD_GUARD_V(nullptr);
|
||||
ERR_FAIL_COND_V(!camera_2d_override.is_enabled(), nullptr);
|
||||
return camera_2d_override.is_enabled() ? get_camera_2d() : nullptr;
|
||||
}
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
void Viewport::set_canvas_transform(const Transform2D &p_transform) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
canvas_transform = p_transform;
|
||||
|
||||
if (!override_canvas_transform) {
|
||||
RenderingServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform);
|
||||
}
|
||||
}
|
||||
|
||||
Transform2D Viewport::get_canvas_transform() const {
|
||||
ERR_READ_THREAD_GUARD_V(Transform2D());
|
||||
@@ -4220,6 +4211,13 @@ void Viewport::_audio_listener_2d_remove(AudioListener2D *p_audio_listener) {
|
||||
}
|
||||
|
||||
void Viewport::_camera_2d_set(Camera2D *p_camera_2d) {
|
||||
#if DEBUG_ENABLED
|
||||
if (is_camera_2d_override_enabled()) {
|
||||
camera_2d_override.set_overridden_camera(p_camera_2d);
|
||||
return;
|
||||
}
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
camera_2d = p_camera_2d;
|
||||
}
|
||||
|
||||
@@ -4454,19 +4452,24 @@ void Viewport::_camera_3d_set(Camera3D *p_camera) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if DEBUG_ENABLED
|
||||
if (is_camera_3d_override_enabled()) {
|
||||
camera_3d_override.set_overridden_camera(p_camera);
|
||||
return;
|
||||
}
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
if (camera_3d) {
|
||||
camera_3d->notification(Camera3D::NOTIFICATION_LOST_CURRENT);
|
||||
}
|
||||
|
||||
camera_3d = p_camera;
|
||||
|
||||
if (!camera_3d_override) {
|
||||
if (camera_3d) {
|
||||
RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_3d->get_camera());
|
||||
} else {
|
||||
RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID());
|
||||
}
|
||||
}
|
||||
|
||||
if (camera_3d) {
|
||||
camera_3d->notification(Camera3D::NOTIFICATION_BECAME_CURRENT);
|
||||
@@ -4504,77 +4507,34 @@ void Viewport::_camera_3d_make_next_current(Camera3D *p_exclude) {
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG_ENABLED
|
||||
void Viewport::enable_camera_3d_override(bool p_enable) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
if (p_enable == camera_3d_override) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_enable) {
|
||||
camera_3d_override.rid = RenderingServer::get_singleton()->camera_create();
|
||||
camera_3d_override.enable(this, camera_3d);
|
||||
} else {
|
||||
RenderingServer::get_singleton()->free(camera_3d_override.rid);
|
||||
camera_3d_override.rid = RID();
|
||||
}
|
||||
|
||||
if (p_enable) {
|
||||
RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_3d_override.rid);
|
||||
} else if (camera_3d) {
|
||||
RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_3d->get_camera());
|
||||
} else {
|
||||
RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID());
|
||||
camera_3d_override.disable(camera_3d);
|
||||
}
|
||||
}
|
||||
|
||||
void Viewport::set_camera_3d_override_perspective(real_t p_fovy_degrees, real_t p_z_near, real_t p_z_far) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
if (camera_3d_override) {
|
||||
if (camera_3d_override.fov == p_fovy_degrees && camera_3d_override.z_near == p_z_near &&
|
||||
camera_3d_override.z_far == p_z_far && camera_3d_override.projection == Camera3DOverrideData::PROJECTION_PERSPECTIVE) {
|
||||
return;
|
||||
bool Viewport::is_camera_3d_override_enabled() const {
|
||||
ERR_READ_THREAD_GUARD_V(false);
|
||||
return camera_3d_override.is_enabled();
|
||||
}
|
||||
|
||||
camera_3d_override.fov = p_fovy_degrees;
|
||||
camera_3d_override.z_near = p_z_near;
|
||||
camera_3d_override.z_far = p_z_far;
|
||||
camera_3d_override.projection = Camera3DOverrideData::PROJECTION_PERSPECTIVE;
|
||||
|
||||
RenderingServer::get_singleton()->camera_set_perspective(camera_3d_override.rid, camera_3d_override.fov, camera_3d_override.z_near, camera_3d_override.z_far);
|
||||
}
|
||||
Camera3D *Viewport::get_overridden_camera_3d() const {
|
||||
ERR_READ_THREAD_GUARD_V(nullptr);
|
||||
ERR_FAIL_COND_V(!camera_3d_override.is_enabled(), nullptr);
|
||||
return camera_3d_override.get_overridden_camera();
|
||||
}
|
||||
|
||||
void Viewport::set_camera_3d_override_orthogonal(real_t p_size, real_t p_z_near, real_t p_z_far) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
if (camera_3d_override) {
|
||||
if (camera_3d_override.size == p_size && camera_3d_override.z_near == p_z_near &&
|
||||
camera_3d_override.z_far == p_z_far && camera_3d_override.projection == Camera3DOverrideData::PROJECTION_ORTHOGONAL) {
|
||||
return;
|
||||
}
|
||||
|
||||
camera_3d_override.size = p_size;
|
||||
camera_3d_override.z_near = p_z_near;
|
||||
camera_3d_override.z_far = p_z_far;
|
||||
camera_3d_override.projection = Camera3DOverrideData::PROJECTION_ORTHOGONAL;
|
||||
|
||||
RenderingServer::get_singleton()->camera_set_orthogonal(camera_3d_override.rid, camera_3d_override.size, camera_3d_override.z_near, camera_3d_override.z_far);
|
||||
}
|
||||
}
|
||||
|
||||
HashMap<StringName, real_t> Viewport::get_camera_3d_override_properties() const {
|
||||
HashMap<StringName, real_t> props;
|
||||
|
||||
props["size"] = 0;
|
||||
props["fov"] = 0;
|
||||
props["z_near"] = 0;
|
||||
props["z_far"] = 0;
|
||||
ERR_READ_THREAD_GUARD_V(props);
|
||||
|
||||
props["size"] = camera_3d_override.size;
|
||||
props["fov"] = camera_3d_override.fov;
|
||||
props["z_near"] = camera_3d_override.z_near;
|
||||
props["z_far"] = camera_3d_override.z_far;
|
||||
return props;
|
||||
Camera3D *Viewport::get_override_camera_3d() const {
|
||||
ERR_READ_THREAD_GUARD_V(nullptr);
|
||||
ERR_FAIL_COND_V(!camera_3d_override.is_enabled(), nullptr);
|
||||
return get_camera_3d();
|
||||
}
|
||||
#endif //DEBUG_ENABLED
|
||||
|
||||
void Viewport::set_disable_3d(bool p_disable) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
@@ -4587,76 +4547,6 @@ bool Viewport::is_3d_disabled() const {
|
||||
return disable_3d;
|
||||
}
|
||||
|
||||
bool Viewport::is_camera_3d_override_enabled() const {
|
||||
ERR_READ_THREAD_GUARD_V(false);
|
||||
return camera_3d_override;
|
||||
}
|
||||
|
||||
void Viewport::set_camera_3d_override_transform(const Transform3D &p_transform) {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
if (camera_3d_override) {
|
||||
camera_3d_override.transform = p_transform;
|
||||
RenderingServer::get_singleton()->camera_set_transform(camera_3d_override.rid, p_transform);
|
||||
}
|
||||
}
|
||||
|
||||
Transform3D Viewport::get_camera_3d_override_transform() const {
|
||||
ERR_READ_THREAD_GUARD_V(Transform3D());
|
||||
if (camera_3d_override) {
|
||||
return camera_3d_override.transform;
|
||||
}
|
||||
|
||||
return Transform3D();
|
||||
}
|
||||
|
||||
Vector3 Viewport::camera_3d_override_project_ray_normal(const Point2 &p_pos) const {
|
||||
ERR_READ_THREAD_GUARD_V(Vector3());
|
||||
Vector3 ray = camera_3d_override_project_local_ray_normal(p_pos);
|
||||
return camera_3d_override.transform.basis.xform(ray).normalized();
|
||||
}
|
||||
|
||||
Vector3 Viewport::camera_3d_override_project_local_ray_normal(const Point2 &p_pos) const {
|
||||
ERR_READ_THREAD_GUARD_V(Vector3());
|
||||
Size2 viewport_size = get_camera_rect_size();
|
||||
Vector2 cpos = get_camera_coords(p_pos);
|
||||
Vector3 ray;
|
||||
|
||||
if (camera_3d_override.projection == Camera3DOverrideData::PROJECTION_ORTHOGONAL) {
|
||||
ray = Vector3(0, 0, -1);
|
||||
} else {
|
||||
Projection cm;
|
||||
cm.set_perspective(camera_3d_override.fov, get_visible_rect().size.aspect(), camera_3d_override.z_near, camera_3d_override.z_far, false);
|
||||
|
||||
Vector2 screen_he = cm.get_viewport_half_extents();
|
||||
ray = Vector3(((cpos.x / viewport_size.width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (cpos.y / viewport_size.height)) * 2.0 - 1.0) * screen_he.y, -camera_3d_override.z_near).normalized();
|
||||
}
|
||||
|
||||
return ray;
|
||||
}
|
||||
|
||||
Vector3 Viewport::camera_3d_override_project_ray_origin(const Point2 &p_pos) const {
|
||||
ERR_READ_THREAD_GUARD_V(Vector3());
|
||||
Size2 viewport_size = get_camera_rect_size();
|
||||
Vector2 cpos = get_camera_coords(p_pos);
|
||||
ERR_FAIL_COND_V(viewport_size.y == 0, Vector3());
|
||||
|
||||
if (camera_3d_override.projection == Camera3DOverrideData::PROJECTION_ORTHOGONAL) {
|
||||
Vector2 pos = cpos / viewport_size;
|
||||
real_t vsize, hsize;
|
||||
hsize = camera_3d_override.size * viewport_size.aspect();
|
||||
vsize = camera_3d_override.size;
|
||||
|
||||
Vector3 ray;
|
||||
ray.x = pos.x * (hsize)-hsize / 2;
|
||||
ray.y = (1.0 - pos.y) * (vsize)-vsize / 2;
|
||||
ray.z = -camera_3d_override.z_near;
|
||||
ray = camera_3d_override.transform.xform(ray);
|
||||
return ray;
|
||||
} else {
|
||||
return camera_3d_override.transform.origin;
|
||||
};
|
||||
}
|
||||
|
||||
Ref<World3D> Viewport::get_world_3d() const {
|
||||
ERR_READ_THREAD_GUARD_V(Ref<World3D>());
|
||||
return world_3d;
|
||||
@@ -5594,3 +5484,64 @@ void SubViewport::_validate_property(PropertyInfo &p_property) const {
|
||||
SubViewport::SubViewport() {
|
||||
RS::get_singleton()->viewport_set_size(get_viewport_rid(), get_size().width, get_size().height);
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
|
||||
#if DEBUG_ENABLED
|
||||
template <class T>
|
||||
bool Viewport::CameraOverride<T>::is_enabled() const {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void Viewport::CameraOverride<T>::enable(Viewport *p_viewport, const T *p_current_camera) {
|
||||
if (enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
T *override_camera = memnew(T);
|
||||
override_camera->set_name(vformat("Override%s", T ::get_class_static()));
|
||||
p_viewport->add_child(override_camera, false, Node::INTERNAL_MODE_BACK);
|
||||
|
||||
override_camera->make_current();
|
||||
set_overridden_camera(p_current_camera);
|
||||
|
||||
// Call to make the override camera current must happen before we enable the override to prevent the override mechanism from kicking in.
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void Viewport::CameraOverride<T>::disable(T *p_current_camera) {
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Call to make the overridden camera current must happen after we disable the override to prevent the override mechanism from kicking in.
|
||||
enabled = false;
|
||||
|
||||
T *overridden_camera = get_overridden_camera();
|
||||
if (overridden_camera) {
|
||||
overridden_camera->make_current();
|
||||
} else {
|
||||
p_current_camera->clear_current();
|
||||
}
|
||||
|
||||
p_current_camera->queue_free();
|
||||
overridden_camera_id = ObjectID();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void Viewport::CameraOverride<T>::set_overridden_camera(const T *p_camera) {
|
||||
overridden_camera_id = p_camera ? p_camera->get_instance_id() : ObjectID();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T *Viewport::CameraOverride<T>::get_overridden_camera() const {
|
||||
return ObjectDB::get_instance<T>(overridden_camera_id);
|
||||
}
|
||||
|
||||
// Explicit template instantiation to allow template definitions inside cpp file
|
||||
// and prevent instantiation using other than the desired camera types.
|
||||
template class Viewport::CameraOverride<Camera2D>;
|
||||
template class Viewport::CameraOverride<Camera3D>;
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
@@ -248,9 +248,6 @@ private:
|
||||
RID current_canvas;
|
||||
RID subwindow_canvas;
|
||||
|
||||
bool override_canvas_transform = false;
|
||||
|
||||
Transform2D canvas_transform_override;
|
||||
Transform2D canvas_transform;
|
||||
Transform2D global_canvas_transform;
|
||||
Transform2D stretch_transform;
|
||||
@@ -533,11 +530,12 @@ public:
|
||||
Ref<World2D> get_world_2d() const;
|
||||
Ref<World2D> find_world_2d() const;
|
||||
|
||||
void enable_canvas_transform_override(bool p_enable);
|
||||
bool is_canvas_transform_override_enabled() const;
|
||||
|
||||
void set_canvas_transform_override(const Transform2D &p_transform);
|
||||
Transform2D get_canvas_transform_override() const;
|
||||
#if DEBUG_ENABLED
|
||||
void enable_camera_2d_override(bool p_enable);
|
||||
bool is_camera_2d_override_enabled() const;
|
||||
Camera2D *get_overridden_camera_2d() const;
|
||||
Camera2D *get_override_camera_2d() const;
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
void set_canvas_transform(const Transform2D &p_transform);
|
||||
Transform2D get_canvas_transform() const;
|
||||
@@ -737,6 +735,23 @@ public:
|
||||
virtual bool is_sub_viewport() const { return false; }
|
||||
|
||||
private:
|
||||
#if DEBUG_ENABLED
|
||||
template <class T>
|
||||
class CameraOverride {
|
||||
private:
|
||||
bool enabled = false;
|
||||
ObjectID overridden_camera_id;
|
||||
|
||||
public:
|
||||
bool is_enabled() const;
|
||||
void enable(Viewport *p_viewport, const T *p_current_camera);
|
||||
void disable(T *p_current_camera);
|
||||
|
||||
void set_overridden_camera(const T *p_camera);
|
||||
T *get_overridden_camera() const;
|
||||
};
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
// 2D audio, camera, and physics. (don't put World2D here because World2D is needed for Control nodes).
|
||||
friend class AudioListener2D; // Needs _audio_listener_2d_set and _audio_listener_2d_remove
|
||||
AudioListener2D *audio_listener_2d = nullptr;
|
||||
@@ -747,6 +762,9 @@ private:
|
||||
|
||||
friend class Camera2D; // Needs _camera_2d_set
|
||||
Camera2D *camera_2d = nullptr;
|
||||
#if DEBUG_ENABLED
|
||||
CameraOverride<Camera2D> camera_2d_override;
|
||||
#endif // DEBUG_ENABLED
|
||||
void _camera_2d_set(Camera2D *p_camera_2d);
|
||||
|
||||
#ifndef PHYSICS_2D_DISABLED
|
||||
@@ -786,26 +804,11 @@ private:
|
||||
void _collision_object_3d_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);
|
||||
#endif // PHYSICS_3D_DISABLED
|
||||
|
||||
struct Camera3DOverrideData {
|
||||
Transform3D transform;
|
||||
enum Projection {
|
||||
PROJECTION_PERSPECTIVE,
|
||||
PROJECTION_ORTHOGONAL
|
||||
};
|
||||
Projection projection = Projection::PROJECTION_PERSPECTIVE;
|
||||
real_t fov = 0.0;
|
||||
real_t size = 0.0;
|
||||
real_t z_near = 0.0;
|
||||
real_t z_far = 0.0;
|
||||
RID rid;
|
||||
|
||||
operator bool() const {
|
||||
return rid != RID();
|
||||
}
|
||||
} camera_3d_override;
|
||||
|
||||
friend class Camera3D;
|
||||
Camera3D *camera_3d = nullptr;
|
||||
#if DEBUG_ENABLED
|
||||
CameraOverride<Camera3D> camera_3d_override;
|
||||
#endif // DEBUG_ENABLED
|
||||
HashSet<Camera3D *> camera_3d_set;
|
||||
void _camera_3d_transform_changed_notify();
|
||||
void _camera_3d_set(Camera3D *p_camera);
|
||||
@@ -825,19 +828,13 @@ public:
|
||||
bool is_audio_listener_3d() const;
|
||||
|
||||
Camera3D *get_camera_3d() const;
|
||||
|
||||
#if DEBUG_ENABLED
|
||||
void enable_camera_3d_override(bool p_enable);
|
||||
bool is_camera_3d_override_enabled() const;
|
||||
|
||||
void set_camera_3d_override_transform(const Transform3D &p_transform);
|
||||
Transform3D get_camera_3d_override_transform() const;
|
||||
|
||||
void set_camera_3d_override_perspective(real_t p_fovy_degrees, real_t p_z_near, real_t p_z_far);
|
||||
void set_camera_3d_override_orthogonal(real_t p_size, real_t p_z_near, real_t p_z_far);
|
||||
HashMap<StringName, real_t> get_camera_3d_override_properties() const;
|
||||
|
||||
Vector3 camera_3d_override_project_ray_normal(const Point2 &p_pos) const;
|
||||
Vector3 camera_3d_override_project_ray_origin(const Point2 &p_pos) const;
|
||||
Vector3 camera_3d_override_project_local_ray_normal(const Point2 &p_pos) const;
|
||||
Camera3D *get_overridden_camera_3d() const;
|
||||
Camera3D *get_override_camera_3d() const;
|
||||
#endif // DEBUG_ENABLED
|
||||
|
||||
void set_disable_3d(bool p_disable);
|
||||
bool is_3d_disabled() const;
|
||||
|
||||
Reference in New Issue
Block a user