Compare commits
11 Commits
versions/1
...
versions/2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae66f9c2fe | ||
|
|
2bfa2ad4c7 | ||
|
|
dfdcd0fd7f | ||
|
|
5ac252bf2e | ||
|
|
fa1969a087 | ||
|
|
3dd72f5f56 | ||
|
|
7f2a459592 | ||
|
|
45b4e46f74 | ||
|
|
11b730e79b | ||
|
|
ca21423a06 | ||
|
|
13e9d00b37 |
Binary file not shown.
4
LICENSE.txt
Normal file
4
LICENSE.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
Copyright © HTC Corporation, LLC and its affiliates. All rights reserved.
|
||||
|
||||
Your use of this SDK, sample, or tool is subject to HTC VIVE SDK License Agreement, available at https://developer.vive.com/resources/downloads/licenses-and-agreements/
|
||||
|
||||
10
README.md
10
README.md
@@ -1,10 +1,10 @@
|
||||
# VIVE OpenXR Plugin - Windows
|
||||
The "VIVE OpenXR Plugin - Windows" plugin package contains some OpenXR Unity features for developers to use.
|
||||
# VIVE OpenXR Plugin
|
||||
The "VIVE OpenXR Plugin" plugin package contains some OpenXR Unity features for developers to use.
|
||||
## How to install:
|
||||
### 1. Download the unitypackage from the github.
|
||||
https://github.com/ViveSoftware/VIVE-OpenXR-PC/blob/master/Installer/ViveOpenXRInstaller.unitypackage
|
||||
https://github.com/ViveSoftware/VIVE-OpenXR/blob/master/Installer/ViveOpenXRInstaller.unitypackage
|
||||
### 2. Import the unitypackage file in the Unity editor.
|
||||
### 3. Select the menu on the Unity UI "VIVE/OpenXR_PC Installer", press "Install or Update latest version".
|
||||
### 3. Select the menu on the Unity UI "VIVE/OpenXR Installer", press "Install or Update latest version".
|
||||
|
||||
Note: For "Install specific version", please copy the release version from https://github.com/ViveSoftware/VIVE-OpenXR-PC/releases,
|
||||
Note: For "Install specific version", please copy the release version from https://github.com/ViveSoftware/VIVE-OpenXR/releases,
|
||||
then paste the version(for example: "1.0.12") to install the specific version.
|
||||
@@ -1,80 +0,0 @@
|
||||
# **VIVE OpenXR Plugin - Windows** For Unity - v1.0.13
|
||||
Copyright HTC Corporation. All Rights Reserved.
|
||||
|
||||
**VIVE OpenXR Plugin - Windows**: This plugin provides support for openxr based on the following specifications.
|
||||
- [Vive Facial Tracking](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XR_HTC_facial_tracking)
|
||||
- [Vive Cosmos Controller](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XR_HTC_vive_cosmos_controller_interaction)
|
||||
- [Scene Understanding](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XR_MSFT_scene_understanding)
|
||||
- [Hand Tracking](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XR_EXT_hand_tracking)
|
||||
- [Vive Focus3 Controller](https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_HTC_vive_focus3_controller_interaction)
|
||||
- [Hand Interaction](https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_HTC_hand_interaction)
|
||||
- [Palm pose](https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_EXT_palm_pose)
|
||||
---
|
||||
## Changes for v1.0.13 - 2023/06/26
|
||||
- Fix problem that "OpenXR.Input.PoseControl" and "OpenXR.Input.Pose" are deprecated after OpenXR Plugin 1.6.0.
|
||||
1. When **USE_INPUT_SYSTEM_POSE_CONTROL** is defined, switch to use InputSystem.XR.PoseControl; otherwise, use OpenXR.Input.PoseControl for backward compatibility.
|
||||
2. When **USE_INPUT_SYSTEM_POSE_CONTROL** is defined, switch to use InputSystem.XR.PoseState; otherwise, use OpenXR.Input.Pose for backward compatibility.
|
||||
|
||||
## Changes for v1.0.12 - 2023/06/02
|
||||
- Remove Eye gaze sample.It is recommended to use the Controller sample provided by the Unity OpenXR Plugin to test eye gaze.
|
||||
|
||||
## Changes for v1.0.11 - 2023/02/16
|
||||
- Add openxr XR_EXT_palm_pose support for Vive Focus3 controller and Vive Cosmos controller.
|
||||
- Add Hand Interaction extension support.
|
||||
- Add hand interaction demo in hand tracking sample.
|
||||
|
||||
## Changes for v1.0.10 - 2023/01/13
|
||||
- Add eye gaze sample.
|
||||
|
||||
## Changes for v1.0.9 - 2022/11/10
|
||||
- Fix the dependency issue with OpenXR plugin.
|
||||
|
||||
|
||||
## Changes for v1.0.8 - 2022/10/11
|
||||
- Update the package name from **Vive Wave OpenXR Plugin - Windows** to **VIVE OpenXR Plugin - Windows**.
|
||||
- Fixed problem that blendshapes and input element columns of facial tracking sample not aligned correctly in Unity Inspector.
|
||||
- Fix haptic problem for cosmos controller profile.
|
||||
- Add Focus3 controller extension support.
|
||||
|
||||
## Changes for v1.0.7 - 2022/09/26
|
||||
- Fixed function type conversion problem when using handtracking feature with other OpenXR features at the same time.
|
||||
|
||||
## Changes for v1.0.6 - 2022/09/15
|
||||
### Vive Hand Tracking
|
||||
- Fixed delay problem when locating controller with HandTracking extension.
|
||||
|
||||
## Changes for v1.0.5 - 2022/06/24
|
||||
- Update documentation links for (1) Vive Facial Tracking (2) Vive Cosmos Controller (3) Scene Understanding (4) Hand Tracking.
|
||||
- Refine plugin and sample for (1) Vive Facial Tracking (2) Hand Tracking.
|
||||
### Vive Hand Tracking
|
||||
- Implement extension XR_EXT_hand_joints_motion_range for Hand tracking.
|
||||
- Fixed incorrect joint rotation.
|
||||
|
||||
### Vive Facial Tracking
|
||||
- Fixed incorrect eye gaze direction for sample.
|
||||
|
||||
## Changes for v1.0.4 - 2022/4/28:
|
||||
- Update the package name from **Vive OpenXR Plugin** to **VIVE Wave OpenXR Plugin - Windows**.
|
||||
- Fixed missing material for Hand Tracking sample.
|
||||
- Fixed Hand tracking sample crashed issue.
|
||||
- Add 3D HandTracking Sample.
|
||||
|
||||
## Changes for v1.0.3 - 2022/4/08:
|
||||
- Refactor Hand Tracking sample.
|
||||
- Fixed build error related to Scene Understanding plugin.
|
||||
|
||||
## Changes for v1.0.2 - 2022/3/23:
|
||||
- Add support for openxr hand tracking extension.
|
||||
|
||||
## Changes for v1.0.1 - 2022/2/10:
|
||||
|
||||
### Vive Cosmos Controller
|
||||
- Correct the input path of menu key.
|
||||
|
||||
### Scene Understanding
|
||||
- Move Mesh subsystem from plugin part to sample code.
|
||||
|
||||
## Changes for v1.0.0 - 2021/1/06:
|
||||
|
||||
* This is the first release of Vive OpenXR Unity Plugin.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 28769a4eba0d8bf448df06f6edc80599
|
||||
guid: aae4484d37f3dc949851ce06e791456e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
|
||||
370
com.htc.upm.vive.openxr/Editor/AndroidManifestProcess.cs
Normal file
370
com.htc.upm.vive.openxr/Editor/AndroidManifestProcess.cs
Normal file
@@ -0,0 +1,370 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEditor.PackageManager;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using UnityEngine.XR.OpenXR.Features.Interactions;
|
||||
using VIVE.OpenXR.Hand;
|
||||
using VIVE.OpenXR.Tracker;
|
||||
|
||||
// Reference to Unity's OpenXR package
|
||||
|
||||
namespace VIVE.OpenXR.Editor
|
||||
{
|
||||
internal class ModifyAndroidManifest : OpenXRFeatureBuildHooks
|
||||
{
|
||||
public override int callbackOrder => 1;
|
||||
|
||||
public override Type featureType => typeof(VIVEFocus3Feature);
|
||||
|
||||
protected override void OnPreprocessBuildExt(BuildReport report)
|
||||
{
|
||||
}
|
||||
|
||||
private static string _manifestPath;
|
||||
|
||||
protected override void OnPostGenerateGradleAndroidProjectExt(string path)
|
||||
{
|
||||
_manifestPath = GetManifestPath(path);
|
||||
|
||||
var androidManifest = new AndroidManifest(_manifestPath);
|
||||
//androidManifest.AddVIVECategory();
|
||||
androidManifest.AddViveSDKVersion();
|
||||
androidManifest.AddUnityVersion();
|
||||
androidManifest.AddOpenXRPermission();
|
||||
androidManifest.AddOpenXRFeatures();
|
||||
androidManifest.Save();
|
||||
}
|
||||
|
||||
protected override void OnPostprocessBuildExt(BuildReport report)
|
||||
{
|
||||
if (File.Exists(_manifestPath))
|
||||
File.Delete(_manifestPath);
|
||||
}
|
||||
|
||||
private string _manifestFilePath;
|
||||
|
||||
private string GetManifestPath(string basePath)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_manifestFilePath)) return _manifestFilePath;
|
||||
|
||||
var pathBuilder = new StringBuilder(basePath);
|
||||
pathBuilder.Append(Path.DirectorySeparatorChar).Append("src");
|
||||
pathBuilder.Append(Path.DirectorySeparatorChar).Append("main");
|
||||
pathBuilder.Append(Path.DirectorySeparatorChar).Append("AndroidManifest.xml");
|
||||
_manifestFilePath = pathBuilder.ToString();
|
||||
|
||||
return _manifestFilePath;
|
||||
}
|
||||
|
||||
private class AndroidXmlDocument : XmlDocument
|
||||
{
|
||||
private string m_Path;
|
||||
protected XmlNamespaceManager nsMgr;
|
||||
public readonly string AndroidXmlNamespace = "http://schemas.android.com/apk/res/android";
|
||||
|
||||
public AndroidXmlDocument(string path)
|
||||
{
|
||||
m_Path = path;
|
||||
using (var reader = new XmlTextReader(m_Path))
|
||||
{
|
||||
reader.Read();
|
||||
Load(reader);
|
||||
}
|
||||
|
||||
nsMgr = new XmlNamespaceManager(NameTable);
|
||||
nsMgr.AddNamespace("android", AndroidXmlNamespace);
|
||||
}
|
||||
|
||||
public string Save()
|
||||
{
|
||||
return SaveAs(m_Path);
|
||||
}
|
||||
|
||||
public string SaveAs(string path)
|
||||
{
|
||||
using (var writer = new XmlTextWriter(path, new UTF8Encoding(false)))
|
||||
{
|
||||
writer.Formatting = Formatting.Indented;
|
||||
Save(writer);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
[InitializeOnLoad]
|
||||
public static class CheckIfSimultaneousInteractionEnabled
|
||||
{
|
||||
const string LOG_TAG = "CheckIfSimultaneousInteractionEnabled ";
|
||||
static StringBuilder m_sb = null;
|
||||
static StringBuilder sb
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_sb == null) { m_sb = new StringBuilder(); }
|
||||
return m_sb;
|
||||
}
|
||||
}
|
||||
static void DEBUG(StringBuilder msg) { Debug.Log(msg); }
|
||||
|
||||
internal const string MENU_NAME = "VIVE/Interaction Mode/Enable Simultaneous Interaction";
|
||||
|
||||
private static bool m_IsEnabled = false;
|
||||
public static bool IsEnabled { get { return m_IsEnabled; } }
|
||||
|
||||
static CheckIfSimultaneousInteractionEnabled()
|
||||
{
|
||||
m_IsEnabled = EditorPrefs.GetBool(MENU_NAME, false);
|
||||
|
||||
/// Delaying until first editor tick so that the menu
|
||||
/// will be populated before setting check state, and
|
||||
/// re-apply correct action
|
||||
EditorApplication.delayCall += () =>
|
||||
{
|
||||
PerformAction(m_IsEnabled);
|
||||
};
|
||||
}
|
||||
|
||||
[MenuItem(MENU_NAME, priority = 601)]
|
||||
private static void ToggleAction()
|
||||
{
|
||||
/// Toggling action
|
||||
PerformAction(!m_IsEnabled);
|
||||
}
|
||||
|
||||
public static void PerformAction(bool enabled)
|
||||
{
|
||||
/// Set checkmark on menu item
|
||||
Menu.SetChecked(MENU_NAME, enabled);
|
||||
|
||||
/// Saving editor state
|
||||
EditorPrefs.SetBool(MENU_NAME, enabled);
|
||||
|
||||
m_IsEnabled = enabled;
|
||||
|
||||
//sb.Clear().Append(LOG_TAG).Append(m_IsEnabled ? "Enable " : "Disable ").Append("Simultaneous Interaction."); DEBUG(sb);
|
||||
}
|
||||
|
||||
[MenuItem(MENU_NAME, validate = true, priority = 601)]
|
||||
public static bool ValidateEnabled()
|
||||
{
|
||||
Menu.SetChecked(MENU_NAME, m_IsEnabled);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private class AndroidManifest : AndroidXmlDocument
|
||||
{
|
||||
private readonly XmlElement IntetnFilterElement;
|
||||
private readonly XmlElement ManifestElement;
|
||||
private readonly XmlElement ApplicationElement;
|
||||
|
||||
public AndroidManifest(string path) : base(path)
|
||||
{
|
||||
IntetnFilterElement = SelectSingleNode("/manifest/application/activity/intent-filter") as XmlElement;
|
||||
ManifestElement = SelectSingleNode("/manifest") as XmlElement;
|
||||
ApplicationElement = SelectSingleNode("/manifest/application") as XmlElement;
|
||||
}
|
||||
|
||||
private XmlAttribute CreateAndroidAttribute(string key, string value)
|
||||
{
|
||||
XmlAttribute attr = CreateAttribute("android", key, AndroidXmlNamespace);
|
||||
attr.Value = value;
|
||||
return attr;
|
||||
}
|
||||
|
||||
private const string FAKE_VERSION = "0.0.0";
|
||||
|
||||
private static string SearchPackageVersion(string packageName)
|
||||
{
|
||||
var listRequest = Client.List(true);
|
||||
do
|
||||
{
|
||||
if (listRequest.IsCompleted)
|
||||
{
|
||||
if (listRequest.Result == null)
|
||||
{
|
||||
Debug.Log("List result: is empty");
|
||||
return FAKE_VERSION;
|
||||
}
|
||||
|
||||
foreach (var pi in listRequest.Result)
|
||||
{
|
||||
//Debug.Log("List has: " + pi.name + " == " + packageName);
|
||||
if (pi.name == packageName)
|
||||
{
|
||||
Debug.Log("Found " + packageName);
|
||||
|
||||
return pi.version;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
Thread.Sleep(100);
|
||||
} while (true);
|
||||
return FAKE_VERSION;
|
||||
}
|
||||
|
||||
internal void AddViveSDKVersion()
|
||||
{
|
||||
var newUsesFeature = CreateElement("meta-data");
|
||||
newUsesFeature.Attributes.Append(CreateAndroidAttribute("name", "com.htc.ViveOpenXR.SdkVersion"));
|
||||
newUsesFeature.Attributes.Append(CreateAndroidAttribute("value", SearchPackageVersion("com.htc.upm.vive.openxr")));
|
||||
ApplicationElement.AppendChild(newUsesFeature);
|
||||
}
|
||||
|
||||
internal void AddUnityVersion()
|
||||
{
|
||||
var newUsesFeature = CreateElement("meta-data");
|
||||
newUsesFeature.Attributes.Append(CreateAndroidAttribute("name", "com.htc.vr.content.UnityVersion"));
|
||||
newUsesFeature.Attributes.Append(CreateAndroidAttribute("value", Application.unityVersion));
|
||||
ApplicationElement.AppendChild(newUsesFeature);
|
||||
}
|
||||
|
||||
internal void AddVIVECategory()
|
||||
{
|
||||
var md = IntetnFilterElement.AppendChild(CreateElement("category"));
|
||||
md.Attributes.Append(CreateAndroidAttribute("name", "com.htc.intent.category.VRAPP"));
|
||||
}
|
||||
|
||||
internal void AddOpenXRPermission()
|
||||
{
|
||||
var md = ManifestElement.AppendChild(CreateElement("uses-permission"));
|
||||
md.Attributes.Append(CreateAndroidAttribute("name", "org.khronos.openxr.permission.OPENXR"));
|
||||
|
||||
md = ManifestElement.AppendChild(CreateElement("uses-permission"));
|
||||
md.Attributes.Append(CreateAndroidAttribute("name", "org.khronos.openxr.permission.OPENXR_SYSTEM"));
|
||||
|
||||
var md2 = IntetnFilterElement.AppendChild(CreateElement("category"));
|
||||
md2.Attributes.Append(CreateAndroidAttribute("name", "org.khronos.openxr.intent.category.IMMERSIVE_HMD"));
|
||||
}
|
||||
|
||||
internal void AddOpenXRFeatures()
|
||||
{
|
||||
bool enableHandtracking = false;
|
||||
bool enableTracker = false;
|
||||
bool enableEyetracking = false;
|
||||
bool enableLipexpression = false;
|
||||
const string kHandTrackingExtension = "XR_EXT_hand_tracking";
|
||||
const string kFacialTrackingExtension = "XR_HTC_facial_tracking";
|
||||
const string kHandInteractionHTC = "XR_HTC_hand_interaction";
|
||||
const string kHandInteractionEXT = "XR_EXT_hand_interaction";
|
||||
|
||||
var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(BuildTargetGroup.Android);
|
||||
if (null == settings)
|
||||
return;
|
||||
|
||||
foreach (var feature in settings.GetFeatures<OpenXRInteractionFeature>())
|
||||
{
|
||||
if ((feature is ViveWristTracker || feature is ViveXRTracker) && feature.enabled)
|
||||
{
|
||||
enableHandtracking = true;
|
||||
enableTracker = true;
|
||||
}
|
||||
if (feature is EyeGazeInteraction && feature.enabled)
|
||||
{
|
||||
enableEyetracking = true;
|
||||
}
|
||||
if (feature is ViveHandInteraction && feature.enabled)
|
||||
{
|
||||
enableHandtracking = true;
|
||||
}
|
||||
}
|
||||
|
||||
var features = settings.GetFeatures<OpenXRFeature>();
|
||||
foreach (var feature in features)
|
||||
{
|
||||
if (!feature.enabled) { continue; }
|
||||
|
||||
FieldInfo fieldInfoOpenXrExtensionStrings = typeof(OpenXRFeature).GetField(
|
||||
"openxrExtensionStrings",
|
||||
BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
if (fieldInfoOpenXrExtensionStrings != null)
|
||||
{
|
||||
var openXrExtensionStringsArray =
|
||||
((string)fieldInfoOpenXrExtensionStrings.GetValue(feature)).Split(' ');
|
||||
|
||||
foreach (string stringItem in openXrExtensionStringsArray)
|
||||
{
|
||||
if (string.IsNullOrEmpty(stringItem)) { continue; }
|
||||
|
||||
if (stringItem.Equals(kHandTrackingExtension) ||
|
||||
stringItem.Equals(kHandInteractionHTC) ||
|
||||
stringItem.Equals(kHandInteractionEXT))
|
||||
{
|
||||
enableHandtracking = true;
|
||||
}
|
||||
if (stringItem.Equals(kFacialTrackingExtension))
|
||||
{
|
||||
enableEyetracking = true;
|
||||
enableLipexpression = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (feature is VIVEFocus3Feature)
|
||||
{
|
||||
for (int i = 0; i < features.Length; i++)
|
||||
{
|
||||
if (features[i] is Enterprise.ViveEnterpriseCommand)
|
||||
{
|
||||
features[i].enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (enableHandtracking)
|
||||
{
|
||||
var newUsesFeature = CreateElement("uses-feature");
|
||||
newUsesFeature.Attributes.Append(CreateAndroidAttribute("name", "wave.feature.handtracking"));
|
||||
newUsesFeature.Attributes.Append(CreateAndroidAttribute("required", "true"));
|
||||
ManifestElement.AppendChild(newUsesFeature);
|
||||
}
|
||||
|
||||
if (enableTracker)
|
||||
{
|
||||
var newUsesFeature = CreateElement("uses-feature");
|
||||
newUsesFeature.Attributes.Append(CreateAndroidAttribute("name", "wave.feature.tracker"));
|
||||
newUsesFeature.Attributes.Append(CreateAndroidAttribute("required", "true"));
|
||||
ManifestElement.AppendChild(newUsesFeature);
|
||||
}
|
||||
|
||||
if (enableEyetracking)
|
||||
{
|
||||
var newUsesFeature = CreateElement("uses-feature");
|
||||
newUsesFeature.Attributes.Append(CreateAndroidAttribute("name", "wave.feature.eyetracking"));
|
||||
newUsesFeature.Attributes.Append(CreateAndroidAttribute("required", "true"));
|
||||
ManifestElement.AppendChild(newUsesFeature);
|
||||
}
|
||||
|
||||
if (enableLipexpression)
|
||||
{
|
||||
var newUsesFeature = CreateElement("uses-feature");
|
||||
newUsesFeature.Attributes.Append(CreateAndroidAttribute("name", "wave.feature.lipexpression"));
|
||||
newUsesFeature.Attributes.Append(CreateAndroidAttribute("required", "true"));
|
||||
ManifestElement.AppendChild(newUsesFeature);
|
||||
}
|
||||
|
||||
if (CheckIfSimultaneousInteractionEnabled.IsEnabled)
|
||||
{
|
||||
var newUsesFeature = CreateElement("uses-feature");
|
||||
newUsesFeature.Attributes.Append(CreateAndroidAttribute("name", "wave.feature.simultaneous_interaction"));
|
||||
newUsesFeature.Attributes.Append(CreateAndroidAttribute("required", "true"));
|
||||
ManifestElement.AppendChild(newUsesFeature);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b9da6a2c254e9354891b5ab88cd630f0
|
||||
guid: cd029ee7a3204f446b0def5eafc0a380
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3af3c139ab2eee9498a484a154cad9af
|
||||
guid: ddf1278db13678e45b960b274d526b39
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 686c57b9d62a14c47b8353ea34d46bb3
|
||||
guid: 213dee666ce1d064bac61bf4164523d9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -0,0 +1,826 @@
|
||||
// "VIVE SDK
|
||||
// © 2020 HTC Corporation. All Rights Reserved.
|
||||
//
|
||||
// Unless otherwise required by copyright law and practice,
|
||||
// upon the execution of HTC SDK license agreement,
|
||||
// HTC grants you access to and use of the VIVE SDK(s).
|
||||
// You shall fully comply with all of HTC’s SDK license agreement terms and
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
namespace VIVE.OpenXR.CompositionLayer.Editor
|
||||
{
|
||||
#region Composition Layer Editor
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using VIVE.OpenXR.CompositionLayer;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
|
||||
[CustomEditor(typeof(CompositionLayer))]
|
||||
public class CompositionLayerEditor : Editor
|
||||
{
|
||||
static string PropertyName_LayerType = "layerType";
|
||||
static GUIContent Label_LayerType = new GUIContent("Type", "Specify the type of the composition layer.");
|
||||
SerializedProperty Property_LayerType;
|
||||
|
||||
static string PropertyName_CompositionDepth = "compositionDepth";
|
||||
static GUIContent Label_CompositionDepth = new GUIContent("Composition Depth", "Specify the composition depth of the layer.");
|
||||
SerializedProperty Property_CompositionDepth;
|
||||
|
||||
static string PropertyName_LayerShape = "layerShape";
|
||||
static GUIContent Label_LayerShape = new GUIContent("Shape", "Specify the shape of the layer.");
|
||||
SerializedProperty Property_LayerShape;
|
||||
|
||||
static string PropertyName_LayerVisibility = "layerVisibility";
|
||||
static GUIContent Label_LayerVisibility = new GUIContent("Visibility", "Specify the visibility of the layer.");
|
||||
SerializedProperty Property_LayerVisibility;
|
||||
|
||||
static string PropertyName_LockMode = "lockMode";
|
||||
static GUIContent Label_LockMode = new GUIContent("Locked Parameter", "Cylinder Layer parameter to be locked when changing the radius.");
|
||||
SerializedProperty Property_LockMode;
|
||||
|
||||
static string PropertyName_QuadWidth = "m_QuadWidth";
|
||||
static GUIContent Label_QuadWidth = new GUIContent("Width", "Width of a Quad Layer");
|
||||
SerializedProperty Property_QuadWidth;
|
||||
|
||||
static string PropertyName_QuadHeight = "m_QuadHeight";
|
||||
static GUIContent Label_QuadHeight = new GUIContent("Height", "Height of a Quad Layer");
|
||||
SerializedProperty Property_QuadHeight;
|
||||
|
||||
static string PropertyName_EquirectRadius = "m_EquirectRadius";
|
||||
static GUIContent Label_EquirectRadius = new GUIContent("Radius", "Radius of Equirect Layer");
|
||||
SerializedProperty Property_EquirectRadius;
|
||||
|
||||
static string PropertyName_EquirectScaleX = "m_EquirectScaleX";
|
||||
static GUIContent Label_EquirectScaleX = new GUIContent("scale.x", "Scale.X of Equirect Layer");
|
||||
SerializedProperty Property_EquirectScaleX;
|
||||
|
||||
static string PropertyName_EquirectScaleY = "m_EquirectScaleY";
|
||||
static GUIContent Label_EquirectScaleY = new GUIContent("scale.y", "Scale.Y of Equirect Layer");
|
||||
SerializedProperty Property_EquirectScaleY;
|
||||
|
||||
static string PropertyName_EquirectBiasX = "m_EquirectBiasX";
|
||||
static GUIContent Label_EquirectBiasX = new GUIContent("bias.x", "Bias.X of Equirect Layer");
|
||||
SerializedProperty Property_EquirectBiasX;
|
||||
|
||||
static string PropertyName_EquirectBiasY = "m_EquirectBiasY";
|
||||
static GUIContent Label_EquirectBiasY = new GUIContent("bias.y", "Bias.Y of Equirect Layer");
|
||||
SerializedProperty Property_EquirectBiasY;
|
||||
|
||||
static string PropertyName_EquirectCentralHorizontalAngle = "m_EquirectCentralHorizontalAngle";
|
||||
static GUIContent Label_EquirectCentralHorizontalAngle = new GUIContent("CentralHorizontalAngle", "Central Horizontal Angle of Equirect Layer");
|
||||
SerializedProperty Property_EquirectCentralHorizontalAngle;
|
||||
|
||||
static string PropertyName_EquirectUpperVerticalAngle = "m_EquirectUpperVerticalAngle";
|
||||
static GUIContent Label_EquirectUpperVerticalAngle = new GUIContent("UpperVerticalAngle", "Upper Vertical Angle of Equirect Layer");
|
||||
SerializedProperty Property_EquirectUpperVerticalAngle;
|
||||
|
||||
static string PropertyName_EquirectLowerVerticalAngle = "m_EquirectLowerVerticalAngle";
|
||||
static GUIContent Label_EquirectLowerVerticalAngle = new GUIContent("LowerVerticalAngle", "Lower Vertical Angle of Equirect Layer");
|
||||
SerializedProperty Property_EquirectLowerVerticalAngle;
|
||||
|
||||
|
||||
static string PropertyName_CylinderHeight = "m_CylinderHeight";
|
||||
static GUIContent Label_CylinderHeight = new GUIContent("Height", "Height of Cylinder Layer");
|
||||
SerializedProperty Property_CylinderHeight;
|
||||
|
||||
static string PropertyName_CylinderArcLength = "m_CylinderArcLength";
|
||||
static GUIContent Label_CylinderArcLength = new GUIContent("Arc Length", "Arc Length of Cylinder Layer");
|
||||
SerializedProperty Property_CylinderArcLength;
|
||||
|
||||
static string PropertyName_CylinderRadius = "m_CylinderRadius";
|
||||
static GUIContent Label_CylinderRadius = new GUIContent("Radius", "Radius of Cylinder Layer");
|
||||
SerializedProperty Property_CylinderRadius;
|
||||
|
||||
static string PropertyName_AngleOfArc = "m_CylinderAngleOfArc";
|
||||
static GUIContent Label_AngleOfArc = new GUIContent("Arc Angle", "Central angle of arc of Cylinder Layer");
|
||||
SerializedProperty Property_AngleOfArc;
|
||||
|
||||
static string PropertyName_isExternalSurface = "isExternalSurface";
|
||||
static GUIContent Label_isExternalSurface = new GUIContent("External Surface", "Specify using external surface or not.");
|
||||
SerializedProperty Property_isExternalSurface;
|
||||
|
||||
static string PropertyName_ExternalSurfaceWidth = "externalSurfaceWidth";
|
||||
static GUIContent Label_ExternalSurfaceWidth = new GUIContent("Width");
|
||||
SerializedProperty Property_ExternalSurfaceWidth;
|
||||
|
||||
static string PropertyName_ExternalSurfaceHeight = "externalSurfaceHeight";
|
||||
static GUIContent Label_ExternalSurfaceHeight = new GUIContent("Height");
|
||||
SerializedProperty Property_ExternalSurfaceHeight;
|
||||
|
||||
static string PropertyName_IsDynamicLayer = "isDynamicLayer";
|
||||
static GUIContent Label_IsDynamicLayer = new GUIContent("Dynamic Layer", "Specify whether Layer needs to be updated each frame or not.");
|
||||
SerializedProperty Property_IsDynamicLayer;
|
||||
|
||||
static string PropertyName_IsCustomRects = "isCustomRects";
|
||||
static GUIContent Label_IsCustomRects = new GUIContent("Customize Rects", "Using a single texture as a stereo image");
|
||||
SerializedProperty Property_IsCustomRects;
|
||||
|
||||
static string PropertyName_CustomRects = "customRects";
|
||||
static GUIContent Label_CustomRects = new GUIContent("Customize Rects Type", "Specify the customize rects type of the left texture.");
|
||||
SerializedProperty Property_CustomRects;
|
||||
|
||||
|
||||
static string PropertyName_ApplyColorScaleBias = "applyColorScaleBias";
|
||||
static GUIContent Label_ApplyColorScaleBias = new GUIContent("Apply Color Scale Bias", "Color scale and bias are applied to a layer color during composition, after its conversion to premultiplied alpha representation. LayerColor = LayerColor * colorScale + colorBias");
|
||||
SerializedProperty Property_ApplyColorScaleBias;
|
||||
|
||||
static string PropertyName_SolidEffect = "solidEffect";
|
||||
static GUIContent Label_SolidEffect = new GUIContent("Solid Effect", "Apply UnderLay Color Scale Bias in Runtime Level.");
|
||||
SerializedProperty Property_SolidEffect;
|
||||
|
||||
|
||||
static string PropertyName_ColorScale = "colorScale";
|
||||
static GUIContent Label_ColorScale = new GUIContent("Color Scale", "Will be used for modulatting the color sourced from the images.");
|
||||
SerializedProperty Property_ColorScale;
|
||||
|
||||
static string PropertyName_ColorBias = "colorBias";
|
||||
static GUIContent Label_ColorBias = new GUIContent("Color Bias", "Will be used for offseting the color sourced from the images.");
|
||||
SerializedProperty Property_ColorBias;
|
||||
|
||||
static string PropertyName_IsProtectedSurface = "isProtectedSurface";
|
||||
static GUIContent Label_IsProtectedSurface = new GUIContent("Protected Surface");
|
||||
SerializedProperty Property_IsProtectedSurface;
|
||||
|
||||
static string PropertyName_RenderPriority = "renderPriority";
|
||||
static GUIContent Label_RenderPriority = new GUIContent("Render Priority", "When Auto Fallback is enabled, layers with a higher render priority will be rendered as normal layers first.");
|
||||
SerializedProperty Property_RenderPriority;
|
||||
|
||||
static string PropertyName_TrackingOrigin = "trackingOrigin";
|
||||
static GUIContent Label_TrackingOrigin = new GUIContent("Tracking Origin", "Assign the tracking origin here to offset the pose of the Composition Layer.");
|
||||
SerializedProperty Property_TrackingOrigin;
|
||||
|
||||
private bool showLayerParams = true, showColorScaleBiasParams = true;
|
||||
|
||||
//private bool showExternalSurfaceParams = false;
|
||||
|
||||
Rect FullRect = new Rect(0, 0, 1, 1);
|
||||
Rect LeftRightRect = new Rect(0, 0, 0.5f, 1);
|
||||
Rect TopDownRect = new Rect(0, 0.5f, 1, 0.5f);
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
if (Property_LayerType == null) Property_LayerType = serializedObject.FindProperty(PropertyName_LayerType);
|
||||
if (Property_CompositionDepth == null) Property_CompositionDepth = serializedObject.FindProperty(PropertyName_CompositionDepth);
|
||||
if (Property_LayerShape == null) Property_LayerShape = serializedObject.FindProperty(PropertyName_LayerShape);
|
||||
if (Property_LayerVisibility == null) Property_LayerVisibility = serializedObject.FindProperty(PropertyName_LayerVisibility);
|
||||
if (Property_CustomRects == null) Property_CustomRects = serializedObject.FindProperty(PropertyName_CustomRects);
|
||||
if (Property_LockMode == null) Property_LockMode = serializedObject.FindProperty(PropertyName_LockMode);
|
||||
if (Property_QuadWidth == null) Property_QuadWidth = serializedObject.FindProperty(PropertyName_QuadWidth);
|
||||
if (Property_QuadHeight == null) Property_QuadHeight = serializedObject.FindProperty(PropertyName_QuadHeight);
|
||||
if (Property_EquirectRadius == null) Property_EquirectRadius = serializedObject.FindProperty(PropertyName_EquirectRadius);
|
||||
if (Property_EquirectScaleX == null) Property_EquirectScaleX = serializedObject.FindProperty(PropertyName_EquirectScaleX);
|
||||
if (Property_EquirectScaleY == null) Property_EquirectScaleY = serializedObject.FindProperty(PropertyName_EquirectScaleY);
|
||||
if (Property_EquirectBiasX == null) Property_EquirectBiasX = serializedObject.FindProperty(PropertyName_EquirectBiasX);
|
||||
if (Property_EquirectBiasY == null) Property_EquirectBiasY = serializedObject.FindProperty(PropertyName_EquirectBiasY);
|
||||
if (Property_EquirectCentralHorizontalAngle == null) Property_EquirectCentralHorizontalAngle = serializedObject.FindProperty(PropertyName_EquirectCentralHorizontalAngle);
|
||||
if (Property_EquirectUpperVerticalAngle == null) Property_EquirectUpperVerticalAngle = serializedObject.FindProperty(PropertyName_EquirectUpperVerticalAngle);
|
||||
if (Property_EquirectLowerVerticalAngle == null) Property_EquirectLowerVerticalAngle = serializedObject.FindProperty(PropertyName_EquirectLowerVerticalAngle);
|
||||
if (Property_CylinderHeight == null) Property_CylinderHeight = serializedObject.FindProperty(PropertyName_CylinderHeight);
|
||||
if (Property_CylinderArcLength == null) Property_CylinderArcLength = serializedObject.FindProperty(PropertyName_CylinderArcLength);
|
||||
if (Property_CylinderRadius == null) Property_CylinderRadius = serializedObject.FindProperty(PropertyName_CylinderRadius);
|
||||
if (Property_AngleOfArc == null) Property_AngleOfArc = serializedObject.FindProperty(PropertyName_AngleOfArc);
|
||||
if (Property_isExternalSurface == null) Property_isExternalSurface = serializedObject.FindProperty(PropertyName_isExternalSurface);
|
||||
if (Property_ExternalSurfaceWidth == null) Property_ExternalSurfaceWidth = serializedObject.FindProperty(PropertyName_ExternalSurfaceWidth);
|
||||
if (Property_ExternalSurfaceHeight == null) Property_ExternalSurfaceHeight = serializedObject.FindProperty(PropertyName_ExternalSurfaceHeight);
|
||||
if (Property_IsDynamicLayer == null) Property_IsDynamicLayer = serializedObject.FindProperty(PropertyName_IsDynamicLayer);
|
||||
if (Property_IsCustomRects == null) Property_IsCustomRects = serializedObject.FindProperty(PropertyName_IsCustomRects);
|
||||
if (Property_ApplyColorScaleBias == null) Property_ApplyColorScaleBias = serializedObject.FindProperty(PropertyName_ApplyColorScaleBias);
|
||||
if (Property_SolidEffect == null) Property_SolidEffect = serializedObject.FindProperty(PropertyName_SolidEffect);
|
||||
if (Property_ColorScale == null) Property_ColorScale = serializedObject.FindProperty(PropertyName_ColorScale);
|
||||
if (Property_ColorBias == null) Property_ColorBias = serializedObject.FindProperty(PropertyName_ColorBias);
|
||||
if (Property_IsProtectedSurface == null) Property_IsProtectedSurface = serializedObject.FindProperty(PropertyName_IsProtectedSurface);
|
||||
if (Property_RenderPriority == null) Property_RenderPriority = serializedObject.FindProperty(PropertyName_RenderPriority);
|
||||
if (Property_TrackingOrigin == null) Property_TrackingOrigin = serializedObject.FindProperty(PropertyName_TrackingOrigin);
|
||||
|
||||
CompositionLayer targetCompositionLayer = target as CompositionLayer;
|
||||
|
||||
if (!FeatureHelpers.GetFeatureWithIdForBuildTarget(BuildTargetGroup.Android, ViveCompositionLayer.featureId).enabled)
|
||||
{
|
||||
EditorGUILayout.HelpBox("The Composition Layer feature is not enabled in OpenXR Settings.\nEnable it to use the Composition Layer.", MessageType.Warning);
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(Property_LayerType, new GUIContent(Label_LayerType));
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
EditorGUILayout.PropertyField(Property_CompositionDepth, new GUIContent(Label_CompositionDepth));
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
EditorGUILayout.PropertyField(Property_LayerShape, new GUIContent(Label_LayerShape));
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
if (Property_LayerShape.intValue == (int)CompositionLayer.LayerShape.Equirect || Property_LayerShape.intValue == (int)CompositionLayer.LayerShape.Equirect2)
|
||||
{
|
||||
if (targetCompositionLayer.isPreviewingQuad)
|
||||
{
|
||||
targetCompositionLayer.isPreviewingQuad = false;
|
||||
if (targetCompositionLayer.generatedPreview != null)
|
||||
{
|
||||
DestroyImmediate(targetCompositionLayer.generatedPreview);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetCompositionLayer.isPreviewingCylinder)
|
||||
{
|
||||
targetCompositionLayer.isPreviewingCylinder = false;
|
||||
if (targetCompositionLayer.generatedPreview != null)
|
||||
{
|
||||
DestroyImmediate(targetCompositionLayer.generatedPreview);
|
||||
}
|
||||
}
|
||||
|
||||
if (!FeatureHelpers.GetFeatureWithIdForBuildTarget(BuildTargetGroup.Android, ViveCompositionLayerEquirect.featureId).enabled)
|
||||
{
|
||||
EditorGUILayout.HelpBox("The Composition Layer Equirect feature is not enabled in OpenXR Settings.\nEnable it to use Equirect layers.", MessageType.Warning);
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel++;
|
||||
showLayerParams = EditorGUILayout.Foldout(showLayerParams, "Equirect Parameters");
|
||||
if (showLayerParams)
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property_EquirectRadius, new GUIContent(Label_EquirectRadius));
|
||||
|
||||
if (Property_LayerShape.intValue == (int)CompositionLayer.LayerShape.Equirect)
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property_EquirectScaleX, new GUIContent(Label_EquirectScaleX));
|
||||
EditorGUILayout.PropertyField(Property_EquirectScaleY, new GUIContent(Label_EquirectScaleY));
|
||||
EditorGUILayout.PropertyField(Property_EquirectBiasX, new GUIContent(Label_EquirectBiasX));
|
||||
EditorGUILayout.PropertyField(Property_EquirectBiasY, new GUIContent(Label_EquirectBiasY));
|
||||
}
|
||||
|
||||
else if (Property_LayerShape.intValue == (int)CompositionLayer.LayerShape.Equirect2)
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property_EquirectCentralHorizontalAngle, new GUIContent(Label_EquirectCentralHorizontalAngle));
|
||||
EditorGUILayout.PropertyField(Property_EquirectUpperVerticalAngle, new GUIContent(Label_EquirectUpperVerticalAngle));
|
||||
EditorGUILayout.PropertyField(Property_EquirectLowerVerticalAngle, new GUIContent(Label_EquirectLowerVerticalAngle));
|
||||
}
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
bool EquirectParamsChanged = targetCompositionLayer.LayerDimensionsChanged();
|
||||
if (targetCompositionLayer.isPreviewingEquirect)
|
||||
{
|
||||
Transform generatedPreviewTransform = targetCompositionLayer.transform.Find(CompositionLayer.EquirectPreviewName);
|
||||
|
||||
if (generatedPreviewTransform != null)
|
||||
{
|
||||
targetCompositionLayer.generatedPreview = generatedPreviewTransform.gameObject;
|
||||
|
||||
if (EquirectParamsChanged)
|
||||
{
|
||||
MeshFilter equirectMeshFilter = targetCompositionLayer.generatedPreview.GetComponent<MeshFilter>();
|
||||
|
||||
//Generate vertices
|
||||
equirectMeshFilter.mesh = CompositionLayer.MeshGenerationHelper.GenerateEquirectMesh(targetCompositionLayer.hmd, targetCompositionLayer.EquirectRadius);
|
||||
|
||||
targetCompositionLayer.generatedPreview.transform.localPosition = Vector3.zero;
|
||||
targetCompositionLayer.generatedPreview.transform.localRotation = Quaternion.identity;
|
||||
|
||||
targetCompositionLayer.generatedPreview.transform.localScale = targetCompositionLayer.GetNormalizedLocalScale(targetCompositionLayer.transform, Vector3.one);
|
||||
}
|
||||
|
||||
if (targetCompositionLayer.generatedPreview.GetComponent<MeshRenderer>().sharedMaterial.mainTexture != targetCompositionLayer.texture)
|
||||
{
|
||||
targetCompositionLayer.generatedPreview.GetComponent<MeshRenderer>().sharedMaterial.mainTexture = targetCompositionLayer.texture;
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Hide Equirect Preview"))
|
||||
{
|
||||
targetCompositionLayer.isPreviewingEquirect = false;
|
||||
if (targetCompositionLayer.generatedPreview != null)
|
||||
{
|
||||
DestroyImmediate(targetCompositionLayer.generatedPreview);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
targetCompositionLayer.isPreviewingEquirect = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GUILayout.Button("Show Equirect Preview"))
|
||||
{
|
||||
Rect srcRectLeft = FullRect;
|
||||
if (targetCompositionLayer.isCustomRects && targetCompositionLayer.customRects == CompositionLayer.CustomRectsType.LeftRight)
|
||||
srcRectLeft = LeftRightRect;
|
||||
if (targetCompositionLayer.isCustomRects && targetCompositionLayer.customRects == CompositionLayer.CustomRectsType.TopDown)
|
||||
srcRectLeft = TopDownRect;
|
||||
|
||||
targetCompositionLayer.isPreviewingEquirect = true;
|
||||
//Vector3[] cylinderVertices = CompositionLayer.MeshGenerationHelper.GenerateCylinderVertex(targetCompositionLayer.CylinderAngleOfArc, targetCompositionLayer.CylinderRadius, targetCompositionLayer.CylinderHeight);
|
||||
//Add components to Game Object
|
||||
targetCompositionLayer.generatedPreview = new GameObject();
|
||||
targetCompositionLayer.generatedPreview.hideFlags = HideFlags.HideAndDontSave;
|
||||
targetCompositionLayer.generatedPreview.name = CompositionLayer.EquirectPreviewName;
|
||||
targetCompositionLayer.generatedPreview.transform.SetParent(targetCompositionLayer.gameObject.transform);
|
||||
targetCompositionLayer.generatedPreview.transform.localPosition = Vector3.zero;
|
||||
targetCompositionLayer.generatedPreview.transform.localRotation = Quaternion.identity;
|
||||
|
||||
targetCompositionLayer.generatedPreview.transform.localScale = targetCompositionLayer.GetNormalizedLocalScale(targetCompositionLayer.transform, Vector3.one);
|
||||
|
||||
MeshRenderer equirectMeshRenderer = targetCompositionLayer.generatedPreview.AddComponent<MeshRenderer>();
|
||||
MeshFilter equirectMeshFilter = targetCompositionLayer.generatedPreview.AddComponent<MeshFilter>();
|
||||
equirectMeshRenderer.sharedMaterial = new Material(Shader.Find("Unlit/Transparent"));
|
||||
|
||||
if (targetCompositionLayer.texture != null)
|
||||
{
|
||||
equirectMeshRenderer.sharedMaterial.mainTexture = targetCompositionLayer.texture;
|
||||
equirectMeshRenderer.sharedMaterial.mainTextureOffset = srcRectLeft.position;
|
||||
equirectMeshRenderer.sharedMaterial.mainTextureScale = srcRectLeft.size;
|
||||
}
|
||||
|
||||
//Generate Mesh
|
||||
equirectMeshFilter.mesh = CompositionLayer.MeshGenerationHelper.GenerateEquirectMesh(targetCompositionLayer.hmd, targetCompositionLayer.EquirectRadius);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
}
|
||||
if (Property_LayerShape.intValue == (int)CompositionLayer.LayerShape.Cylinder)
|
||||
{
|
||||
if (!FeatureHelpers.GetFeatureWithIdForBuildTarget(BuildTargetGroup.Android, ViveCompositionLayerCylinder.featureId).enabled)
|
||||
{
|
||||
EditorGUILayout.HelpBox("The Composition Layer Cylinder feature is not enabled in OpenXR Settings.\nEnable it to use Cylinder layers.", MessageType.Warning);
|
||||
}
|
||||
|
||||
if (targetCompositionLayer.isPreviewingQuad)
|
||||
{
|
||||
targetCompositionLayer.isPreviewingQuad = false;
|
||||
if (targetCompositionLayer.generatedPreview != null)
|
||||
{
|
||||
DestroyImmediate(targetCompositionLayer.generatedPreview);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetCompositionLayer.isPreviewingEquirect)
|
||||
{
|
||||
targetCompositionLayer.isPreviewingEquirect = false;
|
||||
if (targetCompositionLayer.generatedPreview != null)
|
||||
{
|
||||
DestroyImmediate(targetCompositionLayer.generatedPreview);
|
||||
}
|
||||
}
|
||||
|
||||
Transform generatedQuadTransform = targetCompositionLayer.transform.Find(CompositionLayer.QuadUnderlayMeshName);
|
||||
if (generatedQuadTransform != null)
|
||||
{
|
||||
DestroyImmediate(generatedQuadTransform.gameObject);
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel++;
|
||||
showLayerParams = EditorGUILayout.Foldout(showLayerParams, "Cylinder Parameters");
|
||||
if (showLayerParams)
|
||||
{
|
||||
float radiusLowerBound = Mathf.Max(0.001f, CompositionLayer.CylinderParameterHelper.ArcLengthAndDegAngleOfArcToRadius(targetCompositionLayer.cylinderArcLength, targetCompositionLayer.angleOfArcUpperLimit));
|
||||
float radiusUpperBound = CompositionLayer.CylinderParameterHelper.ArcLengthAndDegAngleOfArcToRadius(targetCompositionLayer.cylinderArcLength, targetCompositionLayer.angleOfArcLowerLimit);
|
||||
EditorGUILayout.HelpBox("Changing the Arc Length will affect the upper and lower bounds of the radius.\nUpper Bound of Radius: " + radiusUpperBound + "\nLower Bound of Radius: " + radiusLowerBound, MessageType.Info);
|
||||
|
||||
EditorGUILayout.PropertyField(Property_CylinderRadius, new GUIContent(Label_CylinderRadius));
|
||||
EditorGUILayout.PropertyField(Property_LockMode, new GUIContent(Label_LockMode));
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
EditorGUILayout.HelpBox("Arc Length and Arc Angle are correlated, adjusting one of them changes the other as well. The Radius will not be changed when adjusting these two values.", MessageType.Info);
|
||||
if (targetCompositionLayer.lockMode == CompositionLayer.CylinderLayerParamLockMode.ArcLength)
|
||||
{
|
||||
GUI.enabled = false;
|
||||
EditorGUILayout.PropertyField(Property_CylinderArcLength, new GUIContent(Label_CylinderArcLength));
|
||||
GUI.enabled = true;
|
||||
EditorGUILayout.Slider(Property_AngleOfArc, targetCompositionLayer.angleOfArcLowerLimit, targetCompositionLayer.angleOfArcUpperLimit, new GUIContent(Label_AngleOfArc));
|
||||
}
|
||||
else if (targetCompositionLayer.lockMode == CompositionLayer.CylinderLayerParamLockMode.ArcAngle)
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property_CylinderArcLength, new GUIContent(Label_CylinderArcLength));
|
||||
GUI.enabled = false;
|
||||
EditorGUILayout.Slider(Property_AngleOfArc, targetCompositionLayer.angleOfArcLowerLimit, targetCompositionLayer.angleOfArcUpperLimit, new GUIContent(Label_AngleOfArc));
|
||||
GUI.enabled = true;
|
||||
}
|
||||
EditorGUILayout.PropertyField(Property_CylinderHeight, new GUIContent(Label_CylinderHeight));
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
CompositionLayer.CylinderLayerParamAdjustmentMode currentAdjustmentMode = targetCompositionLayer.CurrentAdjustmentMode();
|
||||
|
||||
switch (currentAdjustmentMode)
|
||||
{
|
||||
case CompositionLayer.CylinderLayerParamAdjustmentMode.ArcLength:
|
||||
{
|
||||
targetCompositionLayer.CylinderAngleOfArc = CompositionLayer.CylinderParameterHelper.RadiusAndArcLengthToDegAngleOfArc(targetCompositionLayer.CylinderArcLength, targetCompositionLayer.CylinderRadius);
|
||||
float cylinderArcLengthRef = targetCompositionLayer.CylinderArcLength;
|
||||
if (!ArcLengthValidityCheck(ref cylinderArcLengthRef, targetCompositionLayer.CylinderRadius, targetCompositionLayer.angleOfArcLowerLimit, targetCompositionLayer.angleOfArcUpperLimit))
|
||||
{
|
||||
targetCompositionLayer.CylinderArcLength = cylinderArcLengthRef;
|
||||
targetCompositionLayer.CylinderAngleOfArc = CompositionLayer.CylinderParameterHelper.RadiusAndArcLengthToDegAngleOfArc(targetCompositionLayer.CylinderArcLength, targetCompositionLayer.CylinderRadius);
|
||||
}
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
break;
|
||||
}
|
||||
case CompositionLayer.CylinderLayerParamAdjustmentMode.ArcAngle:
|
||||
{
|
||||
targetCompositionLayer.CylinderArcLength = CompositionLayer.CylinderParameterHelper.RadiusAndDegAngleOfArcToArcLength(targetCompositionLayer.CylinderAngleOfArc, targetCompositionLayer.CylinderRadius);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
break;
|
||||
}
|
||||
case CompositionLayer.CylinderLayerParamAdjustmentMode.Radius:
|
||||
default:
|
||||
{
|
||||
float cylinderRadiusRef = targetCompositionLayer.CylinderRadius;
|
||||
RadiusValidityCheck(targetCompositionLayer.CylinderArcLength, ref cylinderRadiusRef, targetCompositionLayer.angleOfArcLowerLimit, targetCompositionLayer.angleOfArcUpperLimit, targetCompositionLayer.lockMode);
|
||||
targetCompositionLayer.CylinderRadius = cylinderRadiusRef;
|
||||
if (targetCompositionLayer.lockMode == CompositionLayer.CylinderLayerParamLockMode.ArcLength)
|
||||
{
|
||||
targetCompositionLayer.CylinderAngleOfArc = CompositionLayer.CylinderParameterHelper.RadiusAndArcLengthToDegAngleOfArc(targetCompositionLayer.CylinderArcLength, targetCompositionLayer.CylinderRadius);
|
||||
float cylinderArcLengthRef = targetCompositionLayer.CylinderArcLength;
|
||||
if (!ArcLengthValidityCheck(ref cylinderArcLengthRef, targetCompositionLayer.CylinderRadius, targetCompositionLayer.angleOfArcLowerLimit, targetCompositionLayer.angleOfArcUpperLimit))
|
||||
{
|
||||
targetCompositionLayer.CylinderArcLength = cylinderArcLengthRef;
|
||||
targetCompositionLayer.CylinderAngleOfArc = CompositionLayer.CylinderParameterHelper.RadiusAndArcLengthToDegAngleOfArc(targetCompositionLayer.CylinderArcLength, targetCompositionLayer.CylinderRadius);
|
||||
}
|
||||
}
|
||||
else if (targetCompositionLayer.lockMode == CompositionLayer.CylinderLayerParamLockMode.ArcAngle)
|
||||
{
|
||||
targetCompositionLayer.CylinderArcLength = CompositionLayer.CylinderParameterHelper.RadiusAndDegAngleOfArcToArcLength(targetCompositionLayer.CylinderAngleOfArc, targetCompositionLayer.CylinderRadius);
|
||||
}
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.HelpBox("Current Layer Aspect Ratio (Arc Length : Height) = " + targetCompositionLayer.CylinderArcLength + " : " + targetCompositionLayer.CylinderHeight, MessageType.Info);
|
||||
|
||||
Vector3 CompositionLayerScale = targetCompositionLayer.gameObject.transform.localScale;
|
||||
bool CylinderParamsChanged = targetCompositionLayer.LayerDimensionsChanged();
|
||||
|
||||
if (targetCompositionLayer.isPreviewingCylinder)
|
||||
{
|
||||
|
||||
Transform generatedPreviewTransform = targetCompositionLayer.transform.Find(CompositionLayer.CylinderPreviewName);
|
||||
|
||||
if (generatedPreviewTransform != null)
|
||||
{
|
||||
targetCompositionLayer.generatedPreview = generatedPreviewTransform.gameObject;
|
||||
|
||||
if (CylinderParamsChanged)
|
||||
{
|
||||
//Generate vertices
|
||||
Vector3[] cylinderVertices = CompositionLayer.MeshGenerationHelper.GenerateCylinderVertex(targetCompositionLayer.CylinderAngleOfArc, targetCompositionLayer.CylinderRadius, targetCompositionLayer.CylinderHeight);;
|
||||
|
||||
MeshFilter cylinderMeshFilter = targetCompositionLayer.generatedPreview.GetComponent<MeshFilter>();
|
||||
//Generate Mesh
|
||||
cylinderMeshFilter.mesh = CompositionLayer.MeshGenerationHelper.GenerateCylinderMesh(targetCompositionLayer.CylinderAngleOfArc, cylinderVertices);
|
||||
|
||||
targetCompositionLayer.generatedPreview.transform.localPosition = Vector3.zero;
|
||||
targetCompositionLayer.generatedPreview.transform.localRotation = Quaternion.identity;
|
||||
|
||||
targetCompositionLayer.generatedPreview.transform.localScale = targetCompositionLayer.GetNormalizedLocalScale(targetCompositionLayer.transform, Vector3.one);
|
||||
}
|
||||
|
||||
if (targetCompositionLayer.generatedPreview.GetComponent<MeshRenderer>().sharedMaterial.mainTexture != targetCompositionLayer.texture)
|
||||
{
|
||||
targetCompositionLayer.generatedPreview.GetComponent<MeshRenderer>().sharedMaterial.mainTexture = targetCompositionLayer.texture;
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Hide Cylinder Preview"))
|
||||
{
|
||||
targetCompositionLayer.isPreviewingCylinder = false;
|
||||
if (targetCompositionLayer.generatedPreview != null)
|
||||
{
|
||||
DestroyImmediate(targetCompositionLayer.generatedPreview);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
targetCompositionLayer.isPreviewingCylinder = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GUILayout.Button("Show Cylinder Preview"))
|
||||
{
|
||||
Rect srcRectLeft = FullRect;
|
||||
if (targetCompositionLayer.isCustomRects && targetCompositionLayer.customRects == CompositionLayer.CustomRectsType.LeftRight)
|
||||
srcRectLeft = LeftRightRect;
|
||||
if (targetCompositionLayer.isCustomRects && targetCompositionLayer.customRects == CompositionLayer.CustomRectsType.TopDown)
|
||||
srcRectLeft = TopDownRect;
|
||||
|
||||
targetCompositionLayer.isPreviewingCylinder = true;
|
||||
Vector3[] cylinderVertices = CompositionLayer.MeshGenerationHelper.GenerateCylinderVertex(targetCompositionLayer.CylinderAngleOfArc, targetCompositionLayer.CylinderRadius, targetCompositionLayer.CylinderHeight);
|
||||
//Add components to Game Object
|
||||
targetCompositionLayer.generatedPreview = new GameObject();
|
||||
targetCompositionLayer.generatedPreview.hideFlags = HideFlags.HideAndDontSave;
|
||||
targetCompositionLayer.generatedPreview.name = CompositionLayer.CylinderPreviewName;
|
||||
targetCompositionLayer.generatedPreview.transform.SetParent(targetCompositionLayer.gameObject.transform);
|
||||
targetCompositionLayer.generatedPreview.transform.localPosition = Vector3.zero;
|
||||
targetCompositionLayer.generatedPreview.transform.localRotation = Quaternion.identity;
|
||||
|
||||
targetCompositionLayer.generatedPreview.transform.localScale = targetCompositionLayer.GetNormalizedLocalScale(targetCompositionLayer.transform, Vector3.one);
|
||||
|
||||
MeshRenderer cylinderMeshRenderer = targetCompositionLayer.generatedPreview.AddComponent<MeshRenderer>();
|
||||
MeshFilter cylinderMeshFilter = targetCompositionLayer.generatedPreview.AddComponent<MeshFilter>();
|
||||
cylinderMeshRenderer.sharedMaterial = new Material(Shader.Find("Unlit/Transparent"));
|
||||
|
||||
if (targetCompositionLayer.texture != null)
|
||||
{
|
||||
cylinderMeshRenderer.sharedMaterial.mainTexture = targetCompositionLayer.texture;
|
||||
cylinderMeshRenderer.sharedMaterial.mainTextureOffset = srcRectLeft.position;
|
||||
cylinderMeshRenderer.sharedMaterial.mainTextureScale = srcRectLeft.size;
|
||||
}
|
||||
|
||||
//Generate Mesh
|
||||
cylinderMeshFilter.mesh = CompositionLayer.MeshGenerationHelper.GenerateCylinderMesh(targetCompositionLayer.CylinderAngleOfArc, cylinderVertices);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.Space(10);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
else if (Property_LayerShape.intValue == (int)CompositionLayer.LayerShape.Quad)
|
||||
{
|
||||
if (targetCompositionLayer.isPreviewingCylinder)
|
||||
{
|
||||
targetCompositionLayer.isPreviewingCylinder = false;
|
||||
if (targetCompositionLayer.generatedPreview != null)
|
||||
{
|
||||
DestroyImmediate(targetCompositionLayer.generatedPreview);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetCompositionLayer.isPreviewingEquirect)
|
||||
{
|
||||
targetCompositionLayer.isPreviewingEquirect = false;
|
||||
if (targetCompositionLayer.generatedPreview != null)
|
||||
{
|
||||
DestroyImmediate(targetCompositionLayer.generatedPreview);
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel++;
|
||||
showLayerParams = EditorGUILayout.Foldout(showLayerParams, "Quad Parameters");
|
||||
if (showLayerParams)
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property_QuadWidth, new GUIContent(Label_QuadWidth));
|
||||
EditorGUILayout.PropertyField(Property_QuadHeight, new GUIContent(Label_QuadHeight));
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
EditorGUILayout.HelpBox("Current Layer Aspect Ratio (Width : Height) = " + targetCompositionLayer.quadWidth + " : " + targetCompositionLayer.quadHeight, MessageType.Info);
|
||||
|
||||
Vector3 CompositionLayerScale = targetCompositionLayer.gameObject.transform.localScale;
|
||||
bool QuadParamsChanged = targetCompositionLayer.LayerDimensionsChanged();
|
||||
if (targetCompositionLayer.isPreviewingQuad)
|
||||
{
|
||||
Transform generatedPreviewTransform = targetCompositionLayer.transform.Find(CompositionLayer.QuadPreviewName);
|
||||
|
||||
if (generatedPreviewTransform != null)
|
||||
{
|
||||
targetCompositionLayer.generatedPreview = generatedPreviewTransform.gameObject;
|
||||
|
||||
if (QuadParamsChanged)
|
||||
{
|
||||
//Generate vertices
|
||||
Vector3[] quadVertices = CompositionLayer.MeshGenerationHelper.GenerateQuadVertex(targetCompositionLayer.quadWidth, targetCompositionLayer.quadHeight);
|
||||
|
||||
MeshFilter quadMeshFilter = targetCompositionLayer.generatedPreview.GetComponent<MeshFilter>();
|
||||
//Generate Mesh
|
||||
quadMeshFilter.mesh = CompositionLayer.MeshGenerationHelper.GenerateQuadMesh(quadVertices);
|
||||
|
||||
targetCompositionLayer.generatedPreview.transform.localPosition = Vector3.zero;
|
||||
targetCompositionLayer.generatedPreview.transform.localRotation = Quaternion.identity;
|
||||
|
||||
targetCompositionLayer.generatedPreview.transform.localScale = targetCompositionLayer.GetNormalizedLocalScale(targetCompositionLayer.transform, Vector3.one);
|
||||
}
|
||||
|
||||
if (targetCompositionLayer.generatedPreview.GetComponent<MeshRenderer>().sharedMaterial.mainTexture != targetCompositionLayer.texture)
|
||||
{
|
||||
targetCompositionLayer.generatedPreview.GetComponent<MeshRenderer>().sharedMaterial.mainTexture = targetCompositionLayer.texture;
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Hide Quad Preview"))
|
||||
{
|
||||
targetCompositionLayer.isPreviewingQuad = false;
|
||||
if (targetCompositionLayer.generatedPreview != null)
|
||||
{
|
||||
DestroyImmediate(targetCompositionLayer.generatedPreview);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
targetCompositionLayer.isPreviewingQuad = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GUILayout.Button("Show Quad Preview"))
|
||||
{
|
||||
Rect srcRectLeft = FullRect;
|
||||
if (targetCompositionLayer.isCustomRects && targetCompositionLayer.customRects == CompositionLayer.CustomRectsType.LeftRight)
|
||||
srcRectLeft = LeftRightRect;
|
||||
if (targetCompositionLayer.isCustomRects && targetCompositionLayer.customRects == CompositionLayer.CustomRectsType.TopDown)
|
||||
srcRectLeft = TopDownRect;
|
||||
|
||||
targetCompositionLayer.isPreviewingQuad = true;
|
||||
//Generate vertices
|
||||
Vector3[] quadVertices = CompositionLayer.MeshGenerationHelper.GenerateQuadVertex(targetCompositionLayer.quadWidth, targetCompositionLayer.quadHeight);
|
||||
|
||||
//Add components to Game Object
|
||||
targetCompositionLayer.generatedPreview = new GameObject();
|
||||
targetCompositionLayer.generatedPreview.hideFlags = HideFlags.HideAndDontSave;
|
||||
targetCompositionLayer.generatedPreview.name = CompositionLayer.QuadPreviewName;
|
||||
targetCompositionLayer.generatedPreview.transform.SetParent(targetCompositionLayer.gameObject.transform);
|
||||
targetCompositionLayer.generatedPreview.transform.localPosition = Vector3.zero;
|
||||
targetCompositionLayer.generatedPreview.transform.localRotation = Quaternion.identity;
|
||||
|
||||
targetCompositionLayer.generatedPreview.transform.localScale = targetCompositionLayer.GetNormalizedLocalScale(targetCompositionLayer.transform, Vector3.one);
|
||||
|
||||
MeshRenderer quadMeshRenderer = targetCompositionLayer.generatedPreview.AddComponent<MeshRenderer>();
|
||||
MeshFilter quadMeshFilter = targetCompositionLayer.generatedPreview.AddComponent<MeshFilter>();
|
||||
quadMeshRenderer.sharedMaterial = new Material(Shader.Find("Unlit/Transparent"));
|
||||
|
||||
if (targetCompositionLayer.texture != null)
|
||||
{
|
||||
quadMeshRenderer.sharedMaterial.mainTexture = targetCompositionLayer.texture;
|
||||
quadMeshRenderer.sharedMaterial.mainTextureOffset = srcRectLeft.position;
|
||||
quadMeshRenderer.sharedMaterial.mainTextureScale = srcRectLeft.size;
|
||||
}
|
||||
//Generate Mesh
|
||||
quadMeshFilter.mesh = CompositionLayer.MeshGenerationHelper.GenerateQuadMesh(quadVertices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Rect UI For textures
|
||||
Rect labelRect = EditorGUILayout.GetControlRect();
|
||||
|
||||
EditorGUI.LabelField(new Rect(labelRect.x, labelRect.y, labelRect.width / 2, labelRect.height), new GUIContent("Left Texture", "Texture used for the left eye"));
|
||||
EditorGUI.LabelField(new Rect(labelRect.x + labelRect.width / 2, labelRect.y, labelRect.width / 2, labelRect.height), new GUIContent("Right Texture", "Texture used for the right eye"));
|
||||
|
||||
Rect textureRect = EditorGUILayout.GetControlRect(GUILayout.Height(64));
|
||||
|
||||
targetCompositionLayer.texture = (Texture)EditorGUI.ObjectField(new Rect(textureRect.x, textureRect.y, 64, textureRect.height), targetCompositionLayer.texture, typeof(Texture), true);
|
||||
targetCompositionLayer.textureRight = (Texture)EditorGUI.ObjectField(new Rect(textureRect.x + textureRect.width / 2, textureRect.y, 64, textureRect.height), targetCompositionLayer.textureRight, typeof(Texture), true);
|
||||
if (null == targetCompositionLayer.textureLeft)
|
||||
{
|
||||
targetCompositionLayer.texture = targetCompositionLayer.textureRight;
|
||||
//myScript.textures[1] = right;
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(Property_LayerVisibility, new GUIContent(Label_LayerVisibility));
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
EditorGUILayout.PropertyField(Property_IsDynamicLayer, Label_IsDynamicLayer);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
//EditorGUILayout.PropertyField(Property_isExternalSurface, Label_isExternalSurface);
|
||||
//serializedObject.ApplyModifiedProperties();
|
||||
|
||||
//if (targetCompositionLayer.isExternalSurface)
|
||||
/*if (false)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
showExternalSurfaceParams = EditorGUILayout.Foldout(showExternalSurfaceParams, "External Surface Parameters");
|
||||
if (showExternalSurfaceParams)
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property_ExternalSurfaceWidth, Label_ExternalSurfaceWidth);
|
||||
EditorGUILayout.PropertyField(Property_ExternalSurfaceHeight, Label_ExternalSurfaceHeight);
|
||||
EditorGUILayout.PropertyField(Property_IsProtectedSurface, Label_IsProtectedSurface);
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
}*/
|
||||
|
||||
if((Property_LayerShape.intValue != (int)CompositionLayer.LayerShape.Equirect && Property_LayerShape.intValue != (int)CompositionLayer.LayerShape.Equirect2) && (targetCompositionLayer.textureLeft == targetCompositionLayer.textureRight || targetCompositionLayer.textureRight == null))
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property_IsCustomRects, Label_IsCustomRects);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
if (targetCompositionLayer.isCustomRects)
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property_CustomRects, new GUIContent(Label_CustomRects));
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.PropertyField(Property_ApplyColorScaleBias, Label_ApplyColorScaleBias);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
if (targetCompositionLayer.applyColorScaleBias)
|
||||
{
|
||||
if(!FeatureHelpers.GetFeatureWithIdForBuildTarget(BuildTargetGroup.Android, ViveCompositionLayerColorScaleBias.featureId).enabled)
|
||||
{
|
||||
EditorGUILayout.HelpBox("The Color Scale Bias feature is not enabled in OpenXR Settings.", MessageType.Warning);
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel++;
|
||||
if (targetCompositionLayer.layerType == CompositionLayer.LayerType.Underlay)
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property_SolidEffect, Label_SolidEffect);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
showColorScaleBiasParams = EditorGUILayout.Foldout(showColorScaleBiasParams, "Color Scale Bias Parameters");
|
||||
if (showColorScaleBiasParams)
|
||||
{
|
||||
|
||||
EditorGUILayout.PropertyField(Property_ColorScale, Label_ColorScale);
|
||||
EditorGUILayout.PropertyField(Property_ColorBias, Label_ColorBias);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
ViveCompositionLayer compositionLayerFeature = (ViveCompositionLayer)FeatureHelpers.GetFeatureWithIdForBuildTarget(BuildTargetGroup.Android, ViveCompositionLayer.featureId);
|
||||
|
||||
if (compositionLayerFeature != null && compositionLayerFeature.enableAutoFallback)
|
||||
{
|
||||
EditorGUILayout.PropertyField(Property_RenderPriority, new GUIContent(Label_RenderPriority));
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(Property_TrackingOrigin, Label_TrackingOrigin);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
public static bool RadiusValidityCheck(float inArcLength, ref float inRadius, float thetaLowerLimit, float thetaUpperLimit, CompositionLayer.CylinderLayerParamLockMode lockMode)
|
||||
{
|
||||
bool isValid = true;
|
||||
|
||||
if (inRadius <= 0)
|
||||
{
|
||||
inRadius = CompositionLayer.CylinderParameterHelper.ArcLengthAndDegAngleOfArcToRadius(inArcLength, thetaUpperLimit);
|
||||
isValid = false;
|
||||
return isValid;
|
||||
}
|
||||
|
||||
float degThetaResult = CompositionLayer.CylinderParameterHelper.RadiusAndArcLengthToDegAngleOfArc(inArcLength, inRadius);
|
||||
|
||||
if (degThetaResult < thetaLowerLimit)
|
||||
{
|
||||
if (lockMode == CompositionLayer.CylinderLayerParamLockMode.ArcAngle) //Angle locked, increase arc length
|
||||
{
|
||||
ArcLengthValidityCheck(ref inArcLength, inRadius, thetaLowerLimit, thetaUpperLimit);
|
||||
inRadius = CompositionLayer.CylinderParameterHelper.ArcLengthAndDegAngleOfArcToRadius(inArcLength, thetaLowerLimit);
|
||||
}
|
||||
else if (lockMode == CompositionLayer.CylinderLayerParamLockMode.ArcLength) //ArcLength Locked, keep angle at min
|
||||
{
|
||||
inRadius = CompositionLayer.CylinderParameterHelper.ArcLengthAndDegAngleOfArcToRadius(inArcLength, thetaLowerLimit);
|
||||
}
|
||||
isValid = false;
|
||||
}
|
||||
else if (degThetaResult > thetaUpperLimit)
|
||||
{
|
||||
if (lockMode == CompositionLayer.CylinderLayerParamLockMode.ArcAngle) //Angle locked, decrease arc length
|
||||
{
|
||||
ArcLengthValidityCheck(ref inArcLength, inRadius, thetaLowerLimit, thetaUpperLimit);
|
||||
inRadius = CompositionLayer.CylinderParameterHelper.ArcLengthAndDegAngleOfArcToRadius(inArcLength, thetaUpperLimit);
|
||||
}
|
||||
else if (lockMode == CompositionLayer.CylinderLayerParamLockMode.ArcLength) //ArcLength Locked, keep angle at max
|
||||
{
|
||||
inRadius = CompositionLayer.CylinderParameterHelper.ArcLengthAndDegAngleOfArcToRadius(inArcLength, thetaUpperLimit);
|
||||
}
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
public static bool ArcLengthValidityCheck(ref float inArcLength, float inRadius, float thetaLowerLimit, float thetaUpperLimit)
|
||||
{
|
||||
bool isValid = true;
|
||||
|
||||
if (inArcLength <= 0)
|
||||
{
|
||||
inArcLength = CompositionLayer.CylinderParameterHelper.RadiusAndDegAngleOfArcToArcLength(thetaLowerLimit, inRadius);
|
||||
isValid = false;
|
||||
return isValid;
|
||||
}
|
||||
|
||||
float degThetaResult = CompositionLayer.CylinderParameterHelper.RadiusAndArcLengthToDegAngleOfArc(inArcLength, inRadius);
|
||||
|
||||
if (degThetaResult < thetaLowerLimit)
|
||||
{
|
||||
inArcLength = CompositionLayer.CylinderParameterHelper.RadiusAndDegAngleOfArcToArcLength(thetaLowerLimit, inRadius);
|
||||
isValid = false;
|
||||
}
|
||||
else if (degThetaResult > thetaUpperLimit)
|
||||
{
|
||||
inArcLength = CompositionLayer.CylinderParameterHelper.RadiusAndDegAngleOfArcToArcLength(thetaUpperLimit, inRadius);
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a99cc2a2471f1e7499276e561bbb8d1e
|
||||
guid: ec04348c6d3a8ce43ada545a76766344
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -0,0 +1,308 @@
|
||||
// "VIVE SDK
|
||||
// © 2020 HTC Corporation. All Rights Reserved.
|
||||
//
|
||||
// Unless otherwise required by copyright law and practice,
|
||||
// upon the execution of HTC SDK license agreement,
|
||||
// HTC grants you access to and use of the VIVE SDK(s).
|
||||
// You shall fully comply with all of HTC’s SDK license agreement terms and
|
||||
// conditions signed by you and all SDK and API requirements,
|
||||
// specifications, and documentation provided by HTC to You."
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
namespace VIVE.OpenXR.CompositionLayer.Editor
|
||||
{
|
||||
using UnityEditor;
|
||||
using UnityEngine.UI;
|
||||
|
||||
[CustomEditor(typeof(CompositionLayerUICanvas))]
|
||||
public class CompositionLayerUICanvasEditor : Editor
|
||||
{
|
||||
static string PropertyName_MaxRenderTextureSize = "maxRenderTextureSize";
|
||||
static GUIContent Label_MaxRenderTextureSize = new GUIContent("Max Render Texture Size", "Maximum render texture dimension. e.g. If maxRenderTextureSize is 1024, the render texture dimensions of a canvas with an Aspect Ratio of 2:1 will be 1024 x 512.");
|
||||
SerializedProperty Property_MaxRenderTextureSize;
|
||||
|
||||
static string PropertyName_LayerType = "layerType";
|
||||
static GUIContent Label_LayerType = new GUIContent("Layer Type", "Overlays render on top of all in-game objects.\nUnderlays can be occluded by in-game objects but may introduce alpha blending issues with transparent objects.");
|
||||
SerializedProperty Property_LayerType;
|
||||
|
||||
static string PropertyName_LayerVisibility = "layerVisibility";
|
||||
static GUIContent Label_LayerVisibility = new GUIContent("Visibility", "Specify the visibility of the layer.");
|
||||
SerializedProperty Property_LayerVisibility;
|
||||
|
||||
static string PropertyName_CameraBGColor = "cameraBGColor";
|
||||
static GUIContent Label_CameraBGColor = new GUIContent("Camera Background Color", "Background color of the camera for rendering the Canvas to the render texture target.\nChanging this option will affect the tint of the final image of the Canvas if no background gameobject is assigned.");
|
||||
SerializedProperty Property_CameraBGColor;
|
||||
|
||||
static string PropertyName_BackgroundGO = "backgroundGO";
|
||||
static GUIContent Label_BackgroundGO = new GUIContent("Background GameObject", "GameObject that contains a UI Component and will be used as the background of the Canvas.\nWhen succesfully assigned, the area which the background UI component covers will no longer be affected by the background color of the camera.");
|
||||
SerializedProperty Property_BackgroundGO;
|
||||
|
||||
static string PropertyName_EnableAlphaBlendingCorrection = "enableAlphaBlendingCorrection";
|
||||
static GUIContent Label_EnableAlphaBlendingCorrection = new GUIContent("Enable Alpha Blending Correction", "Enable this option if transparent UI elements are rendering darker than expected in an overall sense.\nNote that enabling this option will consume more resources.");
|
||||
SerializedProperty Property_EnableAlphaBlendingCorrection;
|
||||
|
||||
static string PropertyName_CompositionDepth = "compositionDepth";
|
||||
static GUIContent Label_CompositionDepth = new GUIContent("Composition Depth", "Specify Layer Composition Depth.");
|
||||
SerializedProperty Property_CompositionDepth;
|
||||
|
||||
static string PropertyName_RenderPriority = "renderPriority";
|
||||
static GUIContent Label_RenderPriority = new GUIContent("Render Priority", "When Auto Fallback is enabled, layers with a higher render priority will be rendered as normal layers first.");
|
||||
SerializedProperty Property_RenderPriority;
|
||||
|
||||
static string PropertyName_TrackingOrigin = "trackingOrigin";
|
||||
static GUIContent Label_TrackingOrigin = new GUIContent("Tracking Origin", "Assign the tracking origin here to offset the pose of the Composition Layer.");
|
||||
SerializedProperty Property_TrackingOrigin;
|
||||
|
||||
bool isCurrentBackgroundGOValid = true, isMaterialReplaced = true, backgroundUINotFoundError = false, backgroundObjectNotChildError = false;
|
||||
List<GameObject> validbackgroundGO;
|
||||
|
||||
private const string layerNameString = "CompositionLayerUICanvas";
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
//Check if current selected layer is rendered by main camera
|
||||
|
||||
if (Property_MaxRenderTextureSize == null) Property_MaxRenderTextureSize = serializedObject.FindProperty(PropertyName_MaxRenderTextureSize);
|
||||
if (Property_LayerType == null) Property_LayerType = serializedObject.FindProperty(PropertyName_LayerType);
|
||||
if (Property_LayerVisibility == null) Property_LayerVisibility = serializedObject.FindProperty(PropertyName_LayerVisibility);
|
||||
if (Property_CameraBGColor == null) Property_CameraBGColor = serializedObject.FindProperty(PropertyName_CameraBGColor);
|
||||
if (Property_BackgroundGO == null) Property_BackgroundGO = serializedObject.FindProperty(PropertyName_BackgroundGO);
|
||||
if (Property_EnableAlphaBlendingCorrection == null) Property_EnableAlphaBlendingCorrection = serializedObject.FindProperty(PropertyName_EnableAlphaBlendingCorrection);
|
||||
if (Property_CompositionDepth == null) Property_CompositionDepth = serializedObject.FindProperty(PropertyName_CompositionDepth);
|
||||
if (Property_RenderPriority == null) Property_RenderPriority = serializedObject.FindProperty(PropertyName_RenderPriority);
|
||||
if (Property_TrackingOrigin == null) Property_TrackingOrigin = serializedObject.FindProperty(PropertyName_TrackingOrigin);
|
||||
|
||||
|
||||
CompositionLayerUICanvas targetLayerCanvasUI = target as CompositionLayerUICanvas;
|
||||
|
||||
Graphic[] graphicComponents = targetLayerCanvasUI.GetComponentsInChildren<Graphic>();
|
||||
|
||||
EditorGUILayout.HelpBox("CompositionLayerUICanvas will automatically generate the components necessary for rendering UI Canvas(es) with CompositionLayer(s).", MessageType.Info);
|
||||
|
||||
EditorGUILayout.PropertyField(Property_MaxRenderTextureSize, Label_MaxRenderTextureSize);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
EditorGUILayout.PropertyField(Property_LayerType, Label_LayerType);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
if (targetLayerCanvasUI.layerType == CompositionLayer.LayerType.Underlay)
|
||||
{
|
||||
EditorGUILayout.HelpBox("When using Underlay, overlapping non-opaque canvas elements (i.e. elements with alpha value < 1) might look different during runtime due to inherent alpha blending limitations.\n", MessageType.Warning);
|
||||
EditorGUILayout.PropertyField(Property_EnableAlphaBlendingCorrection, Label_EnableAlphaBlendingCorrection);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
else
|
||||
{
|
||||
targetLayerCanvasUI.enableAlphaBlendingCorrection = false;
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(Property_LayerVisibility, new GUIContent(Label_LayerVisibility));
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
if (isCurrentBackgroundGOValid) //Cache valid result
|
||||
{
|
||||
validbackgroundGO = new List<GameObject>();
|
||||
foreach (GameObject backgroundGO in targetLayerCanvasUI.backgroundGO)
|
||||
{
|
||||
validbackgroundGO.Add(backgroundGO);
|
||||
}
|
||||
}
|
||||
|
||||
List<GameObject> prevBackgroundGO = new List<GameObject>();
|
||||
foreach (GameObject backgroundGO in targetLayerCanvasUI.backgroundGO)
|
||||
{
|
||||
prevBackgroundGO.Add(backgroundGO);
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(Property_BackgroundGO, Label_BackgroundGO);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
bool needMaterialReplacement = false;
|
||||
|
||||
if (targetLayerCanvasUI.backgroundGO != null)
|
||||
{
|
||||
List<Graphic> backgroundGraphics = new List<Graphic>();
|
||||
|
||||
foreach (GameObject backgroundGO in targetLayerCanvasUI.backgroundGO)
|
||||
{
|
||||
if (backgroundGO == null) continue;
|
||||
|
||||
backgroundGraphics.Add(backgroundGO.GetComponent<Graphic>());
|
||||
}
|
||||
|
||||
bool backgroundGraphicIsInChild = false;
|
||||
if (backgroundGraphics.Count > 0)
|
||||
{
|
||||
foreach (Graphic backgroundGraphic in backgroundGraphics) //Loop through graphic components of selected background objects
|
||||
{
|
||||
if (backgroundGraphic != null)
|
||||
{
|
||||
backgroundUINotFoundError = false;
|
||||
foreach (Graphic graphicComponent in graphicComponents) //Loop through graphic components under current canvas
|
||||
{
|
||||
if (graphicComponent == backgroundGraphic)
|
||||
{
|
||||
backgroundGraphicIsInChild = true;
|
||||
backgroundObjectNotChildError = false;
|
||||
break;
|
||||
}
|
||||
backgroundGraphicIsInChild = false;
|
||||
}
|
||||
|
||||
if (!backgroundGraphicIsInChild) //Triggers when one of the selected objects is invalid
|
||||
{
|
||||
backgroundObjectNotChildError = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
backgroundUINotFoundError = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!backgroundUINotFoundError && !backgroundObjectNotChildError)
|
||||
{
|
||||
isCurrentBackgroundGOValid = true;
|
||||
foreach (GameObject backgroundGOCurr in targetLayerCanvasUI.backgroundGO)
|
||||
{
|
||||
if (backgroundGOCurr == null) continue;
|
||||
|
||||
if (!prevBackgroundGO.Contains(backgroundGOCurr)) //Needs material replacement
|
||||
{
|
||||
needMaterialReplacement = true;
|
||||
isMaterialReplaced = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
EditorGUILayout.HelpBox("The blending mode of the background UI shader will be changed in order to ignore the background color of the camera.", MessageType.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
isCurrentBackgroundGOValid = false;
|
||||
if (backgroundUINotFoundError)
|
||||
{
|
||||
EditorGUILayout.HelpBox("The background object you are trying to assign does not contain a UI Component.", MessageType.Error);
|
||||
}
|
||||
|
||||
if (backgroundObjectNotChildError)
|
||||
{
|
||||
EditorGUILayout.HelpBox("The background object you are trying to assign is not under the current Canvas.", MessageType.Error);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Revert Background GameObjects"))
|
||||
{
|
||||
targetLayerCanvasUI.backgroundGO = validbackgroundGO;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(Property_CameraBGColor, Label_CameraBGColor);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
//Check the material config of the UI elements
|
||||
foreach (Graphic graphicComponent in graphicComponents)
|
||||
{
|
||||
if (graphicComponent.material == null || graphicComponent.material == graphicComponent.defaultMaterial)
|
||||
{
|
||||
needMaterialReplacement = true;
|
||||
isMaterialReplaced = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (needMaterialReplacement || !isMaterialReplaced)
|
||||
{
|
||||
EditorGUILayout.HelpBox("The current material configurations of the UI elements will lead to incorrect alpha blending.\n" +
|
||||
"Replace the materials to yield better visual results.", MessageType.Error);
|
||||
|
||||
if (GUILayout.Button("Replace UI Materials"))
|
||||
{
|
||||
targetLayerCanvasUI.ReplaceUIMaterials();
|
||||
isMaterialReplaced = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Check if current selected layer is rendered by main camera
|
||||
if (Camera.main != null)
|
||||
{
|
||||
if ((Camera.main.cullingMask & (1 << targetLayerCanvasUI.gameObject.layer)) != 0)
|
||||
{
|
||||
EditorGUILayout.HelpBox("Currently selected layer: " + LayerMask.LayerToName(targetLayerCanvasUI.gameObject.layer) + "\nThis layer is not culled by the Main Camera.\nSelect a layer that will not be rendered by the Main Camera and apply it to all child objects.", MessageType.Error);
|
||||
|
||||
//TODO: Add Auto Layer button
|
||||
if (GUILayout.Button("Auto Select Layer"))
|
||||
{
|
||||
// Open tag manager
|
||||
SerializedObject tagManager = new SerializedObject(AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/TagManager.asset")[0]);
|
||||
// Layers Property
|
||||
SerializedProperty layersProp = tagManager.FindProperty("layers");
|
||||
|
||||
//Check if the layer CompositionLayerUICanvas exists
|
||||
bool layerExists = false, firstEmptyLayerFound = false;
|
||||
int emptyLayerIndex = 0;
|
||||
for (int i = 0; i < layersProp.arraySize; i++)
|
||||
{
|
||||
if (layersProp.GetArrayElementAtIndex(i).stringValue == layerNameString)
|
||||
{
|
||||
layerExists = true;
|
||||
ApplyLayerToGameObjectRecursive(targetLayerCanvasUI.gameObject, i);
|
||||
break;
|
||||
}
|
||||
else if (layersProp.GetArrayElementAtIndex(i).stringValue == "")
|
||||
{
|
||||
if (!firstEmptyLayerFound) //Remember the index of the first empty layer
|
||||
{
|
||||
firstEmptyLayerFound = true;
|
||||
emptyLayerIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!layerExists) //Create layer and apply it
|
||||
{
|
||||
layersProp.GetArrayElementAtIndex(emptyLayerIndex).stringValue = layerNameString;
|
||||
|
||||
ApplyLayerToGameObjectRecursive(targetLayerCanvasUI.gameObject, emptyLayerIndex);
|
||||
|
||||
tagManager.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.HelpBox("Main Camera not found, and hence cannot confirm the status of its Culling Mask.\nMake sure that the Main Camera does not draw the " + LayerMask.LayerToName(targetLayerCanvasUI.gameObject.layer) + " layer." , MessageType.Warning);
|
||||
}
|
||||
|
||||
|
||||
EditorGUILayout.PropertyField(Property_CompositionDepth, Label_CompositionDepth);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
EditorGUILayout.PropertyField(Property_RenderPriority, Label_RenderPriority);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
EditorGUILayout.PropertyField(Property_TrackingOrigin, Label_TrackingOrigin);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
private void ApplyLayerToGameObjectRecursive(GameObject targetGO, int layerID)
|
||||
{
|
||||
if (targetGO.transform.childCount > 0)
|
||||
{
|
||||
for (int i=0; i<targetGO.transform.childCount; i++)
|
||||
{
|
||||
ApplyLayerToGameObjectRecursive(targetGO.transform.GetChild(i).gameObject, layerID);
|
||||
}
|
||||
}
|
||||
|
||||
targetGO.layer = layerID;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 03f67eb290fa9f3468b94c84f9f50e84
|
||||
guid: 222aadbc313466a41bafc2f46013fe3d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -1,34 +0,0 @@
|
||||
using UnityEditor;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
|
||||
namespace HTC.Vive.OpenXR.Editor
|
||||
{
|
||||
[OpenXRFeatureSet(
|
||||
FeatureSetId = featureSetId,
|
||||
FeatureIds = new string[]
|
||||
{
|
||||
"com.htc.openxr.sceneunderstanding.feature",
|
||||
"com.htc.openxr.facialtracking.feature",
|
||||
"com.htc.openxr.feature.input.htcvivecosmos",
|
||||
"com.company.openxr.handtracking.feature",
|
||||
"com.htc.openxr.feature.input.htcvivefocus3",
|
||||
"com.htc.openxr.feature.input.htcvivehandinteraction"
|
||||
},
|
||||
DefaultFeatureIds = new string[]
|
||||
{
|
||||
"com.htc.openxr.sceneunderstanding.feature",
|
||||
"com.htc.openxr.facialtracking.feature",
|
||||
"com.htc.openxr.feature.input.htcvivecosmos",
|
||||
"com.company.openxr.handtracking.feature",
|
||||
"com.htc.openxr.feature.input.htcvivefocus3",
|
||||
"com.htc.openxr.feature.input.htcvivehandinteraction"
|
||||
},
|
||||
UiName = "VIVE OpenXR",
|
||||
Description = "Enable the full suite of features for Vive OpenXR.",
|
||||
SupportedBuildTargets = new BuildTargetGroup[] { BuildTargetGroup.Standalone }
|
||||
)]
|
||||
sealed class VIVEFeatureSet
|
||||
{
|
||||
internal const string featureSetId = "com.HTC.openxr.featureset.vive";
|
||||
}
|
||||
}
|
||||
166
com.htc.upm.vive.openxr/Editor/PackageManagerHelper.cs
Normal file
166
com.htc.upm.vive.openxr/Editor/PackageManagerHelper.cs
Normal file
@@ -0,0 +1,166 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
|
||||
using UnityEditor.PackageManager;
|
||||
using UnityEditor.PackageManager.Requests;
|
||||
using UnityEngine;
|
||||
|
||||
public static class PackageManagerHelper
|
||||
{
|
||||
private static bool s_wasPreparing;
|
||||
private static bool m_wasAdded;
|
||||
private static bool s_wasRemoved;
|
||||
private static ListRequest m_listRequest;
|
||||
private static AddRequest m_addRequest;
|
||||
private static RemoveRequest m_removeRequest;
|
||||
private static string s_fallbackIdentifier;
|
||||
|
||||
public static bool isPreparingList
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_listRequest == null) { return s_wasPreparing = true; }
|
||||
|
||||
switch (m_listRequest.Status)
|
||||
{
|
||||
case StatusCode.InProgress:
|
||||
return s_wasPreparing = true;
|
||||
case StatusCode.Failure:
|
||||
if (!s_wasPreparing)
|
||||
{
|
||||
Debug.LogError("Something wrong when adding package to list. error:" + m_listRequest.Error.errorCode + "(" + m_listRequest.Error.message + ")");
|
||||
}
|
||||
break;
|
||||
case StatusCode.Success:
|
||||
break;
|
||||
}
|
||||
|
||||
return s_wasPreparing = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool isAddingToList
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_addRequest == null) { return m_wasAdded = false; }
|
||||
|
||||
switch (m_addRequest.Status)
|
||||
{
|
||||
case StatusCode.InProgress:
|
||||
return m_wasAdded = true;
|
||||
case StatusCode.Failure:
|
||||
if (!m_wasAdded)
|
||||
{
|
||||
AddRequest request = m_addRequest;
|
||||
m_addRequest = null;
|
||||
if (string.IsNullOrEmpty(s_fallbackIdentifier))
|
||||
{
|
||||
Debug.LogError("Something wrong when adding package to list. error:" + request.Error.errorCode + "(" + request.Error.message + ")");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("Failed to install package: \"" + request.Error.message + "\". Retry with fallback identifier \"" + s_fallbackIdentifier + "\"");
|
||||
AddToPackageList(s_fallbackIdentifier);
|
||||
}
|
||||
|
||||
s_fallbackIdentifier = null;
|
||||
}
|
||||
break;
|
||||
case StatusCode.Success:
|
||||
if (!m_wasAdded)
|
||||
{
|
||||
m_addRequest = null;
|
||||
s_fallbackIdentifier = null;
|
||||
ResetPackageList();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return m_wasAdded = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool isRemovingFromList
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_removeRequest == null) { return s_wasRemoved = false; }
|
||||
|
||||
switch (m_removeRequest.Status)
|
||||
{
|
||||
case StatusCode.InProgress:
|
||||
return s_wasRemoved = true;
|
||||
case StatusCode.Failure:
|
||||
if (!s_wasRemoved)
|
||||
{
|
||||
if (m_removeRequest != null) { Debug.LogError("Something wrong when removing package from list. error:" + m_removeRequest.Error.errorCode + "(" + m_removeRequest.Error.message + ")"); }
|
||||
var request = m_removeRequest;
|
||||
m_removeRequest = null;
|
||||
}
|
||||
break;
|
||||
case StatusCode.Success:
|
||||
if (!s_wasRemoved)
|
||||
{
|
||||
m_removeRequest = null;
|
||||
ResetPackageList();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return s_wasRemoved = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void PreparePackageList()
|
||||
{
|
||||
if (m_listRequest != null) { return; }
|
||||
m_listRequest = Client.List(true, true);
|
||||
}
|
||||
|
||||
public static void ResetPackageList()
|
||||
{
|
||||
s_wasPreparing = false;
|
||||
m_listRequest = null;
|
||||
}
|
||||
|
||||
public static bool IsPackageInList(string name, out UnityEditor.PackageManager.PackageInfo packageInfo)
|
||||
{
|
||||
packageInfo = null;
|
||||
if (m_listRequest == null || m_listRequest.Result == null) return false;
|
||||
|
||||
foreach (var package in m_listRequest.Result)
|
||||
{
|
||||
if (package.name.Equals(name))
|
||||
{
|
||||
packageInfo = package;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void AddToPackageList(string identifier, string fallbackIdentifier = null)
|
||||
{
|
||||
Debug.Assert(m_addRequest == null);
|
||||
|
||||
m_addRequest = Client.Add(identifier);
|
||||
s_fallbackIdentifier = fallbackIdentifier;
|
||||
}
|
||||
|
||||
public static void RemovePackage(string identifier)
|
||||
{
|
||||
Debug.Assert(m_removeRequest == null);
|
||||
|
||||
m_removeRequest = Client.Remove(identifier);
|
||||
}
|
||||
|
||||
public static PackageCollection GetPackageList()
|
||||
{
|
||||
if (m_listRequest == null || m_listRequest.Result == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return m_listRequest.Result;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9d6ba0632411b7742b59d20955e2ea57
|
||||
guid: 43952515f295bac4385e71851692047d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b82495a07a589504fa93324ca990a306
|
||||
guid: 5f1198e3724eb5b44a705edc6d6bae06
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
namespace VIVE.OpenXR.Editor
|
||||
{
|
||||
[Serializable]
|
||||
public class PreferenceAvatarAsset : ScriptableObject
|
||||
{
|
||||
public const string AssetPath = "Assets/VIVE/OpenXR/Preferences/PreferenceAvatarAsset.asset";
|
||||
|
||||
// VRM constants
|
||||
public const string kVrm0Package = "UniVRM-0.109.0_7aff.unitypackage";
|
||||
public const string kVrm0Asset = "Assets/VRM.meta";
|
||||
public const string kVrm1Package = "VRM-0.109.0_7aff.unitypackage";
|
||||
public const string kVrm1Asset = "Assets/VRM10.meta";
|
||||
|
||||
public bool SupportVrm0 = false;
|
||||
public bool SupportVrm1 = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 94f6766384418a0418eb5ebdb371be20
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,301 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEditor.PackageManager;
|
||||
using UnityEditor.PackageManager.Requests;
|
||||
using UnityEditor.XR.Management.Metadata;
|
||||
|
||||
namespace VIVE.OpenXR.Editor
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
public static class ViveOpenXRPreference
|
||||
{
|
||||
#region Log
|
||||
static StringBuilder m_sb = null;
|
||||
static StringBuilder sb {
|
||||
get {
|
||||
if (m_sb == null) { m_sb = new StringBuilder(); }
|
||||
return m_sb;
|
||||
}
|
||||
}
|
||||
const string LOG_TAG = "VIVE.OpenXR.Editor.ViveOpenXRPreference";
|
||||
static void DEBUG(StringBuilder msg) { Debug.LogFormat("{0} {1}", LOG_TAG, msg); }
|
||||
static void ERROR(StringBuilder msg) { Debug.LogErrorFormat("{0} {1}", LOG_TAG, msg); }
|
||||
#endregion
|
||||
|
||||
static ViveOpenXRPreference()
|
||||
{
|
||||
EditorApplication.update += OnUpdate;
|
||||
}
|
||||
|
||||
#region Scripting Symbols
|
||||
internal struct ScriptingDefinedSettings
|
||||
{
|
||||
public string[] scriptingDefinedSymbols;
|
||||
public BuildTargetGroup[] targetGroups;
|
||||
|
||||
public ScriptingDefinedSettings(string[] symbols, BuildTargetGroup[] groups)
|
||||
{
|
||||
scriptingDefinedSymbols = symbols;
|
||||
targetGroups = groups;
|
||||
}
|
||||
}
|
||||
|
||||
const string DEFINE_USE_VRM_0_x = "USE_VRM_0_x";
|
||||
static readonly ScriptingDefinedSettings m_ScriptDefineSettingVrm0 = new ScriptingDefinedSettings(
|
||||
new string[] { DEFINE_USE_VRM_0_x, },
|
||||
new BuildTargetGroup[] { BuildTargetGroup.Android, }
|
||||
);
|
||||
|
||||
static void AddScriptingDefineSymbols(ScriptingDefinedSettings setting)
|
||||
{
|
||||
for (int group_index = 0; group_index < setting.targetGroups.Length; group_index++)
|
||||
{
|
||||
var group = setting.targetGroups[group_index];
|
||||
string definesString = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
|
||||
List<string> allDefines = definesString.Split(';').ToList();
|
||||
for (int symbol_index = 0; symbol_index < setting.scriptingDefinedSymbols.Length; symbol_index++)
|
||||
{
|
||||
if (!allDefines.Contains(setting.scriptingDefinedSymbols[symbol_index]))
|
||||
{
|
||||
sb.Clear().Append("AddDefineSymbols() ").Append(setting.scriptingDefinedSymbols[symbol_index]).Append(" to group ").Append(group); DEBUG(sb);
|
||||
allDefines.Add(setting.scriptingDefinedSymbols[symbol_index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Clear().Append("AddDefineSymbols() ").Append(setting.scriptingDefinedSymbols[symbol_index]).Append(" already existed."); DEBUG(sb);
|
||||
}
|
||||
}
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(
|
||||
group,
|
||||
string.Join(";", allDefines.ToArray())
|
||||
);
|
||||
}
|
||||
}
|
||||
static void RemoveScriptingDefineSymbols(ScriptingDefinedSettings setting)
|
||||
{
|
||||
for (int group_index = 0; group_index < setting.targetGroups.Length; group_index++)
|
||||
{
|
||||
var group = setting.targetGroups[group_index];
|
||||
string definesString = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
|
||||
List<string> allDefines = definesString.Split(';').ToList();
|
||||
for (int symbol_index = 0; symbol_index < setting.scriptingDefinedSymbols.Length; symbol_index++)
|
||||
{
|
||||
if (allDefines.Contains(setting.scriptingDefinedSymbols[symbol_index]))
|
||||
{
|
||||
sb.Clear().Append("RemoveDefineSymbols() ").Append(setting.scriptingDefinedSymbols[symbol_index]).Append(" from group ").Append(group); DEBUG(sb);
|
||||
allDefines.Remove(setting.scriptingDefinedSymbols[symbol_index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Clear().Append("RemoveDefineSymbols() ").Append(setting.scriptingDefinedSymbols[symbol_index]).Append(" already existed."); DEBUG(sb);
|
||||
}
|
||||
}
|
||||
PlayerSettings.SetScriptingDefineSymbolsForGroup(
|
||||
group,
|
||||
string.Join(";", allDefines.ToArray())
|
||||
);
|
||||
}
|
||||
}
|
||||
static bool HasScriptingDefineSymbols(ScriptingDefinedSettings setting)
|
||||
{
|
||||
for (int group_index = 0; group_index < setting.targetGroups.Length; group_index++)
|
||||
{
|
||||
var group = setting.targetGroups[group_index];
|
||||
string definesString = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
|
||||
List<string> allDefines = definesString.Split(';').ToList();
|
||||
for (int symbol_index = 0; symbol_index < setting.scriptingDefinedSymbols.Length; symbol_index++)
|
||||
{
|
||||
if (!allDefines.Contains(setting.scriptingDefinedSymbols[symbol_index]))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const string XR_LOADER_OPENXR_NAME = "UnityEngine.XR.OpenXR.OpenXRLoader";
|
||||
internal static bool ViveOpenXRAndroidAssigned { get { return XRPackageMetadataStore.IsLoaderAssigned(XR_LOADER_OPENXR_NAME, BuildTargetGroup.Android); } }
|
||||
|
||||
static PreferenceAvatarAsset m_AssetAvatar = null;
|
||||
static void CheckPreferenceAssets()
|
||||
{
|
||||
if (File.Exists(PreferenceAvatarAsset.AssetPath))
|
||||
{
|
||||
m_AssetAvatar = AssetDatabase.LoadAssetAtPath(PreferenceAvatarAsset.AssetPath, typeof(PreferenceAvatarAsset)) as PreferenceAvatarAsset;
|
||||
}
|
||||
else
|
||||
{
|
||||
string folderPath = PreferenceAvatarAsset.AssetPath.Substring(0, PreferenceAvatarAsset.AssetPath.LastIndexOf('/'));
|
||||
DirectoryInfo folder = Directory.CreateDirectory(folderPath);
|
||||
sb.Clear().Append("CheckPreferenceAssets() Creates folder: Assets/").Append(folder.Name); DEBUG(sb);
|
||||
|
||||
m_AssetAvatar = ScriptableObject.CreateInstance(typeof(PreferenceAvatarAsset)) as PreferenceAvatarAsset;
|
||||
m_AssetAvatar.SupportVrm0 = false;
|
||||
m_AssetAvatar.SupportVrm1 = false;
|
||||
|
||||
sb.Clear().Append("CheckPreferenceAssets() Creates the asset: ").Append(PreferenceAvatarAsset.AssetPath); DEBUG(sb);
|
||||
AssetDatabase.CreateAsset(m_AssetAvatar, PreferenceAvatarAsset.AssetPath);
|
||||
}
|
||||
}
|
||||
|
||||
static int checkPreferenceAssetsFrame = 0;
|
||||
static void OnUpdate()
|
||||
{
|
||||
if (!ViveOpenXRAndroidAssigned) { return; }
|
||||
|
||||
checkPreferenceAssetsFrame++;
|
||||
checkPreferenceAssetsFrame %= 1200; // 10s
|
||||
if (checkPreferenceAssetsFrame != 0) { return; }
|
||||
|
||||
CheckPreferenceAssets();
|
||||
|
||||
if (m_AssetAvatar)
|
||||
{
|
||||
// Adds the script symbol if VRM0 is imported.
|
||||
if (File.Exists(PreferenceAvatarAsset.kVrm0Asset))
|
||||
{
|
||||
if (!HasScriptingDefineSymbols(m_ScriptDefineSettingVrm0))
|
||||
{
|
||||
sb.Clear().Append("OnUpdate() Adds m_ScriptDefineSettingVrm0."); DEBUG(sb);
|
||||
AddScriptingDefineSymbols(m_ScriptDefineSettingVrm0);
|
||||
}
|
||||
m_AssetAvatar.SupportVrm0 = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (HasScriptingDefineSymbols(m_ScriptDefineSettingVrm0))
|
||||
{
|
||||
sb.Clear().Append("OnUpdate() Removes m_ScriptDefineSettingVrm0."); DEBUG(sb);
|
||||
RemoveScriptingDefineSymbols(m_ScriptDefineSettingVrm0);
|
||||
}
|
||||
m_AssetAvatar.SupportVrm0 = false;
|
||||
}
|
||||
|
||||
m_AssetAvatar.SupportVrm1 = File.Exists(PreferenceAvatarAsset.kVrm1Asset);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Preferences
|
||||
const string kPreferenceName = "VIVE OpenXR";
|
||||
private static GUIContent m_Vrm0Option = new GUIContent("VRM 0", "Avatar format.");
|
||||
private static GUIContent m_Vrm1Option = new GUIContent("VRM 1", "Avatar format.");
|
||||
|
||||
internal static void ImportModule(string packagePath, bool interactive = false)
|
||||
{
|
||||
string target = Path.Combine("Packages/com.htc.upm.vive.openxr/UnityPackages~", packagePath);
|
||||
sb.Clear().Append("ImportModule: " + target); DEBUG(sb);
|
||||
AssetDatabase.ImportPackage(target, interactive);
|
||||
}
|
||||
|
||||
static bool avatarOption = true;
|
||||
#pragma warning disable 0618
|
||||
[PreferenceItem(kPreferenceName)]
|
||||
#pragma warning restore 0618
|
||||
private static void OnPreferencesGUI()
|
||||
{
|
||||
if (EditorApplication.isCompiling)
|
||||
{
|
||||
EditorGUILayout.LabelField("Compiling...");
|
||||
return;
|
||||
}
|
||||
if (PackageManagerHelper.isAddingToList)
|
||||
{
|
||||
EditorGUILayout.LabelField("Installing packages...");
|
||||
return;
|
||||
}
|
||||
if (PackageManagerHelper.isRemovingFromList)
|
||||
{
|
||||
EditorGUILayout.LabelField("Removing packages...");
|
||||
return;
|
||||
}
|
||||
|
||||
PackageManagerHelper.PreparePackageList();
|
||||
if (PackageManagerHelper.isPreparingList)
|
||||
{
|
||||
EditorGUILayout.LabelField("Checking Packages...");
|
||||
return;
|
||||
}
|
||||
|
||||
CheckPreferenceAssets();
|
||||
|
||||
GUIStyle sectionTitleStyle = new GUIStyle(EditorStyles.label);
|
||||
sectionTitleStyle.fontSize = 16;
|
||||
sectionTitleStyle.richText = true;
|
||||
sectionTitleStyle.fontStyle = FontStyle.Bold;
|
||||
|
||||
#region Avatar
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Space(10);
|
||||
GUILayout.Label("Avatar", sectionTitleStyle);
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
GUIStyle foldoutStyle = EditorStyles.foldout;
|
||||
foldoutStyle.fontSize = 14;
|
||||
foldoutStyle.fontStyle = FontStyle.Normal;
|
||||
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Space(20);
|
||||
avatarOption = EditorGUILayout.Foldout(avatarOption, "Supported Format", foldoutStyle);
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
foldoutStyle.fontSize = 12;
|
||||
foldoutStyle.fontStyle = FontStyle.Normal;
|
||||
|
||||
if (m_AssetAvatar && avatarOption)
|
||||
{
|
||||
/// VRM 0
|
||||
GUILayout.Space(5);
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Space(35);
|
||||
if (!m_AssetAvatar.SupportVrm0)
|
||||
{
|
||||
bool toggled = EditorGUILayout.ToggleLeft(m_Vrm0Option, false, GUILayout.Width(230f));
|
||||
if (toggled)
|
||||
{
|
||||
sb.Clear().Append("OnPreferencesGUI() Adds ").Append(PreferenceAvatarAsset.kVrm0Package); DEBUG(sb);
|
||||
ImportModule(PreferenceAvatarAsset.kVrm0Package);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.ToggleLeft(m_Vrm0Option, true, GUILayout.Width(230f));
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
|
||||
/// VRM 1
|
||||
GUILayout.Space(5);
|
||||
GUILayout.BeginHorizontal();
|
||||
GUILayout.Space(35);
|
||||
if (!m_AssetAvatar.SupportVrm1)
|
||||
{
|
||||
bool toggled = EditorGUILayout.ToggleLeft(m_Vrm1Option, false, GUILayout.Width(230f));
|
||||
if (toggled)
|
||||
{
|
||||
sb.Clear().Append("OnPreferencesGUI() Adds ").Append(PreferenceAvatarAsset.kVrm1Package); DEBUG(sb);
|
||||
ImportModule(PreferenceAvatarAsset.kVrm1Package);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.ToggleLeft(m_Vrm1Option, true, GUILayout.Width(230f));
|
||||
}
|
||||
GUILayout.EndHorizontal();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 73bdd0b88ffae0e43a3a498347e6dea4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "HTC.Vive.OpenXR.Editor",
|
||||
"rootNamespace": "HTC.Vive.OpenXR.Editor",
|
||||
"name": "VIVE.OpenXR.Editor",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:e40ba710768534012815d3193fa296cb",
|
||||
"GUID:f9fe0089ec81f4079af78eb2287a6163",
|
||||
"GUID:4847341ff46394e83bb78fbd0652937e",
|
||||
"GUID:96aa6ba065960476598f8f643e7252b6"
|
||||
"VIVE.OpenXR",
|
||||
"Unity.XR.OpenXR",
|
||||
"Unity.XR.OpenXR.Editor",
|
||||
"Unity.XR.Management.Editor"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c34271c4bb951904aa11cacc978a4396
|
||||
guid: d6b33c0ff458eb344807c1608836e334
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
24
com.htc.upm.vive.openxr/Editor/ViveAnchorEditor.cs
Normal file
24
com.htc.upm.vive.openxr/Editor/ViveAnchorEditor.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
using UnityEditor;
|
||||
using VIVE.OpenXR.Feature;
|
||||
|
||||
namespace VIVE.OpenXR.Editor
|
||||
{
|
||||
[CustomEditor(typeof(ViveAnchor))]
|
||||
internal class ViveAnchorEditor : UnityEditor.Editor
|
||||
{
|
||||
private SerializedProperty enablePersistedAnchor;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
enablePersistedAnchor = serializedObject.FindProperty("enablePersistedAnchor");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
EditorGUILayout.PropertyField(enablePersistedAnchor);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
com.htc.upm.vive.openxr/Editor/ViveAnchorEditor.cs.meta
Normal file
11
com.htc.upm.vive.openxr/Editor/ViveAnchorEditor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9094698271e2abb4ab295256548772c3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
26
com.htc.upm.vive.openxr/Editor/ViveCompositionLayerEditor.cs
Normal file
26
com.htc.upm.vive.openxr/Editor/ViveCompositionLayerEditor.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
|
||||
namespace VIVE.OpenXR.CompositionLayer
|
||||
{
|
||||
[CustomEditor(typeof(ViveCompositionLayer))]
|
||||
internal class ViveCompositionLayerEditor : UnityEditor.Editor
|
||||
{
|
||||
private SerializedProperty enableAutoFallback;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
enableAutoFallback = serializedObject.FindProperty("enableAutoFallback");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
EditorGUILayout.PropertyField(enableAutoFallback);
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a4e5396be5abca4ab71bc9a8fd60e40
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
44
com.htc.upm.vive.openxr/Editor/ViveMenu.cs
Normal file
44
com.htc.upm.vive.openxr/Editor/ViveMenu.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
|
||||
namespace VIVE.OpenXR.Editor
|
||||
{
|
||||
public class ViveMenu : UnityEditor.Editor
|
||||
{
|
||||
private const string kMenuXR = "VIVE/XR/Convert Main Camera to ViveRig";
|
||||
|
||||
[MenuItem(kMenuXR, priority = 101)]
|
||||
private static void ConvertToViveRig()
|
||||
{
|
||||
// 1. Removes default Camera
|
||||
Camera cam = FindObjectOfType<Camera>();
|
||||
if (cam != null && cam.transform.parent == null)
|
||||
{
|
||||
Debug.Log("ConvertToViveRig() remove " + cam.gameObject.name);
|
||||
DestroyImmediate(cam.gameObject);
|
||||
}
|
||||
|
||||
// 2. Loads ViveRig
|
||||
if (GameObject.Find("ViveRig") == null && GameObject.Find("ViveRig(Clone)") == null)
|
||||
{
|
||||
GameObject prefab = Resources.Load<GameObject>("Prefabs/ViveRig");
|
||||
if (prefab != null)
|
||||
{
|
||||
Debug.Log("ConvertToViveRig() load " + prefab.name);
|
||||
GameObject inst = Instantiate(prefab, null);
|
||||
if (inst != null)
|
||||
{
|
||||
inst.name = "ViveRig";
|
||||
UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(SceneManager.GetActiveScene());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
11
com.htc.upm.vive.openxr/Editor/ViveMenu.cs.meta
Normal file
11
com.htc.upm.vive.openxr/Editor/ViveMenu.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f78968df8bc5794393fb2016e223a6c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
64
com.htc.upm.vive.openxr/Editor/ViveMockRuntimeEditor.cs
Normal file
64
com.htc.upm.vive.openxr/Editor/ViveMockRuntimeEditor.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using VIVE.OpenXR.Feature;
|
||||
|
||||
namespace VIVE.OpenXR.Editor
|
||||
{
|
||||
[CustomEditor(typeof(ViveMockRuntime))]
|
||||
internal class ViveMockRuntimeEditor : UnityEditor.Editor
|
||||
{
|
||||
private SerializedProperty enableFuture;
|
||||
private SerializedProperty enableAnchor;
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
enableFuture = serializedObject.FindProperty("enableFuture");
|
||||
enableAnchor = serializedObject.FindProperty("enableAnchor");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
// Show a text field for description
|
||||
EditorGUILayout.HelpBox("VIVE's mock runtime. Used with OpenXR MockRuntime to test unsupported extensions and features on Editor.", MessageType.Info);
|
||||
|
||||
if (GUILayout.Button("Install MockRuntime Library")) {
|
||||
InstallMockRuntimeLibrary();
|
||||
}
|
||||
|
||||
// check if changed
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(enableFuture);
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
if (!enableFuture.boolValue) {
|
||||
enableAnchor.boolValue = false;
|
||||
}
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
EditorGUILayout.PropertyField(enableAnchor);
|
||||
if (EditorGUI.EndChangeCheck()) {
|
||||
if (enableAnchor.boolValue) {
|
||||
enableFuture.boolValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
public void InstallMockRuntimeLibrary() {
|
||||
string sourcePathName = "Packages/com.htc.upm.vive.openxr/MockRuntime~/Win64/ViveMockRuntime.dll";
|
||||
string destPath = "Assets/Plugins/Win64";
|
||||
string destPathName = "Assets/Plugins/Win64/ViveMockRuntime.dll";
|
||||
|
||||
// check if the folder exists. If not, create it.
|
||||
if (!System.IO.Directory.Exists(destPath)) {
|
||||
System.IO.Directory.CreateDirectory(destPath);
|
||||
}
|
||||
|
||||
FileUtil.CopyFileOrDirectory(sourcePathName, destPathName);
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
11
com.htc.upm.vive.openxr/Editor/ViveMockRuntimeEditor.cs.meta
Normal file
11
com.htc.upm.vive.openxr/Editor/ViveMockRuntimeEditor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eedb4211aafd2cb4bae86fcc0e948f72
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
46
com.htc.upm.vive.openxr/Editor/ViveOpenXRFeatureSet.cs
Normal file
46
com.htc.upm.vive.openxr/Editor/ViveOpenXRFeatureSet.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright HTC Corporation All Rights Reserved.
|
||||
#if UNITY_EDITOR
|
||||
|
||||
using UnityEditor;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
|
||||
namespace VIVE.OpenXR
|
||||
{
|
||||
[OpenXRFeatureSet(
|
||||
FeatureIds = new string[] {
|
||||
VIVEFocus3Feature.featureId,
|
||||
VIVEFocus3Profile.featureId,
|
||||
Hand.ViveHandTracking.featureId,
|
||||
"vive.openxr.feature.compositionlayer",
|
||||
"vive.openxr.feature.compositionlayer.cylinder",
|
||||
"vive.openxr.feature.compositionlayer.colorscalebias",
|
||||
CompositionLayer.ViveCompositionLayerEquirect.featureId,
|
||||
Tracker.ViveWristTracker.featureId,
|
||||
Hand.ViveHandInteraction.featureId,
|
||||
"vive.openxr.feature.foveation",
|
||||
FacialTracking.ViveFacialTracking.featureId,
|
||||
PlaneDetection.VivePlaneDetection.featureId,
|
||||
VivePathEnumeration.featureId,
|
||||
Feature.ViveAnchor.featureId,
|
||||
DisplayRefreshRate.ViveDisplayRefreshRate.featureId,
|
||||
Passthrough.VivePassthrough.featureId,
|
||||
FirstPersonObserver.ViveFirstPersonObserver.FeatureId,
|
||||
SecondaryViewConfiguration.ViveSecondaryViewConfiguration.FeatureId,
|
||||
UserPresence.ViveUserPresence.featureId,
|
||||
CompositionLayer.ViveCompositionLayerExtraSettings.featureId,
|
||||
FrameSynchronization.ViveFrameSynchronization.featureId,
|
||||
EyeTracker.ViveEyeTracker.featureId,
|
||||
Feature.ViveMockRuntime.featureId,
|
||||
Interaction.ViveInteractions.featureId,
|
||||
},
|
||||
UiName = "VIVE XR Support",
|
||||
Description = "Necessary to deploy an VIVE XR compatible app.",
|
||||
FeatureSetId = "com.htc.vive.openxr.featureset.vivexr",
|
||||
#if UNITY_ANDROID
|
||||
DefaultFeatureIds = new string[] { VIVEFocus3Feature.featureId, VIVEFocus3Profile.featureId, },
|
||||
#endif
|
||||
SupportedBuildTargets = new BuildTargetGroup[] { BuildTargetGroup.Android, BuildTargetGroup.Standalone }
|
||||
)]
|
||||
sealed class ViveOpenXRFeatureSet { }
|
||||
}
|
||||
#endif
|
||||
11
com.htc.upm.vive.openxr/Editor/ViveOpenXRFeatureSet.cs.meta
Normal file
11
com.htc.upm.vive.openxr/Editor/ViveOpenXRFeatureSet.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6fe9adb019aff2e419eee912e8171cf9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
81
com.htc.upm.vive.openxr/Editor/ViveSpectatorCameraProcess.cs
Normal file
81
com.htc.upm.vive.openxr/Editor/ViveSpectatorCameraProcess.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Build.Reporting;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using static VIVE.OpenXR.VIVEFocus3Feature;
|
||||
|
||||
namespace VIVE.OpenXR.Editor
|
||||
{
|
||||
public class ViveSpectatorCameraProcess : OpenXRFeatureBuildHooks
|
||||
{
|
||||
public override int callbackOrder => 1;
|
||||
|
||||
public override Type featureType => typeof(VIVEFocus3Feature);
|
||||
|
||||
/// <summary>
|
||||
/// Enable or disable the "First Person Observer" extension according to the Spectator Camera Feature.
|
||||
/// </summary>
|
||||
/// <param name="enable">Type True if Spectator Camera Feature is enabled. Otherwise, type False.</param>
|
||||
private static void SetFirstPersonObserver(in bool enable)
|
||||
{
|
||||
var settings = OpenXRSettings.GetSettingsForBuildTargetGroup(BuildTargetGroup.Android);
|
||||
|
||||
foreach (OpenXRFeature feature in settings.GetFeatures<OpenXRFeature>())
|
||||
{
|
||||
FieldInfo fieldInfoOpenXrExtensionStrings = typeof(OpenXRFeature).GetField(
|
||||
"openxrExtensionStrings",
|
||||
BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
if (fieldInfoOpenXrExtensionStrings != null)
|
||||
{
|
||||
var openXrExtensionStringsArray =
|
||||
((string)fieldInfoOpenXrExtensionStrings.GetValue(feature)).Split(' ');
|
||||
|
||||
foreach (var stringItem in openXrExtensionStringsArray)
|
||||
{
|
||||
if (string.IsNullOrEmpty(stringItem))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!string.Equals(stringItem, FirstPersonObserver.ViveFirstPersonObserver.OPEN_XR_EXTENSION_STRING))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
feature.enabled = enable;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region The callbacks during the build process when your OpenXR Extension is enabled.
|
||||
|
||||
protected override void OnPreprocessBuildExt(BuildReport report)
|
||||
{
|
||||
if (IsViveSpectatorCameraEnabled())
|
||||
{
|
||||
SetFirstPersonObserver(true);
|
||||
UnityEngine.Debug.Log("Enable \"First Person Observer\" extension due to the Spectator Camera Feature.");
|
||||
}
|
||||
else
|
||||
{
|
||||
SetFirstPersonObserver(false);
|
||||
UnityEngine.Debug.Log("Disable \"First Person Observer\" extension because Spectator Camera Feature is closed.");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPostGenerateGradleAndroidProjectExt(string path)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnPostprocessBuildExt(BuildReport report)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4fcb7e5a984acb64bb9221b9b05c0517
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"name": "HTC.VIVE.OPENXR",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:4847341ff46394e83bb78fbd0652937e",
|
||||
"GUID:75469ad4d38634e559750d17036d5f7c",
|
||||
"GUID:96aa6ba065960476598f8f643e7252b6"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": true,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
4
com.htc.upm.vive.openxr/LICENSE.txt
Normal file
4
com.htc.upm.vive.openxr/LICENSE.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
Copyright © HTC Corporation, LLC and its affiliates. All rights reserved.
|
||||
|
||||
Your use of this SDK, sample, or tool is subject to HTC VIVE SDK License Agreement, available at https://developer.vive.com/resources/downloads/licenses-and-agreements/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d77374400df33e4396eb7e610d731d7
|
||||
guid: ecdb711833cec9e49b0c978f3f9aada1
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
BIN
com.htc.upm.vive.openxr/MockRuntime~/Win64/ViveMockRuntime.dll
LFS
Normal file
BIN
com.htc.upm.vive.openxr/MockRuntime~/Win64/ViveMockRuntime.dll
LFS
Normal file
Binary file not shown.
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 661e7acd9eb00954994e90a733ef85c3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42871fe047fc3f6428246272b42a0630
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7cc26b297a5859041aa2a4c1b6ea8d45
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 11437acb07f69f0488ff34fc80714d41
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d308a0a31ed751c4e8732edd46dab7a0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,43 +0,0 @@
|
||||
using UnityEditor;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using VIVE.FacialTracking;
|
||||
namespace UnityEditor.XR.OpenXR.Samples.FacialTracking
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
public class FacialTrackingFeatureInstaller : Editor
|
||||
{
|
||||
#if !UNITY_SAMPLE_DEV
|
||||
private const string k_ScriptPath = "FacialTracking Example/Editor/FacialTrackingFeatureInstaller.cs";
|
||||
static FacialTrackingFeatureInstaller()
|
||||
{
|
||||
FeatureHelpers.RefreshFeatures(BuildTargetGroup.Standalone);
|
||||
var feature = OpenXRSettings.Instance.GetFeature<VIVE_FacialTracking_OpenXR_API>();
|
||||
if (feature != null)
|
||||
{
|
||||
if (feature.enabled != true)
|
||||
{
|
||||
feature.enabled = true;
|
||||
}
|
||||
}
|
||||
Debug.Log(AssetDatabase.FindAssets(Path.GetFileNameWithoutExtension(k_ScriptPath)).Select(AssetDatabase.GUIDToAssetPath));
|
||||
var source = AssetDatabase.FindAssets(Path.GetFileNameWithoutExtension(k_ScriptPath))
|
||||
.Select(AssetDatabase.GUIDToAssetPath)
|
||||
.FirstOrDefault(r => r.Contains(k_ScriptPath));
|
||||
|
||||
if (string.IsNullOrEmpty(source))
|
||||
{
|
||||
Debug.LogError("File Not Exist");
|
||||
return;
|
||||
}
|
||||
|
||||
source = Path.GetDirectoryName(source);
|
||||
Debug.Log(source);
|
||||
AssetDatabase.DeleteAsset(Path.Combine(Path.GetDirectoryName(source), "Editor"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3db97ef06df531243bb52fd4a70723ea
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a973f4662aff486448146cf2b9bd4755
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f0401084408f3e4aaf32b5827e19ab6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bba121844e9a1ec40b25e6a891b5c54d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 281dba7d6bd94694db4295902d0cefd3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b713246b98e0edd48b3ac2dc544d5645
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,465 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &3051409913850635161
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 3051409913850609593}
|
||||
- component: {fileID: 3051409913849839515}
|
||||
- component: {fileID: 3051409913848708443}
|
||||
m_Layer: 0
|
||||
m_Name: Eye_Left
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &3051409913850609593
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3051409913850635161}
|
||||
m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: -0.034480397, y: 0.008242355, z: 0.078922845}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 3051409913850609595}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!33 &3051409913849839515
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3051409913850635161}
|
||||
m_Mesh: {fileID: 4300002, guid: cc2bd8780f283784899dcb72f2f7702f, type: 3}
|
||||
--- !u!23 &3051409913848708443
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3051409913850635161}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RayTraceProcedural: 0
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: 64185bf5c669e274ca89bb76c87d1429, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_AdditionalVertexStreams: {fileID: 0}
|
||||
--- !u!1 &3051409913850635163
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 3051409913850609595}
|
||||
- component: {fileID: 3051409913860149339}
|
||||
- component: {fileID: 3051409913850733895}
|
||||
- component: {fileID: 3051409913850733890}
|
||||
m_Layer: 0
|
||||
m_Name: Avatar_Shieh_V2
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &3051409913850609595
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3051409913850635163}
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: -0.04, z: -0.158}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children:
|
||||
- {fileID: 3051409913850609593}
|
||||
- {fileID: 3051409913850609599}
|
||||
- {fileID: 3051409913850609597}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!95 &3051409913860149339
|
||||
Animator:
|
||||
serializedVersion: 3
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3051409913850635163}
|
||||
m_Enabled: 1
|
||||
m_Avatar: {fileID: 9000000, guid: cc2bd8780f283784899dcb72f2f7702f, type: 3}
|
||||
m_Controller: {fileID: 0}
|
||||
m_CullingMode: 1
|
||||
m_UpdateMode: 0
|
||||
m_ApplyRootMotion: 0
|
||||
m_LinearVelocityBlending: 0
|
||||
m_WarningMessage:
|
||||
m_HasTransformHierarchy: 1
|
||||
m_AllowConstantClipSamplingOptimization: 1
|
||||
m_KeepAnimatorControllerStateOnDisable: 0
|
||||
--- !u!114 &3051409913850733895
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3051409913850635163}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 2872c722b18f6d043ad0dbae08561d64, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
EyesModels:
|
||||
- {fileID: 3051409913850609593}
|
||||
- {fileID: 3051409913850609599}
|
||||
EyeShapeTables:
|
||||
- skinnedMeshRenderer: {fileID: 3051409913864302235}
|
||||
eyeShapes: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000100000002000000030000000400000005000000060000000700000008000000090000000a0000000b0000000c0000000d0000000e000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
EyebrowAnimationCurveUpper:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 1
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 0
|
||||
EyebrowAnimationCurveLower:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 1
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 0
|
||||
EyebrowAnimationCurveHorizontal:
|
||||
serializedVersion: 2
|
||||
m_Curve:
|
||||
- serializedVersion: 3
|
||||
time: 0
|
||||
value: 0
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
- serializedVersion: 3
|
||||
time: 1
|
||||
value: 1
|
||||
inSlope: 0
|
||||
outSlope: 0
|
||||
tangentMode: 0
|
||||
weightedMode: 0
|
||||
inWeight: 0.33333334
|
||||
outWeight: 0.33333334
|
||||
m_PreInfinity: 2
|
||||
m_PostInfinity: 2
|
||||
m_RotationOrder: 0
|
||||
NeededToGetData: 1
|
||||
--- !u!114 &3051409913850733890
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3051409913850635163}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 42350b51669fc604cb2cad73c39f116c, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
LipShapeTables:
|
||||
- skinnedMeshRenderer: {fileID: 3051409913864302235}
|
||||
lipShapes: 010000000000000002000000030000000400000006000000050000000800000007000000090000000a0000000b0000000d0000000c0000000f0000000e00000011000000100000001200000014000000130000001600000015000000170000001800000019000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1a000000200000001b0000001c0000001d0000001e0000001f00000022000000210000002400000023000000
|
||||
NeededToGetData: 1
|
||||
--- !u!1 &3051409913850635165
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 3051409913850609597}
|
||||
- component: {fileID: 3051409913864302235}
|
||||
m_Layer: 0
|
||||
m_Name: Head
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &3051409913850609597
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3051409913850635165}
|
||||
m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: -0, y: -0.05097887, z: 0.004202667}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 3051409913850609595}
|
||||
m_RootOrder: 2
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!137 &3051409913864302235
|
||||
SkinnedMeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3051409913850635165}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 3
|
||||
m_RayTraceProcedural: 0
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: 64185bf5c669e274ca89bb76c87d1429, type: 2}
|
||||
- {fileID: 2100000, guid: ed4b25628f9822042ae28821748b430f, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
serializedVersion: 2
|
||||
m_Quality: 0
|
||||
m_UpdateWhenOffscreen: 1
|
||||
m_SkinnedMotionVectors: 1
|
||||
m_Mesh: {fileID: 4300000, guid: cc2bd8780f283784899dcb72f2f7702f, type: 3}
|
||||
m_Bones: []
|
||||
m_BlendShapeWeights:
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
- 0
|
||||
m_RootBone: {fileID: 0}
|
||||
m_AABB:
|
||||
m_Center: {x: 0, y: 0, z: 0.0039771833}
|
||||
m_Extent: {x: 0.0988433, y: 0.18122566, z: 0.12538658}
|
||||
m_DirtyAABB: 0
|
||||
--- !u!1 &3051409913850635167
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 3051409913850609599}
|
||||
- component: {fileID: 3051409913849839513}
|
||||
- component: {fileID: 3051409913848708441}
|
||||
m_Layer: 0
|
||||
m_Name: Eye_Right
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &3051409913850609599
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3051409913850635167}
|
||||
m_LocalRotation: {x: 0, y: -0, z: -0, w: 1}
|
||||
m_LocalPosition: {x: 0.034480397, y: 0.008242355, z: 0.078922845}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_Children: []
|
||||
m_Father: {fileID: 3051409913850609595}
|
||||
m_RootOrder: 1
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!33 &3051409913849839513
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3051409913850635167}
|
||||
m_Mesh: {fileID: 4300004, guid: cc2bd8780f283784899dcb72f2f7702f, type: 3}
|
||||
--- !u!23 &3051409913848708441
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 3051409913850635167}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RayTraceProcedural: 0
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: 64185bf5c669e274ca89bb76c87d1429, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 0
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 1
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_AdditionalVertexStreams: {fileID: 0}
|
||||
@@ -1,19 +0,0 @@
|
||||
# VIVE OpenXR Facial Tracking Unity Feature
|
||||
|
||||
To help software developers create an application with actual facial expressions on 3D avatars with the OpenXR facial tracing extension [XR_HTC_facial_tracking](https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#XR_HTC_facial_tracking).
|
||||
|
||||
## Load sample code
|
||||
**Window** > **Package Manager** > **VIVE OpenXR Plugin - Windows** > **Samples** > Click to import **FacialTracking Example**
|
||||
|
||||
## Play the sample scene
|
||||
1. **Edit** > **Project Settings** > **XR Plug-in Management** > Select **OpenXR** , click Exclamation mark next to it then choose **Fix All**.
|
||||
2. **Edit** > **Project Settings** > **XR Plug-in Management** > **OpenXR** > Add Interaction profiles for your device.
|
||||
3. **Edit** > **Project Settings** > **XR Plug-in Management** > **OpenXR** > Select **Facial Tracking** under **VIVE OpenXR** Feature Groups.
|
||||
4. In the Unity Project window, select the sample scene file in **Assets** > **Samples** > **VIVE OpenXR Plugin - Windows** > **1.0.13** > **FacialTracking Example** > **Scenes** > **FaceSample.unity** then click Play.
|
||||
|
||||
## How to use VIVE OpenXR Facial Tracking Unity Feature
|
||||
1. Import VIVE OpenXR Plugin - Windows
|
||||
2. Add your avatar object to the Unity scene.
|
||||
- Attach "AvatarEyeSample.cs" and "AvatarLipSample.cs" to your avatar object or Drag "Avatar_Shieh_V2" prefab into scene hierarchy.
|
||||
- Refer to functions **StartFrameWork** and **StopFrameWork** in **FacialManager.cs** for creating and releasing handle for face.
|
||||
- Refer to the function **GetWeightings** in **FacialManager.cs** for getting the weightings of blendshapes.
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a61dfaae82a22ea46a30881e98813962
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,755 +0,0 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!29 &1
|
||||
OcclusionCullingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_OcclusionBakeSettings:
|
||||
smallestOccluder: 5
|
||||
smallestHole: 0.25
|
||||
backfaceThreshold: 100
|
||||
m_SceneGUID: 00000000000000000000000000000000
|
||||
m_OcclusionCullingData: {fileID: 0}
|
||||
--- !u!104 &2
|
||||
RenderSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 9
|
||||
m_Fog: 0
|
||||
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
|
||||
m_FogMode: 3
|
||||
m_FogDensity: 0.01
|
||||
m_LinearFogStart: 0
|
||||
m_LinearFogEnd: 300
|
||||
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
|
||||
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
|
||||
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
|
||||
m_AmbientIntensity: 1
|
||||
m_AmbientMode: 0
|
||||
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
|
||||
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_HaloStrength: 0.5
|
||||
m_FlareStrength: 1
|
||||
m_FlareFadeSpeed: 3
|
||||
m_HaloTexture: {fileID: 0}
|
||||
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
|
||||
m_DefaultReflectionMode: 0
|
||||
m_DefaultReflectionResolution: 128
|
||||
m_ReflectionBounces: 1
|
||||
m_ReflectionIntensity: 1
|
||||
m_CustomReflection: {fileID: 0}
|
||||
m_Sun: {fileID: 0}
|
||||
m_IndirectSpecularColor: {r: 0.45112008, g: 0.49971223, b: 0.5675026, a: 1}
|
||||
m_UseRadianceAmbientProbe: 0
|
||||
--- !u!157 &3
|
||||
LightmapSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 12
|
||||
m_GIWorkflowMode: 0
|
||||
m_GISettings:
|
||||
serializedVersion: 2
|
||||
m_BounceScale: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_EnvironmentLightingMode: 0
|
||||
m_EnableBakedLightmaps: 1
|
||||
m_EnableRealtimeLightmaps: 1
|
||||
m_LightmapEditorSettings:
|
||||
serializedVersion: 12
|
||||
m_Resolution: 2
|
||||
m_BakeResolution: 40
|
||||
m_AtlasSize: 1024
|
||||
m_AO: 0
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 1
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAmbientOcclusion: 0
|
||||
m_Padding: 2
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_LightmapsBakeMode: 1
|
||||
m_TextureCompression: 1
|
||||
m_FinalGather: 0
|
||||
m_FinalGatherFiltering: 1
|
||||
m_FinalGatherRayCount: 256
|
||||
m_ReflectionCompression: 2
|
||||
m_MixedBakeMode: 2
|
||||
m_BakeBackend: 0
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 500
|
||||
m_PVRBounces: 2
|
||||
m_PVREnvironmentSampleCount: 500
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_PVRFilteringMode: 2
|
||||
m_PVRDenoiserTypeDirect: 0
|
||||
m_PVRDenoiserTypeIndirect: 0
|
||||
m_PVRDenoiserTypeAO: 0
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVREnvironmentMIS: 0
|
||||
m_PVRCulling: 1
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 5
|
||||
m_PVRFilteringGaussRadiusAO: 2
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
m_ExportTrainingData: 0
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_LightingDataAsset: {fileID: 0}
|
||||
m_LightingSettings: {fileID: 4890085278179872738, guid: 139b813ee621cbb41b237fe73214bf9f, type: 2}
|
||||
--- !u!196 &4
|
||||
NavMeshSettings:
|
||||
serializedVersion: 2
|
||||
m_ObjectHideFlags: 0
|
||||
m_BuildSettings:
|
||||
serializedVersion: 2
|
||||
agentTypeID: 0
|
||||
agentRadius: 0.5
|
||||
agentHeight: 2
|
||||
agentSlope: 45
|
||||
agentClimb: 0.4
|
||||
ledgeDropHeight: 0
|
||||
maxJumpAcrossDistance: 0
|
||||
minRegionArea: 2
|
||||
manualCellSize: 0
|
||||
cellSize: 0.16666667
|
||||
manualTileSize: 0
|
||||
tileSize: 256
|
||||
accuratePlacement: 0
|
||||
maxJobWorkers: 0
|
||||
preserveTilesOutsideBounds: 0
|
||||
debug:
|
||||
m_Flags: 0
|
||||
m_NavMeshData: {fileID: 0}
|
||||
--- !u!1 &306469291
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 1972517298404456, guid: 628ff83903a43c74ba5c884b8d6d0b59, type: 2}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 306469292}
|
||||
- component: {fileID: 306469293}
|
||||
m_Layer: 0
|
||||
m_Name: Avatar Sample
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &306469292
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 4567766556640800, guid: 628ff83903a43c74ba5c884b8d6d0b59, type: 2}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 306469291}
|
||||
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_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 1374042943}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 2
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &306469293
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 306469291}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 196084005ab84764aac2e78a079dc66c, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
camera: {fileID: 1387412029}
|
||||
--- !u!1001 &539581763
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 4074961600660305650, guid: 7776754447252ff4087ea2ebcc9821d3, type: 3}
|
||||
propertyPath: m_IsActive
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8040272353404943719, guid: 7776754447252ff4087ea2ebcc9821d3, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: Head Render Scene
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8040272353404943719, guid: 7776754447252ff4087ea2ebcc9821d3, type: 3}
|
||||
propertyPath: m_IsActive
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8952382327610939962, guid: 7776754447252ff4087ea2ebcc9821d3, type: 3}
|
||||
propertyPath: m_RootOrder
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8952382327610939962, guid: 7776754447252ff4087ea2ebcc9821d3, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8952382327610939962, guid: 7776754447252ff4087ea2ebcc9821d3, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8952382327610939962, guid: 7776754447252ff4087ea2ebcc9821d3, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8952382327610939962, guid: 7776754447252ff4087ea2ebcc9821d3, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8952382327610939962, guid: 7776754447252ff4087ea2ebcc9821d3, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8952382327610939962, guid: 7776754447252ff4087ea2ebcc9821d3, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8952382327610939962, guid: 7776754447252ff4087ea2ebcc9821d3, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8952382327610939962, guid: 7776754447252ff4087ea2ebcc9821d3, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8952382327610939962, guid: 7776754447252ff4087ea2ebcc9821d3, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8952382327610939962, guid: 7776754447252ff4087ea2ebcc9821d3, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 7776754447252ff4087ea2ebcc9821d3, type: 3}
|
||||
--- !u!1 &760214750
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 760214753}
|
||||
- component: {fileID: 760214752}
|
||||
- component: {fileID: 760214751}
|
||||
m_Layer: 0
|
||||
m_Name: Objects placed in front of user
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 0
|
||||
--- !u!114 &760214751
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 760214750}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 19eff34b54274a84c8b0f87cffbfd76a, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!20 &760214752
|
||||
Camera:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 760214750}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 2
|
||||
m_ClearFlags: 1
|
||||
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
|
||||
m_projectionMatrixMode: 1
|
||||
m_GateFitMode: 2
|
||||
m_FOVAxisMode: 0
|
||||
m_SensorSize: {x: 36, y: 24}
|
||||
m_LensShift: {x: 0, y: 0}
|
||||
m_FocalLength: 50
|
||||
m_NormalizedViewPortRect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1
|
||||
height: 1
|
||||
near clip plane: 0.3
|
||||
far clip plane: 1000
|
||||
field of view: 60
|
||||
orthographic: 0
|
||||
orthographic size: 5
|
||||
m_Depth: 0
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 2147483647
|
||||
m_RenderingPath: -1
|
||||
m_TargetTexture: {fileID: 8400000, guid: 600a6f0266444c145945aa3e7f2a29a6, type: 2}
|
||||
m_TargetDisplay: 0
|
||||
m_TargetEye: 0
|
||||
m_HDR: 0
|
||||
m_AllowMSAA: 1
|
||||
m_AllowDynamicResolution: 0
|
||||
m_ForceIntoRT: 0
|
||||
m_OcclusionCulling: 1
|
||||
m_StereoConvergence: 10
|
||||
m_StereoSeparation: 0.022
|
||||
--- !u!4 &760214753
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 760214750}
|
||||
m_LocalRotation: {x: 0, y: 1, z: 0, w: 0}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0.6}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children:
|
||||
- {fileID: 1921226929}
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 4
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0}
|
||||
--- !u!4 &1374042943 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 3051409913850609595, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
m_PrefabInstance: {fileID: 3051409913039127684}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!1 &1387412024
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1387412029}
|
||||
- component: {fileID: 1387412028}
|
||||
- component: {fileID: 1387412026}
|
||||
- component: {fileID: 1387412025}
|
||||
- component: {fileID: 1387412027}
|
||||
m_Layer: 0
|
||||
m_Name: Main Camera
|
||||
m_TagString: MainCamera
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!81 &1387412025
|
||||
AudioListener:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1387412024}
|
||||
m_Enabled: 1
|
||||
--- !u!124 &1387412026
|
||||
Behaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1387412024}
|
||||
m_Enabled: 1
|
||||
--- !u!114 &1387412027
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1387412024}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 5a2a9c34df4095f47b9ca8f975175f5b, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_Device: 0
|
||||
m_PoseSource: 2
|
||||
m_PoseProviderComponent: {fileID: 0}
|
||||
m_TrackingType: 0
|
||||
m_UpdateType: 0
|
||||
m_UseRelativeTransform: 0
|
||||
--- !u!20 &1387412028
|
||||
Camera:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1387412024}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 2
|
||||
m_ClearFlags: 1
|
||||
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
|
||||
m_projectionMatrixMode: 1
|
||||
m_GateFitMode: 2
|
||||
m_FOVAxisMode: 0
|
||||
m_SensorSize: {x: 36, y: 24}
|
||||
m_LensShift: {x: 0, y: 0}
|
||||
m_FocalLength: 50
|
||||
m_NormalizedViewPortRect:
|
||||
serializedVersion: 2
|
||||
x: 0
|
||||
y: 0
|
||||
width: 1
|
||||
height: 1
|
||||
near clip plane: 0.01
|
||||
far clip plane: 1000
|
||||
field of view: 60
|
||||
orthographic: 0
|
||||
orthographic size: 5
|
||||
m_Depth: -1
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_RenderingPath: -1
|
||||
m_TargetTexture: {fileID: 0}
|
||||
m_TargetDisplay: 0
|
||||
m_TargetEye: 3
|
||||
m_HDR: 0
|
||||
m_AllowMSAA: 1
|
||||
m_AllowDynamicResolution: 0
|
||||
m_ForceIntoRT: 0
|
||||
m_OcclusionCulling: 1
|
||||
m_StereoConvergence: 10
|
||||
m_StereoSeparation: 0.022
|
||||
--- !u!4 &1387412029
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1387412024}
|
||||
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_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 3
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!1 &1921226928
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 1921226929}
|
||||
- component: {fileID: 1921226932}
|
||||
- component: {fileID: 1921226931}
|
||||
- component: {fileID: 1921226930}
|
||||
m_Layer: 0
|
||||
m_Name: Mirror
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &1921226929
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1921226928}
|
||||
m_LocalRotation: {x: -0, y: 1, z: -0, w: 0}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: -1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 760214753}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0}
|
||||
--- !u!23 &1921226930
|
||||
MeshRenderer:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1921226928}
|
||||
m_Enabled: 1
|
||||
m_CastShadows: 1
|
||||
m_ReceiveShadows: 1
|
||||
m_DynamicOccludee: 1
|
||||
m_StaticShadowCaster: 0
|
||||
m_MotionVectors: 1
|
||||
m_LightProbeUsage: 1
|
||||
m_ReflectionProbeUsage: 1
|
||||
m_RayTracingMode: 2
|
||||
m_RayTraceProcedural: 0
|
||||
m_RenderingLayerMask: 1
|
||||
m_RendererPriority: 0
|
||||
m_Materials:
|
||||
- {fileID: 2100000, guid: 20c0a6a4ee4540848b1ad902026d6110, type: 2}
|
||||
m_StaticBatchInfo:
|
||||
firstSubMesh: 0
|
||||
subMeshCount: 0
|
||||
m_StaticBatchRoot: {fileID: 0}
|
||||
m_ProbeAnchor: {fileID: 0}
|
||||
m_LightProbeVolumeOverride: {fileID: 0}
|
||||
m_ScaleInLightmap: 1
|
||||
m_ReceiveGI: 1
|
||||
m_PreserveUVs: 1
|
||||
m_IgnoreNormalsForChartDetection: 0
|
||||
m_ImportantGI: 0
|
||||
m_StitchLightmapSeams: 0
|
||||
m_SelectedEditorRenderState: 3
|
||||
m_MinimumChartSize: 4
|
||||
m_AutoUVMaxDistance: 0.5
|
||||
m_AutoUVMaxAngle: 89
|
||||
m_LightmapParameters: {fileID: 0}
|
||||
m_SortingLayerID: 0
|
||||
m_SortingLayer: 0
|
||||
m_SortingOrder: 0
|
||||
m_AdditionalVertexStreams: {fileID: 0}
|
||||
--- !u!64 &1921226931
|
||||
MeshCollider:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1921226928}
|
||||
m_Material: {fileID: 0}
|
||||
m_IsTrigger: 0
|
||||
m_Enabled: 1
|
||||
serializedVersion: 4
|
||||
m_Convex: 0
|
||||
m_CookingOptions: 30
|
||||
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!33 &1921226932
|
||||
MeshFilter:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1921226928}
|
||||
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
|
||||
--- !u!1 &2095842635
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 2095842637}
|
||||
- component: {fileID: 2095842636}
|
||||
m_Layer: 0
|
||||
m_Name: Directional Light
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!108 &2095842636
|
||||
Light:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2095842635}
|
||||
m_Enabled: 1
|
||||
serializedVersion: 10
|
||||
m_Type: 1
|
||||
m_Shape: 0
|
||||
m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1}
|
||||
m_Intensity: 1
|
||||
m_Range: 10
|
||||
m_SpotAngle: 30
|
||||
m_InnerSpotAngle: 21.80208
|
||||
m_CookieSize: 10
|
||||
m_Shadows:
|
||||
m_Type: 2
|
||||
m_Resolution: -1
|
||||
m_CustomResolution: -1
|
||||
m_Strength: 1
|
||||
m_Bias: 0.05
|
||||
m_NormalBias: 0.4
|
||||
m_NearPlane: 0.2
|
||||
m_CullingMatrixOverride:
|
||||
e00: 1
|
||||
e01: 0
|
||||
e02: 0
|
||||
e03: 0
|
||||
e10: 0
|
||||
e11: 1
|
||||
e12: 0
|
||||
e13: 0
|
||||
e20: 0
|
||||
e21: 0
|
||||
e22: 1
|
||||
e23: 0
|
||||
e30: 0
|
||||
e31: 0
|
||||
e32: 0
|
||||
e33: 1
|
||||
m_UseCullingMatrixOverride: 0
|
||||
m_Cookie: {fileID: 0}
|
||||
m_DrawHalo: 0
|
||||
m_Flare: {fileID: 0}
|
||||
m_RenderMode: 0
|
||||
m_CullingMask:
|
||||
serializedVersion: 2
|
||||
m_Bits: 4294967295
|
||||
m_RenderingLayerMask: 1
|
||||
m_Lightmapping: 4
|
||||
m_LightShadowCasterMode: 0
|
||||
m_AreaSize: {x: 1, y: 1}
|
||||
m_BounceIntensity: 1
|
||||
m_ColorTemperature: 6570
|
||||
m_UseColorTemperature: 0
|
||||
m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0}
|
||||
m_UseBoundingSphereOverride: 0
|
||||
m_UseViewFrustumForShadowCasterCull: 1
|
||||
m_ShadowRadius: 0
|
||||
m_ShadowAngle: 0
|
||||
--- !u!4 &2095842637
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 2095842635}
|
||||
m_LocalRotation: {x: -0.008544729, y: -0.21568543, z: 0.9708363, w: -0.10432531}
|
||||
m_LocalPosition: {x: 0, y: 3, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_RootOrder: 0
|
||||
m_LocalEulerAnglesHint: {x: 24.871, y: -358.205, z: -167.337}
|
||||
--- !u!1001 &3051409913039127684
|
||||
PrefabInstance:
|
||||
m_ObjectHideFlags: 0
|
||||
serializedVersion: 2
|
||||
m_Modification:
|
||||
m_TransformParent: {fileID: 306469292}
|
||||
m_Modifications:
|
||||
- target: {fileID: 3051409913850609593, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalScale.z
|
||||
value: -1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609593, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609593, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609593, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609593, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 180
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609595, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_RootOrder
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609595, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalScale.z
|
||||
value: -1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609595, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalPosition.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609595, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: -0.04
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609595, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalPosition.z
|
||||
value: -0.158
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609595, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609595, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalRotation.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609595, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609595, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609595, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.x
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609595, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609595, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609597, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalScale.z
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609599, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalScale.z
|
||||
value: -1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609599, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalRotation.w
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609599, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalRotation.y
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609599, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalRotation.z
|
||||
value: 0
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850609599, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_LocalEulerAnglesHint.y
|
||||
value: 180
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850635163, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_Name
|
||||
value: Avatar_Shieh_V2
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850733890, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_Enabled
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850733890, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: NeededToGetData
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850733895, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: m_Enabled
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3051409913850733895, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
propertyPath: NeededToGetData
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 4e2328178fed81348aec48d0f79c86fa, type: 3}
|
||||
Binary file not shown.
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 139b813ee621cbb41b237fe73214bf9f
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 4890085278179872738
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7eb9da8a5f7ef3740828986abcac7265
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,71 +0,0 @@
|
||||
//========= Copyright 2019, HTC Corporation. All rights reserved. ===========
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
namespace VIVE
|
||||
{
|
||||
namespace FacialTracking.Sample
|
||||
{
|
||||
public static class Eye
|
||||
{
|
||||
public const int WeightingCount = (int)XrEyeShapeHTC.XR_EYE_EXPRESSION_MAX_ENUM_HTC;
|
||||
private static XrFacialExpressionsHTC EyeExpression_;
|
||||
private static int LastUpdateFrame = -1;
|
||||
private static Error LastUpdateResult = Error.FAILED;
|
||||
private static Dictionary<XrEyeShapeHTC, float> Weightings;
|
||||
private static float[] blendshapes = new float[60];
|
||||
static Eye()
|
||||
{
|
||||
Weightings = new Dictionary<XrEyeShapeHTC, float>();
|
||||
for (int i = 0; i < WeightingCount; ++i) Weightings.Add((XrEyeShapeHTC)i, 0.0f);
|
||||
}
|
||||
private static bool UpdateData()
|
||||
{
|
||||
if (Time.frameCount == LastUpdateFrame) return LastUpdateResult == Error.WORK;
|
||||
else LastUpdateFrame = Time.frameCount;
|
||||
EyeExpression_.expressionCount = 60;
|
||||
EyeExpression_.type = XrStructureType.XR_TYPE_FACIAL_EXPRESSIONS_HTC;
|
||||
EyeExpression_.blendShapeWeightings = Marshal.AllocCoTaskMem(sizeof(float) * EyeExpression_.expressionCount);
|
||||
var feature = OpenXRSettings.Instance.GetFeature<VIVE_FacialTracking_OpenXR_API>();
|
||||
int res = feature.xrGetFacialExpressionsHTC(OpenXRSettings.Instance.GetFeature<VIVE_FacialTracking_OpenXR_API>().m_expressionHandle, ref EyeExpression_);
|
||||
if (res == (int)XrResult.XR_SUCCESS)
|
||||
{
|
||||
Marshal.Copy(EyeExpression_.blendShapeWeightings, blendshapes, 0, EyeExpression_.expressionCount);
|
||||
LastUpdateResult = Error.WORK;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
LastUpdateResult = Error.FAILED;
|
||||
}
|
||||
return LastUpdateResult == Error.WORK;
|
||||
}
|
||||
public static bool GetEyeWeightings(out Dictionary<XrEyeShapeHTC, float> shapes, XrFacialExpressionsHTC expression)
|
||||
{
|
||||
for (int i = 0; i < WeightingCount; ++i)
|
||||
{
|
||||
Weightings[(XrEyeShapeHTC)(i)] = blendshapes[i];
|
||||
}
|
||||
shapes = Weightings;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets weighting values from Eye module.
|
||||
/// </summary>
|
||||
/// <param name="shapes">Weighting values obtained from Eye module.</param>
|
||||
/// <returns>Indicates whether the values received are new.</returns>\
|
||||
[Obsolete("Create FacialManager object and call member function GetWeightings instead")]
|
||||
public static bool GetEyeWeightings(out Dictionary<XrEyeShapeHTC, float> shapes)
|
||||
{
|
||||
UpdateData();
|
||||
return GetEyeWeightings(out shapes, EyeExpression_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86a415a999d54da45982ad39e33e9ac1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,32 +0,0 @@
|
||||
//========= Copyright 2018, HTC Corporation. All rights reserved. ===========
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VIVE
|
||||
{
|
||||
namespace FacialTracking.Sample
|
||||
{
|
||||
public enum EyeShape
|
||||
{
|
||||
None = -1,
|
||||
Eye_Left_Blink = 0,
|
||||
Eye_Left_Wide,
|
||||
Eye_Left_Right,
|
||||
Eye_Left_Left,
|
||||
Eye_Left_Up,
|
||||
Eye_Left_Down,
|
||||
Eye_Right_Blink = 6,
|
||||
Eye_Right_Wide,
|
||||
Eye_Right_Right,
|
||||
Eye_Right_Left,
|
||||
Eye_Right_Up,
|
||||
Eye_Right_Down,
|
||||
Eye_Frown = 12,
|
||||
Eye_Left_Squeeze,
|
||||
Eye_Right_Squeeze,
|
||||
Max = 15,
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37460e91d6cb92340a576dfe03bef2b4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,72 +0,0 @@
|
||||
//========= Copyright 2018, HTC Corporation. All rights reserved. ===========
|
||||
#if UNITY_EDITOR
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System;
|
||||
|
||||
namespace VIVE
|
||||
{
|
||||
namespace FacialTracking.Sample
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(EyeShapeTable))]
|
||||
public class EyeShapeTableDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(position, label, property);
|
||||
|
||||
Rect newFieldPosition = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
|
||||
newFieldPosition.height = EditorGUIUtility.singleLineHeight;
|
||||
Rect newLabelPosition = position;
|
||||
newLabelPosition.width -= newFieldPosition.width;
|
||||
newLabelPosition.height = EditorGUIUtility.singleLineHeight;
|
||||
SerializedProperty propSkinedMesh = property.FindPropertyRelative("skinnedMeshRenderer");
|
||||
SerializedProperty propEyeShapes = property.FindPropertyRelative("eyeShapes");
|
||||
EditorGUI.PropertyField(newFieldPosition, propSkinedMesh, GUIContent.none);
|
||||
newFieldPosition.y += EditorGUIUtility.singleLineHeight;
|
||||
|
||||
SkinnedMeshRenderer skinnedMesh = propSkinedMesh.objectReferenceValue as SkinnedMeshRenderer;
|
||||
if (skinnedMesh != null && skinnedMesh.sharedMesh.blendShapeCount > 0)
|
||||
{
|
||||
if (propEyeShapes.arraySize != skinnedMesh.sharedMesh.blendShapeCount)
|
||||
{
|
||||
propEyeShapes.arraySize = skinnedMesh.sharedMesh.blendShapeCount;
|
||||
for (int i = 0; i < skinnedMesh.sharedMesh.blendShapeCount; ++i)
|
||||
{
|
||||
SerializedProperty propEyeShape = propEyeShapes.GetArrayElementAtIndex(i);
|
||||
string elementName = skinnedMesh.sharedMesh.GetBlendShapeName(i);
|
||||
|
||||
propEyeShape.intValue = (int)XrEyeShapeHTC.XR_EYE_SHAPE_NONE_HTC;
|
||||
foreach (XrEyeShapeHTC EyeShape in (XrEyeShapeHTC[])Enum.GetValues(typeof(XrEyeShapeHTC)))
|
||||
{
|
||||
if (elementName == EyeShape.ToString())
|
||||
propEyeShape.intValue = (int)EyeShape;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < skinnedMesh.sharedMesh.blendShapeCount; ++i)
|
||||
{
|
||||
SerializedProperty propEyeShape = propEyeShapes.GetArrayElementAtIndex(i);
|
||||
newLabelPosition.y = newFieldPosition.y;
|
||||
string elementName = skinnedMesh.sharedMesh.GetBlendShapeName(i);
|
||||
EditorGUI.LabelField(newLabelPosition, " " + elementName);
|
||||
EditorGUI.PropertyField(newFieldPosition, propEyeShape, GUIContent.none);
|
||||
newFieldPosition.y += EditorGUIUtility.singleLineHeight;
|
||||
}
|
||||
}
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
int LineCount = 1;
|
||||
SerializedProperty propSkinedMesh = property.FindPropertyRelative("skinnedMeshRenderer");
|
||||
SkinnedMeshRenderer skinnedMesh = propSkinedMesh.objectReferenceValue as SkinnedMeshRenderer;
|
||||
if (skinnedMesh != null) LineCount += skinnedMesh.sharedMesh.blendShapeCount;
|
||||
return EditorGUIUtility.singleLineHeight * LineCount;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fb05e3e629aecd44ebe7dbfc4a7a6d56
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,100 +0,0 @@
|
||||
//========= Copyright 2018, HTC Corporation. All rights reserved. ===========
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
namespace VIVE
|
||||
{
|
||||
namespace FacialTracking.Sample
|
||||
{
|
||||
public class Eye_Framework : MonoBehaviour
|
||||
{
|
||||
public enum FrameworkStatus { STOP, START, WORKING, ERROR, NOT_SUPPORT }
|
||||
/// <summary>
|
||||
/// The status of the Eye engine.
|
||||
/// </summary>
|
||||
public static FrameworkStatus Status { get; protected set; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether to enable Eye module.
|
||||
/// </summary>
|
||||
public bool EnableEye = true;
|
||||
|
||||
private static Eye_Framework Mgr = null;
|
||||
public static Eye_Framework Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Mgr == null)
|
||||
{
|
||||
Mgr = FindObjectOfType<Eye_Framework>();
|
||||
}
|
||||
if (Mgr == null)
|
||||
{
|
||||
Debug.LogError("Eye_Framework not found");
|
||||
}
|
||||
return Mgr;
|
||||
}
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
StartFramework();
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
StopFramework();
|
||||
}
|
||||
[Obsolete("Create FacialManager object and call member function StartFramework instead")]
|
||||
public void StartFramework()
|
||||
{
|
||||
if (!EnableEye) return;
|
||||
if (Status == FrameworkStatus.WORKING || Status == FrameworkStatus.NOT_SUPPORT) return;
|
||||
XrFacialTrackerCreateInfoHTC m_expressioncreateInfo = new XrFacialTrackerCreateInfoHTC(
|
||||
XrStructureType.XR_TYPE_FACIAL_TRACKER_CREATE_INFO_HTC,
|
||||
IntPtr.Zero,
|
||||
XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC);
|
||||
var feature = OpenXRSettings.Instance.GetFeature<VIVE_FacialTracking_OpenXR_API>();
|
||||
int res = feature.xrCreateFacialTrackerHTC(m_expressioncreateInfo, out OpenXRSettings.Instance.GetFeature<VIVE_FacialTracking_OpenXR_API>().m_expressionHandle);
|
||||
if (res == (int)XrResult.XR_SUCCESS || res == (int)XrResult.XR_SESSION_LOSS_PENDING)
|
||||
{
|
||||
Debug.Log("Initial Eye success : " + res);
|
||||
Status = FrameworkStatus.WORKING;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Initial Eye fail : " + res);
|
||||
Status = FrameworkStatus.ERROR;
|
||||
}
|
||||
}
|
||||
[Obsolete("Create FacialManager object and call member function StopFramework instead")]
|
||||
public void StopFramework()
|
||||
{
|
||||
if (Status != FrameworkStatus.NOT_SUPPORT)
|
||||
{
|
||||
if (Status != FrameworkStatus.STOP)
|
||||
{
|
||||
var feature = OpenXRSettings.Instance.GetFeature<VIVE_FacialTracking_OpenXR_API>();
|
||||
int res = feature.xrDestroyFacialTrackerHTC(OpenXRSettings.Instance.GetFeature<VIVE_FacialTracking_OpenXR_API>().m_expressionHandle);
|
||||
if (res == (int)XrResult.XR_SUCCESS)
|
||||
{
|
||||
Debug.Log("Release Eye engine success : " + res);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Release Eye engine fail : " + res);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("Stop Eye Framework : module not on");
|
||||
}
|
||||
}
|
||||
Status = FrameworkStatus.STOP;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e820c013bcd10a4ea94b6d91672f893
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,234 +0,0 @@
|
||||
//========= Copyright 2018, HTC Corporation. All rights reserved. ===========
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VIVE
|
||||
{
|
||||
namespace FacialTracking.Sample
|
||||
{
|
||||
[Serializable]
|
||||
public class EyeShapeTable
|
||||
{
|
||||
public SkinnedMeshRenderer skinnedMeshRenderer;
|
||||
public EyeShape[] eyeShapes;
|
||||
}
|
||||
public class AvatarEyeSample : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private Transform[] EyesModels = new Transform[0];
|
||||
[SerializeField] private List<EyeShapeTable> EyeShapeTables;
|
||||
/// <summary>
|
||||
/// Customize this curve to fit the blend shapes of your avatar.
|
||||
/// </summary>
|
||||
[SerializeField] private AnimationCurve EyebrowAnimationCurveUpper;
|
||||
/// <summary>
|
||||
/// Customize this curve to fit the blend shapes of your avatar.
|
||||
/// </summary>
|
||||
[SerializeField] private AnimationCurve EyebrowAnimationCurveLower;
|
||||
/// <summary>
|
||||
/// Customize this curve to fit the blend shapes of your avatar.
|
||||
/// </summary>
|
||||
[SerializeField] private AnimationCurve EyebrowAnimationCurveHorizontal;
|
||||
|
||||
public bool NeededToGetData = true;
|
||||
private Dictionary<XrEyeShapeHTC, float> EyeWeightings = new Dictionary<XrEyeShapeHTC, float>();
|
||||
//Map Openxr eye shape to Avatar eye blendshape
|
||||
private static Dictionary<EyeShape, XrEyeShapeHTC> ShapeMap;
|
||||
private AnimationCurve[] EyebrowAnimationCurves = new AnimationCurve[(int)EyeShape.Max];
|
||||
private GameObject[] EyeAnchors;
|
||||
private const int NUM_OF_EYES = 2;
|
||||
private static XrFacialExpressionsHTC EyeExpression;
|
||||
private FacialManager facialManager = new FacialManager();
|
||||
static AvatarEyeSample()
|
||||
{
|
||||
ShapeMap = new Dictionary<EyeShape, XrEyeShapeHTC>();
|
||||
ShapeMap.Add(EyeShape.Eye_Left_Blink, XrEyeShapeHTC.XR_EYE_EXPRESSION_LEFT_BLINK_HTC);
|
||||
ShapeMap.Add(EyeShape.Eye_Left_Wide, XrEyeShapeHTC.XR_EYE_EXPRESSION_LEFT_WIDE_HTC);
|
||||
ShapeMap.Add(EyeShape.Eye_Right_Blink, XrEyeShapeHTC.XR_EYE_EXPRESSION_RIGHT_BLINK_HTC);
|
||||
ShapeMap.Add(EyeShape.Eye_Right_Wide, XrEyeShapeHTC.XR_EYE_EXPRESSION_RIGHT_WIDE_HTC);
|
||||
ShapeMap.Add(EyeShape.Eye_Left_Squeeze, XrEyeShapeHTC.XR_EYE_EXPRESSION_LEFT_SQUEEZE_HTC);
|
||||
ShapeMap.Add(EyeShape.Eye_Right_Squeeze, XrEyeShapeHTC.XR_EYE_EXPRESSION_RIGHT_SQUEEZE_HTC);
|
||||
ShapeMap.Add(EyeShape.Eye_Left_Down, XrEyeShapeHTC.XR_EYE_EXPRESSION_LEFT_DOWN_HTC);
|
||||
ShapeMap.Add(EyeShape.Eye_Right_Down, XrEyeShapeHTC.XR_EYE_EXPRESSION_RIGHT_DOWN_HTC);
|
||||
ShapeMap.Add(EyeShape.Eye_Left_Left, XrEyeShapeHTC.XR_EYE_EXPRESSION_LEFT_OUT_HTC);
|
||||
ShapeMap.Add(EyeShape.Eye_Right_Left, XrEyeShapeHTC.XR_EYE_EXPRESSION_RIGHT_IN_HTC);
|
||||
ShapeMap.Add(EyeShape.Eye_Left_Right, XrEyeShapeHTC.XR_EYE_EXPRESSION_LEFT_IN_HTC);
|
||||
ShapeMap.Add(EyeShape.Eye_Right_Right, XrEyeShapeHTC.XR_EYE_EXPRESSION_RIGHT_OUT_HTC);
|
||||
ShapeMap.Add(EyeShape.Eye_Left_Up, XrEyeShapeHTC.XR_EYE_EXPRESSION_LEFT_UP_HTC);
|
||||
ShapeMap.Add(EyeShape.Eye_Right_Up, XrEyeShapeHTC.XR_EYE_EXPRESSION_RIGHT_UP_HTC);
|
||||
}
|
||||
private void Start()
|
||||
{
|
||||
facialManager.StartFramework(XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC);
|
||||
SetEyesModels(EyesModels[0], EyesModels[1]);
|
||||
SetEyeShapeTables(EyeShapeTables);
|
||||
|
||||
AnimationCurve[] curves = new AnimationCurve[(int)EyeShape.Max];
|
||||
for (int i = 0; i < EyebrowAnimationCurves.Length; ++i)
|
||||
{
|
||||
if (i == (int)EyeShape.Eye_Left_Up || i == (int)EyeShape.Eye_Right_Up) curves[i] = EyebrowAnimationCurveUpper;
|
||||
else if (i == (int)EyeShape.Eye_Left_Down || i == (int)EyeShape.Eye_Right_Down) curves[i] = EyebrowAnimationCurveLower;
|
||||
else curves[i] = EyebrowAnimationCurveHorizontal;
|
||||
}
|
||||
SetEyeShapeAnimationCurves(curves);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (NeededToGetData)
|
||||
{
|
||||
facialManager.GetWeightings(out EyeWeightings);
|
||||
UpdateEyeShapes(EyeWeightings);
|
||||
|
||||
|
||||
Vector3 GazeDirectionCombinedLocal = Vector3.zero;
|
||||
if (EyeWeightings[XrEyeShapeHTC.XR_EYE_EXPRESSION_LEFT_IN_HTC] > EyeWeightings[XrEyeShapeHTC.XR_EYE_EXPRESSION_LEFT_OUT_HTC])
|
||||
{
|
||||
GazeDirectionCombinedLocal.x = -1 * EyeWeightings[XrEyeShapeHTC.XR_EYE_EXPRESSION_LEFT_IN_HTC];
|
||||
}
|
||||
else
|
||||
{
|
||||
GazeDirectionCombinedLocal.x = EyeWeightings[XrEyeShapeHTC.XR_EYE_EXPRESSION_LEFT_OUT_HTC];
|
||||
}
|
||||
if (EyeWeightings[XrEyeShapeHTC.XR_EYE_EXPRESSION_LEFT_UP_HTC] > EyeWeightings[XrEyeShapeHTC.XR_EYE_EXPRESSION_LEFT_DOWN_HTC])
|
||||
{
|
||||
GazeDirectionCombinedLocal.y = EyeWeightings[XrEyeShapeHTC.XR_EYE_EXPRESSION_LEFT_UP_HTC];
|
||||
}
|
||||
else
|
||||
{
|
||||
GazeDirectionCombinedLocal.y = -EyeWeightings[XrEyeShapeHTC.XR_EYE_EXPRESSION_LEFT_DOWN_HTC];
|
||||
}
|
||||
GazeDirectionCombinedLocal.z = (float)1.0;
|
||||
|
||||
Vector3 target = EyeAnchors[0].transform.TransformPoint(GazeDirectionCombinedLocal);
|
||||
EyesModels[0].LookAt(target);
|
||||
|
||||
if (EyeWeightings[XrEyeShapeHTC.XR_EYE_EXPRESSION_RIGHT_IN_HTC] > EyeWeightings[XrEyeShapeHTC.XR_EYE_EXPRESSION_RIGHT_OUT_HTC])
|
||||
{
|
||||
GazeDirectionCombinedLocal.x = EyeWeightings[XrEyeShapeHTC.XR_EYE_EXPRESSION_RIGHT_IN_HTC];
|
||||
}
|
||||
else
|
||||
{
|
||||
GazeDirectionCombinedLocal.x = -1 * EyeWeightings[XrEyeShapeHTC.XR_EYE_EXPRESSION_RIGHT_OUT_HTC];
|
||||
}
|
||||
if (EyeWeightings[XrEyeShapeHTC.XR_EYE_EXPRESSION_RIGHT_UP_HTC] > EyeWeightings[XrEyeShapeHTC.XR_EYE_EXPRESSION_RIGHT_DOWN_HTC])
|
||||
{
|
||||
GazeDirectionCombinedLocal.y = EyeWeightings[XrEyeShapeHTC.XR_EYE_EXPRESSION_RIGHT_UP_HTC];
|
||||
}
|
||||
else
|
||||
{
|
||||
GazeDirectionCombinedLocal.y = -EyeWeightings[XrEyeShapeHTC.XR_EYE_EXPRESSION_RIGHT_DOWN_HTC];
|
||||
}
|
||||
GazeDirectionCombinedLocal.z = (float)1.0;
|
||||
|
||||
target = EyeAnchors[1].transform.TransformPoint(GazeDirectionCombinedLocal);
|
||||
EyesModels[1].LookAt(target);
|
||||
}
|
||||
}
|
||||
private void OnDestroy()
|
||||
{
|
||||
facialManager.StopFramework(XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC);
|
||||
DestroyEyeAnchors();
|
||||
}
|
||||
|
||||
public void SetEyesModels(Transform leftEye, Transform rightEye)
|
||||
{
|
||||
if (leftEye != null && rightEye != null)
|
||||
{
|
||||
EyesModels = new Transform[NUM_OF_EYES] { leftEye, rightEye };
|
||||
DestroyEyeAnchors();
|
||||
CreateEyeAnchors();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetEyeShapeTables(List<EyeShapeTable> eyeShapeTables)
|
||||
{
|
||||
bool valid = true;
|
||||
if (eyeShapeTables == null)
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int table = 0; table < eyeShapeTables.Count; ++table)
|
||||
{
|
||||
if (eyeShapeTables[table].skinnedMeshRenderer == null)
|
||||
{
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
for (int shape = 0; shape < eyeShapeTables[table].eyeShapes.Length; ++shape)
|
||||
{
|
||||
EyeShape eyeShape = eyeShapeTables[table].eyeShapes[shape];
|
||||
if (eyeShape > EyeShape.Max || eyeShape < 0)
|
||||
{
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (valid)
|
||||
EyeShapeTables = eyeShapeTables;
|
||||
}
|
||||
|
||||
public void SetEyeShapeAnimationCurves(AnimationCurve[] eyebrowAnimationCurves)
|
||||
{
|
||||
if (eyebrowAnimationCurves.Length == (int)EyeShape.Max)
|
||||
EyebrowAnimationCurves = eyebrowAnimationCurves;
|
||||
}
|
||||
|
||||
public void UpdateEyeShapes(Dictionary<XrEyeShapeHTC, float> eyeWeightings)
|
||||
{
|
||||
foreach (var table in EyeShapeTables)
|
||||
RenderModelEyeShape(table, eyeWeightings);
|
||||
}
|
||||
|
||||
private void RenderModelEyeShape(EyeShapeTable eyeShapeTable, Dictionary<XrEyeShapeHTC, float> weighting)
|
||||
{
|
||||
for (int i = 0; i < eyeShapeTable.eyeShapes.Length; ++i)
|
||||
{
|
||||
EyeShape eyeShape = eyeShapeTable.eyeShapes[i];
|
||||
if (eyeShape > EyeShape.Max || eyeShape < 0 || !ShapeMap.ContainsKey(eyeShape)) continue;
|
||||
XrEyeShapeHTC xreyeshape = ShapeMap[eyeShape];
|
||||
if (eyeShape == EyeShape.Eye_Left_Blink || eyeShape == EyeShape.Eye_Right_Blink)
|
||||
{
|
||||
|
||||
eyeShapeTable.skinnedMeshRenderer.SetBlendShapeWeight(i, weighting[xreyeshape] * 100f);
|
||||
}
|
||||
else
|
||||
{
|
||||
AnimationCurve curve = EyebrowAnimationCurves[(int)eyeShape];
|
||||
eyeShapeTable.skinnedMeshRenderer.SetBlendShapeWeight(i, curve.Evaluate(weighting[xreyeshape]) * 100f);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateEyeAnchors()
|
||||
{
|
||||
EyeAnchors = new GameObject[NUM_OF_EYES];
|
||||
for (int i = 0; i < NUM_OF_EYES; ++i)
|
||||
{
|
||||
EyeAnchors[i] = new GameObject();
|
||||
EyeAnchors[i].name = "EyeAnchor_" + i;
|
||||
EyeAnchors[i].transform.SetParent(gameObject.transform);
|
||||
EyeAnchors[i].transform.localPosition = EyesModels[i].localPosition;
|
||||
EyeAnchors[i].transform.localRotation = EyesModels[i].localRotation;
|
||||
EyeAnchors[i].transform.localScale = EyesModels[i].localScale;
|
||||
}
|
||||
}
|
||||
|
||||
private void DestroyEyeAnchors()
|
||||
{
|
||||
if (EyeAnchors != null)
|
||||
{
|
||||
foreach (var obj in EyeAnchors)
|
||||
if (obj != null) Destroy(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2872c722b18f6d043ad0dbae08561d64
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,35 +0,0 @@
|
||||
//========= Copyright 2018, HTC Corporation. All rights reserved. ===========
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VIVE
|
||||
{
|
||||
namespace FacialTracking.Sample
|
||||
{
|
||||
/// <summary>
|
||||
/// A very basic mirror.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Camera))]
|
||||
public class MirrorCameraSample_Eye : MonoBehaviour
|
||||
{
|
||||
private const float Distance = 0.6f;
|
||||
private void Update()
|
||||
{
|
||||
if (Eye_Framework.Status != Eye_Framework.FrameworkStatus.WORKING) return;
|
||||
|
||||
}
|
||||
|
||||
private void Release()
|
||||
{
|
||||
}
|
||||
private void SetMirroTransform()
|
||||
{
|
||||
transform.position = Camera.main.transform.position + Camera.main.transform.forward * Distance;
|
||||
transform.position = new Vector3(transform.position.x, Camera.main.transform.position.y, transform.position.z);
|
||||
transform.LookAt(Camera.main.transform);
|
||||
transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19eff34b54274a84c8b0f87cffbfd76a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,22 +0,0 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace VIVE.FacialTracking.Sample
|
||||
{
|
||||
public class FollowCamera : MonoBehaviour
|
||||
{
|
||||
// Start is called before the first frame update
|
||||
public new Transform camera;
|
||||
private Vector3 offset;
|
||||
void Start()
|
||||
{
|
||||
this.transform.position = new Vector3(camera.position.x, camera.position.y, camera.position.z + 1);
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
this.transform.position = new Vector3(this.transform.position.x, camera.position.y, this.transform.position.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 196084005ab84764aac2e78a079dc66c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 412f6d64b6ea21045b60b739f1a83f31
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,71 +0,0 @@
|
||||
//========= Copyright 2019, HTC Corporation. All rights reserved. ===========
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
namespace VIVE
|
||||
{
|
||||
namespace FacialTracking.Sample
|
||||
{
|
||||
public class Lip
|
||||
{
|
||||
public const int WeightingCount = (int)XrLipShapeHTC.XR_LIP_SHAPE_MAX_ENUM_HTC;
|
||||
private static int LastUpdateFrame = -1;
|
||||
private static Error LastUpdateResult = Error.FAILED;
|
||||
private static Dictionary<XrLipShapeHTC, float> Weightings;
|
||||
private static float[] blendshapes = new float[60];
|
||||
private static XrFacialExpressionsHTC LipExpression;
|
||||
|
||||
static Lip()
|
||||
{
|
||||
Weightings = new Dictionary<XrLipShapeHTC, float>();
|
||||
for (int i = 0; i < WeightingCount; ++i) Weightings.Add((XrLipShapeHTC)i, 0.0f);
|
||||
}
|
||||
|
||||
private static bool UpdateData()
|
||||
{
|
||||
if (Time.frameCount == LastUpdateFrame) return LastUpdateResult == Error.WORK;
|
||||
else LastUpdateFrame = Time.frameCount;
|
||||
LipExpression.expressionCount = 60;
|
||||
LipExpression.type = XrStructureType.XR_TYPE_FACIAL_EXPRESSIONS_HTC;
|
||||
LipExpression.blendShapeWeightings = Marshal.AllocCoTaskMem(sizeof(float)* LipExpression.expressionCount);
|
||||
var feature = OpenXRSettings.Instance.GetFeature<VIVE_FacialTracking_OpenXR_API>();
|
||||
int res = feature.xrGetFacialExpressionsHTC(OpenXRSettings.Instance.GetFeature<VIVE_FacialTracking_OpenXR_API>().m_expressionHandle_Lip, ref LipExpression);
|
||||
|
||||
|
||||
if(res == (int)XrResult.XR_SUCCESS)
|
||||
{
|
||||
LastUpdateResult = Error.WORK;
|
||||
Marshal.Copy(LipExpression.blendShapeWeightings, blendshapes,0, LipExpression.expressionCount);
|
||||
for (int i = 0; i < WeightingCount; ++i)
|
||||
{
|
||||
Weightings[(XrLipShapeHTC)(i)] = blendshapes[i];
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
LastUpdateResult = Error.FAILED;
|
||||
}
|
||||
return LastUpdateResult == Error.WORK;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets weighting values from Lip module.
|
||||
/// </summary>
|
||||
/// <param name="shapes">Weighting values obtained from Lip module.</param>
|
||||
/// <returns>Indicates whether the values received are new.</returns>
|
||||
[Obsolete("Create FacialManager object and call member function GetWeightings instead")]
|
||||
public static bool GetLipWeightings(out Dictionary<XrLipShapeHTC, float> shapes)
|
||||
{
|
||||
bool update = UpdateData();
|
||||
shapes = Weightings;
|
||||
return update;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8bc508f7f051e624181e0391cf04db7f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,69 +0,0 @@
|
||||
//========= Copyright 2019, HTC Corporation. All rights reserved. ===========
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace VIVE
|
||||
{
|
||||
namespace FacialTracking.Sample
|
||||
{
|
||||
public enum LipShape
|
||||
{
|
||||
None = -1,
|
||||
Jaw_Right = 0,
|
||||
Jaw_Left = 1,
|
||||
Jaw_Forward = 2,
|
||||
Jaw_Open = 3,
|
||||
Mouth_Ape_Shape = 4,
|
||||
Mouth_Upper_Right = 5,
|
||||
Mouth_Upper_Left = 6,
|
||||
Mouth_Lower_Right = 7,
|
||||
Mouth_Lower_Left = 8,
|
||||
Mouth_Upper_Overturn = 9,
|
||||
Mouth_Lower_Overturn = 10,
|
||||
Mouth_Pout = 11,
|
||||
Mouth_Smile_Right = 12,
|
||||
Mouth_Smile_Left = 13,
|
||||
Mouth_Sad_Right = 14,
|
||||
Mouth_Sad_Left = 15,
|
||||
Cheek_Puff_Right = 16,
|
||||
Cheek_Puff_Left = 17,
|
||||
Cheek_Suck = 18,
|
||||
Mouth_Upper_UpRight = 19,
|
||||
Mouth_Upper_UpLeft = 20,
|
||||
Mouth_Lower_DownRight = 21,
|
||||
Mouth_Lower_DownLeft = 22,
|
||||
Mouth_Upper_Inside = 23,
|
||||
Mouth_Lower_Inside = 24,
|
||||
Mouth_Lower_Overlay = 25,
|
||||
Tongue_LongStep1 = 26,
|
||||
Tongue_LongStep2 = 32,
|
||||
Tongue_Down = 30,
|
||||
Tongue_Up = 29,
|
||||
Tongue_Right = 28,
|
||||
Tongue_Left = 27,
|
||||
Tongue_Roll = 31,
|
||||
Tongue_UpLeft_Morph = 34,
|
||||
Tongue_UpRight_Morph = 33,
|
||||
Tongue_DownLeft_Morph = 36,
|
||||
Tongue_DownRight_Morph = 35,
|
||||
Max = 37,
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct PredictionData
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 60)]
|
||||
public float[] blend_shape_weight;
|
||||
};
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct LipData
|
||||
{
|
||||
public int frame;
|
||||
public int time;
|
||||
public IntPtr image;
|
||||
public PredictionData prediction_data;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44593dc2ec4dd36449dfb356ce482a0d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,73 +0,0 @@
|
||||
//========= Copyright 2019, HTC Corporation. All rights reserved. ===========
|
||||
#if UNITY_EDITOR
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System;
|
||||
|
||||
namespace VIVE
|
||||
{
|
||||
namespace FacialTracking.Sample
|
||||
{
|
||||
|
||||
[CustomPropertyDrawer(typeof(LipShapeTable))]
|
||||
public class LipShapeTableDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(position, label, property);
|
||||
|
||||
Rect newFieldPosition = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
|
||||
newFieldPosition.height = EditorGUIUtility.singleLineHeight;
|
||||
Rect newLabelPosition = position;
|
||||
newLabelPosition.width -= newFieldPosition.width;
|
||||
newLabelPosition.height = newFieldPosition.height;
|
||||
SerializedProperty propSkinedMesh = property.FindPropertyRelative("skinnedMeshRenderer");
|
||||
SerializedProperty propLipShapes = property.FindPropertyRelative("lipShapes");
|
||||
EditorGUI.PropertyField(newFieldPosition, propSkinedMesh, GUIContent.none);
|
||||
newFieldPosition.y += EditorGUIUtility.singleLineHeight;
|
||||
|
||||
SkinnedMeshRenderer skinnedMesh = propSkinedMesh.objectReferenceValue as SkinnedMeshRenderer;
|
||||
if (skinnedMesh != null && skinnedMesh.sharedMesh.blendShapeCount > 0)
|
||||
{
|
||||
if (propLipShapes.arraySize != skinnedMesh.sharedMesh.blendShapeCount)
|
||||
{
|
||||
propLipShapes.arraySize = skinnedMesh.sharedMesh.blendShapeCount;
|
||||
for (int i = 0; i < skinnedMesh.sharedMesh.blendShapeCount; ++i)
|
||||
{
|
||||
SerializedProperty propLipShape = propLipShapes.GetArrayElementAtIndex(i);
|
||||
string elementName = skinnedMesh.sharedMesh.GetBlendShapeName(i);
|
||||
|
||||
propLipShape.intValue = (int)XrLipShapeHTC.XR_LIP_SHAPE_NONE_HTC;
|
||||
foreach (XrLipShapeHTC lipShape in (XrLipShapeHTC[])Enum.GetValues(typeof(XrLipShapeHTC)))
|
||||
{
|
||||
if (elementName == lipShape.ToString())
|
||||
propLipShape.intValue = (int)lipShape;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < skinnedMesh.sharedMesh.blendShapeCount; ++i)
|
||||
{
|
||||
SerializedProperty propLipShape = propLipShapes.GetArrayElementAtIndex(i);
|
||||
newLabelPosition.y = newFieldPosition.y;
|
||||
string elementName = skinnedMesh.sharedMesh.GetBlendShapeName(i);
|
||||
EditorGUI.LabelField(newLabelPosition, " " + elementName);
|
||||
EditorGUI.PropertyField(newFieldPosition, propLipShape, GUIContent.none);
|
||||
newFieldPosition.y += EditorGUIUtility.singleLineHeight;
|
||||
}
|
||||
}
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
int LineCount = 1;
|
||||
SerializedProperty propSkinedMesh = property.FindPropertyRelative("skinnedMeshRenderer");
|
||||
SkinnedMeshRenderer skinnedMesh = propSkinedMesh.objectReferenceValue as SkinnedMeshRenderer;
|
||||
if (skinnedMesh != null) LineCount += skinnedMesh.sharedMesh.blendShapeCount;
|
||||
return EditorGUIUtility.singleLineHeight * LineCount;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91324d258827df746818399b9a51d4d5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,103 +0,0 @@
|
||||
//========= Copyright 2019, HTC Corporation. All rights reserved. ===========
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
|
||||
namespace VIVE
|
||||
{
|
||||
namespace FacialTracking.Sample
|
||||
{
|
||||
public class Lip_Framework : MonoBehaviour
|
||||
{
|
||||
public enum FrameworkStatus { STOP, START, WORKING, ERROR }
|
||||
/// <summary>
|
||||
/// The status of the Lip engine.
|
||||
/// </summary>
|
||||
public static FrameworkStatus Status { get; protected set; }
|
||||
/// <summary>
|
||||
/// Whether to enable Lip module.
|
||||
/// </summary>
|
||||
public bool EnableLip = true;
|
||||
|
||||
private static Lip_Framework Mgr = null;
|
||||
public static Lip_Framework Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Mgr == null)
|
||||
{
|
||||
Mgr = FindObjectOfType<Lip_Framework>();
|
||||
}
|
||||
if (Mgr == null)
|
||||
{
|
||||
Debug.LogError("Lip_Framework not found");
|
||||
}
|
||||
return Mgr;
|
||||
}
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
StartFramework();
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
StopFramework();
|
||||
}
|
||||
[Obsolete("Create FacialManager object and call member function StartFramework instead")]
|
||||
|
||||
private void StartFramework()
|
||||
{
|
||||
if (!EnableLip) return;
|
||||
if (Status == FrameworkStatus.WORKING) return;
|
||||
|
||||
Status = FrameworkStatus.START;
|
||||
|
||||
Debug.Log("Starting to Initial Lip Engine");
|
||||
XrFacialTrackerCreateInfoHTC m_expressioncreateInfo = new XrFacialTrackerCreateInfoHTC(
|
||||
XrStructureType.XR_TYPE_FACIAL_TRACKER_CREATE_INFO_HTC,
|
||||
IntPtr.Zero,
|
||||
XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC);
|
||||
var feature = OpenXRSettings.Instance.GetFeature<VIVE_FacialTracking_OpenXR_API>();
|
||||
int res = (int)feature.xrCreateFacialTrackerHTC(m_expressioncreateInfo, out OpenXRSettings.Instance.GetFeature<VIVE_FacialTracking_OpenXR_API>().m_expressionHandle_Lip);
|
||||
if (res == (int)XrResult.XR_SUCCESS || res == (int)XrResult.XR_SESSION_LOSS_PENDING)
|
||||
{
|
||||
Debug.Log("Initial Lip Engine :" + res);
|
||||
Status = FrameworkStatus.WORKING;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Initial Lip Engine :" + res);
|
||||
Status = FrameworkStatus.ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
[Obsolete("Create FacialManager object and call member function StopFramework instead")]
|
||||
|
||||
public void StopFramework()
|
||||
{
|
||||
if (Status != FrameworkStatus.STOP)
|
||||
{
|
||||
var feature = OpenXRSettings.Instance.GetFeature<VIVE_FacialTracking_OpenXR_API>();
|
||||
int res = feature.xrDestroyFacialTrackerHTC(OpenXRSettings.Instance.GetFeature<VIVE_FacialTracking_OpenXR_API>().m_expressionHandle_Lip);
|
||||
if (res == (int)XrResult.XR_SUCCESS)
|
||||
{
|
||||
Debug.Log("Release Lip Engine : " + res);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Release Lip Engine : " + res);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("Stop Lip Framework : module not on");
|
||||
}
|
||||
Status = FrameworkStatus.STOP;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 846f91cae57562348bd10c1617b45b13
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,93 +0,0 @@
|
||||
//========= Copyright 2019, HTC Corporation. All rights reserved. ===========
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace VIVE
|
||||
{
|
||||
namespace FacialTracking.Sample
|
||||
{
|
||||
[Serializable]
|
||||
public class LipShapeTable
|
||||
{
|
||||
public SkinnedMeshRenderer skinnedMeshRenderer;
|
||||
public XrLipShapeHTC[] lipShapes;
|
||||
}
|
||||
public class AvatarLipSample : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private List<LipShapeTable> LipShapeTables;
|
||||
|
||||
public bool NeededToGetData = true;
|
||||
private Dictionary<XrLipShapeHTC, float> LipWeightings;
|
||||
private FacialManager facialManager = new FacialManager();
|
||||
private void Start()
|
||||
{
|
||||
facialManager.StartFramework(XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC);
|
||||
SetLipShapeTables(LipShapeTables);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (NeededToGetData)
|
||||
{
|
||||
facialManager.GetWeightings(out LipWeightings);
|
||||
//Lip.GetLipWeightings(out LipWeightings);
|
||||
UpdateLipShapes(LipWeightings);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetLipShapeTables(List<LipShapeTable> lipShapeTables)
|
||||
{
|
||||
bool valid = true;
|
||||
if (lipShapeTables == null)
|
||||
{
|
||||
valid = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int table = 0; table < lipShapeTables.Count; ++table)
|
||||
{
|
||||
if (lipShapeTables[table].skinnedMeshRenderer == null)
|
||||
{
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
for (int shape = 0; shape < lipShapeTables[table].lipShapes.Length; ++shape)
|
||||
{
|
||||
XrLipShapeHTC lipShape = lipShapeTables[table].lipShapes[shape];
|
||||
if (lipShape > XrLipShapeHTC.XR_LIP_SHAPE_MAX_ENUM_HTC || lipShape < 0)
|
||||
{
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (valid)
|
||||
LipShapeTables = lipShapeTables;
|
||||
}
|
||||
|
||||
public void UpdateLipShapes(Dictionary<XrLipShapeHTC, float> lipWeightings)
|
||||
{
|
||||
foreach (var table in LipShapeTables)
|
||||
RenderModelLipShape(table, lipWeightings);
|
||||
}
|
||||
|
||||
private void RenderModelLipShape(LipShapeTable lipShapeTable, Dictionary<XrLipShapeHTC, float> weighting)
|
||||
{
|
||||
for (int i = 0; i < lipShapeTable.lipShapes.Length; i++)
|
||||
{
|
||||
int targetIndex = (int)lipShapeTable.lipShapes[i];
|
||||
if (targetIndex > (int)XrLipShapeHTC.XR_LIP_SHAPE_MAX_ENUM_HTC || targetIndex < 0) continue;
|
||||
lipShapeTable.skinnedMeshRenderer.SetBlendShapeWeight(i, weighting[(XrLipShapeHTC)targetIndex] * 100);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
facialManager.StopFramework(XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42350b51669fc604cb2cad73c39f116c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,32 +0,0 @@
|
||||
//========= Copyright 2019, HTC Corporation. All rights reserved. ===========
|
||||
using UnityEngine;
|
||||
|
||||
namespace VIVE
|
||||
{
|
||||
namespace FacialTracking.Sample
|
||||
{
|
||||
/// <summary>
|
||||
/// A very basic mirror.
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(Camera))]
|
||||
public class MirrorCameraSample_Lip : MonoBehaviour
|
||||
{
|
||||
private const float Distance = 0.6f;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Lip_Framework.Status != Lip_Framework.FrameworkStatus.WORKING) return;
|
||||
SetMirroTransform();
|
||||
}
|
||||
|
||||
private void SetMirroTransform()
|
||||
{
|
||||
transform.position = Camera.main.transform.position + Camera.main.transform.forward * Distance;
|
||||
transform.position = new Vector3(transform.position.x, Camera.main.transform.position.y, transform.position.z);
|
||||
transform.LookAt(Camera.main.transform);
|
||||
transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c81a0042ed8435d4097d6717e1b45dd8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a49f13dd5640c8d4e89b897d41545ac2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,216 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using System;
|
||||
namespace VIVE.FacialTracking
|
||||
{
|
||||
public class FacialManager
|
||||
{
|
||||
private class FacialData
|
||||
{
|
||||
public bool isStarted = false;
|
||||
public XrFacialTrackingTypeHTC trackingType;
|
||||
public bool isActive;
|
||||
public ulong trackerHandle;
|
||||
public int updatedFrame = -1;
|
||||
public Dictionary<XrEyeShapeHTC, float> eyeWeightings = new Dictionary<XrEyeShapeHTC, float>();
|
||||
public Dictionary<XrLipShapeHTC, float> LipWeightings = new Dictionary<XrLipShapeHTC, float>();
|
||||
public float[] blendshapes;
|
||||
public bool isCreated { get { return trackerHandle != default; } }
|
||||
public FacialData(XrFacialTrackingTypeHTC type)
|
||||
{
|
||||
trackingType = type;
|
||||
for (int i = 0; i < (int)XrEyeShapeHTC.XR_EYE_EXPRESSION_MAX_ENUM_HTC; ++i) eyeWeightings.Add((XrEyeShapeHTC)i, 0.0f);
|
||||
for (int i = 0; i < (int)XrLipShapeHTC.XR_LIP_SHAPE_MAX_ENUM_HTC; ++i) LipWeightings.Add((XrLipShapeHTC)i, 0.0f);
|
||||
int shapeSize = type == XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC
|
||||
? (int)XrEyeShapeHTC.XR_EYE_EXPRESSION_MAX_ENUM_HTC : (int)XrLipShapeHTC.XR_LIP_SHAPE_MAX_ENUM_HTC;
|
||||
blendshapes = new float[shapeSize];
|
||||
}
|
||||
public void ClearData()
|
||||
{
|
||||
Array.Clear(blendshapes, 0, blendshapes.Length);
|
||||
eyeWeightings.Clear();
|
||||
LipWeightings.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private FacialData eyeFacialData = new FacialData(XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC);
|
||||
private FacialData lipFacialData = new FacialData(XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC);
|
||||
private VIVE_FacialTracking_OpenXR_API feature;
|
||||
private static bool isInitialized;
|
||||
private static bool isSystemSupportEye;
|
||||
private static bool isSystemSupportLip;
|
||||
|
||||
private FacialData getFacialData(XrFacialTrackingTypeHTC type)
|
||||
{
|
||||
if (type == XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC)
|
||||
return eyeFacialData;
|
||||
else
|
||||
return lipFacialData;
|
||||
}
|
||||
|
||||
private void OnFeatureSessionCreate(ulong xrSession)
|
||||
{
|
||||
TryCreateFacialTracker(eyeFacialData);
|
||||
TryCreateFacialTracker(lipFacialData);
|
||||
}
|
||||
private void OnFeatureSessionDestroy(ulong xrSession)
|
||||
{
|
||||
TryDestroyFacialTracker(eyeFacialData);
|
||||
TryDestroyFacialTracker(lipFacialData);
|
||||
}
|
||||
|
||||
private void OnFeatureSystemChange(ulong systemId)
|
||||
{
|
||||
UpdateSystemSupported();
|
||||
}
|
||||
|
||||
private void UpdateSystemSupported()
|
||||
{
|
||||
if (feature == null || !feature.IsEnabledAndInitialized)
|
||||
{
|
||||
isSystemSupportEye = false;
|
||||
isSystemSupportLip = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
feature.SystemSupportsFacialTracking(out var result,out isSystemSupportEye,out isSystemSupportLip);
|
||||
if (result != XrResult.XR_SUCCESS)
|
||||
{
|
||||
Debug.LogWarning("Fail SystemSupportsHandTracking: " + result);
|
||||
}
|
||||
if (!isSystemSupportEye)
|
||||
{
|
||||
UnityEngine.Debug.Log("Initial eyetracking failed , the device may not support EyeExpression");
|
||||
}
|
||||
if (!isSystemSupportLip)
|
||||
{
|
||||
UnityEngine.Debug.Log("Initial liptracking failed , the device may not support LipExpression");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public bool Initialize()
|
||||
{
|
||||
if(feature == null)
|
||||
feature = OpenXRSettings.Instance.GetFeature<VIVE_FacialTracking_OpenXR_API>();
|
||||
if (!isInitialized)
|
||||
{
|
||||
if (feature != null)
|
||||
{
|
||||
feature.onSessionCreate += OnFeatureSessionCreate;
|
||||
feature.onSessionDestroy += OnFeatureSessionDestroy;
|
||||
feature.onSystemChange += OnFeatureSystemChange;
|
||||
}
|
||||
if (feature != null && feature.IsEnabledAndInitialized)
|
||||
{
|
||||
UpdateSystemSupported();
|
||||
isInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
return isInitialized;
|
||||
}
|
||||
private bool TryCreateFacialTracker(FacialData facialData)
|
||||
{
|
||||
if (!facialData.isStarted) return false;
|
||||
if (!Initialize()) { return false; }
|
||||
if (facialData.trackingType == XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC && !isSystemSupportEye) { return false; }
|
||||
if (facialData.trackingType == XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_LIP_DEFAULT_HTC && !isSystemSupportLip) { return false; }
|
||||
if (!feature.IsSessionCreated) { return false; }
|
||||
if (!facialData.isCreated)
|
||||
{
|
||||
if (!feature.TryCreateFacialTracker(facialData.trackingType, out facialData.trackerHandle, out var result))
|
||||
{
|
||||
facialData.trackerHandle = default;
|
||||
Debug.LogWarning("Fail CreateFacialTracker: " + result);
|
||||
}
|
||||
}
|
||||
|
||||
return facialData.isCreated;
|
||||
}
|
||||
|
||||
private void TryDestroyFacialTracker(FacialData facialData)
|
||||
{
|
||||
if (!facialData.isCreated) { return; }
|
||||
if (!Initialize()) { return; }
|
||||
|
||||
if(!feature.TryDestroFacialTracker(facialData.trackerHandle, out var res))
|
||||
{
|
||||
Debug.LogWarning("Fail DestroyFacialTracker: " + res);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("Success DestroyFacialTracker: " + res);
|
||||
}
|
||||
facialData.trackerHandle = default;
|
||||
facialData.ClearData();
|
||||
}
|
||||
private void TryGetFacialData(FacialData facialData)
|
||||
{
|
||||
if(facialData.isCreated)
|
||||
{
|
||||
if(facialData.updatedFrame != Time.frameCount)
|
||||
{
|
||||
int maxExpressionCount = facialData.trackingType == XrFacialTrackingTypeHTC.XR_FACIAL_TRACKING_TYPE_EYE_DEFAULT_HTC
|
||||
? (int)XrEyeShapeHTC.XR_EYE_EXPRESSION_MAX_ENUM_HTC : (int)XrLipShapeHTC.XR_LIP_SHAPE_MAX_ENUM_HTC;
|
||||
facialData.updatedFrame = Time.frameCount;
|
||||
if (!feature.TryGetFacialData(
|
||||
facialData.trackerHandle,
|
||||
out facialData.isActive,
|
||||
maxExpressionCount,
|
||||
out var result,
|
||||
facialData.blendshapes))
|
||||
{
|
||||
facialData.isActive = false;
|
||||
Debug.LogWarning("Fail TryGetFacialData: " + result);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public void StartFramework(XrFacialTrackingTypeHTC type)
|
||||
{
|
||||
var facialdata = getFacialData(type);
|
||||
facialdata.isStarted = true;
|
||||
TryCreateFacialTracker(facialdata);
|
||||
}
|
||||
public void StopFramework(XrFacialTrackingTypeHTC type)
|
||||
{
|
||||
var facialdata = getFacialData(type);
|
||||
facialdata.isStarted = false;
|
||||
TryDestroyFacialTracker(facialdata);
|
||||
}
|
||||
public bool GetWeightings<T>(out Dictionary<T, float> shapes)
|
||||
{
|
||||
if (typeof(T) == typeof(XrEyeShapeHTC))
|
||||
{
|
||||
TryGetFacialData(eyeFacialData);
|
||||
for (int i = 0; i < (int)XrEyeShapeHTC.XR_EYE_EXPRESSION_MAX_ENUM_HTC; ++i)
|
||||
{
|
||||
eyeFacialData.eyeWeightings[(XrEyeShapeHTC)i] = eyeFacialData.blendshapes[i];
|
||||
}
|
||||
shapes = (Dictionary<T, float>)(System.Object)(eyeFacialData.eyeWeightings);
|
||||
return true;
|
||||
}
|
||||
else if (typeof(T) == typeof(XrLipShapeHTC))
|
||||
{
|
||||
TryGetFacialData(lipFacialData);
|
||||
for (int i = 0; i < (int)XrLipShapeHTC.XR_LIP_SHAPE_MAX_ENUM_HTC; ++i)
|
||||
{
|
||||
lipFacialData.LipWeightings[(XrLipShapeHTC)i] = lipFacialData.blendshapes[i];
|
||||
}
|
||||
shapes = (Dictionary<T, float>)(System.Object)(lipFacialData.LipWeightings);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
shapes = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,192 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEditor;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
#endif
|
||||
namespace VIVE
|
||||
{
|
||||
namespace FacialTracking
|
||||
{
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[OpenXRFeature(UiName = "Facial Tracking",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Standalone },
|
||||
Company = "HTC",
|
||||
Desc = "Facial Tracking OpenXR Feature",
|
||||
DocumentationLink = "https://developer.vive.com/resources/openxr/openxr-pcvr/tutorials/unity/integrate-facial-tracking-your-avatar/",
|
||||
OpenxrExtensionStrings = "XR_HTC_facial_tracking",
|
||||
Version = "0.0.1",
|
||||
FeatureId = featureId)]
|
||||
#endif
|
||||
public class VIVE_FacialTracking_OpenXR_API : OpenXRFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// The feature id string. This is used to give the feature a well known id for reference.
|
||||
/// </summary>
|
||||
public const string featureId = "com.htc.openxr.facialtracking.feature";
|
||||
private ulong m_XrInstance;
|
||||
private ulong m_XrSession;
|
||||
private ulong m_systemid;
|
||||
[Obsolete] XrSystemProperties systemProperties;
|
||||
[Obsolete] public ulong m_expressionHandle;
|
||||
[Obsolete] public ulong m_expressionHandle_Lip;
|
||||
|
||||
public bool IsInitialized { get { return m_xrGetSystemProperties != null; } }
|
||||
public bool IsEnabledAndInitialized { get { return enabled && IsInitialized; } }
|
||||
public bool IsSessionCreated { get { return XrSession != default; } }
|
||||
public ulong XrInstance { get { return m_XrInstance; } }
|
||||
public ulong XrSession { get { return m_XrSession; } }
|
||||
public ulong SystemId { get { return m_systemid; } }
|
||||
|
||||
public event Action<ulong> onSessionCreate;
|
||||
public event Action<ulong> onSessionDestroy;
|
||||
public event Action<ulong> onSystemChange;
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool OnInstanceCreate(ulong xrInstance)
|
||||
{
|
||||
UnityEngine.Debug.Log($"OnInstanceCreate({xrInstance:X})");
|
||||
m_XrInstance = xrInstance;
|
||||
|
||||
return GetXrFunctionDelegates(xrInstance);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void OnInstanceDestroy(ulong xrInstance)
|
||||
{
|
||||
UnityEngine.Debug.Log($"OnInstanceDestroy({xrInstance:X})");
|
||||
m_XrInstance = default;
|
||||
}
|
||||
protected override void OnSessionCreate(ulong xrSession)
|
||||
{
|
||||
UnityEngine.Debug.Log($"OnSessionCreate({xrSession:X})");
|
||||
m_XrSession = xrSession;
|
||||
|
||||
try { onSessionCreate?.Invoke(xrSession); }
|
||||
catch (Exception e) { UnityEngine.Debug.LogError(e); }
|
||||
}
|
||||
protected override void OnSystemChange(ulong xrSystem)
|
||||
{
|
||||
UnityEngine.Debug.Log($"OnSystemChange({xrSystem:X})");
|
||||
m_systemid = xrSystem;
|
||||
|
||||
try { onSystemChange?.Invoke(xrSystem); }
|
||||
catch (Exception e) { UnityEngine.Debug.LogError(e); }
|
||||
}
|
||||
|
||||
protected override void OnSessionDestroy(ulong xrSession)
|
||||
{
|
||||
UnityEngine.Debug.Log($"OnSessionDestroy({xrSession:X})");
|
||||
m_XrSession = default;
|
||||
try { onSessionDestroy?.Invoke(xrSession); }
|
||||
catch (Exception e) { UnityEngine.Debug.LogError(e); }
|
||||
}
|
||||
|
||||
private bool GetXrFunctionDelegates(ulong xrInstance)
|
||||
{
|
||||
if (xrGetInstanceProcAddr == null || xrGetInstanceProcAddr == IntPtr.Zero)
|
||||
UnityEngine.Debug.LogError("xrGetInstanceProcAddr is null");
|
||||
// Get delegate of xrGetInstanceProcAddr.
|
||||
var xrGetProc = Marshal.GetDelegateForFunctionPointer<xrGetInstanceProcDelegate>(xrGetInstanceProcAddr);
|
||||
// Get delegate of other OpenXR functions using xrGetInstanceProcAddr.
|
||||
if (!MarshelFunc(xrInstance, xrGetProc, "xrGetSystemProperties", ref m_xrGetSystemProperties)) { return false; }
|
||||
if (!MarshelFunc(xrInstance, xrGetProc, "xrCreateFacialTrackerHTC", ref m_xrCreateFacialTrackerHTC)) { return false; }
|
||||
if (!MarshelFunc(xrInstance, xrGetProc, "xrDestroyFacialTrackerHTC", ref m_xrDestroyFacialTrackerHTC)) { return false; }
|
||||
if (!MarshelFunc(xrInstance, xrGetProc, "xrGetFacialExpressionsHTC", ref m_xrGetFacialExpressionsHTC)) { return false; }
|
||||
return true;
|
||||
}
|
||||
private static bool MarshelFunc<T>(ulong instance, xrGetInstanceProcDelegate instanceProc, string funcName, ref T func, bool verbose = true)
|
||||
where T : Delegate
|
||||
{
|
||||
if (instanceProc(instance, funcName, out var fp) != 0)
|
||||
{
|
||||
if (verbose)
|
||||
{
|
||||
UnityEngine.Debug.LogError("Fail getting function " + funcName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
func = Marshal.GetDelegateForFunctionPointer<T>(fp);
|
||||
return true;
|
||||
}
|
||||
delegate int XrGetInstanceProcAddrDelegate(ulong instance, string name, out IntPtr function);
|
||||
XrGetInstanceProcAddrDelegate m_XrGetInstanceProcAddr;
|
||||
|
||||
delegate int xrGetSystemPropertiesDelegate(ulong instance, ulong systemId, ref XrSystemProperties properties);
|
||||
xrGetSystemPropertiesDelegate m_xrGetSystemProperties;
|
||||
public int xrGetSystemProperties(ref XrSystemProperties properties) =>
|
||||
m_xrGetSystemProperties(m_XrInstance, m_systemid, ref properties);
|
||||
public int xrGetSystemProperties(ulong instance, ulong systemId, ref XrSystemProperties properties) =>
|
||||
m_xrGetSystemProperties(instance, systemId, ref properties);
|
||||
|
||||
delegate int xrCreateFacialTrackerHTCDelegate(ulong session, XrFacialTrackerCreateInfoHTC createInfo, out ulong expression);
|
||||
xrCreateFacialTrackerHTCDelegate m_xrCreateFacialTrackerHTC;
|
||||
public int xrCreateFacialTrackerHTC(XrFacialTrackerCreateInfoHTC createInfo ,out ulong handle) =>
|
||||
m_xrCreateFacialTrackerHTC(m_XrSession, createInfo, out handle);
|
||||
public int xrCreateFacialTrackerHTC(ulong session, XrFacialTrackerCreateInfoHTC createInfo, out ulong handle) =>
|
||||
m_xrCreateFacialTrackerHTC(session, createInfo, out handle);
|
||||
|
||||
delegate int xrDestroyFacialTrackerHTCDelegate(ulong facialTracker);
|
||||
xrDestroyFacialTrackerHTCDelegate m_xrDestroyFacialTrackerHTC;
|
||||
public int xrDestroyFacialTrackerHTC(ulong handle) =>
|
||||
m_xrDestroyFacialTrackerHTC(handle);
|
||||
|
||||
delegate int xrGetFacialExpressionsHTCDelegate(ulong facialTracker, ref XrFacialExpressionsHTC eyeExpressionData);
|
||||
xrGetFacialExpressionsHTCDelegate m_xrGetFacialExpressionsHTC;
|
||||
public int xrGetFacialExpressionsHTC(ulong handle,ref XrFacialExpressionsHTC eyeExpressionData) =>
|
||||
m_xrGetFacialExpressionsHTC(handle, ref eyeExpressionData);
|
||||
|
||||
public unsafe void SystemSupportsFacialTracking(out XrResult result,out bool isSupportEye,out bool isSupportLip)
|
||||
{
|
||||
XrSystemFacialTrackingPropertiesHTC expressionProperties = new XrSystemFacialTrackingPropertiesHTC
|
||||
{
|
||||
type = XrStructureType.XR_TYPE_SYSTEM_FACIAL_TRACKING_PROPERTIES_HTC,
|
||||
next = IntPtr.Zero,
|
||||
};
|
||||
|
||||
var systemProp = new XrSystemProperties()
|
||||
{
|
||||
type = XrStructureType.XR_TYPE_SYSTEM_PROPERTIES,
|
||||
next = (IntPtr)(&expressionProperties),
|
||||
};
|
||||
result = (XrResult)xrGetSystemProperties(XrInstance, SystemId ,ref systemProp);
|
||||
isSupportEye = expressionProperties.supportEyeFacialTracking != 0;
|
||||
isSupportLip = expressionProperties.supportLipFacialTracking != 0;
|
||||
}
|
||||
|
||||
public bool TryCreateFacialTracker(XrFacialTrackingTypeHTC type,out ulong handle, out XrResult result)
|
||||
{
|
||||
XrFacialTrackerCreateInfoHTC createInfo = new XrFacialTrackerCreateInfoHTC(
|
||||
XrStructureType.XR_TYPE_FACIAL_TRACKER_CREATE_INFO_HTC,
|
||||
IntPtr.Zero,
|
||||
type);
|
||||
result = (XrResult)xrCreateFacialTrackerHTC(XrSession,createInfo, out handle);
|
||||
return result == XrResult.XR_SUCCESS;
|
||||
}
|
||||
public bool TryDestroFacialTracker(ulong handle, out XrResult result)
|
||||
{
|
||||
result= (XrResult)xrDestroyFacialTrackerHTC(handle);
|
||||
return result == XrResult.XR_SUCCESS;
|
||||
}
|
||||
public bool TryGetFacialData(ulong handle,out bool isActive,int maxExpressioncount,out XrResult result,float[] blendshapes)
|
||||
{
|
||||
XrFacialExpressionsHTC facialExpression = new XrFacialExpressionsHTC()
|
||||
{
|
||||
type = XrStructureType.XR_TYPE_FACIAL_EXPRESSIONS_HTC,
|
||||
expressionCount = maxExpressioncount,
|
||||
sampleTime = 10L, //An arbitrary number greater than 0
|
||||
blendShapeWeightings = Marshal.AllocCoTaskMem(sizeof(float) * maxExpressioncount),
|
||||
};
|
||||
result = (XrResult)xrGetFacialExpressionsHTC(handle, ref facialExpression);
|
||||
|
||||
Marshal.Copy(facialExpression.blendShapeWeightings, blendshapes, 0, maxExpressioncount);
|
||||
isActive = facialExpression.isActive != 0u;
|
||||
|
||||
return result == XrResult.XR_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be5cb237345f49840bbc00c128fde3d9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,681 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.InputSystem.XR;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
using UnityEngine.Scripting;
|
||||
using UnityEngine.XR.OpenXR.Features.Interactions;
|
||||
using UnityEngine.XR.OpenXR.Input;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
#if USE_INPUT_SYSTEM_POSE_CONTROL
|
||||
using PoseControl = UnityEngine.InputSystem.XR.PoseControl;
|
||||
#else
|
||||
using PoseControl = UnityEngine.XR.OpenXR.Input.PoseControl;
|
||||
#endif
|
||||
|
||||
namespace UnityEngine.XR.OpenXR.Features
|
||||
{
|
||||
/// <summary>
|
||||
/// This <see cref="OpenXRInteractionFeature"/> enables the use of HTC Vive Focus3 Controllers interaction profiles in OpenXR.
|
||||
/// </summary>
|
||||
#if UNITY_EDITOR
|
||||
[UnityEditor.XR.OpenXR.Features.OpenXRFeature(UiName = "HTC Vive Focus3 Controller Support",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Standalone, BuildTargetGroup.WSA },
|
||||
Company = "HTC",
|
||||
Desc = "Allows for mapping input to the HTC Vive Focus3 Controller interaction profile.",
|
||||
//DocumentationLink = "https://developer.vive.com/resources/openxr/openxr-pcvr/tutorials/unity/cosmos-controller-openxr-feature-unity/",
|
||||
OpenxrExtensionStrings = "XR_HTC_vive_focus3_controller_interaction XR_EXT_palm_pose",
|
||||
Version = "0.0.2",
|
||||
Category = UnityEditor.XR.OpenXR.Features.FeatureCategory.Interaction,
|
||||
FeatureId = featureId)]
|
||||
#endif
|
||||
public class HtcViveFocus3InputFeature : OpenXRInteractionFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// The feature id string. This is used to give the feature a well known id for reference.
|
||||
/// </summary>
|
||||
public const string featureId = "com.htc.openxr.feature.input.htcvivefocus3";
|
||||
|
||||
/// <summary>
|
||||
/// An Input System device based off the <see cref="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_HTC_vive_focus3_controller_interaction">HTC Vive Controller</see>.
|
||||
/// </summary>
|
||||
///
|
||||
[Preserve, InputControlLayout(displayName = "HTC Vive Focus3 Controller (OpenXR)", commonUsages = new[] { "LeftHand", "RightHand" })]
|
||||
public class ViveFocus3Controller : XRControllerWithRumble
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="ButtonControl"/> representing information from the <see cref="HtcViveFocus3Controller.thumbrestTouched"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "thumbresttouch" })]
|
||||
public ButtonControl thumbrestTouched { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="ButtonControl"/> representing information from the <see cref="HtcViveFocus3Controller.squeezeTouched"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "griptouch" })]
|
||||
public ButtonControl gripTouched { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="AxisControl"/> representing information from the <see cref="HtcViveFocus3Controller.squeeze"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "GripAxis" })]
|
||||
public AxisControl grip { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="ButtonControl"/> representing information from the <see cref="HtcViveFocus3Controller.squeezeClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "GripButton" })]
|
||||
public ButtonControl gripPressed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="ButtonControl"/> representing the <see cref="HtcViveFocus3Controller.b"/> <see cref="HtcViveFocus3Controller.y"/> OpenXR bindings, depending on handedness.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "B", "Y" })]
|
||||
public ButtonControl secondaryButton { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="ButtonControl"/> representing the <see cref="HtcViveFocus3Controller.a"/> <see cref="HtcViveFocus3Controller.x"/> OpenXR bindings, depending on handedness.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "A", "X" })]
|
||||
public ButtonControl primaryButton { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="ButtonControl"/> representing information from the <see cref="HtcViveFocus3Controller.menu"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "Primary", "menubutton" })]
|
||||
public ButtonControl menu { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="ButtonControl"/> representing information from the <see cref="HtcViveFocus3Controller.triggerTouch"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "triggertouch" })]
|
||||
public ButtonControl triggerTouched { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="AxisControl"/> representing information from the <see cref="HtcViveFocus3Controller.trigger"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "triggeraxis" })]
|
||||
public AxisControl trigger { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="ButtonControl"/> representing information from the <see cref="HtcViveFocus3Controller.triggerClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "triggerbutton" })]
|
||||
public ButtonControl triggerPressed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="Vector2Control"/> representing information from the <see cref="HtcViveFocus3Controller.joystick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "Primary2DAxis", "joystickaxes" })]
|
||||
public Vector2Control joystick { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="ButtonControl"/> representing information from the <see cref="HtcViveFocus3Controller.joystickClick"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "joystickorpadpressed", "joystickpressed" })]
|
||||
public ButtonControl joystickClicked { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="ButtonControl"/> representing information from the <see cref="HtcViveFocus3Controller.joystickTouched"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "joystickorpadtouched", "joysticktouched" })]
|
||||
public ButtonControl joystickTouched { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> representing information from the <see cref="HtcViveFocus3Controller.grip"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, alias = "device")]
|
||||
public PoseControl devicePose { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> representing information from the <see cref="HtcViveFocus3Controller.aim"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0)]
|
||||
public PoseControl pointer { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="ButtonControl"/> required for back compatibility with the XRSDK layouts. this represents the overall tracking state of the device. this value is equivalent to mapping devicePose/isTracked
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 28)]
|
||||
new public ButtonControl isTracked { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="IntegerControl"/> required for back compatibility with the XRSDK layouts. this represents the bit flag set indicating what data is valid. this value is equivalent to mapping devicePose/trackingState
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 32)]
|
||||
new public IntegerControl trackingState { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="Vector3Control"/> required for back compatibility with the XRSDK layouts. this is the device position, or grip position. this value is equivalent to mapping devicePose/position
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 36, aliases = new[] { "gripPosition" })]
|
||||
new public Vector3Control devicePosition { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="QuaternionControl"/> required for back compatibility with the XRSDK layouts. this is the device orientation, or grip orientation. this value is equivalent to mapping devicePose/rotation
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 48, aliases = new[] { "gripOrientation", "gripRotation" })]
|
||||
new public QuaternionControl deviceRotation { get; private set; }
|
||||
|
||||
/// A <see cref="Vector3Control"/> required for back compatibility with the XRSDK layouts. this is the pointer position. this value is equivalent to mapping pointerPose/position
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 96)]
|
||||
public Vector3Control pointerPosition { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="QuaternionControl"/> required for back compatibility with the XRSDK layouts. this is the pointer rotation. this value is equivalent to mapping pointerPose/rotation
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 108, aliases = new[] { "pointerOrientation" })]
|
||||
public QuaternionControl pointerRotation { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="HapticControl"/> that represents the <see cref="HtcViveFocus3Controller.haptic"/> binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(usage = "Haptic")]
|
||||
public HapticControl haptic { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> representing information from the <see cref="HtcViveFocus3Controller.palm"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl()]
|
||||
public PoseControl palm { get; private set; }
|
||||
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
thumbrestTouched = GetChildControl<ButtonControl>("thumbrestTouched");
|
||||
gripTouched = GetChildControl<ButtonControl>("gripTouched");
|
||||
grip = GetChildControl<AxisControl>("grip");
|
||||
gripPressed = GetChildControl<ButtonControl>("gripPressed");
|
||||
primaryButton = GetChildControl<ButtonControl>("primaryButton");
|
||||
secondaryButton = GetChildControl<ButtonControl>("secondaryButton");
|
||||
menu = GetChildControl<ButtonControl>("menu");
|
||||
trigger = GetChildControl<AxisControl>("trigger");
|
||||
triggerTouched = GetChildControl<ButtonControl>("triggerTouched");
|
||||
triggerPressed = GetChildControl<ButtonControl>("triggerPressed");
|
||||
joystick = GetChildControl<Vector2Control>("joystick");
|
||||
joystickClicked = GetChildControl<ButtonControl>("joystickClicked");
|
||||
joystickTouched = GetChildControl<ButtonControl>("joystickTouched");
|
||||
|
||||
devicePose = GetChildControl<PoseControl>("devicePose");
|
||||
pointer = GetChildControl<PoseControl>("pointer");
|
||||
|
||||
isTracked = GetChildControl<ButtonControl>("isTracked");
|
||||
trackingState = GetChildControl<IntegerControl>("trackingState");
|
||||
devicePosition = GetChildControl<Vector3Control>("devicePosition");
|
||||
deviceRotation = GetChildControl<QuaternionControl>("deviceRotation");
|
||||
pointerPosition = GetChildControl<Vector3Control>("pointerPosition");
|
||||
pointerRotation = GetChildControl<QuaternionControl>("pointerRotation");
|
||||
haptic = GetChildControl<HapticControl>("haptic");
|
||||
palm = GetChildControl<PoseControl>("palm");
|
||||
}
|
||||
}
|
||||
/// <summary>The interaction profile string used to reference the <see cref="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_HTC_vive_focus3_controller_interaction">HTC Vive Focus3 Controller</see>.</summary>
|
||||
public const string profile = "/interaction_profiles/htc/vive_focus3_controller";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Binary"/> interaction binding '.../input/trigger/click' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string select = "/input/trigger/click";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Binary"/> interaction binding '.../input/a/click' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string a = "/input/a/click";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Binary"/> interaction binding '.../input/b/click' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string b = "/input/b/click";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Binary"/> interaction binding '.../input/x/click' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string x = "/input/x/click";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Binary"/> interaction binding '.../input/y/click' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string y = "/input/y/click";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Axis1D"/> interaction binding '.../input/squeeze/click' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string squeeze = "/input/squeeze/value";
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Binary"/> interaction binding '.../input/squeeze/touch' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string squeezeTouch = "/input/squeeze/touch";
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Binary"/> interaction binding '.../input/squeeze/click' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string squeezeClick = "/input/squeeze/click";
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Binary"/> interaction binding '.../input/menu/click' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string menu = "/input/menu/click";
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Binary"/> interaction binding '.../input/trigger/touch' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string triggerTouch = "/input/trigger/touch";
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Axis1D"/> interaction binding '.../input/trigger/value' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string trigger = "/input/trigger/value";
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Binary"/> interaction binding '.../input/trigger/click' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string triggerClick = "/input/trigger/click";
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Axis2D"/> interaction binding '.../input/trackpad' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string thumbstick = "/input/thumbstick";
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Binary"/> interaction binding '.../input/trackpad/click' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string thumbstickClick = "/input/thumbstick/click";
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Binary"/> interaction binding '.../input/trackpad/touch' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string thumbstickTouch = "/input/thumbstick/touch";
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Pose"/> interaction binding '.../input/grip/pose' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string grip = "/input/grip/pose";
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Pose"/> interaction binding '.../input/aim/pose' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string aim = "/input/aim/pose";
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Vibrate"/> interaction binding '.../output/haptic' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string haptic = "/output/haptic";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Pose"/> interaction binding '.../input/palm_ext/pose' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string palm = "/input/palm_ext/pose";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Binary"/> interaction binding '.../input/thumbrest/touch' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string thumbrest = "/input/thumbrest/touch";
|
||||
|
||||
private const string kDeviceLocalizedName = "HTC Vive Focus3 Controller OpenXR";
|
||||
/// <summary>
|
||||
/// Registers the <see cref="ViveFocus3Controller"/> layout with the Input System. Matches the <see cref="ActionMapConfig"/> that is registered with <see cref="RegisterControllerMap"/>.
|
||||
/// </summary>
|
||||
|
||||
protected override void RegisterDeviceLayout()
|
||||
{
|
||||
InputSystem.InputSystem.RegisterLayout(typeof(ViveFocus3Controller),
|
||||
matches: new InputDeviceMatcher()
|
||||
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
||||
.WithProduct(kDeviceLocalizedName));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Removes the <see cref="ViveFocus3Controller"/> layout from the Input System. Matches the <see cref="ActionMapConfig"/> that is registered with <see cref="RegisterControllerMap"/>.
|
||||
/// </summary>
|
||||
protected override void UnregisterDeviceLayout()
|
||||
{
|
||||
InputSystem.InputSystem.RemoveLayout(typeof(ViveFocus3Controller).Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers an <see cref="ActionMapConfig"/> with OpenXR that matches the <see cref="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_HTC_vive_focus3_controller_interaction">HTC Vive Focus3 Controller</see>. Also calls <see cref="RegisterDeviceLayout"/> when the Input System package is available.
|
||||
/// </summary>
|
||||
protected override void RegisterActionMapsWithRuntime()
|
||||
{
|
||||
ActionMapConfig actionMap = new ActionMapConfig()
|
||||
{
|
||||
name = "vivefocus3controller",
|
||||
localizedName = kDeviceLocalizedName,
|
||||
desiredInteractionProfile = profile,
|
||||
manufacturer = "HTC",
|
||||
serialNumber = "",
|
||||
deviceInfos = new List<DeviceConfig>()
|
||||
{
|
||||
new DeviceConfig()
|
||||
{
|
||||
characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.TrackedDevice | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Left),
|
||||
userPath = UserPaths.leftHand
|
||||
},
|
||||
new DeviceConfig()
|
||||
{
|
||||
characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.HeldInHand | InputDeviceCharacteristics.TrackedDevice | InputDeviceCharacteristics.Controller | InputDeviceCharacteristics.Right),
|
||||
userPath = UserPaths.rightHand
|
||||
}
|
||||
},
|
||||
actions = new List<ActionConfig>()
|
||||
{
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "primarybutton",
|
||||
localizedName = "Primary Button",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"PrimaryButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = x,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.leftHand }
|
||||
},
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = a,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.rightHand }
|
||||
},
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "secondarybutton",
|
||||
localizedName = "Secondary Button",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"SecondaryButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = y,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.leftHand }
|
||||
},
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = b,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.rightHand }
|
||||
},
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "thumbrestTouched",
|
||||
localizedName = "Thumbrest Touched",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"ThumbrestTouch",
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = thumbrest,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "grip",
|
||||
localizedName = "Grip",
|
||||
type = ActionType.Axis1D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Grip"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = squeeze,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "gripTouched",
|
||||
localizedName = "Grip Touched",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"GripTouch",
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = squeezeTouch,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "grippressed",
|
||||
localizedName = "Grip Pressed",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"GripPressed",
|
||||
"GripButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = squeezeClick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "menu",
|
||||
localizedName = "Menu",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"MenuButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = menu,
|
||||
interactionProfileName = profile,
|
||||
userPaths = new List<string>() { UserPaths.leftHand }
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "trigger",
|
||||
localizedName = "Trigger",
|
||||
type = ActionType.Axis1D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Trigger"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = trigger,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "triggerTouched",
|
||||
localizedName = "TriggerTouched",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"TriggerTouch"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = triggerTouch,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "triggerpressed",
|
||||
localizedName = "Trigger Pressed",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"TriggerPressed",
|
||||
"TriggerButton"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = triggerClick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "thumbstick",
|
||||
localizedName = "Thumbstick",
|
||||
type = ActionType.Axis2D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Primary2DAxis"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = thumbstick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "thumbsticktouched",
|
||||
localizedName = "Thumbstick Touched",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Primary2DAxisTouch"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = thumbstickTouch,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "thumbstickclicked",
|
||||
localizedName = "Thumbstick Clicked",
|
||||
type = ActionType.Binary,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Primary2DAxisClick"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = thumbstickClick,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "devicepose",
|
||||
localizedName = "Device Pose",
|
||||
type = ActionType.Pose,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Device"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = grip,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "pointer",
|
||||
localizedName = "Pointer Pose",
|
||||
type = ActionType.Pose,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Pointer"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = aim,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "haptic",
|
||||
localizedName = "Haptic Output",
|
||||
type = ActionType.Vibrate,
|
||||
usages = new List<string>() { "Haptic" },
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = haptic,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "palm",
|
||||
localizedName = "Palm Pose",
|
||||
type = ActionType.Pose,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Palm"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = palm,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
AddActionMap(actionMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c90cb647e537c84ba07688712190d17
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a7d87364cc42b1a4692f56baec26a8f3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 22ec09192290b7a4fa47af97e8826a6c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,268 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine.InputSystem.XR;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
using UnityEngine.Scripting;
|
||||
using UnityEngine.XR.OpenXR.Features.Interactions;
|
||||
using UnityEngine.XR.OpenXR.Input;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
#if USE_INPUT_SYSTEM_POSE_CONTROL
|
||||
using PoseControl = UnityEngine.InputSystem.XR.PoseControl;
|
||||
#else
|
||||
using PoseControl = UnityEngine.XR.OpenXR.Input.PoseControl;
|
||||
#endif
|
||||
|
||||
namespace UnityEngine.XR.OpenXR.Features
|
||||
{
|
||||
/// <summary>
|
||||
/// This <see cref="OpenXRInteractionFeature"/> enables the use of HTC Vive hand interaction profiles in OpenXR.
|
||||
/// </summary>
|
||||
#if UNITY_EDITOR
|
||||
[UnityEditor.XR.OpenXR.Features.OpenXRFeature(UiName = "HTC Vive hand interaction Support",
|
||||
BuildTargetGroups = new[] { BuildTargetGroup.Standalone, BuildTargetGroup.WSA },
|
||||
Company = "HTC",
|
||||
Desc = "Allows for mapping input to the HTC Vive hand interaction interaction profile.",
|
||||
DocumentationLink = "https://developer.vive.com/resources/openxr/openxr-pcvr/tutorials/unity/hand-interaction-profile/",
|
||||
OpenxrExtensionStrings = "XR_HTC_hand_interaction",
|
||||
Version = "0.0.1",
|
||||
Category = UnityEditor.XR.OpenXR.Features.FeatureCategory.Interaction,
|
||||
FeatureId = featureId)]
|
||||
#endif
|
||||
public class HtcViveHandInteractionInputFeature : OpenXRInteractionFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// The feature id string. This is used to give the feature a well known id for reference.
|
||||
/// </summary>
|
||||
public const string featureId = "com.htc.openxr.feature.input.htcvivehandinteraction";
|
||||
|
||||
/// <summary>
|
||||
/// An Input System device based off the <see cref="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_HTC_hand_interaction">HTC Vive Controller</see>.
|
||||
/// </summary>
|
||||
///
|
||||
[Preserve, InputControlLayout(displayName = "HTC Vive hand interaction (OpenXR)", commonUsages = new[] { "LeftHand", "RightHand" })]
|
||||
public class ViveHandInteraction : XRController
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="AxisControl"/> representing information from the <see cref="HtcViveHandInteraction.squeeze"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "GripAxis" })]
|
||||
public AxisControl grip { get; private set; }
|
||||
/// <summary>
|
||||
/// A <see cref="AxisControl"/> representing information from the <see cref="HtcViveHandInteraction.select"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(aliases = new[] { "selectaxis" })]
|
||||
public AxisControl select { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> representing information from the <see cref="HtcViveHandInteraction.grip"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0, alias = "device")]
|
||||
public PoseControl devicePose { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="PoseControl"/> representing information from the <see cref="HtcViveHandInteraction.aim"/> OpenXR binding.
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 0)]
|
||||
public PoseControl pointer { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="ButtonControl"/> required for back compatibility with the XRSDK layouts. this represents the overall tracking state of the device. this value is equivalent to mapping devicePose/isTracked
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 28)]
|
||||
new public ButtonControl isTracked { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="IntegerControl"/> required for back compatibility with the XRSDK layouts. this represents the bit flag set indicating what data is valid. this value is equivalent to mapping devicePose/trackingState
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 32)]
|
||||
new public IntegerControl trackingState { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="Vector3Control"/> required for back compatibility with the XRSDK layouts. this is the device position, or grip position. this value is equivalent to mapping devicePose/position
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 36, aliases = new[] { "gripPosition" })]
|
||||
new public Vector3Control devicePosition { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="QuaternionControl"/> required for back compatibility with the XRSDK layouts. this is the device orientation, or grip orientation. this value is equivalent to mapping devicePose/rotation
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 48, aliases = new[] { "gripOrientation", "gripRotation" })]
|
||||
new public QuaternionControl deviceRotation { get; private set; }
|
||||
|
||||
/// A <see cref="Vector3Control"/> required for back compatibility with the XRSDK layouts. this is the pointer position. this value is equivalent to mapping pointerPose/position
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 96)]
|
||||
public Vector3Control pointerPosition { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="QuaternionControl"/> required for back compatibility with the XRSDK layouts. this is the pointer rotation. this value is equivalent to mapping pointerPose/rotation
|
||||
/// </summary>
|
||||
[Preserve, InputControl(offset = 108, aliases = new[] { "pointerOrientation" })]
|
||||
public QuaternionControl pointerRotation { get; private set; }
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
grip = GetChildControl<AxisControl>("grip");
|
||||
select = GetChildControl<AxisControl>("select");
|
||||
|
||||
devicePose = GetChildControl<PoseControl>("devicePose");
|
||||
pointer = GetChildControl<PoseControl>("pointer");
|
||||
|
||||
isTracked = GetChildControl<ButtonControl>("isTracked");
|
||||
trackingState = GetChildControl<IntegerControl>("trackingState");
|
||||
devicePosition = GetChildControl<Vector3Control>("devicePosition");
|
||||
deviceRotation = GetChildControl<QuaternionControl>("deviceRotation");
|
||||
pointerPosition = GetChildControl<Vector3Control>("pointerPosition");
|
||||
pointerRotation = GetChildControl<QuaternionControl>("pointerRotation");
|
||||
}
|
||||
}
|
||||
/// <summary>The interaction profile string used to reference the <see cref="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_HTC_hand_interaction">HTC Vive hand interaction</see>.</summary>
|
||||
public const string profile = "/interaction_profiles/htc/hand_interaction";
|
||||
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Axis1D"/> interaction binding '.../input/squeeze/click' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string squeeze = "/input/squeeze/value";
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Axis1D"/> interaction binding '.../input/select/value' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string select = "/input/select/value";
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Pose"/> interaction binding '.../input/grip/pose' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string grip = "/input/grip/pose";
|
||||
/// <summary>
|
||||
/// Constant for a <see cref="ActionType.Pose"/> interaction binding '.../input/aim/pose' OpenXR Input Binding. Used by <see cref="XrActionConfig"/> to bind actions to physical inputs.
|
||||
/// </summary>
|
||||
public const string aim = "/input/aim/pose";
|
||||
|
||||
private const string kDeviceLocalizedName = "HTC Vive hand interaction OpenXR";
|
||||
/// <summary>
|
||||
/// Registers the <see cref="ViveHandInteraction"/> layout with the Input System. Matches the <see cref="ActionMapConfig"/> that is registered with <see cref="RegisterControllerMap"/>.
|
||||
/// </summary>
|
||||
protected override void RegisterDeviceLayout()
|
||||
{
|
||||
InputSystem.InputSystem.RegisterLayout(typeof(ViveHandInteraction),
|
||||
matches: new InputDeviceMatcher()
|
||||
.WithInterface(XRUtilities.InterfaceMatchAnyVersion)
|
||||
.WithProduct(kDeviceLocalizedName));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Removes the <see cref="ViveHandInteraction"/> layout from the Input System. Matches the <see cref="ActionMapConfig"/> that is registered with <see cref="RegisterControllerMap"/>.
|
||||
/// </summary>
|
||||
protected override void UnregisterDeviceLayout()
|
||||
{
|
||||
InputSystem.InputSystem.RemoveLayout(typeof(ViveHandInteraction).Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers an <see cref="ActionMapConfig"/> with OpenXR that matches the <see cref="https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#XR_HTC_hand_interaction">HTC Vive hand interaction</see>. Also calls <see cref="RegisterDeviceLayout"/> when the Input System package is available.
|
||||
/// </summary>
|
||||
protected override void RegisterActionMapsWithRuntime()
|
||||
{
|
||||
ActionMapConfig actionMap = new ActionMapConfig()
|
||||
{
|
||||
name = "ViveHandInteraction",
|
||||
localizedName = kDeviceLocalizedName,
|
||||
desiredInteractionProfile = profile,
|
||||
manufacturer = "HTC",
|
||||
serialNumber = "",
|
||||
deviceInfos = new List<DeviceConfig>()
|
||||
{
|
||||
new DeviceConfig()
|
||||
{
|
||||
characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.TrackedDevice | InputDeviceCharacteristics.HandTracking | InputDeviceCharacteristics.Left),
|
||||
userPath = "/user/hand_htc/left"
|
||||
},
|
||||
new DeviceConfig()
|
||||
{
|
||||
characteristics = (InputDeviceCharacteristics)(InputDeviceCharacteristics.TrackedDevice | InputDeviceCharacteristics.HandTracking | InputDeviceCharacteristics.Right),
|
||||
userPath = "/user/hand_htc/right"
|
||||
}
|
||||
},
|
||||
actions = new List<ActionConfig>()
|
||||
{
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "grip",
|
||||
localizedName = "Grip",
|
||||
type = ActionType.Axis1D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Grip"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = squeeze,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "select",
|
||||
localizedName = "Select",
|
||||
type = ActionType.Axis1D,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Select"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = select,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "devicepose",
|
||||
localizedName = "Device Pose",
|
||||
type = ActionType.Pose,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Device"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = grip,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
},
|
||||
new ActionConfig()
|
||||
{
|
||||
name = "pointer",
|
||||
localizedName = "Pointer Pose",
|
||||
type = ActionType.Pose,
|
||||
usages = new List<string>()
|
||||
{
|
||||
"Pointer"
|
||||
},
|
||||
bindings = new List<ActionBinding>()
|
||||
{
|
||||
new ActionBinding()
|
||||
{
|
||||
interactionPath = aim,
|
||||
interactionProfileName = profile,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
AddActionMap(actionMap);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 52487a0e9b06950449d9fe1c91687776
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,54 +0,0 @@
|
||||
using UnityEditor;
|
||||
using UnityEditor.XR.OpenXR.Features;
|
||||
using UnityEngine;
|
||||
using UnityEngine.XR.OpenXR;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using VIVE.HandTracking;
|
||||
using UnityEngine.XR.OpenXR.Features;
|
||||
namespace UnityEditor.XR.OpenXR.Samples.HandTracking
|
||||
{
|
||||
[InitializeOnLoad]
|
||||
public class HandTrackingFeauterInstaller : Editor
|
||||
{
|
||||
#if !UNITY_SAMPLE_DEV
|
||||
private const string k_ScriptPath = "HandTracking Example/Editor/HandTrackingFeauterInstaller.cs";
|
||||
static HandTrackingFeauterInstaller()
|
||||
{
|
||||
FeatureHelpers.RefreshFeatures(BuildTargetGroup.Standalone);
|
||||
var feature = OpenXRSettings.Instance.GetFeature<HandTracking_OpenXR_API>();
|
||||
var HandInteractionfeature = OpenXRSettings.Instance.GetFeature<HtcViveHandInteractionInputFeature>();
|
||||
if (feature != null)
|
||||
{
|
||||
if (feature.enabled != true)
|
||||
{
|
||||
feature.enabled = true;
|
||||
}
|
||||
}
|
||||
if (HandInteractionfeature != null)
|
||||
{
|
||||
if (HandInteractionfeature.enabled != true)
|
||||
{
|
||||
HandInteractionfeature.enabled = true;
|
||||
}
|
||||
}
|
||||
Debug.Log(AssetDatabase.FindAssets(Path.GetFileNameWithoutExtension(k_ScriptPath)).Select(AssetDatabase.GUIDToAssetPath));
|
||||
var source = AssetDatabase.FindAssets(Path.GetFileNameWithoutExtension(k_ScriptPath))
|
||||
.Select(AssetDatabase.GUIDToAssetPath)
|
||||
.FirstOrDefault(r => r.Contains(k_ScriptPath));
|
||||
|
||||
if (string.IsNullOrEmpty(source))
|
||||
{
|
||||
Debug.LogError("File Not Exist");
|
||||
return;
|
||||
}
|
||||
|
||||
source = Path.GetDirectoryName(source);
|
||||
Debug.Log(source);
|
||||
AssetDatabase.DeleteAsset(Path.Combine(Path.GetDirectoryName(source), "Editor"));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 25c6b0688a353874791039a7510e9003
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user