Make 3D selection box independent of object size

This commit is contained in:
Haoyu Qiu 2021-08-09 22:51:26 +08:00
parent a418d09617
commit 9d9043e1a9
2 changed files with 36 additions and 18 deletions

View file

@ -2410,15 +2410,28 @@ void SpatialEditorViewport::_notification(int p_what) {
se->aabb = new_aabb;
t.translate(se->aabb.position);
Transform t_offset = t;
// apply AABB scaling before item's global transform
{
const Vector3 offset(0.005, 0.005, 0.005);
Basis aabb_s;
aabb_s.scale(se->aabb.size);
aabb_s.scale(se->aabb.size + offset);
t.translate(se->aabb.position - offset / 2);
t.basis = t.basis * aabb_s;
}
{
const Vector3 offset(0.01, 0.01, 0.01);
Basis aabb_s;
aabb_s.scale(se->aabb.size + offset);
t_offset.translate(se->aabb.position - offset / 2);
t_offset.basis = t_offset.basis * aabb_s;
}
VisualServer::get_singleton()->instance_set_transform(se->sbox_instance, t);
VisualServer::get_singleton()->instance_set_transform(se->sbox_instance_offset, t_offset);
VisualServer::get_singleton()->instance_set_transform(se->sbox_instance_xray, t);
VisualServer::get_singleton()->instance_set_transform(se->sbox_instance_xray_offset, t_offset);
}
if (changed || (spatial_editor->is_gizmo_visible() && !exist)) {
@ -4292,9 +4305,15 @@ SpatialEditorSelectedItem::~SpatialEditorSelectedItem() {
if (sbox_instance.is_valid()) {
VisualServer::get_singleton()->free(sbox_instance);
}
if (sbox_instance_offset.is_valid()) {
VisualServer::get_singleton()->free(sbox_instance_offset);
}
if (sbox_instance_xray.is_valid()) {
VisualServer::get_singleton()->free(sbox_instance_xray);
}
if (sbox_instance_xray_offset.is_valid()) {
VisualServer::get_singleton()->free(sbox_instance_xray_offset);
}
}
void SpatialEditor::select_gizmo_highlight_axis(int p_axis) {
@ -4425,21 +4444,32 @@ Object *SpatialEditor::_get_editor_data(Object *p_what) {
si->sbox_instance = VisualServer::get_singleton()->instance_create2(
selection_box->get_rid(),
sp->get_world()->get_scenario());
si->sbox_instance_offset = VisualServer::get_singleton()->instance_create2(
selection_box->get_rid(),
sp->get_world()->get_scenario());
VS::get_singleton()->instance_geometry_set_cast_shadows_setting(
si->sbox_instance,
VS::SHADOW_CASTING_SETTING_OFF);
// Use the Edit layer to hide the selection box when View Gizmos is disabled, since it is a bit distracting.
// It's still possible to approximately guess what is selected by looking at the manipulation gizmo position.
VS::get_singleton()->instance_set_layer_mask(si->sbox_instance, 1 << SpatialEditorViewport::GIZMO_EDIT_LAYER);
VS::get_singleton()->instance_set_layer_mask(si->sbox_instance_offset, 1 << SpatialEditorViewport::GIZMO_EDIT_LAYER);
si->sbox_instance_xray = VisualServer::get_singleton()->instance_create2(
selection_box_xray->get_rid(),
sp->get_world()->get_scenario());
si->sbox_instance_xray_offset = VisualServer::get_singleton()->instance_create2(
selection_box_xray->get_rid(),
sp->get_world()->get_scenario());
VS::get_singleton()->instance_geometry_set_cast_shadows_setting(
si->sbox_instance_xray,
VS::SHADOW_CASTING_SETTING_OFF);
VS::get_singleton()->instance_geometry_set_cast_shadows_setting(
si->sbox_instance_xray_offset,
VS::SHADOW_CASTING_SETTING_OFF);
// Use the Edit layer to hide the selection box when View Gizmos is disabled, since it is a bit distracting.
// It's still possible to approximately guess what is selected by looking at the manipulation gizmo position.
VS::get_singleton()->instance_set_layer_mask(si->sbox_instance_xray, 1 << SpatialEditorViewport::GIZMO_EDIT_LAYER);
VS::get_singleton()->instance_set_layer_mask(si->sbox_instance_xray_offset, 1 << SpatialEditorViewport::GIZMO_EDIT_LAYER);
return si;
}
@ -4447,10 +4477,6 @@ Object *SpatialEditor::_get_editor_data(Object *p_what) {
void SpatialEditor::_generate_selection_boxes() {
// Use two AABBs to create the illusion of a slightly thicker line.
AABB aabb(Vector3(), Vector3(1, 1, 1));
AABB aabb_offset(Vector3(), Vector3(1, 1, 1));
// Grow the bounding boxes slightly to avoid Z-fighting with the mesh's edges.
aabb.grow_by(0.005);
aabb_offset.grow_by(0.01);
// Create a x-ray (visible through solid surfaces) and standard version of the selection box.
// Both will be drawn at the same position, but with different opacity.
@ -4470,16 +4496,6 @@ void SpatialEditor::_generate_selection_boxes() {
st_xray->add_vertex(b);
}
for (int i = 0; i < 12; i++) {
Vector3 a, b;
aabb_offset.get_edge(i, a, b);
st->add_vertex(a);
st->add_vertex(b);
st_xray->add_vertex(a);
st_xray->add_vertex(b);
}
Ref<SpatialMaterial> mat = memnew(SpatialMaterial);
mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true);
const Color selection_box_color = EDITOR_GET("editors/3d/selection_box_color");

View file

@ -480,7 +480,9 @@ public:
bool last_xform_dirty;
Spatial *sp;
RID sbox_instance;
RID sbox_instance_offset;
RID sbox_instance_xray;
RID sbox_instance_xray_offset;
SpatialEditorSelectedItem() {
sp = nullptr;