上传YomovSDK
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cd029ee7a3204f446b0def5eafc0a380
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ddf1278db13678e45b960b274d526b39
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 213dee666ce1d064bac61bf4164523d9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec04348c6d3a8ce43ada545a76766344
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 222aadbc313466a41bafc2f46013fe3d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
166
Packages/com.htc.upm.vive.openxr/Editor/PackageManagerHelper.cs
Normal file
166
Packages/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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43952515f295bac4385e71851692047d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/com.htc.upm.vive.openxr/Editor/Preferences.meta
Normal file
8
Packages/com.htc.upm.vive.openxr/Editor/Preferences.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f1198e3724eb5b44a705edc6d6bae06
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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:
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "VIVE.OpenXR.Editor",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"VIVE.OpenXR",
|
||||
"Unity.XR.OpenXR",
|
||||
"Unity.XR.OpenXR.Editor",
|
||||
"Unity.XR.Management.Editor"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d6b33c0ff458eb344807c1608836e334
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
24
Packages/com.htc.upm.vive.openxr/Editor/ViveAnchorEditor.cs
Normal file
24
Packages/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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9094698271e2abb4ab295256548772c3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
Packages/com.htc.upm.vive.openxr/Editor/ViveMenu.cs
Normal file
44
Packages/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
Packages/com.htc.upm.vive.openxr/Editor/ViveMenu.cs.meta
Normal file
11
Packages/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:
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eedb4211aafd2cb4bae86fcc0e948f72
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6fe9adb019aff2e419eee912e8171cf9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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:
|
||||
Reference in New Issue
Block a user