Improve dragging scene into 3D viewport
* When there's nothing to collide with: * Place the new scene on XZ plane when possible. * When the camera does not point toward the XZ plane or the intersection is too far away, place the new scene on a plane that is in front of the camera and parallel to the frame. * Fixes positioning when in orthogonal view. * Place on physical collision point or the XZ plane when possible. * Otherwise, place it on the plane in front of the camera as if the camera was perspective. * Makes use of snap settings when placing the new scene.
This commit is contained in:
parent
11e1bac768
commit
877cb1cbc0
@ -2664,7 +2664,7 @@ void Node3DEditorViewport::_notification(int p_what) {
|
||||
return;
|
||||
}
|
||||
if (preview_node->is_inside_tree()) {
|
||||
preview_node_pos = _get_instance_position(preview_node_viewport_pos);
|
||||
preview_node_pos = spatial_editor->snap_point(_get_instance_position(preview_node_viewport_pos));
|
||||
Transform3D preview_gl_transform = Transform3D(Basis(), preview_node_pos);
|
||||
preview_node->set_global_transform(preview_gl_transform);
|
||||
if (!preview_node->is_visible()) {
|
||||
@ -3748,24 +3748,45 @@ void Node3DEditorViewport::assign_pending_data_pointers(Node3D *p_preview_node,
|
||||
|
||||
Vector3 Node3DEditorViewport::_get_instance_position(const Point2 &p_pos) const {
|
||||
const float MAX_DISTANCE = 50.0;
|
||||
const float FALLBACK_DISTANCE = 5.0;
|
||||
|
||||
Vector3 world_ray = _get_ray(p_pos);
|
||||
Vector3 world_pos = _get_ray_pos(p_pos);
|
||||
|
||||
Vector3 point = world_pos + world_ray * MAX_DISTANCE;
|
||||
|
||||
PhysicsDirectSpaceState3D *ss = get_tree()->get_root()->get_world_3d()->get_direct_space_state();
|
||||
|
||||
PhysicsDirectSpaceState3D::RayParameters ray_params;
|
||||
ray_params.from = world_pos;
|
||||
ray_params.to = world_pos + world_ray * MAX_DISTANCE;
|
||||
ray_params.to = world_pos + world_ray * camera->get_far();
|
||||
|
||||
PhysicsDirectSpaceState3D::RayResult result;
|
||||
if (ss->intersect_ray(ray_params, result)) {
|
||||
point = result.position;
|
||||
return result.position;
|
||||
}
|
||||
|
||||
return point;
|
||||
const bool is_orthogonal = camera->get_projection() == Camera3D::PROJECTION_ORTHOGONAL;
|
||||
|
||||
// The XZ plane.
|
||||
Vector3 intersection;
|
||||
Plane plane(Vector3(0, 1, 0));
|
||||
if (plane.intersects_ray(world_pos, world_ray, &intersection)) {
|
||||
if (is_orthogonal || world_pos.distance_to(intersection) <= MAX_DISTANCE) {
|
||||
return intersection;
|
||||
}
|
||||
}
|
||||
|
||||
// Plane facing the camera using fallback distance.
|
||||
if (is_orthogonal) {
|
||||
plane = Plane(world_ray, cursor.pos - world_ray * (cursor.distance - FALLBACK_DISTANCE));
|
||||
} else {
|
||||
plane = Plane(world_ray, world_pos + world_ray * FALLBACK_DISTANCE);
|
||||
}
|
||||
if (plane.intersects_ray(world_pos, world_ray, &intersection)) {
|
||||
return intersection;
|
||||
}
|
||||
|
||||
// Not likely, but just in case...
|
||||
return world_pos + world_ray * FALLBACK_DISTANCE;
|
||||
}
|
||||
|
||||
AABB Node3DEditorViewport::_calculate_spatial_bounds(const Node3D *p_parent, bool p_exclude_top_level_transform) {
|
||||
@ -4045,7 +4066,7 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po
|
||||
gl_transform = parent_node3d->get_global_gizmo_transform();
|
||||
}
|
||||
|
||||
gl_transform.origin = spatial_editor->snap_point(preview_node_pos);
|
||||
gl_transform.origin = preview_node_pos;
|
||||
gl_transform.basis *= node3d->get_transform().basis;
|
||||
|
||||
editor_data->get_undo_redo()->add_do_method(instantiated_scene, "set_global_transform", gl_transform);
|
||||
|
Loading…
Reference in New Issue
Block a user