Skip to content

Commit 77aa2f4

Browse files
fixed cpl of bugs in bounds control when accessing visuals when they haven't been created yet
finished migration handler (added folder generation and check, added appbar migration) made app bar use generic target that implements new IBoundsTargetProvider so we can use both boundscontrol and boundingbox with it deprecated boundingbox specific methods in boundingboxhelper / added generic variants of methods
1 parent a92dcae commit 77aa2f4

File tree

8 files changed

+212
-76
lines changed

8 files changed

+212
-76
lines changed

Assets/MixedRealityToolkit.SDK/Experimental/Features/UX/BoundsControl/BoundsControl.cs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ namespace Microsoft.MixedReality.Toolkit.Experimental.UI.BoundsControl
2424
public class BoundsControl : MonoBehaviour,
2525
IMixedRealitySourceStateHandler,
2626
IMixedRealityFocusChangedHandler,
27-
IMixedRealityFocusHandler
27+
IMixedRealityFocusHandler,
28+
IBoundsTargetProvider
2829
{
2930
#region Serialized Fields and Properties
3031
[SerializeField]
@@ -215,7 +216,7 @@ public Vector3 BoxPadding
215216
/// <summary>
216217
/// This section defines the links / lines that are drawn between the corners of the control.
217218
/// </summary>
218-
public LinksConfiguration LinksConfiguration { get => linksConfiguration; set => LinksConfiguration = value; }
219+
public LinksConfiguration LinksConfiguration { get => linksConfiguration; set => linksConfiguration = value; }
219220

220221
[SerializeField]
221222
[Tooltip("Configuration of the scale handles.")]
@@ -430,6 +431,11 @@ public void UnhighlightWires()
430431
/// </summary>
431432
public void CreateRig()
432433
{
434+
if (!IsInitialized())
435+
{
436+
return;
437+
}
438+
433439
DestroyRig();
434440
InitializeRigRoot();
435441
InitializeDataStructures();
@@ -786,7 +792,10 @@ private void UpdateBounds()
786792
}
787793
}
788794

789-
795+
private bool IsInitialized()
796+
{
797+
return scaleHandles != null && rotationHandles != null && boxDisplay != null && links != null && proximityEffect != null;
798+
}
790799

