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: |