override public void EnableTool(bool bEnable) { base.EnableTool(bEnable); m_PreviewSegment.renderer.enabled = false; m_ExtendPath = null; m_ExtendPathType = ExtendPathType.None; }
override protected void Awake() { base.Awake(); m_PathWidget = WidgetManager.m_Instance.GetNthActiveCameraPath(m_PathNumber); // We need to set m_CommandParam so we're properly highlighted in // SketchControlsScript.IsCommandActive. if (m_PathWidget != null) { int?index = WidgetManager.m_Instance.GetIndexOfCameraPath(m_PathWidget); if (index == null) { throw new ArgumentException("SelectCameraPathButton m_PathWidget index invalid."); } m_CommandParam = index.Value; } else { m_CommandParam = -1; } // Count the number of active camera paths at the time we were created. // Note that this caching method is ok in this instance because these buttons are transient. var datas = WidgetManager.m_Instance.CameraPathWidgets; m_NumActivePaths = 0; foreach (TypedWidgetData <CameraPathWidget> data in datas) { ++m_NumActivePaths; } }
override public void HideTool(bool hide) { base.HideTool(hide); RefreshMeshVisibility(); m_PreviewSegment.renderer.enabled = false; m_ExtendPath = null; m_ExtendPathType = ExtendPathType.None; }
// Adds a path knot of type knotType to the path owned by widget at the // transform defined by spawnXf. public CreatePathKnotCommand(CameraPathWidget widget, CameraPathKnot.Type knotType, PathT pathT, TrTransform spawnXf, BaseCommand parent = null) : base(parent) { m_Widget = widget; m_KnotType = knotType; m_SpawnXf = spawnXf; m_PathT = pathT; }
override protected void UpdateVisuals() { base.UpdateVisuals(); CameraPathWidget cpw = WidgetManager.m_Instance.GetCurrentCameraPath().WidgetScript; if (cpw != null) { cpw.HighlightEntirePath(); } }
override protected void OnButtonPressed() { // Create a new path if we pressed the + icon. if (m_NumActivePaths == m_PathNumber) { m_PathWidget = WidgetManager.m_Instance.CreatePathWidget(); SketchSurfacePanel.m_Instance.EnableSpecificTool(BaseTool.ToolType.CameraPathTool); App.Switchboard.TriggerCameraPathModeChanged(CameraPathTool.Mode.AddPositionKnot); } WidgetManager.m_Instance.CameraPathsVisible = true; WidgetManager.m_Instance.SetCurrentCameraPath(m_PathWidget); SketchControlsScript.m_Instance.EatGazeObjectInput(); }
public RemovePathKnotCommand(CameraPathWidget widget, CameraPathKnot knot, TrTransform removeXf, BaseCommand parent = null) : base(parent) { Knot = knot; m_Widget = widget; m_RemovedXf = removeXf; // If we're removing a position knot, remember its ordered index. This is necessary // because it's probable that the path will change after removal and Undo won't be able // to place the knot back on the path at the current position. if (Knot.KnotType == CameraPathKnot.Type.Position) { m_KnotIndex = m_Widget.Path.PositionKnots.IndexOf((CameraPathPositionKnot)Knot); m_PathT = new PathT(); } else { m_PathT = Knot.PathT; } }
public static void DrawCameraPath(int index) { CameraPathWidget widget = WidgetManager.m_Instance.CameraPathWidgets.ElementAt(index).WidgetScript; CameraPath path = widget.Path; var positions = new List <Vector3>(); var rotations = new List <Quaternion>(); for (float t = 0; t < path.Segments.Count; t += .1f) { positions.Add(path.GetPosition(new PathT(t))); rotations.Add(path.GetRotation(new PathT(t))); } DrawStrokes.MultiPositionPathsToStrokes( new List <List <Vector3> > { positions }, new List <List <Quaternion> > { rotations }, null, Vector3.zero ); }
override public void LateUpdateTool() { Transform xf = InputManager.Brush.Geometry.ToolAttachPoint; m_RemoveKnot.transform.position = xf.position; m_RemoveKnot.transform.rotation = xf.rotation; if (m_LastPlacedKnot == null) { // Detect point nearest to path and jump to path if close enough. float bestDistance = float.MaxValue; m_PrevLastValidPath = m_LastValidPath; m_LastValidPosition = xf.position; m_LastValidPath = null; GrabWidgetData currentData = WidgetManager.m_Instance.GetCurrentCameraPath(); var datas = WidgetManager.m_Instance.CameraPathWidgets; foreach (TypedWidgetData <CameraPathWidget> data in datas) { CameraPathWidget widget = data.WidgetScript; Debug.AssertFormat(widget != null, "Non-CameraPathWidget in CameraPathWidget list"); // Check our tool attach point against the path. If there is a collision, we're going // to jump the position of our mesh to the point on the path. Vector3?projected = widget.Path.ProjectPositionOntoPath(xf.position); if (projected != null) { float distToProjected = Vector3.Distance(projected.Value, xf.position); if (distToProjected < bestDistance) { bestDistance = distToProjected; m_LastValidPosition = projected.Value; m_LastValidPath = widget; // We reset this here and not above (with m_LastValidPath) because we want the value // to retain as the user moves around beyond the end. It's only when hiding and // interacting with a path do we want it to reset. m_ExtendPath = null; } } // In addition to checking collision with the path, check collision with the end points // of the paths. If the user comes near an end point, but is *not* colliding with the // path, they should be able to extend the length of the path. That is, add a new knot // off the respective end. bool currentWidget = (currentData == null) ? false : currentData.m_WidgetScript == widget; if (currentWidget && m_Mode == Mode.AddPositionKnot) { if (widget.Path.PathLoops) { // We never want to show an extended path when the path loops. m_ExtendPath = null; m_ExtendPathType = ExtendPathType.None; } else { // logic for extending off one end of the path. CameraPath.EndType end = widget.Path.IsPositionNearEnd(xf.position); // If we're not near an end point but we're in loop mode, break out of loop mode. if (end == CameraPath.EndType.None && m_ExtendPathType == ExtendPathType.Loop) { m_ExtendPath = null; m_ExtendPathType = ExtendPathType.None; } else if (end != CameraPath.EndType.None && m_ExtendPathType != ExtendPathType.Loop) { m_ExtendPath = widget; // If we're currently extending our path and we're now close to the other end, // set our extend type to looping. if (widget.Path.NumPositionKnots > 1 && (m_ExtendPathType == ExtendPathType.ExtendAtHead && end == CameraPath.EndType.Tail) || (m_ExtendPathType == ExtendPathType.ExtendAtTail && end == CameraPath.EndType.Head)) { m_ExtendPathType = ExtendPathType.Loop; } else { m_ExtendPathType = (end == CameraPath.EndType.Head) ? ExtendPathType.ExtendAtHead : ExtendPathType.ExtendAtTail; } } } } } m_PositionKnot.transform.position = m_LastValidPosition; m_PositionKnot.transform.rotation = xf.rotation; m_RotationKnot.transform.position = m_LastValidPosition; m_RotationKnot.transform.rotation = xf.rotation; m_SpeedKnot.transform.position = m_LastValidPosition; m_SpeedKnot.transform.rotation = Quaternion.identity; m_FovKnot.transform.position = m_LastValidPosition; m_FovKnot.transform.rotation = Quaternion.identity; // If we're not colliding with a path, but we are colliding with an end, show the preview // segment. if (m_LastValidPath == null && m_ExtendPath != null) { m_PreviewSegment.renderer.enabled = true; m_ExtendPath.Path.RefreshSegmentVisuals(xf.position, m_PreviewSegment, m_ExtendPathType); } else { m_PreviewSegment.renderer.enabled = false; } } else { m_PreviewSegment.renderer.enabled = false; m_PrevLastValidPath = m_LastValidPath; m_LastValidPath = null; } }
override public void UpdateTool() { base.UpdateTool(); // If we're in the recording state, just look for cancel and get out. if (CurrentMode == Mode.Recording) { if (InputManager.m_Instance.GetCommandDown(InputManager.SketchCommands.MenuContextClick)) { SketchControlsScript.m_Instance.CameraPathCaptureRig.StopRecordingPath(false); } return; } var widgets = WidgetManager.m_Instance.CameraPathWidgets; Transform toolAttachXf = InputManager.Brush.Geometry.ToolAttachPoint; bool input = InputManager.m_Instance.GetCommand(InputManager.SketchCommands.Activate); bool inputDown = InputManager.m_Instance.GetCommandDown(InputManager.SketchCommands.Activate); // Tint any path we're intersecting with. if (!input && m_LastValidPath != null && m_Mode != Mode.RemoveKnot) { m_LastValidPath.TintSegments(m_LastValidPosition); } // Initiating input. if (inputDown) { // We clicked, but the path we clicked on isn't the active path. In that case, // switch it to the active path and eat up this input. // Don't do this for removing knots. That input should be explicit. if (m_Mode != Mode.RemoveKnot && m_LastValidPath != null) { GrabWidgetData data = WidgetManager.m_Instance.GetCurrentCameraPath(); bool lastValidIsCurrent = (data == null) ? false : data.m_WidgetScript == m_LastValidPath; if (!lastValidIsCurrent) { WidgetManager.m_Instance.SetCurrentCameraPath(m_LastValidPath); return; } } switch (m_Mode) { case Mode.AddPositionKnot: // Create a new path if none exists or if we're trying to add a position point // in a place where we're not extending an existing path. if (!WidgetManager.m_Instance.AnyCameraPathWidgetsActive || (m_LastValidPath == null && m_ExtendPath == null)) { m_ExtendPath = WidgetManager.m_Instance.CreatePathWidget(); m_ExtendPathType = ExtendPathType.ExtendAtHead; WidgetManager.m_Instance.SetCurrentCameraPath(m_ExtendPath); } if (m_LastValidPath != null) { m_LastValidPath.AddPathConstrainedKnot( CameraPathKnot.Type.Position, m_LastValidPosition, toolAttachXf.rotation); m_LastPlacedKnot = m_LastValidPath.Path.LastPlacedKnotInfo; m_LastPlacedKnotPath = m_LastValidPath; } else if (m_ExtendPath != null) { // Manipulation of a path we wish to extend. m_ExtendPath.ExtendPath(toolAttachXf.position, m_ExtendPathType); // Remember the index of the path we just added to, so we can manipulate it // while input is held. // Don't record this if we just made our path loop. if (!m_ExtendPath.Path.PathLoops) { m_LastPlacedKnot = m_ExtendPath.Path.LastPlacedKnotInfo; m_LastPlacedKnotPath = m_ExtendPath; } } break; case Mode.AddRotationKnot: if (m_LastValidPath != null) { m_LastValidPath.AddPathConstrainedKnot( CameraPathKnot.Type.Rotation, m_LastValidPosition, toolAttachXf.rotation); m_LastPlacedKnot = m_LastValidPath.Path.LastPlacedKnotInfo; m_LastPlacedKnotPath = m_LastValidPath; } break; case Mode.AddSpeedKnot: if (m_LastValidPath != null) { m_LastValidPath.AddPathConstrainedKnot( CameraPathKnot.Type.Speed, m_LastValidPosition, toolAttachXf.rotation); m_LastPlacedKnot = m_LastValidPath.Path.LastPlacedKnotInfo; m_LastPlacedKnotPath = m_LastValidPath; } break; case Mode.AddFovKnot: if (m_LastValidPath != null) { m_LastValidPath.AddPathConstrainedKnot( CameraPathKnot.Type.Fov, m_LastValidPosition, toolAttachXf.rotation); m_LastPlacedKnot = m_LastValidPath.Path.LastPlacedKnotInfo; m_LastPlacedKnotPath = m_LastValidPath; } break; case Mode.RemoveKnot: CheckToRemoveKnot(toolAttachXf.position); break; } // Remember what our controller looked like so we can manipulate this knot. if (m_LastPlacedKnot != null) { Transform controller = InputManager.Brush.Transform; Transform knotXf = m_LastPlacedKnot.knot.transform; TrTransform newWidgetXf = Coords.AsGlobal[knotXf]; m_LastPlacedKnotXf_LS = Coords.AsGlobal[controller].inverse * newWidgetXf; HideAllMeshes(); } } else if (input) { if (m_Mode == Mode.RemoveKnot) { CheckToRemoveKnot(toolAttachXf.position); } else if (m_LastPlacedKnot != null) { // Holding input from last frame can allow us to manipulate a just placed position knot. WidgetManager.m_Instance.PathTinter.TintKnot(m_LastPlacedKnot.knot); TrTransform controllerXf = Coords.AsGlobal[InputManager.Brush.Transform]; TrTransform inputXf = controllerXf * m_LastPlacedKnotXf_LS; switch (m_LastPlacedKnot.knot.KnotType) { case CameraPathKnot.Type.Position: if (m_LastPlacedKnot.control != 0) { CameraPathPositionKnot pk = m_LastPlacedKnot.knot as CameraPathPositionKnot; float tangentMag = pk.GetTangentMagnitudeFromControlXf(inputXf); Vector3 knotFwd = (inputXf.translation - m_LastPlacedKnot.knot.transform.position).normalized; if ((CameraPathPositionKnot.ControlType)m_LastPlacedKnot.control == CameraPathPositionKnot.ControlType.TangentControlBack) { knotFwd *= -1.0f; } SketchMemoryScript.m_Instance.PerformAndRecordCommand( new ModifyPositionKnotCommand( m_LastPlacedKnotPath.Path, m_LastPlacedKnot, tangentMag, knotFwd, mergesWithCreateCommand: true)); } break; case CameraPathKnot.Type.Rotation: // Rotation knots hide when we grab them, and in their place, we set the preview widget. m_LastPlacedKnot.knot.gameObject.SetActive(false); SketchControlsScript.m_Instance.CameraPathCaptureRig.OverridePreviewWidgetPathT( m_LastPlacedKnot.knot.PathT); SketchMemoryScript.m_Instance.PerformAndRecordCommand( new MoveConstrainedKnotCommand(m_LastPlacedKnotPath.Path, m_LastPlacedKnot, inputXf.rotation, mergesWithCreateCommand: true)); break; case CameraPathKnot.Type.Speed: CameraPathSpeedKnot sk = m_LastPlacedKnot.knot as CameraPathSpeedKnot; float speed = sk.GetSpeedValueFromY( InputManager.Brush.Behavior.PointerAttachPoint.transform.position.y); SketchMemoryScript.m_Instance.PerformAndRecordCommand( new ModifySpeedKnotCommand(sk, speed, mergesWithCreateCommand: true)); break; case CameraPathKnot.Type.Fov: CameraPathFovKnot fk = m_LastPlacedKnot.knot as CameraPathFovKnot; float fov = fk.GetFovValueFromY( InputManager.Brush.Behavior.PointerAttachPoint.transform.position.y); SketchMemoryScript.m_Instance.PerformAndRecordCommand( new ModifyFovKnotCommand(fk, fov, mergesWithCreateCommand: true)); break; } } } else { // No input to work with. Forget we had anything and make sure our meshes are showing. if (m_LastPlacedKnot != null) { RefreshMeshVisibility(); // Rotation knots hide when we grab them, make sure it's enabled. if (m_LastPlacedKnot.knot.KnotType == CameraPathKnot.Type.Rotation) { m_LastPlacedKnot.knot.gameObject.SetActive(true); SketchControlsScript.m_Instance.CameraPathCaptureRig.OverridePreviewWidgetPathT(null); } } m_LastPlacedKnot = null; m_LastPlacedKnotPath = null; } }
void CacheCurrentPathWidget() { var data = WidgetManager.m_Instance.GetCurrentCameraPath(); m_CurrentPathWidget = (data == null) ? null : data.WidgetScript; }
static public void CreateFromSaveData(CameraPathMetadata cameraPath) { // Create a new widget. CameraPathWidget widget = Instantiate<CameraPathWidget>( WidgetManager.m_Instance.CameraPathWidgetPrefab); widget.transform.parent = App.Scene.MainCanvas.transform; // The scale of path widgets is arbitrary. However, the scale should be one at creation // time so the knots added below have appropriate mesh scales. widget.transform.localScale = Vector3.one; widget.transform.localPosition = Vector3.zero; widget.transform.localRotation = Quaternion.identity; // Add the path knots and set their tangent speed. for (int i = 0; i < cameraPath.PathKnots.Length; ++i) { GameObject go = Instantiate<GameObject>( WidgetManager.m_Instance.CameraPathPositionKnotPrefab); go.transform.position = cameraPath.PathKnots[i].Xf.translation; go.transform.rotation = cameraPath.PathKnots[i].Xf.rotation; go.transform.parent = widget.transform; CameraPathPositionKnot knot = go.GetComponent<CameraPathPositionKnot>(); knot.TangentMagnitude = cameraPath.PathKnots[i].TangentMagnitude; widget.m_Path.PositionKnots.Add(knot); widget.m_Path.AllKnots.Add(knot); if (i > 0) { widget.m_Path.Segments.Add(CameraPath.CreateSegment(widget.transform)); } } // Refresh the path so the segment curves are correct. for (int i = 0; i < cameraPath.PathKnots.Length - 1; ++i) { widget.m_Path.RefreshSegment(i); } // Add the rotation knots. Note this list is ordered, and they're serialized in order, // so we need to make sure they're created in order. for (int i = 0; i < cameraPath.RotationKnots.Length; ++i) { GameObject go = Instantiate<GameObject>( WidgetManager.m_Instance.CameraPathRotationKnotPrefab); go.transform.position = cameraPath.RotationKnots[i].Xf.translation; go.transform.rotation = cameraPath.RotationKnots[i].Xf.rotation; go.transform.parent = widget.transform; CameraPathRotationKnot knot = go.GetComponent<CameraPathRotationKnot>(); knot.PathT = new PathT(cameraPath.RotationKnots[i].PathTValue); knot.DistanceAlongSegment = widget.m_Path.GetSegmentDistanceToT(knot.PathT); widget.m_Path.RotationKnots.Add(knot); widget.m_Path.AllKnots.Add(knot); } // Align quaternions on all rotation knots so we don't have unexpected camera flips // when calculating rotation as we walk the path. widget.m_Path.RefreshRotationKnotPolarities(); // Add the speed knots. Note this list is ordered, and they're serialized in order, // so we need to make sure they're created in order. for (int i = 0; i < cameraPath.SpeedKnots.Length; ++i) { GameObject go = Instantiate<GameObject>( WidgetManager.m_Instance.CameraPathSpeedKnotPrefab); go.transform.position = cameraPath.SpeedKnots[i].Xf.translation; go.transform.rotation = cameraPath.SpeedKnots[i].Xf.rotation; go.transform.parent = widget.transform; CameraPathSpeedKnot knot = go.GetComponent<CameraPathSpeedKnot>(); knot.PathT = new PathT(cameraPath.SpeedKnots[i].PathTValue); knot.DistanceAlongSegment = widget.m_Path.GetSegmentDistanceToT(knot.PathT); knot.SpeedValue = cameraPath.SpeedKnots[i].Speed; widget.m_Path.SpeedKnots.Add(knot); widget.m_Path.AllKnots.Add(knot); } // Add the fov knots. Note this list is ordered, and they're serialized in order, // so we need to make sure they're created in order. for (int i = 0; i < cameraPath.FovKnots.Length; ++i) { GameObject go = Instantiate<GameObject>( WidgetManager.m_Instance.CameraPathFovKnotPrefab); go.transform.position = cameraPath.FovKnots[i].Xf.translation; go.transform.rotation = cameraPath.FovKnots[i].Xf.rotation; go.transform.parent = widget.transform; CameraPathFovKnot knot = go.GetComponent<CameraPathFovKnot>(); knot.PathT = new PathT(cameraPath.FovKnots[i].PathTValue); knot.DistanceAlongSegment = widget.m_Path.GetSegmentDistanceToT(knot.PathT); knot.FovValue = cameraPath.FovKnots[i].Fov; widget.m_Path.FovKnots.Add(knot); widget.m_Path.AllKnots.Add(knot); } // Refresh visuals on the whole path. for (int i = 0; i < widget.m_Path.AllKnots.Count; ++i) { widget.m_Path.AllKnots[i].RefreshVisuals(); widget.m_Path.AllKnots[i].ActivateTint(false); widget.m_Path.AllKnots[i].SetActivePathVisuals(false); } // And turn them off. widget.m_Path.ValidatePathLooping(); widget.m_Path.SetKnotsActive(false); App.Switchboard.TriggerCameraPathCreated(); }