@@ -3986,6 +3986,21 @@ void Node3DEditorViewport::_notification(int p_what) {
39863986 }
39873987 }
39883988
3989+ if (active_node->has_meta (" _snap_transform" )) {
3990+ Callable snap_fn = active_node->get_meta (" _snap_transform" );
3991+ Variant snap_result = snap_fn.call (active_node->get_global_transform ());
3992+ if (snap_result.get_type () == Variant::TRANSFORM3D ) {
3993+ Transform3D snapped = snap_result;
3994+ active_node->set_global_transform (snapped);
3995+ for (Node *E : selection) {
3996+ Node3D *sp = Object::cast_to<Node3D>(E);
3997+ if (sp && sp != active_node && relative_transforms.has (sp)) {
3998+ sp->set_global_transform (snapped * relative_transforms[sp]);
3999+ }
4000+ }
4001+ }
4002+ }
4003+
39894004 if (!ruler->is_inside_tree ()) {
39904005 double snap = EDITOR_GET (" interface/inspector/default_float_step" );
39914006 int snap_step_decimals = Math::range_step_decimals (snap);
@@ -4098,6 +4113,14 @@ void Node3DEditorViewport::_notification(int p_what) {
40984113 }
40994114 }
41004115
4116+ if (selected_node->has_meta (" _snap_transform" )) {
4117+ Callable snap_fn = selected_node->get_meta (" _snap_transform" );
4118+ Variant snap_result = snap_fn.call (selected_node->get_global_transform ());
4119+ if (snap_result.get_type () == Variant::TRANSFORM3D ) {
4120+ selected_node->set_global_transform (snap_result);
4121+ }
4122+ }
4123+
41014124 if (!ruler->is_inside_tree ()) {
41024125 double snap = EDITOR_GET (" interface/inspector/default_float_step" );
41034126 int snap_step_decimals = Math::range_step_decimals (snap);
@@ -4133,6 +4156,22 @@ void Node3DEditorViewport::_notification(int p_what) {
41334156 preview_basis.rotate (Vector3 (0 , 1 , 0 ), preview_node_angle);
41344157 Transform3D preview_gl_transform = Transform3D (preview_basis, preview_node_pos);
41354158 preview_node->set_global_transform (preview_gl_transform);
4159+ for (int i = 0 ; i < preview_node->get_child_count (); i++) {
4160+ Node3D *child = Object::cast_to<Node3D>(preview_node->get_child (i));
4161+ if (child && child->has_meta (" _snap_transform" )) {
4162+ Callable snap_fn = child->get_meta (" _snap_transform" );
4163+ Variant snap_result = snap_fn.call (preview_node->get_global_transform ());
4164+ if (snap_result.get_type () == Variant::TRANSFORM3D ) {
4165+ Transform3D snapped = snap_result;
4166+ Basis snap_rot = snapped.basis .orthonormalized ();
4167+ Basis child_local_rot = child->get_transform ().basis .orthonormalized ();
4168+ Basis compensated = snap_rot * child_local_rot.transposed ();
4169+ preview_node->set_global_transform (Transform3D (compensated, snapped.origin ));
4170+ preview_node_pos = snapped.origin ;
4171+ }
4172+ break ;
4173+ }
4174+ }
41364175 if (!preview_node->is_visible ()) {
41374176 preview_node->show ();
41384177 }
@@ -6168,16 +6207,13 @@ bool Node3DEditorViewport::_create_instance(Node *p_parent, const String &p_path
61686207 parent_tf = parent_node3d->get_global_gizmo_transform ();
61696208 }
61706209
6171- Basis preview_rotation;
6172- preview_rotation.rotate (Vector3 (0 , 1 , 0 ), preview_node_angle);
6173-
61746210 Transform3D new_tf = node3d->get_transform ();
61756211 if (node3d->is_set_as_top_level ()) {
61766212 new_tf.origin += preview_node_pos;
6177- new_tf.basis = preview_rotation * new_tf.basis ;
6213+ new_tf.basis = preview_node_basis * new_tf.basis ;
61786214 } else {
61796215 new_tf.origin = parent_tf.affine_inverse ().xform (preview_node_pos + node3d->get_position ());
6180- new_tf.basis = parent_tf.affine_inverse ().basis * preview_rotation * new_tf.basis ;
6216+ new_tf.basis = parent_tf.affine_inverse ().basis * preview_node_basis * new_tf.basis ;
61816217 }
61826218
61836219 undo_redo->add_do_method (instantiated_scene, " set_transform" , new_tf);
@@ -6247,6 +6283,13 @@ void Node3DEditorViewport::_perform_drop_data() {
62476283 return ;
62486284 }
62496285
6286+ if (preview_node && preview_node->is_inside_tree ()) {
6287+ preview_node_basis = preview_node->get_global_transform ().basis ;
6288+ } else {
6289+ preview_node_basis = Basis ();
6290+ preview_node_basis.rotate (Vector3 (0 , 1 , 0 ), preview_node_angle);
6291+ }
6292+
62506293 _remove_preview_node ();
62516294
62526295 PackedStringArray error_files;
0 commit comments