Improve "Snap Object to Floor" functionality

- Display an error message if no selected nodes could be snapped
- Only register an undo/redo action if at least one node
  could be snapped
- Increase the maximum snapping height to 20
- Increase the negative snapping limit to 0.2
This commit is contained in:
Hugo Locurcio 2019-08-18 01:42:42 +02:00
parent cc9f2a2d8b
commit 78878fbc97
No known key found for this signature in database
GPG Key ID: 39E8F8BE30B0A49C

View File

@ -5176,7 +5176,7 @@ void SpatialEditor::snap_selected_nodes_to_floor() {
// We add a bit of margin to the from position to avoid it from snapping
// when the spatial is already on a floor and there's another floor under
// it
from = from + Vector3(0.0, 0.1, 0.0);
from = from + Vector3(0.0, 0.2, 0.0);
Dictionary d;
@ -5191,31 +5191,56 @@ void SpatialEditor::snap_selected_nodes_to_floor() {
Array keys = snap_data.keys();
if (keys.size()) {
undo_redo->create_action(TTR("Snap Nodes To Floor"));
// The maximum height an object can travel to be snapped
const float max_snap_height = 20.0;
// Will be set to `true` if at least one node from the selection was sucessfully snapped
bool snapped_to_floor = false;
if (keys.size()) {
// For snapping to be performed, there must be solid geometry under at least one of the selected nodes.
// We need to check this before snapping to register the undo/redo action only if needed.
for (int i = 0; i < keys.size(); i++) {
Node *node = keys[i];
Spatial *sp = Object::cast_to<Spatial>(node);
Dictionary d = snap_data[node];
Vector3 from = d["from"];
Vector3 position_offset = d["position_offset"];
Vector3 to = from - Vector3(0.0, 10.0, 0.0);
Vector3 to = from - Vector3(0.0, max_snap_height, 0.0);
Set<RID> excluded = _get_physics_bodies_rid(sp);
if (ss->intersect_ray(from, to, result, excluded)) {
Transform new_transform = sp->get_global_transform();
new_transform.origin.y = result.position.y;
new_transform.origin = new_transform.origin - position_offset;
undo_redo->add_do_method(sp, "set_global_transform", new_transform);
undo_redo->add_undo_method(sp, "set_global_transform", sp->get_global_transform());
snapped_to_floor = true;
}
}
undo_redo->commit_action();
if (snapped_to_floor) {
undo_redo->create_action(TTR("Snap Nodes To Floor"));
// Perform snapping if at least one node can be snapped
for (int i = 0; i < keys.size(); i++) {
Node *node = keys[i];
Spatial *sp = Object::cast_to<Spatial>(node);
Dictionary d = snap_data[node];
Vector3 from = d["from"];
Vector3 to = from - Vector3(0.0, max_snap_height, 0.0);
Set<RID> excluded = _get_physics_bodies_rid(sp);
if (ss->intersect_ray(from, to, result, excluded)) {
Vector3 position_offset = d["position_offset"];
Transform new_transform = sp->get_global_transform();
new_transform.origin.y = result.position.y;
new_transform.origin = new_transform.origin - position_offset;
undo_redo->add_do_method(sp, "set_global_transform", new_transform);
undo_redo->add_undo_method(sp, "set_global_transform", sp->get_global_transform());
}
}
undo_redo->commit_action();
} else {
EditorNode::get_singleton()->show_warning(TTR("Couldn't find a solid floor to snap the selection to."));
}
}
}