diff --git a/Assets/Controller Left.prefab b/Assets/Controller Left.prefab index 94fdb6d..2ce84bc 100755 Binary files a/Assets/Controller Left.prefab and b/Assets/Controller Left.prefab differ diff --git a/Assets/Controller Right.prefab b/Assets/Controller Right.prefab index 451416c..58c2692 100755 Binary files a/Assets/Controller Right.prefab and b/Assets/Controller Right.prefab differ diff --git a/Assets/Furniture Prefabs/Bed 1.prefab b/Assets/Furniture Prefabs/Bed 1.prefab index d699e2d..0442468 100755 Binary files a/Assets/Furniture Prefabs/Bed 1.prefab and b/Assets/Furniture Prefabs/Bed 1.prefab differ diff --git a/Assets/Furniture Prefabs/Bed 2.prefab b/Assets/Furniture Prefabs/Bed 2.prefab index be70164..f0cc03c 100755 Binary files a/Assets/Furniture Prefabs/Bed 2.prefab and b/Assets/Furniture Prefabs/Bed 2.prefab differ diff --git a/Assets/Furniture Prefabs/Sofa 1.prefab b/Assets/Furniture Prefabs/Sofa 1.prefab index eeb9d5c..f8fe04b 100755 Binary files a/Assets/Furniture Prefabs/Sofa 1.prefab and b/Assets/Furniture Prefabs/Sofa 1.prefab differ diff --git a/Assets/FurnitureMiniature.cs b/Assets/FurnitureMiniature.cs new file mode 100755 index 0000000..92aedeb --- /dev/null +++ b/Assets/FurnitureMiniature.cs @@ -0,0 +1,39 @@ +using UnityEngine; +using System.Collections; + +public class FurnitureMiniature : FurnitureObject { + public override void Grab(Transform attachment) { + transform.parent = null; + foreach (var collider in GetComponentsInChildren()) { + collider.enabled = false; + } + GetComponent().isKinematic = true; + + var mini = gameObject.AddComponent(); + mini.DestinationAttachment = attachment; + mini.Duration = 0.33f; + } + + public override void Release() { + var mini = gameObject.GetComponent(); + if (mini) { + mini.End(); + } + + transform.parent = null; + foreach (var collider in GetComponentsInChildren()) { + collider.enabled = true; + } + GetComponent().isKinematic = false; + } + + // Use this for initialization + void Start () { + + } + + // Update is called once per frame + void Update () { + + } +} diff --git a/Assets/FurnitureMiniature.cs.meta b/Assets/FurnitureMiniature.cs.meta new file mode 100755 index 0000000..02ed23a --- /dev/null +++ b/Assets/FurnitureMiniature.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: cc866a4108edf754a94b112e005156e7 +timeCreated: 1464235042 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/FurnitureObject.cs b/Assets/FurnitureObject.cs new file mode 100755 index 0000000..531d03b --- /dev/null +++ b/Assets/FurnitureObject.cs @@ -0,0 +1,7 @@ +using UnityEngine; +using System.Collections; + +public class FurnitureObject : MonoBehaviour { + public virtual void Grab(Transform attachment) { } + public virtual void Release() { } +} diff --git a/Assets/FurnitureObject.cs.meta b/Assets/FurnitureObject.cs.meta new file mode 100755 index 0000000..d2be5e1 --- /dev/null +++ b/Assets/FurnitureObject.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 44b6e16155f118a40b4c700c55978f9d +timeCreated: 1464233125 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/LeftController.cs b/Assets/LeftController.cs index ee75828..d08bbc1 100755 --- a/Assets/LeftController.cs +++ b/Assets/LeftController.cs @@ -5,26 +5,25 @@ public class LeftController : MonoBehaviour { public bool AlwaysCenter = false; + Transform controllerRig; + SteamVR_ControllerEvents controllerEvents; - private Transform controllerRig; - private SteamVR_TrackedController trackedController; + GameObject mainCamera; + GameObject warehouseCamera; - private GameObject mainCamera; - private GameObject warehouseCamera; + CameraFade cameraFade; + SteamVR_Camera mainSteamVRCamera; - private CameraFade cameraFade; - private SteamVR_Camera mainSteamVRCamera; + bool inWarehouse = false; - private bool inWarehouse = false; - - // Use this for initialization - void Start () { + void Awake() { controllerRig = this.transform.parent; - trackedController = GetComponent(); - trackedController.TriggerClicked += TriggerClicked; - trackedController.Gripped += Gripped; + controllerEvents = GetComponent(); + controllerEvents.TriggerAxisChanged += triggerAxisChanged; + } + void Start () { mainCamera = GameObject.Find("Main Camera (origin)"); warehouseCamera = GameObject.Find("Warehouse Camera (origin)"); @@ -32,9 +31,8 @@ public class LeftController : MonoBehaviour { mainSteamVRCamera = mainCamera.GetComponentInChildren(); } - // Update is called once per frame - void Update () { - float alpha = SteamVR_Controller.Input((int)trackedController.controllerIndex).GetAxis(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger).x; + void triggerAxisChanged(object sender, ControllerClickedEventArgs e) { + float alpha = e.buttonPressure; if (alpha > 0.05) { cameraFade.SetFade(alpha); if (!inWarehouse) { @@ -51,15 +49,5 @@ public class LeftController : MonoBehaviour { inWarehouse = false; } } - } - - void TriggerClicked(object sender, ClickedEventArgs e) { - //var warehouseCamera = GameObject.FindWithTag("WarehouseCamera").GetComponent(); - //warehouseCamera.enabled = true; - Debug.Log("awd"); - } - - void Gripped(object sender, ClickedEventArgs e) { - } } diff --git a/Assets/RightController.cs b/Assets/RightController.cs index 3c581f1..f154bf9 100755 --- a/Assets/RightController.cs +++ b/Assets/RightController.cs @@ -1,13 +1,16 @@ using UnityEngine; using System.Collections; +using System; public class RightController : MonoBehaviour { - public GameObject banana; - public GameObject viveController; + public Transform MiniatureAttachmentPoint; - SteamVR_TrackedController trackedController; + SteamVR_LaserPointer laserPointer; + SteamVR_ControllerEvents controllerEvents; WarehouseColumn warehouse; + FurnitureObject heldItem; + WarehouseRow whRow = null; Vector3? whScrollStartPos = null; float whScrollDistance; @@ -17,24 +20,22 @@ public class RightController : MonoBehaviour { float whRowScrollOffset = 0.0f; void Awake() { - trackedController = GetComponent(); - trackedController.TriggerClicked += triggerClicked; - trackedController.TriggerUnclicked += triggerUnclicked; + laserPointer = GetComponent(); + + controllerEvents = GetComponent(); + controllerEvents.TriggerClicked += triggerClicked; + controllerEvents.TriggerUnclicked += triggerUnclicked; + controllerEvents.TouchpadClicked += touchpadClicked; + controllerEvents.TouchpadUnclicked += touchpadUnclicked; warehouse = GameObject.Find("Warehouse/Shelves/Column").GetComponent(); } - void Start () { - GetComponent().LeaveView += toggleBanana; + void Start () { + laserPointer.pointer.layer = 9; } - void toggleBanana() { - banana.SetActive(!banana.activeSelf); - viveController.SetActive(!viveController.activeSelf); - } - void Update () { - // Warehouse scroll if (whScrollStartPos != null) { Vector3 curPos = transform.position + (transform.forward * whScrollDistance); @@ -54,7 +55,12 @@ public class RightController : MonoBehaviour { return hit; } - void triggerClicked(object sender, ClickedEventArgs e) { + // Furniture picking + void triggerClicked(object sender, ControllerClickedEventArgs e) { + if (heldItem != null) { + return; + } + var ray = new Ray(transform.position, transform.forward); RaycastHit result; bool hit = Physics.Raycast(ray, out result); @@ -63,7 +69,34 @@ public class RightController : MonoBehaviour { return; } - var item = result.transform.GetComponent(); + var item = result.transform.GetComponentInParent(); + if (!item) { + return; + } + + item.Grab(MiniatureAttachmentPoint); + heldItem = item; + } + void triggerUnclicked(object sender, ControllerClickedEventArgs e) { + if (heldItem == null) { + return; + } + + heldItem.Release(); + heldItem = null; + } + + // Furniture scrolling by drag + void touchpadClicked(object sender, ControllerClickedEventArgs e) { + var ray = new Ray(transform.position, transform.forward); + RaycastHit result; + bool hit = Physics.Raycast(ray, out result); + + if (!hit) { + return; + } + + var item = result.transform.GetComponentInParent(); if (!item) { return; } @@ -74,8 +107,7 @@ public class RightController : MonoBehaviour { whBaseOffset = warehouse.Offset; whRowBaseOffset = whRow.Offset; } - - void triggerUnclicked(object sender, ClickedEventArgs e) { + void touchpadUnclicked(object sender, ControllerClickedEventArgs e) { if (whScrollStartPos != null) { whScrollStartPos = null; } diff --git a/Assets/SteamVR_Unity_Toolkit.meta b/Assets/SteamVR_Unity_Toolkit.meta new file mode 100755 index 0000000..6467f1f --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5348ca62989d6bc4b9aa25a5b1fd76f6 +folderAsset: yes +timeCreated: 1464192738 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Prefabs.meta b/Assets/SteamVR_Unity_Toolkit/Prefabs.meta new file mode 100755 index 0000000..352c58e --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Prefabs.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 721907082a166594bb4946c03c4e712f +folderAsset: yes +timeCreated: 1461528015 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Prefabs/FramesPerSecondCanvas.prefab b/Assets/SteamVR_Unity_Toolkit/Prefabs/FramesPerSecondCanvas.prefab new file mode 100755 index 0000000..bf8ceec Binary files /dev/null and b/Assets/SteamVR_Unity_Toolkit/Prefabs/FramesPerSecondCanvas.prefab differ diff --git a/Assets/SteamVR_Unity_Toolkit/Prefabs/FramesPerSecondCanvas.prefab.meta b/Assets/SteamVR_Unity_Toolkit/Prefabs/FramesPerSecondCanvas.prefab.meta new file mode 100755 index 0000000..f3499b5 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Prefabs/FramesPerSecondCanvas.prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 39aa6e3f7c442a04d997c9ed23f46981 +timeCreated: 1462698525 +licenseType: Free +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Prefabs/[CameraRig].prefab b/Assets/SteamVR_Unity_Toolkit/Prefabs/[CameraRig].prefab new file mode 100755 index 0000000..cfeb39d Binary files /dev/null and b/Assets/SteamVR_Unity_Toolkit/Prefabs/[CameraRig].prefab differ diff --git a/Assets/SteamVR_Unity_Toolkit/Prefabs/[CameraRig].prefab.meta b/Assets/SteamVR_Unity_Toolkit/Prefabs/[CameraRig].prefab.meta new file mode 100755 index 0000000..01f84a6 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Prefabs/[CameraRig].prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1bb80779de0d85b4bba906974dbaa477 +timeCreated: 1461528558 +licenseType: Free +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts.meta b/Assets/SteamVR_Unity_Toolkit/Scripts.meta new file mode 100755 index 0000000..42613b9 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1931978e1716e50408b878e63b7302ed +folderAsset: yes +timeCreated: 1461529462 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/Abstractions.meta b/Assets/SteamVR_Unity_Toolkit/Scripts/Abstractions.meta new file mode 100755 index 0000000..a2d7a4d --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/Abstractions.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: e265a8da22ede3840b5351cfef43b27b +folderAsset: yes +timeCreated: 1461570982 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/Abstractions/SteamVR_WorldPointer.cs b/Assets/SteamVR_Unity_Toolkit/Scripts/Abstractions/SteamVR_WorldPointer.cs new file mode 100755 index 0000000..6f7e7ac --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/Abstractions/SteamVR_WorldPointer.cs @@ -0,0 +1,358 @@ +//==================================================================================== +// +// Purpose: Provide abstraction into projecting a raycast into the game world. +// As this is an abstract class, it should never be used on it's own. +// +// Events Emitted: +// +// WorldPointerIn - is emitted when the pointer collides with an object +// WorldPointerOut - is emitted when the pointer stops colliding with an object +// WorldPointerDestinationSet - is emmited when the pointer is deactivated +// +// Event Payload: +// +// controllerIndex - The index of the controller the pointer is attached to +// distance - The distance from the collided object the controller is +// target - The Transform of the object the pointer has collided with +// tipPosition - The world position of the beam tip +// +//==================================================================================== + +using UnityEngine; +using System.Collections; + +public struct WorldPointerEventArgs +{ + public uint controllerIndex; + public float distance; + public Transform target; + public Vector3 destinationPosition; + public bool enableTeleport; +} + +public delegate void WorldPointerEventHandler(object sender, WorldPointerEventArgs e); + +public class SteamVR_PlayAreaCollider : MonoBehaviour +{ + private GameObject parent; + + public void SetParent(GameObject setParent) + { + parent = setParent; + } + + void OnTriggerStay(Collider collider) + { + if (parent.GetComponent().IsActive() && !collider.name.Contains("PlayerObject_")) + { + parent.GetComponent().setPlayAreaCursorCollision(true); + } + } + + void OnTriggerExit(Collider collider) + { + if (! collider.name.Contains("PlayerObject_")) { + parent.GetComponent().setPlayAreaCursorCollision(false); + } + } +} + +public abstract class SteamVR_WorldPointer : MonoBehaviour { + public Color pointerHitColor = new Color(0f, 0.5f, 0f, 1f); + public Color pointerMissColor = new Color(0.8f, 0f, 0f, 1f); + public bool showPlayAreaCursor = false; + public Vector2 playAreaCursorDimensions = Vector2.zero; + public bool handlePlayAreaCursorCollisions = false; + public bool enableTeleport = true; + public bool beamAlwaysOn = false; + public float activateDelay = 0f; + + protected Vector3 destinationPosition; + protected float pointerContactDistance = 0f; + protected Transform pointerContactTarget = null; + protected uint controllerIndex; + + protected Material pointerMaterial; + protected bool playAreaCursorCollided = false; + + private SteamVR_PlayArea playArea; + private GameObject playAreaCursor; + private GameObject[] playAreaCursorBoundaries; + private bool isActive; + + private float activateDelayTimer = 0f; + private float updatesPerSecond = 60f; + + public event WorldPointerEventHandler WorldPointerIn; + public event WorldPointerEventHandler WorldPointerOut; + public event WorldPointerEventHandler WorldPointerDestinationSet; + + public virtual void OnWorldPointerIn(WorldPointerEventArgs e) + { + if (WorldPointerIn != null) + WorldPointerIn(this, e); + } + + public virtual void OnWorldPointerOut(WorldPointerEventArgs e) + { + if (WorldPointerOut != null) + WorldPointerOut(this, e); + } + + public virtual void OnWorldPointerDestinationSet(WorldPointerEventArgs e) + { + if (WorldPointerDestinationSet != null) + WorldPointerDestinationSet(this, e); + } + + public virtual void setPlayAreaCursorCollision(bool state) + { + if (handlePlayAreaCursorCollisions) + { + playAreaCursorCollided = state; + } + } + + public virtual bool IsActive() + { + return isActive; + } + + public virtual bool CanActivate() + { + return (activateDelayTimer <= 0); + } + + protected WorldPointerEventArgs SetPointerEvent(uint controllerIndex, float distance, Transform target, Vector3 position) + { + WorldPointerEventArgs e; + e.controllerIndex = controllerIndex; + e.distance = distance; + e.target = target; + e.destinationPosition = position; + e.enableTeleport = enableTeleport; + return e; + } + + protected virtual void Start() + { + if (GetComponent() == null) + { + Debug.LogError("SteamVR_WorldPointer is required to be attached to a SteamVR Controller that has the SteamVR_ControllerEvents script attached to it"); + return; + } + + this.name = "PlayerObject_" + this.name; + + //Setup controller event listeners + GetComponent().AliasPointerOn += new ControllerClickedEventHandler(EnablePointerBeam); + GetComponent().AliasPointerOff += new ControllerClickedEventHandler(DisablePointerBeam); + + playArea = GameObject.FindObjectOfType(); + playAreaCursorBoundaries = new GameObject[4]; + + pointerMaterial = new Material(Shader.Find("Unlit/TransparentColor")); + pointerMaterial.color = pointerMissColor; + } + + protected virtual void Update() + { + if (activateDelayTimer > 0) + { + activateDelayTimer--; + } + } + + protected virtual void InitPointer() + { + InitPlayAreaCursor(); + } + + protected virtual void SetPlayAreaCursorTransform(Vector3 destination) + { + playAreaCursor.transform.position = destination; + } + + protected virtual void EnablePointerBeam(object sender, ControllerClickedEventArgs e) + { + if (!isActive && activateDelayTimer <= 0) + { + setPlayAreaCursorCollision(false); + controllerIndex = e.controllerIndex; + TogglePointer(true); + isActive = true; + } + } + + protected virtual void DisablePointerBeam(object sender, ControllerClickedEventArgs e) + { + if (isActive && activateDelayTimer <= 0) + { + activateDelayTimer = activateDelay * updatesPerSecond; + controllerIndex = e.controllerIndex; + TogglePointer(false); + isActive = false; + } + } + + protected virtual void PointerIn() + { + if (!pointerContactTarget) + { + return; + } + + OnWorldPointerIn(SetPointerEvent(controllerIndex, pointerContactDistance, pointerContactTarget, destinationPosition)); + + SteamVR_InteractableObject interactableObject = pointerContactTarget.GetComponent(); + if (interactableObject && interactableObject.pointerActivatesUseAction && interactableObject.holdButtonToUse) + { + interactableObject.StartUsing(this.gameObject); + } + } + + protected virtual void PointerOut() + { + if (!pointerContactTarget) + { + return; + } + + OnWorldPointerOut(SetPointerEvent(controllerIndex, pointerContactDistance, pointerContactTarget, destinationPosition)); + + SteamVR_InteractableObject interactableObject = pointerContactTarget.GetComponent(); + if (interactableObject && interactableObject.pointerActivatesUseAction && interactableObject.holdButtonToUse) + { + interactableObject.StopUsing(this.gameObject); + } + } + + protected virtual void PointerSet() + { + if (!isActive || !pointerContactTarget) + { + return; + } + + SteamVR_InteractableObject interactableObject = pointerContactTarget.GetComponent(); + if (interactableObject && interactableObject.pointerActivatesUseAction) + { + if (interactableObject.IsUsing()) + { + interactableObject.StopUsing(this.gameObject); + } else if (!interactableObject.holdButtonToUse) + { + interactableObject.StartUsing(this.gameObject); + } + } + + if (!playAreaCursorCollided && (interactableObject == null || !interactableObject.pointerActivatesUseAction)) + { + OnWorldPointerDestinationSet(SetPointerEvent(controllerIndex, pointerContactDistance, pointerContactTarget, destinationPosition)); + } + } + + protected virtual void TogglePointer(bool state) + { + bool playAreaState = (showPlayAreaCursor ? state: false); + playAreaCursor.gameObject.SetActive(playAreaState); + } + + protected virtual void SetPointerMaterial() + { + foreach(GameObject playAreaCursorBoundary in playAreaCursorBoundaries) + { + playAreaCursorBoundary.GetComponent().material = pointerMaterial; + } + } + + protected void UpdatePointerMaterial(Color color) + { + if (playAreaCursorCollided) + { + color = pointerMissColor; + } + pointerMaterial.color = color; + SetPointerMaterial(); + } + + private void DrawPlayAreaCursorBoundary(int index, float left, float right, float top, float bottom, float thickness, Vector3 localPosition) + { + + GameObject playAreaCursorBoundary = GameObject.CreatePrimitive(PrimitiveType.Cube); + playAreaCursorBoundary.name = string.Format("[{0}]PlayerObject_WorldPointer_PlayAreaCursorBoundary_" + index, this.gameObject.name); + + float width = (right - left) / 1.065f; + float length = (top - bottom) / 1.08f; + float height = thickness; + + playAreaCursorBoundary.transform.localScale = new Vector3(width, height, length); + Destroy(playAreaCursorBoundary.GetComponent()); + playAreaCursorBoundary.layer = 2; + + playAreaCursorBoundary.transform.parent = playAreaCursor.transform; + playAreaCursorBoundary.transform.localPosition = localPosition; + + playAreaCursorBoundaries[index] = playAreaCursorBoundary; + } + + private void InitPlayAreaCursor() + { + int btmRightInner = 0; + int btmLeftInner = 1; + int topLeftInner = 2; + int topRightInner = 3; + + int btmRightOuter = 4; + int btmLeftOuter = 5; + int topLeftOuter = 6; + int topRightOuter = 7; + + Vector3[] cursorDrawVertices = playArea.vertices; + + if (playAreaCursorDimensions != Vector2.zero) + { + float customAreaPadding = playArea.borderThickness; + + cursorDrawVertices[btmRightOuter] = new Vector3(playAreaCursorDimensions.x / 2, 0f, (playAreaCursorDimensions.y / 2) * -1); + cursorDrawVertices[btmLeftOuter] = new Vector3((playAreaCursorDimensions.x / 2) * -1, 0f, (playAreaCursorDimensions.y / 2) * -1); + cursorDrawVertices[topLeftOuter] = new Vector3((playAreaCursorDimensions.x / 2) * -1, 0f, playAreaCursorDimensions.y / 2); + cursorDrawVertices[topRightOuter] = new Vector3(playAreaCursorDimensions.x / 2, 0f, playAreaCursorDimensions.y / 2); + + cursorDrawVertices[btmRightInner] = cursorDrawVertices[btmRightOuter] + new Vector3(-customAreaPadding, 0f, customAreaPadding); + cursorDrawVertices[btmLeftInner] = cursorDrawVertices[btmLeftOuter] + new Vector3(customAreaPadding, 0f, customAreaPadding); + cursorDrawVertices[topLeftInner] = cursorDrawVertices[topLeftOuter] + new Vector3(customAreaPadding, 0f, -customAreaPadding); + cursorDrawVertices[topRightInner] = cursorDrawVertices[topRightOuter] + new Vector3(-customAreaPadding, 0f, -customAreaPadding); + } + + float width = cursorDrawVertices[btmRightOuter].x - cursorDrawVertices[topLeftOuter].x; + float length = cursorDrawVertices[topLeftOuter].z - cursorDrawVertices[btmRightOuter].z; + float height = 0.01f; + + playAreaCursor = GameObject.CreatePrimitive(PrimitiveType.Cube); + playAreaCursor.name = string.Format("[{0}]PlayerObject_WorldPointer_PlayAreaCursor", this.gameObject.name); + playAreaCursor.transform.parent = null; + playAreaCursor.transform.localScale = new Vector3(width, height, length); + playAreaCursor.SetActive(false); + + playAreaCursor.GetComponent().enabled = false; + + BoxCollider playAreaCursorCollider = playAreaCursor.GetComponent(); + playAreaCursorCollider.isTrigger = true; + playAreaCursorCollider.center = new Vector3(0f, 65f, 0f); + playAreaCursorCollider.size = new Vector3(1f, 100f, 1f); + playAreaCursor.AddComponent().isKinematic = true; + SteamVR_PlayAreaCollider playAreaCursorScript = playAreaCursor.AddComponent(); + playAreaCursorScript.SetParent(this.gameObject); + playAreaCursor.layer = 2; + + float playAreaBoundaryX = playArea.transform.localScale.x / 2; + float playAreaBoundaryZ = playArea.transform.localScale.z / 2; + float heightOffset = 0f; + + DrawPlayAreaCursorBoundary(0, cursorDrawVertices[btmLeftOuter].x, cursorDrawVertices[btmRightOuter].x, cursorDrawVertices[btmRightInner].z, cursorDrawVertices[btmRightOuter].z, height, new Vector3(0f, heightOffset, playAreaBoundaryZ)); + DrawPlayAreaCursorBoundary(1, cursorDrawVertices[btmLeftOuter].x, cursorDrawVertices[btmLeftInner].x, cursorDrawVertices[topLeftOuter].z, cursorDrawVertices[btmLeftOuter].z, height, new Vector3(playAreaBoundaryX, heightOffset, 0f)); + DrawPlayAreaCursorBoundary(2, cursorDrawVertices[btmLeftOuter].x, cursorDrawVertices[btmRightOuter].x, cursorDrawVertices[btmRightInner].z, cursorDrawVertices[btmRightOuter].z, height, new Vector3(0f, heightOffset, -playAreaBoundaryZ)); + DrawPlayAreaCursorBoundary(3, cursorDrawVertices[btmLeftOuter].x, cursorDrawVertices[btmLeftInner].x, cursorDrawVertices[topLeftOuter].z, cursorDrawVertices[btmLeftOuter].z, height, new Vector3(-playAreaBoundaryX, heightOffset, 0f)); + } +} \ No newline at end of file diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/Abstractions/SteamVR_WorldPointer.cs.meta b/Assets/SteamVR_Unity_Toolkit/Scripts/Abstractions/SteamVR_WorldPointer.cs.meta new file mode 100755 index 0000000..7819909 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/Abstractions/SteamVR_WorldPointer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f2527c033c62a9d489bc580ce4ddda27 +timeCreated: 1461571032 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/Helper.meta b/Assets/SteamVR_Unity_Toolkit/Scripts/Helper.meta new file mode 100755 index 0000000..4e3dd9b --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/Helper.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c1c260a84c4ca2a4b9445da0a4c9291b +folderAsset: yes +timeCreated: 1461778923 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/Helper/CurveGenerator.cs b/Assets/SteamVR_Unity_Toolkit/Scripts/Helper/CurveGenerator.cs new file mode 100755 index 0000000..11b9368 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/Helper/CurveGenerator.cs @@ -0,0 +1,319 @@ +//==================================================================================== +// +// Purpose: To generate a bezier curve between at least 4 points in space and draw +// a number of spheres across the generated curve +// +// This script is heavily based on the tutorial at: +// http://catlikecoding.com/unity/tutorials/curves-and-splines/ +// +//==================================================================================== + +using UnityEngine; +using System.Collections; +using System; + +public static class Bezier +{ + + public static Vector3 GetPoint(Vector3 p0, Vector3 p1, Vector3 p2, float t) + { + t = Mathf.Clamp01(t); + float oneMinusT = 1f - t; + return + oneMinusT * oneMinusT * p0 + + 2f * oneMinusT * t * p1 + + t * t * p2; + } + + public static Vector3 GetFirstDerivative(Vector3 p0, Vector3 p1, Vector3 p2, float t) + { + return + 2f * (1f - t) * (p1 - p0) + + 2f * t * (p2 - p1); + } + + public static Vector3 GetPoint(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t) + { + t = Mathf.Clamp01(t); + float OneMinusT = 1f - t; + return + OneMinusT * OneMinusT * OneMinusT * p0 + + 3f * OneMinusT * OneMinusT * t * p1 + + 3f * OneMinusT * t * t * p2 + + t * t * t * p3; + } + + public static Vector3 GetFirstDerivative(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t) + { + t = Mathf.Clamp01(t); + float oneMinusT = 1f - t; + return + 3f * oneMinusT * oneMinusT * (p1 - p0) + + 6f * oneMinusT * t * (p2 - p1) + + 3f * t * t * (p3 - p2); + } +} + +public class CurveGenerator : MonoBehaviour +{ + private enum BezierControlPointMode + { + Free, + Aligned, + Mirrored + } + + private Vector3[] points; + private GameObject[] items; + private BezierControlPointMode[] modes; + private bool loop; + private int frequency; + private bool customTracer; + + public void Create(int setFrequency, float radius, GameObject tracer) + { + float circleSize = radius / 8; + + frequency = setFrequency; + items = new GameObject[frequency]; + for (int f = 0; f < items.Length; f++) + { + customTracer = true; + items[f] = (tracer ? Instantiate(tracer) : CreateSphere()); + items[f].transform.parent = this.transform; + items[f].layer = 2; + items[f].transform.localScale = new Vector3(circleSize, circleSize, circleSize); + } + } + + public void SetPoints(Vector3[] controlPoints, Material material) + { + points = controlPoints; + modes = new BezierControlPointMode[] { + BezierControlPointMode.Free, + BezierControlPointMode.Free + }; + + SetObjects(material); + } + + public void TogglePoints(bool state) + { + this.gameObject.SetActive(state); + } + + private GameObject CreateSphere() + { + customTracer = false; + GameObject item = GameObject.CreatePrimitive(PrimitiveType.Sphere); + Destroy(item.GetComponent()); + item.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; + item.GetComponent().receiveShadows = false; + + return item; + } + + private bool Loop + { + get + { + return loop; + } + set + { + loop = value; + if (value == true) + { + modes[modes.Length - 1] = modes[0]; + SetControlPoint(0, points[0]); + } + } + } + + private int ControlPointCount + { + get + { + return points.Length; + } + } + + private Vector3 GetControlPoint(int index) + { + return points[index]; + } + + private void SetControlPoint(int index, Vector3 point) + { + if (index % 3 == 0) + { + Vector3 delta = point - points[index]; + if (loop) + { + if (index == 0) + { + points[1] += delta; + points[points.Length - 2] += delta; + points[points.Length - 1] = point; + } + else if (index == points.Length - 1) + { + points[0] = point; + points[1] += delta; + points[index - 1] += delta; + } + else + { + points[index - 1] += delta; + points[index + 1] += delta; + } + } + else + { + if (index > 0) + { + points[index - 1] += delta; + } + if (index + 1 < points.Length) + { + points[index + 1] += delta; + } + } + } + points[index] = point; + EnforceMode(index); + } + + private void EnforceMode(int index) + { + int modeIndex = (index + 1) / 3; + BezierControlPointMode mode = modes[modeIndex]; + if (mode == BezierControlPointMode.Free || !loop && (modeIndex == 0 || modeIndex == modes.Length - 1)) + { + return; + } + + int middleIndex = modeIndex * 3; + int fixedIndex, enforcedIndex; + if (index <= middleIndex) + { + fixedIndex = middleIndex - 1; + if (fixedIndex < 0) + { + fixedIndex = points.Length - 2; + } + enforcedIndex = middleIndex + 1; + if (enforcedIndex >= points.Length) + { + enforcedIndex = 1; + } + } + else + { + fixedIndex = middleIndex + 1; + if (fixedIndex >= points.Length) + { + fixedIndex = 1; + } + enforcedIndex = middleIndex - 1; + if (enforcedIndex < 0) + { + enforcedIndex = points.Length - 2; + } + } + + Vector3 middle = points[middleIndex]; + Vector3 enforcedTangent = middle - points[fixedIndex]; + if (mode == BezierControlPointMode.Aligned) + { + enforcedTangent = enforcedTangent.normalized * Vector3.Distance(middle, points[enforcedIndex]); + } + points[enforcedIndex] = middle + enforcedTangent; + } + + private int CurveCount + { + get + { + return (points.Length - 1) / 3; + } + } + + private Vector3 GetPoint(float t) + { + int i; + if (t >= 1f) + { + t = 1f; + i = points.Length - 4; + } + else + { + t = Mathf.Clamp01(t) * CurveCount; + i = (int)t; + t -= i; + i *= 3; + } + return transform.TransformPoint(Bezier.GetPoint(points[i], points[i + 1], points[i + 2], points[i + 3], t)); + } + + private void SetObjects(Material material) + { + float stepSize = frequency * 1; + if (this.Loop || stepSize == 1) + { + stepSize = 1f / stepSize; + } + else + { + stepSize = 1f / (stepSize - 1); + } + + for (int f = 0; f < frequency; f++) + { + if (customTracer && (f == 0 || f == (frequency - 1))) + { + items[f].SetActive(false); + continue; + } + setMeshMaterial(items[f], material); + setSkinnedMeshMaterial(items[f], material); + + Vector3 position = this.GetPoint(f * stepSize); + items[f].transform.position = position; + + Vector3 nextPosition = this.GetPoint((f + 1) * stepSize); + Vector3 lookPosition = (nextPosition - position).normalized; + if (lookPosition != Vector3.zero) + { + items[f].transform.rotation = Quaternion.LookRotation(lookPosition); + } + } + } + + private void setMeshMaterial(GameObject item, Material material) + { + if (item.GetComponent()) + { + item.GetComponent().material = material; + } + + foreach (MeshRenderer mr in item.GetComponentsInChildren()) + { + mr.material = material; + } + } + + private void setSkinnedMeshMaterial(GameObject item, Material material) + { + if (item.GetComponent()) + { + item.GetComponent().material = material; + } + + foreach (SkinnedMeshRenderer mr in item.GetComponentsInChildren()) + { + mr.material = material; + } + } +} diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/Helper/CurveGenerator.cs.meta b/Assets/SteamVR_Unity_Toolkit/Scripts/Helper/CurveGenerator.cs.meta new file mode 100755 index 0000000..879d32d --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/Helper/CurveGenerator.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4a821bc6f26954b429adf294ef162c1d +timeCreated: 1461778933 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/Helper/FramsPerSecondViewer.cs b/Assets/SteamVR_Unity_Toolkit/Scripts/Helper/FramsPerSecondViewer.cs new file mode 100755 index 0000000..3e2e641 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/Helper/FramsPerSecondViewer.cs @@ -0,0 +1,66 @@ +//==================================================================================== +// +// Purpose: Provide GUI view of the current frames per second in the game +// +// This script must be attached to a Text element within a Canvas that has the +// Render Mode set to "Screen Space - Camera" and the Render Camera set to the +// [CameraRig]-> Camera (head) -> Camera (eye) object with a plane distance of 0.1. +// +// This script is pretty much a copy and paste from the script at: +// http://talesfromtherift.com/vr-fps-counter/ +// +// So all credit to Peter Koch for his work. Twitter: @peterept +// +//==================================================================================== + +using UnityEngine; +using UnityEngine.UI; + +public class FramsPerSecondViewer : MonoBehaviour { + public bool displayFPS = true; + public int targetFPS = 90; + public int fontSize = 32; + public Vector3 position = Vector3.zero; + public Color goodColor = Color.green; + public Color warnColor = Color.yellow; + public Color badColor = Color.red; + + private const float updateInterval = 0.5f; + private int framesCount; + private float framesTime; + private Text text; + + void Start() + { + text = this.GetComponent(); + text.fontSize = fontSize; + text.transform.localPosition = position; + } + + void Update() + { + framesCount++; + framesTime += Time.unscaledDeltaTime; + + if (framesTime > updateInterval) + { + if (text != null) + { + if (displayFPS) + { + float fps = framesCount / framesTime; + text.text = System.String.Format("{0:F2} FPS", fps); + text.color = (fps > (targetFPS - 5) ? goodColor : + (fps > (targetFPS - 30) ? warnColor : + badColor)); + } + else + { + text.text = ""; + } + } + framesCount = 0; + framesTime = 0; + } + } +} diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/Helper/FramsPerSecondViewer.cs.meta b/Assets/SteamVR_Unity_Toolkit/Scripts/Helper/FramsPerSecondViewer.cs.meta new file mode 100755 index 0000000..4accc24 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/Helper/FramsPerSecondViewer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c05937b3f7f046f4ba4de4f8f7b39f2f +timeCreated: 1462697634 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/Shaders.meta b/Assets/SteamVR_Unity_Toolkit/Scripts/Shaders.meta new file mode 100755 index 0000000..ad977a6 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/Shaders.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 8888fe9d9528bf443a7af10a0062e480 +folderAsset: yes +timeCreated: 1462087292 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/Shaders/Unlit_TransparentColor.shader b/Assets/SteamVR_Unity_Toolkit/Scripts/Shaders/Unlit_TransparentColor.shader new file mode 100755 index 0000000..5ce4b4c --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/Shaders/Unlit_TransparentColor.shader @@ -0,0 +1,31 @@ +Shader "Unlit/TransparentColor" +{ + Properties + { + _Color("Color Tint", Color) = (1,1,1,1) + _MainTex("Base (RGB) Alpha (A)", 2D) = "white" + } + + Category + { + Lighting Off + ZWrite Off + //ZWrite On // uncomment if you have problems like the sprite disappear in some rotations. + Cull back + Blend SrcAlpha OneMinusSrcAlpha + //AlphaTest Greater 0.001 // uncomment if you have problems like the sprites or 3d text have white quads instead of alpha pixels. + Tags{ Queue = Transparent } + + SubShader + { + Pass + { + SetTexture[_MainTex] + { + ConstantColor[_Color] + Combine Texture * constant + } + } + } + } +} \ No newline at end of file diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/Shaders/Unlit_TransparentColor.shader.meta b/Assets/SteamVR_Unity_Toolkit/Scripts/Shaders/Unlit_TransparentColor.shader.meta new file mode 100755 index 0000000..83cae98 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/Shaders/Unlit_TransparentColor.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 4c84081e4523a5646919b30697cfccb8 +timeCreated: 1462087316 +licenseType: Free +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_BasicTeleport.cs b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_BasicTeleport.cs new file mode 100755 index 0000000..64b610e --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_BasicTeleport.cs @@ -0,0 +1,121 @@ +//==================================================================================== +// +// Purpose: Provide basic teleportation of VR CameraRig +// +// This script must be attached to the [CameraRig] Prefab +// +// A GameObject must have the SteamVR_WorldPointer attached to it to listen for the +// updated world position to teleport to. +// +//==================================================================================== + +using UnityEngine; +using System.Collections; + +public class SteamVR_BasicTeleport : MonoBehaviour { + public float blinkTransitionSpeed = 0.6f; + [Range(0f,32f)] + public float distanceBlinkDelay = 0f; + public bool headsetPositionCompensation = true; + + protected int listenerInitTries = 5; + protected Transform eyeCamera; + protected bool adjustYForTerrain = false; + + private float blinkPause = 0f; + private float fadeInTime = 0f; + private float maxBlinkTransitionSpeed = 1.5f; + private float maxBlinkDistance = 33f; + + protected virtual void Start() + { + adjustYForTerrain = false; + InitPointerListeners(); + eyeCamera = GameObject.FindObjectOfType().GetComponent(); + } + + protected virtual void Blink(float transitionSpeed) + { + fadeInTime = transitionSpeed; + SteamVR_Fade.Start(Color.black, 0); + Invoke("ReleaseBlink", blinkPause); + } + + protected virtual void DoTeleport(object sender, WorldPointerEventArgs e) + { + if (e.target && e.enableTeleport) + { + Vector3 newPosition = GetNewPosition(e.destinationPosition, e.target); + CalculateBlinkDelay(blinkTransitionSpeed, newPosition); + Blink(blinkTransitionSpeed); + SetNewPosition(newPosition, e.target); + } + } + + protected virtual void SetNewPosition(Vector3 position, Transform target) + { + this.transform.position = CheckTerrainCollision(position, target); + } + + protected virtual Vector3 GetNewPosition(Vector3 tipPosition, Transform target) + { + float newX = (headsetPositionCompensation ? (tipPosition.x - (eyeCamera.position.x - this.transform.position.x)) : tipPosition.x); + float newY = this.transform.position.y; + float newZ = (headsetPositionCompensation ? (tipPosition.z - (eyeCamera.position.z - this.transform.position.z)) : tipPosition.z); + + return new Vector3(newX, newY, newZ); + } + + protected Vector3 CheckTerrainCollision(Vector3 position, Transform target) + { + if(adjustYForTerrain && target.GetComponent()) + { + position.y = Terrain.activeTerrain.SampleHeight(position); + } + return position; + } + + private void CalculateBlinkDelay(float blinkSpeed, Vector3 newPosition) + { + blinkPause = 0f; + if (distanceBlinkDelay > 0f) + { + float distance = Vector3.Distance(this.transform.position, newPosition); + blinkPause = Mathf.Clamp((distance * blinkTransitionSpeed) / (maxBlinkDistance - distanceBlinkDelay), 0, maxBlinkTransitionSpeed); + blinkPause = (blinkSpeed <= 0.25 ? 0f : blinkPause); + } + } + + private void ReleaseBlink() + { + SteamVR_Fade.Start(Color.clear, fadeInTime); + fadeInTime = 0f; + } + + private void InitPointerListeners() + { + SteamVR_WorldPointer[] worldPointers = GameObject.FindObjectsOfType(); + + // If the WorldPointer Object isn't initialised yet then retry in a quarter of a second + // Because the Controller is a child of the CameraRig (and the WorldPointer is usually attached + // to the Controller) then it is likely the WorldPointer object isn't available at start. + if (worldPointers.Length == 0) + { + if (listenerInitTries > 0) + { + listenerInitTries--; + Invoke("InitPointerListeners", 0.25f); + } + else + { + Debug.LogError("A GameObject must exist with a SteamVR_WorldPointer script attached to it"); + return; + } + } + + foreach (SteamVR_WorldPointer worldPointer in worldPointers) + { + worldPointer.WorldPointerDestinationSet += new WorldPointerEventHandler(DoTeleport); + } + } +} diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_BasicTeleport.cs.meta b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_BasicTeleport.cs.meta new file mode 100755 index 0000000..ca6ca6e --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_BasicTeleport.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ef7e6bfad51b1f24f8bba548c8dcecb8 +timeCreated: 1461573022 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_BezierPointer.cs b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_BezierPointer.cs new file mode 100755 index 0000000..6fde278 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_BezierPointer.cs @@ -0,0 +1,250 @@ +//==================================================================================== +// +// Purpose: Provide curved laser pointer at the ground to VR Controller +// +// This script must be attached to a Controller within the [CameraRig] Prefab +// +// The SteamVR_ControllerEvents script must also be attached to the Controller +// +// Press the default 'Grip' button on the controller to activate the beam +// Released the default 'Grip' button on the controller to deactivate the beam +// +// This script is an implementation of the SteamVR_WorldPointer. +// +//==================================================================================== + +using UnityEngine; +using System.Collections; + +public class SteamVR_BezierPointer : SteamVR_WorldPointer +{ + public float pointerLength = 10f; + public int pointerDensity = 10; + public bool showPointerCursor = true; + public float pointerCursorRadius = 0.5f; + public float beamCurveOffset = 1f; + public GameObject customPointerTracer; + public GameObject customPointerCursor; + + private Transform projectedBeamContainer; + private Transform projectedBeamForward; + private Transform projectedBeamJoint; + private Transform projectedBeamDown; + + private GameObject pointerCursor; + private CurveGenerator curvedBeam; + + // Use this for initialization + protected override void Start() + { + base.Start(); + InitProjectedBeams(); + InitPointer(); + TogglePointer(false); + } + + protected override void Update() + { + base.Update(); + if (projectedBeamForward.gameObject.activeSelf) + { + ProjectForwardBeam(); + ProjectDownBeam(); + DisplayCurvedBeam(); + SetPointerCursor(); + } + } + + protected override void InitPointer() + { + pointerCursor = (customPointerCursor ? Instantiate(customPointerCursor) : CreateCursor()); + + pointerCursor.name = string.Format("[{0}]PlayerObject_WorldPointer_BezierPointer_PointerCursor", this.gameObject.name); + pointerCursor.layer = 2; + pointerCursor.SetActive(false); + + GameObject global = new GameObject(string.Format("[{0}]PlayerObject_WorldPointer_BezierPointer_CurvedBeamContainer", this.gameObject.name)); + global.SetActive(false); + curvedBeam = global.gameObject.AddComponent(); + curvedBeam.transform.parent = null; + curvedBeam.Create(pointerDensity, pointerCursorRadius, customPointerTracer); + base.InitPointer(); + } + + private GameObject CreateCursor() + { + float cursorYOffset = 0.02f; + GameObject cursor = GameObject.CreatePrimitive(PrimitiveType.Cylinder); + cursor.GetComponent().shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; + cursor.GetComponent().receiveShadows = false; + cursor.transform.localScale = new Vector3(pointerCursorRadius, cursorYOffset, pointerCursorRadius); + Destroy(cursor.GetComponent()); + return cursor; + } + + protected override void SetPointerMaterial() + { + if (pointerCursor.GetComponent()) + { + pointerCursor.GetComponent().material = pointerMaterial; + } + + foreach(MeshRenderer mr in pointerCursor.GetComponentsInChildren()) + { + mr.material = pointerMaterial; + } + + if (pointerCursor.GetComponent()) + { + pointerCursor.GetComponent().material = pointerMaterial; + } + + foreach (SkinnedMeshRenderer mr in pointerCursor.GetComponentsInChildren()) + { + mr.material = pointerMaterial; + } + + base.SetPointerMaterial(); + } + + protected override void TogglePointer(bool state) + { + state = (beamAlwaysOn ? true : state); + + projectedBeamForward.gameObject.SetActive(state); + projectedBeamJoint.gameObject.SetActive(state); + projectedBeamDown.gameObject.SetActive(state); + } + + protected override void DisablePointerBeam(object sender, ControllerClickedEventArgs e) + { + base.PointerSet(); + base.DisablePointerBeam(sender, e); + TogglePointerCursor(false); + curvedBeam.TogglePoints(false); + } + + private void TogglePointerCursor(bool state) + { + state = (beamAlwaysOn ? true : state); + + bool pointerCursorState = (showPointerCursor && state ? showPointerCursor : false); + bool playAreaCursorState = (showPlayAreaCursor && state ? showPlayAreaCursor : false); + pointerCursor.gameObject.SetActive(pointerCursorState); + base.TogglePointer(playAreaCursorState); + } + + private void InitProjectedBeams() + { + projectedBeamContainer = new GameObject(string.Format("[{0}]PlayerObject_WorldPointer_BezierPointer_ProjectedBeamContainer", this.gameObject.name)).transform; + projectedBeamContainer.transform.parent = this.transform; + projectedBeamContainer.transform.localPosition = Vector3.zero; + + projectedBeamForward = new GameObject(string.Format("[{0}]PlayerObject_WorldPointer_BezierPointer_ProjectedBeamForward", this.gameObject.name)).transform; + projectedBeamForward.transform.parent = projectedBeamContainer.transform; + + projectedBeamJoint = new GameObject(string.Format("[{0}]PlayerObject_WorldPointer_BezierPointer_ProjectedBeamJoint", this.gameObject.name)).transform; + projectedBeamJoint.transform.parent = projectedBeamContainer.transform; + projectedBeamJoint.transform.localScale = new Vector3(0.01f, 0.01f, 0.01f); + + projectedBeamDown = new GameObject(string.Format("[{0}]PlayerObject_WorldPointer_BezierPointer_ProjectedBeamDown", this.gameObject.name)).transform; + } + + private float GetForwardBeamLength() + { + float actualLength = pointerLength; + Ray pointerRaycast = new Ray(transform.position, transform.forward); + RaycastHit collidedWith; + bool hasRayHit = Physics.Raycast(pointerRaycast, out collidedWith); + + //reset if beam not hitting or hitting new target + if (!hasRayHit || (pointerContactTarget && pointerContactTarget != collidedWith.transform)) + { + pointerContactDistance = 0f; + } + + //check if beam has hit a new target + if (hasRayHit) + { + pointerContactDistance = collidedWith.distance; + } + + //adjust beam length if something is blocking it + if (hasRayHit && pointerContactDistance < pointerLength) + { + actualLength = pointerContactDistance; + } + + return actualLength; + } + + private void ProjectForwardBeam() + { + float setThicknes = 0.01f; + float setLength = GetForwardBeamLength(); + //if the additional decimal isn't added then the beam position glitches + float beamPosition = setLength / (2 + 0.00001f); + + projectedBeamForward.transform.localScale = new Vector3(setThicknes, setThicknes, setLength); + projectedBeamForward.transform.localPosition = new Vector3(0f, 0f, beamPosition); + projectedBeamJoint.transform.localPosition = new Vector3(0f, 0f, setLength - (projectedBeamJoint.transform.localScale.z / 2)); + projectedBeamContainer.transform.localRotation = Quaternion.identity; + } + + private void ProjectDownBeam() + { + projectedBeamDown.transform.position = new Vector3(projectedBeamJoint.transform.position.x, projectedBeamJoint.transform.position.y, projectedBeamJoint.transform.position.z); + + Ray projectedBeamDownRaycast = new Ray(projectedBeamDown.transform.position, Vector3.down); + RaycastHit collidedWith; + bool downRayHit = Physics.Raycast(projectedBeamDownRaycast, out collidedWith); + + if (!downRayHit || (pointerContactTarget && pointerContactTarget != collidedWith.transform)) + { + if (pointerContactTarget != null) + { + base.PointerOut(); + } + pointerContactTarget = null; + destinationPosition = Vector3.zero; + } + + if (downRayHit) + { + projectedBeamDown.transform.position = new Vector3(projectedBeamJoint.transform.position.x, projectedBeamJoint.transform.position.y - collidedWith.distance, projectedBeamJoint.transform.position.z); + projectedBeamDown.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f); + pointerContactTarget = collidedWith.transform; + destinationPosition = projectedBeamDown.transform.position; + + base.PointerIn(); + } + } + + private void SetPointerCursor() + { + if (pointerContactTarget != null) + { + TogglePointerCursor(true); + pointerCursor.transform.position = projectedBeamDown.transform.position; + base.SetPlayAreaCursorTransform(pointerCursor.transform.position); + UpdatePointerMaterial(pointerHitColor); + } else + { + TogglePointerCursor(false); + UpdatePointerMaterial(pointerMissColor); + } + } + + private void DisplayCurvedBeam() + { + Vector3[] beamPoints = new Vector3[] + { + this.transform.position, + projectedBeamJoint.transform.position + new Vector3(0f, beamCurveOffset, 0f), + projectedBeamDown.transform.position, + projectedBeamDown.transform.position, + }; + curvedBeam.SetPoints(beamPoints, pointerMaterial); + curvedBeam.TogglePoints(true); + } +} \ No newline at end of file diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_BezierPointer.cs.meta b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_BezierPointer.cs.meta new file mode 100755 index 0000000..1a2b346 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_BezierPointer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2f0ad608ee982c348aaa6aea32a3db61 +timeCreated: 1461759912 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_ControllerActions.cs b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_ControllerActions.cs new file mode 100755 index 0000000..a1baff7 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_ControllerActions.cs @@ -0,0 +1,55 @@ +using UnityEngine; +using System.Collections; + +public class SteamVR_ControllerActions : MonoBehaviour { + private bool controllerVisible = true; + private ushort hapticPulseStrength; + private int hapticPulseCountdown; + + private uint controllerIndex; + private SteamVR_TrackedObject trackedController; + private SteamVR_Controller.Device device; + private ushort maxHapticVibration = 3999; + + public bool IsControllerVisible() + { + return controllerVisible; + } + + public void ToggleControllerModel(bool on) + { + foreach (MeshRenderer renderer in this.GetComponentsInChildren()) + { + renderer.enabled = on; + } + + foreach (SkinnedMeshRenderer renderer in this.GetComponentsInChildren()) + { + renderer.enabled = on; + } + controllerVisible = on; + } + + public void TriggerHapticPulse(int duration, ushort strength) + { + hapticPulseCountdown = duration; + hapticPulseStrength = (strength <= maxHapticVibration ? strength : maxHapticVibration); + } + + private void Awake() + { + trackedController = GetComponent(); + } + + private void Update() + { + controllerIndex = (uint)trackedController.index; + device = SteamVR_Controller.Input((int)controllerIndex); + + if (hapticPulseCountdown > 0) + { + device.TriggerHapticPulse(hapticPulseStrength); + hapticPulseCountdown -= 1; + } + } +} diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_ControllerActions.cs.meta b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_ControllerActions.cs.meta new file mode 100755 index 0000000..58339a2 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_ControllerActions.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d45c8d32f1d960d4498790bb3961fc52 +timeCreated: 1462549415 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_ControllerEvents.cs b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_ControllerEvents.cs new file mode 100755 index 0000000..cb7a07c --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_ControllerEvents.cs @@ -0,0 +1,356 @@ +using UnityEngine; +using System.Collections; + +public struct ControllerClickedEventArgs +{ + public uint controllerIndex; + public float buttonPressure; + public Vector2 touchpadAxis; +} + +public delegate void ControllerClickedEventHandler(object sender, ControllerClickedEventArgs e); + +public class SteamVR_ControllerEvents : MonoBehaviour { + public enum ButtonAlias + { + Trigger, + Grip, + Touchpad_Touch, + Touchpad_Press, + Application_Menu + } + + public ButtonAlias pointerToggleButton = ButtonAlias.Grip; + public ButtonAlias grabToggleButton = ButtonAlias.Trigger; + public ButtonAlias useToggleButton = ButtonAlias.Trigger; + public ButtonAlias menuToggleButton = ButtonAlias.Application_Menu; + + public int axisFidelity = 1; + + public bool triggerPressed = false; + public bool triggerAxisChanged = false; + public bool applicationMenuPressed = false; + public bool touchpadPressed = false; + public bool touchpadTouched = false; + public bool touchpadAxisChanged = false; + public bool gripPressed = false; + + public event ControllerClickedEventHandler TriggerClicked; + public event ControllerClickedEventHandler TriggerUnclicked; + + public event ControllerClickedEventHandler TriggerAxisChanged; + + public event ControllerClickedEventHandler ApplicationMenuClicked; + public event ControllerClickedEventHandler ApplicationMenuUnclicked; + + public event ControllerClickedEventHandler GripClicked; + public event ControllerClickedEventHandler GripUnclicked; + + public event ControllerClickedEventHandler TouchpadClicked; + public event ControllerClickedEventHandler TouchpadUnclicked; + + public event ControllerClickedEventHandler TouchpadTouched; + public event ControllerClickedEventHandler TouchpadUntouched; + + public event ControllerClickedEventHandler TouchpadAxisChanged; + + public event ControllerClickedEventHandler AliasPointerOn; + public event ControllerClickedEventHandler AliasPointerOff; + + public event ControllerClickedEventHandler AliasGrabOn; + public event ControllerClickedEventHandler AliasGrabOff; + + public event ControllerClickedEventHandler AliasUseOn; + public event ControllerClickedEventHandler AliasUseOff; + + public event ControllerClickedEventHandler AliasMenuOn; + public event ControllerClickedEventHandler AliasMenuOff; + + private uint controllerIndex; + private SteamVR_TrackedObject trackedController; + private SteamVR_Controller.Device device; + + private Vector2 touchpadAxis = Vector2.zero; + private Vector2 triggerAxis = Vector2.zero; + + public virtual void OnTriggerClicked(ControllerClickedEventArgs e) + { + if (TriggerClicked != null) + TriggerClicked(this, e); + } + + public virtual void OnTriggerUnclicked(ControllerClickedEventArgs e) + { + if (TriggerUnclicked != null) + TriggerUnclicked(this, e); + } + + public virtual void OnTriggerAxisChanged(ControllerClickedEventArgs e) + { + if (TriggerAxisChanged != null) + TriggerAxisChanged(this, e); + } + + public virtual void OnApplicationMenuClicked(ControllerClickedEventArgs e) + { + if (ApplicationMenuClicked != null) + ApplicationMenuClicked(this, e); + } + + public virtual void OnApplicationMenuUnclicked(ControllerClickedEventArgs e) + { + if (ApplicationMenuUnclicked != null) + ApplicationMenuUnclicked(this, e); + } + + public virtual void OnGripClicked(ControllerClickedEventArgs e) + { + if (GripClicked != null) + GripClicked(this, e); + } + + public virtual void OnGripUnclicked(ControllerClickedEventArgs e) + { + if (GripUnclicked != null) + GripUnclicked(this, e); + } + + public virtual void OnTouchpadClicked(ControllerClickedEventArgs e) + { + if (TouchpadClicked != null) + TouchpadClicked(this, e); + } + + public virtual void OnTouchpadUnclicked(ControllerClickedEventArgs e) + { + if (TouchpadUnclicked != null) + TouchpadUnclicked(this, e); + } + + public virtual void OnTouchpadTouched(ControllerClickedEventArgs e) + { + if (TouchpadTouched != null) + TouchpadTouched(this, e); + } + + public virtual void OnTouchpadUntouched(ControllerClickedEventArgs e) + { + if (TouchpadUntouched != null) + TouchpadUntouched(this, e); + } + + public virtual void OnTouchpadAxisChanged(ControllerClickedEventArgs e) + { + if (TouchpadAxisChanged != null) + TouchpadAxisChanged(this, e); + } + + public virtual void OnAliasPointerOn(ControllerClickedEventArgs e) + { + if (AliasPointerOn != null) + AliasPointerOn(this, e); + } + + public virtual void OnAliasPointerOff(ControllerClickedEventArgs e) + { + if (AliasPointerOff != null) + AliasPointerOff(this, e); + } + + public virtual void OnAliasGrabOn(ControllerClickedEventArgs e) + { + if (AliasGrabOn != null) + AliasGrabOn(this, e); + } + + public virtual void OnAliasGrabOff(ControllerClickedEventArgs e) + { + if (AliasGrabOff != null) + AliasGrabOff(this, e); + } + + public virtual void OnAliasUseOn(ControllerClickedEventArgs e) + { + if (AliasUseOn != null) + AliasUseOn(this, e); + } + + public virtual void OnAliasUseOff(ControllerClickedEventArgs e) + { + if (AliasUseOff != null) + AliasUseOff(this, e); + } + + public virtual void OnAliasMenuOn(ControllerClickedEventArgs e) + { + if (AliasMenuOn != null) + AliasMenuOn(this, e); + } + + public virtual void OnAliasMenuOff(ControllerClickedEventArgs e) + { + if (AliasMenuOff != null) + AliasMenuOff(this, e); + } + + ControllerClickedEventArgs SetButtonEvent(ref bool buttonBool, bool value, float buttonPressure) + { + buttonBool = value; + ControllerClickedEventArgs e; + e.controllerIndex = controllerIndex; + e.buttonPressure = buttonPressure; + e.touchpadAxis = device.GetAxis(); + return e; + } + + void Awake() + { + trackedController = GetComponent(); + } + + void EmitAlias(ButtonAlias type, bool touchDown, float buttonPressure, ref bool buttonBool) + { + if (pointerToggleButton == type) + { + if (touchDown) + { + OnAliasPointerOn(SetButtonEvent(ref buttonBool, true, buttonPressure)); + } else + { + OnAliasPointerOff(SetButtonEvent(ref buttonBool, false, buttonPressure)); + } + } + + if (grabToggleButton == type) + { + if (touchDown) + { + OnAliasGrabOn(SetButtonEvent(ref buttonBool, true, buttonPressure)); + } + else + { + OnAliasGrabOff(SetButtonEvent(ref buttonBool, false, buttonPressure)); + } + } + + if (useToggleButton == type) + { + if (touchDown) + { + OnAliasUseOn(SetButtonEvent(ref buttonBool, true, buttonPressure)); + } + else + { + OnAliasUseOff(SetButtonEvent(ref buttonBool, false, buttonPressure)); + } + } + + if (menuToggleButton == type) + { + if (touchDown) + { + OnAliasMenuOn(SetButtonEvent(ref buttonBool, true, buttonPressure)); + } + else + { + OnAliasMenuOff(SetButtonEvent(ref buttonBool, false, buttonPressure)); + } + } + } + + bool Vector2ShallowEquals(Vector2 vectorA, Vector2 vectorB) + { + return (vectorA.x.ToString("F" + axisFidelity) == vectorB.x.ToString("F" + axisFidelity) && + vectorA.y.ToString("F" + axisFidelity) == vectorB.y.ToString("F" + axisFidelity)); + } + + void Update() + { + controllerIndex = (uint)trackedController.index; + device = SteamVR_Controller.Input((int)controllerIndex); + + Vector2 currentTriggerAxis = device.GetAxis(Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger); + Vector2 currentTouchpadAxis = device.GetAxis(); + + if (Vector2ShallowEquals(triggerAxis, currentTriggerAxis)) + { + triggerAxisChanged = false; + } else + { + OnTriggerAxisChanged(SetButtonEvent(ref triggerPressed, true, currentTriggerAxis.x)); + triggerAxisChanged = true; + } + + if(Vector2ShallowEquals(touchpadAxis, currentTouchpadAxis)) + { + touchpadAxisChanged = false; + } else + { + OnTouchpadAxisChanged(SetButtonEvent(ref touchpadTouched, true, 1f)); + touchpadAxisChanged = true; + } + + touchpadAxis = new Vector2(currentTouchpadAxis.x, currentTouchpadAxis.y); + triggerAxis = new Vector2(currentTriggerAxis.x, currentTriggerAxis.y); + + //Trigger + if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Trigger)) + { + OnTriggerClicked(SetButtonEvent(ref triggerPressed, true, currentTriggerAxis.x)); + EmitAlias(ButtonAlias.Trigger, true, currentTriggerAxis.x, ref triggerPressed); + } else if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Trigger)) + { + OnTriggerUnclicked(SetButtonEvent(ref triggerPressed, false, 0f)); + EmitAlias(ButtonAlias.Trigger, false, 0f, ref triggerPressed); + } + + //ApplicationMenu + if (device.GetTouchDown(SteamVR_Controller.ButtonMask.ApplicationMenu)) + { + OnApplicationMenuClicked(SetButtonEvent(ref applicationMenuPressed, true, 1f)); + EmitAlias(ButtonAlias.Application_Menu, true, 1f, ref applicationMenuPressed); + } + else if (device.GetTouchUp(SteamVR_Controller.ButtonMask.ApplicationMenu)) + { + + OnApplicationMenuUnclicked(SetButtonEvent(ref applicationMenuPressed, false, 0f)); + EmitAlias(ButtonAlias.Application_Menu, false, 0f, ref applicationMenuPressed); + } + + //Grip + if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Grip)) + { + OnGripClicked(SetButtonEvent(ref gripPressed, true, 1f)); + EmitAlias(ButtonAlias.Grip, true, 1f, ref gripPressed); + } + else if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Grip)) + { + OnGripUnclicked(SetButtonEvent(ref gripPressed, false, 0f)); + EmitAlias(ButtonAlias.Grip, false, 0f, ref gripPressed); + } + + //Touchpad Clicked + if (device.GetPressDown(SteamVR_Controller.ButtonMask.Touchpad)) + { + OnTouchpadClicked(SetButtonEvent(ref touchpadPressed, true, 1f)); + EmitAlias(ButtonAlias.Touchpad_Press, true, 1f, ref touchpadPressed); + } + else if (device.GetPressUp(SteamVR_Controller.ButtonMask.Touchpad)) + { + OnTouchpadUnclicked(SetButtonEvent(ref touchpadPressed, false, 0f)); + EmitAlias(ButtonAlias.Touchpad_Press, false, 0f, ref touchpadPressed); + } + + //Touchpad Touched + if (device.GetTouchDown(SteamVR_Controller.ButtonMask.Touchpad)) + { + OnTouchpadTouched(SetButtonEvent(ref touchpadTouched, true, 1f)); + EmitAlias(ButtonAlias.Touchpad_Touch, true, 1f, ref touchpadTouched); + } + else if (device.GetTouchUp(SteamVR_Controller.ButtonMask.Touchpad)) + { + OnTouchpadUntouched(SetButtonEvent(ref touchpadTouched, false, 0f)); + EmitAlias(ButtonAlias.Touchpad_Touch, false, 0f, ref touchpadTouched); + } + } +} diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_ControllerEvents.cs.meta b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_ControllerEvents.cs.meta new file mode 100755 index 0000000..23981e2 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_ControllerEvents.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: eba3cd5456cd79e49948f5ceb58544b4 +timeCreated: 1461529683 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_HeadsetCollisionFade.cs b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_HeadsetCollisionFade.cs new file mode 100755 index 0000000..70d214f --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_HeadsetCollisionFade.cs @@ -0,0 +1,59 @@ +using UnityEngine; +using System.Collections; + +public struct HeadsetCollisionEventArgs +{ + public Collider collider; + public Transform currentTransform; +} + +public delegate void HeadsetCollisionEventHandler(object sender, HeadsetCollisionEventArgs e); + +public class SteamVR_HeadsetCollisionFade : MonoBehaviour { + public float blinkTransitionSpeed = 0.1f; + public Color fadeColor = Color.black; + + public event HeadsetCollisionEventHandler HeadsetCollisionDetect; + + public virtual void OnHeadsetCollisionDetect(HeadsetCollisionEventArgs e) + { + if (HeadsetCollisionDetect != null) + HeadsetCollisionDetect(this, e); + } + + protected HeadsetCollisionEventArgs SetHeadsetCollisionEvent(Collider collider, Transform currentTransform) + { + HeadsetCollisionEventArgs e; + e.collider = collider; + e.currentTransform = currentTransform; + return e; + } + + protected void Start () { + this.name = "PlayerObject_" + this.name; + BoxCollider collider = this.gameObject.AddComponent(); + collider.isTrigger = true; + collider.size = new Vector3(0.1f, 0.1f, 0.1f); + + Rigidbody rb = this.gameObject.AddComponent(); + rb.isKinematic = true; + rb.useGravity = false; + } + + protected void OnTriggerStay(Collider collider) + { + if (!collider.name.Contains("PlayerObject_")) + { + OnHeadsetCollisionDetect(SetHeadsetCollisionEvent(collider, this.transform)); + SteamVR_Fade.Start(fadeColor, blinkTransitionSpeed); + } + } + + protected void OnTriggerExit(Collider collider) + { + if (!collider.name.Contains("PlayerObject_")) + { + SteamVR_Fade.Start(Color.clear, blinkTransitionSpeed); + } + } +} diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_HeadsetCollisionFade.cs.meta b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_HeadsetCollisionFade.cs.meta new file mode 100755 index 0000000..367d907 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_HeadsetCollisionFade.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 21b4bc319f4966f4faedb4f429f7c9c9 +timeCreated: 1461927173 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_HeightAdjustTeleport.cs b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_HeightAdjustTeleport.cs new file mode 100755 index 0000000..f1f67fb --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_HeightAdjustTeleport.cs @@ -0,0 +1,100 @@ +//==================================================================================== +// +// Purpose: Provide basic teleportation of VR CameraRig +// +// This script must be attached to the [CameraRig] Prefab +// +// A GameObject must have the SteamVR_WorldPointer attached to it to listen for the +// updated world position to teleport to. +// +//==================================================================================== + +using UnityEngine; +using System.Collections; + +public class SteamVR_HeightAdjustTeleport : SteamVR_BasicTeleport { + public bool playSpaceFalling = true; + private float currentRayDownY = 0f; + + GameObject currentFloor = null; + + protected override void Start() + { + base.Start(); + adjustYForTerrain = true; + } + + protected override void DoTeleport(object sender, WorldPointerEventArgs e) + { + base.DoTeleport(sender, e); + if (e.enableTeleport) + { + DropToNearestFloor(false); + } + } + + protected override Vector3 GetNewPosition(Vector3 tipPosition, Transform target) + { + Vector3 basePosition = base.GetNewPosition(tipPosition, target); + basePosition.y = GetTeleportY(target, tipPosition); + return basePosition; + } + + private float GetTeleportY(Transform target, Vector3 tipPosition) + { + float newY = this.transform.position.y; + //Check to see if the tip is on top of an object + if (target && (tipPosition.y + 0.5f) > (target.position.y + (target.localScale.y / 2))) + { + newY = tipPosition.y; + } + + return newY; + } + + private bool CurrentFloorChanged(RaycastHit collidedObj) + { + return (currentFloor != collidedObj.transform.gameObject); + } + + private bool MeshYChanged(RaycastHit collidedObj, float floorY) + { + return (collidedObj.transform.GetComponent() && floorY != currentRayDownY); + } + + private bool FloorIsGrabbedObject(RaycastHit collidedObj) + { + return (collidedObj.transform.GetComponent() && collidedObj.transform.GetComponent().IsGrabbed()); + } + + private void DropToNearestFloor(bool withBlink) + { + //send a ray down to find the closest object to stand on + Ray ray = new Ray(eyeCamera.transform.position, -transform.up); + RaycastHit rayCollidedWith; + bool rayHit = Physics.Raycast(ray, out rayCollidedWith); + float floorY = eyeCamera.transform.position.y - rayCollidedWith.distance; + + if (rayHit && ! FloorIsGrabbedObject(rayCollidedWith) && ( MeshYChanged(rayCollidedWith, floorY) || CurrentFloorChanged(rayCollidedWith) ) ) + { + currentFloor = rayCollidedWith.transform.gameObject; + currentRayDownY = floorY; + + if (withBlink && !rayCollidedWith.transform.GetComponent()) + { + Blink(blinkTransitionSpeed); + } + + Vector3 newPosition = new Vector3(this.transform.position.x, floorY, this.transform.position.z); + SetNewPosition(newPosition, currentFloor.transform); + } + } + + private void Update() + { + if (playSpaceFalling) + { + DropToNearestFloor(true); + } + } +} diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_HeightAdjustTeleport.cs.meta b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_HeightAdjustTeleport.cs.meta new file mode 100755 index 0000000..95a730f --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_HeightAdjustTeleport.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 377ced3493c4e1842a5b1c23f56519db +timeCreated: 1461687851 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractGrab.cs b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractGrab.cs new file mode 100755 index 0000000..5c8c95c --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractGrab.cs @@ -0,0 +1,293 @@ +//==================================================================================== +// +// Purpose: Provide ability to grab an interactable object when it is being touched +// +// This script must be attached to a Controller within the [CameraRig] Prefab +// +// The SteamVR_ControllerEvents and SteamVR_InteractTouch scripts must also be +// attached to the Controller +// +// Press the default 'Trigger' button on the controller to grab an object +// Released the default 'Trigger' button on the controller to drop an object +// +//==================================================================================== + +using UnityEngine; +using System.Collections; + +public class SteamVR_InteractGrab : MonoBehaviour +{ + public Rigidbody controllerAttachPoint = null; + public bool hideControllerOnGrab = false; + public float hideControllerDelay = 0f; + + public event ObjectInteractEventHandler ControllerGrabInteractableObject; + public event ObjectInteractEventHandler ControllerUngrabInteractableObject; + + Joint controllerAttachJoint; + GameObject grabbedObject = null; + + SteamVR_InteractTouch interactTouch; + SteamVR_TrackedObject trackedController; + SteamVR_ControllerActions controllerActions; + + private int grabEnabledState = 0; + + public virtual void OnControllerGrabInteractableObject(ObjectInteractEventArgs e) + { + if (ControllerGrabInteractableObject != null) + ControllerGrabInteractableObject(this, e); + } + + public virtual void OnControllerUngrabInteractableObject(ObjectInteractEventArgs e) + { + if (ControllerUngrabInteractableObject != null) + ControllerUngrabInteractableObject(this, e); + } + + public void ForceRelease() + { + if (grabbedObject.GetComponent().AttatchIsTrackObject()) + { + UngrabTrackedObject(); + } + else + { + ReleaseObject((uint)trackedController.index, false); + } + } + + private void Awake() + { + if (GetComponent() == null) + { + Debug.LogError("SteamVR_InteractGrab is required to be attached to a SteamVR Controller that has the SteamVR_InteractTouch script attached to it"); + return; + } + + interactTouch = GetComponent(); + trackedController = GetComponent(); + controllerActions = GetComponent(); + } + + private void Start() + { + //If no attach point has been specified then just use the tip of the controller + if (controllerAttachPoint == null) + { + controllerAttachPoint = transform.GetChild(0).Find("tip").GetChild(0).GetComponent(); + } + + if (GetComponent() == null) + { + Debug.LogError("SteamVR_InteractGrab is required to be attached to a SteamVR Controller that has the SteamVR_ControllerEvents script attached to it"); + return; + } + + GetComponent().AliasGrabOn += new ControllerClickedEventHandler(DoGrabObject); + GetComponent().AliasGrabOff += new ControllerClickedEventHandler(DoReleaseObject); + } + + private bool IsObjectGrabbable(GameObject obj) + { + return (interactTouch.IsObjectInteractable(obj) && obj.GetComponent().isGrabbable); + } + + private bool IsObjectHoldOnGrab(GameObject obj) + { + return (obj && obj.GetComponent() && obj.GetComponent().holdButtonToGrab); + } + + private void SnapObjectToGrabToController(GameObject obj) + { + //Pause collisions (if allowed on object) for a moment whilst sorting out position to prevent clipping issues + obj.GetComponent().PauseCollisions(0.2f); + + SteamVR_InteractableObject.GrabSnapType grabType = obj.GetComponent().grabSnapType; + + if (grabType == SteamVR_InteractableObject.GrabSnapType.Rotation_Snap) + { + // Identity Controller Rotation + this.transform.eulerAngles = new Vector3(0f, 270f, 0f); + obj.transform.eulerAngles = obj.GetComponent().snapToRotation; + } + + if (grabType != SteamVR_InteractableObject.GrabSnapType.Precision_Snap) + { + obj.transform.position = controllerAttachPoint.transform.position + obj.GetComponent().snapToPosition; + } + + CreateJoint(obj); + } + + private void CreateJoint(GameObject obj) + { + + if (obj.GetComponent().grabAttatchMechanic == SteamVR_InteractableObject.GrabAttatchType.Fixed_Joint) + { + controllerAttachJoint = obj.AddComponent(); + } + else if (obj.GetComponent().grabAttatchMechanic == SteamVR_InteractableObject.GrabAttatchType.Spring_Joint) + { + SpringJoint tempSpringJoint = obj.AddComponent(); + tempSpringJoint.spring = obj.GetComponent().springJointStrength; + tempSpringJoint.damper = obj.GetComponent().springJointDamper; + controllerAttachJoint = tempSpringJoint; + } + controllerAttachJoint.breakForce = obj.GetComponent().detatchThreshold; + controllerAttachJoint.connectedBody = controllerAttachPoint; + } + + private Rigidbody ReleaseGrabbedObjectFromController(bool withThrow) + { + var jointGameObject = controllerAttachJoint.gameObject; + var rigidbody = jointGameObject.GetComponent(); + if (withThrow) + { + Object.DestroyImmediate(controllerAttachJoint); + } else + { + Object.Destroy(controllerAttachJoint); + } + controllerAttachJoint = null; + + return rigidbody; + } + + private void ThrowReleasedObject(Rigidbody rb, uint controllerIndex) + { + var origin = trackedController.origin ? trackedController.origin : trackedController.transform.parent; + var device = SteamVR_Controller.Input((int)controllerIndex); + if (origin != null) + { + rb.velocity = origin.TransformVector(device.velocity); + rb.angularVelocity = origin.TransformVector(device.angularVelocity); + } + else + { + rb.velocity = device.velocity; + rb.angularVelocity = device.angularVelocity; + } + rb.maxAngularVelocity = rb.angularVelocity.magnitude; + } + + private void GrabInteractedObject() + { + if (controllerAttachJoint == null && grabbedObject == null && IsObjectGrabbable(interactTouch.GetTouchedObject())) + { + InitGrabbedObject(); + SnapObjectToGrabToController(grabbedObject); + } + } + + private void GrabTrackedObject() + { + if (grabbedObject == null && IsObjectGrabbable(interactTouch.GetTouchedObject())) { + InitGrabbedObject(); + } + } + + private void InitGrabbedObject() + { + grabbedObject = interactTouch.GetTouchedObject(); + OnControllerGrabInteractableObject(interactTouch.SetControllerInteractEvent(grabbedObject)); + grabbedObject.GetComponent().Grabbed(this.gameObject); + if (grabbedObject) + { + grabbedObject.GetComponent().ToggleHighlight(false); + } + if (hideControllerOnGrab) + { + Invoke("HideController", hideControllerDelay); + } + } + + private void HideController() + { + if(grabbedObject != null) + { + controllerActions.ToggleControllerModel(false); + } + } + + private void UngrabInteractedObject(uint controllerIndex, bool withThrow) + { + if (grabbedObject != null && controllerAttachJoint != null) + { + Rigidbody releasedObjectRigidBody = ReleaseGrabbedObjectFromController(withThrow); + if (withThrow) + { + ThrowReleasedObject(releasedObjectRigidBody, controllerIndex); + } + InitUngrabbedObject(); + } + } + + private void UngrabTrackedObject() + { + if (grabbedObject != null) + { + InitUngrabbedObject(); + } + } + + private void InitUngrabbedObject() + { + OnControllerUngrabInteractableObject(interactTouch.SetControllerInteractEvent(grabbedObject)); + grabbedObject.GetComponent().Ungrabbed(this.gameObject); + + if (hideControllerOnGrab) + { + controllerActions.ToggleControllerModel(true); + } + + grabbedObject.GetComponent().ToggleHighlight(false); + grabbedObject = null; + } + + private void ReleaseObject(uint controllerIndex, bool withThrow) + { + UngrabInteractedObject(controllerIndex, withThrow); + grabEnabledState = 0; + } + + private bool IsValidGrab() + { + GameObject obj = interactTouch.GetTouchedObject(); + return (obj != null && interactTouch.IsObjectInteractable(obj)); + } + + private void DoGrabObject(object sender, ControllerClickedEventArgs e) + { + if (IsValidGrab()) + { + if (interactTouch.GetTouchedObject().GetComponent().AttatchIsTrackObject()) + { + GrabTrackedObject(); + } else + { + GrabInteractedObject(); + } + + if(!IsObjectHoldOnGrab(interactTouch.GetTouchedObject())) + { + grabEnabledState++; + } + } + } + + private void DoReleaseObject(object sender, ControllerClickedEventArgs e) + { + if (IsObjectHoldOnGrab(grabbedObject) || grabEnabledState >= 2) + { + if (grabbedObject.GetComponent().AttatchIsTrackObject()) + { + UngrabTrackedObject(); + } + else + { + ReleaseObject(e.controllerIndex, true); + } + } + } +} diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractGrab.cs.meta b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractGrab.cs.meta new file mode 100755 index 0000000..326857d --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractGrab.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 947b27445602ed640b885db7e667dfc1 +timeCreated: 1461746152 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractTouch.cs b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractTouch.cs new file mode 100755 index 0000000..40e9075 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractTouch.cs @@ -0,0 +1,121 @@ +//==================================================================================== +// +// Purpose: Provide basic touch detection of controller to interactable objects +// +// This script must be attached to a Controller within the [CameraRig] Prefab +// +//==================================================================================== + +using UnityEngine; +using System.Collections; + +public struct ObjectInteractEventArgs +{ + public uint controllerIndex; + public GameObject target; +} + +public delegate void ObjectInteractEventHandler(object sender, ObjectInteractEventArgs e); + +public class SteamVR_InteractTouch : MonoBehaviour { + + public bool hideControllerOnTouch = false; + public float hideControllerDelay = 0f; + public Color globalTouchHighlightColor = Color.clear; + + public event ObjectInteractEventHandler ControllerTouchInteractableObject; + public event ObjectInteractEventHandler ControllerUntouchInteractableObject; + + GameObject touchedObject = null; + SteamVR_TrackedObject trackedController; + SteamVR_ControllerActions controllerActions; + + public virtual void OnControllerTouchInteractableObject(ObjectInteractEventArgs e) + { + if (ControllerTouchInteractableObject != null) + ControllerTouchInteractableObject(this, e); + } + + public virtual void OnControllerUntouchInteractableObject(ObjectInteractEventArgs e) + { + if (ControllerUntouchInteractableObject != null) + ControllerUntouchInteractableObject(this, e); + } + + public ObjectInteractEventArgs SetControllerInteractEvent(GameObject target) + { + ObjectInteractEventArgs e; + e.controllerIndex = (uint)trackedController.index; + e.target = target; + return e; + } + + public GameObject GetTouchedObject() + { + return touchedObject; + } + + public bool IsObjectInteractable(GameObject obj) + { + return (obj && obj.GetComponent()); + } + + private void Awake() + { + trackedController = GetComponent(); + controllerActions = GetComponent(); + } + + private void Start() + { + if (GetComponent() == null) + { + Debug.LogError("SteamVR_InteractTouch is required to be attached to a SteamVR Controller that has the SteamVR_ControllerActions script attached to it"); + return; + } + + //Create trigger box collider for controller + SphereCollider collider = this.gameObject.AddComponent(); + collider.radius = 0.05f; + collider.center = new Vector3(0f, -0.035f, -0.01f); + collider.isTrigger = true; + } + + private void OnTriggerStay(Collider collider) + { + if (touchedObject == null && IsObjectInteractable(collider.gameObject)) + { + touchedObject = collider.gameObject; + OnControllerTouchInteractableObject(SetControllerInteractEvent(touchedObject)); + touchedObject.GetComponent().ToggleHighlight(true, globalTouchHighlightColor); + touchedObject.GetComponent().StartTouching(this.gameObject); + if (controllerActions.IsControllerVisible() && hideControllerOnTouch) + { + Invoke("HideController", hideControllerDelay); + } + } + } + + private void OnTriggerExit(Collider collider) + { + if (IsObjectInteractable(collider.gameObject)) + { + OnControllerUntouchInteractableObject(SetControllerInteractEvent(collider.gameObject)); + collider.GetComponent().ToggleHighlight(false); + collider.GetComponent().StopTouching(this.gameObject); + } + touchedObject = null; + if (hideControllerOnTouch) + { + controllerActions.ToggleControllerModel(true); + } + } + + private void HideController() + { + if (touchedObject != null) + { + controllerActions.ToggleControllerModel(false); + } + } +} diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractTouch.cs.meta b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractTouch.cs.meta new file mode 100755 index 0000000..2d62886 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractTouch.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 64e104da36bd3b04b90c6ae969ac66dc +timeCreated: 1461745433 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractUse.cs b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractUse.cs new file mode 100755 index 0000000..5d47596 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractUse.cs @@ -0,0 +1,154 @@ +//==================================================================================== +// +// Purpose: Provide ability to use an interactable object when it is being touched +// +// This script must be attached to a Controller within the [CameraRig] Prefab +// +// The SteamVR_ControllerEvents and SteamVR_InteractTouch scripts must also be +// attached to the Controller +// +// Press the default 'Trigger' button on the controller to use an object +// Released the default 'Trigger' button on the controller to stop using an object +// +//==================================================================================== + +using UnityEngine; +using System.Collections; + +public class SteamVR_InteractUse : MonoBehaviour +{ + public bool hideControllerOnUse = false; + public float hideControllerDelay = 0f; + + public event ObjectInteractEventHandler ControllerUseInteractableObject; + public event ObjectInteractEventHandler ControllerUnuseInteractableObject; + + GameObject usingObject = null; + SteamVR_InteractTouch interactTouch; + SteamVR_TrackedObject trackedController; + SteamVR_ControllerActions controllerActions; + + public virtual void OnControllerUseInteractableObject(ObjectInteractEventArgs e) + { + if (ControllerUseInteractableObject != null) + ControllerUseInteractableObject(this, e); + } + + public virtual void OnControllerUnuseInteractableObject(ObjectInteractEventArgs e) + { + if (ControllerUnuseInteractableObject != null) + ControllerUnuseInteractableObject(this, e); + } + + private void Awake() + { + if (GetComponent() == null) + { + Debug.LogError("SteamVR_InteractUse is required to be attached to a SteamVR Controller that has the SteamVR_InteractTouch script attached to it"); + return; + } + + interactTouch = GetComponent(); + trackedController = GetComponent(); + controllerActions = GetComponent(); + } + + private void Start() + { + if (GetComponent() == null) + { + Debug.LogError("SteamVR_InteractUse is required to be attached to a SteamVR Controller that has the SteamVR_ControllerEvents script attached to it"); + return; + } + + GetComponent().AliasUseOn += new ControllerClickedEventHandler(DoStartUseObject); + GetComponent().AliasUseOff += new ControllerClickedEventHandler(DoStopUseObject); + } + + private bool IsObjectUsable(GameObject obj) + { + return (interactTouch.IsObjectInteractable(obj) && obj.GetComponent().isUsable); + } + + private bool IsObjectHoldOnUse(GameObject obj) + { + return (obj && obj.GetComponent() && obj.GetComponent().holdButtonToUse); + } + + private int GetObjectUsingState(GameObject obj) + { + if (obj && obj.GetComponent()) + { + return obj.GetComponent().UsingState; + } + return 0; + } + + private void SetObjectUsingState(GameObject obj, int value) + { + if (obj && obj.GetComponent()) + { + obj.GetComponent().UsingState = value; + } + } + + private void UseInteractedObject(GameObject touchedObject) + { + if ((usingObject == null || usingObject != touchedObject) && IsObjectUsable(touchedObject)) + { + usingObject = touchedObject; + OnControllerUseInteractableObject(interactTouch.SetControllerInteractEvent(usingObject)); + usingObject.GetComponent().StartUsing(this.gameObject); + if (hideControllerOnUse) + { + Invoke("HideController", hideControllerDelay); + } + usingObject.GetComponent().ToggleHighlight(false); + } + } + + private void HideController() + { + if(usingObject != null) + { + controllerActions.ToggleControllerModel(false); + } + } + + private void UnuseInteractedObject() + { + if (usingObject != null) + { + OnControllerUnuseInteractableObject(interactTouch.SetControllerInteractEvent(usingObject)); + usingObject.GetComponent().StopUsing(this.gameObject); + if (hideControllerOnUse) + { + controllerActions.ToggleControllerModel(true); + } + usingObject.GetComponent().ToggleHighlight(false); + usingObject = null; + } + } + + private void DoStartUseObject(object sender, ControllerClickedEventArgs e) + { + GameObject touchedObject = interactTouch.GetTouchedObject(); + if (touchedObject != null && interactTouch.IsObjectInteractable(touchedObject)) + { + UseInteractedObject(touchedObject); + if (!IsObjectHoldOnUse(usingObject)) + { + SetObjectUsingState(usingObject, GetObjectUsingState(usingObject) + 1); + } + } + } + + private void DoStopUseObject(object sender, ControllerClickedEventArgs e) + { + if (IsObjectHoldOnUse(usingObject) || GetObjectUsingState(usingObject) >= 2) + { + SetObjectUsingState(usingObject, 0); + UnuseInteractedObject(); + } + } +} diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractUse.cs.meta b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractUse.cs.meta new file mode 100755 index 0000000..079e2d1 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractUse.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 65eb64f0f2fd6d64faddbcf5d7d3bdbb +timeCreated: 1461746619 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractableObject.cs b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractableObject.cs new file mode 100755 index 0000000..b76fb35 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractableObject.cs @@ -0,0 +1,345 @@ +//===================================================================================== +// +// Purpose: Provide a mechanism for determining if a game world object is interactable +// +// This script should be attached to any object that needs touch, use or grab +// +// An optional highlight color can be set to change the object's appearance if it is +// invoked. +// +//===================================================================================== + +using UnityEngine; +using System.Collections; +using System.Collections.Generic; + +public class SteamVR_InteractableObject : MonoBehaviour +{ + public enum GrabSnapType + { + Simple_Snap, + Rotation_Snap, + Precision_Snap + } + + public enum GrabAttatchType + { + Fixed_Joint, + Spring_Joint, + Track_Object + } + + [Header("Touch Interactions", order = 1)] + public bool highlightOnTouch = false; + public Color touchHighlightColor = Color.clear; + + [Header("Grab Interactions", order = 2)] + public bool isGrabbable = false; + public bool holdButtonToGrab = true; + public bool pauseCollisionsOnGrab = true; + public GrabSnapType grabSnapType = GrabSnapType.Simple_Snap; + public Vector3 snapToRotation = Vector3.zero; + public Vector3 snapToPosition = Vector3.zero; + + [Header("Grab Mechanics", order = 3)] + public GrabAttatchType grabAttatchMechanic = GrabAttatchType.Fixed_Joint; + public float detatchThreshold = 500f; + public float springJointStrength = 500f; + public float springJointDamper = 50f; + + [Header("Use Interactions", order = 4)] + public bool isUsable = false; + public bool holdButtonToUse = true; + public bool pointerActivatesUseAction = false; + + protected Rigidbody rb; + protected GameObject grabbingObject = null; + + private bool isTouched = false; + private bool isUsing = false; + private int usingState = 0; + private Color[] originalObjectColours = null; + + private Transform trackPoint; + private bool customTrackPoint = false; + + public bool IsTouched() + { + return isTouched; + } + + public bool IsGrabbed() + { + return (grabbingObject != null); + } + + public bool IsUsing() + { + return isUsing; + } + + public virtual void StartTouching(GameObject touchingObject) + { + isTouched = true; + } + + public virtual void StopTouching(GameObject previousTouchingObject) + { + isTouched = false; + } + + public virtual void Grabbed(GameObject currentGrabbingObject) + { + ForceReleaseGrab(); + RemoveTrackPoint(); + grabbingObject = currentGrabbingObject; + SetTrackPoint(grabbingObject); + } + + public virtual void Ungrabbed(GameObject previousGrabbingObject) + { + RemoveTrackPoint(); + grabbingObject = null; + } + + public virtual void StartUsing(GameObject usingObject) + { + isUsing = true; + } + + public virtual void StopUsing(GameObject previousUsingObject) + { + isUsing = false; + } + + public virtual void ToggleHighlight(bool toggle) + { + ToggleHighlight(toggle, Color.clear); + } + + public virtual void ToggleHighlight(bool toggle, Color globalHighlightColor) + { + if (highlightOnTouch) + { + if (toggle && !IsGrabbed() && !isUsing) + { + Color color = (touchHighlightColor != Color.clear ? touchHighlightColor : globalHighlightColor); + if (color != Color.clear) + { + var colorArray = BuildHighlightColorArray(color); + ChangeColor(colorArray); + } + } + else + { + if(originalObjectColours == null) + { + Debug.LogError("SteamVR_InteractableObject has not had the Start() method called, if you are inheriting this class then call base.Start() in your Start() method. [Error raised on line 78 of SteamVR_InteractableObject.cs]"); + return; + } + ChangeColor(originalObjectColours); + } + } + } + + public int UsingState + { + get { return usingState; } + set{ usingState = value; } + } + + public void PauseCollisions(float pauseTime) + { + if (pauseCollisionsOnGrab) + { + if (this.GetComponent()) + { + this.GetComponent().detectCollisions = false; + } + foreach (Rigidbody rb in this.GetComponentsInChildren()) + { + rb.detectCollisions = false; + } + Invoke("UnpauseCollisions", pauseTime); + } + } + + public bool AttatchIsTrackObject() + { + return (grabAttatchMechanic == GrabAttatchType.Track_Object); + } + + protected virtual void Awake() + { + rb = this.GetComponent(); + } + + protected virtual void Start() + { + originalObjectColours = StoreOriginalColors(); + } + + protected virtual void Update() + { + if (grabAttatchMechanic == GrabAttatchType.Track_Object) + { + CheckBreakDistance(); + } + } + + protected virtual void FixedUpdate() + { + if (grabAttatchMechanic == GrabAttatchType.Track_Object) + { + FixedUpdateTrackedObject(); + } + } + + protected virtual void OnJointBreak(float force) + { + ForceReleaseGrab(); + } + + private void ForceReleaseGrab() + { + if (grabbingObject) + { + grabbingObject.GetComponent().ForceRelease(); + } + } + + private void UnpauseCollisions() + { + if (this.GetComponent()) + { + this.GetComponent().detectCollisions = true; + } + foreach (Rigidbody rb in this.GetComponentsInChildren()) + { + rb.detectCollisions = true; + } + } + + private Renderer[] GetRendererArray() + { + return (GetComponents().Length > 0 ? GetComponents() : GetComponentsInChildren()); + } + + private Color[] StoreOriginalColors() + { + Renderer[] rendererArray = GetRendererArray(); + int length = rendererArray.Length; + Color[] colors = new Color[length]; + + for (int i = 0; i < length; i++) + { + var renderer = rendererArray[i]; + if (renderer.material.HasProperty("_Color")) + { + colors[i] = renderer.material.color; + } + } + return colors; + } + + private Color[] BuildHighlightColorArray(Color color) + { + Renderer[] rendererArray = GetRendererArray(); + int length = rendererArray.Length; + Color[] colors = new Color[length]; + + for (int i = 0; i < length; i++) + { + colors[i] = color; + } + return colors; + } + + private void ChangeColor(Color[] colors) + { + Renderer[] rendererArray = GetRendererArray(); + int i = 0; + foreach (Renderer renderer in rendererArray) + { + if (renderer.material.HasProperty("_Color")) + { + renderer.material.color = colors[i]; + } + i++; + } + } + + private void CheckBreakDistance() + { + if(trackPoint) + { + float distance = Vector3.Distance(trackPoint.position, this.transform.position); + if (distance > (detatchThreshold / 1000)) + { + ForceReleaseGrab(); + } + } + } + + private void SetTrackPoint(GameObject point) + { + Transform controllerPoint = point.transform; + + if (point.GetComponent() && point.GetComponent().controllerAttachPoint) + { + controllerPoint = point.GetComponent().controllerAttachPoint.transform; + } + + if (grabAttatchMechanic == GrabAttatchType.Track_Object && grabSnapType == GrabSnapType.Precision_Snap) + { + trackPoint = new GameObject(string.Format("[{0}]TrackObject_PrecisionSnap_AttatchPoint", this.gameObject.name)).transform; + trackPoint.parent = point.transform; + trackPoint.position = this.transform.position; + trackPoint.rotation = this.transform.rotation; + customTrackPoint = true; + } else + { + trackPoint = controllerPoint; + customTrackPoint = false; + } + } + + private void RemoveTrackPoint() + { + if (customTrackPoint && trackPoint) + { + Destroy(trackPoint.gameObject); + } + else + { + trackPoint = null; + } + } + + private void FixedUpdateTrackedObject() + { + if (trackPoint) + { + float rotationMultiplier = 20f; + float positionMultiplier = 3000f; + float maxDistanceDelta = 10f; + + Quaternion rotationDelta = trackPoint.rotation * Quaternion.Inverse(this.transform.rotation); + Vector3 positionDelta = (trackPoint.position - this.transform.position); + + float angle; + Vector3 axis; + rotationDelta.ToAngleAxis(out angle, out axis); + angle = (angle > 180 ? angle -= 360 : angle); + + if (angle != 0) + { + Vector3 AngularTarget = (Time.fixedDeltaTime * angle * axis) * rotationMultiplier; + rb.angularVelocity = Vector3.MoveTowards(rb.angularVelocity, AngularTarget, maxDistanceDelta); + } + + Vector3 VelocityTarget = positionDelta * positionMultiplier * Time.fixedDeltaTime; + rb.velocity = Vector3.MoveTowards(rb.velocity, VelocityTarget, maxDistanceDelta); + } + } +} \ No newline at end of file diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractableObject.cs.meta b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractableObject.cs.meta new file mode 100755 index 0000000..cd9ae6e --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_InteractableObject.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a3abaf4521bf2344ea21ed3020b98eb2 +timeCreated: 1461583046 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_TouchpadWalking.cs b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_TouchpadWalking.cs new file mode 100755 index 0000000..7369252 --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_TouchpadWalking.cs @@ -0,0 +1,208 @@ +using UnityEngine; +using System.Collections; + +public class SteamVR_TouchpadWalking : MonoBehaviour { + public float maxWalkSpeed = 3f; + public float deceleration = 0.1f; + public float headsetYOffset = 0.2f; + public bool ignoreGrabbedCollisions = true; + + private float movementSpeed = 0f; + private float strafeSpeed = 0f; + private int listenerInitTries = 5; + + private Transform headset; + private Vector2 touchAxis; + + private Rigidbody rb; + private BoxCollider bc; + + private GameObject floorTouching; + private Vector3 lastGoodPosition; + private bool lastGoodPositionSet = false; + private float highestHeadsetY = 0f; + private float crouchMargin = 0.5f; + private float lastPlayAreaY = 0f; + + private void Start () { + this.name = "PlayerObject_" + this.name; + lastGoodPositionSet = false; + headset = GetHeadset(); + CreateCollider(); + InitListeners(); + } + + private Transform GetHeadset() + { +#if (UNITY_5_4_OR_NEWER) + return GameObject.FindObjectOfType().GetComponent(); +#endif + return GameObject.FindObjectOfType().GetComponent(); + } + + private void InitListeners() + { + SteamVR_ControllerEvents[] controllers = GameObject.FindObjectsOfType(); + if (controllers.Length == 0) + { + if (listenerInitTries > 0) + { + listenerInitTries--; + Invoke("InitListeners", 0.25f); + } + else + { + Debug.LogError("A GameObject must exist with a SteamVR_ControllerEvents script attached to it"); + return; + } + } + + foreach (SteamVR_ControllerEvents controller in controllers) + { + controller.TouchpadAxisChanged += new ControllerClickedEventHandler(DoTouchpadAxisChanged); + controller.TouchpadUntouched += new ControllerClickedEventHandler(DoTouchpadUntouched); + + if (ignoreGrabbedCollisions && controller.GetComponent()) + { + SteamVR_InteractGrab grabbingController = controller.GetComponent(); + grabbingController.ControllerGrabInteractableObject += new ObjectInteractEventHandler(OnGrabObject); + grabbingController.ControllerUngrabInteractableObject += new ObjectInteractEventHandler(OnUngrabObject); + } + } + + if (headset.GetComponent()) + { + headset.GetComponent().HeadsetCollisionDetect += new HeadsetCollisionEventHandler(OnHeadsetCollision); + } + } + + private void OnGrabObject(object sender, ObjectInteractEventArgs e) + { + Physics.IgnoreCollision(this.GetComponent(), e.target.GetComponent(), true); + } + + private void OnUngrabObject(object sender, ObjectInteractEventArgs e) + { + Physics.IgnoreCollision(this.GetComponent(), e.target.GetComponent(), false); + } + + private void OnHeadsetCollision(object sender, HeadsetCollisionEventArgs e) + { + if (lastGoodPositionSet) { + SteamVR_Fade.Start(Color.black, 0f); + this.transform.position = lastGoodPosition; + } + } + + private void CreateCollider() + { + rb = this.gameObject.AddComponent(); + rb.mass = 100; + rb.freezeRotation = true; + + bc = this.gameObject.AddComponent(); + bc.center = new Vector3(0f, 1f, 0f); + bc.size = new Vector3(0.25f, 1f, 0.25f); + + this.gameObject.layer = 2; + } + + private void DoTouchpadAxisChanged(object sender, ControllerClickedEventArgs e) + { + touchAxis = e.touchpadAxis; + } + + private void DoTouchpadUntouched(object sender, ControllerClickedEventArgs e) + { + touchAxis = Vector2.zero; + } + + private void CalculateSpeed(ref float speed, float inputValue) + { + if (inputValue != 0f) + { + speed = (maxWalkSpeed * inputValue); + } + else + { + Decelerate(ref speed); + } + } + + private void Decelerate(ref float speed) + { + if (speed > 0) + { + speed -= Mathf.Lerp(deceleration, maxWalkSpeed, 0f); + } + else if (speed < 0) + { + speed += Mathf.Lerp(deceleration, -maxWalkSpeed, 0f); + } + else + { + speed = 0; + } + + float deadzone = 0.1f; + if (speed < deadzone && speed > -deadzone) + { + speed = 0; + } + } + + private void Move() + { + Vector3 movement = headset.transform.forward * movementSpeed * Time.deltaTime; + Vector3 strafe = headset.transform.right * strafeSpeed * Time.deltaTime; + float fixY = this.transform.position.y; + this.transform.position += (movement + strafe); + this.transform.position = new Vector3(this.transform.position.x, fixY, this.transform.position.z); + } + + private void UpdateCollider() + { + float playAreaHeightAdjustment = 0.009f; + float newBCYSize = (headset.transform.position.y - headsetYOffset) - this.transform.position.y; + float newBCYCenter = (newBCYSize != 0 ? (newBCYSize / 2) + playAreaHeightAdjustment: 0); + + bc.size = new Vector3(bc.size.x, newBCYSize, bc.size.z); + bc.center = new Vector3(headset.localPosition.x, newBCYCenter, headset.localPosition.z); + } + + private void SetHeadsetY() + { + //if the play area height has changed then always recalc headset height + float floorVariant = 0.005f; + if (this.transform.position.y > lastPlayAreaY + floorVariant || this.transform.position.y < lastPlayAreaY - floorVariant) + { + highestHeadsetY = 0f; + } + + if (headset.transform.position.y > highestHeadsetY) + { + highestHeadsetY = headset.transform.position.y; + } + + if (headset.transform.position.y > highestHeadsetY - crouchMargin) + { + lastGoodPositionSet = true; + lastGoodPosition = this.transform.position; + } + + lastPlayAreaY = this.transform.position.y; + } + + private void Update() + { + SetHeadsetY(); + UpdateCollider(); + } + + private void FixedUpdate() + { + CalculateSpeed(ref movementSpeed, touchAxis.y); + CalculateSpeed(ref strafeSpeed, touchAxis.x); + Move(); + } +} \ No newline at end of file diff --git a/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_TouchpadWalking.cs.meta b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_TouchpadWalking.cs.meta new file mode 100755 index 0000000..09a868b --- /dev/null +++ b/Assets/SteamVR_Unity_Toolkit/Scripts/SteamVR_TouchpadWalking.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b0a3634ed0880214bb405386bdad8e93 +timeCreated: 1462638636 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Test.unity b/Assets/Test.unity index 56656ed..d8fa2c1 100755 Binary files a/Assets/Test.unity and b/Assets/Test.unity differ diff --git a/Assets/WarehouseItem.cs b/Assets/WarehouseItem.cs index ebe0a78..29289a4 100755 --- a/Assets/WarehouseItem.cs +++ b/Assets/WarehouseItem.cs @@ -1,7 +1,41 @@ using UnityEngine; using System.Collections; -public class WarehouseItem : MonoBehaviour { +public class WarehouseItem : FurnitureObject { + + public override void Grab(Transform attachment) { + var replacement = GameObject.Instantiate(this); + replacement.transform.parent = transform.parent; + replacement.transform.SetSiblingIndex(transform.GetSiblingIndex()); + + transform.parent = null; + foreach (var collider in GetComponentsInChildren()) { + collider.enabled = false; + } + GetComponent().isKinematic = true; + + var mini = gameObject.AddComponent(); + mini.OriginItem = replacement; + mini.DestinationAttachment = attachment; + mini.Duration = 0.33f; + mini.GoalScale = new Vector3(0.05f, 0.05f, 0.05f); + } + + public override void Release() { + var mini = gameObject.GetComponent(); + if (mini) { + mini.End(); + } + + transform.parent = null; + foreach (var collider in GetComponentsInChildren()) { + collider.enabled = true; + } + GetComponent().isKinematic = false; + + gameObject.AddComponent(); + Destroy(this); + } // Use this for initialization void Start () { diff --git a/Assets/WarehouseMiniatureAnim.cs b/Assets/WarehouseMiniatureAnim.cs new file mode 100755 index 0000000..a01eba2 --- /dev/null +++ b/Assets/WarehouseMiniatureAnim.cs @@ -0,0 +1,42 @@ +using UnityEngine; +using System.Collections; + +public class WarehouseMiniatureAnim : MonoBehaviour { + + public WarehouseItem OriginItem; + public Transform DestinationAttachment; + public Vector3 GoalScale = Vector3.one; + public float Duration = 1.0f; + + Vector3 originalPos; + Vector3 originalScale; + float alpha = 0.0f; + + void Start () { + originalPos = transform.position; + originalScale = Vector3.Scale(transform.localScale, GoalScale); + } + + void Update () { + alpha += Time.deltaTime / Duration; + + if (alpha > 1) { + End(); + return; + } + + var t2 = DestinationAttachment.transform; + var startPos = OriginItem ? OriginItem.transform.position : originalPos; + transform.position = Vector3.Lerp(startPos, t2.position, alpha); + //transform.rotation = Quaternion.Slerp(transform.rotation, t2.rotation, alpha); + var startScale = OriginItem ? OriginItem.transform.localScale : originalScale; + transform.localScale = Vector3.Lerp(startScale, Vector3.Scale(originalScale, t2.lossyScale), alpha); + } + + public void End() { + transform.SetParent(DestinationAttachment, false); + transform.localPosition = Vector3.zero; + transform.localScale = originalScale; + Destroy(this); + } +} diff --git a/Assets/WarehouseMiniatureAnim.cs.meta b/Assets/WarehouseMiniatureAnim.cs.meta new file mode 100755 index 0000000..b4bf7c3 --- /dev/null +++ b/Assets/WarehouseMiniatureAnim.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 466a12fccfe5d204ab533593ac72ee96 +timeCreated: 1464215897 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: