21using System.Collections.Generic;
28 public class TableTopGizmo {
30 #region Private Structs
32 private struct GameboardMesh
34 public string boardMeshAssetPath;
35 public string surfaceMeshChildPath;
36 public string borderMeshChildPath;
37 public string stageMeshChildPath;
38 public string stageCornerMeshChildPath;
40 public GameObject meshObj;
41 public Mesh meshSurface;
42 public Mesh meshBorder;
43 public Mesh meshStage;
44 public Mesh meshStageCorner;
46 public bool TryLoadMeshes()
48 bool allMeshesLoaded = meshObj !=
null && meshBorder !=
null && meshSurface !=
null
49 && meshStage !=
null && meshStageCorner !=
null;
53 LoadGameboardModel(boardMeshAssetPath, surfaceMeshChildPath, borderMeshChildPath,
54 stageMeshChildPath, stageCornerMeshChildPath,
55 out meshObj, out meshSurface, out meshBorder, out meshStage, out meshStageCorner);
57 return !allMeshesLoaded;
60 public void LoadGameboardModel(
string meshAssetPath,
string surfaceMeshChildPath,
string borderMeshChildPath,
61 string stageMeshChildPath,
string stageCornerMeshChildPath,
62 out GameObject meshObj, out Mesh meshSurface, out Mesh meshBorder, out Mesh meshStage, out Mesh meshStageCorner)
64 meshObj = AssetDatabase.LoadAssetAtPath<GameObject>(meshAssetPath);
66 TryGetMesh(surfaceMeshChildPath, out meshSurface);
67 TryGetMesh(borderMeshChildPath, out meshBorder);
68 TryGetMesh(stageMeshChildPath, out meshStage);
69 TryGetMesh(stageCornerMeshChildPath, out meshStageCorner);
72 private bool TryGetMesh(
string meshPath, out Mesh resultMesh)
74 var meshTransform = meshObj.transform.Find(meshPath);
75 if(meshTransform !=
null && meshTransform.TryGetComponent<MeshFilter>(out var meshFilter))
77 resultMesh = meshFilter.sharedMesh;
85 private struct LineSegment
87 public LineSegment(Vector3 start, Vector3 end,
int LOD)
98 private struct GizmoReferenceFrame : System.IDisposable
100 private Matrix4x4 previousGizmoMatrix;
102 public GizmoReferenceFrame(Matrix4x4 temporaryGizmoReferenceFrame)
104 previousGizmoMatrix = Gizmos.matrix;
105 Gizmos.matrix = temporaryGizmoReferenceFrame;
108 public void Dispose()
110 Gizmos.matrix = previousGizmoMatrix;
114 private struct GizmoColor : System.IDisposable
116 private Color previousGizmoColor;
117 public GizmoColor(Color temporaryGizmoColor)
119 previousGizmoColor = Gizmos.color;
120 Gizmos.color = temporaryGizmoColor;
123 public GizmoColor(Color temporaryGizmoColor,
float alphaOverride)
124 : this(new Color(temporaryGizmoColor.r, temporaryGizmoColor.g, temporaryGizmoColor.b, alphaOverride))
128 public GizmoColor(
float r,
float g,
float b)
129 : this(new Color(r,g,b))
133 public GizmoColor(
float r,
float g,
float b,
float a)
134 : this(new Color(r, g, b, a))
138 public void Dispose()
140 Gizmos.color = previousGizmoColor;
144 #endregion Private Structs
146 private GameboardMesh gameboardMesh_LE =
new GameboardMesh()
148 boardMeshAssetPath = MeshAssets.GetPathToGameboardMesh(
GameboardType.GameboardType_LE),
149 surfaceMeshChildPath =
"Surface_LE",
150 borderMeshChildPath =
"Border_LE",
151 stageMeshChildPath =
"Stage_LE",
152 stageCornerMeshChildPath =
"Stage_Corner_LE"
155 private GameboardMesh gameboardMesh_XE =
new GameboardMesh()
157 boardMeshAssetPath = MeshAssets.GetPathToGameboardMesh(
GameboardType.GameboardType_XE),
158 surfaceMeshChildPath =
"Surface_Flat",
159 borderMeshChildPath =
"Border_Flat",
160 stageMeshChildPath =
"Stage_Flat",
161 stageCornerMeshChildPath =
"Stage_Corner_Flat"
164 private GameboardMesh gameboardMesh_XE_Raised =
new GameboardMesh()
166 boardMeshAssetPath = MeshAssets.GetPathToGameboardMesh(
GameboardType.GameboardType_XE_Raised),
167 surfaceMeshChildPath =
"Surface_Raised",
168 borderMeshChildPath =
"Border_Raised",
169 stageMeshChildPath =
"Stage_Raised",
170 stageCornerMeshChildPath =
"Stage_Corner_Raised"
173 private string logoMeshAssetPath = MeshAssets.GetPathToT5LogoMesh();
174 private string logoBorderChildPath =
"Circle";
175 private string logoLeftCharacterChildPath =
"Tilt";
176 private string logoRightCharacterChildPath =
"Five";
178 private ScaleSettings scaleSettings;
179 private GameBoardSettings gameBoardSettings;
180 private float scaleToUWRLD_USTAGE => scaleSettings.GetScaleToWorldSpaceFromGameboardSpace(gameBoardSettings.gameBoardScale);
181 private GameBoard.GameboardExtents gameboardExtents =
new GameBoard.GameboardExtents(
182 GameBoard.GameboardExtents.GAMEBOARD_SIZE_LE);
184 private float totalGameBoardWidthInMeters =>
185 usableGameBoardWidthInMeters + 2f * GameBoard.GameboardExtents.BORDER_WIDTH_IN_METERS;
186 private float totalGameBoardLengthInMeters =>
187 usableGameBoardLengthInMeters + 2f * GameBoard.GameboardExtents.BORDER_WIDTH_IN_METERS;
189 private float usableGameBoardWidthInMeters => gameboardExtents.ViewableSpanX.ToMeters;
190 private float usableGameBoardLengthInMeters => gameboardExtents.ViewableSpanZ.ToMeters;
194 private GameObject logoObj;
195 private Mesh meshLogoBorder;
196 private Mesh meshLogoLeftCharacter;
197 private Mesh meshLogoRightCharacter;
199 private Mesh meshRuler;
200 private List<LineSegment> rulerData;
204 private List<LineSegment> xGridLines;
205 private List<LineSegment> zGridLines;
206 private float yGridOffset;
208 private readonly Color t5Orange =
new Color(0.9450980392156862f, 0.34901960784313724f, 0.13333333333333333f);
209 private readonly Color t5LightGray =
new Color(0.9607843137254902f, 0.9647058823529412f, 0.9647058823529412f);
210 private readonly Color t5Gray =
new Color(0.3764705882352941f, 0.39215686274509803f, 0.4392156862745098f);
211 private void Configure(ScaleSettings scaleSettings, GameBoardSettings gameBoardSettings,
212 float gridOffsetY, GameBoard.GameboardExtents gameboardExtents)
214 this.scaleSettings = scaleSettings;
215 this.gameBoardSettings = gameBoardSettings;
216 this.yGridOffset = gridOffsetY;
217 this.gameboardExtents = gameboardExtents;
219 gameboardMesh_LE.TryLoadMeshes();
220 gameboardMesh_XE.TryLoadMeshes();
221 gameboardMesh_XE_Raised.TryLoadMeshes();
225 logoObj = AssetDatabase.LoadAssetAtPath<GameObject>(logoMeshAssetPath);
228 if(
null == meshLogoBorder)
230 var transform = logoObj.transform.Find( logoBorderChildPath );
231 if(transform !=
null)
233 if(transform.TryGetComponent<MeshFilter>(out var meshFilter))
235 meshLogoBorder = meshFilter.sharedMesh;
239 if(
null == meshLogoLeftCharacter)
241 var transform = logoObj.transform.Find( logoLeftCharacterChildPath );
242 if(transform !=
null)
244 if(transform.TryGetComponent<MeshFilter>(out var meshFilter))
246 meshLogoLeftCharacter = meshFilter.sharedMesh;
250 if(
null == meshLogoRightCharacter)
252 var transform = logoObj.transform.Find( logoRightCharacterChildPath );
253 if(transform !=
null)
255 if(transform.TryGetComponent<MeshFilter>(out var meshFilter))
257 meshLogoRightCharacter = meshFilter.sharedMesh;
262 var previousGameboardType = gameboardType;
263 gameboardType = gameBoardSettings.currentGameBoard.GetDisplayedGameboardType(gameBoardSettings);
265 bool gameboardTypeChanged = previousGameboardType != gameboardType;
267 if (
null == xGridLines ||
null == zGridLines || gameboardTypeChanged)
272 if(
null == meshRuler || gameboardTypeChanged)
274 ConstructRulerMesh(gameboardExtents.ViewableSpanX,
"meshRuler", out meshRuler);
278 public void ConstructRulerMesh(Length rulerLength,
string meshName, out Mesh meshRuler)
280 var rulerData =
new List<LineSegment>();
282 float oneMillimeterLengthInMeters =
new Length(1, LengthUnit.Millimeters).ToMeters;
285 for (
int i = 0; i * oneMillimeterLengthInMeters < rulerLength.ToMeters; i++)
287 float currentDistance = i * (oneMillimeterLengthInMeters / rulerLength.ToMeters);
288 float smallestFractionOfBoardWidth = 1f / 150f;
290 float tickMarkLength = smallestFractionOfBoardWidth;
293 lod -= i % 5 == 0 ? 1 : 0;
294 lod -= i % 10 == 0 ? 1 : 0;
296 tickMarkLength += (3 - lod) * smallestFractionOfBoardWidth;
298 rulerData.Add(
new LineSegment(
new Vector3(currentDistance, 0f, 0f),
new Vector3(currentDistance, 0f, tickMarkLength), lod));
301 float oneSixteenthInchLengthInMeters =
new Length(1 / 16f, LengthUnit.Inches).ToMeters;
304 for (
int i = 0; i * oneSixteenthInchLengthInMeters < rulerLength.ToMeters; i++)
306 float currentDistance = i * (oneSixteenthInchLengthInMeters / rulerLength.ToMeters);
307 float smallestFractionOfBoardWidth = 1f / 300f;
309 float tickMarkLength = smallestFractionOfBoardWidth;
312 lod -= i % 2 == 0 ? 1 : 0;
313 lod -= i % 4 == 0 ? 1 : 0;
314 lod -= i % 8 == 0 ? 1 : 0;
315 lod -= i % 16 == 0 ? 1 : 0;
317 tickMarkLength += (5 - lod) * smallestFractionOfBoardWidth;
319 float offsetFromCentimeterRuler = 1 / 16f;
320 rulerData.Add(
new LineSegment(
321 new Vector3(currentDistance, 0f, offsetFromCentimeterRuler - tickMarkLength),
322 new Vector3(currentDistance, 0f, offsetFromCentimeterRuler),
326 meshRuler =
new Mesh();
327 meshRuler.name = meshName;
329 int vertArraySizeRatio = 4;
330 Vector3[] verts =
new Vector3[rulerData.Count * vertArraySizeRatio];
332 int triArraySizeRatio = 6;
333 int[] triangles =
new int[rulerData.Count * triArraySizeRatio];
335 float lineThickness = 1 / 2800f;
338 var lineThicknessOffset = Vector3.right * (lineThickness / 2f);
340 for (
int i = 0; i < rulerData.Count; i++)
342 var line = rulerData[i];
344 var bottomLeft = line.Start - lineThicknessOffset + Vector3.left / 2 + Vector3.back / 32f;
345 var topLeft = line.End - lineThicknessOffset + Vector3.left / 2 + Vector3.back / 32f;
347 var bottomRight = line.Start + lineThicknessOffset + Vector3.left / 2 + Vector3.back / 32f;
348 var topRight = line.End + lineThicknessOffset + Vector3.left / 2 + Vector3.back / 32f;
350 var vertIndex = i * vertArraySizeRatio;
351 verts[vertIndex] = bottomLeft;
352 verts[vertIndex + 1] = topLeft;
353 verts[vertIndex + 2] = bottomRight;
354 verts[vertIndex + 3] = topRight;
356 var triIndex = i * triArraySizeRatio;
357 triangles[triIndex] = vertIndex;
358 triangles[triIndex + 1] = vertIndex + 1;
359 triangles[triIndex + 2] = vertIndex + 2;
361 triangles[triIndex + 3] = vertIndex + 2;
362 triangles[triIndex + 4] = vertIndex + 1;
363 triangles[triIndex + 5] = vertIndex + 3;
366 meshRuler.vertices = verts;
367 meshRuler.triangles = triangles;
368 meshRuler.RecalculateNormals();
372 public void ResetGrid(ScaleSettings newScaleSettings =
null, GameBoardSettings newGameBoardSettings =
null)
374 if (newScaleSettings !=
null)
376 this.scaleSettings = newScaleSettings;
378 if(newGameBoardSettings !=
null)
380 this.gameBoardSettings = newGameBoardSettings;
383 if(xGridLines ==
null)
385 xGridLines =
new List<LineSegment>();
387 else xGridLines.Clear();
389 if(zGridLines ==
null)
391 zGridLines =
new List<LineSegment>();
393 else zGridLines.Clear();
395 var lineLengthZ = 0.5f;
396 var linePosOffsetZ = lineLengthZ - 0.5f;
397 var lineStartPosZ = lineLengthZ;
398 var lineStopPosZ = -lineLengthZ + linePosOffsetZ;
399 var minDimension = Mathf.Min(usableGameBoardWidthInMeters, usableGameBoardLengthInMeters);
400 var oneUnit = scaleSettings.oneUnitLengthInMeters / minDimension;
402 for (
int i = 0; i * scaleSettings.oneUnitLengthInMeters < usableGameBoardWidthInMeters / 2; i++)
404 float distanceFromCenter = i * (scaleSettings.oneUnitLengthInMeters / minDimension);
407 xGridLines.Add(
new LineSegment(
new Vector3(distanceFromCenter, 0, lineStartPosZ),
new Vector3(distanceFromCenter, 0, lineStopPosZ), lod));
410 if(i < 1) {
continue;}
412 xGridLines.Add(
new LineSegment(
new Vector3(-distanceFromCenter, 0, lineStartPosZ),
new Vector3(-distanceFromCenter, 0, lineStopPosZ), lod));
416 for (
int i = 0; i * scaleSettings.oneUnitLengthInMeters < usableGameBoardWidthInMeters / 2; i++)
418 float distanceFromCenter = i * (scaleSettings.oneUnitLengthInMeters / minDimension);
421 zGridLines.Add(
new LineSegment(
new Vector3(0.5f, 0, distanceFromCenter),
new Vector3(-0.5f, 0, distanceFromCenter), lod));
424 if(i < scaleSettings.oneUnitLengthInMeters) {
continue; }
426 zGridLines.Add(
new LineSegment(
new Vector3(0.5f, 0, -distanceFromCenter),
new Vector3(-0.5f, 0, -distanceFromCenter), lod));
430 public void Draw(ScaleSettings scaleSettings, GameBoardSettings gameBoardSettings,
431 float alpha,
bool showGrid,
float gridOffsetY = 0f)
433 Configure (scaleSettings, gameBoardSettings, gridOffsetY, gameboardExtents);
435 if (
null == gameBoardSettings) {
return; }
437 GameboardMesh gameboardMesh;
439 switch (gameboardType)
442 gameboardMesh = gameboardMesh_XE;
445 gameboardMesh = gameboardMesh_XE_Raised;
450 gameboardMesh = gameboardMesh_LE;
454 var rotToUSTAGE_UBOARD = GetRotToUSTAGE_UBOARD(gameBoardSettings);
456 Matrix4x4 mtxUWRLD_USTAGE = gameBoardSettings.currentGameBoard.transform.localToWorldMatrix * Matrix4x4.Scale(Vector3.one * scaleToUWRLD_USTAGE);
467 var fadeInStartAngle = 3f;
468 var fadeInEndAngle = 10f;
469 var stageGizmoAlpha = GetStageOpacity(rotToUSTAGE_UBOARD, fadeInStartAngle, fadeInEndAngle, alpha);
471 DrawStage(gameboardMesh, mtxUWRLD_USTAGE, stageGizmoAlpha);
478 var lowestCorner_USTAGE = GetLowestCorner(rotToUSTAGE_UBOARD);
480 var verticalOffset_USTAGE = -lowestCorner_USTAGE.pos_USTAGE.y;
481 var mtxUSTAGE_UBOARD = Matrix4x4.TRS(verticalOffset_USTAGE * Vector3.up, rotToUSTAGE_UBOARD, Vector3.one);
482 var mtxUWRLD_UBOARD = mtxUWRLD_USTAGE * mtxUSTAGE_UBOARD;
484 DrawPhysicalBoard(gameboardMesh, mtxUWRLD_UBOARD, alpha);
493 private void DrawStage(GameboardMesh gameboardMesh, Matrix4x4 mtxGizmo,
float alpha)
500 using (
new GizmoReferenceFrame(mtxGizmo))
502 if (gameboardMesh.meshStage !=
null)
504 using (
new GizmoColor(1.0f, 1.0f, 1.0f, alpha))
506 Gizmos.DrawMesh(gameboardMesh.meshStage);
510 if (gameboardMesh.meshStageCorner !=
null)
512 using (
new GizmoColor(t5Orange, alpha))
514 Gizmos.DrawMesh(gameboardMesh.meshStageCorner, 0);
518 if (gameboardMesh.meshSurface !=
null)
520 using (
new GizmoColor(0.5f, 0.5f, 0.5f, alpha / 2f))
522 Gizmos.DrawMesh(gameboardMesh.meshSurface, 0);
528 private (GameBoard.Corner corner, Vector3 pos_USTAGE) GetLowestCorner(Quaternion rotToUSTAGE_UBOARD)
532 T5_GameboardSize gameboardSize;
534 switch (gameboardType)
537 gameboardSize = GameBoard.GameboardExtents.GAMEBOARD_SIZE_XE;
540 gameboardSize = GameBoard.GameboardExtents.GAMEBOARD_SIZE_XE_RAISED;
544 gameboardSize = GameBoard.GameboardExtents.GAMEBOARD_SIZE_LE;
548 GameBoard.GameboardExtents gameboardExtents =
new GameBoard.GameboardExtents(gameboardSize);
551 (GameBoard.Corner corner, Vector3 pos_USTAGE) lowestCorner_USTAGE
552 = (GameBoard.Corner.FarLeft, rotToUSTAGE_UBOARD * gameboardExtents.GetCornerPositionInGameboardSpace(GameBoard.Corner.FarLeft));
554 for (GameBoard.Corner corner = GameBoard.Corner.FarRight; (
int)corner < 4; corner++)
556 var cornerPos_USTAGE = rotToUSTAGE_UBOARD * gameboardExtents.GetCornerPositionInGameboardSpace(corner);
558 if (cornerPos_USTAGE.y < lowestCorner_USTAGE.pos_USTAGE.y)
560 lowestCorner_USTAGE = (corner, cornerPos_USTAGE);
563 return lowestCorner_USTAGE;
566 private Quaternion GetRotToUSTAGE_UBOARD(GameBoardSettings gameboardSettings)
568 var rotToUSTAGE_UBOARD = gameboardSettings.enableGameboardOrientationOverride
569 ? Quaternion.Euler(gameboardSettings.gameboardOrientationOverride)
570 : gameboardSettings.physicalGameboardOrigin ==
null ? Quaternion.identity : gameboardSettings.physicalGameboardOrigin.transform.localRotation;
571 return rotToUSTAGE_UBOARD;
574 private float GetStageOpacity(Quaternion rotToULBOARD_ULSTAGE,
float lowerAngleThreshold,
float higherAngleThreshold,
float baseOpacity)
598 var alignmentWithStage = 1f - Mathf.Abs(Quaternion.Dot(Quaternion.identity, rotToULBOARD_ULSTAGE));
599 var referenceAlignmentStartThreshold = 1f - Quaternion.Dot(Quaternion.identity, Quaternion.Euler(Vector3.right * lowerAngleThreshold));
600 var referenceAlignmentEndThreshold = 1f - Quaternion.Dot(Quaternion.identity, Quaternion.Euler(Vector3.right * higherAngleThreshold));
601 return Mathf.Lerp(0f, baseOpacity,
602 Mathf.Min(Mathf.Max(alignmentWithStage - referenceAlignmentStartThreshold, 0f) / (referenceAlignmentEndThreshold - referenceAlignmentStartThreshold), 1f));
605 private void DrawPhysicalBoard(GameboardMesh gameboardMesh, Matrix4x4 mtxGizmo,
float alpha)
612 using (
new GizmoReferenceFrame(mtxGizmo))
614 if (gameboardMesh.meshSurface !=
null)
616 using (
new GizmoColor(0.5f, 0.5f, 0.5f, alpha))
618 Gizmos.DrawMesh(gameboardMesh.meshSurface, 0);
622 if (gameboardMesh.meshBorder !=
null)
624 using (
new GizmoColor(0.0f, 0.0f, 0.0f, alpha))
626 Gizmos.DrawMesh(gameboardMesh.meshBorder, 0);
630 if (meshLogoBorder !=
null && meshLogoLeftCharacter !=
null && meshLogoRightCharacter !=
null)
632 DrawLogo(Gizmos.matrix, alpha);
637 private void DrawLogo(Matrix4x4 mtxGizmo,
float alpha)
644 using (
new GizmoReferenceFrame(mtxGizmo))
646 using (
new GizmoColor(t5LightGray, alpha))
648 Gizmos.DrawMesh( meshLogoBorder, 0 );
651 using (
new GizmoColor(t5Orange, alpha))
653 Gizmos.DrawMesh(meshLogoLeftCharacter, 0);
656 using (
new GizmoColor(t5Gray, alpha))
658 Gizmos.DrawMesh(meshLogoRightCharacter, 0);
663 private void DrawGrid(
float alpha)
665 var contentScaleFactor = scaleToUWRLD_USTAGE;
666 float heightOffsetInMeters = yGridOffset * scaleSettings.oneUnitLengthInMeters;
667 float lengthOffsetInMeters = Mathf.Max(usableGameBoardLengthInMeters - usableGameBoardWidthInMeters, 0f) / 2f;
669 var gameBoardTransform = gameBoardSettings.currentGameBoard.transform;
672 Matrix4x4 mtxPreTransform = Matrix4x4.Scale(
673 Vector3.one * Mathf.Min(usableGameBoardWidthInMeters, usableGameBoardLengthInMeters));
675 Matrix4x4 mtxGizmo = Matrix4x4.TRS(
676 gameBoardSettings.gameBoardCenter + (gameBoardTransform.up * heightOffsetInMeters / contentScaleFactor),
677 gameBoardTransform.rotation,
678 Vector3.one / contentScaleFactor ) * mtxPreTransform;
681 var gridLinePeriod = scaleSettings.contentScaleUnit == LengthUnit.Inches ? 12 : 10;
685 float beginFadeThreshold = 20f;
686 float endFadeThreshold = 10f;
689 TryGetCameraPositionOverGameBoard(out var cameraPositionOverGameBoard);
690 Vector3 testUnitVector = cameraPositionOverGameBoard + Vector3.right * scaleSettings.oneUnitLengthInMeters / contentScaleFactor;
691 Vector3 secondTestUnitVector = cameraPositionOverGameBoard + Vector3.right * gridLinePeriod * scaleSettings.oneUnitLengthInMeters / contentScaleFactor;
693 var screenSpaceDistance = (SceneView.currentDrawingSceneView.camera.WorldToScreenPoint(testUnitVector)
694 - SceneView.currentDrawingSceneView.camera.WorldToScreenPoint(cameraPositionOverGameBoard)).magnitude;
695 var secondScreenSpaceDistance = (SceneView.currentDrawingSceneView.camera.WorldToScreenPoint(secondTestUnitVector)
696 - SceneView.currentDrawingSceneView.camera.WorldToScreenPoint(cameraPositionOverGameBoard)).magnitude;
699 var beginFade = screenSpaceDistance < beginFadeThreshold;
700 var endFade = screenSpaceDistance < endFadeThreshold;
702 var beginSecondFade = secondScreenSpaceDistance < beginFadeThreshold;
703 var endSecondFade = secondScreenSpaceDistance < endFadeThreshold;
705 var fadeFactor = 1f - Mathf.Clamp((beginFadeThreshold - screenSpaceDistance) / endFadeThreshold, 0f, 1f);
706 var secondFadeFactor = 1f - Mathf.Clamp((beginFadeThreshold - secondScreenSpaceDistance) / endFadeThreshold, 0f, 1f);
708 var fadeAlpha = alpha * fadeFactor;
709 var secondFadeAlpha = alpha * secondFadeFactor;
712 using (
new GizmoReferenceFrame(mtxGizmo))
714 DrawGridLines(xGridLines, gridLinePeriod, alpha, beginFade, endFade, fadeAlpha, beginSecondFade, endSecondFade, secondFadeAlpha);
715 DrawGridLines(zGridLines, gridLinePeriod, alpha, beginFade, endFade, fadeAlpha, beginSecondFade, endSecondFade, secondFadeAlpha);
719 private void DrawGridLines(List<LineSegment> lines,
int gridLinePeriod,
float alpha,
bool beginFade,
bool endFade,
720 float fadeAlpha,
bool beginSecondFade,
bool endSecondFade,
float secondFadeAlpha)
722 var gridLinePeriodSquared = gridLinePeriod * gridLinePeriod;
723 var mtxGizmo = Gizmos.matrix;
727 float cursorSphereRadius = scaleToUWRLD_USTAGE * (scaleSettings.oneUnitLengthInMeters / 2f);
730 cursorSphereRadius *= (gridLinePeriod * gridLinePeriod) / 2f;
734 cursorSphereRadius *= gridLinePeriod / 2f;
737 for(
int i = 0; i < lines.Count; i++)
740 var isPeriodic = i % gridLinePeriod == 0 || i % gridLinePeriod == gridLinePeriod - 1;
741 if(endFade && !isPeriodic) {
continue; }
743 var isDoublePeriodic = i % gridLinePeriodSquared == 0 || i % gridLinePeriodSquared == gridLinePeriodSquared - 1;
744 if(endSecondFade && !isDoublePeriodic) {
continue; }
747 var currentGridLineSegment = lines[i];
748 var transformedLineSegment =
new LineSegment(
749 mtxGizmo.MultiplyPoint3x4(currentGridLineSegment.Start),
750 mtxGizmo.MultiplyPoint3x4(currentGridLineSegment.End), currentGridLineSegment.LOD);
752 var lineCollidesWithCursor = TryGetCursorPosition(out var cursorPosition)
753 && CheckRaySphereCollision(cursorPosition, cursorSphereRadius, transformedLineSegment);
756 var lineAlpha = alpha;
757 if(beginSecondFade && !isDoublePeriodic)
759 lineAlpha = secondFadeAlpha;
761 else if(beginFade && !isPeriodic)
763 lineAlpha = fadeAlpha;
766 using (lineCollidesWithCursor
767 ?
new GizmoColor(1f, 0f, 0f, alpha)
768 : new GizmoColor(1f, 1f, 1f, lineAlpha))
771 if (lineCollidesWithCursor)
773 var xLineExtensionFactor = totalGameBoardWidthInMeters / usableGameBoardWidthInMeters;
774 var zLineExtensionFactor = totalGameBoardLengthInMeters / usableGameBoardLengthInMeters;
777 var lineDifference = currentGridLineSegment.End - currentGridLineSegment.Start;
778 var xAxisAligned = Mathf.Abs(Vector3.Dot(Vector3.right, lineDifference)) == 1;
780 var mtxPreTransform = Matrix4x4.Scale(
781 (xAxisAligned ?
new Vector3(xLineExtensionFactor, 1f, 1f) :
new Vector3(1f, 1f, zLineExtensionFactor)));
782 var newMtxWorld = Matrix4x4.TRS(
783 gameBoardSettings.currentGameBoard.transform.position,
784 gameBoardSettings.currentGameBoard.transform.rotation,
785 new Vector3(scaleToUWRLD_USTAGE * usableGameBoardWidthInMeters, 0f, scaleToUWRLD_USTAGE * usableGameBoardWidthInMeters));
788 using (
new GizmoReferenceFrame(newMtxWorld))
790 Gizmos.DrawLine(currentGridLineSegment.Start, mtxPreTransform.MultiplyPoint3x4(currentGridLineSegment.Start));
791 Gizmos.DrawLine(currentGridLineSegment.End, mtxPreTransform.MultiplyPoint3x4(currentGridLineSegment.End));
794 Gizmos.DrawLine(currentGridLineSegment.Start, currentGridLineSegment.End);
799 private bool TryGetCursorPosition(out Vector3 intersectPoint)
801 var sceneView = UnityEditor.SceneView.currentDrawingSceneView;
802 var sceneViewCamera = sceneView.camera;
803 var mousePos = Event.current.mousePosition - sceneView.position.position;
806 mousePos = GUIUtility.GUIToScreenPoint(mousePos);
809 var frameOffset = Vector2.down * 36f;
810 mousePos.y = (sceneViewCamera.pixelHeight - mousePos.y - frameOffset.y);
812 var ray = sceneViewCamera.ScreenPointToRay(mousePos);
814 return TryGetGridPlanePosition(ray, out intersectPoint);
817 private bool TryGetCameraPositionOverGameBoard(out Vector3 intersectPoint)
819 var ray =
new Ray(UnityEditor.SceneView.currentDrawingSceneView.camera.transform.position, -gameBoardSettings.currentGameBoard.transform.up);
820 return TryGetGridPlanePosition(ray, out intersectPoint);
823 private bool TryGetGridPlanePosition(Ray ray, out Vector3 intersectPoint)
826 var planeOffsetY = (yGridOffset * scaleSettings.oneUnitLengthInMeters) / scaleToUWRLD_USTAGE;
827 var gridPlane =
new Plane(
828 gameBoardSettings.currentGameBoard.transform.up,
829 gameBoardSettings.currentGameBoard.transform.localToWorldMatrix.MultiplyPoint3x4(planeOffsetY * Vector3.up));
831 if(gridPlane.Raycast(ray, out var intersectionDistance))
834 intersectPoint = ray.GetPoint(intersectionDistance);
838 intersectPoint = Vector3.zero;
842 private bool CheckRaySphereCollision(Vector3 sphereCenter,
float sphereRadius, LineSegment lineSegment){
844 var ray =
new Ray(lineSegment.Start, lineSegment.End - lineSegment.Start);
846 Vector3 rayToSphereCenterDistance = ray.origin - sphereCenter;
847 float a = Vector3.Dot(ray.direction, ray.direction);
848 float b = 2f * Vector3.Dot(rayToSphereCenterDistance, ray.direction);
849 float c = Vector3.Dot(rayToSphereCenterDistance, rayToSphereCenterDistance) - sphereRadius * sphereRadius;
850 float discriminant = (b * b) - (4*a*c);
851 return discriminant > 0;
854 private void DrawRulers(
float alpha)
856 if(meshRuler ==
null) {
return; }
858 var contentScaleFactor = scaleToUWRLD_USTAGE;
859 float borderWidthInMeters = GameBoard.GameboardExtents.BORDER_WIDTH_IN_METERS;
860 float lengthOffsetInMeters = Mathf.Max(usableGameBoardLengthInMeters - usableGameBoardWidthInMeters, 0f) / 2f;
861 var gameBoardTransform = gameBoardSettings.currentGameBoard.transform;
862 var gameboardCenter = gameBoardSettings.gameBoardCenter;
864 Matrix4x4 mtxPreTransform = Matrix4x4.Scale(
new Vector3(usableGameBoardWidthInMeters, 1f, usableGameBoardLengthInMeters));
866 using (
new GizmoColor(1f, 0.8320962f, 0.3803922f, alpha))
869 Matrix4x4 mtxWorld = Matrix4x4.TRS(gameboardCenter + (gameBoardTransform.forward * lengthOffsetInMeters / contentScaleFactor) + (0.5f * (usableGameBoardLengthInMeters + borderWidthInMeters) * gameBoardTransform.forward) / contentScaleFactor,
870 Quaternion.Euler(gameBoardSettings.gameBoardRotation),
871 Vector3.one / contentScaleFactor );
872 using (
new GizmoReferenceFrame(mtxWorld * mtxPreTransform))
874 Gizmos.DrawMesh(meshRuler, 0 );
878 mtxWorld = Matrix4x4.TRS(gameboardCenter - (0.5f * (usableGameBoardWidthInMeters + borderWidthInMeters) * gameBoardTransform.forward) / contentScaleFactor,
879 Quaternion.Euler(gameBoardSettings.gameBoardRotation),
880 Vector3.one / contentScaleFactor );
881 using (
new GizmoReferenceFrame(mtxWorld * mtxPreTransform))
883 Gizmos.DrawMesh(meshRuler, 0 );
887 mtxPreTransform = Matrix4x4.TRS( Vector3.zero, Quaternion.Euler(0.0f, 90.0f, 0.0f), Vector3.one * usableGameBoardWidthInMeters);
888 mtxWorld = Matrix4x4.TRS(gameboardCenter + (0.5f * (usableGameBoardWidthInMeters + borderWidthInMeters) * gameBoardTransform.right) / contentScaleFactor,
889 Quaternion.Euler(gameBoardSettings.gameBoardRotation),
890 Vector3.one / contentScaleFactor );
891 using (
new GizmoReferenceFrame(mtxWorld * mtxPreTransform))
893 Gizmos.DrawMesh(meshRuler, 0 );
897 mtxWorld = Matrix4x4.TRS(gameboardCenter - (0.5f * (usableGameBoardWidthInMeters + borderWidthInMeters) * gameBoardTransform.right) / contentScaleFactor,
898 Quaternion.Euler(gameBoardSettings.gameBoardRotation),
899 Vector3.one / contentScaleFactor );
900 using (
new GizmoReferenceFrame(mtxWorld * mtxPreTransform))
902 Gizmos.DrawMesh(meshRuler, 0 );
GameboardType
The type of Gameboard being tracked by the glasses.