Esempio n. 1
0
        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;
            }
        }
Esempio n. 2
0
  override public void RecordAndSetPosRot(TrTransform inputXf) {
    // Don't manipulate anything if we're eating input.
    if (m_EatInteractingInput) {
      return;
    }

    SnapEnabled = (m_ActiveKnot.knot.KnotType == CameraPathKnot.Type.Rotation ||
                   m_ActiveKnot.knot.KnotType == CameraPathKnot.Type.Position) &&
                  InputManager.Controllers[(int)m_InteractingController].GetCommand(
                      InputManager.SketchCommands.MenuContextClick);
    inputXf = GetDesiredTransform(inputXf);

    if (m_ActiveKnot.knot.KnotType == CameraPathKnot.Type.Position) {
      // Move the base knot.
      if (m_ActiveKnot.control == 0) {
        // If this knot is the tail or the head and we're within snapping distance of the other
        // end, snap to the transform.
        TrTransform snappedXf = inputXf;
        int positionKnot = m_ActiveKnot.positionKnotIndex.Value;
        if (positionKnot == 0 || positionKnot == Path.NumPositionKnots - 1) {
          int otherIndex = positionKnot == 0 ? Path.NumPositionKnots - 1 : 0;
          float distToOther = Vector3.Distance(inputXf.translation,
              Path.PositionKnots[otherIndex].KnotXf.position);
          if (distToOther < m_KnotSnapDistanceToEnd) {
            snappedXf.translation = Path.PositionKnots[otherIndex].KnotXf.position;
            snappedXf.rotation = Path.PositionKnots[otherIndex].KnotXf.rotation;
          }
        }

        SketchMemoryScript.m_Instance.PerformAndRecordCommand(
            new MovePositionKnotCommand(m_Path, m_ActiveKnot, snappedXf));
      } else {
        // Modify the knot tangents.
        CameraPathPositionKnot pk = m_ActiveKnot.knot as CameraPathPositionKnot;
        if (SnapEnabled) {
          Vector3 snappedTranslation = inputXf.translation;
          snappedTranslation.y = pk.transform.position.y;
          inputXf.translation = snappedTranslation;
        }
        float tangentMag = pk.GetTangentMagnitudeFromControlXf(inputXf);
        Vector3 knotFwd = (inputXf.translation - m_ActiveKnot.knot.transform.position).normalized;
        if ((CameraPathPositionKnot.ControlType)m_ActiveKnot.control ==
            CameraPathPositionKnot.ControlType.TangentControlBack) {
          knotFwd *= -1.0f;
        }
        SketchMemoryScript.m_Instance.PerformAndRecordCommand(
            new ModifyPositionKnotCommand(m_Path, m_ActiveKnot, tangentMag, knotFwd));
      }
      return;
    }

    // Constrain rotation and speed knots to the path.
    // Instead of testing the raw value that comes in from the controller position, test our
    // last valid path position plus any translation that's happened the past frame.  This
    // method keeps the test positions near the path, allowing continuous movement when the
    // user has moved beyond the intersection distance to the path.
    Vector3 positionToProject = inputXf.translation;
    if (m_KnotEditingLastInputXf.HasValue) {
      Vector3 translationDiff = inputXf.translation - m_KnotEditingLastInputXf.Value;
      positionToProject = m_ActiveKnot.knot.KnotXf.position + translationDiff;
    }
    m_KnotEditingLastInputXf = inputXf.translation;

    // Project transform on to the path to get t.
    Vector3 error = Vector3.zero;
    if (m_Path.ProjectPositionOnToPath(positionToProject, out PathT pathT, out error)) {
      // Move the base knot.
      if (m_ActiveKnot.control == 0) {
        // Path constrained knots are a little sticky on the ends of the path.  Knots very
        // near the ends *probably* want to be on the ends, and when there are small deltas
        // near the ends, it causes unwanted erratic curves.
        m_ActiveKnot.pathT = m_Path.MaybeSnapPathTToEnd(pathT, m_KnotSnapDistanceToEnd);

        // Rotation knots allow the user to place the preview widget at their position
        // for live preview.
        if (m_ActiveKnot.knot.KnotType == CameraPathKnot.Type.Rotation) {
          CheckForPreviewWidgetOverride(pathT);
        }

        SketchMemoryScript.m_Instance.PerformAndRecordCommand(
            new MoveConstrainedKnotCommand(m_Path, m_ActiveKnot, inputXf.rotation));
      } else {
        // Alternate controls.
        BaseControllerBehavior b = InputManager.Controllers[(int)m_InteractingController].Behavior;
        float controllerY = b.PointerAttachPoint.transform.position.y;

        if (m_ActiveKnot.knot.KnotType == CameraPathKnot.Type.Speed) {
          CameraPathSpeedKnot sk = m_ActiveKnot.knot as CameraPathSpeedKnot;
          float speed = sk.GetSpeedValueFromY(controllerY - m_GrabControlInitialYDiff);
          SketchMemoryScript.m_Instance.PerformAndRecordCommand(
              new ModifySpeedKnotCommand(sk, speed));
        } else if (m_ActiveKnot.knot.KnotType == CameraPathKnot.Type.Fov) {
          CameraPathFovKnot fk = m_ActiveKnot.knot as CameraPathFovKnot;
          float fov = fk.GetFovValueFromY(controllerY - m_GrabControlInitialYDiff);
          CheckForPreviewWidgetOverride(fk.PathT);
          SketchMemoryScript.m_Instance.PerformAndRecordCommand(
              new ModifyFovKnotCommand(fk, fov));
        }
      }
    }
    m_KnotEditingLastInputXf -= error;
  }