//======= Copyright (c) Valve Corporation, All rights reserved. =============== // // Purpose: Example menu using OnGUI with SteamVR_Camera's overlay support // //============================================================================= using UnityEngine; using Valve.VR; namespace Valve.VR { public class SteamVR_Menu : MonoBehaviour { public Texture cursor, background, logo; public float logoHeight, menuOffset; public Vector2 scaleLimits = new Vector2(0.1f, 5.0f); public float scaleRate = 0.5f; SteamVR_Overlay overlay; Camera overlayCam; Vector4 uvOffset; float distance; public RenderTexture texture { get { return overlay ? overlay.texture as RenderTexture : null; } } public float scale { get; private set; } string scaleLimitX, scaleLimitY, scaleRateText; CursorLockMode savedCursorLockState; bool savedCursorVisible; void Awake() { scaleLimitX = string.Format("{0:N1}", scaleLimits.x); scaleLimitY = string.Format("{0:N1}", scaleLimits.y); scaleRateText = string.Format("{0:N1}", scaleRate); var overlay = SteamVR_Overlay.instance; if (overlay != null) { uvOffset = overlay.uvOffset; distance = overlay.distance; } } void OnGUI() { if (overlay == null) return; var texture = overlay.texture as RenderTexture; var prevActive = RenderTexture.active; RenderTexture.active = texture; if (Event.current.type == EventType.Repaint) GL.Clear(false, true, Color.clear); var area = new Rect(0, 0, texture.width, texture.height); // Account for screen smaller than texture (since mouse position gets clamped) if (Screen.width < texture.width) { area.width = Screen.width; overlay.uvOffset.x = -(float)(texture.width - Screen.width) / (2 * texture.width); } if (Screen.height < texture.height) { area.height = Screen.height; overlay.uvOffset.y = (float)(texture.height - Screen.height) / (2 * texture.height); } GUILayout.BeginArea(area); if (background != null) { GUI.DrawTexture(new Rect( (area.width - background.width) / 2, (area.height - background.height) / 2, background.width, background.height), background); } GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); GUILayout.BeginVertical(); if (logo != null) { GUILayout.Space(area.height / 2 - logoHeight); GUILayout.Box(logo); } GUILayout.Space(menuOffset); bool bHideMenu = GUILayout.Button("[Esc] - Close menu"); GUILayout.BeginHorizontal(); GUILayout.Label(string.Format("Scale: {0:N4}", scale)); { var result = GUILayout.HorizontalSlider(scale, scaleLimits.x, scaleLimits.y); if (result != scale) { SetScale(result); } } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label(string.Format("Scale limits:")); { var result = GUILayout.TextField(scaleLimitX); if (result != scaleLimitX) { if (float.TryParse(result, out scaleLimits.x)) scaleLimitX = result; } } { var result = GUILayout.TextField(scaleLimitY); if (result != scaleLimitY) { if (float.TryParse(result, out scaleLimits.y)) scaleLimitY = result; } } GUILayout.EndHorizontal(); GUILayout.BeginHorizontal(); GUILayout.Label(string.Format("Scale rate:")); { var result = GUILayout.TextField(scaleRateText); if (result != scaleRateText) { if (float.TryParse(result, out scaleRate)) scaleRateText = result; } } GUILayout.EndHorizontal(); if (SteamVR.active) { var vr = SteamVR.instance; GUILayout.BeginHorizontal(); { var t = SteamVR_Camera.sceneResolutionScale; int w = (int)(vr.sceneWidth * t); int h = (int)(vr.sceneHeight * t); int pct = (int)(100.0f * t); GUILayout.Label(string.Format("Scene quality: {0}x{1} ({2}%)", w, h, pct)); var result = Mathf.RoundToInt(GUILayout.HorizontalSlider(pct, 50, 200)); if (result != pct) { SteamVR_Camera.sceneResolutionScale = (float)result / 100.0f; } } GUILayout.EndHorizontal(); } var tracker = SteamVR_Render.Top(); if (tracker != null) { tracker.wireframe = GUILayout.Toggle(tracker.wireframe, "Wireframe"); if (SteamVR.settings.trackingSpace == ETrackingUniverseOrigin.TrackingUniverseSeated) { if (GUILayout.Button("Switch to Standing")) SteamVR.settings.trackingSpace = ETrackingUniverseOrigin.TrackingUniverseStanding; if (GUILayout.Button("Center View")) { var system = OpenVR.System; if (system != null) system.ResetSeatedZeroPose(); } } else { if (GUILayout.Button("Switch to Seated")) SteamVR.settings.trackingSpace = ETrackingUniverseOrigin.TrackingUniverseSeated; } } #if !UNITY_EDITOR if (GUILayout.Button("Exit")) Application.Quit(); #endif GUILayout.Space(menuOffset); var env = System.Environment.GetEnvironmentVariable("VR_OVERRIDE"); if (env != null) { GUILayout.Label("VR_OVERRIDE=" + env); } GUILayout.Label("Graphics device: " + SystemInfo.graphicsDeviceVersion); GUILayout.EndVertical(); GUILayout.FlexibleSpace(); GUILayout.EndHorizontal(); GUILayout.EndArea(); if (cursor != null) { float x = Input.mousePosition.x, y = Screen.height - Input.mousePosition.y; float w = cursor.width, h = cursor.height; GUI.DrawTexture(new Rect(x, y, w, h), cursor); } RenderTexture.active = prevActive; if (bHideMenu) HideMenu(); } public void ShowMenu() { var overlay = SteamVR_Overlay.instance; if (overlay == null) return; var texture = overlay.texture as RenderTexture; if (texture == null) { Debug.LogError("[SteamVR] Menu requires overlay texture to be a render texture.", this); return; } SaveCursorState(); Cursor.visible = true; Cursor.lockState = CursorLockMode.None; this.overlay = overlay; uvOffset = overlay.uvOffset; distance = overlay.distance; // If an existing camera is rendering into the overlay texture, we need // to temporarily disable it to keep it from clearing the texture on us. var cameras = Object.FindObjectsOfType(typeof(Camera)) as Camera[]; foreach (var cam in cameras) { if (cam.enabled && cam.targetTexture == texture) { overlayCam = cam; overlayCam.enabled = false; break; } } var tracker = SteamVR_Render.Top(); if (tracker != null) scale = tracker.origin.localScale.x; } public void HideMenu() { RestoreCursorState(); if (overlayCam != null) overlayCam.enabled = true; if (overlay != null) { overlay.uvOffset = uvOffset; overlay.distance = distance; overlay = null; } } void Update() { if (Input.GetKeyDown(KeyCode.Escape) || Input.GetKeyDown(KeyCode.Joystick1Button7)) { if (overlay == null) { ShowMenu(); } else { HideMenu(); } } else if (Input.GetKeyDown(KeyCode.Home)) { SetScale(1.0f); } else if (Input.GetKey(KeyCode.PageUp)) { SetScale(Mathf.Clamp(scale + scaleRate * Time.deltaTime, scaleLimits.x, scaleLimits.y)); } else if (Input.GetKey(KeyCode.PageDown)) { SetScale(Mathf.Clamp(scale - scaleRate * Time.deltaTime, scaleLimits.x, scaleLimits.y)); } } void SetScale(float scale) { this.scale = scale; var tracker = SteamVR_Render.Top(); if (tracker != null) tracker.origin.localScale = new Vector3(scale, scale, scale); } void SaveCursorState() { savedCursorVisible = Cursor.visible; savedCursorLockState = Cursor.lockState; } void RestoreCursorState() { Cursor.visible = savedCursorVisible; Cursor.lockState = savedCursorLockState; } } }