Initialer Upload neues Unity-Projekt
This commit is contained in:
502
Assets/SteamVR/Scripts/SteamVR_LoadLevel.cs
Normal file
502
Assets/SteamVR/Scripts/SteamVR_LoadLevel.cs
Normal file
@ -0,0 +1,502 @@
|
||||
//======= Copyright (c) Valve Corporation, All rights reserved. ===============
|
||||
//
|
||||
// Purpose: Helper for smoothing over transitions between levels.
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using Valve.VR;
|
||||
using System.IO;
|
||||
|
||||
namespace Valve.VR
|
||||
{
|
||||
public class SteamVR_LoadLevel : MonoBehaviour
|
||||
{
|
||||
private static SteamVR_LoadLevel _active = null;
|
||||
public static bool loading { get { return _active != null; } }
|
||||
public static float progress
|
||||
{
|
||||
get { return (_active != null && _active.async != null) ? _active.async.progress : 0.0f; }
|
||||
}
|
||||
public static Texture progressTexture
|
||||
{
|
||||
get { return (_active != null) ? _active.renderTexture : null; }
|
||||
}
|
||||
|
||||
// Name of level to load.
|
||||
public string levelName;
|
||||
|
||||
// Name of internal process to launch (instead of levelName).
|
||||
public string internalProcessPath;
|
||||
|
||||
// The command-line args for the internal process to launch.
|
||||
public string internalProcessArgs;
|
||||
|
||||
// If true, call LoadLevelAdditiveAsync instead of LoadLevelAsync.
|
||||
public bool loadAdditive;
|
||||
|
||||
// Async load causes crashes in some apps.
|
||||
public bool loadAsync = true;
|
||||
|
||||
// Optional logo texture.
|
||||
public Texture loadingScreen;
|
||||
|
||||
// Optional progress bar textures.
|
||||
public Texture progressBarEmpty, progressBarFull;
|
||||
|
||||
// Sizes of overlays.
|
||||
public float loadingScreenWidthInMeters = 6.0f;
|
||||
public float progressBarWidthInMeters = 3.0f;
|
||||
|
||||
// If specified, the loading screen will be positioned in the player's view this far away.
|
||||
public float loadingScreenDistance = 0.0f;
|
||||
|
||||
// Optional overrides for where to display loading screen and progress bar overlays.
|
||||
// Otherwise defaults to using this object's transform.
|
||||
public Transform loadingScreenTransform, progressBarTransform;
|
||||
|
||||
// Optional skybox override textures.
|
||||
public Texture front, back, left, right, top, bottom;
|
||||
|
||||
// Colors to use when dropping to the compositor between levels if no skybox is set.
|
||||
public Color backgroundColor = Color.black;
|
||||
|
||||
// If false, the background color above gets applied as the foreground color in the compositor.
|
||||
// This does not have any effect when using a skybox instead.
|
||||
public bool showGrid = false;
|
||||
|
||||
// Time to fade from current scene to the compositor and back.
|
||||
public float fadeOutTime = 0.5f;
|
||||
public float fadeInTime = 0.5f;
|
||||
|
||||
// Additional time to wait after finished loading before we start fading the new scene back in.
|
||||
// This is to cover up any initial hitching that takes place right at the start of levels.
|
||||
// Most scenes should hopefully not require this.
|
||||
public float postLoadSettleTime = 0.0f;
|
||||
|
||||
// Time to fade loading screen in and out (also used for progress bar).
|
||||
public float loadingScreenFadeInTime = 1.0f;
|
||||
public float loadingScreenFadeOutTime = 0.25f;
|
||||
|
||||
float fadeRate = 1.0f;
|
||||
float alpha = 0.0f;
|
||||
|
||||
AsyncOperation async; // used to track level load progress
|
||||
RenderTexture renderTexture; // used to render progress bar
|
||||
|
||||
ulong loadingScreenOverlayHandle = OpenVR.k_ulOverlayHandleInvalid;
|
||||
ulong progressBarOverlayHandle = OpenVR.k_ulOverlayHandleInvalid;
|
||||
|
||||
public bool autoTriggerOnEnable = false;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
if (autoTriggerOnEnable)
|
||||
Trigger();
|
||||
}
|
||||
|
||||
public void Trigger()
|
||||
{
|
||||
if (!loading && !string.IsNullOrEmpty(levelName))
|
||||
StartCoroutine(LoadLevel());
|
||||
}
|
||||
|
||||
// Helper function to quickly and simply load a level from script.
|
||||
public static void Begin(string levelName,
|
||||
bool showGrid = false, float fadeOutTime = 0.5f,
|
||||
float r = 0.0f, float g = 0.0f, float b = 0.0f, float a = 1.0f)
|
||||
{
|
||||
var loader = new GameObject("loader").AddComponent<SteamVR_LoadLevel>();
|
||||
loader.levelName = levelName;
|
||||
loader.showGrid = showGrid;
|
||||
loader.fadeOutTime = fadeOutTime;
|
||||
loader.backgroundColor = new Color(r, g, b, a);
|
||||
loader.Trigger();
|
||||
}
|
||||
|
||||
// Updates progress bar.
|
||||
void OnGUI()
|
||||
{
|
||||
if (_active != this)
|
||||
return;
|
||||
|
||||
// Optionally create an overlay for our progress bar to use, separate from the loading screen.
|
||||
if (progressBarEmpty != null && progressBarFull != null)
|
||||
{
|
||||
if (progressBarOverlayHandle == OpenVR.k_ulOverlayHandleInvalid)
|
||||
progressBarOverlayHandle = GetOverlayHandle("progressBar", progressBarTransform != null ? progressBarTransform : transform, progressBarWidthInMeters);
|
||||
|
||||
if (progressBarOverlayHandle != OpenVR.k_ulOverlayHandleInvalid)
|
||||
{
|
||||
var progress = (async != null) ? async.progress : 0.0f;
|
||||
|
||||
// Use the full bar size for everything.
|
||||
var w = progressBarFull.width;
|
||||
var h = progressBarFull.height;
|
||||
|
||||
// Create a separate render texture so we can composite the full image on top of the empty one.
|
||||
if (renderTexture == null)
|
||||
{
|
||||
renderTexture = new RenderTexture(w, h, 0);
|
||||
renderTexture.Create();
|
||||
}
|
||||
|
||||
var prevActive = RenderTexture.active;
|
||||
RenderTexture.active = renderTexture;
|
||||
|
||||
if (Event.current.type == EventType.Repaint)
|
||||
GL.Clear(false, true, Color.clear);
|
||||
|
||||
GUILayout.BeginArea(new Rect(0, 0, w, h));
|
||||
|
||||
GUI.DrawTexture(new Rect(0, 0, w, h), progressBarEmpty);
|
||||
|
||||
// Reveal the full bar texture based on progress.
|
||||
GUI.DrawTextureWithTexCoords(new Rect(0, 0, progress * w, h), progressBarFull, new Rect(0.0f, 0.0f, progress, 1.0f));
|
||||
|
||||
GUILayout.EndArea();
|
||||
|
||||
RenderTexture.active = prevActive;
|
||||
|
||||
// Texture needs to be set every frame after it is updated since SteamVR makes a copy internally to a shared texture.
|
||||
var overlay = OpenVR.Overlay;
|
||||
if (overlay != null)
|
||||
{
|
||||
var texture = new Texture_t();
|
||||
texture.handle = renderTexture.GetNativeTexturePtr();
|
||||
texture.eType = SteamVR.instance.textureType;
|
||||
texture.eColorSpace = EColorSpace.Auto;
|
||||
overlay.SetOverlayTexture(progressBarOverlayHandle, ref texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if false
|
||||
// Draw loading screen and progress bar to 2d companion window as well.
|
||||
if (loadingScreen != null)
|
||||
{
|
||||
var screenAspect = (float)Screen.width / Screen.height;
|
||||
var textureAspect = (float)loadingScreen.width / loadingScreen.height;
|
||||
|
||||
float w, h;
|
||||
if (screenAspect < textureAspect)
|
||||
{
|
||||
// Clamp horizontally
|
||||
w = Screen.width * 0.9f;
|
||||
h = w / textureAspect;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Clamp vertically
|
||||
h = Screen.height * 0.9f;
|
||||
w = h * textureAspect;
|
||||
}
|
||||
|
||||
GUILayout.BeginArea(new Rect(0, 0, Screen.width, Screen.height));
|
||||
|
||||
var x = Screen.width / 2 - w / 2;
|
||||
var y = Screen.height / 2 - h / 2;
|
||||
GUI.DrawTexture(new Rect(x, y, w, h), loadingScreen);
|
||||
|
||||
GUILayout.EndArea();
|
||||
}
|
||||
|
||||
if (renderTexture != null)
|
||||
{
|
||||
var x = Screen.width / 2 - renderTexture.width / 2;
|
||||
var y = Screen.height * 0.9f - renderTexture.height;
|
||||
GUI.DrawTexture(new Rect(x, y, renderTexture.width, renderTexture.height), renderTexture);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Fade our overlays in/out over time.
|
||||
void Update()
|
||||
{
|
||||
if (_active != this)
|
||||
return;
|
||||
|
||||
alpha = Mathf.Clamp01(alpha + fadeRate * Time.deltaTime);
|
||||
|
||||
var overlay = OpenVR.Overlay;
|
||||
if (overlay != null)
|
||||
{
|
||||
if (loadingScreenOverlayHandle != OpenVR.k_ulOverlayHandleInvalid)
|
||||
overlay.SetOverlayAlpha(loadingScreenOverlayHandle, alpha);
|
||||
|
||||
if (progressBarOverlayHandle != OpenVR.k_ulOverlayHandleInvalid)
|
||||
overlay.SetOverlayAlpha(progressBarOverlayHandle, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
// Corourtine to handle all the steps across loading boundaries.
|
||||
IEnumerator LoadLevel()
|
||||
{
|
||||
// Optionally rotate loading screen transform around the camera into view.
|
||||
// We assume here that the loading screen is already facing toward the origin,
|
||||
// and that the progress bar transform (if any) is a child and will follow along.
|
||||
if (loadingScreen != null && loadingScreenDistance > 0.0f)
|
||||
{
|
||||
Transform hmd = this.transform;
|
||||
if (Camera.main != null)
|
||||
hmd = Camera.main.transform;
|
||||
|
||||
Quaternion rot = Quaternion.Euler(0.0f, hmd.eulerAngles.y, 0.0f);
|
||||
Vector3 pos = hmd.position + (rot * new Vector3(0.0f, 0.0f, loadingScreenDistance));
|
||||
|
||||
var t = loadingScreenTransform != null ? loadingScreenTransform : transform;
|
||||
t.position = pos;
|
||||
t.rotation = rot;
|
||||
}
|
||||
|
||||
_active = this;
|
||||
|
||||
SteamVR_Events.Loading.Send(true);
|
||||
|
||||
// Calculate rate for fading in loading screen and progress bar.
|
||||
if (loadingScreenFadeInTime > 0.0f)
|
||||
{
|
||||
fadeRate = 1.0f / loadingScreenFadeInTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = 1.0f;
|
||||
}
|
||||
|
||||
var overlay = OpenVR.Overlay;
|
||||
|
||||
// Optionally create our loading screen overlay.
|
||||
if (loadingScreen != null && overlay != null)
|
||||
{
|
||||
loadingScreenOverlayHandle = GetOverlayHandle("loadingScreen", loadingScreenTransform != null ? loadingScreenTransform : transform, loadingScreenWidthInMeters);
|
||||
if (loadingScreenOverlayHandle != OpenVR.k_ulOverlayHandleInvalid)
|
||||
{
|
||||
var texture = new Texture_t();
|
||||
texture.handle = loadingScreen.GetNativeTexturePtr();
|
||||
texture.eType = SteamVR.instance.textureType;
|
||||
texture.eColorSpace = EColorSpace.Auto;
|
||||
overlay.SetOverlayTexture(loadingScreenOverlayHandle, ref texture);
|
||||
}
|
||||
}
|
||||
|
||||
bool fadedForeground = false;
|
||||
|
||||
// Fade out to compositor
|
||||
SteamVR_Events.LoadingFadeOut.Send(fadeOutTime);
|
||||
|
||||
// Optionally set a skybox to use as a backdrop in the compositor.
|
||||
var compositor = OpenVR.Compositor;
|
||||
if (compositor != null)
|
||||
{
|
||||
if (front != null)
|
||||
{
|
||||
SteamVR_Skybox.SetOverride(front, back, left, right, top, bottom);
|
||||
|
||||
// Explicitly fade to the compositor since loading will cause us to stop rendering.
|
||||
compositor.FadeGrid(fadeOutTime, true);
|
||||
yield return new WaitForSeconds(fadeOutTime);
|
||||
}
|
||||
else if (backgroundColor != Color.clear)
|
||||
{
|
||||
// Otherwise, use the specified background color.
|
||||
if (showGrid)
|
||||
{
|
||||
// Set compositor background color immediately, and start fading to it.
|
||||
compositor.FadeToColor(0.0f, backgroundColor.r, backgroundColor.g, backgroundColor.b, backgroundColor.a, true);
|
||||
compositor.FadeGrid(fadeOutTime, true);
|
||||
yield return new WaitForSeconds(fadeOutTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fade the foreground color in (which will blend on top of the scene), and then cut to the compositor.
|
||||
compositor.FadeToColor(fadeOutTime, backgroundColor.r, backgroundColor.g, backgroundColor.b, backgroundColor.a, false);
|
||||
yield return new WaitForSeconds(fadeOutTime + 0.1f);
|
||||
compositor.FadeGrid(0.0f, true);
|
||||
fadedForeground = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we're fully faded out, we can stop submitting frames to the compositor.
|
||||
SteamVR_Render.pauseRendering = true;
|
||||
|
||||
// Continue waiting for the overlays to fully fade in before continuing.
|
||||
while (alpha < 1.0f)
|
||||
yield return null;
|
||||
|
||||
// Keep us from getting destroyed when loading the new level, otherwise this coroutine will get stopped prematurely.
|
||||
transform.parent = null;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
|
||||
if (!string.IsNullOrEmpty(internalProcessPath))
|
||||
{
|
||||
Debug.Log("<b>[SteamVR]</b> Launching external application...");
|
||||
var applications = OpenVR.Applications;
|
||||
if (applications == null)
|
||||
{
|
||||
Debug.Log("<b>[SteamVR]</b> Failed to get OpenVR.Applications interface!");
|
||||
}
|
||||
else
|
||||
{
|
||||
var workingDirectory = Directory.GetCurrentDirectory();
|
||||
var fullPath = Path.Combine(workingDirectory, internalProcessPath);
|
||||
Debug.Log("<b>[SteamVR]</b> LaunchingInternalProcess");
|
||||
Debug.Log("<b>[SteamVR]</b> ExternalAppPath = " + internalProcessPath);
|
||||
Debug.Log("<b>[SteamVR]</b> FullPath = " + fullPath);
|
||||
Debug.Log("<b>[SteamVR]</b> ExternalAppArgs = " + internalProcessArgs);
|
||||
Debug.Log("<b>[SteamVR]</b> WorkingDirectory = " + workingDirectory);
|
||||
var error = applications.LaunchInternalProcess(fullPath, internalProcessArgs, workingDirectory);
|
||||
Debug.Log("<b>[SteamVR]</b> LaunchInternalProcessError: " + error);
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.EditorApplication.isPlaying = false;
|
||||
#elif !UNITY_METRO
|
||||
System.Diagnostics.Process.GetCurrentProcess().Kill();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var mode = loadAdditive ? UnityEngine.SceneManagement.LoadSceneMode.Additive : UnityEngine.SceneManagement.LoadSceneMode.Single;
|
||||
if (loadAsync)
|
||||
{
|
||||
Application.backgroundLoadingPriority = ThreadPriority.Low;
|
||||
async = UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(levelName, mode);
|
||||
|
||||
// Performing this in a while loop instead seems to help smooth things out.
|
||||
//yield return async;
|
||||
while (!async.isDone)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityEngine.SceneManagement.SceneManager.LoadScene(levelName, mode);
|
||||
}
|
||||
}
|
||||
|
||||
yield return null;
|
||||
|
||||
System.GC.Collect();
|
||||
|
||||
yield return null;
|
||||
|
||||
Shader.WarmupAllShaders();
|
||||
|
||||
// Optionally wait a short period of time after loading everything back in, but before we start rendering again
|
||||
// in order to give everything a change to settle down to avoid any hitching at the start of the new level.
|
||||
yield return new WaitForSeconds(postLoadSettleTime);
|
||||
|
||||
SteamVR_Render.pauseRendering = false;
|
||||
|
||||
// Fade out loading screen.
|
||||
if (loadingScreenFadeOutTime > 0.0f)
|
||||
{
|
||||
fadeRate = -1.0f / loadingScreenFadeOutTime;
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha = 0.0f;
|
||||
}
|
||||
|
||||
// Fade out to compositor
|
||||
SteamVR_Events.LoadingFadeIn.Send(fadeInTime);
|
||||
|
||||
// Refresh compositor reference since loading scenes might have invalidated it.
|
||||
compositor = OpenVR.Compositor;
|
||||
if (compositor != null)
|
||||
{
|
||||
// Fade out foreground color if necessary.
|
||||
if (fadedForeground)
|
||||
{
|
||||
compositor.FadeGrid(0.0f, false);
|
||||
compositor.FadeToColor(fadeInTime, 0.0f, 0.0f, 0.0f, 0.0f, false);
|
||||
yield return new WaitForSeconds(fadeInTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fade scene back in, and reset skybox once no longer visible.
|
||||
compositor.FadeGrid(fadeInTime, false);
|
||||
yield return new WaitForSeconds(fadeInTime);
|
||||
|
||||
if (front != null)
|
||||
{
|
||||
SteamVR_Skybox.ClearOverride();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, stick around long enough for our overlays to fully fade out.
|
||||
while (alpha > 0.0f)
|
||||
yield return null;
|
||||
|
||||
if (overlay != null)
|
||||
{
|
||||
if (progressBarOverlayHandle != OpenVR.k_ulOverlayHandleInvalid)
|
||||
overlay.HideOverlay(progressBarOverlayHandle);
|
||||
if (loadingScreenOverlayHandle != OpenVR.k_ulOverlayHandleInvalid)
|
||||
overlay.HideOverlay(loadingScreenOverlayHandle);
|
||||
}
|
||||
|
||||
Destroy(gameObject);
|
||||
|
||||
_active = null;
|
||||
|
||||
SteamVR_Events.Loading.Send(false);
|
||||
}
|
||||
|
||||
// Helper to create (or reuse if possible) each of our different overlay types.
|
||||
ulong GetOverlayHandle(string overlayName, Transform transform, float widthInMeters = 1.0f)
|
||||
{
|
||||
ulong handle = OpenVR.k_ulOverlayHandleInvalid;
|
||||
|
||||
var overlay = OpenVR.Overlay;
|
||||
if (overlay == null)
|
||||
return handle;
|
||||
|
||||
var key = SteamVR_Overlay.key + "." + overlayName;
|
||||
|
||||
var error = overlay.FindOverlay(key, ref handle);
|
||||
if (error != EVROverlayError.None)
|
||||
error = overlay.CreateOverlay(key, overlayName, ref handle);
|
||||
if (error == EVROverlayError.None)
|
||||
{
|
||||
overlay.ShowOverlay(handle);
|
||||
overlay.SetOverlayAlpha(handle, alpha);
|
||||
overlay.SetOverlayWidthInMeters(handle, widthInMeters);
|
||||
|
||||
// D3D textures are upside-down in Unity to match OpenGL.
|
||||
if (SteamVR.instance.textureType == ETextureType.DirectX)
|
||||
{
|
||||
var textureBounds = new VRTextureBounds_t();
|
||||
textureBounds.uMin = 0;
|
||||
textureBounds.vMin = 1;
|
||||
textureBounds.uMax = 1;
|
||||
textureBounds.vMax = 0;
|
||||
overlay.SetOverlayTextureBounds(handle, ref textureBounds);
|
||||
}
|
||||
|
||||
// Convert from world space to tracking space using the top-most camera.
|
||||
var vrcam = (loadingScreenDistance == 0.0f) ? SteamVR_Render.Top() : null;
|
||||
if (vrcam != null && vrcam.origin != null)
|
||||
{
|
||||
var offset = new SteamVR_Utils.RigidTransform(vrcam.origin, transform);
|
||||
offset.pos.x /= vrcam.origin.localScale.x;
|
||||
offset.pos.y /= vrcam.origin.localScale.y;
|
||||
offset.pos.z /= vrcam.origin.localScale.z;
|
||||
|
||||
var t = offset.ToHmdMatrix34();
|
||||
overlay.SetOverlayTransformAbsolute(handle, SteamVR.settings.trackingSpace, ref t);
|
||||
}
|
||||
else
|
||||
{
|
||||
var t = new SteamVR_Utils.RigidTransform(transform).ToHmdMatrix34();
|
||||
overlay.SetOverlayTransformAbsolute(handle, SteamVR.settings.trackingSpace, ref t);
|
||||
}
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user