791800
private bool DoesActivationMatchFocus(FocusEventData eventData)
792801
{
@@ -857,6 +866,9 @@ private void DestroyRig()
857866

858867
private void UpdateRigVisibilityInInspector()
859868
{
869+
if (!IsInitialized())
870+
return;
871+
860872
HideFlags desiredFlags = hideElementsInInspector ? HideFlags.HideInHierarchy | HideFlags.HideInInspector : HideFlags.None;
861873
scaleHandles.UpdateVisibilityInInspector(desiredFlags);
862874
links.UpdateVisibilityInInspector(desiredFlags);
@@ -1108,7 +1120,7 @@ private void SetHighlighted(Transform activeHandle)
11081120

11091121
private void ResetVisuals()
11101122
{
1111-
if (currentPointer != null)
1123+
if (currentPointer != null || !IsInitialized())
11121124
{
11131125
return;
11141126
}

Assets/MixedRealityToolkit.SDK/Experimental/Features/UX/BoundsControl/Visuals/Links.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ internal void Flatten(ref int[] flattenedHandles)
134134
internal void CreateLinks(RotationHandles rotationHandles, Transform parent, Vector3 currentBoundsExtents)
135135
{
136136
// create links
137-
if (links != null)
137+
if (links != null && config.ShowWireFrame)
138138
{
139139
GameObject link;
140140
Vector3 linkDimensions = GetLinkDimensions(currentBoundsExtents);

Assets/MixedRealityToolkit.SDK/Experimental/Features/Utilities/Migration/BoundsControlMigrationHandler.cs

Lines changed: 89 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -26,46 +26,58 @@ public void Migrate(GameObject gameObject)
2626
var boundingBox = gameObject.GetComponent<BoundingBox>();
2727
var boundsControl = gameObject.AddComponent<BoundsControl>();
2828

29-
// migrate logic settings
30-
boundsControl.Target = boundingBox.Target;
31-
boundsControl.BoundsOverride = boundingBox.BoundsOverride;
32-
boundsControl.CalculationMethod = MigrateCalculationMethod(boundingBox.CalculationMethod);
33-
boundsControl.BoundsControlActivation = MigrateActivationFlag(boundingBox.BoundingBoxActivation);
34-
35-
// only carry over min max scaling values if user hasn't attached min max scale constraint component yet
36-
if (gameObject.GetComponent<MinMaxScaleConstraint>() == null)
3729
{
38-
MinMaxScaleConstraint scaleConstraint = gameObject.AddComponent<MinMaxScaleConstraint>();
30+
Undo.RecordObject(gameObject, "BoundsControl migration: swapping BoundingBox with BoundsControl.");
31+
32+
// migrate logic settings
33+
boundsControl.Target = boundingBox.Target;
34+
boundsControl.BoundsOverride = boundingBox.BoundsOverride;
35+
boundsControl.CalculationMethod = MigrateCalculationMethod(boundingBox.CalculationMethod);
36+
boundsControl.BoundsControlActivation = MigrateActivationFlag(boundingBox.BoundingBoxActivation);
37+
38+
// only carry over min max scaling values if user hasn't attached min max scale constraint component yet
39+
if (gameObject.GetComponent<MinMaxScaleConstraint>() == null)
40+
{
3941
#pragma warning disable 0618
40-
scaleConstraint.ScaleMinimum = boundingBox.ScaleMinimum;
41-
scaleConstraint.ScaleMaximum = boundingBox.ScaleMaximum;
42+
// create a minmaxscaleconstraint in case there's a min max scale set up
43+
if (boundingBox.ScaleMinimum != 0.0f || boundingBox.ScaleMaximum != 0.0f)
44+
{
45+
MinMaxScaleConstraint scaleConstraint = gameObject.AddComponent<MinMaxScaleConstraint>();
46+
scaleConstraint.ScaleMinimum = boundingBox.ScaleMinimum;
47+
scaleConstraint.ScaleMaximum = boundingBox.ScaleMaximum;
48+
}
4249
#pragma warning restore 0618
50+
}
51+
52+
// migrate visuals
53+
boundsControl.DrawTetherWhenManipulating = boundingBox.DrawTetherWhenManipulating;
54+
boundsControl.HandlesIgnoreCollider = boundingBox.HandlesIgnoreCollider;
55+
boundsControl.FlattenAxis = MigrateFlattenAxis(boundingBox.FlattenAxis);
56+
boundsControl.BoxPadding = boundingBox.BoxPadding;
57+
string configDir = GetBoundsControlConfigDirectory(boundingBox);
58+
MigrateBoxDisplay(boundsControl, boundingBox, configDir);
59+
MigrateLinks(boundsControl, boundingBox, configDir);
60+
MigrateScaleHandles(boundsControl, boundingBox, configDir);
61+
MigrateRotationHandles(boundsControl, boundingBox, configDir);
62+
MigrateProximityEffect(boundsControl, boundingBox, configDir);
63+
64+
// debug properties
65+
boundsControl.DebugText = boundingBox.debugText;
66+
boundsControl.HideElementsInInspector = boundingBox.HideElementsInInspector;
67+
68+
// events
69+
boundsControl.RotateStarted = boundingBox.RotateStarted;
70+
boundsControl.RotateStopped = boundingBox.RotateStopped;
71+
boundsControl.ScaleStarted = boundingBox.ScaleStarted;
72+
boundsControl.ScaleStopped = boundingBox.ScaleStopped;
73+
74+
// destroy obsolete component
75+
Object.DestroyImmediate(boundingBox);
4376
}
4477

45-
// migrate visuals
46-
boundsControl.DrawTetherWhenManipulating = boundingBox.DrawTetherWhenManipulating;
47-
boundsControl.HandlesIgnoreCollider = boundingBox.HandlesIgnoreCollider;
48-
boundsControl.FlattenAxis = MigrateFlattenAxis(boundingBox.FlattenAxis);
49-
boundsControl.BoxPadding = boundingBox.BoxPadding;
50-
string configDir = GetBoundsControlConfigDirectory(boundingBox);
51-
MigrateBoxDisplay(boundsControl, boundingBox, configDir);
52-
MigrateLinks(boundsControl, boundingBox, configDir);
53-
MigrateScaleHandles(boundsControl, boundingBox, configDir);
54-
MigrateRotationHandles(boundsControl, boundingBox, configDir);
55-
MigrateProximityEffect(boundsControl, boundingBox, configDir);
56-
57-
// debug properties
58-
boundsControl.DebugText = boundingBox.debugText;
59-
boundsControl.HideElementsInInspector = boundingBox.HideElementsInInspector;
60-
61-
// events
62-
boundsControl.RotateStarted = boundingBox.RotateStarted;
63-
boundsControl.RotateStopped = boundingBox.RotateStopped;
64-
boundsControl.ScaleStarted = boundingBox.ScaleStarted;
65-
boundsControl.ScaleStopped = boundingBox.ScaleStopped;
66-
67-
// destroy obsolete component
68-
UnityEngine.Object.DestroyImmediate(boundingBox);
78+
// look in the scene for app bars and upgrade them too to point to the new component
79+
MigrateAppBar(boundingBox, boundsControl);
80+
6981
}
7082

7183
private string GetBoundsControlConfigDirectory(BoundingBox boundingBox)
@@ -75,18 +87,30 @@ private string GetBoundsControlConfigDirectory(BoundingBox boundingBox)
7587
if (scene != null)
7688
{
7789
string scenePath = scene.path;
78-
string dirPath = System.IO.Path.GetDirectoryName(scenePath);
79-
string configPath = System.IO.Path.Combine(dirPath, "BoundsControlConfigs/");
80-
return configPath;
90+
string sceneDir = System.IO.Path.GetDirectoryName(scenePath);
91+
92+
const string configDir = "BoundsControlConfigs";
93+
string configPath = System.IO.Path.Combine(sceneDir, configDir);
94+
if (AssetDatabase.IsValidFolder(configPath))
95+
{
96+
return configPath;
97+
}
98+
else
99+
{
100+
string guid = AssetDatabase.CreateFolder(sceneDir, configDir);
101+
return AssetDatabase.GUIDToAssetPath(guid);
102+
}
81103
}
82104

83105
return "";
84106
}
85107
private string GenerateUniqueConfigName(string directory, GameObject migratingFrom, string configName)
86108
{
87-
return directory + migratingFrom.name + migratingFrom.GetInstanceID() + configName + ".asset";
109+
return directory + "/" + migratingFrom.name + migratingFrom.GetInstanceID() + configName + ".asset";
88110
}
89111

112+
#region Flags Migration
113+
90114
private BoundsCalculationMethod MigrateCalculationMethod(BoundingBox.BoundsCalculationMethod calculationMethod)
91115
{
92116
switch (calculationMethod)
@@ -173,9 +197,13 @@ private RotationHandlePrefabCollider MigrateRotationHandleColliderType(BoundingB
173197
return RotationHandlePrefabCollider.Sphere;
174198
}
175199

200+
#endregion Flags Migration
201+
202+
#region Visuals Configuration Migration
203+
176204
private void MigrateBoxDisplay(BoundsControl control, BoundingBox box, string configAssetDirectory)
177205
{
178-
BoxDisplayConfiguration config = new BoxDisplayConfiguration();
206+
BoxDisplayConfiguration config = ScriptableObject.CreateInstance<BoxDisplayConfiguration>();
179207
AssetDatabase.CreateAsset(config, GenerateUniqueConfigName(configAssetDirectory, box.gameObject, "BoxDisplayConfiguration"));
180208

181209
config.BoxMaterial = box.BoxMaterial;
@@ -187,7 +215,7 @@ private void MigrateBoxDisplay(BoundsControl control, BoundingBox box, string co
187215

188216
private void MigrateLinks(BoundsControl control, BoundingBox box, string configAssetDirectory)
189217
{
190-
LinksConfiguration config = new LinksConfiguration();
218+
LinksConfiguration config = ScriptableObject.CreateInstance<LinksConfiguration>();
191219
AssetDatabase.CreateAsset(config, GenerateUniqueConfigName(configAssetDirectory, box.gameObject, "LinksConfiguration"));
192220

193221
config.WireframeMaterial = box.WireframeMaterial;
@@ -201,7 +229,7 @@ private void MigrateLinks(BoundsControl control, BoundingBox box, string configA
201229

202230
private void MigrateScaleHandles(BoundsControl control, BoundingBox box, string configAssetDirectory)
203231
{
204-
ScaleHandlesConfiguration config = new ScaleHandlesConfiguration();
232+
ScaleHandlesConfiguration config = ScriptableObject.CreateInstance<ScaleHandlesConfiguration>();
205233
AssetDatabase.CreateAsset(config, GenerateUniqueConfigName(configAssetDirectory, box.gameObject, "ScaleHandlesConfiguration"));
206234

207235
config.HandleSlatePrefab = box.ScaleHandleSlatePrefab;
@@ -217,7 +245,7 @@ private void MigrateScaleHandles(BoundsControl control, BoundingBox box, string
217245

218246
private void MigrateRotationHandles(BoundsControl control, BoundingBox box, string configAssetDirectory)
219247
{
220-
RotationHandlesConfiguration config = new RotationHandlesConfiguration();
248+
RotationHandlesConfiguration config = ScriptableObject.CreateInstance<RotationHandlesConfiguration>();
221249
AssetDatabase.CreateAsset(config, GenerateUniqueConfigName(configAssetDirectory, box.gameObject, "RotationHandlesConfiguration"));
222250

223251
config.RotationHandlePrefabColliderType = MigrateRotationHandleColliderType(box.RotationHandlePrefabColliderType);
@@ -235,7 +263,7 @@ private void MigrateRotationHandles(BoundsControl control, BoundingBox box, stri
235263

236264
private void MigrateProximityEffect(BoundsControl control, BoundingBox box, string configAssetDirectory)
237265
{
238-
ProximityEffectConfiguration config = new ProximityEffectConfiguration();
266+
ProximityEffectConfiguration config = ScriptableObject.CreateInstance<ProximityEffectConfiguration>();
239267
AssetDatabase.CreateAsset(config, GenerateUniqueConfigName(configAssetDirectory, box.gameObject, "ProximityEffectConfiguration"));
240268

241269
config.ProximityEffectActive = box.ProximityEffectActive;
@@ -250,5 +278,22 @@ private void MigrateProximityEffect(BoundsControl control, BoundingBox box, stri
250278

251279
control.HandleProximityEffectConfiguration = config;
252280
}
281+
282+
#endregion Visuals Configuration Migration
283+
private void MigrateAppBar(BoundingBox boundingBox, BoundsControl boundsControl)
284+
{
285+
// note: this might be expensive for larger scenes but we don't know where the appbar is
286+
// placed in the hierarchy so we have to search the scene for it
287+
AppBar[] appBars = Object.FindObjectsOfType<AppBar>();
288+
for (int i = 0; i < appBars.Length; ++i)
289+
{
290+
AppBar appBar = appBars[i];
291+
if (appBar.BoundingBox == boundingBox)
292+
{
293+
Undo.RecordObject(appBar, "BoundsControl migration: changed target of app bar.");
294+
appBar.BoundingBox = boundsControl;
295+
}
296+
}
297+
}
253298
}
254299
}

Assets/MixedRealityToolkit.SDK/Features/UX/Scripts/AppBar/AppBar.cs

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,12 @@ public bool UseHide
111111

112112
[Header("Target Bounding Box")]
113113
[SerializeField]
114-
private BoundingBox boundingBox = null;
114+
[Tooltip("Object the app bar is controlling - This object must implement the IBoundsTargetProvider.")]
115+
private MonoBehaviour boundingBox = null;
116+
/// <summary>
117+
/// Object the app bar is controlling - This object must implement the IBoundsTargetProvider.
118+
/// </summary>
119+
public MonoBehaviour BoundingBox { get => boundingBox; set => boundingBox = value; }
115120

116121
[SerializeField]
117122
private GameObject baseRenderer = null;
@@ -200,7 +205,7 @@ private void LateUpdate()
200205
public void Reset()
201206
{
202207
state = AppBarStateEnum.Default;
203-
FollowBoundingBox(false);
208+
FollowTargetObject(false);
204209
lastTimeTapped = Time.time + coolDownTime;
205210
}
206211

@@ -241,8 +246,12 @@ public void OnButtonPressed(AppBarButton button)
241246
protected virtual void OnClickRemove()
242247
{
243248
// Set the app bar and bounding box to inactive
244-
boundingBox.Target.SetActive(false);
245-
boundingBox.gameObject.SetActive(false);
249+
var boundsProvider = BoundingBox as IBoundsTargetProvider;
250+
if (boundsProvider != null)
251+
{
252+
boundsProvider.Target.SetActive(false);
253+
}
254+
BoundingBox.gameObject.SetActive(false);
246255
gameObject.SetActive(false);
247256
}
248257

@@ -275,8 +284,8 @@ private void InitializeButtons()
275284
private void UpdateAppBar()
276285
{
277286
UpdateButtons();
278-
UpdateBoundingBox();
279-
FollowBoundingBox(true);
287+
UpdateTargetObject();
288+
FollowTargetObject(true);
280289
}
281290

282291
private void UpdateButtons()
@@ -331,9 +340,10 @@ private void UpdateButtons()
331340
backgroundBar.transform.localPosition = Vector3.forward * buttonDepth / 2;
332341
}
333342

334-
private void UpdateBoundingBox()
343+
private void UpdateTargetObject()
335344
{
336-
if (boundingBox == null || boundingBox.Target == null)
345+
var boundsProvider = BoundingBox as IBoundsTargetProvider;
346+
if (boundsProvider == null || boundsProvider.Target == null)
337347
{
338348
if (displayType == AppBarDisplayTypeEnum.Manipulation)
339349
{
@@ -347,36 +357,37 @@ private void UpdateBoundingBox()
347357
return;
348358
}
349359

350-
// BoundingBox can't update in editor mode
360+
// Target can't be updated in editor mode
351361
if (!Application.isPlaying)
352362
return;
353363

354-
if (boundingBox == null)
364+
if (boundsProvider == null)
355365
return;
356366

357367
switch (state)
358368
{
359369
case AppBarStateEnum.Manipulation:
360-
boundingBox.Active = true;
370+
boundsProvider.Active = true;
361371
break;
362372

363373
default:
364-
boundingBox.Active = false;
374+
boundsProvider.Active = false;
365375
break;
366376
}
367377
}
368378

369-
private void FollowBoundingBox(bool smooth)
379+
private void FollowTargetObject(bool smooth)
370380
{
371-
if (boundingBox == null)
381+
var boundsProvider = BoundingBox as IBoundsTargetProvider;
382+
if (boundsProvider == null)
372383
return;
373384

374385
//calculate best follow position for AppBar
375386
Vector3 finalPosition = Vector3.zero;
376387
Vector3 headPosition = CameraCache.Main.transform.position;
377388
boundsPoints.Clear();
378389

379-
helper.UpdateNonAABoundingBoxCornerPositions(boundingBox, boundsPoints);
390+
helper.UpdateNonAABoundsCornerPositions(boundsProvider.TargetBounds, boundsPoints);
380391
int followingFaceIndex = helper.GetIndexOfForwardFace(headPosition);
381392
Vector3 faceNormal = helper.GetFaceNormal(followingFaceIndex);
382393

@@ -387,7 +398,7 @@ private void FollowBoundingBox(bool smooth)
387398
transform.position = smooth ? Vector3.Lerp(transform.position, finalPosition, Time.deltaTime * backgroundBarMoveSpeed) : finalPosition;
388399

389400
// Rotate on the y axis
390-
Vector3 direction = (boundingBox.TargetBounds.bounds.center - finalPosition).normalized;
401+
Vector3 direction = (boundsProvider.TargetBounds.bounds.center - finalPosition).normalized;
391402
if (direction != Vector3.zero)
392403
{
393404
Vector3 eulerAngles = Quaternion.LookRotation(direction, Vector3.up).eulerAngles;

0 commit comments

Comments
 (0)