Make Camera3D gizmo the same aspect ratio as its viewport
This commit is contained in:
parent
245e6454a0
commit
6c5dc78f59
4 changed files with 64 additions and 20 deletions
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "node_3d_editor_gizmos.h"
|
||||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "core/math/convex_hull.h"
|
||||
#include "core/math/geometry_2d.h"
|
||||
#include "core/math/geometry_3d.h"
|
||||
|
@ -1732,6 +1733,24 @@ Camera3DGizmoPlugin::Camera3DGizmoPlugin() {
|
|||
create_handle_material("handles");
|
||||
}
|
||||
|
||||
Size2i Camera3DGizmoPlugin::_get_viewport_size(Camera3D *p_camera) {
|
||||
Viewport *viewport = p_camera->get_viewport();
|
||||
|
||||
Window *window = Object::cast_to<Window>(viewport);
|
||||
if (window) {
|
||||
return window->get_size();
|
||||
}
|
||||
|
||||
SubViewport *sub_viewport = Object::cast_to<SubViewport>(viewport);
|
||||
ERR_FAIL_NULL_V(sub_viewport, Size2i());
|
||||
|
||||
if (sub_viewport == EditorNode::get_singleton()->get_scene_root()) {
|
||||
return Size2(GLOBAL_GET("display/window/size/viewport_width"), GLOBAL_GET("display/window/size/viewport_height"));
|
||||
}
|
||||
|
||||
return sub_viewport->get_size();
|
||||
}
|
||||
|
||||
bool Camera3DGizmoPlugin::has_gizmo(Node3D *p_spatial) {
|
||||
return Object::cast_to<Camera3D>(p_spatial) != nullptr;
|
||||
}
|
||||
|
@ -1830,6 +1849,10 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
|
|||
|
||||
Ref<Material> material = get_material("camera_material", p_gizmo);
|
||||
|
||||
const Size2i viewport_size = _get_viewport_size(camera);
|
||||
const real_t viewport_aspect = viewport_size.x > 0 && viewport_size.y > 0 ? viewport_size.aspect() : 1.0;
|
||||
const Size2 size_factor = viewport_aspect > 1.0 ? Size2(1.0, 1.0 / viewport_aspect) : Size2(viewport_aspect, 1.0);
|
||||
|
||||
#define ADD_TRIANGLE(m_a, m_b, m_c) \
|
||||
{ \
|
||||
lines.push_back(m_a); \
|
||||
|
@ -1857,10 +1880,11 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
|
|||
// The real FOV is halved for accurate representation
|
||||
float fov = camera->get_fov() / 2.0;
|
||||
|
||||
Vector3 side = Vector3(Math::sin(Math::deg_to_rad(fov)), 0, -Math::cos(Math::deg_to_rad(fov)));
|
||||
Vector3 nside = side;
|
||||
nside.x = -nside.x;
|
||||
Vector3 up = Vector3(0, side.x, 0);
|
||||
const float hsize = Math::sin(Math::deg_to_rad(fov));
|
||||
const float depth = -Math::cos(Math::deg_to_rad(fov));
|
||||
Vector3 side = Vector3(hsize * size_factor.x, 0, depth);
|
||||
Vector3 nside = Vector3(-side.x, side.y, side.z);
|
||||
Vector3 up = Vector3(0, hsize * size_factor.y, 0);
|
||||
|
||||
ADD_TRIANGLE(Vector3(), side + up, side - up);
|
||||
ADD_TRIANGLE(Vector3(), nside + up, nside - up);
|
||||
|
@ -1868,18 +1892,18 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
|
|||
ADD_TRIANGLE(Vector3(), side - up, nside - up);
|
||||
|
||||
handles.push_back(side);
|
||||
side.x *= 0.25;
|
||||
nside.x *= 0.25;
|
||||
Vector3 tup(0, up.y * 3 / 2, side.z);
|
||||
side.x = MIN(side.x, hsize * 0.25);
|
||||
nside.x = -side.x;
|
||||
Vector3 tup(0, up.y + hsize / 2, side.z);
|
||||
ADD_TRIANGLE(tup, side + up, nside + up);
|
||||
|
||||
} break;
|
||||
|
||||
case Camera3D::PROJECTION_ORTHOGONAL: {
|
||||
float size = camera->get_size();
|
||||
|
||||
float hsize = size * 0.5;
|
||||
Vector3 right(hsize, 0, 0);
|
||||
Vector3 up(0, hsize, 0);
|
||||
Vector3 right(hsize * size_factor.x, 0, 0);
|
||||
Vector3 up(0, hsize * size_factor.y, 0);
|
||||
Vector3 back(0, 0, -1.0);
|
||||
Vector3 front(0, 0, 0);
|
||||
|
||||
|
@ -1890,18 +1914,19 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
|
|||
|
||||
handles.push_back(right + back);
|
||||
|
||||
right.x *= 0.25;
|
||||
Vector3 tup(0, up.y * 3 / 2, back.z);
|
||||
right.x = MIN(right.x, hsize * 0.25);
|
||||
Vector3 tup(0, up.y + hsize / 2, back.z);
|
||||
ADD_TRIANGLE(tup, right + up + back, -right + up + back);
|
||||
|
||||
} break;
|
||||
|
||||
case Camera3D::PROJECTION_FRUSTUM: {
|
||||
float hsize = camera->get_size() / 2.0;
|
||||
|
||||
Vector3 side = Vector3(hsize, 0, -camera->get_near()).normalized();
|
||||
Vector3 nside = side;
|
||||
nside.x = -nside.x;
|
||||
Vector3 up = Vector3(0, side.x, 0);
|
||||
side.x *= size_factor.x;
|
||||
Vector3 nside = Vector3(-side.x, side.y, side.z);
|
||||
Vector3 up = Vector3(0, hsize * size_factor.y, 0);
|
||||
Vector3 offset = Vector3(camera->get_frustum_offset().x, camera->get_frustum_offset().y, 0.0);
|
||||
|
||||
ADD_TRIANGLE(Vector3(), side + up + offset, side - up + offset);
|
||||
|
@ -1909,11 +1934,11 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
|
|||
ADD_TRIANGLE(Vector3(), side + up + offset, nside + up + offset);
|
||||
ADD_TRIANGLE(Vector3(), side - up + offset, nside - up + offset);
|
||||
|
||||
side.x *= 0.25;
|
||||
nside.x *= 0.25;
|
||||
Vector3 tup(0, up.y * 3 / 2, side.z);
|
||||
side.x = MIN(side.x, hsize * 0.25);
|
||||
nside.x = -side.x;
|
||||
Vector3 tup(0, up.y + hsize / 2, side.z);
|
||||
ADD_TRIANGLE(tup + offset, side + up + offset, nside + up + offset);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
#undef ADD_TRIANGLE
|
||||
|
@ -1921,7 +1946,10 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
|
|||
|
||||
p_gizmo->add_lines(lines, material);
|
||||
p_gizmo->add_collision_segments(lines);
|
||||
p_gizmo->add_handles(handles, get_material("handles"));
|
||||
|
||||
if (!handles.is_empty()) {
|
||||
p_gizmo->add_handles(handles, get_material("handles"));
|
||||
}
|
||||
}
|
||||
|
||||
//////
|
||||
|
|
|
@ -264,6 +264,9 @@ public:
|
|||
class Camera3DGizmoPlugin : public EditorNode3DGizmoPlugin {
|
||||
GDCLASS(Camera3DGizmoPlugin, EditorNode3DGizmoPlugin);
|
||||
|
||||
private:
|
||||
static Size2i _get_viewport_size(Camera3D *p_camera);
|
||||
|
||||
public:
|
||||
bool has_gizmo(Node3D *p_spatial) override;
|
||||
String get_gizmo_name() const override;
|
||||
|
|
|
@ -7248,6 +7248,8 @@ void Node3DEditor::_notification(int p_what) {
|
|||
|
||||
sun_state->set_custom_minimum_size(sun_vb->get_combined_minimum_size());
|
||||
environ_state->set_custom_minimum_size(environ_vb->get_combined_minimum_size());
|
||||
|
||||
EditorNode::get_singleton()->connect("project_settings_changed", callable_mp(this, &Node3DEditor::update_all_gizmos).bind(Variant()));
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
|
|
|
@ -112,6 +112,12 @@ void Camera3D::_notification(int p_what) {
|
|||
if (current || first_camera) {
|
||||
viewport->_camera_3d_set(this);
|
||||
}
|
||||
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
viewport->connect(SNAME("size_changed"), callable_mp((Node3D *)this, &Camera3D::update_gizmos));
|
||||
}
|
||||
#endif
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_TRANSFORM_CHANGED: {
|
||||
|
@ -133,6 +139,11 @@ void Camera3D::_notification(int p_what) {
|
|||
}
|
||||
|
||||
if (viewport) {
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (Engine::get_singleton()->is_editor_hint()) {
|
||||
viewport->disconnect(SNAME("size_changed"), callable_mp((Node3D *)this, &Camera3D::update_gizmos));
|
||||
}
|
||||
#endif
|
||||
viewport->_camera_3d_remove(this);
|
||||
viewport = nullptr;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue