35 [Tooltip(
"Show/Hide the Board Gizmo in the Editor.")]
38 [Tooltip(
"Show/Hide the Unit Grid on the Board Gizmo in the Editor.")]
41 public float GridHeightOffset = 0f;
42 public bool StickyHeightOffset =
true;
48 [Tooltip(
"Sets the Alpha transparency of the Board Gizmo in the Editor.")]
56 [Obsolete(
"Please use Gameboard.TryGetGameboardType() instead.",
true)]
59 #endregion Public Fields
62 #region Private Fields
69 private TableTopGizmo boardGizmo =
new TableTopGizmo();
74 private float gridOffsetY => StickyHeightOffset ? Mathf.RoundToInt(GridHeightOffset) : GridHeightOffset;
79 private LengthUnit currentContentScaleUnit;
84 private float currentContentScaleRatio;
89 private Vector3 currentScale;
91 private const float MIN_SCALE = 0.00001f;
95 private static Dictionary<PlayerIndex, GameboardType> playerGameboards =
new Dictionary<PlayerIndex, GameboardType>();
96 private static Dictionary<GlassesHandle, PrimaryGameboardCore> gameboardCores
97 =
new Dictionary<GlassesHandle, PrimaryGameboardCore>();
99 private static HashSet<PrimaryGameboardCore> lostGameboards =
new HashSet<PrimaryGameboardCore>();
100 private static HashSet<GlassesHandle> incomingGlassesHandles =
new HashSet<GlassesHandle>();
101 private static HashSet<GlassesHandle> lostGlassesHandles =
new HashSet<GlassesHandle>();
103 private const UInt16 MAX_SUPPORTED_GAMEBOARD_POSES = 1;
104 #endregion Private Fields
150 #endregion Public Enums
153 #region Public Structs
155 [Obsolete(
"GameboardDimensions is obsolete, please use GameboardExtents instead.",
true)]
156 public struct GameboardDimensions
158 public Length playableSpaceX;
159 public Length playableSpaceY;
160 public Length borderWidth;
161 public Length totalSpaceX => playableSpaceX + (borderWidth * 2);
162 public Length totalSpaceY => playableSpaceY + (borderWidth * 2);
167 playableSpaceX = gameboardExtents.ViewableSpanX;
168 playableSpaceY = gameboardExtents.ViewableSpanZ;
176 public struct GameboardExtents
225 internal const float BORDER_WIDTH_IN_METERS = 0.05f;
230 static GameboardExtents()
233 GAMEBOARD_SIZE_XE =
new T5_GameboardSize(0.35f, 0.35f, 0.61667f, 0.35f, 0.0f);
234 GAMEBOARD_SIZE_XE_RAISED =
new T5_GameboardSize(0.35f, 0.35f, 0.55944f, 0.35f, 0.20944f);
257 return Vector3.forward * ViewableExtentPositiveZ.ToMeters
260 return Vector3.forward * ViewableExtentPositiveZ.ToMeters
263 return Vector3.back * ViewableExtentNegativeZ.ToMeters
266 return Vector3.back * ViewableExtentNegativeZ.ToMeters
269 throw new System.ArgumentException(
"Cannot get corner positions for invalid Corner enum values.");
284 return Vector3.left * ViewableExtentNegativeX.ToMeters
287 return Vector3.right * ViewableExtentPositiveX.ToMeters
294 throw new System.ArgumentException(
"Cannot get edge center positions for invalid Edge enum values.");
305 [Obsolete(
"GameboardExtents.GetPhysicalCenterPositionInGameboardSpace is deprecated. Please use GameboardExtents.GetGeometricCenterPositionInGameboardSpace instead.")]
323 #endregion Private Structs
326 #region Public Functions
343 if(!
Player.TryGetGlassesHandle(playerIndex, out var glassesHandle)
344 || !playerGameboards.TryGetValue(playerIndex, out var currentGameboardType))
350 gameboardType = currentGameboardType;
360 [Obsolete(
"TryGetGameboardDimensions is obsolete. Please use TryGetGameboardExtents instead.",
true)]
375 result =
NativePlugin.GetGameboardDimensions(gameboardType, ref gameboardSize);
407 result =
NativePlugin.GetGameboardDimensions(gameboardType, ref gameboardSize);
432 out Vector3 positionInWorldSpace, out Quaternion rotationToWorldSpace)
436 positionInWorldSpace = Vector3.zero;
437 rotationToWorldSpace = Quaternion.identity;
441 TransformPose(positionInGameboardSpace, rotationToGameboardSpace, playerSettings.scaleSettings,
442 out positionInWorldSpace, out rotationToWorldSpace);
460 poseInWorldSpace =
new Pose();
464 poseInWorldSpace =
TransformPose(poseInGameboardSpace, playerSettings.scaleSettings);
482 pointInWorldSpace = Vector3.zero;
486 pointInWorldSpace =
TransformPoint(pointInGameboardSpace, playerSettings.scaleSettings);
503 out Vector3 positionInGameboardSpace, out Quaternion rotationToGameboardSpace)
507 positionInGameboardSpace = Vector3.zero;
508 rotationToGameboardSpace = Quaternion.identity;
513 out positionInGameboardSpace, out rotationToGameboardSpace);
531 poseInGameboardSpace =
new Pose();
553 pointInGameboardSpace = Vector3.zero;
563 new public void Awake()
566 currentScale = transform.localScale;
578 boardGizmo.Draw(scaleSettings, gameBoardSettings,
GizmoOpacity, ShowGrid, gridOffsetY);
581 var sceneViewRepaintNecessary = ScaleCompensate(scaleSettings);
582 sceneViewRepaintNecessary |= ContentScaleCompensate(scaleSettings);
584 if(sceneViewRepaintNecessary)
586 boardGizmo.ResetGrid(scaleSettings, gameBoardSettings);
587 UnityEditor.SceneView.lastActiveSceneView.Repaint();
596 public GameboardType GetDisplayedGameboardType(GameBoardSettings gameBoardSettings)
598 return GetDisplayedGameboardType(
PlayerIndex.One, gameBoardSettings);
608 var displayedGameboardType = playerGameboards.TryGetValue(playerIndex, out var gameboardType)
612 displayedGameboardType = gameBoardSettings.gameboardTypeOverride != GameboardType.GameboardType_None
613 ? gameBoardSettings.gameboardTypeOverride
614 : displayedGameboardType;
616 return displayedGameboardType;
621 #endregion Public Functions
624 #region Internal Functions
626 internal static void Scan()
628 incomingGlassesHandles.Clear();
629 lostGlassesHandles.Clear();
630 lostGameboards.Clear();
631 var glassesHandles = Glasses.GetAllConnectedGlassesHandles();
634 for(
int i = 0; i < glassesHandles.Length; i++)
636 var glassesHandle = glassesHandles[i];
637 incomingGlassesHandles.Add(glassesHandle);
639 if (Glasses.IsTracked(glassesHandle))
641 if(!gameboardCores.ContainsKey(glassesHandle)
642 && Player.TryGetPlayerIndex(glassesHandle, out var playerIndex)
643 && Player.TryGetSettings(playerIndex, out var playerSettings)
644 && playerSettings.gameboardSettings.physicalGameboardOrigin !=
null)
646 gameboardCores.Add(glassesHandle,
new PrimaryGameboardCore(
647 glassesHandle, playerSettings.gameboardSettings.physicalGameboardOrigin.transform));
653 foreach (var glassesHandle
in gameboardCores.Keys)
655 if(!incomingGlassesHandles.Contains(glassesHandle))
657 lostGlassesHandles.Add(glassesHandle);
660 else if(!Glasses.IsTracked(glassesHandle)
661 || !Player.TryGetPlayerIndex(glassesHandle, out var playerIndex)
662 || !Player.TryGetSettings(playerIndex, out var playerSettings)
663 || playerSettings.gameboardSettings.physicalGameboardOrigin ==
null)
665 lostGameboards.Add(gameboardCores[glassesHandle]);
670 foreach(var lostGlassesHandle
in lostGlassesHandles)
672 lostGameboards.Add(gameboardCores[lostGlassesHandle]);
673 gameboardCores.Remove(lostGlassesHandle);
676 foreach(var lostGameboard
in lostGameboards)
678 lostGameboard.Dispose();
682 internal static void Update(GlassesHandle glassesHandle, GameBoardSettings gameboardSettings, ScaleSettings scaleSettings)
684 if(gameboardCores.TryGetValue(glassesHandle, out var gameboardCore))
686 gameboardCore.Update(gameboardSettings, scaleSettings);
697 playerGameboards[playerIndex] = gameboardType;
700 internal static void SetGameboardType(GlassesHandle glassesHandle,
GameboardType gameboardType)
702 if (Player.TryGetPlayerIndex(glassesHandle, out var playerIndex))
704 SetGameboardType(playerIndex, gameboardType);
715 internal Pose
TransformPose(Pose poseInGameboardSpace, ScaleSettings scaleSettings)
717 TransformPose(poseInGameboardSpace.position, poseInGameboardSpace.rotation, scaleSettings,
718 out var posUWRLD, out var rotToUWRLD_OBJ);
719 return new Pose(posUWRLD, rotToUWRLD_OBJ);
731 internal void TransformPose(Vector3 positionInGameboardSpace, Quaternion rotationToGameboardSpace, ScaleSettings scaleSettings,
732 out Vector3 positionInWorldSpace, out Quaternion rotationToWorldSpace)
734 positionInWorldSpace =
TransformPoint(positionInGameboardSpace, scaleSettings);
737 var rotToUWRLD_USTAGE = transform.rotation;
740 var rotToUSTAGE_OBJ = rotationToGameboardSpace;
743 var rotToUWRLD_OBJ = rotToUWRLD_USTAGE * rotToUSTAGE_OBJ;
745 rotationToWorldSpace = rotToUWRLD_OBJ;
755 internal Vector3
TransformPoint(Vector3 pointInGameboardSpace, ScaleSettings scaleSettings)
757 var pos_USTAGE = pointInGameboardSpace;
759 var scaleToUWRLD_USTAGE = scaleSettings.GetScaleToWorldSpaceFromGameboardSpace(
localScale);
760 var rotToUWRLD_USTAGE = transform.rotation;
761 var pos_UWRLD = rotToUWRLD_USTAGE * (scaleToUWRLD_USTAGE * pos_USTAGE) + transform.position;
776 out var posUSTAGE, out var rotToUSTAGE_OBJ);
777 return new Pose(posUSTAGE, rotToUSTAGE_OBJ);
789 internal void InverseTransformPose(Vector3 positionInWorldSpace, Quaternion rotationToWorldSpace, ScaleSettings scaleSettings,
790 out Vector3 positionInGameboardSpace, out Quaternion rotationToGameboardSpace)
795 var rotToUWRLD_USTAGE = transform.rotation;
798 var rotToUSTAGE_UWRLD = Quaternion.Inverse(rotToUWRLD_USTAGE);
801 var rotToUWRLD_OBJ = rotationToWorldSpace;
804 var rotToUSTAGE_OBJ = rotToUSTAGE_UWRLD * rotToUWRLD_OBJ;
806 rotationToGameboardSpace = rotToUSTAGE_OBJ;
818 var pos_UWRLD = pointInWorldSpace;
820 var scaleToUSTAGE_UWRLD = 1f / scaleSettings.GetScaleToWorldSpaceFromGameboardSpace(
localScale);
821 var rotToUSTAGE_UWRLD = Quaternion.Inverse(transform.rotation);
822 var pos_USTAGE = pos_UWRLD - transform.position;
823 pos_USTAGE = rotToUSTAGE_UWRLD * pos_USTAGE;
824 pos_USTAGE *= scaleToUSTAGE_UWRLD;
829 internal static void OnDisable()
831 foreach (var gameboardCore
in gameboardCores.Values)
833 gameboardCore.Dispose();
835 gameboardCores.Clear();
841 #region Private Functions
851 private bool ScaleCompensate(ScaleSettings scaleSettings)
853 if(currentScale == transform.localScale) {
return false; }
856 if( transform.localScale.x < MIN_SCALE)
858 transform.localScale = Vector3.one * MIN_SCALE;
865 currentScale = transform.localScale;
872 private bool ContentScaleCompensate(ScaleSettings scaleSettings)
875 && currentContentScaleUnit == scaleSettings.
contentScaleUnit) {
return false; }
890 #endregion Private Functions
893 #region Private Classes
895 private abstract class BaseGameboardCore : TrackableCore<GameBoardSettings, T5_GameboardPose>, IDisposable
897 #region Protected Fields
899 protected GlassesHandle glassesHandle;
900 protected Transform gameboardTransform;
902 protected Pose DEFAULT_GAMEBOARD_POSE_USTAGE =
new Pose(Vector3.zero, Quaternion.identity);
904 #endregion Protected Fields
907 #region Public Functions
909 public BaseGameboardCore(GlassesHandle glassesHandle, Transform gameboardTransform)
911 this.glassesHandle = glassesHandle;
912 this.gameboardTransform = gameboardTransform;
915 public void Dispose()
920 #endregion Public Functions
923 #region Protected Functions
925 protected override void Update(GameBoardSettings settings, ScaleSettings scaleSettings, GameBoardSettings gameBoardSettings)
928 base.Update(settings, scaleSettings, settings);
931 #endregion Protected Functions
934 #region TrackableCore Overrides
936 protected override void SetDefaultPoseGameboardSpace(GameBoardSettings settings)
938 pose_USTAGE = DEFAULT_GAMEBOARD_POSE_USTAGE;
941 protected override void SetDrivenObjectTransform(GameBoardSettings settings, ScaleSettings scaleSettings, GameBoardSettings gameboardSettings)
943 gameboardTransform?.SetPositionAndRotation(pose_UWRLD.position, pose_UWRLD.rotation);
946 protected override void SetInvalidPoseGameboardSpace(in T5_GameboardPose state, GameBoardSettings settings, ScaleSettings scaleSettings, GameBoardSettings gameboardSettings)
948 SetPoseGameboardSpace(state, settings, scaleSettings, settings);
951 protected override void SetPoseGameboardSpace(in T5_GameboardPose state, GameBoardSettings settings, ScaleSettings scaleSettings, GameBoardSettings gameboardSettings)
953 var gameboardPos_USTAGE = ConvertPosSTAGEToUSTAGE(state.PosOfBOARD_STAGE);
954 Quaternion rotToSTAGE_BOARD = Quaternion.Inverse(state.RotationToBOARD_STAGE);
955 Quaternion rotToUSTAGE_UBOARD = ChangeHandednessRightToLeft(rotToSTAGE_BOARD);
957 pose_USTAGE =
new Pose(gameboardPos_USTAGE, rotToUSTAGE_UBOARD);
960 protected override void SetPoseUnityWorldSpace(ScaleSettings scaleSettings, GameBoardSettings gameboardSettings)
965 protected override bool TryCheckConnected(out
bool connected)
968 connected = Glasses.IsTracked(glassesHandle);
972 #endregion TrackableCore Overrides
975 #region Private Helper Functions
977 private Quaternion ChangeHandednessRightToLeft(Quaternion rotToB_A)
979 return new Quaternion(-rotToB_A.x, -rotToB_A.z, -rotToB_A.y, rotToB_A.w);
982 #endregion Private Helper Functions
986 private class PrimaryGameboardCore : BaseGameboardCore
988 public PrimaryGameboardCore(GlassesHandle glassesHandle, Transform gameboardTransform)
989 : base(glassesHandle, gameboardTransform) { }
991 public void Update(GameBoardSettings gameboardSettings, ScaleSettings scaleSettings)
993 base.Update(gameboardSettings, scaleSettings, gameboardSettings);
998 protected override bool TryGetStateFromPlugin(out T5_GameboardPose state, out
bool poseIsValid)
1000 var succeeded =
false;
1001 T5_GameboardPose[] resultingPoses =
new T5_GameboardPose[MAX_SUPPORTED_GAMEBOARD_POSES];
1002 UInt16 count = MAX_SUPPORTED_GAMEBOARD_POSES;
1006 succeeded = NativePlugin.GetGameboardPoses(glassesHandle, resultingPoses, ref count) == NativePlugin.T5_RESULT_SUCCESS;
1010 Log.Error(e.Message);
1013 if (!succeeded || count < 1 || resultingPoses.Length < 1)
1015 state =
new T5_GameboardPose();
1016 poseIsValid =
false;
1017 GameBoard.SetGameboardType(glassesHandle,
GameboardType.GameboardType_None);
1021 state = resultingPoses[0];
1023 GameBoard.SetGameboardType(glassesHandle, state.GameboardType);
1028 #endregion Private Classes