// /****************************************************************************** // * File: CurvedLineRendererPencil.cs // * Copyright (c) 2023 Qualcomm Technologies, Inc. and/or its subsidiaries. All rights reserved. // * // * // ******************************************************************************/ using System.Collections.Generic; using UnityEngine; using UnityEngine.Rendering; namespace QCHT.Samples.Drawing { /// /// Pen tool which draws a smooth curved line renderer. /// public sealed class CurvedLineRendererPencil : Pen { [Header("Curve settings")] [SerializeField] private float distanceNewPoint = 0.1f; [SerializeField] private float lineSegmentSize = 0.08f; [SerializeField] private int cornerVertices = 1; [SerializeField] private int capVertices = 1; /// /// Current points of the current drawing curved line. /// private readonly List _currentLeftCurvedLinePoints = new List(); private readonly List _currentRightCurvedLinePoints = new List(); /// /// Designates the next point to validate in the curve. /// While the distance between the last and this point is under distanceNewPoint value, /// then this point is not frozen in the drawing curve. /// private Vector3 _nextLeftPoint; private Vector3 _nextRightPoint; private CurvedLineRenderer _currentLeftCurvedLineRenderer; private CurvedLineRenderer _currentRightCurvedLineRenderer; #region Pen Overrides protected override void OnPenDown(bool isLeft) { var curvedLineRenderer = InstantiateCurvedLine(); if (isLeft) { _currentLeftCurvedLineRenderer = curvedLineRenderer; _currentLeftCurvedLinePoints.Clear(); UpdateNextPointPosition(pencilLeftPointer, ref _nextLeftPoint); SaveNextPoint(_currentLeftCurvedLinePoints, _nextLeftPoint); } else { _currentRightCurvedLineRenderer = curvedLineRenderer; _currentRightCurvedLinePoints.Clear(); UpdateNextPointPosition(pencilRightPointer, ref _nextRightPoint); SaveNextPoint(_currentRightCurvedLinePoints, _nextRightPoint); } } protected override void OnPenUp(bool isLeft) { // Do nothing here. } protected override void OnPenDrawingUpdate(bool isLeft) { var curvedLineRenderer = isLeft ? _currentLeftCurvedLineRenderer : _currentRightCurvedLineRenderer; var curvedLinePoints = isLeft ? _currentLeftCurvedLinePoints : _currentRightCurvedLinePoints; var pencilPointer = isLeft ? pencilLeftPointer : pencilRightPointer; var nextPosition = isLeft ? ref _nextLeftPoint : ref _nextRightPoint; UpdateNextPointPosition(pencilPointer, ref nextPosition); UpdateCurrentLinePoints(curvedLinePoints, nextPosition, distanceNewPoint); UpdateCurrentLineRenderer(curvedLineRenderer, curvedLinePoints, nextPosition); } protected override void OnPenClear() { // Do nothing here. } #endregion /// /// Instantiates a new drawing curved line. /// Stores it in the pencil history. /// private CurvedLineRenderer InstantiateCurvedLine() { var curveObj = new GameObject("CurvedLine"); curveObj.transform.SetParent(transform); var curvedLineRenderer = curveObj.AddComponent(); curvedLineRenderer.LineWidth = _width; curvedLineRenderer.LineSegmentWidth = lineSegmentSize; var lineRenderer = curvedLineRenderer.GetComponent(); lineRenderer.startWidth = _width; lineRenderer.endWidth = _width; lineRenderer.material = _brush.Material; lineRenderer.numCornerVertices = cornerVertices; lineRenderer.numCapVertices = capVertices; lineRenderer.positionCount = 0; lineRenderer.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion; lineRenderer.shadowCastingMode = ShadowCastingMode.Off; lineRenderer.receiveShadows = false; if (_brush.Type == BrushDescriptor.ColorType.PlainColor) { lineRenderer.startColor = _brush.Color; lineRenderer.endColor = _brush.Color; } else { lineRenderer.colorGradient = _brush.Gradient; } _pencilLinesHistory.Push(curveObj); return curvedLineRenderer; } /// /// Updates the next point position to the pointer position. /// private static void UpdateNextPointPosition(PencilPointer pencilPointer, ref Vector3 nextPoint) { nextPoint = pencilPointer.transform.position; } /// /// Stores the next point into the frozen positions table. /// private static void SaveNextPoint(List curvedLinePoints, Vector3 nextLinePoint) { curvedLinePoints.Add(nextLinePoint); } /// /// Updates the current line frozen points by checking the distance from the last and the next position. /// private static void UpdateCurrentLinePoints(List curvedLinePoints, Vector3 nextLinePoint, float distanceToNewPoint) { var lastPosition = curvedLinePoints[curvedLinePoints.Count - 1]; if (Vector3.Distance(lastPosition, nextLinePoint) > distanceToNewPoint) SaveNextPoint(curvedLinePoints, nextLinePoint); } /// /// Created a concat table of the frozen positions and the potential next frozen position. /// Sends these positions to the curved line renderer. /// private static void UpdateCurrentLineRenderer(CurvedLineRenderer curvedLineRenderer, List curvedLinePoints, Vector3 nextPosition) { if (!curvedLineRenderer) return; var points = new Vector3[curvedLinePoints.Count + 1]; for (var i = 0; i < curvedLinePoints.Count; i++) { points[i] = curvedLinePoints[i]; } points[curvedLinePoints.Count] = nextPosition; curvedLineRenderer.SetPositions(points); } } }