void Start() { // Disable the pointer graphic (until the user holds down on the touchpad) Pointer.enabled = false; // Ensure we mark the player as not teleporting CurrentTeleportState = TeleportStateNick.None; // Standard plane mesh used for "fade out" graphic when you teleport // This way you don't need to supply a simple plane mesh in the inspector PlaneMesh = new Mesh(); Vector3[] verts = new Vector3[] { new Vector3(-1, -1, 0), new Vector3(-1, 1, 0), new Vector3(1, 1, 0), new Vector3(1, -1, 0) }; int[] elts = new int[] { 0, 1, 2, 0, 2, 3 }; PlaneMesh.vertices = verts; PlaneMesh.triangles = elts; PlaneMesh.RecalculateBounds(); if (FadeMaterial != null) { FadeMaterialInstance = new Material(FadeMaterial); } // Set some standard variables MaterialFadeID = Shader.PropertyToID("_Fade"); EnabledAnimatorID = Animator.StringToHash("Enabled"); RoomBorder = GetComponent <BorderRenderer>(); Vector3 p0, p1, p2, p3; if (GetChaperoneBounds(out p0, out p1, out p2, out p3)) { // Rotate to match camera rig rotation var originRotationMatrix = Matrix4x4.TRS(Vector3.zero, OriginTransform.rotation, Vector3.one); BorderPointSet p = new BorderPointSet(new Vector3[] { originRotationMatrix *p0, originRotationMatrix *p1, originRotationMatrix *p2, originRotationMatrix *p3, originRotationMatrix *p0, }); RoomBorder.Points = new BorderPointSet[] { p }; } RoomBorder.enabled = false; }
void Update() { // If we are currently teleporting (ie handling the fade in/out transition)... if (CurrentTeleportState == TeleportStateNick.Teleporting) { // Wait until half of the teleport time has passed before the next event (note: both the switch from fade // out to fade in and the switch from fade in to stop the animation is half of the fade duration) if (Time.time - TeleportTimeMarker >= TeleportFadeDuration / 2) { if (FadingIn) { // We have finished fading in CurrentTeleportState = TeleportStateNick.None; } else { // We have finished fading out - time to teleport! Vector3 offset = OriginTransform.position - HeadTransform.position; offset.y = 0; OriginTransform.position = Pointer.SelectedPoint + offset; } TeleportTimeMarker = Time.time; FadingIn = !FadingIn; } } // At this point, we are NOT actively teleporting. So now we care about controller input. else if (CurrentTeleportState == TeleportStateNick.Selecting) { Debug.Assert(ActiveController != null); // Here, there is an active controller - that is, the user is holding down on the trackpad. // Poll controller for pertinent button data int index = (int)ActiveController.controller.index; var device = SteamVR_Controller.Input(index); bool shouldTeleport = device.GetPressUp(SteamVR_Controller.ButtonMask.Touchpad); bool shouldCancel = device.GetPressUp(SteamVR_Controller.ButtonMask.Grip); if (shouldTeleport || shouldCancel) { // If the user has decided to teleport (ie lets go of touchpad) then remove all visual indicators // related to selecting things and actually teleport // If the user has decided to cancel (ie squeezes grip button) then remove visual indicators and do nothing if (shouldTeleport && Pointer.PointOnNavMesh) { // Begin teleport sequence CurrentTeleportState = TeleportStateNick.Teleporting; TeleportTimeMarker = Time.time; } else { CurrentTeleportState = TeleportStateNick.None; } // Reset active controller, disable pointer, disable visual indicators ActiveController = null; Pointer.enabled = false; RoomBorder.enabled = false; //RoomBorder.Transpose = Matrix4x4.TRS(OriginTransform.position, Quaternion.identity, Vector3.one); if (NavmeshAnimator != null) { NavmeshAnimator.SetBool(EnabledAnimatorID, false); } Pointer.transform.parent = null; Pointer.transform.position = Vector3.zero; Pointer.transform.rotation = Quaternion.identity; Pointer.transform.localScale = Vector3.one; } else { // The user is still deciding where to teleport and has the touchpad held down. // Note: rendering of the parabolic pointer / marker is done in ParabolicPointer Vector3 offset = HeadTransform.position - OriginTransform.position; offset.y = 0; // Render representation of where the chaperone bounds will be after teleporting RoomBorder.enabled = Pointer.PointOnNavMesh; RoomBorder.Transpose = Matrix4x4.TRS(Pointer.SelectedPoint - offset, Quaternion.identity, Vector3.one); // Haptic feedback click every [HaptickClickAngleStep] degrees if (Pointer.CurrentParabolaAngleY >= 45) // Don't click when at max degrees { LastClickAngle = Pointer.CurrentPointVector; } float angleClickDiff = Vector3.Angle(LastClickAngle, Pointer.CurrentPointVector); if (IsClicking && Mathf.Abs(angleClickDiff) > HapticClickAngleStep) { LastClickAngle = Pointer.CurrentPointVector; if (Pointer.PointOnNavMesh) { device.TriggerHapticPulse(); } } // Trigger a stronger haptic pulse when "entering" a teleportable surface if (Pointer.PointOnNavMesh && !IsClicking) { IsClicking = true; device.TriggerHapticPulse(750); LastClickAngle = Pointer.CurrentPointVector; } else if (!Pointer.PointOnNavMesh && IsClicking) { IsClicking = false; } } } else //CurrentTeleportState == TeleportState.None { // At this point the user is not holding down on the touchpad at all or has canceled a teleport and hasn't // let go of the touchpad. So we wait for the user to press the touchpad and enable visual indicators // if necessary. foreach (Valve.VR.InteractionSystem.Hand obj in Controllers) { if (obj.controller == null) { continue; } int index = (int)obj.controller.index; if (index == -1) { continue; } var device = SteamVR_Controller.Input(index); if (device.GetPressDown(SteamVR_Controller.ButtonMask.Touchpad)) { // Set active controller to this controller, and enable the parabolic pointer and visual indicators // that the user can use to determine where they are able to teleport. ActiveController = obj; Pointer.transform.parent = obj.transform; Pointer.transform.localPosition = Vector3.zero; Pointer.transform.localRotation = Quaternion.identity; Pointer.transform.localScale = Vector3.one; Pointer.enabled = true; CurrentTeleportState = TeleportStateNick.Selecting; if (NavmeshAnimator != null) { NavmeshAnimator.SetBool(EnabledAnimatorID, true); } Pointer.ForceUpdateCurrentAngle(); LastClickAngle = Pointer.CurrentPointVector; IsClicking = Pointer.PointOnNavMesh; } } } }