size 22472672 |
@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: bc2dd9d1274c0e04fa36b500a6c86c71 | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,25 @@ | |||
using System.Collections; | |||
using System.Collections.Generic; | |||
using UnityEngine; | |||
namespace EMD.DemoUtility | |||
{ | |||
public class SmoothFollowBehaviour : MonoBehaviour | |||
{ | |||
[SerializeField] | |||
private Transform m_Target; | |||
[SerializeField] | |||
private float m_SmoothValue = 0.5f; | |||
void LateUpdate() | |||
{ | |||
if (m_Target != null) | |||
{ | |||
transform.position = Vector3.Lerp(transform.position, m_Target.position, m_SmoothValue); | |||
transform.rotation = Quaternion.Lerp(transform.rotation, m_Target.rotation, m_SmoothValue); | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,11 @@ | |||
fileFormatVersion: 2 | |||
guid: 068e885c69b62b14fac7da48f837e74d | |||
MonoImporter: | |||
externalObjects: {} | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 4bc2544df28a1a942b15ec45a8ee7b14 | |||
folderAsset: yes | |||
DefaultImporter: | |||
externalObjects: {} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,6 @@ | |||
fileFormatVersion: 2 | |||
guid: c33af0785775d7548b22541da37936fe | |||
folderAsset: yes | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: |
@ -0,0 +1,127 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: Custom inspector display for SteamVR_Camera | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
using UnityEditor; | |||
using System.IO; | |||
[CustomEditor(typeof(SteamVR_Camera)), CanEditMultipleObjects] | |||
public class SteamVR_Editor : Editor | |||
{ | |||
int bannerHeight = 150; | |||
Texture logo; | |||
SerializedProperty script, wireframe; | |||
string GetResourcePath() | |||
{ | |||
var ms = MonoScript.FromScriptableObject(this); | |||
var path = AssetDatabase.GetAssetPath(ms); | |||
path = Path.GetDirectoryName(path); | |||
return path.Substring(0, path.Length - "Editor".Length) + "Textures/"; | |||
} | |||
void OnEnable() | |||
{ | |||
var resourcePath = GetResourcePath(); | |||
logo = AssetDatabase.LoadAssetAtPath<Texture2D>(resourcePath + "logo.png"); | |||
script = serializedObject.FindProperty("m_Script"); | |||
wireframe = serializedObject.FindProperty("wireframe"); | |||
foreach (SteamVR_Camera target in targets) | |||
target.ForceLast(); | |||
} | |||
public override void OnInspectorGUI() | |||
{ | |||
serializedObject.Update(); | |||
var rect = GUILayoutUtility.GetRect(Screen.width - 38, bannerHeight, GUI.skin.box); | |||
if (logo) | |||
GUI.DrawTexture(rect, logo, ScaleMode.ScaleToFit); | |||
if (!Application.isPlaying) | |||
{ | |||
var expand = false; | |||
var collapse = false; | |||
foreach (SteamVR_Camera target in targets) | |||
{ | |||
if (AssetDatabase.Contains(target)) | |||
continue; | |||
if (target.isExpanded) | |||
collapse = true; | |||
else | |||
expand = true; | |||
} | |||
if (expand) | |||
{ | |||
GUILayout.BeginHorizontal(); | |||
if (GUILayout.Button("Expand")) | |||
{ | |||
foreach (SteamVR_Camera target in targets) | |||
{ | |||
if (AssetDatabase.Contains(target)) | |||
continue; | |||
if (!target.isExpanded) | |||
{ | |||
target.Expand(); | |||
EditorUtility.SetDirty(target); | |||
} | |||
} | |||
} | |||
GUILayout.Space(18); | |||
GUILayout.EndHorizontal(); | |||
} | |||
if (collapse) | |||
{ | |||
GUILayout.BeginHorizontal(); | |||
if (GUILayout.Button("Collapse")) | |||
{ | |||
foreach (SteamVR_Camera target in targets) | |||
{ | |||
if (AssetDatabase.Contains(target)) | |||
continue; | |||
if (target.isExpanded) | |||
{ | |||
target.Collapse(); | |||
EditorUtility.SetDirty(target); | |||
} | |||
} | |||
} | |||
GUILayout.Space(18); | |||
GUILayout.EndHorizontal(); | |||
} | |||
} | |||
EditorGUILayout.PropertyField(script); | |||
EditorGUILayout.PropertyField(wireframe); | |||
serializedObject.ApplyModifiedProperties(); | |||
} | |||
public static void ExportPackage() | |||
{ | |||
AssetDatabase.ExportPackage(new string[] { | |||
"Assets/SteamVR", | |||
"Assets/Plugins/openvr_api.cs", | |||
"Assets/Plugins/openvr_api.bundle", | |||
"Assets/Plugins/x86/openvr_api.dll", | |||
"Assets/Plugins/x86/steam_api.dll", | |||
"Assets/Plugins/x86/libsteam_api.so", | |||
"Assets/Plugins/x86_64/openvr_api.dll", | |||
"Assets/Plugins/x86_64/steam_api.dll", | |||
"Assets/Plugins/x86_64/libsteam_api.so", | |||
"Assets/Plugins/x86_64/libopenvr_api.so", | |||
}, "steamvr.unitypackage", ExportPackageOptions.Recurse); | |||
EditorApplication.Exit(0); | |||
} | |||
} | |||
@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 5ba22c80948c94e44a82b9fd1b3abd0d | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: |
@ -0,0 +1,48 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: Preferences pane for how SteamVR plugin behaves. | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
using UnityEditor; | |||
public class SteamVR_Preferences | |||
{ | |||
/// <summary> | |||
/// Should SteamVR automatically enable VR when opening Unity or pressing play. | |||
/// </summary> | |||
public static bool AutoEnableVR | |||
{ | |||
get | |||
{ | |||
return EditorPrefs.GetBool("SteamVR_AutoEnableVR", true); | |||
} | |||
set | |||
{ | |||
EditorPrefs.SetBool("SteamVR_AutoEnableVR", value); | |||
} | |||
} | |||
[PreferenceItem("SteamVR")] | |||
static void PreferencesGUI() | |||
{ | |||
EditorGUILayout.BeginVertical(); | |||
EditorGUILayout.Space(); | |||
// Automatically Enable VR | |||
{ | |||
string title = "Automatically Enable VR"; | |||
string tooltip = "Should SteamVR automatically enable VR on launch and play?"; | |||
AutoEnableVR = EditorGUILayout.Toggle(new GUIContent(title, tooltip), AutoEnableVR); | |||
string helpMessage = "To enable VR manually:\n"; | |||
helpMessage += "- go to Edit -> Project Settings -> Player,\n"; | |||
helpMessage += "- tick 'Virtual Reality Supported',\n"; | |||
helpMessage += "- make sure OpenVR is in the 'Virtual Reality SDKs' list."; | |||
EditorGUILayout.HelpBox(helpMessage, MessageType.Info); | |||
} | |||
EditorGUILayout.EndVertical(); | |||
} | |||
} | |||
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 29abf75f7265ccb45b799eac4ab0ca94 | |||
timeCreated: 1487968203 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,104 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: Custom inspector display for SteamVR_RenderModel | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
using UnityEditor; | |||
using System.Text; | |||
using System.Collections.Generic; | |||
[CustomEditor(typeof(SteamVR_RenderModel)), CanEditMultipleObjects] | |||
public class SteamVR_RenderModelEditor : Editor | |||
{ | |||
SerializedProperty script, index, modelOverride, shader, verbose, createComponents, updateDynamically; | |||
static string[] renderModelNames; | |||
int renderModelIndex; | |||
void OnEnable() | |||
{ | |||
script = serializedObject.FindProperty("m_Script"); | |||
index = serializedObject.FindProperty("index"); | |||
modelOverride = serializedObject.FindProperty("modelOverride"); | |||
shader = serializedObject.FindProperty("shader"); | |||
verbose = serializedObject.FindProperty("verbose"); | |||
createComponents = serializedObject.FindProperty("createComponents"); | |||
updateDynamically = serializedObject.FindProperty("updateDynamically"); | |||
// Load render model names if necessary. | |||
if (renderModelNames == null) | |||
{ | |||
renderModelNames = LoadRenderModelNames(); | |||
} | |||
// Update renderModelIndex based on current modelOverride value. | |||
if (modelOverride.stringValue != "") | |||
{ | |||
for (int i = 0; i < renderModelNames.Length; i++) | |||
{ | |||
if (modelOverride.stringValue == renderModelNames[i]) | |||
{ | |||
renderModelIndex = i; | |||
break; | |||
} | |||
} | |||
} | |||
} | |||
static string[] LoadRenderModelNames() | |||
{ | |||
var results = new List<string>(); | |||
results.Add("None"); | |||
using (var holder = new SteamVR_RenderModel.RenderModelInterfaceHolder()) | |||
{ | |||
var renderModels = holder.instance; | |||
if (renderModels != null) | |||
{ | |||
uint count = renderModels.GetRenderModelCount(); | |||
for (uint i = 0; i < count; i++) | |||
{ | |||
var buffer = new StringBuilder(); | |||
var requiredSize = renderModels.GetRenderModelName(i, buffer, 0); | |||
if (requiredSize == 0) | |||
continue; | |||
buffer.EnsureCapacity((int)requiredSize); | |||
renderModels.GetRenderModelName(i, buffer, requiredSize); | |||
results.Add(buffer.ToString()); | |||
} | |||
} | |||
} | |||
return results.ToArray(); | |||
} | |||
public override void OnInspectorGUI() | |||
{ | |||
serializedObject.Update(); | |||
EditorGUILayout.PropertyField(script); | |||
EditorGUILayout.PropertyField(index); | |||
//EditorGUILayout.PropertyField(modelOverride); | |||
GUILayout.BeginHorizontal(); | |||
GUILayout.Label(new GUIContent("Model Override", SteamVR_RenderModel.modelOverrideWarning)); | |||
var selected = EditorGUILayout.Popup(renderModelIndex, renderModelNames); | |||
if (selected != renderModelIndex) | |||
{ | |||
renderModelIndex = selected; | |||
modelOverride.stringValue = (selected > 0) ? renderModelNames[selected] : ""; | |||
} | |||
GUILayout.EndHorizontal(); | |||
EditorGUILayout.PropertyField(shader); | |||
EditorGUILayout.PropertyField(verbose); | |||
EditorGUILayout.PropertyField(createComponents); | |||
EditorGUILayout.PropertyField(updateDynamically); | |||
serializedObject.ApplyModifiedProperties(); | |||
} | |||
} | |||
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 67867a20919f7db45a2e7034fda1c28e | |||
timeCreated: 1433373945 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,688 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: Prompt developers to use settings most compatible with SteamVR. | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
using UnityEditor; | |||
using System.IO; | |||
[InitializeOnLoad] | |||
public class SteamVR_Settings : EditorWindow | |||
{ | |||
const bool forceShow = false; // Set to true to get the dialog to show back up in the case you clicked Ignore All. | |||
const string ignore = "ignore."; | |||
const string useRecommended = "Use recommended ({0})"; | |||
const string currentValue = " (current = {0})"; | |||
const string buildTarget = "Build Target"; | |||
const string showUnitySplashScreen = "Show Unity Splashscreen"; | |||
const string defaultIsFullScreen = "Default is Fullscreen"; | |||
const string defaultScreenSize = "Default Screen Size"; | |||
const string runInBackground = "Run In Background"; | |||
const string displayResolutionDialog = "Display Resolution Dialog"; | |||
const string resizableWindow = "Resizable Window"; | |||
const string fullscreenMode = "D3D11 Fullscreen Mode"; | |||
const string visibleInBackground = "Visible In Background"; | |||
#if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) | |||
const string renderingPath = "Rendering Path"; | |||
#endif | |||
const string colorSpace = "Color Space"; | |||
const string gpuSkinning = "GPU Skinning"; | |||
#if false // skyboxes are currently broken | |||
const string singlePassStereoRendering = "Single-Pass Stereo Rendering"; | |||
#endif | |||
const BuildTarget recommended_BuildTarget = BuildTarget.StandaloneWindows64; | |||
const bool recommended_ShowUnitySplashScreen = false; | |||
const bool recommended_DefaultIsFullScreen = false; | |||
const int recommended_DefaultScreenWidth = 1024; | |||
const int recommended_DefaultScreenHeight = 768; | |||
const bool recommended_RunInBackground = true; | |||
const ResolutionDialogSetting recommended_DisplayResolutionDialog = ResolutionDialogSetting.HiddenByDefault; | |||
const bool recommended_ResizableWindow = true; | |||
const D3D11FullscreenMode recommended_FullscreenMode = D3D11FullscreenMode.FullscreenWindow; | |||
const bool recommended_VisibleInBackground = true; | |||
#if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) | |||
const RenderingPath recommended_RenderPath = RenderingPath.Forward; | |||
#endif | |||
const ColorSpace recommended_ColorSpace = ColorSpace.Linear; | |||
const bool recommended_GpuSkinning = true; | |||
#if false | |||
const bool recommended_SinglePassStereoRendering = true; | |||
#endif | |||
static SteamVR_Settings window; | |||
static SteamVR_Settings() | |||
{ | |||
EditorApplication.update += Update; | |||
} | |||
static void Update() | |||
{ | |||
bool show = | |||
(!EditorPrefs.HasKey(ignore + buildTarget) && | |||
EditorUserBuildSettings.activeBuildTarget != recommended_BuildTarget) || | |||
(!EditorPrefs.HasKey(ignore + showUnitySplashScreen) && | |||
#if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) | |||
PlayerSettings.showUnitySplashScreen != recommended_ShowUnitySplashScreen) || | |||
#else | |||
PlayerSettings.SplashScreen.show != recommended_ShowUnitySplashScreen) || | |||
#endif | |||
(!EditorPrefs.HasKey(ignore + defaultIsFullScreen) && | |||
PlayerSettings.defaultIsFullScreen != recommended_DefaultIsFullScreen) || | |||
(!EditorPrefs.HasKey(ignore + defaultScreenSize) && | |||
(PlayerSettings.defaultScreenWidth != recommended_DefaultScreenWidth || | |||
PlayerSettings.defaultScreenHeight != recommended_DefaultScreenHeight)) || | |||
(!EditorPrefs.HasKey(ignore + runInBackground) && | |||
PlayerSettings.runInBackground != recommended_RunInBackground) || | |||
(!EditorPrefs.HasKey(ignore + displayResolutionDialog) && | |||
PlayerSettings.displayResolutionDialog != recommended_DisplayResolutionDialog) || | |||
(!EditorPrefs.HasKey(ignore + resizableWindow) && | |||
PlayerSettings.resizableWindow != recommended_ResizableWindow) || | |||
(!EditorPrefs.HasKey(ignore + fullscreenMode) && | |||
PlayerSettings.d3d11FullscreenMode != recommended_FullscreenMode) || | |||
(!EditorPrefs.HasKey(ignore + visibleInBackground) && | |||
PlayerSettings.visibleInBackground != recommended_VisibleInBackground) || | |||
#if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) | |||
(!EditorPrefs.HasKey(ignore + renderingPath) && | |||
PlayerSettings.renderingPath != recommended_RenderPath) || | |||
#endif | |||
(!EditorPrefs.HasKey(ignore + colorSpace) && | |||
PlayerSettings.colorSpace != recommended_ColorSpace) || | |||
(!EditorPrefs.HasKey(ignore + gpuSkinning) && | |||
PlayerSettings.gpuSkinning != recommended_GpuSkinning) || | |||
#if false | |||
(!EditorPrefs.HasKey(ignore + singlePassStereoRendering) && | |||
PlayerSettings.singlePassStereoRendering != recommended_SinglePassStereoRendering) || | |||
#endif | |||
forceShow; | |||
if (show) | |||
{ | |||
window = GetWindow<SteamVR_Settings>(true); | |||
window.minSize = new Vector2(320, 440); | |||
//window.title = "SteamVR"; | |||
} | |||
if (SteamVR_Preferences.AutoEnableVR) | |||
{ | |||
// Switch to native OpenVR support. | |||
var updated = false; | |||
if (!PlayerSettings.virtualRealitySupported) | |||
{ | |||
PlayerSettings.virtualRealitySupported = true; | |||
updated = true; | |||
} | |||
#if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) | |||
var devices = UnityEditorInternal.VR.VREditor.GetVREnabledDevices(BuildTargetGroup.Standalone); | |||
#else | |||
var devices = UnityEditorInternal.VR.VREditor.GetVREnabledDevicesOnTargetGroup(BuildTargetGroup.Standalone); | |||
#endif | |||
var hasOpenVR = false; | |||
foreach (var device in devices) | |||
if (device.ToLower() == "openvr") | |||
hasOpenVR = true; | |||
if (!hasOpenVR) | |||
{ | |||
string[] newDevices; | |||
if (updated) | |||
{ | |||
newDevices = new string[] { "OpenVR" }; | |||
} | |||
else | |||
{ | |||
newDevices = new string[devices.Length + 1]; | |||
for (int i = 0; i < devices.Length; i++) | |||
newDevices[i] = devices[i]; | |||
newDevices[devices.Length] = "OpenVR"; | |||
updated = true; | |||
} | |||
#if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) | |||
UnityEditorInternal.VR.VREditor.SetVREnabledDevices(BuildTargetGroup.Standalone, newDevices); | |||
#else | |||
UnityEditorInternal.VR.VREditor.SetVREnabledDevicesOnTargetGroup(BuildTargetGroup.Standalone, newDevices); | |||
#endif | |||
} | |||
if (updated) | |||
Debug.Log("Switching to native OpenVR support."); | |||
} | |||
var dlls = new string[] | |||
{ | |||
"Plugins/x86/openvr_api.dll", | |||
"Plugins/x86_64/openvr_api.dll" | |||
}; | |||
foreach (var path in dlls) | |||
{ | |||
if (!File.Exists(Application.dataPath + "/" + path)) | |||
continue; | |||
if (AssetDatabase.DeleteAsset("Assets/" + path)) | |||
Debug.Log("Deleting " + path); | |||
else | |||
{ | |||
Debug.Log(path + " in use; cannot delete. Please restart Unity to complete upgrade."); | |||
} | |||
} | |||
EditorApplication.update -= Update; | |||
} | |||
Vector2 scrollPosition; | |||
string GetResourcePath() | |||
{ | |||
var ms = MonoScript.FromScriptableObject(this); | |||
var path = AssetDatabase.GetAssetPath(ms); | |||
path = Path.GetDirectoryName(path); | |||
return path.Substring(0, path.Length - "Editor".Length) + "Textures/"; | |||
} | |||
public void OnGUI() | |||
{ | |||
var resourcePath = GetResourcePath(); | |||
var logo = AssetDatabase.LoadAssetAtPath<Texture2D>(resourcePath + "logo.png"); | |||
var rect = GUILayoutUtility.GetRect(position.width, 150, GUI.skin.box); | |||
if (logo) | |||
GUI.DrawTexture(rect, logo, ScaleMode.ScaleToFit); | |||
EditorGUILayout.HelpBox("Recommended project settings for SteamVR:", MessageType.Warning); | |||
scrollPosition = GUILayout.BeginScrollView(scrollPosition); | |||
int numItems = 0; | |||
if (!EditorPrefs.HasKey(ignore + buildTarget) && | |||
EditorUserBuildSettings.activeBuildTarget != recommended_BuildTarget) | |||
{ | |||
++numItems; | |||
GUILayout.Label(buildTarget + string.Format(currentValue, EditorUserBuildSettings.activeBuildTarget)); | |||
GUILayout.BeginHorizontal(); | |||
if (GUILayout.Button(string.Format(useRecommended, recommended_BuildTarget))) | |||
{ | |||
#if (UNITY_5_5 || UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) | |||
EditorUserBuildSettings.SwitchActiveBuildTarget(recommended_BuildTarget); | |||
#else | |||
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Standalone, recommended_BuildTarget); | |||
#endif | |||
} | |||
GUILayout.FlexibleSpace(); | |||
if (GUILayout.Button("Ignore")) | |||
{ | |||
EditorPrefs.SetBool(ignore + buildTarget, true); | |||
} | |||
GUILayout.EndHorizontal(); | |||
} | |||
#if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) | |||
if (!EditorPrefs.HasKey(ignore + showUnitySplashScreen) && | |||
PlayerSettings.showUnitySplashScreen != recommended_ShowUnitySplashScreen) | |||
{ | |||
++numItems; | |||
GUILayout.Label(showUnitySplashScreen + string.Format(currentValue, PlayerSettings.showUnitySplashScreen)); | |||
GUILayout.BeginHorizontal(); | |||
if (GUILayout.Button(string.Format(useRecommended, recommended_ShowUnitySplashScreen))) | |||
{ | |||
PlayerSettings.showUnitySplashScreen = recommended_ShowUnitySplashScreen; | |||
} | |||
GUILayout.FlexibleSpace(); | |||
if (GUILayout.Button("Ignore")) | |||
{ | |||
EditorPrefs.SetBool(ignore + showUnitySplashScreen, true); | |||
} | |||
GUILayout.EndHorizontal(); | |||
} | |||
#else | |||
if (!EditorPrefs.HasKey(ignore + showUnitySplashScreen) && | |||
PlayerSettings.SplashScreen.show != recommended_ShowUnitySplashScreen) | |||
{ | |||
++numItems; | |||
GUILayout.Label(showUnitySplashScreen + string.Format(currentValue, PlayerSettings.SplashScreen.show)); | |||
GUILayout.BeginHorizontal(); | |||
if (GUILayout.Button(string.Format(useRecommended, recommended_ShowUnitySplashScreen))) | |||
{ | |||
PlayerSettings.SplashScreen.show = recommended_ShowUnitySplashScreen; | |||
} | |||
GUILayout.FlexibleSpace(); | |||
if (GUILayout.Button("Ignore")) | |||
{ | |||
EditorPrefs.SetBool(ignore + showUnitySplashScreen, true); | |||
} | |||
GUILayout.EndHorizontal(); | |||
} | |||
#endif | |||
if (!EditorPrefs.HasKey(ignore + defaultIsFullScreen) && | |||
PlayerSettings.defaultIsFullScreen != recommended_DefaultIsFullScreen) | |||
{ | |||
++numItems; | |||
GUILayout.Label(defaultIsFullScreen + string.Format(currentValue, PlayerSettings.defaultIsFullScreen)); | |||
GUILayout.BeginHorizontal(); | |||
if (GUILayout.Button(string.Format(useRecommended, recommended_DefaultIsFullScreen))) | |||
{ | |||
PlayerSettings.defaultIsFullScreen = recommended_DefaultIsFullScreen; | |||
} | |||
GUILayout.FlexibleSpace(); | |||
if (GUILayout.Button("Ignore")) | |||
{ | |||
EditorPrefs.SetBool(ignore + defaultIsFullScreen, true); | |||
} | |||
GUILayout.EndHorizontal(); | |||
} | |||
if (!EditorPrefs.HasKey(ignore + defaultScreenSize) && | |||
(PlayerSettings.defaultScreenWidth != recommended_DefaultScreenWidth || | |||
PlayerSettings.defaultScreenHeight != recommended_DefaultScreenHeight)) | |||
{ | |||
++numItems; | |||
GUILayout.Label(defaultScreenSize + string.Format(" ({0}x{1})", PlayerSettings.defaultScreenWidth, PlayerSettings.defaultScreenHeight)); | |||
GUILayout.BeginHorizontal(); | |||
if (GUILayout.Button(string.Format("Use recommended ({0}x{1})", recommended_DefaultScreenWidth, recommended_DefaultScreenHeight))) | |||
{ | |||
PlayerSettings.defaultScreenWidth = recommended_DefaultScreenWidth; | |||
PlayerSettings.defaultScreenHeight = recommended_DefaultScreenHeight; | |||
} | |||
GUILayout.FlexibleSpace(); | |||
if (GUILayout.Button("Ignore")) | |||
{ | |||
EditorPrefs.SetBool(ignore + defaultScreenSize, true); | |||
} | |||
GUILayout.EndHorizontal(); | |||
} | |||
if (!EditorPrefs.HasKey(ignore + runInBackground) && | |||
PlayerSettings.runInBackground != recommended_RunInBackground) | |||
{ | |||
++numItems; | |||
GUILayout.Label(runInBackground + string.Format(currentValue, PlayerSettings.runInBackground)); | |||
GUILayout.BeginHorizontal(); | |||
if (GUILayout.Button(string.Format(useRecommended, recommended_RunInBackground))) | |||
{ | |||
PlayerSettings.runInBackground = recommended_RunInBackground; | |||
} | |||
GUILayout.FlexibleSpace(); | |||
if (GUILayout.Button("Ignore")) | |||
{ | |||
EditorPrefs.SetBool(ignore + runInBackground, true); | |||
} | |||
GUILayout.EndHorizontal(); | |||
} | |||
if (!EditorPrefs.HasKey(ignore + displayResolutionDialog) && | |||
PlayerSettings.displayResolutionDialog != recommended_DisplayResolutionDialog) | |||
{ | |||
++numItems; | |||
GUILayout.Label(displayResolutionDialog + string.Format(currentValue, PlayerSettings.displayResolutionDialog)); | |||
GUILayout.BeginHorizontal(); | |||
if (GUILayout.Button(string.Format(useRecommended, recommended_DisplayResolutionDialog))) | |||
{ | |||
PlayerSettings.displayResolutionDialog = recommended_DisplayResolutionDialog; | |||
} | |||
GUILayout.FlexibleSpace(); | |||
if (GUILayout.Button("Ignore")) | |||
{ | |||
EditorPrefs.SetBool(ignore + displayResolutionDialog, true); | |||
} | |||
GUILayout.EndHorizontal(); | |||
} | |||
if (!EditorPrefs.HasKey(ignore + resizableWindow) && | |||
PlayerSettings.resizableWindow != recommended_ResizableWindow) | |||
{ | |||
++numItems; | |||
GUILayout.Label(resizableWindow + string.Format(currentValue, PlayerSettings.resizableWindow)); | |||
GUILayout.BeginHorizontal(); | |||
if (GUILayout.Button(string.Format(useRecommended, recommended_ResizableWindow))) | |||
{ | |||
PlayerSettings.resizableWindow = recommended_ResizableWindow; | |||
} | |||
GUILayout.FlexibleSpace(); | |||
if (GUILayout.Button("Ignore")) | |||
{ | |||
EditorPrefs.SetBool(ignore + resizableWindow, true); | |||
} | |||
GUILayout.EndHorizontal(); | |||
} | |||
if (!EditorPrefs.HasKey(ignore + fullscreenMode) && | |||
PlayerSettings.d3d11FullscreenMode != recommended_FullscreenMode) | |||
{ | |||
++numItems; | |||
GUILayout.Label(fullscreenMode + string.Format(currentValue, PlayerSettings.d3d11FullscreenMode)); | |||
GUILayout.BeginHorizontal(); | |||
if (GUILayout.Button(string.Format(useRecommended, recommended_FullscreenMode))) | |||
{ | |||
PlayerSettings.d3d11FullscreenMode = recommended_FullscreenMode; | |||
} | |||
GUILayout.FlexibleSpace(); | |||
if (GUILayout.Button("Ignore")) | |||
{ | |||
EditorPrefs.SetBool(ignore + fullscreenMode, true); | |||
} | |||
GUILayout.EndHorizontal(); | |||
} | |||
if (!EditorPrefs.HasKey(ignore + visibleInBackground) && | |||
PlayerSettings.visibleInBackground != recommended_VisibleInBackground) | |||
{ | |||
++numItems; | |||
GUILayout.Label(visibleInBackground + string.Format(currentValue, PlayerSettings.visibleInBackground)); | |||
GUILayout.BeginHorizontal(); | |||
if (GUILayout.Button(string.Format(useRecommended, recommended_VisibleInBackground))) | |||
{ | |||
PlayerSettings.visibleInBackground = recommended_VisibleInBackground; | |||
} | |||
GUILayout.FlexibleSpace(); | |||
if (GUILayout.Button("Ignore")) | |||
{ | |||
EditorPrefs.SetBool(ignore + visibleInBackground, true); | |||
} | |||
GUILayout.EndHorizontal(); | |||
} | |||
#if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) | |||
if (!EditorPrefs.HasKey(ignore + renderingPath) && | |||
PlayerSettings.renderingPath != recommended_RenderPath) | |||
{ | |||
++numItems; | |||
GUILayout.Label(renderingPath + string.Format(currentValue, PlayerSettings.renderingPath)); | |||
GUILayout.BeginHorizontal(); | |||
if (GUILayout.Button(string.Format(useRecommended, recommended_RenderPath) + " - required for MSAA")) | |||
{ | |||
PlayerSettings.renderingPath = recommended_RenderPath; | |||
} | |||
GUILayout.FlexibleSpace(); | |||
if (GUILayout.Button("Ignore")) | |||
{ | |||
EditorPrefs.SetBool(ignore + renderingPath, true); | |||
} | |||
GUILayout.EndHorizontal(); | |||
} | |||
#endif | |||
if (!EditorPrefs.HasKey(ignore + colorSpace) && | |||
PlayerSettings.colorSpace != recommended_ColorSpace) | |||
{ | |||
++numItems; | |||
GUILayout.Label(colorSpace + string.Format(currentValue, PlayerSettings.colorSpace)); | |||
GUILayout.BeginHorizontal(); | |||
if (GUILayout.Button(string.Format(useRecommended, recommended_ColorSpace) + " - requires reloading scene")) | |||
{ | |||
PlayerSettings.colorSpace = recommended_ColorSpace; | |||
} | |||
GUILayout.FlexibleSpace(); | |||
if (GUILayout.Button("Ignore")) | |||
{ | |||
EditorPrefs.SetBool(ignore + colorSpace, true); | |||
} | |||
GUILayout.EndHorizontal(); | |||
} | |||
if (!EditorPrefs.HasKey(ignore + gpuSkinning) && | |||
PlayerSettings.gpuSkinning != recommended_GpuSkinning) | |||
{ | |||
++numItems; | |||
GUILayout.Label(gpuSkinning + string.Format(currentValue, PlayerSettings.gpuSkinning)); | |||
GUILayout.BeginHorizontal(); | |||
if (GUILayout.Button(string.Format(useRecommended, recommended_GpuSkinning))) | |||
{ | |||
PlayerSettings.gpuSkinning = recommended_GpuSkinning; | |||
} | |||
GUILayout.FlexibleSpace(); | |||
if (GUILayout.Button("Ignore")) | |||
{ | |||
EditorPrefs.SetBool(ignore + gpuSkinning, true); | |||
} | |||
GUILayout.EndHorizontal(); | |||
} | |||
#if false | |||
if (!EditorPrefs.HasKey(ignore + singlePassStereoRendering) && | |||
PlayerSettings.singlePassStereoRendering != recommended_SinglePassStereoRendering) | |||
{ | |||
++numItems; | |||
GUILayout.Label(singlePassStereoRendering + string.Format(currentValue, PlayerSettings.singlePassStereoRendering)); | |||
GUILayout.BeginHorizontal(); | |||
if (GUILayout.Button(string.Format(useRecommended, recommended_SinglePassStereoRendering))) | |||
{ | |||
PlayerSettings.singlePassStereoRendering = recommended_SinglePassStereoRendering; | |||
} | |||
GUILayout.FlexibleSpace(); | |||
if (GUILayout.Button("Ignore")) | |||
{ | |||
EditorPrefs.SetBool(ignore + singlePassStereoRendering, true); | |||
} | |||
GUILayout.EndHorizontal(); | |||
} | |||
#endif | |||
GUILayout.BeginHorizontal(); | |||
GUILayout.FlexibleSpace(); | |||
if (GUILayout.Button("Clear All Ignores")) | |||
{ | |||
EditorPrefs.DeleteKey(ignore + buildTarget); | |||
EditorPrefs.DeleteKey(ignore + showUnitySplashScreen); | |||
EditorPrefs.DeleteKey(ignore + defaultIsFullScreen); | |||
EditorPrefs.DeleteKey(ignore + defaultScreenSize); | |||
EditorPrefs.DeleteKey(ignore + runInBackground); | |||
EditorPrefs.DeleteKey(ignore + displayResolutionDialog); | |||
EditorPrefs.DeleteKey(ignore + resizableWindow); | |||
EditorPrefs.DeleteKey(ignore + fullscreenMode); | |||
EditorPrefs.DeleteKey(ignore + visibleInBackground); | |||
#if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) | |||
EditorPrefs.DeleteKey(ignore + renderingPath); | |||
#endif | |||
EditorPrefs.DeleteKey(ignore + colorSpace); | |||
EditorPrefs.DeleteKey(ignore + gpuSkinning); | |||
#if false | |||
EditorPrefs.DeleteKey(ignore + singlePassStereoRendering); | |||
#endif | |||
} | |||
GUILayout.EndHorizontal(); | |||
GUILayout.EndScrollView(); | |||
GUILayout.FlexibleSpace(); | |||
GUILayout.BeginHorizontal(); | |||
if (numItems > 0) | |||
{ | |||
if (GUILayout.Button("Accept All")) | |||
{ | |||
// Only set those that have not been explicitly ignored. | |||
if (!EditorPrefs.HasKey(ignore + buildTarget)) | |||
#if (UNITY_5_5 || UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) | |||
EditorUserBuildSettings.SwitchActiveBuildTarget(recommended_BuildTarget); | |||
#else | |||
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Standalone, recommended_BuildTarget); | |||
#endif | |||
if (!EditorPrefs.HasKey(ignore + showUnitySplashScreen)) | |||
#if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) | |||
PlayerSettings.showUnitySplashScreen = recommended_ShowUnitySplashScreen; | |||
#else | |||
PlayerSettings.SplashScreen.show = recommended_ShowUnitySplashScreen; | |||
#endif | |||
if (!EditorPrefs.HasKey(ignore + defaultIsFullScreen)) | |||
PlayerSettings.defaultIsFullScreen = recommended_DefaultIsFullScreen; | |||
if (!EditorPrefs.HasKey(ignore + defaultScreenSize)) | |||
{ | |||
PlayerSettings.defaultScreenWidth = recommended_DefaultScreenWidth; | |||
PlayerSettings.defaultScreenHeight = recommended_DefaultScreenHeight; | |||
} | |||
if (!EditorPrefs.HasKey(ignore + runInBackground)) | |||
PlayerSettings.runInBackground = recommended_RunInBackground; | |||
if (!EditorPrefs.HasKey(ignore + displayResolutionDialog)) | |||
PlayerSettings.displayResolutionDialog = recommended_DisplayResolutionDialog; | |||
if (!EditorPrefs.HasKey(ignore + resizableWindow)) | |||
PlayerSettings.resizableWindow = recommended_ResizableWindow; | |||
if (!EditorPrefs.HasKey(ignore + fullscreenMode)) | |||
PlayerSettings.d3d11FullscreenMode = recommended_FullscreenMode; | |||
if (!EditorPrefs.HasKey(ignore + visibleInBackground)) | |||
PlayerSettings.visibleInBackground = recommended_VisibleInBackground; | |||
#if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) | |||
if (!EditorPrefs.HasKey(ignore + renderingPath)) | |||
PlayerSettings.renderingPath = recommended_RenderPath; | |||
#endif | |||
if (!EditorPrefs.HasKey(ignore + colorSpace)) | |||
PlayerSettings.colorSpace = recommended_ColorSpace; | |||
if (!EditorPrefs.HasKey(ignore + gpuSkinning)) | |||
PlayerSettings.gpuSkinning = recommended_GpuSkinning; | |||
#if false | |||
if (!EditorPrefs.HasKey(ignore + singlePassStereoRendering)) | |||
PlayerSettings.singlePassStereoRendering = recommended_SinglePassStereoRendering; | |||
#endif | |||
EditorUtility.DisplayDialog("Accept All", "You made the right choice!", "Ok"); | |||
Close(); | |||
} | |||
if (GUILayout.Button("Ignore All")) | |||
{ | |||
if (EditorUtility.DisplayDialog("Ignore All", "Are you sure?", "Yes, Ignore All", "Cancel")) | |||
{ | |||
// Only ignore those that do not currently match our recommended settings. | |||
if (EditorUserBuildSettings.activeBuildTarget != recommended_BuildTarget) | |||
EditorPrefs.SetBool(ignore + buildTarget, true); | |||
#if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) | |||
if (PlayerSettings.showUnitySplashScreen != recommended_ShowUnitySplashScreen) | |||
#else | |||
if (PlayerSettings.SplashScreen.show != recommended_ShowUnitySplashScreen) | |||
#endif | |||
EditorPrefs.SetBool(ignore + showUnitySplashScreen, true); | |||
if (PlayerSettings.defaultIsFullScreen != recommended_DefaultIsFullScreen) | |||
EditorPrefs.SetBool(ignore + defaultIsFullScreen, true); | |||
if (PlayerSettings.defaultScreenWidth != recommended_DefaultScreenWidth || | |||
PlayerSettings.defaultScreenHeight != recommended_DefaultScreenHeight) | |||
EditorPrefs.SetBool(ignore + defaultScreenSize, true); | |||
if (PlayerSettings.runInBackground != recommended_RunInBackground) | |||
EditorPrefs.SetBool(ignore + runInBackground, true); | |||
if (PlayerSettings.displayResolutionDialog != recommended_DisplayResolutionDialog) | |||
EditorPrefs.SetBool(ignore + displayResolutionDialog, true); | |||
if (PlayerSettings.resizableWindow != recommended_ResizableWindow) | |||
EditorPrefs.SetBool(ignore + resizableWindow, true); | |||
if (PlayerSettings.d3d11FullscreenMode != recommended_FullscreenMode) | |||
EditorPrefs.SetBool(ignore + fullscreenMode, true); | |||
if (PlayerSettings.visibleInBackground != recommended_VisibleInBackground) | |||
EditorPrefs.SetBool(ignore + visibleInBackground, true); | |||
#if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) | |||
if (PlayerSettings.renderingPath != recommended_RenderPath) | |||
EditorPrefs.SetBool(ignore + renderingPath, true); | |||
#endif | |||
if (PlayerSettings.colorSpace != recommended_ColorSpace) | |||
EditorPrefs.SetBool(ignore + colorSpace, true); | |||
if (PlayerSettings.gpuSkinning != recommended_GpuSkinning) | |||
EditorPrefs.SetBool(ignore + gpuSkinning, true); | |||
#if false | |||
if (PlayerSettings.singlePassStereoRendering != recommended_SinglePassStereoRendering) | |||
EditorPrefs.SetBool(ignore + singlePassStereoRendering, true); | |||
#endif | |||
Close(); | |||
} | |||
} | |||
} | |||
else if (GUILayout.Button("Close")) | |||
{ | |||
Close(); | |||
} | |||
GUILayout.EndHorizontal(); | |||
} | |||
} | |||
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: d2244eee8a3a4784fb40d1123ff69301 | |||
timeCreated: 1438809573 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,381 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: Custom inspector display for SteamVR_Skybox | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
using UnityEditor; | |||
using System.Text; | |||
using System.Collections.Generic; | |||
using Valve.VR; | |||
using System.IO; | |||
[CustomEditor(typeof(SteamVR_Skybox)), CanEditMultipleObjects] | |||
public class SteamVR_SkyboxEditor : Editor | |||
{ | |||
private const string nameFormat = "{0}/{1}-{2}.png"; | |||
private const string helpText = "Take snapshot will use the current " + | |||
"position and rotation to capture six directional screenshots to use as this " + | |||
"skybox's textures. Note: This skybox is only used to override what shows up " + | |||
"in the compositor (e.g. when loading levels). Add a Camera component to this " + | |||
"object to override default settings like which layers to render. Additionally, " + | |||
"by specifying your own targetTexture, you can control the size of the textures " + | |||
"and other properties like antialiasing. Don't forget to disable the camera.\n\n" + | |||
"For stereo screenshots, a panorama is render for each eye using the specified " + | |||
"ipd (in millimeters) broken up into segments cellSize pixels square to optimize " + | |||
"generation.\n(32x32 takes about 10 seconds depending on scene complexity, 16x16 " + | |||
"takes around a minute, while will 8x8 take several minutes.)\n\nTo test, hit " + | |||
"play then pause - this will activate the skybox settings, and then drop you to " + | |||
"the compositor where the skybox is rendered."; | |||
public override void OnInspectorGUI() | |||
{ | |||
DrawDefaultInspector(); | |||
EditorGUILayout.HelpBox(helpText, MessageType.Info); | |||
if (GUILayout.Button("Take snapshot")) | |||
{ | |||
var directions = new Quaternion[] { | |||
Quaternion.LookRotation(Vector3.forward), | |||
Quaternion.LookRotation(Vector3.back), | |||
Quaternion.LookRotation(Vector3.left), | |||
Quaternion.LookRotation(Vector3.right), | |||
Quaternion.LookRotation(Vector3.up, Vector3.back), | |||
Quaternion.LookRotation(Vector3.down, Vector3.forward) | |||
}; | |||
Camera tempCamera = null; | |||
foreach (SteamVR_Skybox target in targets) | |||
{ | |||
var targetScene = target.gameObject.scene; | |||
var sceneName = Path.GetFileNameWithoutExtension(targetScene.path); | |||
var scenePath = Path.GetDirectoryName(targetScene.path); | |||
var assetPath = scenePath + "/" + sceneName; | |||
if (!AssetDatabase.IsValidFolder(assetPath)) | |||
{ | |||
var guid = AssetDatabase.CreateFolder(scenePath, sceneName); | |||
assetPath = AssetDatabase.GUIDToAssetPath(guid); | |||
} | |||
var camera = target.GetComponent<Camera>(); | |||
if (camera == null) | |||
{ | |||
if (tempCamera == null) | |||
tempCamera = new GameObject().AddComponent<Camera>(); | |||
camera = tempCamera; | |||
} | |||
var targetTexture = camera.targetTexture; | |||
if (camera.targetTexture == null) | |||
{ | |||
targetTexture = new RenderTexture(1024, 1024, 24); | |||
targetTexture.antiAliasing = 8; | |||
camera.targetTexture = targetTexture; | |||
} | |||
var oldPosition = target.transform.localPosition; | |||
var oldRotation = target.transform.localRotation; | |||
var baseRotation = target.transform.rotation; | |||
var t = camera.transform; | |||
t.position = target.transform.position; | |||
camera.orthographic = false; | |||
camera.fieldOfView = 90; | |||
for (int i = 0; i < directions.Length; i++) | |||
{ | |||
t.rotation = baseRotation * directions[i]; | |||
camera.Render(); | |||
// Copy to texture and save to disk. | |||
RenderTexture.active = targetTexture; | |||
var texture = new Texture2D(targetTexture.width, targetTexture.height, TextureFormat.ARGB32, false); | |||
texture.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0); | |||
texture.Apply(); | |||
RenderTexture.active = null; | |||
var assetName = string.Format(nameFormat, assetPath, target.name, i); | |||
System.IO.File.WriteAllBytes(assetName, texture.EncodeToPNG()); | |||
} | |||
if (camera != tempCamera) | |||
{ | |||
target.transform.localPosition = oldPosition; | |||
target.transform.localRotation = oldRotation; | |||
} | |||
} | |||
if (tempCamera != null) | |||
{ | |||
Object.DestroyImmediate(tempCamera.gameObject); | |||
} | |||
// Now that everything has be written out, reload the associated assets and assign them. | |||
AssetDatabase.Refresh(); | |||
foreach (SteamVR_Skybox target in targets) | |||
{ | |||
var targetScene = target.gameObject.scene; | |||
var sceneName = Path.GetFileNameWithoutExtension(targetScene.path); | |||
var scenePath = Path.GetDirectoryName(targetScene.path); | |||
var assetPath = scenePath + "/" + sceneName; | |||
for (int i = 0; i < directions.Length; i++) | |||
{ | |||
var assetName = string.Format(nameFormat, assetPath, target.name, i); | |||
var importer = AssetImporter.GetAtPath(assetName) as TextureImporter; | |||
#if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) | |||
importer.textureFormat = TextureImporterFormat.RGB24; | |||
#else | |||
importer.textureCompression = TextureImporterCompression.Uncompressed; | |||
#endif | |||
importer.wrapMode = TextureWrapMode.Clamp; | |||
importer.mipmapEnabled = false; | |||
importer.SaveAndReimport(); | |||
var texture = AssetDatabase.LoadAssetAtPath<Texture>(assetName); | |||
target.SetTextureByIndex(i, texture); | |||
} | |||
} | |||
} | |||
else if (GUILayout.Button("Take stereo snapshot")) | |||
{ | |||
const int width = 4096; | |||
const int height = width / 2; | |||
const int halfHeight = height / 2; | |||
var textures = new Texture2D[] { | |||
new Texture2D(width, height, TextureFormat.ARGB32, false), | |||
new Texture2D(width, height, TextureFormat.ARGB32, false) }; | |||
var timer = new System.Diagnostics.Stopwatch(); | |||
Camera tempCamera = null; | |||
foreach (SteamVR_Skybox target in targets) | |||
{ | |||
timer.Start(); | |||
var targetScene = target.gameObject.scene; | |||
var sceneName = Path.GetFileNameWithoutExtension(targetScene.path); | |||
var scenePath = Path.GetDirectoryName(targetScene.path); | |||
var assetPath = scenePath + "/" + sceneName; | |||
if (!AssetDatabase.IsValidFolder(assetPath)) | |||
{ | |||
var guid = AssetDatabase.CreateFolder(scenePath, sceneName); | |||
assetPath = AssetDatabase.GUIDToAssetPath(guid); | |||
} | |||
var camera = target.GetComponent<Camera>(); | |||
if (camera == null) | |||
{ | |||
if (tempCamera == null) | |||
tempCamera = new GameObject().AddComponent<Camera>(); | |||
camera = tempCamera; | |||
} | |||
var fx = camera.gameObject.AddComponent<SteamVR_SphericalProjection>(); | |||
var oldTargetTexture = camera.targetTexture; | |||
var oldOrthographic = camera.orthographic; | |||
var oldFieldOfView = camera.fieldOfView; | |||
var oldAspect = camera.aspect; | |||
var oldPosition = target.transform.localPosition; | |||
var oldRotation = target.transform.localRotation; | |||
var basePosition = target.transform.position; | |||
var baseRotation = target.transform.rotation; | |||
var transform = camera.transform; | |||
int cellSize = int.Parse(target.StereoCellSize.ToString().Substring(1)); | |||
float ipd = target.StereoIpdMm / 1000.0f; | |||
int vTotal = halfHeight / cellSize; | |||
float dv = 90.0f / vTotal; // vertical degrees per segment | |||
float dvHalf = dv / 2.0f; | |||
var targetTexture = new RenderTexture(cellSize, cellSize, 24); | |||
targetTexture.wrapMode = TextureWrapMode.Clamp; | |||
targetTexture.antiAliasing = 8; | |||
camera.fieldOfView = dv; | |||
camera.orthographic = false; | |||
camera.targetTexture = targetTexture; | |||
// Render sections of a sphere using a rectilinear projection | |||
// and resample using a sphereical projection into a single panorama | |||
// texture per eye. We break into sections in order to keep the eye | |||
// separation similar around the sphere. Rendering alternates between | |||
// top and bottom sections, sweeping horizontally around the sphere, | |||
// alternating left and right eyes. | |||
for (int v = 0; v < vTotal; v++) | |||
{ | |||
var pitch = 90.0f - (v * dv) - dvHalf; | |||
var uTotal = width / targetTexture.width; | |||
var du = 360.0f / uTotal; // horizontal degrees per segment | |||
var duHalf = du / 2.0f; | |||
var vTarget = v * halfHeight / vTotal; | |||
for (int i = 0; i < 2; i++) // top, bottom | |||
{ | |||
if (i == 1) | |||
{ | |||
pitch = -pitch; | |||
vTarget = height - vTarget - cellSize; | |||
} | |||
for (int u = 0; u < uTotal; u++) | |||
{ | |||
var yaw = -180.0f + (u * du) + duHalf; | |||
var uTarget = u * width / uTotal; | |||
var xOffset = -ipd / 2 * Mathf.Cos(pitch * Mathf.Deg2Rad); | |||
for (int j = 0; j < 2; j++) // left, right | |||
{ | |||
var texture = textures[j]; | |||
if (j == 1) | |||
{ | |||
xOffset = -xOffset; | |||
} | |||
var offset = baseRotation * Quaternion.Euler(0, yaw, 0) * new Vector3(xOffset, 0, 0); | |||
transform.position = basePosition + offset; | |||
var direction = Quaternion.Euler(pitch, yaw, 0.0f); | |||
transform.rotation = baseRotation * direction; | |||
// vector pointing to center of this section | |||
var N = direction * Vector3.forward; | |||
// horizontal span of this section in degrees | |||
var phi0 = yaw - (du / 2); | |||
var phi1 = phi0 + du; | |||
// vertical span of this section in degrees | |||
var theta0 = pitch + (dv / 2); | |||
var theta1 = theta0 - dv; | |||
var midPhi = (phi0 + phi1) / 2; | |||
var baseTheta = Mathf.Abs(theta0) < Mathf.Abs(theta1) ? theta0 : theta1; | |||
// vectors pointing to corners of image closes to the equator | |||
var V00 = Quaternion.Euler(baseTheta, phi0, 0.0f) * Vector3.forward; | |||
var V01 = Quaternion.Euler(baseTheta, phi1, 0.0f) * Vector3.forward; | |||
// vectors pointing to top and bottom midsection of image | |||
var V0M = Quaternion.Euler(theta0, midPhi, 0.0f) * Vector3.forward; | |||
var V1M = Quaternion.Euler(theta1, midPhi, 0.0f) * Vector3.forward; | |||
// intersection points for each of the above | |||
var P00 = V00 / Vector3.Dot(V00, N); | |||
var P01 = V01 / Vector3.Dot(V01, N); | |||
var P0M = V0M / Vector3.Dot(V0M, N); | |||
var P1M = V1M / Vector3.Dot(V1M, N); | |||
// calculate basis vectors for plane | |||
var P00_P01 = P01 - P00; | |||
var P0M_P1M = P1M - P0M; | |||
var uMag = P00_P01.magnitude; | |||
var vMag = P0M_P1M.magnitude; | |||
var uScale = 1.0f / uMag; | |||
var vScale = 1.0f / vMag; | |||
var uAxis = P00_P01 * uScale; | |||
var vAxis = P0M_P1M * vScale; | |||
// update material constant buffer | |||
fx.Set(N, phi0, phi1, theta0, theta1, | |||
uAxis, P00, uScale, | |||
vAxis, P0M, vScale); | |||
camera.aspect = uMag / vMag; | |||
camera.Render(); | |||
RenderTexture.active = targetTexture; | |||
texture.ReadPixels(new Rect(0, 0, targetTexture.width, targetTexture.height), uTarget, vTarget); | |||
RenderTexture.active = null; | |||
} | |||
} | |||
} | |||
} | |||
// Save textures to disk. | |||
for (int i = 0; i < 2; i++) | |||
{ | |||
var texture = textures[i]; | |||
texture.Apply(); | |||
var assetName = string.Format(nameFormat, assetPath, target.name, i); | |||
File.WriteAllBytes(assetName, texture.EncodeToPNG()); | |||
} | |||
// Cleanup. | |||
if (camera != tempCamera) | |||
{ | |||
camera.targetTexture = oldTargetTexture; | |||
camera.orthographic = oldOrthographic; | |||
camera.fieldOfView = oldFieldOfView; | |||
camera.aspect = oldAspect; | |||
target.transform.localPosition = oldPosition; | |||
target.transform.localRotation = oldRotation; | |||
} | |||
else | |||
{ | |||
tempCamera.targetTexture = null; | |||
} | |||
DestroyImmediate(targetTexture); | |||
DestroyImmediate(fx); | |||
timer.Stop(); | |||
Debug.Log(string.Format("Screenshot took {0} seconds.", timer.Elapsed)); | |||
} | |||
if (tempCamera != null) | |||
{ | |||
DestroyImmediate(tempCamera.gameObject); | |||
} | |||
DestroyImmediate(textures[0]); | |||
DestroyImmediate(textures[1]); | |||
// Now that everything has be written out, reload the associated assets and assign them. | |||
AssetDatabase.Refresh(); | |||
foreach (SteamVR_Skybox target in targets) | |||
{ | |||
var targetScene = target.gameObject.scene; | |||
var sceneName = Path.GetFileNameWithoutExtension(targetScene.path); | |||
var scenePath = Path.GetDirectoryName(targetScene.path); | |||
var assetPath = scenePath + "/" + sceneName; | |||
for (int i = 0; i < 2; i++) | |||
{ | |||
var assetName = string.Format(nameFormat, assetPath, target.name, i); | |||
var importer = AssetImporter.GetAtPath(assetName) as TextureImporter; | |||
importer.mipmapEnabled = false; | |||
importer.wrapMode = TextureWrapMode.Repeat; | |||
#if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) | |||
importer.SetPlatformTextureSettings("Standalone", width, TextureImporterFormat.RGB24); | |||
#else | |||
var settings = importer.GetPlatformTextureSettings("Standalone"); | |||
settings.textureCompression = TextureImporterCompression.Uncompressed; | |||
settings.maxTextureSize = width; | |||
importer.SetPlatformTextureSettings(settings); | |||
#endif | |||
importer.SaveAndReimport(); | |||
var texture = AssetDatabase.LoadAssetAtPath<Texture2D>(assetName); | |||
target.SetTextureByIndex(i, texture); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 80087fbbf7bf93a46bb4aea276b19568 | |||
timeCreated: 1446765449 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,170 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: Notify developers when a new version of the plugin is available. | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
using UnityEditor; | |||
using System.IO; | |||
using System.Text.RegularExpressions; | |||
[InitializeOnLoad] | |||
public class SteamVR_Update : EditorWindow | |||
{ | |||
const string currentVersion = "1.2.3"; | |||
const string versionUrl = "http://media.steampowered.com/apps/steamvr/unitypluginversion.txt"; | |||
const string notesUrl = "http://media.steampowered.com/apps/steamvr/unityplugin-v{0}.txt"; | |||
const string pluginUrl = "http://u3d.as/content/valve-corporation/steam-vr-plugin"; | |||
const string doNotShowKey = "SteamVR.DoNotShow.v{0}"; | |||
static bool gotVersion = false; | |||
static WWW wwwVersion, wwwNotes; | |||
static string version, notes; | |||
static SteamVR_Update window; | |||
static SteamVR_Update() | |||
{ | |||
EditorApplication.update += Update; | |||
} | |||
static void Update() | |||
{ | |||
if (!gotVersion) | |||
{ | |||
if (wwwVersion == null) | |||
wwwVersion = new WWW(versionUrl); | |||
if (!wwwVersion.isDone) | |||
return; | |||
if (UrlSuccess(wwwVersion)) | |||
version = wwwVersion.text; | |||
wwwVersion = null; | |||
gotVersion = true; | |||
if (ShouldDisplay()) | |||
{ | |||
var url = string.Format(notesUrl, version); | |||
wwwNotes = new WWW(url); | |||
window = GetWindow<SteamVR_Update>(true); | |||
window.minSize = new Vector2(320, 440); | |||
//window.title = "SteamVR"; | |||
} | |||
} | |||
if (wwwNotes != null) | |||
{ | |||
if (!wwwNotes.isDone) | |||
return; | |||
if (UrlSuccess(wwwNotes)) | |||
notes = wwwNotes.text; | |||
wwwNotes = null; | |||
if (notes != "") | |||
window.Repaint(); | |||
} | |||
EditorApplication.update -= Update; | |||
} | |||
static bool UrlSuccess(WWW www) | |||
{ | |||
if (!string.IsNullOrEmpty(www.error)) | |||
return false; | |||
if (Regex.IsMatch(www.text, "404 not found", RegexOptions.IgnoreCase)) | |||
return false; | |||
return true; | |||
} | |||
static bool ShouldDisplay() | |||
{ | |||
if (string.IsNullOrEmpty(version)) | |||
return false; | |||
if (version == currentVersion) | |||
return false; | |||
if (EditorPrefs.HasKey(string.Format(doNotShowKey, version))) | |||
return false; | |||
// parse to see if newer (e.g. 1.0.4 vs 1.0.3) | |||
var versionSplit = version.Split('.'); | |||
var currentVersionSplit = currentVersion.Split('.'); | |||
for (int i = 0; i < versionSplit.Length && i < currentVersionSplit.Length; i++) | |||
{ | |||
int versionValue, currentVersionValue; | |||
if (int.TryParse(versionSplit[i], out versionValue) && | |||
int.TryParse(currentVersionSplit[i], out currentVersionValue)) | |||
{ | |||
if (versionValue > currentVersionValue) | |||
return true; | |||
if (versionValue < currentVersionValue) | |||
return false; | |||
} | |||
} | |||
// same up to this point, now differentiate based on number of sub values (e.g. 1.0.4.1 vs 1.0.4) | |||
if (versionSplit.Length <= currentVersionSplit.Length) | |||
return false; | |||
return true; | |||
} | |||
Vector2 scrollPosition; | |||
bool toggleState; | |||
string GetResourcePath() | |||
{ | |||
var ms = MonoScript.FromScriptableObject(this); | |||
var path = AssetDatabase.GetAssetPath(ms); | |||
path = Path.GetDirectoryName(path); | |||
return path.Substring(0, path.Length - "Editor".Length) + "Textures/"; | |||
} | |||
public void OnGUI() | |||
{ | |||
EditorGUILayout.HelpBox("A new version of the SteamVR plugin is available!", MessageType.Warning); | |||
var resourcePath = GetResourcePath(); | |||
var logo = AssetDatabase.LoadAssetAtPath<Texture2D>(resourcePath + "logo.png"); | |||
var rect = GUILayoutUtility.GetRect(position.width, 150, GUI.skin.box); | |||
if (logo) | |||
GUI.DrawTexture(rect, logo, ScaleMode.ScaleToFit); | |||
scrollPosition = GUILayout.BeginScrollView(scrollPosition); | |||
GUILayout.Label("Current version: " + currentVersion); | |||
GUILayout.Label("New version: " + version); | |||
if (notes != "") | |||
{ | |||
GUILayout.Label("Release notes:"); | |||
EditorGUILayout.HelpBox(notes, MessageType.Info); | |||
} | |||
GUILayout.EndScrollView(); | |||
GUILayout.FlexibleSpace(); | |||
if (GUILayout.Button("Get Latest Version")) | |||
{ | |||
Application.OpenURL(pluginUrl); | |||
} | |||
EditorGUI.BeginChangeCheck(); | |||
var doNotShow = GUILayout.Toggle(toggleState, "Do not prompt for this version again."); | |||
if (EditorGUI.EndChangeCheck()) | |||
{ | |||
toggleState = doNotShow; | |||
var key = string.Format(doNotShowKey, version); | |||
if (doNotShow) | |||
EditorPrefs.SetBool(key, true); | |||
else | |||
EditorPrefs.DeleteKey(key); | |||
} | |||
} | |||
} | |||
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 73a0556bda803bf4e898751dcfcf21a8 | |||
timeCreated: 1433880062 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 61f4796ee4f00314e8d8b1ad39a78c28 | |||
folderAsset: yes | |||
timeCreated: 1438797390 | |||
licenseType: Store | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,88 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
using UnityEngine; | |||
using System.Collections; | |||
public struct GazeEventArgs | |||
{ | |||
public float distance; | |||
} | |||
public delegate void GazeEventHandler(object sender, GazeEventArgs e); | |||
public class SteamVR_GazeTracker : MonoBehaviour | |||
{ | |||
public bool isInGaze = false; | |||
public event GazeEventHandler GazeOn; | |||
public event GazeEventHandler GazeOff; | |||
public float gazeInCutoff = 0.15f; | |||
public float gazeOutCutoff = 0.4f; | |||
// Contains a HMD tracked object that we can use to find the user's gaze | |||
Transform hmdTrackedObject = null; | |||
// Use this for initialization | |||
void Start () | |||
{ | |||
} | |||
public virtual void OnGazeOn(GazeEventArgs e) | |||
{ | |||
if (GazeOn != null) | |||
GazeOn(this, e); | |||
} | |||
public virtual void OnGazeOff(GazeEventArgs e) | |||
{ | |||
if (GazeOff != null) | |||
GazeOff(this, e); | |||
} | |||
// Update is called once per frame | |||
void Update () | |||
{ | |||
// If we haven't set up hmdTrackedObject find what the user is looking at | |||
if (hmdTrackedObject == null) | |||
{ | |||
SteamVR_TrackedObject[] trackedObjects = FindObjectsOfType<SteamVR_TrackedObject>(); | |||
foreach (SteamVR_TrackedObject tracked in trackedObjects) | |||
{ | |||
if (tracked.index == SteamVR_TrackedObject.EIndex.Hmd) | |||
{ | |||
hmdTrackedObject = tracked.transform; | |||
break; | |||
} | |||
} | |||
} | |||
if (hmdTrackedObject) | |||
{ | |||
Ray r = new Ray(hmdTrackedObject.position, hmdTrackedObject.forward); | |||
Plane p = new Plane(hmdTrackedObject.forward, transform.position); | |||
float enter = 0.0f; | |||
if (p.Raycast(r, out enter)) | |||
{ | |||
Vector3 intersect = hmdTrackedObject.position + hmdTrackedObject.forward * enter; | |||
float dist = Vector3.Distance(intersect, transform.position); | |||
//Debug.Log("Gaze dist = " + dist); | |||
if (dist < gazeInCutoff && !isInGaze) | |||
{ | |||
isInGaze = true; | |||
GazeEventArgs e; | |||
e.distance = dist; | |||
OnGazeOn(e); | |||
} | |||
else if (dist >= gazeOutCutoff && isInGaze) | |||
{ | |||
isInGaze = false; | |||
GazeEventArgs e; | |||
e.distance = dist; | |||
OnGazeOff(e); | |||
} | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 501eb8b744f73714fbe7dbdd5e3ef66e | |||
timeCreated: 1426193800 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,141 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
using UnityEngine; | |||
using System.Collections; | |||
public struct PointerEventArgs | |||
{ | |||
public uint controllerIndex; | |||
public uint flags; | |||
public float distance; | |||
public Transform target; | |||
} | |||
public delegate void PointerEventHandler(object sender, PointerEventArgs e); | |||
public class SteamVR_LaserPointer : MonoBehaviour | |||
{ | |||
public bool active = true; | |||
public Color color; | |||
public float thickness = 0.002f; | |||
public GameObject holder; | |||
public GameObject pointer; | |||
bool isActive = false; | |||
public bool addRigidBody = false; | |||
public Transform reference; | |||
public event PointerEventHandler PointerIn; | |||
public event PointerEventHandler PointerOut; | |||
Transform previousContact = null; | |||
// Use this for initialization | |||
void Start () | |||
{ | |||
holder = new GameObject(); | |||
holder.transform.parent = this.transform; | |||
holder.transform.localPosition = Vector3.zero; | |||
holder.transform.localRotation = Quaternion.identity; | |||
pointer = GameObject.CreatePrimitive(PrimitiveType.Cube); | |||
pointer.transform.parent = holder.transform; | |||
pointer.transform.localScale = new Vector3(thickness, thickness, 100f); | |||
pointer.transform.localPosition = new Vector3(0f, 0f, 50f); | |||
pointer.transform.localRotation = Quaternion.identity; | |||
BoxCollider collider = pointer.GetComponent<BoxCollider>(); | |||
if (addRigidBody) | |||
{ | |||
if (collider) | |||
{ | |||
collider.isTrigger = true; | |||
} | |||
Rigidbody rigidBody = pointer.AddComponent<Rigidbody>(); | |||
rigidBody.isKinematic = true; | |||
} | |||
else | |||
{ | |||
if(collider) | |||
{ | |||
Object.Destroy(collider); | |||
} | |||
} | |||
Material newMaterial = new Material(Shader.Find("Unlit/Color")); | |||
newMaterial.SetColor("_Color", color); | |||
pointer.GetComponent<MeshRenderer>().material = newMaterial; | |||
} | |||
public virtual void OnPointerIn(PointerEventArgs e) | |||
{ | |||
if (PointerIn != null) | |||
PointerIn(this, e); | |||
} | |||
public virtual void OnPointerOut(PointerEventArgs e) | |||
{ | |||
if (PointerOut != null) | |||
PointerOut(this, e); | |||
} | |||
// Update is called once per frame | |||
void Update () | |||
{ | |||
if (!isActive) | |||
{ | |||
isActive = true; | |||
this.transform.GetChild(0).gameObject.SetActive(true); | |||
} | |||
float dist = 100f; | |||
SteamVR_TrackedController controller = GetComponent<SteamVR_TrackedController>(); | |||
Ray raycast = new Ray(transform.position, transform.forward); | |||
RaycastHit hit; | |||
bool bHit = Physics.Raycast(raycast, out hit); | |||
if(previousContact && previousContact != hit.transform) | |||
{ | |||
PointerEventArgs args = new PointerEventArgs(); | |||
if (controller != null) | |||
{ | |||
args.controllerIndex = controller.controllerIndex; | |||
} | |||
args.distance = 0f; | |||
args.flags = 0; | |||
args.target = previousContact; | |||
OnPointerOut(args); | |||
previousContact = null; | |||
} | |||
if(bHit && previousContact != hit.transform) | |||
{ | |||
PointerEventArgs argsIn = new PointerEventArgs(); | |||
if (controller != null) | |||
{ | |||
argsIn.controllerIndex = controller.controllerIndex; | |||
} | |||
argsIn.distance = hit.distance; | |||
argsIn.flags = 0; | |||
argsIn.target = hit.transform; | |||
OnPointerIn(argsIn); | |||
previousContact = hit.transform; | |||
} | |||
if(!bHit) | |||
{ | |||
previousContact = null; | |||
} | |||
if (bHit && hit.distance < 100f) | |||
{ | |||
dist = hit.distance; | |||
} | |||
if (controller != null && controller.triggerPressed) | |||
{ | |||
pointer.transform.localScale = new Vector3(thickness * 5f, thickness * 5f, dist); | |||
} | |||
else | |||
{ | |||
pointer.transform.localScale = new Vector3(thickness, thickness, dist); | |||
} | |||
pointer.transform.localPosition = new Vector3(0f, 0f, dist/2f); | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: d4e8a839a7c5b7e4580c59e305fb5f01 | |||
timeCreated: 1430337756 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,98 @@ | |||
using UnityEngine; | |||
using System.Collections; | |||
public class SteamVR_Teleporter : MonoBehaviour | |||
{ | |||
public enum TeleportType | |||
{ | |||
TeleportTypeUseTerrain, | |||
TeleportTypeUseCollider, | |||
TeleportTypeUseZeroY | |||
} | |||
public bool teleportOnClick = false; | |||
public TeleportType teleportType = TeleportType.TeleportTypeUseZeroY; | |||
Transform reference | |||
{ | |||
get | |||
{ | |||
var top = SteamVR_Render.Top(); | |||
return (top != null) ? top.origin : null; | |||
} | |||
} | |||
void Start() | |||
{ | |||
var trackedController = GetComponent<SteamVR_TrackedController>(); | |||
if (trackedController == null) | |||
{ | |||
trackedController = gameObject.AddComponent<SteamVR_TrackedController>(); | |||
} | |||
trackedController.TriggerClicked += new ClickedEventHandler(DoClick); | |||
if (teleportType == TeleportType.TeleportTypeUseTerrain) | |||
{ | |||
// Start the player at the level of the terrain | |||
var t = reference; | |||
if (t != null) | |||
t.position = new Vector3(t.position.x, Terrain.activeTerrain.SampleHeight(t.position), t.position.z); | |||
} | |||
} | |||
void DoClick(object sender, ClickedEventArgs e) | |||
{ | |||
if (teleportOnClick) | |||
{ | |||
// First get the current Transform of the the reference space (i.e. the Play Area, e.g. CameraRig prefab) | |||
var t = reference; | |||
if (t == null) | |||
return; | |||
// Get the current Y position of the reference space | |||
float refY = t.position.y; | |||
// Create a plane at the Y position of the Play Area | |||
// Then create a Ray from the origin of the controller in the direction that the controller is pointing | |||
Plane plane = new Plane(Vector3.up, -refY); | |||
Ray ray = new Ray(this.transform.position, transform.forward); | |||
// Set defaults | |||
bool hasGroundTarget = false; | |||
float dist = 0f; | |||
if (teleportType == TeleportType.TeleportTypeUseTerrain) // If we picked to use the terrain | |||
{ | |||
RaycastHit hitInfo; | |||
TerrainCollider tc = Terrain.activeTerrain.GetComponent<TerrainCollider>(); | |||
hasGroundTarget = tc.Raycast(ray, out hitInfo, 1000f); | |||
dist = hitInfo.distance; | |||
} | |||
else if (teleportType == TeleportType.TeleportTypeUseCollider) // If we picked to use the collider | |||
{ | |||
RaycastHit hitInfo; | |||
hasGroundTarget = Physics.Raycast(ray, out hitInfo); | |||
dist = hitInfo.distance; | |||
} | |||
else // If we're just staying flat on the current Y axis | |||
{ | |||
// Intersect a ray with the plane that was created earlier | |||
// and output the distance along the ray that it intersects | |||
hasGroundTarget = plane.Raycast(ray, out dist); | |||
} | |||
if (hasGroundTarget) | |||
{ | |||
// Get the current Camera (head) position on the ground relative to the world | |||
Vector3 headPosOnGround = new Vector3(SteamVR_Render.Top().head.position.x, refY, SteamVR_Render.Top().head.position.z); | |||
// We need to translate the reference space along the same vector | |||
// that is between the head's position on the ground and the intersection point on the ground | |||
// i.e. intersectionPoint - headPosOnGround = translateVector | |||
// currentReferencePosition + translateVector = finalPosition | |||
t.position = t.position + (ray.origin + (ray.direction * dist)) - headPosOnGround; | |||
} | |||
} | |||
} | |||
} | |||
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 24c7d7d77dd0d2a4b8e1ad129b170ee3 | |||
timeCreated: 1430337756 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
size 52553 |
@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 4b6669fb4e4df9c48926f02b694be9d1 | |||
timeCreated: 1437433018 | |||
licenseType: Store | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,58 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
using UnityEngine; | |||
using System.Collections; | |||
[RequireComponent(typeof(SteamVR_TrackedObject))] | |||
public class SteamVR_TestThrow : MonoBehaviour | |||
{ | |||
public GameObject prefab; | |||
public Rigidbody attachPoint; | |||
SteamVR_TrackedObject trackedObj; | |||
FixedJoint joint; | |||
void Awake() | |||
{ | |||
trackedObj = GetComponent<SteamVR_TrackedObject>(); | |||
} | |||
void FixedUpdate() | |||
{ | |||
var device = SteamVR_Controller.Input((int)trackedObj.index); | |||
if (joint == null && device.GetTouchDown(SteamVR_Controller.ButtonMask.Trigger)) | |||
{ | |||
var go = GameObject.Instantiate(prefab); | |||
go.transform.position = attachPoint.transform.position; | |||
joint = go.AddComponent<FixedJoint>(); | |||
joint.connectedBody = attachPoint; | |||
} | |||
else if (joint != null && device.GetTouchUp(SteamVR_Controller.ButtonMask.Trigger)) | |||
{ | |||
var go = joint.gameObject; | |||
var rigidbody = go.GetComponent<Rigidbody>(); | |||
Object.DestroyImmediate(joint); | |||
joint = null; | |||
Object.Destroy(go, 15.0f); | |||
// We should probably apply the offset between trackedObj.transform.position | |||
// and device.transform.pos to insert into the physics sim at the correct | |||
// location, however, we would then want to predict ahead the visual representation | |||
// by the same amount we are predicting our render poses. | |||
var origin = trackedObj.origin ? trackedObj.origin : trackedObj.transform.parent; | |||
if (origin != null) | |||
{ | |||
rigidbody.velocity = origin.TransformVector(device.velocity); | |||
rigidbody.angularVelocity = origin.TransformVector(device.angularVelocity); | |||
} | |||
else | |||
{ | |||
rigidbody.velocity = device.velocity; | |||
rigidbody.angularVelocity = device.angularVelocity; | |||
} | |||
rigidbody.maxAngularVelocity = rigidbody.angularVelocity.magnitude; | |||
} | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: ff4f36585e15b1942827390ff1a92502 | |||
timeCreated: 1437513988 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
size 73867 |
@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 0d936163b5e9a5047b5e4ba5afaf5126 | |||
timeCreated: 1437513966 | |||
licenseType: Store | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,84 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
using UnityEngine; | |||
public class SteamVR_TestTrackedCamera : MonoBehaviour | |||
{ | |||
public Material material; | |||
public Transform target; | |||
public bool undistorted = true; | |||
public bool cropped = true; | |||
void OnEnable() | |||
{ | |||
// The video stream must be symmetrically acquired and released in | |||
// order to properly disable the stream once there are no consumers. | |||
var source = SteamVR_TrackedCamera.Source(undistorted); | |||
source.Acquire(); | |||
// Auto-disable if no camera is present. | |||
if (!source.hasCamera) | |||
enabled = false; | |||
} | |||
void OnDisable() | |||
{ | |||
// Clear the texture when no longer active. | |||
material.mainTexture = null; | |||
// The video stream must be symmetrically acquired and released in | |||
// order to properly disable the stream once there are no consumers. | |||
var source = SteamVR_TrackedCamera.Source(undistorted); | |||
source.Release(); | |||
} | |||
void Update() | |||
{ | |||
var source = SteamVR_TrackedCamera.Source(undistorted); | |||
var texture = source.texture; | |||
if (texture == null) | |||
{ | |||
return; | |||
} | |||
// Apply the latest texture to the material. This must be performed | |||
// every frame since the underlying texture is actually part of a ring | |||
// buffer which is updated in lock-step with its associated pose. | |||
// (You actually really only need to call any of the accessors which | |||
// internally call Update on the SteamVR_TrackedCamera.VideoStreamTexture). | |||
material.mainTexture = texture; | |||
// Adjust the height of the quad based on the aspect to keep the texels square. | |||
var aspect = (float)texture.width / texture.height; | |||
// The undistorted video feed has 'bad' areas near the edges where the original | |||
// square texture feed is stretched to undo the fisheye from the lens. | |||
// Therefore, you'll want to crop it to the specified frameBounds to remove this. | |||
if (cropped) | |||
{ | |||
var bounds = source.frameBounds; | |||
material.mainTextureOffset = new Vector2(bounds.uMin, bounds.vMin); | |||
var du = bounds.uMax - bounds.uMin; | |||
var dv = bounds.vMax - bounds.vMin; | |||
material.mainTextureScale = new Vector2(du, dv); | |||
aspect *= Mathf.Abs(du / dv); | |||
} | |||
else | |||
{ | |||
material.mainTextureOffset = Vector2.zero; | |||
material.mainTextureScale = new Vector2(1, -1); | |||
} | |||
target.localScale = new Vector3(1, 1.0f / aspect, 1); | |||
// Apply the pose that this frame was recorded at. | |||
if (source.hasTracking) | |||
{ | |||
var t = source.transform; | |||
target.localPosition = t.pos; | |||
target.localRotation = t.rot; | |||
} | |||
} | |||
} | |||
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 8b18b36a995ecb04599f35c2741be8d5 | |||
timeCreated: 1465946679 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,127 @@ | |||
%YAML 1.1 | |||
%TAG !u! tag:unity3d.com,2011: | |||
--- !u!21 &2100000 | |||
Material: | |||
serializedVersion: 6 | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 0} | |||
m_Name: SteamVR_TestTrackedCamera | |||
m_Shader: {fileID: 10752, guid: 0000000000000000f000000000000000, type: 0} | |||
m_ShaderKeywords: _EMISSION | |||
m_LightmapFlags: 1 | |||
m_CustomRenderQueue: -1 | |||
stringTagMap: {} | |||
m_SavedProperties: | |||
serializedVersion: 2 | |||
m_TexEnvs: | |||
- first: | |||
name: _BumpMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _DetailAlbedoMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _DetailMask | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _DetailNormalMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _EmissionMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _MainTex | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 0.5, y: -0.49999994} | |||
m_Offset: {x: 0.25, y: 0.75} | |||
- first: | |||
name: _MetallicGlossMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _OcclusionMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _ParallaxMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
m_Floats: | |||
- first: | |||
name: _BumpScale | |||
second: 1 | |||
- first: | |||
name: _Cutoff | |||
second: 0.5 | |||
- first: | |||
name: _DetailNormalMapScale | |||
second: 1 | |||
- first: | |||
name: _DstBlend | |||
second: 0 | |||
- first: | |||
name: _GlossMapScale | |||
second: 1 | |||
- first: | |||
name: _Glossiness | |||
second: 0.5 | |||
- first: | |||
name: _GlossyReflections | |||
second: 1 | |||
- first: | |||
name: _Metallic | |||
second: 0 | |||
- first: | |||
name: _Mode | |||
second: 0 | |||
- first: | |||
name: _OcclusionStrength | |||
second: 1 | |||
- first: | |||
name: _Parallax | |||
second: 0.02 | |||
- first: | |||
name: _SmoothnessTextureChannel | |||
second: 0 | |||
- first: | |||
name: _SpecularHighlights | |||
second: 1 | |||
- first: | |||
name: _SrcBlend | |||
second: 1 | |||
- first: | |||
name: _UVSec | |||
second: 0 | |||
- first: | |||
name: _ZWrite | |||
second: 1 | |||
m_Colors: | |||
- first: | |||
name: _Color | |||
second: {r: 1, g: 1, b: 1, a: 1} | |||
- first: | |||
name: _EmissionColor | |||
second: {r: 0, g: 0, b: 0, a: 1} |
@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 99ee8d48ccf36264e9d9a72baa681249 | |||
timeCreated: 1465950289 | |||
licenseType: Store | |||
NativeFormatImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
size 23886 |
@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 7fb811b0ffe615b4dbf1d5e6ced385fd | |||
timeCreated: 1464227836 | |||
licenseType: Store | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,250 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
using UnityEngine; | |||
using Valve.VR; | |||
public struct ClickedEventArgs | |||
{ | |||
public uint controllerIndex; | |||
public uint flags; | |||
public float padX, padY; | |||
} | |||
public delegate void ClickedEventHandler(object sender, ClickedEventArgs e); | |||
public class SteamVR_TrackedController : MonoBehaviour | |||
{ | |||
public uint controllerIndex; | |||
public VRControllerState_t controllerState; | |||
public bool triggerPressed = false; | |||
public bool steamPressed = false; | |||
public bool menuPressed = false; | |||
public bool padPressed = false; | |||
public bool padTouched = false; | |||
public bool gripped = false; | |||
public event ClickedEventHandler MenuButtonClicked; | |||
public event ClickedEventHandler MenuButtonUnclicked; | |||
public event ClickedEventHandler TriggerClicked; | |||
public event ClickedEventHandler TriggerUnclicked; | |||
public event ClickedEventHandler SteamClicked; | |||
public event ClickedEventHandler PadClicked; | |||
public event ClickedEventHandler PadUnclicked; | |||
public event ClickedEventHandler PadTouched; | |||
public event ClickedEventHandler PadUntouched; | |||
public event ClickedEventHandler Gripped; | |||
public event ClickedEventHandler Ungripped; | |||
// Use this for initialization | |||
protected virtual void Start() | |||
{ | |||
if (this.GetComponent<SteamVR_TrackedObject>() == null) | |||
{ | |||
gameObject.AddComponent<SteamVR_TrackedObject>(); | |||
} | |||
if (controllerIndex != 0) | |||
{ | |||
this.GetComponent<SteamVR_TrackedObject>().index = (SteamVR_TrackedObject.EIndex)controllerIndex; | |||
if (this.GetComponent<SteamVR_RenderModel>() != null) | |||
{ | |||
this.GetComponent<SteamVR_RenderModel>().index = (SteamVR_TrackedObject.EIndex)controllerIndex; | |||
} | |||
} | |||
else | |||
{ | |||
controllerIndex = (uint)this.GetComponent<SteamVR_TrackedObject>().index; | |||
} | |||
} | |||
public void SetDeviceIndex(int index) | |||
{ | |||
this.controllerIndex = (uint)index; | |||
} | |||
public virtual void OnTriggerClicked(ClickedEventArgs e) | |||
{ | |||
if (TriggerClicked != null) | |||
TriggerClicked(this, e); | |||
} | |||
public virtual void OnTriggerUnclicked(ClickedEventArgs e) | |||
{ | |||
if (TriggerUnclicked != null) | |||
TriggerUnclicked(this, e); | |||
} | |||
public virtual void OnMenuClicked(ClickedEventArgs e) | |||
{ | |||
if (MenuButtonClicked != null) | |||
MenuButtonClicked(this, e); | |||
} | |||
public virtual void OnMenuUnclicked(ClickedEventArgs e) | |||
{ | |||
if (MenuButtonUnclicked != null) | |||
MenuButtonUnclicked(this, e); | |||
} | |||
public virtual void OnSteamClicked(ClickedEventArgs e) | |||
{ | |||
if (SteamClicked != null) | |||
SteamClicked(this, e); | |||
} | |||
public virtual void OnPadClicked(ClickedEventArgs e) | |||
{ | |||
if (PadClicked != null) | |||
PadClicked(this, e); | |||
} | |||
public virtual void OnPadUnclicked(ClickedEventArgs e) | |||
{ | |||
if (PadUnclicked != null) | |||
PadUnclicked(this, e); | |||
} | |||
public virtual void OnPadTouched(ClickedEventArgs e) | |||
{ | |||
if (PadTouched != null) | |||
PadTouched(this, e); | |||
} | |||
public virtual void OnPadUntouched(ClickedEventArgs e) | |||
{ | |||
if (PadUntouched != null) | |||
PadUntouched(this, e); | |||
} | |||
public virtual void OnGripped(ClickedEventArgs e) | |||
{ | |||
if (Gripped != null) | |||
Gripped(this, e); | |||
} | |||
public virtual void OnUngripped(ClickedEventArgs e) | |||
{ | |||
if (Ungripped != null) | |||
Ungripped(this, e); | |||
} | |||
// Update is called once per frame | |||
protected virtual void Update() | |||
{ | |||
var system = OpenVR.System; | |||
if (system != null && system.GetControllerState(controllerIndex, ref controllerState, (uint)System.Runtime.InteropServices.Marshal.SizeOf(typeof(VRControllerState_t)))) | |||
{ | |||
ulong trigger = controllerState.ulButtonPressed & (1UL << ((int)EVRButtonId.k_EButton_SteamVR_Trigger)); | |||
if (trigger > 0L && !triggerPressed) | |||
{ | |||
triggerPressed = true; | |||
ClickedEventArgs e; | |||
e.controllerIndex = controllerIndex; | |||
e.flags = (uint)controllerState.ulButtonPressed; | |||
e.padX = controllerState.rAxis0.x; | |||
e.padY = controllerState.rAxis0.y; | |||
OnTriggerClicked(e); | |||
} | |||
else if (trigger == 0L && triggerPressed) | |||
{ | |||
triggerPressed = false; | |||
ClickedEventArgs e; | |||
e.controllerIndex = controllerIndex; | |||
e.flags = (uint)controllerState.ulButtonPressed; | |||
e.padX = controllerState.rAxis0.x; | |||
e.padY = controllerState.rAxis0.y; | |||
OnTriggerUnclicked(e); | |||
} | |||
ulong grip = controllerState.ulButtonPressed & (1UL << ((int)EVRButtonId.k_EButton_Grip)); | |||
if (grip > 0L && !gripped) | |||
{ | |||
gripped = true; | |||
ClickedEventArgs e; | |||
e.controllerIndex = controllerIndex; | |||
e.flags = (uint)controllerState.ulButtonPressed; | |||
e.padX = controllerState.rAxis0.x; | |||
e.padY = controllerState.rAxis0.y; | |||
OnGripped(e); | |||
} | |||
else if (grip == 0L && gripped) | |||
{ | |||
gripped = false; | |||
ClickedEventArgs e; | |||
e.controllerIndex = controllerIndex; | |||
e.flags = (uint)controllerState.ulButtonPressed; | |||
e.padX = controllerState.rAxis0.x; | |||
e.padY = controllerState.rAxis0.y; | |||
OnUngripped(e); | |||
} | |||
ulong pad = controllerState.ulButtonPressed & (1UL << ((int)EVRButtonId.k_EButton_SteamVR_Touchpad)); | |||
if (pad > 0L && !padPressed) | |||
{ | |||
padPressed = true; | |||
ClickedEventArgs e; | |||
e.controllerIndex = controllerIndex; | |||
e.flags = (uint)controllerState.ulButtonPressed; | |||
e.padX = controllerState.rAxis0.x; | |||
e.padY = controllerState.rAxis0.y; | |||
OnPadClicked(e); | |||
} | |||
else if (pad == 0L && padPressed) | |||
{ | |||
padPressed = false; | |||
ClickedEventArgs e; | |||
e.controllerIndex = controllerIndex; | |||
e.flags = (uint)controllerState.ulButtonPressed; | |||
e.padX = controllerState.rAxis0.x; | |||
e.padY = controllerState.rAxis0.y; | |||
OnPadUnclicked(e); | |||
} | |||
ulong menu = controllerState.ulButtonPressed & (1UL << ((int)EVRButtonId.k_EButton_ApplicationMenu)); | |||
if (menu > 0L && !menuPressed) | |||
{ | |||
menuPressed = true; | |||
ClickedEventArgs e; | |||
e.controllerIndex = controllerIndex; | |||
e.flags = (uint)controllerState.ulButtonPressed; | |||
e.padX = controllerState.rAxis0.x; | |||
e.padY = controllerState.rAxis0.y; | |||
OnMenuClicked(e); | |||
} | |||
else if (menu == 0L && menuPressed) | |||
{ | |||
menuPressed = false; | |||
ClickedEventArgs e; | |||
e.controllerIndex = controllerIndex; | |||
e.flags = (uint)controllerState.ulButtonPressed; | |||
e.padX = controllerState.rAxis0.x; | |||
e.padY = controllerState.rAxis0.y; | |||
OnMenuUnclicked(e); | |||
} | |||
pad = controllerState.ulButtonTouched & (1UL << ((int)EVRButtonId.k_EButton_SteamVR_Touchpad)); | |||
if (pad > 0L && !padTouched) | |||
{ | |||
padTouched = true; | |||
ClickedEventArgs e; | |||
e.controllerIndex = controllerIndex; | |||
e.flags = (uint)controllerState.ulButtonPressed; | |||
e.padX = controllerState.rAxis0.x; | |||
e.padY = controllerState.rAxis0.y; | |||
OnPadTouched(e); | |||
} | |||
else if (pad == 0L && padTouched) | |||
{ | |||
padTouched = false; | |||
ClickedEventArgs e; | |||
e.controllerIndex = controllerIndex; | |||
e.flags = (uint)controllerState.ulButtonPressed; | |||
e.padX = controllerState.rAxis0.x; | |||
e.padY = controllerState.rAxis0.y; | |||
OnPadUntouched(e); | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 7346a42905a29b347b1f492e8ad7b49f | |||
timeCreated: 1430337756 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {instanceID: 0} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: c8941a9f98c35d84cb19a5e044467de9 | |||
folderAsset: yes | |||
timeCreated: 1479762244 | |||
licenseType: Store | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 1ab2780fe1da2544b86a1020e5f638e2 | |||
folderAsset: yes | |||
timeCreated: 1479762244 | |||
licenseType: Store | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 1fcf8377413b60c44afff7b2e4efd8f7 | |||
folderAsset: yes | |||
timeCreated: 1482867667 | |||
licenseType: Store | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
size 14839 |
@ -0,0 +1,59 @@ | |||
fileFormatVersion: 2 | |||
guid: b93fe5c516cf6ed4b9153ec790f856e2 | |||
timeCreated: 1484264198 | |||
licenseType: Store | |||
TextureImporter: | |||
fileIDToRecycleName: {} | |||
serializedVersion: 2 | |||
mipmaps: | |||
mipMapMode: 0 | |||
enableMipMap: 0 | |||
linearTexture: 1 | |||
correctGamma: 0 | |||
fadeOut: 0 | |||
borderMipMap: 0 | |||
mipMapFadeDistanceStart: 1 | |||
mipMapFadeDistanceEnd: 3 | |||
bumpmap: | |||
convertToNormalMap: 0 | |||
externalNormalMap: 0 | |||
heightScale: 0.25 | |||
normalMapFilter: 0 | |||
isReadable: 0 | |||
grayScaleToAlpha: 0 | |||
generateCubemap: 0 | |||
cubemapConvolution: 0 | |||
cubemapConvolutionSteps: 7 | |||
cubemapConvolutionExponent: 1.5 | |||
seamlessCubemap: 0 | |||
textureFormat: -1 | |||
maxTextureSize: 2048 | |||
textureSettings: | |||
filterMode: -1 | |||
aniso: 1 | |||
mipBias: -1 | |||
wrapMode: 1 | |||
nPOTScale: 0 | |||
lightmap: 0 | |||
rGBM: 0 | |||
compressionQuality: 50 | |||
allowsAlphaSplitting: 0 | |||
spriteMode: 0 | |||
spriteExtrude: 1 | |||
spriteMeshType: 1 | |||
alignment: 0 | |||
spritePivot: {x: 0.5, y: 0.5} | |||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} | |||
spritePixelsToUnits: 100 | |||
alphaIsTransparency: 1 | |||
spriteTessellationDetail: -1 | |||
textureType: 2 | |||
buildTargetSettings: [] | |||
spriteSheet: | |||
serializedVersion: 2 | |||
sprites: [] | |||
outline: [] | |||
spritePackingTag: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
size 11011 |
@ -0,0 +1,55 @@ | |||
fileFormatVersion: 2 | |||
guid: 032fb1710098a1d47ad34d72e90f714a | |||
timeCreated: 1435940722 | |||
licenseType: Store | |||
TextureImporter: | |||
fileIDToRecycleName: {} | |||
serializedVersion: 2 | |||
mipmaps: | |||
mipMapMode: 0 | |||
enableMipMap: 0 | |||
linearTexture: 1 | |||
correctGamma: 0 | |||
fadeOut: 0 | |||
borderMipMap: 0 | |||
mipMapFadeDistanceStart: 1 | |||
mipMapFadeDistanceEnd: 3 | |||
bumpmap: | |||
convertToNormalMap: 0 | |||
externalNormalMap: 0 | |||
heightScale: .25 | |||
normalMapFilter: 0 | |||
isReadable: 0 | |||
grayScaleToAlpha: 0 | |||
generateCubemap: 0 | |||
cubemapConvolution: 0 | |||
cubemapConvolutionSteps: 8 | |||
cubemapConvolutionExponent: 1.5 | |||
seamlessCubemap: 0 | |||
textureFormat: -3 | |||
maxTextureSize: 2048 | |||
textureSettings: | |||
filterMode: -1 | |||
aniso: 1 | |||
mipBias: -1 | |||
wrapMode: 1 | |||
nPOTScale: 0 | |||
lightmap: 0 | |||
rGBM: 0 | |||
compressionQuality: 50 | |||
spriteMode: 0 | |||
spriteExtrude: 1 | |||
spriteMeshType: 1 | |||
alignment: 0 | |||
spritePivot: {x: .5, y: .5} | |||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} | |||
spritePixelsToUnits: 100 | |||
alphaIsTransparency: 1 | |||
textureType: 2 | |||
buildTargetSettings: [] | |||
spriteSheet: | |||
sprites: [] | |||
spritePackingTag: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
size 10034 |
@ -0,0 +1,55 @@ | |||
fileFormatVersion: 2 | |||
guid: 27f3faef5a63db84c9cbac06e94ab7b3 | |||
timeCreated: 1435940722 | |||
licenseType: Store | |||
TextureImporter: | |||
fileIDToRecycleName: {} | |||
serializedVersion: 2 | |||
mipmaps: | |||
mipMapMode: 0 | |||
enableMipMap: 0 | |||
linearTexture: 1 | |||
correctGamma: 0 | |||
fadeOut: 0 | |||
borderMipMap: 0 | |||
mipMapFadeDistanceStart: 1 | |||
mipMapFadeDistanceEnd: 3 | |||
bumpmap: | |||
convertToNormalMap: 0 | |||
externalNormalMap: 0 | |||
heightScale: .25 | |||
normalMapFilter: 0 | |||
isReadable: 0 | |||
grayScaleToAlpha: 0 | |||
generateCubemap: 0 | |||
cubemapConvolution: 0 | |||
cubemapConvolutionSteps: 8 | |||
cubemapConvolutionExponent: 1.5 | |||
seamlessCubemap: 0 | |||
textureFormat: -3 | |||
maxTextureSize: 2048 | |||
textureSettings: | |||
filterMode: -1 | |||
aniso: 1 | |||
mipBias: -1 | |||
wrapMode: 1 | |||
nPOTScale: 0 | |||
lightmap: 0 | |||
rGBM: 0 | |||
compressionQuality: 50 | |||
spriteMode: 0 | |||
spriteExtrude: 1 | |||
spriteMeshType: 1 | |||
alignment: 0 | |||
spritePivot: {x: .5, y: .5} | |||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} | |||
spritePixelsToUnits: 100 | |||
alphaIsTransparency: 1 | |||
textureType: 2 | |||
buildTargetSettings: [] | |||
spriteSheet: | |||
sprites: [] | |||
spritePackingTag: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
size 11809 |
@ -0,0 +1,55 @@ | |||
fileFormatVersion: 2 | |||
guid: 6789d499b24f8964c8bb06e21008e546 | |||
timeCreated: 1435940722 | |||
licenseType: Store | |||
TextureImporter: | |||
fileIDToRecycleName: {} | |||
serializedVersion: 2 | |||
mipmaps: | |||
mipMapMode: 0 | |||
enableMipMap: 0 | |||
linearTexture: 1 | |||
correctGamma: 0 | |||
fadeOut: 0 | |||
borderMipMap: 0 | |||
mipMapFadeDistanceStart: 1 | |||
mipMapFadeDistanceEnd: 3 | |||
bumpmap: | |||
convertToNormalMap: 0 | |||
externalNormalMap: 0 | |||
heightScale: .25 | |||
normalMapFilter: 0 | |||
isReadable: 0 | |||
grayScaleToAlpha: 0 | |||
generateCubemap: 0 | |||
cubemapConvolution: 0 | |||
cubemapConvolutionSteps: 8 | |||
cubemapConvolutionExponent: 1.5 | |||
seamlessCubemap: 0 | |||
textureFormat: -3 | |||
maxTextureSize: 2048 | |||
textureSettings: | |||
filterMode: -1 | |||
aniso: 1 | |||
mipBias: -1 | |||
wrapMode: 1 | |||
nPOTScale: 0 | |||
lightmap: 0 | |||
rGBM: 0 | |||
compressionQuality: 50 | |||
spriteMode: 0 | |||
spriteExtrude: 1 | |||
spriteMeshType: 1 | |||
alignment: 0 | |||
spritePivot: {x: .5, y: .5} | |||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} | |||
spritePixelsToUnits: 100 | |||
alphaIsTransparency: 1 | |||
textureType: 2 | |||
buildTargetSettings: [] | |||
spriteSheet: | |||
sprites: [] | |||
spritePackingTag: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
size 10163 |
@ -0,0 +1,55 @@ | |||
fileFormatVersion: 2 | |||
guid: 1acda2a2584a8fb4683ea56799b27fa0 | |||
timeCreated: 1435940722 | |||
licenseType: Store | |||
TextureImporter: | |||
fileIDToRecycleName: {} | |||
serializedVersion: 2 | |||
mipmaps: | |||
mipMapMode: 0 | |||
enableMipMap: 0 | |||
linearTexture: 1 | |||
correctGamma: 0 | |||
fadeOut: 0 | |||
borderMipMap: 0 | |||
mipMapFadeDistanceStart: 1 | |||
mipMapFadeDistanceEnd: 3 | |||
bumpmap: | |||
convertToNormalMap: 0 | |||
externalNormalMap: 0 | |||
heightScale: .25 | |||
normalMapFilter: 0 | |||
isReadable: 0 | |||
grayScaleToAlpha: 0 | |||
generateCubemap: 0 | |||
cubemapConvolution: 0 | |||
cubemapConvolutionSteps: 8 | |||
cubemapConvolutionExponent: 1.5 | |||
seamlessCubemap: 0 | |||
textureFormat: -3 | |||
maxTextureSize: 2048 | |||
textureSettings: | |||
filterMode: -1 | |||
aniso: 1 | |||
mipBias: -1 | |||
wrapMode: 1 | |||
nPOTScale: 0 | |||
lightmap: 0 | |||
rGBM: 0 | |||
compressionQuality: 50 | |||
spriteMode: 0 | |||
spriteExtrude: 1 | |||
spriteMeshType: 1 | |||
alignment: 0 | |||
spritePivot: {x: .5, y: .5} | |||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} | |||
spritePixelsToUnits: 100 | |||
alphaIsTransparency: 1 | |||
textureType: 2 | |||
buildTargetSettings: [] | |||
spriteSheet: | |||
sprites: [] | |||
spritePackingTag: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
size 11971 |
@ -0,0 +1,55 @@ | |||
fileFormatVersion: 2 | |||
guid: 90173f9e9e795f74ca97ccc52fe410cd | |||
timeCreated: 1435940723 | |||
licenseType: Store | |||
TextureImporter: | |||
fileIDToRecycleName: {} | |||
serializedVersion: 2 | |||
mipmaps: | |||
mipMapMode: 0 | |||
enableMipMap: 0 | |||
linearTexture: 1 | |||
correctGamma: 0 | |||
fadeOut: 0 | |||
borderMipMap: 0 | |||
mipMapFadeDistanceStart: 1 | |||
mipMapFadeDistanceEnd: 3 | |||
bumpmap: | |||
convertToNormalMap: 0 | |||
externalNormalMap: 0 | |||
heightScale: .25 | |||
normalMapFilter: 0 | |||
isReadable: 0 | |||
grayScaleToAlpha: 0 | |||
generateCubemap: 0 | |||
cubemapConvolution: 0 | |||
cubemapConvolutionSteps: 8 | |||
cubemapConvolutionExponent: 1.5 | |||
seamlessCubemap: 0 | |||
textureFormat: -3 | |||
maxTextureSize: 2048 | |||
textureSettings: | |||
filterMode: -1 | |||
aniso: 1 | |||
mipBias: -1 | |||
wrapMode: 1 | |||
nPOTScale: 0 | |||
lightmap: 0 | |||
rGBM: 0 | |||
compressionQuality: 50 | |||
spriteMode: 0 | |||
spriteExtrude: 1 | |||
spriteMeshType: 1 | |||
alignment: 0 | |||
spritePivot: {x: .5, y: .5} | |||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} | |||
spritePixelsToUnits: 100 | |||
alphaIsTransparency: 1 | |||
textureType: 2 | |||
buildTargetSettings: [] | |||
spriteSheet: | |||
sprites: [] | |||
spritePackingTag: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
size 13315 |
@ -0,0 +1,55 @@ | |||
fileFormatVersion: 2 | |||
guid: 77b322b27d7d39f4d91e479d19065d50 | |||
timeCreated: 1435940723 | |||
licenseType: Store | |||
TextureImporter: | |||
fileIDToRecycleName: {} | |||
serializedVersion: 2 | |||
mipmaps: | |||
mipMapMode: 0 | |||
enableMipMap: 0 | |||
linearTexture: 1 | |||
correctGamma: 0 | |||
fadeOut: 0 | |||
borderMipMap: 0 | |||
mipMapFadeDistanceStart: 1 | |||
mipMapFadeDistanceEnd: 3 | |||
bumpmap: | |||
convertToNormalMap: 0 | |||
externalNormalMap: 0 | |||
heightScale: .25 | |||
normalMapFilter: 0 | |||
isReadable: 0 | |||
grayScaleToAlpha: 0 | |||
generateCubemap: 0 | |||
cubemapConvolution: 0 | |||
cubemapConvolutionSteps: 8 | |||
cubemapConvolutionExponent: 1.5 | |||
seamlessCubemap: 0 | |||
textureFormat: -3 | |||
maxTextureSize: 2048 | |||
textureSettings: | |||
filterMode: -1 | |||
aniso: 1 | |||
mipBias: -1 | |||
wrapMode: 1 | |||
nPOTScale: 0 | |||
lightmap: 0 | |||
rGBM: 0 | |||
compressionQuality: 50 | |||
spriteMode: 0 | |||
spriteExtrude: 1 | |||
spriteMeshType: 1 | |||
alignment: 0 | |||
spritePivot: {x: .5, y: .5} | |||
spriteBorder: {x: 0, y: 0, z: 0, w: 0} | |||
spritePixelsToUnits: 100 | |||
alphaIsTransparency: 1 | |||
textureType: 2 | |||
buildTargetSettings: [] | |||
spriteSheet: | |||
sprites: [] | |||
spritePackingTag: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 05a69997deb9f5944a894239434f00a9 | |||
folderAsset: yes | |||
timeCreated: 1479762244 | |||
licenseType: Store | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,138 @@ | |||
%YAML 1.1 | |||
%TAG !u! tag:unity3d.com,2011: | |||
--- !u!21 &2100000 | |||
Material: | |||
serializedVersion: 6 | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 0} | |||
m_Name: FallbackHandIndicator | |||
m_Shader: {fileID: 10755, guid: 0000000000000000f000000000000000, type: 0} | |||
m_ShaderKeywords: | |||
m_LightmapFlags: 5 | |||
m_CustomRenderQueue: 2000 | |||
stringTagMap: {} | |||
m_SavedProperties: | |||
serializedVersion: 2 | |||
m_TexEnvs: | |||
data: | |||
first: | |||
name: _MainTex | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
data: | |||
first: | |||
name: _BumpMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
data: | |||
first: | |||
name: _DetailNormalMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
data: | |||
first: | |||
name: _MetallicGlossMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
data: | |||
first: | |||
name: _ParallaxMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
data: | |||
first: | |||
name: _OcclusionMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
data: | |||
first: | |||
name: _EmissionMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
data: | |||
first: | |||
name: _DetailMask | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
data: | |||
first: | |||
name: _DetailAlbedoMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
m_Floats: | |||
data: | |||
first: | |||
name: _SrcBlend | |||
second: 1 | |||
data: | |||
first: | |||
name: _DstBlend | |||
second: 0 | |||
data: | |||
first: | |||
name: _Cutoff | |||
second: .5 | |||
data: | |||
first: | |||
name: _ZWrite | |||
second: 1 | |||
data: | |||
first: | |||
name: _Glossiness | |||
second: 0 | |||
data: | |||
first: | |||
name: _Metallic | |||
second: 0 | |||
data: | |||
first: | |||
name: _BumpScale | |||
second: 1 | |||
data: | |||
first: | |||
name: _Parallax | |||
second: .0199999996 | |||
data: | |||
first: | |||
name: _OcclusionStrength | |||
second: 1 | |||
data: | |||
first: | |||
name: _DetailNormalMapScale | |||
second: 1 | |||
data: | |||
first: | |||
name: _UVSec | |||
second: 0 | |||
data: | |||
first: | |||
name: _Mode | |||
second: 0 | |||
m_Colors: | |||
data: | |||
first: | |||
name: _EmissionColor | |||
second: {r: 0, g: 0, b: 0, a: 1} | |||
data: | |||
first: | |||
name: _Color | |||
second: {r: 1, g: 0, b: 0, a: 1} |
@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 9e995e61de69d8647ae2b2d65eceab3f | |||
timeCreated: 1436394722 | |||
licenseType: Store | |||
NativeFormatImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,182 @@ | |||
%YAML 1.1 | |||
%TAG !u! tag:unity3d.com,2011: | |||
--- !u!21 &2100000 | |||
Material: | |||
serializedVersion: 6 | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 0} | |||
m_Name: HoverHighlight | |||
m_Shader: {fileID: 4800000, guid: 0c1cf10ea69e60e4f9eb8955749f88ec, type: 3} | |||
m_ShaderKeywords: | |||
m_LightmapFlags: 5 | |||
m_CustomRenderQueue: -1 | |||
stringTagMap: {} | |||
m_SavedProperties: | |||
serializedVersion: 2 | |||
m_TexEnvs: | |||
data: | |||
first: | |||
name: _MainTex | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
data: | |||
first: | |||
name: _BumpMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
data: | |||
first: | |||
name: _DetailNormalMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
data: | |||
first: | |||
name: _ParallaxMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
data: | |||
first: | |||
name: _OcclusionMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
data: | |||
first: | |||
name: _EmissionMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
data: | |||
first: | |||
name: _DetailMask | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
data: | |||
first: | |||
name: _DetailAlbedoMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
data: | |||
first: | |||
name: _MetallicGlossMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
m_Floats: | |||
data: | |||
first: | |||
name: _SrcBlend | |||
second: 1 | |||
data: | |||
first: | |||
name: _DstBlend | |||
second: 0 | |||
data: | |||
first: | |||
name: _Cutoff | |||
second: 0.5 | |||
data: | |||
first: | |||
name: g_flOutlineWidth | |||
second: 0.005 | |||
data: | |||
first: | |||
name: _Parallax | |||
second: 0.02 | |||
data: | |||
first: | |||
name: _ZWrite | |||
second: 1 | |||
data: | |||
first: | |||
name: _Glossiness | |||
second: 0.5 | |||
data: | |||
first: | |||
name: _BumpScale | |||
second: 1 | |||
data: | |||
first: | |||
name: _OcclusionStrength | |||
second: 1 | |||
data: | |||
first: | |||
name: _DetailNormalMapScale | |||
second: 1 | |||
data: | |||
first: | |||
name: _UVSec | |||
second: 0 | |||
data: | |||
first: | |||
name: _Mode | |||
second: 0 | |||
data: | |||
first: | |||
name: _Metallic | |||
second: 0 | |||
data: | |||
first: | |||
name: _Outline | |||
second: 0.005 | |||
data: | |||
first: | |||
name: _Opacity | |||
second: 0 | |||
data: | |||
first: | |||
name: _node_6969 | |||
second: 0 | |||
data: | |||
first: | |||
name: _OutlineWidth | |||
second: 0.00238 | |||
m_Colors: | |||
data: | |||
first: | |||
name: _EmissionColor | |||
second: {r: 0, g: 0, b: 0, a: 1} | |||
data: | |||
first: | |||
name: _Color | |||
second: {r: 0.486632, g: 0.78411454, b: 0.8823653, a: 1} | |||
data: | |||
first: | |||
name: g_vOutlineColor | |||
second: {r: 0.9485294, g: 0.9223629, b: 0, a: 1} | |||
data: | |||
first: | |||
name: _OutlineColor | |||
second: {r: 1, g: 0.9833671, b: 0.39705884, a: 1} | |||
data: | |||
first: | |||
name: _node_2507 | |||
second: {r: 0.6421389, g: 0.7807802, b: 0.78676474, a: 0} | |||
data: | |||
first: | |||
name: _OutlightColor | |||
second: {r: 0.9446255, g: 1, b: 0.42647058, a: 0.347} | |||
data: | |||
first: | |||
name: _node_8174 | |||
second: {r: 0.5, g: 0.5, b: 0.5, a: 1} | |||
data: | |||
first: | |||
name: _node_8282 | |||
second: {r: 1, g: 1, b: 1, a: 1} |
@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 7b939e5e799d98a469f594828ebab52e | |||
timeCreated: 1439237525 | |||
licenseType: Store | |||
NativeFormatImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,213 @@ | |||
%YAML 1.1 | |||
%TAG !u! tag:unity3d.com,2011: | |||
--- !u!21 &2100000 | |||
Material: | |||
serializedVersion: 6 | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 0} | |||
m_Name: SeeThru | |||
m_Shader: {fileID: 4800000, guid: 6337aa7e7823eee43af8ffe676935e74, type: 3} | |||
m_ShaderKeywords: S_SPECULAR_NONE S_UNLIT _ALPHABLEND_ON | |||
m_LightmapFlags: 5 | |||
m_CustomRenderQueue: -1 | |||
stringTagMap: | |||
OriginalShader: Unlit/Texture | |||
RenderType: Transparent | |||
m_SavedProperties: | |||
serializedVersion: 2 | |||
m_TexEnvs: | |||
- first: | |||
name: _BumpMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _DetailAlbedoMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _DetailMask | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _DetailNormalMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _EmissionMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _MainTex | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _MetallicGlossMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _OcclusionMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _ParallaxMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _SpecGlossMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: g_tOverrideLightmap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
m_Floats: | |||
- first: | |||
name: PixelSnap | |||
second: 0 | |||
- first: | |||
name: _BumpScale | |||
second: 1 | |||
- first: | |||
name: _ColorMask | |||
second: 15 | |||
- first: | |||
name: _Cutoff | |||
second: 0.5 | |||
- first: | |||
name: _DetailNormalMapScale | |||
second: 1 | |||
- first: | |||
name: _DstBlend | |||
second: 10 | |||
- first: | |||
name: _Glossiness | |||
second: 0.5 | |||
- first: | |||
name: _InvFade | |||
second: 0.5 | |||
- first: | |||
name: _Metallic | |||
second: 0 | |||
- first: | |||
name: _Mode | |||
second: 2 | |||
- first: | |||
name: _OcclusionStrength | |||
second: 1 | |||
- first: | |||
name: _OcclusionStrengthDirectDiffuse | |||
second: 1 | |||
- first: | |||
name: _OcclusionStrengthDirectSpecular | |||
second: 1 | |||
- first: | |||
name: _OcclusionStrengthIndirectDiffuse | |||
second: 1 | |||
- first: | |||
name: _OcclusionStrengthIndirectSpecular | |||
second: 1 | |||
- first: | |||
name: _Parallax | |||
second: 0.02 | |||
- first: | |||
name: _SpecularMode | |||
second: 1 | |||
- first: | |||
name: _SrcBlend | |||
second: 5 | |||
- first: | |||
name: _Stencil | |||
second: 0 | |||
- first: | |||
name: _StencilComp | |||
second: 8 | |||
- first: | |||
name: _StencilOp | |||
second: 0 | |||
- first: | |||
name: _StencilReadMask | |||
second: 255 | |||
- first: | |||
name: _StencilWriteMask | |||
second: 255 | |||
- first: | |||
name: _UVSec | |||
second: 0 | |||
- first: | |||
name: _ZWrite | |||
second: 0 | |||
- first: | |||
name: g_bReceiveShadows | |||
second: 1 | |||
- first: | |||
name: g_bUnlit | |||
second: 1 | |||
- first: | |||
name: g_bWorldAlignedTexture | |||
second: 0 | |||
- first: | |||
name: g_flCubeMapScalar | |||
second: 1 | |||
- first: | |||
name: g_flReflectanceBias | |||
second: 0 | |||
- first: | |||
name: g_flReflectanceMax | |||
second: 1 | |||
- first: | |||
name: g_flReflectanceMin | |||
second: 0 | |||
- first: | |||
name: g_flReflectanceScale | |||
second: 1 | |||
m_Colors: | |||
- first: | |||
name: _Color | |||
second: {r: 0.24999985, g: 0.24999985, b: 0.24999985, a: 0.1254902} | |||
- first: | |||
name: _EmissionColor | |||
second: {r: 0, g: 0, b: 0, a: 1} | |||
- first: | |||
name: _SpecColor | |||
second: {r: 0.2, g: 0.2, b: 0.2, a: 1} | |||
- first: | |||
name: _TintColor | |||
second: {r: 0.5, g: 0.5, b: 0.5, a: 0.5} | |||
- first: | |||
name: g_vWorldAlignedNormalTangentU | |||
second: {r: -1, g: 0, b: 0, a: 0} | |||
- first: | |||
name: g_vWorldAlignedNormalTangentV | |||
second: {r: 0, g: 0, b: 1, a: 0} | |||
- first: | |||
name: g_vWorldAlignedTextureNormal | |||
second: {r: 0, g: 1, b: 0, a: 0} | |||
- first: | |||
name: g_vWorldAlignedTexturePosition | |||
second: {r: 0, g: 0, b: 0, a: 0} | |||
- first: | |||
name: g_vWorldAlignedTextureSize | |||
second: {r: 1, g: 1, b: 1, a: 0} |
@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 3bbb445147c574240a8b87a1193788b5 | |||
timeCreated: 1456708947 | |||
licenseType: Store | |||
NativeFormatImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,197 @@ | |||
%YAML 1.1 | |||
%TAG !u! tag:unity3d.com,2011: | |||
--- !u!21 &2100000 | |||
Material: | |||
serializedVersion: 6 | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 0} | |||
m_Name: SteamVRControllerModel | |||
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} | |||
m_ShaderKeywords: S_RECEIVE_SHADOWS S_SPECULAR_METALLIC _EMISSION | |||
m_LightmapFlags: 1 | |||
m_CustomRenderQueue: -1 | |||
stringTagMap: | |||
OriginalShader: Standard | |||
m_SavedProperties: | |||
serializedVersion: 2 | |||
m_TexEnvs: | |||
- first: | |||
name: _BumpMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _DetailAlbedoMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _DetailMask | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _DetailNormalMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _EmissionMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _MainTex | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _MetallicGlossMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _OcclusionMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _ParallaxMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: _SpecGlossMap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
- first: | |||
name: g_tOverrideLightmap | |||
second: | |||
m_Texture: {fileID: 0} | |||
m_Scale: {x: 1, y: 1} | |||
m_Offset: {x: 0, y: 0} | |||
m_Floats: | |||
- first: | |||
name: _BumpScale | |||
second: 1 | |||
- first: | |||
name: _Cutoff | |||
second: 0.5 | |||
- first: | |||
name: _DetailNormalMapScale | |||
second: 1 | |||
- first: | |||
name: _DstBlend | |||
second: 0 | |||
- first: | |||
name: _GlossMapScale | |||
second: 1 | |||
- first: | |||
name: _Glossiness | |||
second: 0.405 | |||
- first: | |||
name: _GlossyReflections | |||
second: 1 | |||
- first: | |||
name: _Metallic | |||
second: 0 | |||
- first: | |||
name: _Mode | |||
second: 0 | |||
- first: | |||
name: _OcclusionStrength | |||
second: 1 | |||
- first: | |||
name: _OcclusionStrengthDirectDiffuse | |||
second: 1 | |||
- first: | |||
name: _OcclusionStrengthDirectSpecular | |||
second: 1 | |||
- first: | |||
name: _OcclusionStrengthIndirectDiffuse | |||
second: 1 | |||
- first: | |||
name: _OcclusionStrengthIndirectSpecular | |||
second: 1 | |||
- first: | |||
name: _Parallax | |||
second: 0.02 | |||
- first: | |||
name: _SmoothnessTextureChannel | |||
second: 0 | |||
- first: | |||
name: _SpecularHighlights | |||
second: 1 | |||
- first: | |||
name: _SpecularMode | |||
second: 2 | |||
- first: | |||
name: _SrcBlend | |||
second: 1 | |||
- first: | |||
name: _UVSec | |||
second: 0 | |||
- first: | |||
name: _ZWrite | |||
second: 1 | |||
- first: | |||
name: g_bReceiveShadows | |||
second: 1 | |||
- first: | |||
name: g_bUnlit | |||
second: 0 | |||
- first: | |||
name: g_bWorldAlignedTexture | |||
second: 0 | |||
- first: | |||
name: g_flCubeMapScalar | |||
second: 1 | |||
- first: | |||
name: g_flReflectanceBias | |||
second: 0 | |||
- first: | |||
name: g_flReflectanceMax | |||
second: 1 | |||
- first: | |||
name: g_flReflectanceMin | |||
second: 0 | |||
- first: | |||
name: g_flReflectanceScale | |||
second: 1 | |||
m_Colors: | |||
- first: | |||
name: _Color | |||
second: {r: 1, g: 1, b: 1, a: 1} | |||
- first: | |||
name: _EmissionColor | |||
second: {r: 0, g: 0, b: 0, a: 1} | |||
- first: | |||
name: _SpecColor | |||
second: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1} | |||
- first: | |||
name: g_vWorldAlignedNormalTangentU | |||
second: {r: -1, g: 0, b: 0, a: 0} | |||
- first: | |||
name: g_vWorldAlignedNormalTangentV | |||
second: {r: 0, g: 0, b: 1, a: 0} | |||
- first: | |||
name: g_vWorldAlignedTextureNormal | |||
second: {r: 0, g: 1, b: 0, a: 0} | |||
- first: | |||
name: g_vWorldAlignedTexturePosition | |||
second: {r: 0, g: 0, b: 0, a: 0} | |||
- first: | |||
name: g_vWorldAlignedTextureSize | |||
second: {r: 1, g: 1, b: 1, a: 0} |
@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 3c433e134e4719444b65bf064a77e22e | |||
timeCreated: 1455877211 | |||
licenseType: Store | |||
NativeFormatImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 6d60d25020af6fb4f8d436244db7cc4b | |||
folderAsset: yes | |||
timeCreated: 1479762244 | |||
licenseType: Store | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,111 @@ | |||
%YAML 1.1 | |||
%TAG !u! tag:unity3d.com,2011: | |||
--- !u!1 &168468 | |||
GameObject: | |||
m_ObjectHideFlags: 0 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
serializedVersion: 4 | |||
m_Component: | |||
- 4: {fileID: 421934} | |||
- 114: {fileID: 11485822} | |||
- 114: {fileID: 11450892} | |||
- 114: {fileID: 11435852} | |||
- 114: {fileID: 11467152} | |||
m_Layer: 0 | |||
m_Name: BlankController | |||
m_TagString: Untagged | |||
m_Icon: {fileID: 0} | |||
m_NavMeshLayer: 0 | |||
m_StaticEditorFlags: 0 | |||
m_IsActive: 1 | |||
--- !u!4 &421934 | |||
Transform: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 168468} | |||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} | |||
m_LocalPosition: {x: 0, y: 0, z: 0} | |||
m_LocalScale: {x: 1, y: 1, z: 1} | |||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} | |||
m_Children: [] | |||
m_Father: {fileID: 0} | |||
m_RootOrder: 0 | |||
--- !u!114 &11435852 | |||
MonoBehaviour: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 168468} | |||
m_Enabled: 1 | |||
m_EditorHideFlags: 0 | |||
m_Script: {fileID: 11500000, guid: 9fb3fe54664b917489646492ee8c4993, type: 3} | |||
m_Name: | |||
m_EditorClassIdentifier: | |||
materials: | |||
- {fileID: 2100000, guid: 3c433e134e4719444b65bf064a77e22e, type: 2} | |||
- {fileID: 2100000, guid: 3bbb445147c574240a8b87a1193788b5, type: 2} | |||
--- !u!114 &11450892 | |||
MonoBehaviour: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 168468} | |||
m_Enabled: 1 | |||
m_EditorHideFlags: 0 | |||
m_Script: {fileID: 11500000, guid: eb6d6653511aff5409d0827d4e3b79ea, type: 3} | |||
m_Name: | |||
m_EditorClassIdentifier: | |||
--- !u!114 &11467152 | |||
MonoBehaviour: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 168468} | |||
m_Enabled: 1 | |||
m_EditorHideFlags: 0 | |||
m_Script: {fileID: 11500000, guid: b8d4cc6cf300b3e4bb1411c4e041030c, type: 3} | |||
m_Name: | |||
m_EditorClassIdentifier: | |||
teleportAllowed: 1 | |||
overrideHoverLock: 1 | |||
--- !u!114 &11485822 | |||
MonoBehaviour: | |||
m_ObjectHideFlags: 1 | |||
m_PrefabParentObject: {fileID: 0} | |||
m_PrefabInternal: {fileID: 100100000} | |||
m_GameObject: {fileID: 168468} | |||
m_Enabled: 1 | |||
m_EditorHideFlags: 0 | |||
m_Script: {fileID: 11500000, guid: b93b6a877adcbf94c89a9d6e0c0e844d, type: 3} | |||
m_Name: | |||
m_EditorClassIdentifier: | |||
--- !u!1001 &100100000 | |||
Prefab: | |||
m_ObjectHideFlags: 1 | |||
serializedVersion: 2 | |||
m_Modification: | |||
m_TransformParent: {fileID: 0} | |||
m_Modifications: | |||
- target: {fileID: 0} | |||
propertyPath: itemPackage | |||
value: | |||
objectReference: {fileID: 11472598, guid: 0fe7b7f42b84b844e9eab51a98276389, | |||
type: 2} | |||
- target: {fileID: 0} | |||
propertyPath: modelOverride | |||
value: | |||
objectReference: {fileID: 0} | |||
- target: {fileID: 0} | |||
propertyPath: controllerMaterial | |||
value: | |||
objectReference: {fileID: 2100000, guid: 3c433e134e4719444b65bf064a77e22e, type: 2} | |||
- target: {fileID: 0} | |||
propertyPath: m_Enabled | |||
value: 1 | |||
objectReference: {fileID: 0} | |||
m_RemovedComponents: [] | |||
m_ParentPrefab: {fileID: 0} | |||
m_RootGameObject: {fileID: 168468} | |||
m_IsPrefabParent: 1 |
@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: 3f39fc63a93686e4a8e9168ee73f24d9 | |||
timeCreated: 1439253462 | |||
licenseType: Store | |||
NativeFormatImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,8 @@ | |||
fileFormatVersion: 2 | |||
guid: dc06161b6d97feb419f45f03b62e14b9 | |||
timeCreated: 1430240738 | |||
licenseType: Store | |||
NativeFormatImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 77a23888f82e2ab4c8bc825f20235e1e | |||
folderAsset: yes | |||
timeCreated: 1479762244 | |||
licenseType: Store | |||
DefaultImporter: | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,35 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: Collider dangling from the player's head | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
using System.Collections; | |||
namespace Valve.VR.InteractionSystem | |||
{ | |||
//------------------------------------------------------------------------- | |||
[RequireComponent( typeof( CapsuleCollider ) )] | |||
public class BodyCollider : MonoBehaviour | |||
{ | |||
public Transform head; | |||
private CapsuleCollider capsuleCollider; | |||
//------------------------------------------------- | |||
void Awake() | |||
{ | |||
capsuleCollider = GetComponent<CapsuleCollider>(); | |||
} | |||
//------------------------------------------------- | |||
void FixedUpdate() | |||
{ | |||
float distanceFromFloor = Vector3.Dot( head.localPosition, Vector3.up ); | |||
capsuleCollider.height = Mathf.Max( capsuleCollider.radius, distanceFromFloor ); | |||
transform.localPosition = head.localPosition - 0.5f * distanceFromFloor * Vector3.up; | |||
} | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 1731d642c0b250b48bb8cdfb153d9792 | |||
timeCreated: 1434649753 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {fileID: 2800000, guid: b93fe5c516cf6ed4b9153ec790f856e2, type: 3} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,529 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: Interactable that can be used to move in a circular motion | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
using UnityEngine.Events; | |||
using System.Collections; | |||
namespace Valve.VR.InteractionSystem | |||
{ | |||
//------------------------------------------------------------------------- | |||
[RequireComponent( typeof( Interactable ) )] | |||
public class CircularDrive : MonoBehaviour | |||
{ | |||
public enum Axis_t | |||
{ | |||
XAxis, | |||
YAxis, | |||
ZAxis | |||
}; | |||
[Tooltip( "The axis around which the circular drive will rotate in local space" )] | |||
public Axis_t axisOfRotation = Axis_t.XAxis; | |||
[Tooltip( "Child GameObject which has the Collider component to initiate interaction, only needs to be set if there is more than one Collider child" )] | |||
public Collider childCollider = null; | |||
[Tooltip( "A LinearMapping component to drive, if not specified one will be dynamically added to this GameObject" )] | |||
public LinearMapping linearMapping; | |||
[Tooltip( "If true, the drive will stay manipulating as long as the button is held down, if false, it will stop if the controller moves out of the collider" )] | |||
public bool hoverLock = false; | |||
[HeaderAttribute( "Limited Rotation" )] | |||
[Tooltip( "If true, the rotation will be limited to [minAngle, maxAngle], if false, the rotation is unlimited" )] | |||
public bool limited = false; | |||
public Vector2 frozenDistanceMinMaxThreshold = new Vector2( 0.1f, 0.2f ); | |||
public UnityEvent onFrozenDistanceThreshold; | |||
[HeaderAttribute( "Limited Rotation Min" )] | |||
[Tooltip( "If limited is true, the specifies the lower limit, otherwise value is unused" )] | |||
public float minAngle = -45.0f; | |||
[Tooltip( "If limited, set whether drive will freeze its angle when the min angle is reached" )] | |||
public bool freezeOnMin = false; | |||
[Tooltip( "If limited, event invoked when minAngle is reached" )] | |||
public UnityEvent onMinAngle; | |||
[HeaderAttribute( "Limited Rotation Max" )] | |||
[Tooltip( "If limited is true, the specifies the upper limit, otherwise value is unused" )] | |||
public float maxAngle = 45.0f; | |||
[Tooltip( "If limited, set whether drive will freeze its angle when the max angle is reached" )] | |||
public bool freezeOnMax = false; | |||
[Tooltip( "If limited, event invoked when maxAngle is reached" )] | |||
public UnityEvent onMaxAngle; | |||
[Tooltip( "If limited is true, this forces the starting angle to be startAngle, clamped to [minAngle, maxAngle]" )] | |||
public bool forceStart = false; | |||
[Tooltip( "If limited is true and forceStart is true, the starting angle will be this, clamped to [minAngle, maxAngle]" )] | |||
public float startAngle = 0.0f; | |||
[Tooltip( "If true, the transform of the GameObject this component is on will be rotated accordingly" )] | |||
public bool rotateGameObject = true; | |||
[Tooltip( "If true, the path of the Hand (red) and the projected value (green) will be drawn" )] | |||
public bool debugPath = false; | |||
[Tooltip( "If debugPath is true, this is the maximum number of GameObjects to create to draw the path" )] | |||
public int dbgPathLimit = 50; | |||
[Tooltip( "If not null, the TextMesh will display the linear value and the angular value of this circular drive" )] | |||
public TextMesh debugText = null; | |||
[Tooltip( "The output angle value of the drive in degrees, unlimited will increase or decrease without bound, take the 360 modulus to find number of rotations" )] | |||
public float outAngle; | |||
private Quaternion start; | |||
private Vector3 worldPlaneNormal = new Vector3( 1.0f, 0.0f, 0.0f ); | |||
private Vector3 localPlaneNormal = new Vector3( 1.0f, 0.0f, 0.0f ); | |||
private Vector3 lastHandProjected; | |||
private Color red = new Color( 1.0f, 0.0f, 0.0f ); | |||
private Color green = new Color( 0.0f, 1.0f, 0.0f ); | |||
private GameObject[] dbgHandObjects; | |||
private GameObject[] dbgProjObjects; | |||
private GameObject dbgObjectsParent; | |||
private int dbgObjectCount = 0; | |||
private int dbgObjectIndex = 0; | |||
private bool driving = false; | |||
// If the drive is limited as is at min/max, angles greater than this are ignored | |||
private float minMaxAngularThreshold = 1.0f; | |||
private bool frozen = false; | |||
private float frozenAngle = 0.0f; | |||
private Vector3 frozenHandWorldPos = new Vector3( 0.0f, 0.0f, 0.0f ); | |||
private Vector2 frozenSqDistanceMinMaxThreshold = new Vector2( 0.0f, 0.0f ); | |||
Hand handHoverLocked = null; | |||
//------------------------------------------------- | |||
private void Freeze( Hand hand ) | |||
{ | |||
frozen = true; | |||
frozenAngle = outAngle; | |||
frozenHandWorldPos = hand.hoverSphereTransform.position; | |||
frozenSqDistanceMinMaxThreshold.x = frozenDistanceMinMaxThreshold.x * frozenDistanceMinMaxThreshold.x; | |||
frozenSqDistanceMinMaxThreshold.y = frozenDistanceMinMaxThreshold.y * frozenDistanceMinMaxThreshold.y; | |||
} | |||
//------------------------------------------------- | |||
private void UnFreeze() | |||
{ | |||
frozen = false; | |||
frozenHandWorldPos.Set( 0.0f, 0.0f, 0.0f ); | |||
} | |||
//------------------------------------------------- | |||
void Start() | |||
{ | |||
if ( childCollider == null ) | |||
{ | |||
childCollider = GetComponentInChildren<Collider>(); | |||
} | |||
if ( linearMapping == null ) | |||
{ | |||
linearMapping = GetComponent<LinearMapping>(); | |||
} | |||
if ( linearMapping == null ) | |||
{ | |||
linearMapping = gameObject.AddComponent<LinearMapping>(); | |||
} | |||
worldPlaneNormal = new Vector3( 0.0f, 0.0f, 0.0f ); | |||
worldPlaneNormal[(int)axisOfRotation] = 1.0f; | |||
localPlaneNormal = worldPlaneNormal; | |||
if ( transform.parent ) | |||
{ | |||
worldPlaneNormal = transform.parent.localToWorldMatrix.MultiplyVector( worldPlaneNormal ).normalized; | |||
} | |||
if ( limited ) | |||
{ | |||
start = Quaternion.identity; | |||
outAngle = transform.localEulerAngles[(int)axisOfRotation]; | |||
if ( forceStart ) | |||
{ | |||
outAngle = Mathf.Clamp( startAngle, minAngle, maxAngle ); | |||
} | |||
} | |||
else | |||
{ | |||
start = Quaternion.AngleAxis( transform.localEulerAngles[(int)axisOfRotation], localPlaneNormal ); | |||
outAngle = 0.0f; | |||
} | |||
if ( debugText ) | |||
{ | |||
debugText.alignment = TextAlignment.Left; | |||
debugText.anchor = TextAnchor.UpperLeft; | |||
} | |||
UpdateAll(); | |||
} | |||
//------------------------------------------------- | |||
void OnDisable() | |||
{ | |||
if ( handHoverLocked ) | |||
{ | |||
ControllerButtonHints.HideButtonHint( handHoverLocked, Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger ); | |||
handHoverLocked.HoverUnlock( GetComponent<Interactable>() ); | |||
handHoverLocked = null; | |||
} | |||
} | |||
//------------------------------------------------- | |||
private IEnumerator HapticPulses( SteamVR_Controller.Device controller, float flMagnitude, int nCount ) | |||
{ | |||
if ( controller != null ) | |||
{ | |||
int nRangeMax = (int)Util.RemapNumberClamped( flMagnitude, 0.0f, 1.0f, 100.0f, 900.0f ); | |||
nCount = Mathf.Clamp( nCount, 1, 10 ); | |||
for ( ushort i = 0; i < nCount; ++i ) | |||
{ | |||
ushort duration = (ushort)Random.Range( 100, nRangeMax ); | |||
controller.TriggerHapticPulse( duration ); | |||
yield return new WaitForSeconds( .01f ); | |||
} | |||
} | |||
} | |||
//------------------------------------------------- | |||
private void OnHandHoverBegin( Hand hand ) | |||
{ | |||
ControllerButtonHints.ShowButtonHint( hand, Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger ); | |||
} | |||
//------------------------------------------------- | |||
private void OnHandHoverEnd( Hand hand ) | |||
{ | |||
ControllerButtonHints.HideButtonHint( hand, Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger ); | |||
if ( driving && hand.GetStandardInteractionButton() ) | |||
{ | |||
StartCoroutine( HapticPulses( hand.controller, 1.0f, 10 ) ); | |||
} | |||
driving = false; | |||
handHoverLocked = null; | |||
} | |||
//------------------------------------------------- | |||
private void HandHoverUpdate( Hand hand ) | |||
{ | |||
if ( hand.GetStandardInteractionButtonDown() ) | |||
{ | |||
// Trigger was just pressed | |||
lastHandProjected = ComputeToTransformProjected( hand.hoverSphereTransform ); | |||
if ( hoverLock ) | |||
{ | |||
hand.HoverLock( GetComponent<Interactable>() ); | |||
handHoverLocked = hand; | |||
} | |||
driving = true; | |||
ComputeAngle( hand ); | |||
UpdateAll(); | |||
ControllerButtonHints.HideButtonHint( hand, Valve.VR.EVRButtonId.k_EButton_SteamVR_Trigger ); | |||
} | |||
else if ( hand.GetStandardInteractionButtonUp() ) | |||
{ | |||
// Trigger was just released | |||
if ( hoverLock ) | |||
{ | |||
hand.HoverUnlock( GetComponent<Interactable>() ); | |||
handHoverLocked = null; | |||
} | |||
} | |||
else if ( driving && hand.GetStandardInteractionButton() && hand.hoveringInteractable == GetComponent<Interactable>() ) | |||
{ | |||
ComputeAngle( hand ); | |||
UpdateAll(); | |||
} | |||
} | |||
//------------------------------------------------- | |||
private Vector3 ComputeToTransformProjected( Transform xForm ) | |||
{ | |||
Vector3 toTransform = ( xForm.position - transform.position ).normalized; | |||
Vector3 toTransformProjected = new Vector3( 0.0f, 0.0f, 0.0f ); | |||
// Need a non-zero distance from the hand to the center of the CircularDrive | |||
if ( toTransform.sqrMagnitude > 0.0f ) | |||
{ | |||
toTransformProjected = Vector3.ProjectOnPlane( toTransform, worldPlaneNormal ).normalized; | |||
} | |||
else | |||
{ | |||
Debug.LogFormat( "The collider needs to be a minimum distance away from the CircularDrive GameObject {0}", gameObject.ToString() ); | |||
Debug.Assert( false, string.Format( "The collider needs to be a minimum distance away from the CircularDrive GameObject {0}", gameObject.ToString() ) ); | |||
} | |||
if ( debugPath && dbgPathLimit > 0 ) | |||
{ | |||
DrawDebugPath( xForm, toTransformProjected ); | |||
} | |||
return toTransformProjected; | |||
} | |||
//------------------------------------------------- | |||
private void DrawDebugPath( Transform xForm, Vector3 toTransformProjected ) | |||
{ | |||
if ( dbgObjectCount == 0 ) | |||
{ | |||
dbgObjectsParent = new GameObject( "Circular Drive Debug" ); | |||
dbgHandObjects = new GameObject[dbgPathLimit]; | |||
dbgProjObjects = new GameObject[dbgPathLimit]; | |||
dbgObjectCount = dbgPathLimit; | |||
dbgObjectIndex = 0; | |||
} | |||
//Actual path | |||
GameObject gSphere = null; | |||
if ( dbgHandObjects[dbgObjectIndex] ) | |||
{ | |||
gSphere = dbgHandObjects[dbgObjectIndex]; | |||
} | |||
else | |||
{ | |||
gSphere = GameObject.CreatePrimitive( PrimitiveType.Sphere ); | |||
gSphere.transform.SetParent( dbgObjectsParent.transform ); | |||
dbgHandObjects[dbgObjectIndex] = gSphere; | |||
} | |||
gSphere.name = string.Format( "actual_{0}", (int)( ( 1.0f - red.r ) * 10.0f ) ); | |||
gSphere.transform.position = xForm.position; | |||
gSphere.transform.rotation = Quaternion.Euler( 0.0f, 0.0f, 0.0f ); | |||
gSphere.transform.localScale = new Vector3( 0.004f, 0.004f, 0.004f ); | |||
gSphere.gameObject.GetComponent<Renderer>().material.color = red; | |||
if ( red.r > 0.1f ) | |||
{ | |||
red.r -= 0.1f; | |||
} | |||
else | |||
{ | |||
red.r = 1.0f; | |||
} | |||
//Projected path | |||
gSphere = null; | |||
if ( dbgProjObjects[dbgObjectIndex] ) | |||
{ | |||
gSphere = dbgProjObjects[dbgObjectIndex]; | |||
} | |||
else | |||
{ | |||
gSphere = GameObject.CreatePrimitive( PrimitiveType.Sphere ); | |||
gSphere.transform.SetParent( dbgObjectsParent.transform ); | |||
dbgProjObjects[dbgObjectIndex] = gSphere; | |||
} | |||
gSphere.name = string.Format( "projed_{0}", (int)( ( 1.0f - green.g ) * 10.0f ) ); | |||
gSphere.transform.position = transform.position + toTransformProjected * 0.25f; | |||
gSphere.transform.rotation = Quaternion.Euler( 0.0f, 0.0f, 0.0f ); | |||
gSphere.transform.localScale = new Vector3( 0.004f, 0.004f, 0.004f ); | |||
gSphere.gameObject.GetComponent<Renderer>().material.color = green; | |||
if ( green.g > 0.1f ) | |||
{ | |||
green.g -= 0.1f; | |||
} | |||
else | |||
{ | |||
green.g = 1.0f; | |||
} | |||
dbgObjectIndex = ( dbgObjectIndex + 1 ) % dbgObjectCount; | |||
} | |||
//------------------------------------------------- | |||
// Updates the LinearMapping value from the angle | |||
//------------------------------------------------- | |||
private void UpdateLinearMapping() | |||
{ | |||
if ( limited ) | |||
{ | |||
// Map it to a [0, 1] value | |||
linearMapping.value = ( outAngle - minAngle ) / ( maxAngle - minAngle ); | |||
} | |||
else | |||
{ | |||
// Normalize to [0, 1] based on 360 degree windings | |||
float flTmp = outAngle / 360.0f; | |||
linearMapping.value = flTmp - Mathf.Floor( flTmp ); | |||
} | |||
UpdateDebugText(); | |||
} | |||
//------------------------------------------------- | |||
// Updates the LinearMapping value from the angle | |||
//------------------------------------------------- | |||
private void UpdateGameObject() | |||
{ | |||
if ( rotateGameObject ) | |||
{ | |||
transform.localRotation = start * Quaternion.AngleAxis( outAngle, localPlaneNormal ); | |||
} | |||
} | |||
//------------------------------------------------- | |||
// Updates the Debug TextMesh with the linear mapping value and the angle | |||
//------------------------------------------------- | |||
private void UpdateDebugText() | |||
{ | |||
if ( debugText ) | |||
{ | |||
debugText.text = string.Format( "Linear: {0}\nAngle: {1}\n", linearMapping.value, outAngle ); | |||
} | |||
} | |||
//------------------------------------------------- | |||
// Updates the Debug TextMesh with the linear mapping value and the angle | |||
//------------------------------------------------- | |||
private void UpdateAll() | |||
{ | |||
UpdateLinearMapping(); | |||
UpdateGameObject(); | |||
UpdateDebugText(); | |||
} | |||
//------------------------------------------------- | |||
// Computes the angle to rotate the game object based on the change in the transform | |||
//------------------------------------------------- | |||
private void ComputeAngle( Hand hand ) | |||
{ | |||
Vector3 toHandProjected = ComputeToTransformProjected( hand.hoverSphereTransform ); | |||
if ( !toHandProjected.Equals( lastHandProjected ) ) | |||
{ | |||
float absAngleDelta = Vector3.Angle( lastHandProjected, toHandProjected ); | |||
if ( absAngleDelta > 0.0f ) | |||
{ | |||
if ( frozen ) | |||
{ | |||
float frozenSqDist = ( hand.hoverSphereTransform.position - frozenHandWorldPos ).sqrMagnitude; | |||
if ( frozenSqDist > frozenSqDistanceMinMaxThreshold.x ) | |||
{ | |||
outAngle = frozenAngle + Random.Range( -1.0f, 1.0f ); | |||
float magnitude = Util.RemapNumberClamped( frozenSqDist, frozenSqDistanceMinMaxThreshold.x, frozenSqDistanceMinMaxThreshold.y, 0.0f, 1.0f ); | |||
if ( magnitude > 0 ) | |||
{ | |||
StartCoroutine( HapticPulses( hand.controller, magnitude, 10 ) ); | |||
} | |||
else | |||
{ | |||
StartCoroutine( HapticPulses( hand.controller, 0.5f, 10 ) ); | |||
} | |||
if ( frozenSqDist >= frozenSqDistanceMinMaxThreshold.y ) | |||
{ | |||
onFrozenDistanceThreshold.Invoke(); | |||
} | |||
} | |||
} | |||
else | |||
{ | |||
Vector3 cross = Vector3.Cross( lastHandProjected, toHandProjected ).normalized; | |||
float dot = Vector3.Dot( worldPlaneNormal, cross ); | |||
float signedAngleDelta = absAngleDelta; | |||
if ( dot < 0.0f ) | |||
{ | |||
signedAngleDelta = -signedAngleDelta; | |||
} | |||
if ( limited ) | |||
{ | |||
float angleTmp = Mathf.Clamp( outAngle + signedAngleDelta, minAngle, maxAngle ); | |||
if ( outAngle == minAngle ) | |||
{ | |||
if ( angleTmp > minAngle && absAngleDelta < minMaxAngularThreshold ) | |||
{ | |||
outAngle = angleTmp; | |||
lastHandProjected = toHandProjected; | |||
} | |||
} | |||
else if ( outAngle == maxAngle ) | |||
{ | |||
if ( angleTmp < maxAngle && absAngleDelta < minMaxAngularThreshold ) | |||
{ | |||
outAngle = angleTmp; | |||
lastHandProjected = toHandProjected; | |||
} | |||
} | |||
else if ( angleTmp == minAngle ) | |||
{ | |||
outAngle = angleTmp; | |||
lastHandProjected = toHandProjected; | |||
onMinAngle.Invoke(); | |||
if ( freezeOnMin ) | |||
{ | |||
Freeze( hand ); | |||
} | |||
} | |||
else if ( angleTmp == maxAngle ) | |||
{ | |||
outAngle = angleTmp; | |||
lastHandProjected = toHandProjected; | |||
onMaxAngle.Invoke(); | |||
if ( freezeOnMax ) | |||
{ | |||
Freeze( hand ); | |||
} | |||
} | |||
else | |||
{ | |||
outAngle = angleTmp; | |||
lastHandProjected = toHandProjected; | |||
} | |||
} | |||
else | |||
{ | |||
outAngle += signedAngleDelta; | |||
lastHandProjected = toHandProjected; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 1f32883eed859804dbb0c5fedac91496 | |||
timeCreated: 1440531244 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {fileID: 2800000, guid: b93fe5c516cf6ed4b9153ec790f856e2, type: 3} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,190 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: Throwable that uses physics joints to attach instead of just | |||
// parenting | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
using System.Collections.Generic; | |||
namespace Valve.VR.InteractionSystem | |||
{ | |||
//------------------------------------------------------------------------- | |||
[RequireComponent( typeof( Interactable ) )] | |||
public class ComplexThrowable : MonoBehaviour | |||
{ | |||
public enum AttachMode | |||
{ | |||
FixedJoint, | |||
Force, | |||
} | |||
public float attachForce = 800.0f; | |||
public float attachForceDamper = 25.0f; | |||
public AttachMode attachMode = AttachMode.FixedJoint; | |||
[EnumFlags] | |||
public Hand.AttachmentFlags attachmentFlags = 0; | |||
private List<Hand> holdingHands = new List<Hand>(); | |||
private List<Rigidbody> holdingBodies = new List<Rigidbody>(); | |||
private List<Vector3> holdingPoints = new List<Vector3>(); | |||
private List<Rigidbody> rigidBodies = new List<Rigidbody>(); | |||
//------------------------------------------------- | |||
void Awake() | |||
{ | |||
GetComponentsInChildren<Rigidbody>( rigidBodies ); | |||
} | |||
//------------------------------------------------- | |||
void Update() | |||
{ | |||
for ( int i = 0; i < holdingHands.Count; i++ ) | |||
{ | |||
if ( !holdingHands[i].GetStandardInteractionButton() ) | |||
{ | |||
PhysicsDetach( holdingHands[i] ); | |||
} | |||
} | |||
} | |||
//------------------------------------------------- | |||
private void OnHandHoverBegin( Hand hand ) | |||
{ | |||
if ( holdingHands.IndexOf( hand ) == -1 ) | |||
{ | |||
if ( hand.controller != null ) | |||
{ | |||
hand.controller.TriggerHapticPulse( 800 ); | |||
} | |||
} | |||
} | |||
//------------------------------------------------- | |||
private void OnHandHoverEnd( Hand hand ) | |||
{ | |||
if ( holdingHands.IndexOf( hand ) == -1 ) | |||
{ | |||
if ( hand.controller != null ) | |||
{ | |||
hand.controller.TriggerHapticPulse( 500 ); | |||
} | |||
} | |||
} | |||
//------------------------------------------------- | |||
private void HandHoverUpdate( Hand hand ) | |||
{ | |||
if ( hand.GetStandardInteractionButtonDown() ) | |||
{ | |||
PhysicsAttach( hand ); | |||
} | |||
} | |||
//------------------------------------------------- | |||
private void PhysicsAttach( Hand hand ) | |||
{ | |||
PhysicsDetach( hand ); | |||
Rigidbody holdingBody = null; | |||
Vector3 holdingPoint = Vector3.zero; | |||
// The hand should grab onto the nearest rigid body | |||
float closestDistance = float.MaxValue; | |||
for ( int i = 0; i < rigidBodies.Count; i++ ) | |||
{ | |||
float distance = Vector3.Distance( rigidBodies[i].worldCenterOfMass, hand.transform.position ); | |||
if ( distance < closestDistance ) | |||
{ | |||
holdingBody = rigidBodies[i]; | |||
closestDistance = distance; | |||
} | |||
} | |||
// Couldn't grab onto a body | |||
if ( holdingBody == null ) | |||
return; | |||
// Create a fixed joint from the hand to the holding body | |||
if ( attachMode == AttachMode.FixedJoint ) | |||
{ | |||
Rigidbody handRigidbody = Util.FindOrAddComponent<Rigidbody>( hand.gameObject ); | |||
handRigidbody.isKinematic = true; | |||
FixedJoint handJoint = hand.gameObject.AddComponent<FixedJoint>(); | |||
handJoint.connectedBody = holdingBody; | |||
} | |||
// Don't let the hand interact with other things while it's holding us | |||
hand.HoverLock( null ); | |||
// Affix this point | |||
Vector3 offset = hand.transform.position - holdingBody.worldCenterOfMass; | |||
offset = Mathf.Min( offset.magnitude, 1.0f ) * offset.normalized; | |||
holdingPoint = holdingBody.transform.InverseTransformPoint( holdingBody.worldCenterOfMass + offset ); | |||
hand.AttachObject( this.gameObject, attachmentFlags ); | |||
// Update holding list | |||
holdingHands.Add( hand ); | |||
holdingBodies.Add( holdingBody ); | |||
holdingPoints.Add( holdingPoint ); | |||
} | |||
//------------------------------------------------- | |||
private bool PhysicsDetach( Hand hand ) | |||
{ | |||
int i = holdingHands.IndexOf( hand ); | |||
if ( i != -1 ) | |||
{ | |||
// Detach this object from the hand | |||
holdingHands[i].DetachObject( this.gameObject, false ); | |||
// Allow the hand to do other things | |||
holdingHands[i].HoverUnlock( null ); | |||
// Delete any existing joints from the hand | |||
if ( attachMode == AttachMode.FixedJoint ) | |||
{ | |||
Destroy( holdingHands[i].GetComponent<FixedJoint>() ); | |||
} | |||
Util.FastRemove( holdingHands, i ); | |||
Util.FastRemove( holdingBodies, i ); | |||
Util.FastRemove( holdingPoints, i ); | |||
return true; | |||
} | |||
return false; | |||
} | |||
//------------------------------------------------- | |||
void FixedUpdate() | |||
{ | |||
if ( attachMode == AttachMode.Force ) | |||
{ | |||
for ( int i = 0; i < holdingHands.Count; i++ ) | |||
{ | |||
Vector3 targetPoint = holdingBodies[i].transform.TransformPoint( holdingPoints[i] ); | |||
Vector3 vdisplacement = holdingHands[i].transform.position - targetPoint; | |||
holdingBodies[i].AddForceAtPosition( attachForce * vdisplacement, targetPoint, ForceMode.Acceleration ); | |||
holdingBodies[i].AddForceAtPosition( -attachForceDamper * holdingBodies[i].GetPointVelocity( targetPoint ), targetPoint, ForceMode.Acceleration ); | |||
} | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: ad77666522338cf49ba83b80b25e6476 | |||
timeCreated: 1440023090 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {fileID: 2800000, guid: b93fe5c516cf6ed4b9153ec790f856e2, type: 3} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,197 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: Highlights the controller when hovering over interactables | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
using System.Collections; | |||
namespace Valve.VR.InteractionSystem | |||
{ | |||
//------------------------------------------------------------------------- | |||
public class ControllerHoverHighlight : MonoBehaviour | |||
{ | |||
public Material highLightMaterial; | |||
public bool fireHapticsOnHightlight = true; | |||
private Hand hand; | |||
private MeshRenderer bodyMeshRenderer; | |||
private MeshRenderer trackingHatMeshRenderer; | |||
private SteamVR_RenderModel renderModel; | |||
private bool renderModelLoaded = false; | |||
SteamVR_Events.Action renderModelLoadedAction; | |||
//------------------------------------------------- | |||
void Start() | |||
{ | |||
hand = GetComponentInParent<Hand>(); | |||
} | |||
//------------------------------------------------- | |||
void Awake() | |||
{ | |||
renderModelLoadedAction = SteamVR_Events.RenderModelLoadedAction( OnRenderModelLoaded ); | |||
} | |||
//------------------------------------------------- | |||
void OnEnable() | |||
{ | |||
renderModelLoadedAction.enabled = true; | |||
} | |||
//------------------------------------------------- | |||
void OnDisable() | |||
{ | |||
renderModelLoadedAction.enabled = false; | |||
} | |||
//------------------------------------------------- | |||
private void OnHandInitialized( int deviceIndex ) | |||
{ | |||
renderModel = gameObject.AddComponent<SteamVR_RenderModel>(); | |||
renderModel.SetDeviceIndex( deviceIndex ); | |||
renderModel.updateDynamically = false; | |||
} | |||
//------------------------------------------------- | |||
private void OnRenderModelLoaded( SteamVR_RenderModel renderModel, bool success ) | |||
{ | |||
if ( renderModel != this.renderModel ) | |||
{ | |||
return; | |||
} | |||
Transform bodyTransform = transform.Find( "body" ); | |||
if ( bodyTransform != null ) | |||
{ | |||
bodyTransform.gameObject.layer = gameObject.layer; | |||
bodyTransform.gameObject.tag = gameObject.tag; | |||
bodyMeshRenderer = bodyTransform.GetComponent<MeshRenderer>(); | |||
bodyMeshRenderer.material = highLightMaterial; | |||
bodyMeshRenderer.enabled = false; | |||
} | |||
Transform trackingHatTransform = transform.Find( "trackhat" ); | |||
if ( trackingHatTransform != null ) | |||
{ | |||
trackingHatTransform.gameObject.layer = gameObject.layer; | |||
trackingHatTransform.gameObject.tag = gameObject.tag; | |||
trackingHatMeshRenderer = trackingHatTransform.GetComponent<MeshRenderer>(); | |||
trackingHatMeshRenderer.material = highLightMaterial; | |||
trackingHatMeshRenderer.enabled = false; | |||
} | |||
foreach ( Transform child in transform ) | |||
{ | |||
if ( ( child.name != "body" ) && ( child.name != "trackhat" ) ) | |||
{ | |||
Destroy( child.gameObject ); | |||
} | |||
} | |||
renderModelLoaded = true; | |||
} | |||
//------------------------------------------------- | |||
private void OnParentHandHoverBegin( Interactable other ) | |||
{ | |||
if ( !this.isActiveAndEnabled ) | |||
{ | |||
return; | |||
} | |||
if ( other.transform.parent != transform.parent ) | |||
{ | |||
ShowHighlight(); | |||
} | |||
} | |||
//------------------------------------------------- | |||
private void OnParentHandHoverEnd( Interactable other ) | |||
{ | |||
HideHighlight(); | |||
} | |||
//------------------------------------------------- | |||
private void OnParentHandInputFocusAcquired() | |||
{ | |||
if ( !this.isActiveAndEnabled ) | |||
{ | |||
return; | |||
} | |||
if ( hand.hoveringInteractable && hand.hoveringInteractable.transform.parent != transform.parent ) | |||
{ | |||
ShowHighlight(); | |||
} | |||
} | |||
//------------------------------------------------- | |||
private void OnParentHandInputFocusLost() | |||
{ | |||
HideHighlight(); | |||
} | |||
//------------------------------------------------- | |||
public void ShowHighlight() | |||
{ | |||
if ( renderModelLoaded == false ) | |||
{ | |||
return; | |||
} | |||
if ( fireHapticsOnHightlight ) | |||
{ | |||
hand.controller.TriggerHapticPulse( 500 ); | |||
} | |||
if ( bodyMeshRenderer != null ) | |||
{ | |||
bodyMeshRenderer.enabled = true; | |||
} | |||
if ( trackingHatMeshRenderer != null ) | |||
{ | |||
trackingHatMeshRenderer.enabled = true; | |||
} | |||
} | |||
//------------------------------------------------- | |||
public void HideHighlight() | |||
{ | |||
if ( renderModelLoaded == false ) | |||
{ | |||
return; | |||
} | |||
if ( fireHapticsOnHightlight ) | |||
{ | |||
hand.controller.TriggerHapticPulse( 300 ); | |||
} | |||
if ( bodyMeshRenderer != null ) | |||
{ | |||
bodyMeshRenderer.enabled = false; | |||
} | |||
if ( trackingHatMeshRenderer != null ) | |||
{ | |||
trackingHatMeshRenderer.enabled = false; | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 8ca2cc563cc33f542a5d9f8f661184ba | |||
timeCreated: 1441139979 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {fileID: 2800000, guid: b93fe5c516cf6ed4b9153ec790f856e2, type: 3} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,28 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: Custom Unity Events that take in additional parameters | |||
// | |||
//============================================================================= | |||
using UnityEngine.Events; | |||
using System; | |||
namespace Valve.VR.InteractionSystem | |||
{ | |||
//------------------------------------------------------------------------- | |||
public static class CustomEvents | |||
{ | |||
//------------------------------------------------- | |||
[System.Serializable] | |||
public class UnityEventSingleFloat : UnityEvent<float> | |||
{ | |||
} | |||
//------------------------------------------------- | |||
[System.Serializable] | |||
public class UnityEventHand : UnityEvent<Hand> | |||
{ | |||
} | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 5f3294e06115d0047a2ac7659a11b168 | |||
timeCreated: 1437076614 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {fileID: 2800000, guid: b93fe5c516cf6ed4b9153ec790f856e2, type: 3} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,48 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: Debug UI shown for the player | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
using UnityEngine.UI; | |||
using System.Collections; | |||
namespace Valve.VR.InteractionSystem | |||
{ | |||
//------------------------------------------------------------------------- | |||
public class DebugUI : MonoBehaviour | |||
{ | |||
private Player player; | |||
//------------------------------------------------- | |||
static private DebugUI _instance; | |||
static public DebugUI instance | |||
{ | |||
get | |||
{ | |||
if ( _instance == null ) | |||
{ | |||
_instance = GameObject.FindObjectOfType<DebugUI>(); | |||
} | |||
return _instance; | |||
} | |||
} | |||
//------------------------------------------------- | |||
void Start() | |||
{ | |||
player = Player.instance; | |||
} | |||
//------------------------------------------------- | |||
private void OnGUI() | |||
{ | |||
#if !HIDE_DEBUG_UI | |||
player.Draw2DDebug(); | |||
#endif | |||
} | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 6f3bba2c36dd79242b3157dbcd876bf2 | |||
timeCreated: 1458703500 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {fileID: 2800000, guid: b93fe5c516cf6ed4b9153ec790f856e2, type: 3} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,22 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: Destroys this object when it is detached from the hand | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
using System.Collections; | |||
namespace Valve.VR.InteractionSystem | |||
{ | |||
//------------------------------------------------------------------------- | |||
[RequireComponent( typeof( Interactable ) )] | |||
public class DestroyOnDetachedFromHand : MonoBehaviour | |||
{ | |||
//------------------------------------------------- | |||
private void OnDetachedFromHand( Hand hand ) | |||
{ | |||
Destroy( gameObject ); | |||
} | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 5240357a2468cdc4291b266bee3cb9b9 | |||
timeCreated: 1442359285 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {fileID: 2800000, guid: b93fe5c516cf6ed4b9153ec790f856e2, type: 3} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,36 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: Destroys this object when its particle system dies | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
using System.Collections; | |||
namespace Valve.VR.InteractionSystem | |||
{ | |||
//------------------------------------------------------------------------- | |||
[RequireComponent( typeof( ParticleSystem ) )] | |||
public class DestroyOnParticleSystemDeath : MonoBehaviour | |||
{ | |||
private ParticleSystem particles; | |||
//------------------------------------------------- | |||
void Awake() | |||
{ | |||
particles = GetComponent<ParticleSystem>(); | |||
InvokeRepeating( "CheckParticleSystem", 0.1f, 0.1f ); | |||
} | |||
//------------------------------------------------- | |||
private void CheckParticleSystem() | |||
{ | |||
if ( !particles.IsAlive() ) | |||
{ | |||
Destroy( this.gameObject ); | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 69cad530c565c714491a326c21accb90 | |||
timeCreated: 1478655595 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {fileID: 2800000, guid: b93fe5c516cf6ed4b9153ec790f856e2, type: 3} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,38 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: Destroys this object when it enters a trigger | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
using System.Collections; | |||
namespace Valve.VR.InteractionSystem | |||
{ | |||
//------------------------------------------------------------------------- | |||
public class DestroyOnTriggerEnter : MonoBehaviour | |||
{ | |||
public string tagFilter; | |||
private bool useTag; | |||
//------------------------------------------------- | |||
void Start() | |||
{ | |||
if ( !string.IsNullOrEmpty( tagFilter ) ) | |||
{ | |||
useTag = true; | |||
} | |||
} | |||
//------------------------------------------------- | |||
void OnTriggerEnter( Collider collider ) | |||
{ | |||
if ( !useTag || ( useTag && collider.gameObject.tag == tagFilter ) ) | |||
{ | |||
Destroy( collider.gameObject.transform.root.gameObject ); | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 7ba84888c9d4c504cb752a3904551a6c | |||
timeCreated: 1438101498 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {fileID: 2800000, guid: b93fe5c516cf6ed4b9153ec790f856e2, type: 3} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,42 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: Triggers haptic pulses based on distance between 2 positions | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
using System.Collections; | |||
namespace Valve.VR.InteractionSystem | |||
{ | |||
//------------------------------------------------------------------------- | |||
public class DistanceHaptics : MonoBehaviour | |||
{ | |||
public Transform firstTransform; | |||
public Transform secondTransform; | |||
public AnimationCurve distanceIntensityCurve = AnimationCurve.Linear( 0.0f, 800.0f, 1.0f, 800.0f ); | |||
public AnimationCurve pulseIntervalCurve = AnimationCurve.Linear( 0.0f, 0.01f, 1.0f, 0.0f ); | |||
//------------------------------------------------- | |||
IEnumerator Start() | |||
{ | |||
while ( true ) | |||
{ | |||
float distance = Vector3.Distance( firstTransform.position, secondTransform.position ); | |||
SteamVR_TrackedObject trackedObject = GetComponentInParent<SteamVR_TrackedObject>(); | |||
if ( trackedObject ) | |||
{ | |||
float pulse = distanceIntensityCurve.Evaluate( distance ); | |||
SteamVR_Controller.Input( (int)trackedObject.index ).TriggerHapticPulse( (ushort)pulse ); | |||
} | |||
float nextPulse = pulseIntervalCurve.Evaluate( distance ); | |||
yield return new WaitForSeconds( nextPulse ); | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 65ef702aaa09d3f46a75659678b1a711 | |||
timeCreated: 1430871385 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {fileID: 2800000, guid: b93fe5c516cf6ed4b9153ec790f856e2, type: 3} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,21 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: This object won't be destroyed when a new scene is loaded | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
using System.Collections; | |||
namespace Valve.VR.InteractionSystem | |||
{ | |||
//------------------------------------------------------------------------- | |||
public class DontDestroyOnLoad : MonoBehaviour | |||
{ | |||
//------------------------------------------------- | |||
void Awake() | |||
{ | |||
DontDestroyOnLoad( this ); | |||
} | |||
} | |||
} |
@ -0,0 +1,9 @@ | |||
fileFormatVersion: 2 | |||
guid: 4d1c07a6449b0ca439ee6fac5f6f7d83 | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {fileID: 2800000, guid: b93fe5c516cf6ed4b9153ec790f856e2, type: 3} | |||
userData: | |||
assetBundleName: |
@ -0,0 +1,32 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: Allows Enums to be shown in the inspector as flags | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
#if UNITY_EDITOR | |||
using UnityEditor; | |||
#endif | |||
namespace Valve.VR.InteractionSystem | |||
{ | |||
//------------------------------------------------------------------------- | |||
public class EnumFlags : PropertyAttribute | |||
{ | |||
public EnumFlags() { } | |||
} | |||
#if UNITY_EDITOR | |||
//------------------------------------------------------------------------- | |||
[CustomPropertyDrawer( typeof( EnumFlags ) )] | |||
public class EnumFlagsPropertyDrawer : PropertyDrawer | |||
{ | |||
public override void OnGUI( Rect position, SerializedProperty property, GUIContent label ) | |||
{ | |||
property.intValue = EditorGUI.MaskField( position, label, property.intValue, property.enumNames ); | |||
} | |||
} | |||
#endif | |||
} |
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 88a2ccbdad9948c45b28f5e63902705b | |||
timeCreated: 1440536338 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {fileID: 2800000, guid: b93fe5c516cf6ed4b9153ec790f856e2, type: 3} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,96 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: Controls for the non-VR debug camera | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
using System.Collections; | |||
namespace Valve.VR.InteractionSystem | |||
{ | |||
//------------------------------------------------------------------------- | |||
[RequireComponent( typeof( Camera ) )] | |||
public class FallbackCameraController : MonoBehaviour | |||
{ | |||
public float speed = 4.0f; | |||
public float shiftSpeed = 16.0f; | |||
public bool showInstructions = true; | |||
private Vector3 startEulerAngles; | |||
private Vector3 startMousePosition; | |||
private float realTime; | |||
//------------------------------------------------- | |||
void OnEnable() | |||
{ | |||
realTime = Time.realtimeSinceStartup; | |||
} | |||
//------------------------------------------------- | |||
void Update() | |||
{ | |||
float forward = 0.0f; | |||
if ( Input.GetKey( KeyCode.W ) || Input.GetKey( KeyCode.UpArrow ) ) | |||
{ | |||
forward += 1.0f; | |||
} | |||
if ( Input.GetKey( KeyCode.S ) || Input.GetKey( KeyCode.DownArrow ) ) | |||
{ | |||
forward -= 1.0f; | |||
} | |||
float right = 0.0f; | |||
if ( Input.GetKey( KeyCode.D ) || Input.GetKey( KeyCode.RightArrow ) ) | |||
{ | |||
right += 1.0f; | |||
} | |||
if ( Input.GetKey( KeyCode.A ) || Input.GetKey( KeyCode.LeftArrow ) ) | |||
{ | |||
right -= 1.0f; | |||
} | |||
float currentSpeed = speed; | |||
if ( Input.GetKey( KeyCode.LeftShift ) || Input.GetKey( KeyCode.RightShift ) ) | |||
{ | |||
currentSpeed = shiftSpeed; | |||
} | |||
float realTimeNow = Time.realtimeSinceStartup; | |||
float deltaRealTime = realTimeNow - realTime; | |||
realTime = realTimeNow; | |||
Vector3 delta = new Vector3( right, 0.0f, forward ) * currentSpeed * deltaRealTime; | |||
transform.position += transform.TransformDirection( delta ); | |||
Vector3 mousePosition = Input.mousePosition; | |||
if ( Input.GetMouseButtonDown( 1 ) /* right mouse */) | |||
{ | |||
startMousePosition = mousePosition; | |||
startEulerAngles = transform.localEulerAngles; | |||
} | |||
if ( Input.GetMouseButton( 1 ) /* right mouse */) | |||
{ | |||
Vector3 offset = mousePosition - startMousePosition; | |||
transform.localEulerAngles = startEulerAngles + new Vector3( -offset.y * 360.0f / Screen.height, offset.x * 360.0f / Screen.width, 0.0f ); | |||
} | |||
} | |||
//------------------------------------------------- | |||
void OnGUI() | |||
{ | |||
if ( showInstructions ) | |||
{ | |||
GUI.Label( new Rect( 10.0f, 10.0f, 600.0f, 400.0f ), | |||
"WASD/Arrow Keys to translate the camera\n" + | |||
"Right mouse click to rotate the camera\n" + | |||
"Left mouse click for standard interactions.\n" ); | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 6043f3be9a21bd74281f9770463bea00 | |||
timeCreated: 1436190027 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {fileID: 2800000, guid: b93fe5c516cf6ed4b9153ec790f856e2, type: 3} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |
@ -0,0 +1,917 @@ | |||
//======= Copyright (c) Valve Corporation, All rights reserved. =============== | |||
// | |||
// Purpose: The hands used by the player in the vr interaction system | |||
// | |||
//============================================================================= | |||
using UnityEngine; | |||
using System; | |||
using System.Collections; | |||
using System.Collections.Generic; | |||
using System.Collections.ObjectModel; | |||
namespace Valve.VR.InteractionSystem | |||
{ | |||
//------------------------------------------------------------------------- | |||
// Links with an appropriate SteamVR controller and facilitates | |||
// interactions with objects in the virtual world. | |||
//------------------------------------------------------------------------- | |||
public class Hand : MonoBehaviour | |||
{ | |||
public enum HandType | |||
{ | |||
Left, | |||
Right, | |||
Any | |||
}; | |||
// The flags used to determine how an object is attached to the hand. | |||
[Flags] | |||
public enum AttachmentFlags | |||
{ | |||
SnapOnAttach = 1 << 0, // The object should snap to the position of the specified attachment point on the hand. | |||
DetachOthers = 1 << 1, // Other objects attached to this hand will be detached. | |||
DetachFromOtherHand = 1 << 2, // This object will be detached from the other hand. | |||
ParentToHand = 1 << 3, // The object will be parented to the hand. | |||
}; | |||
public const AttachmentFlags defaultAttachmentFlags = AttachmentFlags.ParentToHand | | |||
AttachmentFlags.DetachOthers | | |||
AttachmentFlags.DetachFromOtherHand | | |||
AttachmentFlags.SnapOnAttach; | |||
public Hand otherHand; | |||
public HandType startingHandType; | |||
public Transform hoverSphereTransform; | |||
public float hoverSphereRadius = 0.05f; | |||
public LayerMask hoverLayerMask = -1; | |||
public float hoverUpdateInterval = 0.1f; | |||
public Camera noSteamVRFallbackCamera; | |||
public float noSteamVRFallbackMaxDistanceNoItem = 10.0f; | |||
public float noSteamVRFallbackMaxDistanceWithItem = 0.5f; | |||
private float noSteamVRFallbackInteractorDistance = -1.0f; | |||
public SteamVR_Controller.Device controller; | |||
public GameObject controllerPrefab; | |||
private GameObject controllerObject = null; | |||
public bool showDebugText = false; | |||
public bool spewDebugText = false; | |||
public struct AttachedObject | |||
{ | |||
public GameObject attachedObject; | |||
public GameObject originalParent; | |||
public bool isParentedToHand; | |||
} | |||
private List<AttachedObject> attachedObjects = new List<AttachedObject>(); | |||
public ReadOnlyCollection<AttachedObject> AttachedObjects | |||
{ | |||
get { return attachedObjects.AsReadOnly(); } | |||
} | |||
public bool hoverLocked { get; private set; } | |||
private Interactable _hoveringInteractable; | |||
private TextMesh debugText; | |||
private int prevOverlappingColliders = 0; | |||
private const int ColliderArraySize = 16; | |||
private Collider[] overlappingColliders; | |||
private Player playerInstance; | |||
private GameObject applicationLostFocusObject; | |||
SteamVR_Events.Action inputFocusAction; | |||
//------------------------------------------------- | |||
// The Interactable object this Hand is currently hovering over | |||
//------------------------------------------------- | |||
public Interactable hoveringInteractable | |||
{ | |||
get { return _hoveringInteractable; } | |||
set | |||
{ | |||
if ( _hoveringInteractable != value ) | |||
{ | |||
if ( _hoveringInteractable != null ) | |||
{ | |||
HandDebugLog( "HoverEnd " + _hoveringInteractable.gameObject ); | |||
_hoveringInteractable.SendMessage( "OnHandHoverEnd", this, SendMessageOptions.DontRequireReceiver ); | |||
//Note: The _hoveringInteractable can change after sending the OnHandHoverEnd message so we need to check it again before broadcasting this message | |||
if ( _hoveringInteractable != null ) | |||
{ | |||
this.BroadcastMessage( "OnParentHandHoverEnd", _hoveringInteractable, SendMessageOptions.DontRequireReceiver ); // let objects attached to the hand know that a hover has ended | |||
} | |||
} | |||
_hoveringInteractable = value; | |||
if ( _hoveringInteractable != null ) | |||
{ | |||
HandDebugLog( "HoverBegin " + _hoveringInteractable.gameObject ); | |||
_hoveringInteractable.SendMessage( "OnHandHoverBegin", this, SendMessageOptions.DontRequireReceiver ); | |||
//Note: The _hoveringInteractable can change after sending the OnHandHoverBegin message so we need to check it again before broadcasting this message | |||
if ( _hoveringInteractable != null ) | |||
{ | |||
this.BroadcastMessage( "OnParentHandHoverBegin", _hoveringInteractable, SendMessageOptions.DontRequireReceiver ); // let objects attached to the hand know that a hover has begun | |||
} | |||
} | |||
} | |||
} | |||
} | |||
//------------------------------------------------- | |||
// Active GameObject attached to this Hand | |||
//------------------------------------------------- | |||
public GameObject currentAttachedObject | |||
{ | |||
get | |||
{ | |||
CleanUpAttachedObjectStack(); | |||
if ( attachedObjects.Count > 0 ) | |||
{ | |||
return attachedObjects[attachedObjects.Count - 1].attachedObject; | |||
} | |||
return null; | |||
} | |||
} | |||
//------------------------------------------------- | |||
public Transform GetAttachmentTransform( string attachmentPoint = "" ) | |||
{ | |||
Transform attachmentTransform = null; | |||
if ( !string.IsNullOrEmpty( attachmentPoint ) ) | |||
{ | |||
attachmentTransform = transform.Find( attachmentPoint ); | |||
} | |||
if ( !attachmentTransform ) | |||
{ | |||
attachmentTransform = this.transform; | |||
} | |||
return attachmentTransform; | |||
} | |||
//------------------------------------------------- | |||
// Guess the type of this Hand | |||
// | |||
// If startingHandType is Hand.Left or Hand.Right, returns startingHandType. | |||
// If otherHand is non-null and both Hands are linked to controllers, returns | |||
// Hand.Left if this Hand is leftmost relative to the HMD, otherwise Hand.Right. | |||
// Otherwise, returns Hand.Any | |||
//------------------------------------------------- | |||
public HandType GuessCurrentHandType() | |||
{ | |||
if ( startingHandType == HandType.Left || startingHandType == HandType.Right ) | |||
{ | |||
return startingHandType; | |||
} | |||
if ( startingHandType == HandType.Any && otherHand != null && otherHand.controller == null ) | |||
{ | |||
return HandType.Right; | |||
} | |||
if ( controller == null || otherHand == null || otherHand.controller == null ) | |||
{ | |||
return startingHandType; | |||
} | |||
if ( controller.index == SteamVR_Controller.GetDeviceIndex( SteamVR_Controller.DeviceRelation.Leftmost ) ) | |||
{ | |||
return HandType.Left; | |||
} | |||
return HandType.Right; | |||
} | |||
//------------------------------------------------- | |||
// Attach a GameObject to this GameObject | |||
// | |||
// objectToAttach - The GameObject to attach | |||
// flags - The flags to use for attaching the object | |||
// attachmentPoint - Name of the GameObject in the hierarchy of this Hand which should act as the attachment point for this GameObject | |||
//------------------------------------------------- | |||
public void AttachObject( GameObject objectToAttach, AttachmentFlags flags = defaultAttachmentFlags, string attachmentPoint = "" ) | |||
{ | |||
if ( flags == 0 ) | |||
{ | |||
flags = defaultAttachmentFlags; | |||
} | |||
//Make sure top object on stack is non-null | |||
CleanUpAttachedObjectStack(); | |||
//Detach the object if it is already attached so that it can get re-attached at the top of the stack | |||
DetachObject( objectToAttach ); | |||
//Detach from the other hand if requested | |||
if ( ( ( flags & AttachmentFlags.DetachFromOtherHand ) == AttachmentFlags.DetachFromOtherHand ) && otherHand ) | |||
{ | |||
otherHand.DetachObject( objectToAttach ); | |||
} | |||
if ( ( flags & AttachmentFlags.DetachOthers ) == AttachmentFlags.DetachOthers ) | |||
{ | |||
//Detach all the objects from the stack | |||
while ( attachedObjects.Count > 0 ) | |||
{ | |||
DetachObject( attachedObjects[0].attachedObject ); | |||
} | |||
} | |||
if ( currentAttachedObject ) | |||
{ | |||
currentAttachedObject.SendMessage( "OnHandFocusLost", this, SendMessageOptions.DontRequireReceiver ); | |||
} | |||
AttachedObject attachedObject = new AttachedObject(); | |||
attachedObject.attachedObject = objectToAttach; | |||
attachedObject.originalParent = objectToAttach.transform.parent != null ? objectToAttach.transform.parent.gameObject : null; | |||
if ( ( flags & AttachmentFlags.ParentToHand ) == AttachmentFlags.ParentToHand ) | |||
{ | |||
//Parent the object to the hand | |||
objectToAttach.transform.parent = GetAttachmentTransform( attachmentPoint ); | |||
attachedObject.isParentedToHand = true; | |||
} | |||
else | |||
{ | |||
attachedObject.isParentedToHand = false; | |||
} | |||
attachedObjects.Add( attachedObject ); | |||
if ( ( flags & AttachmentFlags.SnapOnAttach ) == AttachmentFlags.SnapOnAttach ) | |||
{ | |||
objectToAttach.transform.localPosition = Vector3.zero; | |||
objectToAttach.transform.localRotation = Quaternion.identity; | |||
} | |||
HandDebugLog( "AttachObject " + objectToAttach ); | |||
objectToAttach.SendMessage( "OnAttachedToHand", this, SendMessageOptions.DontRequireReceiver ); | |||
UpdateHovering(); | |||
} | |||
//------------------------------------------------- | |||
// Detach this GameObject from the attached object stack of this Hand | |||
// | |||
// objectToDetach - The GameObject to detach from this Hand | |||
//------------------------------------------------- | |||
public void DetachObject( GameObject objectToDetach, bool restoreOriginalParent = true ) | |||
{ | |||
int index = attachedObjects.FindIndex( l => l.attachedObject == objectToDetach ); | |||
if ( index != -1 ) | |||
{ | |||
HandDebugLog( "DetachObject " + objectToDetach ); | |||
GameObject prevTopObject = currentAttachedObject; | |||
Transform parentTransform = null; | |||
if ( attachedObjects[index].isParentedToHand ) | |||
{ | |||
if ( restoreOriginalParent && ( attachedObjects[index].originalParent != null ) ) | |||
{ | |||
parentTransform = attachedObjects[index].originalParent.transform; | |||
} | |||
attachedObjects[index].attachedObject.transform.parent = parentTransform; | |||
} | |||
attachedObjects[index].attachedObject.SetActive( true ); | |||
attachedObjects[index].attachedObject.SendMessage( "OnDetachedFromHand", this, SendMessageOptions.DontRequireReceiver ); | |||
attachedObjects.RemoveAt( index ); | |||
GameObject newTopObject = currentAttachedObject; | |||
//Give focus to the top most object on the stack if it changed | |||
if ( newTopObject != null && newTopObject != prevTopObject ) | |||
{ | |||
newTopObject.SetActive( true ); | |||
newTopObject.SendMessage( "OnHandFocusAcquired", this, SendMessageOptions.DontRequireReceiver ); | |||
} | |||
} | |||
CleanUpAttachedObjectStack(); | |||
} | |||
//------------------------------------------------- | |||
// Get the world velocity of the VR Hand. | |||
// Note: controller velocity value only updates on controller events (Button but and down) so good for throwing | |||
//------------------------------------------------- | |||
public Vector3 GetTrackedObjectVelocity() | |||
{ | |||
if ( controller != null ) | |||
{ | |||
return transform.parent.TransformVector( controller.velocity ); | |||
} | |||
return Vector3.zero; | |||
} | |||
//------------------------------------------------- | |||
// Get the world angular velocity of the VR Hand. | |||
// Note: controller velocity value only updates on controller events (Button but and down) so good for throwing | |||
//------------------------------------------------- | |||
public Vector3 GetTrackedObjectAngularVelocity() | |||
{ | |||
if ( controller != null ) | |||
{ | |||
return transform.parent.TransformVector( controller.angularVelocity ); | |||
} | |||
return Vector3.zero; | |||
} | |||
//------------------------------------------------- | |||
private void CleanUpAttachedObjectStack() | |||
{ | |||
attachedObjects.RemoveAll( l => l.attachedObject == null ); | |||
} | |||
//------------------------------------------------- | |||
void Awake() | |||
{ | |||
inputFocusAction = SteamVR_Events.InputFocusAction( OnInputFocus ); | |||
if ( hoverSphereTransform == null ) | |||
{ | |||
hoverSphereTransform = this.transform; | |||
} | |||
applicationLostFocusObject = new GameObject( "_application_lost_focus" ); | |||
applicationLostFocusObject.transform.parent = transform; | |||
applicationLostFocusObject.SetActive( false ); | |||
} | |||
//------------------------------------------------- | |||
IEnumerator Start() | |||
{ | |||
// save off player instance | |||
playerInstance = Player.instance; | |||
if ( !playerInstance ) | |||
{ | |||
Debug.LogError( "No player instance found in Hand Start()" ); | |||
} | |||
// allocate array for colliders | |||
overlappingColliders = new Collider[ColliderArraySize]; | |||
// We are a "no SteamVR fallback hand" if we have this camera set | |||
// we'll use the right mouse to look around and left mouse to interact | |||
// - don't need to find the device | |||
if ( noSteamVRFallbackCamera ) | |||
{ | |||
yield break; | |||
} | |||
//Debug.Log( "Hand - initializing connection routine" ); | |||
// Acquire the correct device index for the hand we want to be | |||
// Also for the other hand if we get there first | |||
while ( true ) | |||
{ | |||
// Don't need to run this every frame | |||
yield return new WaitForSeconds( 1.0f ); | |||
// We have a controller now, break out of the loop! | |||
if ( controller != null ) | |||
break; | |||
//Debug.Log( "Hand - checking controllers..." ); | |||
// Initialize both hands simultaneously | |||
if ( startingHandType == HandType.Left || startingHandType == HandType.Right ) | |||
{ | |||
// Left/right relationship. | |||
// Wait until we have a clear unique left-right relationship to initialize. | |||
int leftIndex = SteamVR_Controller.GetDeviceIndex( SteamVR_Controller.DeviceRelation.Leftmost ); | |||
int rightIndex = SteamVR_Controller.GetDeviceIndex( SteamVR_Controller.DeviceRelation.Rightmost ); | |||
if ( leftIndex == -1 || rightIndex == -1 || leftIndex == rightIndex ) | |||
{ | |||
//Debug.Log( string.Format( "...Left/right hand relationship not yet established: leftIndex={0}, rightIndex={1}", leftIndex, rightIndex ) ); | |||
continue; | |||
} | |||
int myIndex = ( startingHandType == HandType.Right ) ? rightIndex : leftIndex; | |||
int otherIndex = ( startingHandType == HandType.Right ) ? leftIndex : rightIndex; | |||
InitController( myIndex ); | |||
if ( otherHand ) | |||
{ | |||
otherHand.InitController( otherIndex ); | |||
} | |||
} | |||
else | |||
{ | |||
// No left/right relationship. Just wait for a connection | |||
var vr = SteamVR.instance; | |||
for ( int i = 0; i < Valve.VR.OpenVR.k_unMaxTrackedDeviceCount; i++ ) | |||
{ | |||
if ( vr.hmd.GetTrackedDeviceClass( (uint)i ) != Valve.VR.ETrackedDeviceClass.Controller ) | |||
{ | |||
//Debug.Log( string.Format( "Hand - device {0} is not a controller", i ) ); | |||
continue; | |||
} | |||
var device = SteamVR_Controller.Input( i ); | |||
if ( !device.valid ) | |||
{ | |||
//Debug.Log( string.Format( "Hand - device {0} is not valid", i ) ); | |||
continue; | |||
} | |||
if ( ( otherHand != null ) && ( otherHand.controller != null ) ) | |||
{ | |||
// Other hand is using this index, so we cannot use it. | |||
if ( i == (int)otherHand.controller.index ) | |||
{ | |||
//Debug.Log( string.Format( "Hand - device {0} is owned by the other hand", i ) ); | |||
continue; | |||
} | |||
} | |||
InitController( i ); | |||
} | |||
} | |||
} | |||
} | |||
//------------------------------------------------- | |||
private void UpdateHovering() | |||
{ | |||
if ( ( noSteamVRFallbackCamera == null ) && ( controller == null ) ) | |||
{ | |||
return; | |||
} | |||
if ( hoverLocked ) | |||
return; | |||
if ( applicationLostFocusObject.activeSelf ) | |||
return; | |||
float closestDistance = float.MaxValue; | |||
Interactable closestInteractable = null; | |||
// Pick the closest hovering | |||
float flHoverRadiusScale = playerInstance.transform.lossyScale.x; | |||
float flScaledSphereRadius = hoverSphereRadius * flHoverRadiusScale; | |||
// if we're close to the floor, increase the radius to make things easier to pick up | |||
float handDiff = Mathf.Abs( transform.position.y - playerInstance.trackingOriginTransform.position.y ); | |||
float boxMult = Util.RemapNumberClamped( handDiff, 0.0f, 0.5f * flHoverRadiusScale, 5.0f, 1.0f ) * flHoverRadiusScale; | |||
// null out old vals | |||
for ( int i = 0; i < overlappingColliders.Length; ++i ) | |||
{ | |||
overlappingColliders[i] = null; | |||
} | |||
Physics.OverlapBoxNonAlloc( | |||
hoverSphereTransform.position - new Vector3( 0, flScaledSphereRadius * boxMult - flScaledSphereRadius, 0 ), | |||
new Vector3( flScaledSphereRadius, flScaledSphereRadius * boxMult * 2.0f, flScaledSphereRadius ), | |||
overlappingColliders, | |||
Quaternion.identity, | |||
hoverLayerMask.value | |||
); | |||
// DebugVar | |||
int iActualColliderCount = 0; | |||
foreach ( Collider collider in overlappingColliders ) | |||
{ | |||
if ( collider == null ) | |||
continue; | |||
Interactable contacting = collider.GetComponentInParent<Interactable>(); | |||
// Yeah, it's null, skip | |||
if ( contacting == null ) | |||
continue; | |||
// Ignore this collider for hovering | |||
IgnoreHovering ignore = collider.GetComponent<IgnoreHovering>(); | |||
if ( ignore != null ) | |||
{ | |||
if ( ignore.onlyIgnoreHand == null || ignore.onlyIgnoreHand == this ) | |||
{ | |||
continue; | |||
} | |||
} | |||
// Can't hover over the object if it's attached | |||
if ( attachedObjects.FindIndex( l => l.attachedObject == contacting.gameObject ) != -1 ) | |||
continue; | |||
// Occupied by another hand, so we can't touch it | |||
if ( otherHand && otherHand.hoveringInteractable == contacting ) | |||
continue; | |||
// Best candidate so far... | |||
float distance = Vector3.Distance( contacting.transform.position, hoverSphereTransform.position ); | |||
if ( distance < closestDistance ) | |||
{ | |||
closestDistance = distance; | |||
closestInteractable = contacting; | |||
} | |||
iActualColliderCount++; | |||
} | |||
// Hover on this one | |||
hoveringInteractable = closestInteractable; | |||
if ( iActualColliderCount > 0 && iActualColliderCount != prevOverlappingColliders ) | |||
{ | |||
prevOverlappingColliders = iActualColliderCount; | |||
HandDebugLog( "Found " + iActualColliderCount + " overlapping colliders." ); | |||
} | |||
} | |||
//------------------------------------------------- | |||
private void UpdateNoSteamVRFallback() | |||
{ | |||
if ( noSteamVRFallbackCamera ) | |||
{ | |||
Ray ray = noSteamVRFallbackCamera.ScreenPointToRay( Input.mousePosition ); | |||
if ( attachedObjects.Count > 0 ) | |||
{ | |||
// Holding down the mouse: | |||
// move around a fixed distance from the camera | |||
transform.position = ray.origin + noSteamVRFallbackInteractorDistance * ray.direction; | |||
} | |||
else | |||
{ | |||
// Not holding down the mouse: | |||
// cast out a ray to see what we should mouse over | |||
// Don't want to hit the hand and anything underneath it | |||
// So move it back behind the camera when we do the raycast | |||
Vector3 oldPosition = transform.position; | |||
transform.position = noSteamVRFallbackCamera.transform.forward * ( -1000.0f ); | |||
RaycastHit raycastHit; | |||
if ( Physics.Raycast( ray, out raycastHit, noSteamVRFallbackMaxDistanceNoItem ) ) | |||
{ | |||
transform.position = raycastHit.point; | |||
// Remember this distance in case we click and drag the mouse | |||
noSteamVRFallbackInteractorDistance = Mathf.Min( noSteamVRFallbackMaxDistanceNoItem, raycastHit.distance ); | |||
} | |||
else if ( noSteamVRFallbackInteractorDistance > 0.0f ) | |||
{ | |||
// Move it around at the distance we last had a hit | |||
transform.position = ray.origin + Mathf.Min( noSteamVRFallbackMaxDistanceNoItem, noSteamVRFallbackInteractorDistance ) * ray.direction; | |||
} | |||
else | |||
{ | |||
// Didn't hit, just leave it where it was | |||
transform.position = oldPosition; | |||
} | |||
} | |||
} | |||
} | |||
//------------------------------------------------- | |||
private void UpdateDebugText() | |||
{ | |||
if ( showDebugText ) | |||
{ | |||
if ( debugText == null ) | |||
{ | |||
debugText = new GameObject( "_debug_text" ).AddComponent<TextMesh>(); | |||
debugText.fontSize = 120; | |||
debugText.characterSize = 0.001f; | |||
debugText.transform.parent = transform; | |||
debugText.transform.localRotation = Quaternion.Euler( 90.0f, 0.0f, 0.0f ); | |||
} | |||
if ( GuessCurrentHandType() == HandType.Right ) | |||
{ | |||
debugText.transform.localPosition = new Vector3( -0.05f, 0.0f, 0.0f ); | |||
debugText.alignment = TextAlignment.Right; | |||
debugText.anchor = TextAnchor.UpperRight; | |||
} | |||
else | |||
{ | |||
debugText.transform.localPosition = new Vector3( 0.05f, 0.0f, 0.0f ); | |||
debugText.alignment = TextAlignment.Left; | |||
debugText.anchor = TextAnchor.UpperLeft; | |||
} | |||
debugText.text = string.Format( | |||
"Hovering: {0}\n" + | |||
"Hover Lock: {1}\n" + | |||
"Attached: {2}\n" + | |||
"Total Attached: {3}\n" + | |||
"Type: {4}\n", | |||
( hoveringInteractable ? hoveringInteractable.gameObject.name : "null" ), | |||
hoverLocked, | |||
( currentAttachedObject ? currentAttachedObject.name : "null" ), | |||
attachedObjects.Count, | |||
GuessCurrentHandType().ToString() ); | |||
} | |||
else | |||
{ | |||
if ( debugText != null ) | |||
{ | |||
Destroy( debugText.gameObject ); | |||
} | |||
} | |||
} | |||
//------------------------------------------------- | |||
void OnEnable() | |||
{ | |||
inputFocusAction.enabled = true; | |||
// Stagger updates between hands | |||
float hoverUpdateBegin = ( ( otherHand != null ) && ( otherHand.GetInstanceID() < GetInstanceID() ) ) ? ( 0.5f * hoverUpdateInterval ) : ( 0.0f ); | |||
InvokeRepeating( "UpdateHovering", hoverUpdateBegin, hoverUpdateInterval ); | |||
InvokeRepeating( "UpdateDebugText", hoverUpdateBegin, hoverUpdateInterval ); | |||
} | |||
//------------------------------------------------- | |||
void OnDisable() | |||
{ | |||
inputFocusAction.enabled = false; | |||
CancelInvoke(); | |||
} | |||
//------------------------------------------------- | |||
void Update() | |||
{ | |||
UpdateNoSteamVRFallback(); | |||
GameObject attached = currentAttachedObject; | |||
if ( attached ) | |||
{ | |||
attached.SendMessage( "HandAttachedUpdate", this, SendMessageOptions.DontRequireReceiver ); | |||
} | |||
if ( hoveringInteractable ) | |||
{ | |||
hoveringInteractable.SendMessage( "HandHoverUpdate", this, SendMessageOptions.DontRequireReceiver ); | |||
} | |||
} | |||
//------------------------------------------------- | |||
void LateUpdate() | |||
{ | |||
//Re-attach the controller if nothing else is attached to the hand | |||
if ( controllerObject != null && attachedObjects.Count == 0 ) | |||
{ | |||
AttachObject( controllerObject ); | |||
} | |||
} | |||
//------------------------------------------------- | |||
private void OnInputFocus( bool hasFocus ) | |||
{ | |||
if ( hasFocus ) | |||
{ | |||
DetachObject( applicationLostFocusObject, true ); | |||
applicationLostFocusObject.SetActive( false ); | |||
UpdateHandPoses(); | |||
UpdateHovering(); | |||
BroadcastMessage( "OnParentHandInputFocusAcquired", SendMessageOptions.DontRequireReceiver ); | |||
} | |||
else | |||
{ | |||
applicationLostFocusObject.SetActive( true ); | |||
AttachObject( applicationLostFocusObject, AttachmentFlags.ParentToHand ); | |||
BroadcastMessage( "OnParentHandInputFocusLost", SendMessageOptions.DontRequireReceiver ); | |||
} | |||
} | |||
//------------------------------------------------- | |||
void FixedUpdate() | |||
{ | |||
UpdateHandPoses(); | |||
} | |||
//------------------------------------------------- | |||
void OnDrawGizmos() | |||
{ | |||
Gizmos.color = new Color( 0.5f, 1.0f, 0.5f, 0.9f ); | |||
Transform sphereTransform = hoverSphereTransform ? hoverSphereTransform : this.transform; | |||
Gizmos.DrawWireSphere( sphereTransform.position, hoverSphereRadius ); | |||
} | |||
//------------------------------------------------- | |||
private void HandDebugLog( string msg ) | |||
{ | |||
if ( spewDebugText ) | |||
{ | |||
Debug.Log( "Hand (" + this.name + "): " + msg ); | |||
} | |||
} | |||
//------------------------------------------------- | |||
private void UpdateHandPoses() | |||
{ | |||
if ( controller != null ) | |||
{ | |||
SteamVR vr = SteamVR.instance; | |||
if ( vr != null ) | |||
{ | |||
var pose = new Valve.VR.TrackedDevicePose_t(); | |||
var gamePose = new Valve.VR.TrackedDevicePose_t(); | |||
var err = vr.compositor.GetLastPoseForTrackedDeviceIndex( controller.index, ref pose, ref gamePose ); | |||
if ( err == Valve.VR.EVRCompositorError.None ) | |||
{ | |||
var t = new SteamVR_Utils.RigidTransform( gamePose.mDeviceToAbsoluteTracking ); | |||
transform.localPosition = t.pos; | |||
transform.localRotation = t.rot; | |||
} | |||
} | |||
} | |||
} | |||
//------------------------------------------------- | |||
// Continue to hover over this object indefinitely, whether or not the Hand moves out of its interaction trigger volume. | |||
// | |||
// interactable - The Interactable to hover over indefinitely. | |||
//------------------------------------------------- | |||
public void HoverLock( Interactable interactable ) | |||
{ | |||
HandDebugLog( "HoverLock " + interactable ); | |||
hoverLocked = true; | |||
hoveringInteractable = interactable; | |||
} | |||
//------------------------------------------------- | |||
// Stop hovering over this object indefinitely. | |||
// | |||
// interactable - The hover-locked Interactable to stop hovering over indefinitely. | |||
//------------------------------------------------- | |||
public void HoverUnlock( Interactable interactable ) | |||
{ | |||
HandDebugLog( "HoverUnlock " + interactable ); | |||
if ( hoveringInteractable == interactable ) | |||
{ | |||
hoverLocked = false; | |||
} | |||
} | |||
//------------------------------------------------- | |||
// Was the standard interaction button just pressed? In VR, this is a trigger press. In 2D fallback, this is a mouse left-click. | |||
//------------------------------------------------- | |||
public bool GetStandardInteractionButtonDown() | |||
{ | |||
if ( noSteamVRFallbackCamera ) | |||
{ | |||
return Input.GetMouseButtonDown( 0 ); | |||
} | |||
else if ( controller != null ) | |||
{ | |||
return controller.GetHairTriggerDown(); | |||
} | |||
return false; | |||
} | |||
//------------------------------------------------- | |||
// Was the standard interaction button just released? In VR, this is a trigger press. In 2D fallback, this is a mouse left-click. | |||
//------------------------------------------------- | |||
public bool GetStandardInteractionButtonUp() | |||
{ | |||
if ( noSteamVRFallbackCamera ) | |||
{ | |||
return Input.GetMouseButtonUp( 0 ); | |||
} | |||
else if ( controller != null ) | |||
{ | |||
return controller.GetHairTriggerUp(); | |||
} | |||
return false; | |||
} | |||
//------------------------------------------------- | |||
// Is the standard interaction button being pressed? In VR, this is a trigger press. In 2D fallback, this is a mouse left-click. | |||
//------------------------------------------------- | |||
public bool GetStandardInteractionButton() | |||
{ | |||
if ( noSteamVRFallbackCamera ) | |||
{ | |||
return Input.GetMouseButton( 0 ); | |||
} | |||
else if ( controller != null ) | |||
{ | |||
return controller.GetHairTrigger(); | |||
} | |||
return false; | |||
} | |||
//------------------------------------------------- | |||
private void InitController( int index ) | |||
{ | |||
if ( controller == null ) | |||
{ | |||
controller = SteamVR_Controller.Input( index ); | |||
HandDebugLog( "Hand " + name + " connected with device index " + controller.index ); | |||
controllerObject = GameObject.Instantiate( controllerPrefab ); | |||
controllerObject.SetActive( true ); | |||
controllerObject.name = controllerPrefab.name + "_" + this.name; | |||
controllerObject.layer = gameObject.layer; | |||
controllerObject.tag = gameObject.tag; | |||
AttachObject( controllerObject ); | |||
controller.TriggerHapticPulse( 800 ); | |||
// If the player's scale has been changed the object to attach will be the wrong size. | |||
// To fix this we change the object's scale back to its original, pre-attach scale. | |||
controllerObject.transform.localScale = controllerPrefab.transform.localScale; | |||
this.BroadcastMessage( "OnHandInitialized", index, SendMessageOptions.DontRequireReceiver ); // let child objects know we've initialized | |||
} | |||
} | |||
} | |||
#if UNITY_EDITOR | |||
//------------------------------------------------------------------------- | |||
[UnityEditor.CustomEditor( typeof( Hand ) )] | |||
public class HandEditor : UnityEditor.Editor | |||
{ | |||
//------------------------------------------------- | |||
// Custom Inspector GUI allows us to click from within the UI | |||
//------------------------------------------------- | |||
public override void OnInspectorGUI() | |||
{ | |||
DrawDefaultInspector(); | |||
Hand hand = (Hand)target; | |||
if ( hand.otherHand ) | |||
{ | |||
if ( hand.otherHand.otherHand != hand ) | |||
{ | |||
UnityEditor.EditorGUILayout.HelpBox( "The otherHand of this Hand's otherHand is not this Hand.", UnityEditor.MessageType.Warning ); | |||
} | |||
if ( hand.startingHandType == Hand.HandType.Left && hand.otherHand.startingHandType != Hand.HandType.Right ) | |||
{ | |||
UnityEditor.EditorGUILayout.HelpBox( "This is a left Hand but otherHand is not a right Hand.", UnityEditor.MessageType.Warning ); | |||
} | |||
if ( hand.startingHandType == Hand.HandType.Right && hand.otherHand.startingHandType != Hand.HandType.Left ) | |||
{ | |||
UnityEditor.EditorGUILayout.HelpBox( "This is a right Hand but otherHand is not a left Hand.", UnityEditor.MessageType.Warning ); | |||
} | |||
if ( hand.startingHandType == Hand.HandType.Any && hand.otherHand.startingHandType != Hand.HandType.Any ) | |||
{ | |||
UnityEditor.EditorGUILayout.HelpBox( "This is an any-handed Hand but otherHand is not an any-handed Hand.", UnityEditor.MessageType.Warning ); | |||
} | |||
} | |||
} | |||
} | |||
#endif | |||
} |
@ -0,0 +1,12 @@ | |||
fileFormatVersion: 2 | |||
guid: 29e3e4511966ba94d8ba0b98c6c62f82 | |||
timeCreated: 1484266511 | |||
licenseType: Store | |||
MonoImporter: | |||
serializedVersion: 2 | |||
defaultReferences: [] | |||
executionOrder: 0 | |||
icon: {fileID: 2800000, guid: b93fe5c516cf6ed4b9153ec790f856e2, type: 3} | |||
userData: | |||
assetBundleName: | |||
assetBundleVariant: |