CurvedLineRendererPencil.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. // /******************************************************************************
  2. // * File: CurvedLineRendererPencil.cs
  3. // * Copyright (c) 2023 Qualcomm Technologies, Inc. and/or its subsidiaries. All rights reserved.
  4. // *
  5. // *
  6. // ******************************************************************************/
  7. using System.Collections.Generic;
  8. using UnityEngine;
  9. using UnityEngine.Rendering;
  10. namespace QCHT.Samples.Drawing
  11. {
  12. /// <summary>
  13. /// Pen tool which draws a smooth curved line renderer.
  14. /// </summary>
  15. public sealed class CurvedLineRendererPencil : Pen
  16. {
  17. [Header("Curve settings")]
  18. [SerializeField] private float distanceNewPoint = 0.1f;
  19. [SerializeField] private float lineSegmentSize = 0.08f;
  20. [SerializeField] private int cornerVertices = 1;
  21. [SerializeField] private int capVertices = 1;
  22. /// <summary>
  23. /// Current points of the current drawing curved line.
  24. /// </summary>
  25. private readonly List<Vector3> _currentLeftCurvedLinePoints = new List<Vector3>();
  26. private readonly List<Vector3> _currentRightCurvedLinePoints = new List<Vector3>();
  27. /// <summary>
  28. /// Designates the next point to validate in the curve.
  29. /// While the distance between the last and this point is under distanceNewPoint value,
  30. /// then this point is not frozen in the drawing curve.
  31. /// </summary>
  32. private Vector3 _nextLeftPoint;
  33. private Vector3 _nextRightPoint;
  34. private CurvedLineRenderer _currentLeftCurvedLineRenderer;
  35. private CurvedLineRenderer _currentRightCurvedLineRenderer;
  36. #region Pen Overrides
  37. protected override void OnPenDown(bool isLeft)
  38. {
  39. var curvedLineRenderer = InstantiateCurvedLine();
  40. if (isLeft)
  41. {
  42. _currentLeftCurvedLineRenderer = curvedLineRenderer;
  43. _currentLeftCurvedLinePoints.Clear();
  44. UpdateNextPointPosition(pencilLeftPointer, ref _nextLeftPoint);
  45. SaveNextPoint(_currentLeftCurvedLinePoints, _nextLeftPoint);
  46. }
  47. else
  48. {
  49. _currentRightCurvedLineRenderer = curvedLineRenderer;
  50. _currentRightCurvedLinePoints.Clear();
  51. UpdateNextPointPosition(pencilRightPointer, ref _nextRightPoint);
  52. SaveNextPoint(_currentRightCurvedLinePoints, _nextRightPoint);
  53. }
  54. }
  55. protected override void OnPenUp(bool isLeft)
  56. {
  57. // Do nothing here.
  58. }
  59. protected override void OnPenDrawingUpdate(bool isLeft)
  60. {
  61. var curvedLineRenderer = isLeft ? _currentLeftCurvedLineRenderer : _currentRightCurvedLineRenderer;
  62. var curvedLinePoints = isLeft ? _currentLeftCurvedLinePoints : _currentRightCurvedLinePoints;
  63. var pencilPointer = isLeft ? pencilLeftPointer : pencilRightPointer;
  64. var nextPosition = isLeft ? ref _nextLeftPoint : ref _nextRightPoint;
  65. UpdateNextPointPosition(pencilPointer, ref nextPosition);
  66. UpdateCurrentLinePoints(curvedLinePoints, nextPosition, distanceNewPoint);
  67. UpdateCurrentLineRenderer(curvedLineRenderer, curvedLinePoints, nextPosition);
  68. }
  69. protected override void OnPenClear()
  70. {
  71. // Do nothing here.
  72. }
  73. #endregion
  74. /// <summary>
  75. /// Instantiates a new drawing curved line.
  76. /// Stores it in the pencil history.
  77. /// </summary>
  78. private CurvedLineRenderer InstantiateCurvedLine()
  79. {
  80. var curveObj = new GameObject("CurvedLine");
  81. curveObj.transform.SetParent(transform);
  82. var curvedLineRenderer = curveObj.AddComponent<CurvedLineRenderer>();
  83. curvedLineRenderer.LineWidth = _width;
  84. curvedLineRenderer.LineSegmentWidth = lineSegmentSize;
  85. var lineRenderer = curvedLineRenderer.GetComponent<LineRenderer>();
  86. lineRenderer.startWidth = _width;
  87. lineRenderer.endWidth = _width;
  88. lineRenderer.material = _brush.Material;
  89. lineRenderer.numCornerVertices = cornerVertices;
  90. lineRenderer.numCapVertices = capVertices;
  91. lineRenderer.positionCount = 0;
  92. lineRenderer.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion;
  93. lineRenderer.shadowCastingMode = ShadowCastingMode.Off;
  94. lineRenderer.receiveShadows = false;
  95. if (_brush.Type == BrushDescriptor.ColorType.PlainColor)
  96. {
  97. lineRenderer.startColor = _brush.Color;
  98. lineRenderer.endColor = _brush.Color;
  99. }
  100. else
  101. {
  102. lineRenderer.colorGradient = _brush.Gradient;
  103. }
  104. _pencilLinesHistory.Push(curveObj);
  105. return curvedLineRenderer;
  106. }
  107. /// <summary>
  108. /// Updates the next point position to the pointer position.
  109. /// </summary>
  110. private static void UpdateNextPointPosition(PencilPointer pencilPointer, ref Vector3 nextPoint)
  111. {
  112. nextPoint = pencilPointer.transform.position;
  113. }
  114. /// <summary>
  115. /// Stores the next point into the frozen positions table.
  116. /// </summary>
  117. private static void SaveNextPoint(List<Vector3> curvedLinePoints, Vector3 nextLinePoint)
  118. {
  119. curvedLinePoints.Add(nextLinePoint);
  120. }
  121. /// <summary>
  122. /// Updates the current line frozen points by checking the distance from the last and the next position.
  123. /// </summary>
  124. private static void UpdateCurrentLinePoints(List<Vector3> curvedLinePoints, Vector3 nextLinePoint,
  125. float distanceToNewPoint)
  126. {
  127. var lastPosition = curvedLinePoints[curvedLinePoints.Count - 1];
  128. if (Vector3.Distance(lastPosition, nextLinePoint) > distanceToNewPoint)
  129. SaveNextPoint(curvedLinePoints, nextLinePoint);
  130. }
  131. /// <summary>
  132. /// Created a concat table of the frozen positions and the potential next frozen position.
  133. /// Sends these positions to the curved line renderer.
  134. /// </summary>
  135. private static void UpdateCurrentLineRenderer(CurvedLineRenderer curvedLineRenderer,
  136. List<Vector3> curvedLinePoints, Vector3 nextPosition)
  137. {
  138. if (!curvedLineRenderer)
  139. return;
  140. var points = new Vector3[curvedLinePoints.Count + 1];
  141. for (var i = 0; i < curvedLinePoints.Count; i++)
  142. {
  143. points[i] = curvedLinePoints[i];
  144. }
  145. points[curvedLinePoints.Count] = nextPosition;
  146. curvedLineRenderer.SetPositions(points);
  147. }
  148. }
  149. }