Skip to content

Commit c2e8c78

Browse files
committed
Fixes scale handle flattening alignment and resolves long-standing bug with FlattenAuto
1 parent 7a6a9c2 commit c2e8c78

File tree

2 files changed

+67
-28
lines changed

2 files changed

+67
-28
lines changed

Assets/MRTK/SDK/Features/UX/Scripts/BoundsControl/BoundsControl.cs

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,21 @@ public ElasticsManager ElasticsManager
564564
private Vector3[] boundsCorners = new Vector3[8];
565565
public Vector3[] BoundsCorners { get; private set; }
566566

567+
// Current actual flattening axis, derived from FlattenAuto, if set
568+
private FlattenModeType actualFlattenAxis {
569+
get
570+
{
571+
if(FlattenAxis == FlattenModeType.FlattenAuto)
572+
{
573+
return VisualUtils.DetermineAxisToFlatten(TargetBounds.bounds.extents);
574+
}
575+
else
576+
{
577+
return FlattenAxis;
578+
}
579+
}
580+
}
581+
567582
#endregion
568583

569584
#region public Properties
@@ -721,8 +736,8 @@ private static T EnsureScriptable<T>(T instance) where T : ScriptableObject
721736

722737
private void OnEnable()
723738
{
724-
SetActivationFlags();
725739
CreateRig();
740+
SetActivationFlags();
726741
CaptureInitialState();
727742
}
728743

@@ -1235,16 +1250,15 @@ private void TransformTarget(HandleType transformType)
12351250
// If non-uniform scaling or uniform scaling only on the non-flattened axes
12361251
if (ScaleHandlesConfig.ScaleBehavior != HandleScaleMode.Uniform || !UniformScaleOnFlattenedAxis)
12371252
{
1238-
FlattenModeType determinedType = FlattenAxis == FlattenModeType.FlattenAuto ? VisualUtils.DetermineAxisToFlatten(TargetBounds.bounds.extents) : FlattenAxis;
1239-
if (determinedType == FlattenModeType.FlattenX)
1253+
if (actualFlattenAxis == FlattenModeType.FlattenX)
12401254
{
12411255
scaleFactor.x = 1;
12421256
}
1243-
if (determinedType == FlattenModeType.FlattenY)
1257+
if (actualFlattenAxis == FlattenModeType.FlattenY)
12441258
{
12451259
scaleFactor.y = 1;
12461260
}
1247-
if (determinedType == FlattenModeType.FlattenZ)
1261+
if (actualFlattenAxis == FlattenModeType.FlattenZ)
12481262
{
12491263
scaleFactor.z = 1;
12501264
}
@@ -1476,14 +1490,14 @@ private void ResetVisuals()
14761490
}
14771491

14781492
boxDisplay.Reset(active);
1479-
boxDisplay.UpdateFlattenAxis(flattenAxis);
1493+
boxDisplay.UpdateFlattenAxis(actualFlattenAxis);
14801494

14811495
bool isVisible = (active == true && wireframeOnly == false);
14821496

1483-
rotationHandles.Reset(isVisible, flattenAxis);
1484-
links.Reset(active, flattenAxis);
1485-
scaleHandles.Reset(isVisible, flattenAxis);
1486-
translationHandles.Reset(isVisible, flattenAxis);
1497+
rotationHandles.Reset(isVisible, actualFlattenAxis);
1498+
links.Reset(active, actualFlattenAxis);
1499+
scaleHandles.Reset(isVisible, actualFlattenAxis);
1500+
translationHandles.Reset(isVisible, actualFlattenAxis);
14871501
}
14881502

14891503
private void CreateVisuals()
@@ -1543,7 +1557,7 @@ private void UpdateVisuals()
15431557
translationHandles.CalculateHandlePositions(ref boundsCorners);
15441558
scaleHandles.CalculateHandlePositions(ref boundsCorners);
15451559

1546-
boxDisplay.UpdateDisplay(currentBoundsExtents, flattenAxis);
1560+
boxDisplay.UpdateDisplay(currentBoundsExtents, actualFlattenAxis);
15471561

15481562
// move rig into position and rotation
15491563
rigRoot.position = TargetBounds.bounds.center;

Assets/MRTK/SDK/Features/UX/Scripts/BoundsControl/Visuals/ScaleHandles.cs

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public class ScaleHandles : HandlesBase
1616
protected override HandlesBaseConfiguration BaseConfig => config;
1717
private ScaleHandlesConfiguration config;
1818
private bool areHandlesFlattened = false;
19+
private FlattenModeType currentFlattenAxis = FlattenModeType.DoNotFlatten;
1920

2021
/// <summary>
2122
/// Cached handle positions - we keep track of handle positions in this array
@@ -171,16 +172,9 @@ private Bounds CreateVisual(int handleIndex, GameObject parent, bool isFlattened
171172
handleVisual.transform.localPosition = Vector3.zero;
172173
handleVisual.transform.localRotation = Quaternion.identity;
173174

174-
if (isFlattened)
175-
{
176-
// Rotate 2D slate handle asset for proper orientation
177-
parent.transform.Rotate(0, 0, -90);
178-
}
179-
else
180-
{
181-
Quaternion realignment = GetRotationRealignment(handleIndex);
182-
parent.transform.localRotation = realignment;
183-
}
175+
176+
Quaternion realignment = GetRotationRealignment(handleIndex, isFlattened);
177+
parent.transform.localRotation = realignment;
184178

185179
if(config.HandleMaterial != null)
186180
{
@@ -190,7 +184,7 @@ private Bounds CreateVisual(int handleIndex, GameObject parent, bool isFlattened
190184
return handleVisualBounds;
191185
}
192186

193-
protected Quaternion GetRotationRealignment(int handleIndex)
187+
protected Quaternion GetRotationRealignment(int handleIndex, bool isFlattened)
194188
{
195189
// Helper lambda to sign a vector.
196190
Vector3 signVector(Vector3 i) => new Vector3(Mathf.Sign(i.x), Mathf.Sign(i.y), Mathf.Sign(i.z));
@@ -200,21 +194,52 @@ protected Quaternion GetRotationRealignment(int handleIndex)
200194
Vector3 neutralHandle = signVector(HandlePositions[6]);
201195
Vector3 handlePos = signVector(HandlePositions[handleIndex]);
202196

203-
// Flip the handle if it's on the underside of the bounds.
204-
Quaternion flip = Quaternion.Euler(0, 0, handlePos.y > 0 ? 0 : 90);
197+
if(isFlattened)
198+
{
199+
Vector3 axis = Vector3.forward;
200+
switch(currentFlattenAxis)
201+
{
202+
case FlattenModeType.FlattenAuto:
203+
Debug.LogError("ScaleHandles should never receive FlattenAuto. BoundsControl should pass actualFlattenAxis");
204+
break;
205+
case FlattenModeType.FlattenX:
206+
axis = Vector3.right;
207+
break;
208+
case FlattenModeType.FlattenY:
209+
axis = -Vector3.up;
210+
break;
211+
case FlattenModeType.FlattenZ:
212+
axis = Vector3.forward;
213+
break;
214+
}
215+
216+
Vector3 neutralProjected = Vector3.ProjectOnPlane(neutralHandle, axis);
217+
Vector3 handleProjected = Vector3.ProjectOnPlane(handlePos, axis);
205218

206-
float angleAroundVertical = Vector3.SignedAngle(new Vector3(neutralHandle.x, 0, neutralHandle.z),
207-
new Vector3(handlePos.x, 0, handlePos.z),
208-
Vector3.up);
219+
float angleAroundAxis = Vector3.SignedAngle(neutralProjected,
220+
handleProjected,
221+
axis);
209222

210-
return Quaternion.Euler(0, angleAroundVertical, 0) * flip;
223+
return Quaternion.AngleAxis(angleAroundAxis, axis) * Quaternion.LookRotation(axis, Vector3.up);
224+
}
225+
else
226+
{
227+
// Flip the handle if it's on the underside of the bounds.
228+
Quaternion flip = Quaternion.Euler(0, 0, handlePos.y > 0 ? 0 : 90);
229+
230+
float angleAroundVertical = Vector3.SignedAngle(new Vector3(neutralHandle.x, 0, neutralHandle.z),
231+
new Vector3(handlePos.x, 0, handlePos.z),
232+
Vector3.up);
233+
return Quaternion.Euler(0, angleAroundVertical, 0) * flip;
234+
}
211235
}
212236

213237
internal void Reset(bool areHandlesActive, FlattenModeType flattenAxis)
214238
{
215239
IsActive = areHandlesActive;
216240
ResetHandles();
217241
bool isFlattened = flattenAxis != FlattenModeType.DoNotFlatten;
242+
currentFlattenAxis = flattenAxis;
218243
if (areHandlesFlattened != isFlattened)
219244
{
220245
areHandlesFlattened = isFlattened;

0 commit comments

Comments
 (0)