Commit 29de0c28 authored by BlackAngle233's avatar BlackAngle233
Browse files

10.19 learned

parent 912976bb
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
namespace Microsoft.MixedReality.Toolkit.Input.Editor
{
/// <summary>
/// Used to aid in layout of Controller Input Actions.
/// </summary>
[Serializable]
public class ControllerInputActionOptions
{
public List<ControllerInputActionOption> Controllers;
}
}
\ No newline at end of file
{
"Controllers": [
{
"Controller": 32,
"Handedness": 2,
"InputLabelPositions": [
{
"x": 291.0,
"y": 22.0
},
{
"x": 382.0,
"y": 348.0
},
{
"x": -48.0,
"y": 283.0
},
{
"x": 486.0,
"y": 144.0
},
{
"x": -84.0,
"y": 158.0
},
{
"x": -82.0,
"y": 136.0
},
{
"x": 484.0,
"y": 190.0
},
{
"x": 484.0,
"y": 211.0
},
{
"x": 484.0,
"y": 231.0
},
{
"x": -70.0,
"y": 241.0
},
{
"x": -77.0,
"y": 191.0
},
{
"x": -78.0,
"y": 211.0
}
],
"IsLabelFlipped": [
false,
false,
true,
false,
true,
true,
false,
false,
false,
true,
true,
true
]
},
{
"Controller": 32,
"Handedness": 1,
"InputLabelPositions": [
{
"x": 121.0,
"y": 21.0
},
{
"x": 404.0,
"y": 355.0
},
{
"x": 469.0,
"y": 283.0
},
{
"x": -67.0,
"y": 145.0
},
{
"x": 500.0,
"y": 158.0
},
{
"x": 501.0,
"y": 137.0
},
{
"x": -68.0,
"y": 182.0
},
{
"x": -69.0,
"y": 205.0
},
{
"x": -69.0,
"y": 226.0
},
{
"x": 488.0,
"y": 238.0
},
{
"x": 499.0,
"y": 190.0
},
{
"x": 499.0,
"y": 211.0
}
],
"IsLabelFlipped": [
true,
false,
false,
true,
false,
false,
true,
true,
true,
false,
false,
false
]
},
{
"Controller": 128,
"Handedness": 0,
"InputLabelPositions": [
{
"x": 15.0,
"y": 398.0
},
{
"x": 14.0,
"y": 419.0
},
{
"x": 418.0,
"y": 399.0
},
{
"x": 418.0,
"y": 420.0
},
{
"x": -188.0,
"y": 338.0
},
{
"x": 298.0,
"y": 54.0
},
{
"x": -132.0,
"y": 134.0
},
{
"x": 551.0,
"y": 126.0
},
{
"x": 14.0,
"y": 101.0
},
{
"x": 409.0,
"y": 101.0
},
{
"x": -159.0,
"y": 182.0
},
{
"x": 577.0,
"y": 173.0
},
{
"x": 628.0,
"y": 310.0
},
{
"x": 622.0,
"y": 282.0
},
{
"x": 616.0,
"y": 253.0
},
{
"x": 607.0,
"y": 225.0
}
],
"IsLabelFlipped": [
true,
true,
false,
false,
true,
false,
true,
false,
true,
false,
true,
false,
false,
false,
false,
false
]
},
{
"Controller": 8,
"Handedness": 2,
"InputLabelPositions": [
{
"x": -43.0,
"y": 165.0
},
{
"x": 5.0,
"y": 289.0
},
{
"x": 7.0,
"y": 330.0
},
{
"x": 8.0,
"y": 351.0
},
{
"x": 6.0,
"y": 309.0
},
{
"x": 436.0,
"y": 272.0
},
{
"x": 267.0,
"y": 30.0
},
{
"x": 267.0,
"y": 68.0
},
{
"x": 268.0,
"y": 88.0
},
{
"x": 267.0,
"y": 49.0
},
{
"x": 418.0,
"y": 163.0
},
{
"x": -43.0,
"y": 204.0
},
{
"x": 418.0,
"y": 182.0
},
{
"x": -42.0,
"y": 184.0
},
{
"x": 420.0,
"y": 202.0
},
{
"x": 419.0,
"y": 222.0
}
],
"IsLabelFlipped": [
true,
true,
true,
true,
true,
false,
false,
false,
false,
false,
false,
true,
false,
true,
false,
false
]
},
{
"Controller": 8,
"Handedness": 1,
"InputLabelPositions": [
{
"x": 482.0,
"y": 158.0
},
{
"x": 433.0,
"y": 295.0
},
{
"x": 433.0,
"y": 334.0
},
{
"x": 433.0,
"y": 355.0
},
{
"x": 433.0,
"y": 315.0
},
{
"x": -14.0,
"y": 268.0
},
{
"x": 171.0,
"y": 28.0
},
{
"x": 171.0,
"y": 67.0
},
{
"x": 171.0,
"y": 87.0
},
{
"x": 172.0,
"y": 47.0
},
{
"x": 15.0,
"y": 168.0
},
{
"x": 480.0,
"y": 179.0
},
{
"x": 16.0,
"y": 141.0
},
{
"x": 15.0,
"y": 188.0
},
{
"x": 479.0,
"y": 198.0
},
{
"x": 15.0,
"y": 207.0
},
{
"x": 14.0,
"y": 225.0
}
],
"IsLabelFlipped": [
false,
false,
false,
false,
false,
true,
true,
true,
true,
true,
true,
false,
true,
true,
false,
true,
true
]
},
{
"Controller": 2,
"Handedness": 1,
"InputLabelPositions": [
{
"x": 198.0,
"y": 49.0
},
{
"x": 545.0,
"y": 215.0
},
{
"x": 543.0,
"y": 233.0
},
{
"x": 543.0,
"y": 251.0
},
{
"x": 542.0,
"y": 298.0
},
{
"x": -131.0,
"y": 216.0
},
{
"x": -131.0,
"y": 256.0
},
{
"x": -131.0,
"y": 235.0
},
{
"x": -125.0,
"y": 173.0
}
],
"IsLabelFlipped": [
false,
false,
false,
false,
false,
true,
true,
true,
true
]
},
{
"Controller": 2,
"Handedness": 2,
"InputLabelPositions": [
{
"x": 418.0,
"y": 43.0
},
{
"x": -118.0,
"y": 208.0
},
{
"x": -117.0,
"y": 228.0
},
{
"x": -117.0,
"y": 248.0
},
{
"x": -117.0,
"y": 285.0
},
{
"x": 563.0,
"y": 212.0
},
{
"x": 565.0,
"y": 252.0
},
{
"x": 563.0,
"y": 232.0
},
{
"x": 568.0,
"y": 168.0
}
],
"IsLabelFlipped": [
false,
true,
true,
true,
true,
false,
false,
false,
false
]
},
{
"Controller": 16,
"Handedness": 0,
"InputLabelPositions": [
{
"x": 301.0,
"y": 63.0
},
{
"x": -64.0,
"y": 147.0
},
{
"x": 490.0,
"y": 226.0
}
],
"IsLabelFlipped": [
false,
true,
false
]
}
]
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Utilities;
using UnityEditor;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.Editor
{
[CustomEditor(typeof(HoverLight))]
public class HoverLightInspector : UnityEditor.Editor
{
private bool HasFrameBounds() { return true; }
private Bounds OnGetFrameBounds()
{
var light = target as HoverLight;
Debug.Assert(light != null);
return new Bounds(light.transform.position, Vector3.one * light.Radius);
}
[MenuItem("GameObject/Light/Hover Light")]
private static void CreateHoverLight(MenuCommand menuCommand)
{
GameObject hoverLight = new GameObject("Hover Light", typeof(HoverLight));
// Ensure the light gets re-parented to the active context.
GameObjectUtility.SetParentAndAlign(hoverLight, menuCommand.context as GameObject);
// Register the creation in the undo system.
Undo.RegisterCreatedObjectUndo(hoverLight, "Create " + hoverLight.name);
Selection.activeObject = hoverLight;
}
}
}
{
"name": "Microsoft.MixedReality.Toolkit.Editor.Inspectors",
"references": [
"Microsoft.MixedReality.Toolkit",
"Microsoft.MixedReality.Toolkit.Async",
"Microsoft.MixedReality.Toolkit.Editor.BuildAndDeploy",
"Microsoft.MixedReality.Toolkit.Editor.ClassExtensions",
"Microsoft.MixedReality.Toolkit.Editor.Utilities",
"Unity.TextMeshPro.Editor"
],
"optionalUnityReferences": [],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": []
}
\ No newline at end of file
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using Object = UnityEngine.Object;
namespace Microsoft.MixedReality.Toolkit.Editor
{
/// <summary>
/// A custom base shader inspector for Mixed Reality Toolkit shaders.
/// </summary>
public abstract class MixedRealityShaderGUI : ShaderGUI
{
protected enum RenderingMode
{
Opaque = 0,
Cutout = 1,
Fade = 2,
Transparent = 3,
Additive = 4,
Custom = 5
}
protected enum CustomRenderingMode
{
Opaque = 0,
Cutout = 1,
Fade = 2
}
protected enum DepthWrite
{
Off = 0,
On = 1
}
protected static class BaseStyles
{
public static string renderingOptionsTitle = "Rendering Options";
public static string advancedOptionsTitle = "Advanced Options";
public static string renderTypeName = "RenderType";
public static string renderingModeName = "_Mode";
public static string customRenderingModeName = "_CustomMode";
public static string sourceBlendName = "_SrcBlend";
public static string destinationBlendName = "_DstBlend";
public static string blendOperationName = "_BlendOp";
public static string depthTestName = "_ZTest";
public static string depthWriteName = "_ZWrite";
public static string depthOffsetFactorName = "_ZOffsetFactor";
public static string depthOffsetUnitsName = "_ZOffsetUnits";
public static string colorWriteMaskName = "_ColorWriteMask";
public static string cullModeName = "_CullMode";
public static string renderQueueOverrideName = "_RenderQueueOverride";
public static string alphaTestOnName = "_ALPHATEST_ON";
public static string alphaBlendOnName = "_ALPHABLEND_ON";
public static readonly string[] renderingModeNames = Enum.GetNames(typeof(RenderingMode));
public static readonly string[] customRenderingModeNames = Enum.GetNames(typeof(CustomRenderingMode));
public static readonly string[] depthWriteNames = Enum.GetNames(typeof(DepthWrite));
public static GUIContent sourceBlend = new GUIContent("Source Blend", "Blend Mode of Newly Calculated Color");
public static GUIContent destinationBlend = new GUIContent("Destination Blend", "Blend Mode of Existing Color");
public static GUIContent blendOperation = new GUIContent("Blend Operation", "Operation for Blending New Color With Existing Color");
public static GUIContent depthTest = new GUIContent("Depth Test", "How Should Depth Testing Be Performed.");
public static GUIContent depthWrite = new GUIContent("Depth Write", "Controls Whether Pixels From This Material Are Written to the Depth Buffer");
public static GUIContent depthOffsetFactor = new GUIContent("Depth Offset Factor", "Scales the Maximum Z Slope, with Respect to X or Y of the Polygon");
public static GUIContent depthOffsetUnits = new GUIContent("Depth Offset Units", "Scales the Minimum Resolvable Depth Buffer Value");
public static GUIContent colorWriteMask = new GUIContent("Color Write Mask", "Color Channel Writing Mask");
public static GUIContent cullMode = new GUIContent("Cull Mode", "Triangle Culling Mode");
public static GUIContent renderQueueOverride = new GUIContent("Render Queue Override", "Manually Override the Render Queue");
}
protected bool initialized;
protected MaterialProperty renderingMode;
protected MaterialProperty customRenderingMode;
protected MaterialProperty sourceBlend;
protected MaterialProperty destinationBlend;
protected MaterialProperty blendOperation;
protected MaterialProperty depthTest;
protected MaterialProperty depthWrite;
protected MaterialProperty depthOffsetFactor;
protected MaterialProperty depthOffsetUnits;
protected MaterialProperty colorWriteMask;
protected MaterialProperty cullMode;
protected MaterialProperty renderQueueOverride;
protected const string LegacyShadersPath = "Legacy Shaders/";
protected const string TransparentShadersPath = "/Transparent/";
protected const string TransparentCutoutShadersPath = "/Transparent/Cutout/";
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
{
Material material = (Material)materialEditor.target;
FindProperties(props);
Initialize(material);
RenderingModeOptions(materialEditor);
}
protected virtual void FindProperties(MaterialProperty[] props)
{
renderingMode = FindProperty(BaseStyles.renderingModeName, props);
customRenderingMode = FindProperty(BaseStyles.customRenderingModeName, props);
sourceBlend = FindProperty(BaseStyles.sourceBlendName, props);
destinationBlend = FindProperty(BaseStyles.destinationBlendName, props);
blendOperation = FindProperty(BaseStyles.blendOperationName, props);
depthTest = FindProperty(BaseStyles.depthTestName, props);
depthWrite = FindProperty(BaseStyles.depthWriteName, props);
depthOffsetFactor = FindProperty(BaseStyles.depthOffsetFactorName, props);
depthOffsetUnits = FindProperty(BaseStyles.depthOffsetUnitsName, props);
colorWriteMask = FindProperty(BaseStyles.colorWriteMaskName, props);
cullMode = FindProperty(BaseStyles.cullModeName, props);
renderQueueOverride = FindProperty(BaseStyles.renderQueueOverrideName, props);
}
protected void Initialize(Material material)
{
if (!initialized)
{
MaterialChanged(material);
initialized = true;
}
}
protected virtual void MaterialChanged(Material material)
{
SetupMaterialWithRenderingMode(material,
(RenderingMode)renderingMode.floatValue,
(CustomRenderingMode)customRenderingMode.floatValue,
(int)renderQueueOverride.floatValue);
}
protected void RenderingModeOptions(MaterialEditor materialEditor)
{
EditorGUI.BeginChangeCheck();
EditorGUI.showMixedValue = renderingMode.hasMixedValue;
RenderingMode mode = (RenderingMode)renderingMode.floatValue;
EditorGUI.BeginChangeCheck();
mode = (RenderingMode)EditorGUILayout.Popup(renderingMode.displayName, (int)mode, BaseStyles.renderingModeNames);
if (EditorGUI.EndChangeCheck())
{
materialEditor.RegisterPropertyChangeUndo(renderingMode.displayName);
renderingMode.floatValue = (float)mode;
Object[] targets = renderingMode.targets;
foreach (Object target in targets)
{
MaterialChanged((Material)target);
}
}
EditorGUI.showMixedValue = false;
if ((RenderingMode)renderingMode.floatValue == RenderingMode.Custom)
{
EditorGUI.indentLevel += 2;
customRenderingMode.floatValue = EditorGUILayout.Popup(customRenderingMode.displayName, (int)customRenderingMode.floatValue, BaseStyles.customRenderingModeNames);
materialEditor.ShaderProperty(sourceBlend, BaseStyles.sourceBlend);
materialEditor.ShaderProperty(destinationBlend, BaseStyles.destinationBlend);
materialEditor.ShaderProperty(blendOperation, BaseStyles.blendOperation);
materialEditor.ShaderProperty(depthTest, BaseStyles.depthTest);
depthWrite.floatValue = EditorGUILayout.Popup(depthWrite.displayName, (int)depthWrite.floatValue, BaseStyles.depthWriteNames);
materialEditor.ShaderProperty(depthOffsetFactor, BaseStyles.depthOffsetFactor);
materialEditor.ShaderProperty(depthOffsetUnits, BaseStyles.depthOffsetUnits);
materialEditor.ShaderProperty(colorWriteMask, BaseStyles.colorWriteMask);
EditorGUI.indentLevel -= 2;
}
if (!PropertyEnabled(depthWrite))
{
if (MixedRealityToolkitShaderGUIUtilities.DisplayDepthWriteWarning(materialEditor))
{
renderingMode.floatValue = (float)RenderingMode.Custom;
depthWrite.floatValue = (float)DepthWrite.On;
}
}
materialEditor.ShaderProperty(cullMode, BaseStyles.cullMode);
}
protected static void SetupMaterialWithRenderingMode(Material material, RenderingMode mode, CustomRenderingMode customMode, int renderQueueOverride)
{
// If we aren't switching to Custom, then set default values for all RenderingMode types. Otherwise keep whatever user had before
if (mode != RenderingMode.Custom)
{
material.SetInt(BaseStyles.blendOperationName, (int)BlendOp.Add);
material.SetInt(BaseStyles.depthTestName, (int)CompareFunction.LessEqual);
material.SetFloat(BaseStyles.depthOffsetFactorName, 0.0f);
material.SetFloat(BaseStyles.depthOffsetUnitsName, 0.0f);
material.SetInt(BaseStyles.colorWriteMaskName, (int)ColorWriteMask.All);
}
switch (mode)
{
case RenderingMode.Opaque:
{
material.SetOverrideTag(BaseStyles.renderTypeName, BaseStyles.renderingModeNames[(int)RenderingMode.Opaque]);
material.SetInt(BaseStyles.customRenderingModeName, (int)CustomRenderingMode.Opaque);
material.SetInt(BaseStyles.sourceBlendName, (int)BlendMode.One);
material.SetInt(BaseStyles.destinationBlendName, (int)BlendMode.Zero);
material.SetInt(BaseStyles.depthWriteName, (int)DepthWrite.On);
material.DisableKeyword(BaseStyles.alphaTestOnName);
material.DisableKeyword(BaseStyles.alphaBlendOnName);
material.renderQueue = (renderQueueOverride >= 0) ? renderQueueOverride : (int)RenderQueue.Geometry;
}
break;
case RenderingMode.Cutout:
{
material.SetOverrideTag(BaseStyles.renderTypeName, BaseStyles.renderingModeNames[(int)RenderingMode.Cutout]);
material.SetInt(BaseStyles.customRenderingModeName, (int)CustomRenderingMode.Cutout);
material.SetInt(BaseStyles.sourceBlendName, (int)BlendMode.One);
material.SetInt(BaseStyles.destinationBlendName, (int)BlendMode.Zero);
material.SetInt(BaseStyles.depthWriteName, (int)DepthWrite.On);
material.EnableKeyword(BaseStyles.alphaTestOnName);
material.DisableKeyword(BaseStyles.alphaBlendOnName);
material.renderQueue = (renderQueueOverride >= 0) ? renderQueueOverride : (int)RenderQueue.AlphaTest;
}
break;
case RenderingMode.Fade:
{
material.SetOverrideTag(BaseStyles.renderTypeName, BaseStyles.renderingModeNames[(int)RenderingMode.Fade]);
material.SetInt(BaseStyles.customRenderingModeName, (int)CustomRenderingMode.Fade);
material.SetInt(BaseStyles.sourceBlendName, (int)BlendMode.SrcAlpha);
material.SetInt(BaseStyles.destinationBlendName, (int)BlendMode.OneMinusSrcAlpha);
material.SetInt(BaseStyles.depthWriteName, (int)DepthWrite.Off);
material.DisableKeyword(BaseStyles.alphaTestOnName);
material.EnableKeyword(BaseStyles.alphaBlendOnName);
material.renderQueue = (renderQueueOverride >= 0) ? renderQueueOverride : (int)RenderQueue.Transparent;
}
break;
case RenderingMode.Transparent:
{
material.SetOverrideTag(BaseStyles.renderTypeName, BaseStyles.renderingModeNames[(int)RenderingMode.Fade]);
material.SetInt(BaseStyles.customRenderingModeName, (int)CustomRenderingMode.Fade);
material.SetInt(BaseStyles.sourceBlendName, (int)BlendMode.One);
material.SetInt(BaseStyles.destinationBlendName, (int)BlendMode.OneMinusSrcAlpha);
material.SetInt(BaseStyles.depthWriteName, (int)DepthWrite.Off);
material.DisableKeyword(BaseStyles.alphaTestOnName);
material.EnableKeyword(BaseStyles.alphaBlendOnName);
material.renderQueue = (renderQueueOverride >= 0) ? renderQueueOverride : (int)RenderQueue.Transparent;
}
break;
case RenderingMode.Additive:
{
material.SetOverrideTag(BaseStyles.renderTypeName, BaseStyles.renderingModeNames[(int)RenderingMode.Fade]);
material.SetInt(BaseStyles.customRenderingModeName, (int)CustomRenderingMode.Fade);
material.SetInt(BaseStyles.sourceBlendName, (int)BlendMode.One);
material.SetInt(BaseStyles.destinationBlendName, (int)BlendMode.One);
material.SetInt(BaseStyles.depthWriteName, (int)DepthWrite.Off);
material.DisableKeyword(BaseStyles.alphaTestOnName);
material.EnableKeyword(BaseStyles.alphaBlendOnName);
material.renderQueue = (renderQueueOverride >= 0) ? renderQueueOverride : (int)RenderQueue.Transparent;
}
break;
case RenderingMode.Custom:
{
material.SetOverrideTag(BaseStyles.renderTypeName, BaseStyles.customRenderingModeNames[(int)customMode]);
// _SrcBlend, _DstBlend, _BlendOp, _ZTest, _ZWrite, _ColorWriteMask are controlled by UI.
switch (customMode)
{
case CustomRenderingMode.Opaque:
{
material.DisableKeyword(BaseStyles.alphaTestOnName);
material.DisableKeyword(BaseStyles.alphaBlendOnName);
}
break;
case CustomRenderingMode.Cutout:
{
material.EnableKeyword(BaseStyles.alphaTestOnName);
material.DisableKeyword(BaseStyles.alphaBlendOnName);
}
break;
case CustomRenderingMode.Fade:
{
material.DisableKeyword(BaseStyles.alphaTestOnName);
material.EnableKeyword(BaseStyles.alphaBlendOnName);
}
break;
}
material.renderQueue = (renderQueueOverride >= 0) ? renderQueueOverride : material.renderQueue;
}
break;
}
}
/// <summary>
/// Check whether shader feature is enabled
/// </summary>
/// <param name="property">float property to check against</param>
/// <returns>false if 0.0f, true otherwise</returns>
protected static bool PropertyEnabled(MaterialProperty property)
{
return !property.floatValue.Equals(0.0f);
}
/// <summary>
/// Get the value of a given float property for a material
/// </summary>
/// <param name="material">material to check</param>
/// <param name="propertyName">name of property against material</param>
/// <returns>if has property, then value of that property for current material, null otherwise</returns>
protected static float? GetFloatProperty(Material material, string propertyName)
{
if (material.HasProperty(propertyName))
{
return material.GetFloat(propertyName);
}
return null;
}
/// <summary>
/// Get the value of a given vector property for a material
/// </summary>
/// <param name="material">material to check</param>
/// <param name="propertyName">name of property against material</param>
/// <returns>if has property, then value of that property for current material, null otherwise</returns>
protected static Vector4? GetVectorProperty(Material material, string propertyName)
{
if (material.HasProperty(propertyName))
{
return material.GetVector(propertyName);
}
return null;
}
/// <summary>
/// Get the value of a given color property for a material
/// </summary>
/// <param name="material">material to check</param>
/// <param name="propertyName">name of property against material</param>
/// <returns>if has property, then value of that property for current material, null otherwise</returns>
protected static Color? GetColorProperty(Material material, string propertyName)
{
if (material.HasProperty(propertyName))
{
return material.GetColor(propertyName);
}
return null;
}
/// <summary>
/// Sets the shader feature controlled by keyword and property name parameters active or inactive
/// </summary>
/// <param name="material">Material to modify</param>
/// <param name="keywordName">Keyword of shader feature</param>
/// <param name="propertyName">Associated property name for shader feature</param>
/// <param name="propertyValue">float to be treated as a boolean flag for setting shader feature active or inactive</param>
protected static void SetShaderFeatureActive(Material material, string keywordName, string propertyName, float? propertyValue)
{
if (propertyValue.HasValue)
{
if (keywordName != null)
{
if (!propertyValue.Value.Equals(0.0f))
{
material.EnableKeyword(keywordName);
}
else
{
material.DisableKeyword(keywordName);
}
}
material.SetFloat(propertyName, propertyValue.Value);
}
}
/// <summary>
/// Sets vector property against associated material
/// </summary>
/// <param name="material">material to control</param>
/// <param name="propertyName">name of property to set</param>
/// <param name="propertyValue">value of property to set</param>
protected static void SetVectorProperty(Material material, string propertyName, Vector4? propertyValue)
{
if (propertyValue.HasValue)
{
material.SetVector(propertyName, propertyValue.Value);
}
}
/// <summary>
/// Set color property against associated material
/// </summary>
/// <param name="material">material to control</param>
/// <param name="propertyName">name of property to set</param>
/// <param name="propertyValue">value of property to set</param>
protected static void SetColorProperty(Material material, string propertyName, Color? propertyValue)
{
if (propertyValue.HasValue)
{
material.SetColor(propertyName, propertyValue.Value);
}
}
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Utilities;
using System;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEngine.Rendering;
using Object = UnityEngine.Object;
namespace Microsoft.MixedReality.Toolkit.Editor
{
/// <summary>
/// A custom shader inspector for the "Mixed Reality Toolkit/Standard" shader.
/// </summary>
public class MixedRealityStandardShaderGUI : MixedRealityShaderGUI
{
protected enum AlbedoAlphaMode
{
Transparency,
Metallic,
Smoothness
}
protected static class Styles
{
public static string primaryMapsTitle = "Main Maps";
public static string renderingOptionsTitle = "Rendering Options";
public static string advancedOptionsTitle = "Advanced Options";
public static string fluentOptionsTitle = "Fluent Options";
public static string instancedColorName = "_InstancedColor";
public static string instancedColorFeatureName = "_INSTANCED_COLOR";
public static string stencilComparisonName = "_StencilComparison";
public static string stencilOperationName = "_StencilOperation";
public static string disableAlbedoMapName = "_DISABLE_ALBEDO_MAP";
public static string albedoMapAlphaMetallicName = "_METALLIC_TEXTURE_ALBEDO_CHANNEL_A";
public static string albedoMapAlphaSmoothnessName = "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A";
public static string propertiesComponentHelp = "Use the {0} component(s) to control {1} properties.";
public static readonly string[] albedoAlphaModeNames = Enum.GetNames(typeof(AlbedoAlphaMode));
public static GUIContent instancedColor = new GUIContent("Instanced Color", "Enable a Unique Color Per Instance");
public static GUIContent albedo = new GUIContent("Albedo", "Albedo (RGB) and Transparency (Alpha)");
public static GUIContent albedoAssignedAtRuntime = new GUIContent("Assigned at Runtime", "As an optimization albedo operations are disabled when no albedo texture is specified. If a albedo texture will be specified at runtime enable this option.");
public static GUIContent alphaCutoff = new GUIContent("Alpha Cutoff", "Threshold for Alpha Cutoff");
public static GUIContent metallic = new GUIContent("Metallic", "Metallic Value");
public static GUIContent smoothness = new GUIContent("Smoothness", "Smoothness Value");
public static GUIContent enableChannelMap = new GUIContent("Channel Map", "Enable Channel Map, a Channel Packing Texture That Follows Unity's Standard Channel Setup");
public static GUIContent channelMap = new GUIContent("Channel Map", "Metallic (Red), Occlusion (Green), Emission (Blue), Smoothness (Alpha)");
public static GUIContent enableNormalMap = new GUIContent("Normal Map", "Enable Normal Map");
public static GUIContent normalMap = new GUIContent("Normal Map");
public static GUIContent normalMapScale = new GUIContent("Scale", "Scales the Normal Map Normal");
public static GUIContent enableEmission = new GUIContent("Emission", "Enable Emission");
public static GUIContent emissiveColor = new GUIContent("Color");
public static GUIContent enableTriplanarMapping = new GUIContent("Triplanar Mapping", "Enable Triplanar Mapping, a technique which programmatically generates UV coordinates");
public static GUIContent enableLocalSpaceTriplanarMapping = new GUIContent("Local Space", "If True Triplanar Mapping is Calculated in Local Space");
public static GUIContent triplanarMappingBlendSharpness = new GUIContent("Blend Sharpness", "The Power of the Blend with the Normal");
public static GUIContent directionalLight = new GUIContent("Directional Light", "Affected by One Unity Directional Light");
public static GUIContent specularHighlights = new GUIContent("Specular Highlights", "Calculate Specular Highlights");
public static GUIContent sphericalHarmonics = new GUIContent("Spherical Harmonics", "Read From Spherical Harmonics Data for Ambient Light");
public static GUIContent reflections = new GUIContent("Reflections", "Calculate Glossy Reflections");
public static GUIContent refraction = new GUIContent("Refraction", "Calculate Refraction");
public static GUIContent refractiveIndex = new GUIContent("Refractive Index", "Ratio of Indices of Refraction at the Surface Interface");
public static GUIContent rimLight = new GUIContent("Rim Light", "Enable Rim (Fresnel) Lighting");
public static GUIContent rimColor = new GUIContent("Color", "Rim Highlight Color");
public static GUIContent rimPower = new GUIContent("Power", "Rim Highlight Saturation");
public static GUIContent vertexColors = new GUIContent("Vertex Colors", "Enable Vertex Color Tinting");
public static GUIContent vertexExtrusion = new GUIContent("Vertex Extrusion", "Enable Vertex Extrusion Along the Vertex Normal");
public static GUIContent vertexExtrusionValue = new GUIContent("Extrusion Value", "How Far to Extrude the Vertex Along the Vertex Normal");
public static GUIContent vertexExtrusionSmoothNormals = new GUIContent("Use Smooth Normals", "Should Vertex Extrusion use the Smooth Normals in UV3, or Default Normals");
public static GUIContent blendedClippingWidth = new GUIContent("Blended Clipping Width", "The Width of the Clipping Primitive Clip Fade Region on Non-Cutout Materials");
public static GUIContent clippingBorder = new GUIContent("Clipping Border", "Enable a Border Along the Clipping Primitive's Edge");
public static GUIContent clippingBorderWidth = new GUIContent("Width", "Width of the Clipping Border");
public static GUIContent clippingBorderColor = new GUIContent("Color", "Interpolated Color of the Clipping Border");
public static GUIContent nearPlaneFade = new GUIContent("Near Fade", "Objects Disappear (Turn to Black/Transparent) as the Camera (or Hover/Proximity Light) Nears Them");
public static GUIContent nearLightFade = new GUIContent("Use Light", "A Hover or Proximity Light (Rather Than the Camera) Determines Near Fade Distance");
public static GUIContent fadeBeginDistance = new GUIContent("Fade Begin", "Distance From Camera (or Hover/Proximity Light) to Begin Fade In");
public static GUIContent fadeCompleteDistance = new GUIContent("Fade Complete", "Distance From Camera (or Hover/Proximity Light) When Fade is Fully In");
public static GUIContent fadeMinValue = new GUIContent("Fade Min Value", "Clamps the Fade Amount to a Minimum Value");
public static GUIContent hoverLight = new GUIContent("Hover Light", "Enable utilization of Hover Light(s)");
public static GUIContent enableHoverColorOverride = new GUIContent("Override Color", "Override Global Hover Light Color for this Material");
public static GUIContent hoverColorOverride = new GUIContent("Color", "Override Hover Light Color");
public static GUIContent proximityLight = new GUIContent("Proximity Light", "Enable utilization of Proximity Light(s)");
public static GUIContent enableProximityLightColorOverride = new GUIContent("Override Color", "Override Global Proximity Light Color for this Material");
public static GUIContent proximityLightCenterColorOverride = new GUIContent("Center Color", "The Override Color of the ProximityLight Gradient at the Center (RGB) and (A) is Gradient Extent");
public static GUIContent proximityLightMiddleColorOverride = new GUIContent("Middle Color", "The Override Color of the ProximityLight Gradient at the Middle (RGB) and (A) is Gradient Extent");
public static GUIContent proximityLightOuterColorOverride = new GUIContent("Outer Color", "The Override Color of the ProximityLight Gradient at the Outer Edge (RGB) and (A) is Gradient Extent");
public static GUIContent proximityLightSubtractive = new GUIContent("Subtractive", "Proximity Lights Remove Light from a Surface, Used to Mimic a Shadow");
public static GUIContent proximityLightTwoSided = new GUIContent("Two Sided", "Proximity Lights Apply to Both Sides of a Surface");
public static GUIContent fluentLightIntensity = new GUIContent("Light Intensity", "Intensity Scaler for All Hover and Proximity Lights");
public static GUIContent roundCorners = new GUIContent("Round Corners", "(Assumes UVs Specify Borders of Surface, Works Best on Unity Cube, Quad, and Plane)");
public static GUIContent roundCornerRadius = new GUIContent("Unit Radius", "Rounded Rectangle Corner Unit Sphere Radius");
public static GUIContent roundCornersRadius = new GUIContent("Corners Radius", "UpLeft-UpRight-BottomRight-BottomLeft");
public static GUIContent roundCornerMargin = new GUIContent("Margin %", "Distance From Geometry Edge");
public static GUIContent independentCorners = new GUIContent("Independent Corners", "Manage each corner separately");
public static GUIContent borderLight = new GUIContent("Border Light", "Enable Border Lighting (Assumes UVs Specify Borders of Surface, Works Best on Unity Cube, Quad, and Plane)");
public static GUIContent borderLightUsesHoverColor = new GUIContent("Use Hover Color", "Border Color Comes From Hover Light Color Override");
public static GUIContent borderLightReplacesAlbedo = new GUIContent("Replace Albedo", "Border Light Replaces Albedo (Replacement Rather Than Additive)");
public static GUIContent borderLightOpaque = new GUIContent("Opaque Borders", "Borders Override Alpha Value to Appear Opaque");
public static GUIContent borderWidth = new GUIContent("Width %", "Uniform Width Along Border as a % of the Smallest XYZ Dimension");
public static GUIContent borderMinValue = new GUIContent("Brightness", "Brightness Scaler");
public static GUIContent edgeSmoothingValue = new GUIContent("Edge Smoothing Value", "Smooths Edges When Round Corners and Transparency Is Enabled");
public static GUIContent borderLightOpaqueAlpha = new GUIContent("Alpha", "Alpha value of \"opaque\" borders.");
public static GUIContent innerGlow = new GUIContent("Inner Glow", "Enable Inner Glow (Assumes UVs Specify Borders of Surface, Works Best on Unity Cube, Quad, and Plane)");
public static GUIContent innerGlowColor = new GUIContent("Color", "Inner Glow Color (RGB) and Intensity (A)");
public static GUIContent innerGlowPower = new GUIContent("Power", "Power Exponent to Control Glow");
public static GUIContent iridescence = new GUIContent("Iridescence", "Simulated Iridescence via Albedo Changes with the Angle of Observation)");
public static GUIContent iridescentSpectrumMap = new GUIContent("Spectrum Map", "Spectrum of Colors to Apply (Usually a Texture with ROYGBIV from Left to Right)");
public static GUIContent iridescenceIntensity = new GUIContent("Intensity", "Intensity of Iridescence");
public static GUIContent iridescenceThreshold = new GUIContent("Threshold", "Threshold Window to Sample From the Spectrum Map");
public static GUIContent iridescenceAngle = new GUIContent("Angle", "Surface Angle");
public static GUIContent environmentColoring = new GUIContent("Environment Coloring", "Change Color Based on View");
public static GUIContent environmentColorThreshold = new GUIContent("Threshold", "Threshold When Environment Coloring Should Appear Based on Surface Normal");
public static GUIContent environmentColorIntensity = new GUIContent("Intensity", "Intensity (or Brightness) of the Environment Coloring");
public static GUIContent environmentColorX = new GUIContent("X-Axis Color", "Color Along the World Space X-Axis");
public static GUIContent environmentColorY = new GUIContent("Y-Axis Color", "Color Along the World Space Y-Axis");
public static GUIContent environmentColorZ = new GUIContent("Z-Axis Color", "Color Along the World Space Z-Axis");
public static GUIContent stencil = new GUIContent("Enable Stencil Testing", "Enabled Stencil Testing Operations");
public static GUIContent stencilReference = new GUIContent("Stencil Reference", "Value to Compared Against (if Comparison is Anything but Always) and/or the Value to be Written to the Buffer (if Either Pass, Fail or ZFail is Set to Replace)");
public static GUIContent stencilComparison = new GUIContent("Stencil Comparison", "Function to Compare the Reference Value to");
public static GUIContent stencilOperation = new GUIContent("Stencil Operation", "What to do When the Stencil Test Passes");
public static GUIContent ignoreZScale = new GUIContent("Ignore Z Scale", "For Features That Use Object Scale (Round Corners, Border Light, etc.), Ignore the Z Scale of the Object");
}
protected MaterialProperty instancedColor;
protected MaterialProperty albedoMap;
protected MaterialProperty albedoColor;
protected MaterialProperty albedoAlphaMode;
protected MaterialProperty albedoAssignedAtRuntime;
protected MaterialProperty alphaCutoff;
protected MaterialProperty enableChannelMap;
protected MaterialProperty channelMap;
protected MaterialProperty enableNormalMap;
protected MaterialProperty normalMap;
protected MaterialProperty normalMapScale;
protected MaterialProperty enableEmission;
protected MaterialProperty emissiveColor;
protected MaterialProperty enableTriplanarMapping;
protected MaterialProperty enableLocalSpaceTriplanarMapping;
protected MaterialProperty triplanarMappingBlendSharpness;
protected MaterialProperty metallic;
protected MaterialProperty smoothness;
protected MaterialProperty directionalLight;
protected MaterialProperty specularHighlights;
protected MaterialProperty sphericalHarmonics;
protected MaterialProperty reflections;
protected MaterialProperty refraction;
protected MaterialProperty refractiveIndex;
protected MaterialProperty rimLight;
protected MaterialProperty rimColor;
protected MaterialProperty rimPower;
protected MaterialProperty vertexColors;
protected MaterialProperty vertexExtrusion;
protected MaterialProperty vertexExtrusionValue;
protected MaterialProperty vertexExtrusionSmoothNormals;
protected MaterialProperty blendedClippingWidth;
protected MaterialProperty clippingBorder;
protected MaterialProperty clippingBorderWidth;
protected MaterialProperty clippingBorderColor;
protected MaterialProperty nearPlaneFade;
protected MaterialProperty nearLightFade;
protected MaterialProperty fadeBeginDistance;
protected MaterialProperty fadeCompleteDistance;
protected MaterialProperty fadeMinValue;
protected MaterialProperty hoverLight;
protected MaterialProperty enableHoverColorOverride;
protected MaterialProperty hoverColorOverride;
protected MaterialProperty proximityLight;
protected MaterialProperty enableProximityLightColorOverride;
protected MaterialProperty proximityLightCenterColorOverride;
protected MaterialProperty proximityLightMiddleColorOverride;
protected MaterialProperty proximityLightOuterColorOverride;
protected MaterialProperty proximityLightSubtractive;
protected MaterialProperty proximityLightTwoSided;
protected MaterialProperty fluentLightIntensity;
protected MaterialProperty roundCorners;
protected MaterialProperty roundCornerRadius;
protected MaterialProperty roundCornerMargin;
protected MaterialProperty independentCorners;
protected MaterialProperty roundCornersRadius;
protected MaterialProperty borderLight;
protected MaterialProperty borderLightUsesHoverColor;
protected MaterialProperty borderLightReplacesAlbedo;
protected MaterialProperty borderLightOpaque;
protected MaterialProperty borderWidth;
protected MaterialProperty borderMinValue;
protected MaterialProperty edgeSmoothingValue;
protected MaterialProperty borderLightOpaqueAlpha;
protected MaterialProperty innerGlow;
protected MaterialProperty innerGlowColor;
protected MaterialProperty innerGlowPower;
protected MaterialProperty iridescence;
protected MaterialProperty iridescentSpectrumMap;
protected MaterialProperty iridescenceIntensity;
protected MaterialProperty iridescenceThreshold;
protected MaterialProperty iridescenceAngle;
protected MaterialProperty environmentColoring;
protected MaterialProperty environmentColorThreshold;
protected MaterialProperty environmentColorIntensity;
protected MaterialProperty environmentColorX;
protected MaterialProperty environmentColorY;
protected MaterialProperty environmentColorZ;
protected MaterialProperty stencil;
protected MaterialProperty stencilReference;
protected MaterialProperty stencilComparison;
protected MaterialProperty stencilOperation;
protected MaterialProperty ignoreZScale;
protected override void FindProperties(MaterialProperty[] props)
{
base.FindProperties(props);
instancedColor = FindProperty(Styles.instancedColorName, props);
albedoMap = FindProperty("_MainTex", props);
albedoColor = FindProperty("_Color", props);
albedoAlphaMode = FindProperty("_AlbedoAlphaMode", props);
albedoAssignedAtRuntime = FindProperty("_AlbedoAssignedAtRuntime", props);
alphaCutoff = FindProperty("_Cutoff", props);
metallic = FindProperty("_Metallic", props);
smoothness = FindProperty("_Smoothness", props);
enableChannelMap = FindProperty("_EnableChannelMap", props);
channelMap = FindProperty("_ChannelMap", props);
enableNormalMap = FindProperty("_EnableNormalMap", props);
normalMap = FindProperty("_NormalMap", props);
normalMapScale = FindProperty("_NormalMapScale", props);
enableEmission = FindProperty("_EnableEmission", props);
emissiveColor = FindProperty("_EmissiveColor", props);
enableTriplanarMapping = FindProperty("_EnableTriplanarMapping", props);
enableLocalSpaceTriplanarMapping = FindProperty("_EnableLocalSpaceTriplanarMapping", props);
triplanarMappingBlendSharpness = FindProperty("_TriplanarMappingBlendSharpness", props);
directionalLight = FindProperty("_DirectionalLight", props);
specularHighlights = FindProperty("_SpecularHighlights", props);
sphericalHarmonics = FindProperty("_SphericalHarmonics", props);
reflections = FindProperty("_Reflections", props);
refraction = FindProperty("_Refraction", props);
refractiveIndex = FindProperty("_RefractiveIndex", props);
rimLight = FindProperty("_RimLight", props);
rimColor = FindProperty("_RimColor", props);
rimPower = FindProperty("_RimPower", props);
vertexColors = FindProperty("_VertexColors", props);
vertexExtrusion = FindProperty("_VertexExtrusion", props);
vertexExtrusionValue = FindProperty("_VertexExtrusionValue", props);
vertexExtrusionSmoothNormals = FindProperty("_VertexExtrusionSmoothNormals", props);
blendedClippingWidth = FindProperty("_BlendedClippingWidth", props);
clippingBorder = FindProperty("_ClippingBorder", props);
clippingBorderWidth = FindProperty("_ClippingBorderWidth", props);
clippingBorderColor = FindProperty("_ClippingBorderColor", props);
nearPlaneFade = FindProperty("_NearPlaneFade", props);
nearLightFade = FindProperty("_NearLightFade", props);
fadeBeginDistance = FindProperty("_FadeBeginDistance", props);
fadeCompleteDistance = FindProperty("_FadeCompleteDistance", props);
fadeMinValue = FindProperty("_FadeMinValue", props);
hoverLight = FindProperty("_HoverLight", props);
enableHoverColorOverride = FindProperty("_EnableHoverColorOverride", props);
hoverColorOverride = FindProperty("_HoverColorOverride", props);
proximityLight = FindProperty("_ProximityLight", props);
enableProximityLightColorOverride = FindProperty("_EnableProximityLightColorOverride", props);
proximityLightCenterColorOverride = FindProperty("_ProximityLightCenterColorOverride", props);
proximityLightMiddleColorOverride = FindProperty("_ProximityLightMiddleColorOverride", props);
proximityLightOuterColorOverride = FindProperty("_ProximityLightOuterColorOverride", props);
proximityLightSubtractive = FindProperty("_ProximityLightSubtractive", props);
proximityLightTwoSided = FindProperty("_ProximityLightTwoSided", props);
fluentLightIntensity = FindProperty("_FluentLightIntensity", props);
roundCorners = FindProperty("_RoundCorners", props);
roundCornerRadius = FindProperty("_RoundCornerRadius", props);
roundCornersRadius = FindProperty("_RoundCornersRadius", props);
roundCornerMargin = FindProperty("_RoundCornerMargin", props);
independentCorners = FindProperty("_IndependentCorners", props);
borderLight = FindProperty("_BorderLight", props);
borderLightUsesHoverColor = FindProperty("_BorderLightUsesHoverColor", props);
borderLightReplacesAlbedo = FindProperty("_BorderLightReplacesAlbedo", props);
borderLightOpaque = FindProperty("_BorderLightOpaque", props);
borderWidth = FindProperty("_BorderWidth", props);
borderMinValue = FindProperty("_BorderMinValue", props);
edgeSmoothingValue = FindProperty("_EdgeSmoothingValue", props);
borderLightOpaqueAlpha = FindProperty("_BorderLightOpaqueAlpha", props);
innerGlow = FindProperty("_InnerGlow", props);
innerGlowColor = FindProperty("_InnerGlowColor", props);
innerGlowPower = FindProperty("_InnerGlowPower", props);
iridescence = FindProperty("_Iridescence", props);
iridescentSpectrumMap = FindProperty("_IridescentSpectrumMap", props);
iridescenceIntensity = FindProperty("_IridescenceIntensity", props);
iridescenceThreshold = FindProperty("_IridescenceThreshold", props);
iridescenceAngle = FindProperty("_IridescenceAngle", props);
environmentColoring = FindProperty("_EnvironmentColoring", props);
environmentColorThreshold = FindProperty("_EnvironmentColorThreshold", props);
environmentColorIntensity = FindProperty("_EnvironmentColorIntensity", props);
environmentColorX = FindProperty("_EnvironmentColorX", props);
environmentColorY = FindProperty("_EnvironmentColorY", props);
environmentColorZ = FindProperty("_EnvironmentColorZ", props);
stencil = FindProperty("_Stencil", props);
stencilReference = FindProperty("_StencilReference", props);
stencilComparison = FindProperty(Styles.stencilComparisonName, props);
stencilOperation = FindProperty(Styles.stencilOperationName, props);
ignoreZScale = FindProperty("_IgnoreZScale", props);
}
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
{
Material material = (Material)materialEditor.target;
base.OnGUI(materialEditor, props);
MainMapOptions(materialEditor, material);
RenderingOptions(materialEditor, material);
FluentOptions(materialEditor, material);
AdvancedOptions(materialEditor, material);
}
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
{
// Cache old shader properties with potentially different names than the new shader.
float? smoothness = GetFloatProperty(material, "_Glossiness");
float? diffuse = GetFloatProperty(material, "_UseDiffuse");
float? specularHighlights = GetFloatProperty(material, "_SpecularHighlights");
float? normalMap = null;
Texture normalMapTexture = material.GetTexture("_BumpMap");
float? normalMapScale = GetFloatProperty(material, "_BumpScale");
float? emission = null;
Color? emissionColor = GetColorProperty(material, "_EmissionColor");
float? reflections = null;
float? rimLighting = null;
Vector4? textureScaleOffset = null;
float? cullMode = GetFloatProperty(material, "_Cull");
if (oldShader)
{
if (oldShader.name.Contains("Standard"))
{
normalMap = material.IsKeywordEnabled("_NORMALMAP") ? 1.0f : 0.0f;
emission = material.IsKeywordEnabled("_EMISSION") ? 1.0f : 0.0f;
reflections = GetFloatProperty(material, "_GlossyReflections");
}
else if (oldShader.name.Contains("Fast Configurable"))
{
normalMap = material.IsKeywordEnabled("_USEBUMPMAP_ON") ? 1.0f : 0.0f;
emission = GetFloatProperty(material, "_UseEmissionColor");
reflections = GetFloatProperty(material, "_UseReflections");
rimLighting = GetFloatProperty(material, "_UseRimLighting");
textureScaleOffset = GetVectorProperty(material, "_TextureScaleOffset");
}
}
base.AssignNewShaderToMaterial(material, oldShader, newShader);
// Apply old shader properties to the new shader.
SetShaderFeatureActive(material, null, "_Smoothness", smoothness);
SetShaderFeatureActive(material, "_DIRECTIONAL_LIGHT", "_DirectionalLight", diffuse);
SetShaderFeatureActive(material, "_SPECULAR_HIGHLIGHTS", "_SpecularHighlights", specularHighlights);
SetShaderFeatureActive(material, "_NORMAL_MAP", "_EnableNormalMap", normalMap);
if (normalMapTexture)
{
material.SetTexture("_NormalMap", normalMapTexture);
}
SetShaderFeatureActive(material, null, "_NormalMapScale", normalMapScale);
SetShaderFeatureActive(material, "_EMISSION", "_EnableEmission", emission);
SetColorProperty(material, "_EmissiveColor", emissionColor);
SetShaderFeatureActive(material, "_REFLECTIONS", "_Reflections", reflections);
SetShaderFeatureActive(material, "_RIM_LIGHT", "_RimLight", rimLighting);
SetVectorProperty(material, "_MainTex_ST", textureScaleOffset);
SetShaderFeatureActive(material, null, "_CullMode", cullMode);
// Setup the rendering mode based on the old shader.
if (oldShader == null || !oldShader.name.Contains(LegacyShadersPath))
{
SetupMaterialWithRenderingMode(material, (RenderingMode)material.GetFloat(BaseStyles.renderingModeName), CustomRenderingMode.Opaque, -1);
}
else
{
RenderingMode mode = RenderingMode.Opaque;
if (oldShader.name.Contains(TransparentCutoutShadersPath))
{
mode = RenderingMode.Cutout;
}
else if (oldShader.name.Contains(TransparentShadersPath))
{
mode = RenderingMode.Fade;
}
material.SetFloat(BaseStyles.renderingModeName, (float)mode);
MaterialChanged(material);
}
}
protected override void MaterialChanged(Material material)
{
SetupMaterialWithAlbedo(material, albedoMap, albedoAlphaMode, albedoAssignedAtRuntime);
base.MaterialChanged(material);
}
protected void MainMapOptions(MaterialEditor materialEditor, Material material)
{
GUILayout.Label(Styles.primaryMapsTitle, EditorStyles.boldLabel);
materialEditor.TexturePropertySingleLine(Styles.albedo, albedoMap, albedoColor);
if (albedoMap.textureValue == null)
{
materialEditor.ShaderProperty(albedoAssignedAtRuntime, Styles.albedoAssignedAtRuntime, 2);
}
materialEditor.ShaderProperty(enableChannelMap, Styles.enableChannelMap);
if (PropertyEnabled(enableChannelMap))
{
EditorGUI.indentLevel += 2;
materialEditor.TexturePropertySingleLine(Styles.channelMap, channelMap);
GUILayout.Box("Metallic (Red), Occlusion (Green), Emission (Blue), Smoothness (Alpha)", EditorStyles.helpBox, Array.Empty<GUILayoutOption>());
EditorGUI.indentLevel -= 2;
}
if (!PropertyEnabled(enableChannelMap))
{
EditorGUI.indentLevel += 2;
materialEditor.ShaderProperty(albedoAlphaMode, albedoAlphaMode.displayName);
if ((RenderingMode)renderingMode.floatValue == RenderingMode.Cutout ||
(RenderingMode)renderingMode.floatValue == RenderingMode.Custom)
{
materialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoff.text);
}
if ((AlbedoAlphaMode)albedoAlphaMode.floatValue != AlbedoAlphaMode.Metallic)
{
materialEditor.ShaderProperty(metallic, Styles.metallic);
}
if ((AlbedoAlphaMode)albedoAlphaMode.floatValue != AlbedoAlphaMode.Smoothness)
{
materialEditor.ShaderProperty(smoothness, Styles.smoothness);
}
SetupMaterialWithAlbedo(material, albedoMap, albedoAlphaMode, albedoAssignedAtRuntime);
EditorGUI.indentLevel -= 2;
}
if (PropertyEnabled(directionalLight) ||
PropertyEnabled(reflections) ||
PropertyEnabled(rimLight) ||
PropertyEnabled(environmentColoring))
{
materialEditor.ShaderProperty(enableNormalMap, Styles.enableNormalMap);
if (PropertyEnabled(enableNormalMap))
{
EditorGUI.indentLevel += 2;
materialEditor.TexturePropertySingleLine(Styles.normalMap, normalMap, normalMap.textureValue != null ? normalMapScale : null);
EditorGUI.indentLevel -= 2;
}
}
materialEditor.ShaderProperty(enableEmission, Styles.enableEmission);
if (PropertyEnabled(enableEmission))
{
materialEditor.ShaderProperty(emissiveColor, Styles.emissiveColor, 2);
}
materialEditor.ShaderProperty(enableTriplanarMapping, Styles.enableTriplanarMapping);
if (PropertyEnabled(enableTriplanarMapping))
{
materialEditor.ShaderProperty(enableLocalSpaceTriplanarMapping, Styles.enableLocalSpaceTriplanarMapping, 2);
materialEditor.ShaderProperty(triplanarMappingBlendSharpness, Styles.triplanarMappingBlendSharpness, 2);
}
EditorGUILayout.Space();
materialEditor.TextureScaleOffsetProperty(albedoMap);
}
protected void RenderingOptions(MaterialEditor materialEditor, Material material)
{
EditorGUILayout.Space();
GUILayout.Label(Styles.renderingOptionsTitle, EditorStyles.boldLabel);
materialEditor.ShaderProperty(directionalLight, Styles.directionalLight);
if (PropertyEnabled(directionalLight))
{
materialEditor.ShaderProperty(specularHighlights, Styles.specularHighlights, 2);
}
materialEditor.ShaderProperty(sphericalHarmonics, Styles.sphericalHarmonics);
materialEditor.ShaderProperty(reflections, Styles.reflections);
if (PropertyEnabled(reflections))
{
materialEditor.ShaderProperty(refraction, Styles.refraction, 2);
if (PropertyEnabled(refraction))
{
materialEditor.ShaderProperty(refractiveIndex, Styles.refractiveIndex, 4);
}
}
materialEditor.ShaderProperty(rimLight, Styles.rimLight);
if (PropertyEnabled(rimLight))
{
materialEditor.ShaderProperty(rimColor, Styles.rimColor, 2);
materialEditor.ShaderProperty(rimPower, Styles.rimPower, 2);
}
materialEditor.ShaderProperty(vertexColors, Styles.vertexColors);
materialEditor.ShaderProperty(vertexExtrusion, Styles.vertexExtrusion);
if (PropertyEnabled(vertexExtrusion))
{
materialEditor.ShaderProperty(vertexExtrusionValue, Styles.vertexExtrusionValue, 2);
materialEditor.ShaderProperty(vertexExtrusionSmoothNormals, Styles.vertexExtrusionSmoothNormals, 2);
}
if ((RenderingMode)renderingMode.floatValue != RenderingMode.Opaque &&
(RenderingMode)renderingMode.floatValue != RenderingMode.Cutout)
{
materialEditor.ShaderProperty(blendedClippingWidth, Styles.blendedClippingWidth);
GUILayout.Box(string.Format(Styles.propertiesComponentHelp, nameof(ClippingPrimitive), "other clipping"), EditorStyles.helpBox, Array.Empty<GUILayoutOption>());
}
materialEditor.ShaderProperty(clippingBorder, Styles.clippingBorder);
if (PropertyEnabled(clippingBorder))
{
materialEditor.ShaderProperty(clippingBorderWidth, Styles.clippingBorderWidth, 2);
materialEditor.ShaderProperty(clippingBorderColor, Styles.clippingBorderColor, 2);
GUILayout.Box(string.Format(Styles.propertiesComponentHelp, nameof(ClippingPrimitive), "other clipping"), EditorStyles.helpBox, Array.Empty<GUILayoutOption>());
}
materialEditor.ShaderProperty(nearPlaneFade, Styles.nearPlaneFade);
if (PropertyEnabled(nearPlaneFade))
{
materialEditor.ShaderProperty(nearLightFade, Styles.nearLightFade, 2);
materialEditor.ShaderProperty(fadeBeginDistance, Styles.fadeBeginDistance, 2);
materialEditor.ShaderProperty(fadeCompleteDistance, Styles.fadeCompleteDistance, 2);
materialEditor.ShaderProperty(fadeMinValue, Styles.fadeMinValue, 2);
}
}
protected void FluentOptions(MaterialEditor materialEditor, Material material)
{
EditorGUILayout.Space();
GUILayout.Label(Styles.fluentOptionsTitle, EditorStyles.boldLabel);
RenderingMode mode = (RenderingMode)renderingMode.floatValue;
CustomRenderingMode customMode = (CustomRenderingMode)customRenderingMode.floatValue;
materialEditor.ShaderProperty(hoverLight, Styles.hoverLight);
if (PropertyEnabled(hoverLight))
{
GUILayout.Box(string.Format(Styles.propertiesComponentHelp, nameof(HoverLight), Styles.hoverLight.text), EditorStyles.helpBox, Array.Empty<GUILayoutOption>());
materialEditor.ShaderProperty(enableHoverColorOverride, Styles.enableHoverColorOverride, 2);
if (PropertyEnabled(enableHoverColorOverride))
{
materialEditor.ShaderProperty(hoverColorOverride, Styles.hoverColorOverride, 4);
}
}
materialEditor.ShaderProperty(proximityLight, Styles.proximityLight);
if (PropertyEnabled(proximityLight))
{
materialEditor.ShaderProperty(enableProximityLightColorOverride, Styles.enableProximityLightColorOverride, 2);
if (PropertyEnabled(enableProximityLightColorOverride))
{
materialEditor.ShaderProperty(proximityLightCenterColorOverride, Styles.proximityLightCenterColorOverride, 4);
materialEditor.ShaderProperty(proximityLightMiddleColorOverride, Styles.proximityLightMiddleColorOverride, 4);
materialEditor.ShaderProperty(proximityLightOuterColorOverride, Styles.proximityLightOuterColorOverride, 4);
}
materialEditor.ShaderProperty(proximityLightSubtractive, Styles.proximityLightSubtractive, 2);
materialEditor.ShaderProperty(proximityLightTwoSided, Styles.proximityLightTwoSided, 2);
GUILayout.Box(string.Format(Styles.propertiesComponentHelp, nameof(ProximityLight), Styles.proximityLight.text), EditorStyles.helpBox, Array.Empty<GUILayoutOption>());
}
materialEditor.ShaderProperty(borderLight, Styles.borderLight);
if (PropertyEnabled(borderLight))
{
materialEditor.ShaderProperty(borderWidth, Styles.borderWidth, 2);
materialEditor.ShaderProperty(borderMinValue, Styles.borderMinValue, 2);
materialEditor.ShaderProperty(borderLightReplacesAlbedo, Styles.borderLightReplacesAlbedo, 2);
if (PropertyEnabled(hoverLight) && PropertyEnabled(enableHoverColorOverride))
{
materialEditor.ShaderProperty(borderLightUsesHoverColor, Styles.borderLightUsesHoverColor, 2);
}
if (mode == RenderingMode.Cutout || mode == RenderingMode.Fade || mode == RenderingMode.Transparent ||
(mode == RenderingMode.Custom && customMode == CustomRenderingMode.Cutout) ||
(mode == RenderingMode.Custom && customMode == CustomRenderingMode.Fade))
{
materialEditor.ShaderProperty(borderLightOpaque, Styles.borderLightOpaque, 2);
if (PropertyEnabled(borderLightOpaque))
{
materialEditor.ShaderProperty(borderLightOpaqueAlpha, Styles.borderLightOpaqueAlpha, 4);
}
}
}
if (PropertyEnabled(hoverLight) || PropertyEnabled(proximityLight) || PropertyEnabled(borderLight))
{
materialEditor.ShaderProperty(fluentLightIntensity, Styles.fluentLightIntensity);
}
materialEditor.ShaderProperty(roundCorners, Styles.roundCorners);
if (PropertyEnabled(roundCorners))
{
materialEditor.ShaderProperty(independentCorners, Styles.independentCorners, 2);
if (PropertyEnabled(independentCorners))
{
materialEditor.ShaderProperty(roundCornersRadius, Styles.roundCornersRadius, 2);
}
else
{
materialEditor.ShaderProperty(roundCornerRadius, Styles.roundCornerRadius, 2);
}
materialEditor.ShaderProperty(roundCornerMargin, Styles.roundCornerMargin, 2);
}
if (PropertyEnabled(roundCorners) || PropertyEnabled(borderLight))
{
materialEditor.ShaderProperty(edgeSmoothingValue, Styles.edgeSmoothingValue);
}
materialEditor.ShaderProperty(innerGlow, Styles.innerGlow);
if (PropertyEnabled(innerGlow))
{
materialEditor.ShaderProperty(innerGlowColor, Styles.innerGlowColor, 2);
materialEditor.ShaderProperty(innerGlowPower, Styles.innerGlowPower, 2);
}
materialEditor.ShaderProperty(iridescence, Styles.iridescence);
if (PropertyEnabled(iridescence))
{
EditorGUI.indentLevel += 2;
materialEditor.TexturePropertySingleLine(Styles.iridescentSpectrumMap, iridescentSpectrumMap);
EditorGUI.indentLevel -= 2;
materialEditor.ShaderProperty(iridescenceIntensity, Styles.iridescenceIntensity, 2);
materialEditor.ShaderProperty(iridescenceThreshold, Styles.iridescenceThreshold, 2);
materialEditor.ShaderProperty(iridescenceAngle, Styles.iridescenceAngle, 2);
}
materialEditor.ShaderProperty(environmentColoring, Styles.environmentColoring);
if (PropertyEnabled(environmentColoring))
{
materialEditor.ShaderProperty(environmentColorThreshold, Styles.environmentColorThreshold, 2);
materialEditor.ShaderProperty(environmentColorIntensity, Styles.environmentColorIntensity, 2);
materialEditor.ShaderProperty(environmentColorX, Styles.environmentColorX, 2);
materialEditor.ShaderProperty(environmentColorY, Styles.environmentColorY, 2);
materialEditor.ShaderProperty(environmentColorZ, Styles.environmentColorZ, 2);
}
}
protected void AdvancedOptions(MaterialEditor materialEditor, Material material)
{
EditorGUILayout.Space();
GUILayout.Label(Styles.advancedOptionsTitle, EditorStyles.boldLabel);
EditorGUI.BeginChangeCheck();
materialEditor.ShaderProperty(renderQueueOverride, BaseStyles.renderQueueOverride);
if (EditorGUI.EndChangeCheck())
{
MaterialChanged(material);
}
// Show the RenderQueueField but do not allow users to directly manipulate it. That is done via the renderQueueOverride.
GUI.enabled = false;
materialEditor.RenderQueueField();
// Enable instancing to disable batching. Static and dynamic batching will normalize the object scale, which breaks
// features which utilize object scale.
GUI.enabled = !ScaleRequired();
if (!GUI.enabled && !material.enableInstancing)
{
material.enableInstancing = true;
}
materialEditor.EnableInstancingField();
if (material.enableInstancing)
{
GUI.enabled = true;
materialEditor.ShaderProperty(instancedColor, Styles.instancedColor, 2);
}
else
{
// When instancing is disable, disable instanced color.
SetShaderFeatureActive(material, Styles.instancedColorFeatureName, Styles.instancedColorName, 0.0f);
}
materialEditor.ShaderProperty(stencil, Styles.stencil);
if (PropertyEnabled(stencil))
{
materialEditor.ShaderProperty(stencilReference, Styles.stencilReference, 2);
materialEditor.ShaderProperty(stencilComparison, Styles.stencilComparison, 2);
materialEditor.ShaderProperty(stencilOperation, Styles.stencilOperation, 2);
}
else
{
// When stencil is disable, revert to the default stencil operations. Note, when tested on D3D11 hardware the stencil state
// is still set even when the CompareFunction.Disabled is selected, but this does not seem to affect performance.
material.SetInt(Styles.stencilComparisonName, (int)CompareFunction.Disabled);
material.SetInt(Styles.stencilOperationName, (int)StencilOp.Keep);
}
if (ScaleRequired())
{
materialEditor.ShaderProperty(ignoreZScale, Styles.ignoreZScale);
}
}
protected bool ScaleRequired()
{
return PropertyEnabled(vertexExtrusion) ||
PropertyEnabled(roundCorners) ||
PropertyEnabled(borderLight) ||
(PropertyEnabled(enableTriplanarMapping) && PropertyEnabled(enableLocalSpaceTriplanarMapping));
}
protected static void SetupMaterialWithAlbedo(Material material, MaterialProperty albedoMap, MaterialProperty albedoAlphaMode, MaterialProperty albedoAssignedAtRuntime)
{
if (albedoMap.textureValue || PropertyEnabled(albedoAssignedAtRuntime))
{
material.DisableKeyword(Styles.disableAlbedoMapName);
}
else
{
material.EnableKeyword(Styles.disableAlbedoMapName);
}
switch ((AlbedoAlphaMode)albedoAlphaMode.floatValue)
{
case AlbedoAlphaMode.Transparency:
{
material.DisableKeyword(Styles.albedoMapAlphaMetallicName);
material.DisableKeyword(Styles.albedoMapAlphaSmoothnessName);
}
break;
case AlbedoAlphaMode.Metallic:
{
material.EnableKeyword(Styles.albedoMapAlphaMetallicName);
material.DisableKeyword(Styles.albedoMapAlphaSmoothnessName);
}
break;
case AlbedoAlphaMode.Smoothness:
{
material.DisableKeyword(Styles.albedoMapAlphaMetallicName);
material.EnableKeyword(Styles.albedoMapAlphaSmoothnessName);
}
break;
}
}
[MenuItem("Mixed Reality Toolkit/Utilities/Upgrade MRTK Standard Shader for Lightweight Render Pipeline")]
protected static void UpgradeShaderForLightweightRenderPipeline()
{
if (EditorUtility.DisplayDialog("Upgrade MRTK Standard Shader?",
"This will alter the MRTK Standard Shader for use with Unity's Lightweight Render Pipeline. You cannot undo this action.",
"Ok",
"Cancel"))
{
string path = AssetDatabase.GetAssetPath(StandardShaderUtility.MrtkStandardShader);
if (!string.IsNullOrEmpty(path))
{
try
{
string upgradedShader = File.ReadAllText(path);
upgradedShader = upgradedShader.Replace("Tags{ \"RenderType\" = \"Opaque\" \"LightMode\" = \"ForwardBase\" }",
"Tags{ \"RenderType\" = \"Opaque\" \"LightMode\" = \"LightweightForward\" }");
upgradedShader = upgradedShader.Replace("//#define _LIGHTWEIGHT_RENDER_PIPELINE",
"#define _LIGHTWEIGHT_RENDER_PIPELINE");
File.WriteAllText(path, upgradedShader);
AssetDatabase.Refresh();
Debug.LogFormat("Upgraded {0} for use with the Lightweight Render Pipeline.", path);
}
catch (Exception e)
{
Debug.LogException(e);
}
}
else
{
Debug.LogErrorFormat("Failed to get asset path to: {0}", StandardShaderUtility.MrtkStandardShaderName);
}
}
}
[MenuItem("Mixed Reality Toolkit/Utilities/Upgrade MRTK Standard Shader for Lightweight Render Pipeline", true)]
protected static bool UpgradeShaderForLightweightRenderPipelineValidate()
{
// If a scriptable render pipeline is not present, no need to upgrade the shader.
return GraphicsSettings.renderPipelineAsset != null;
}
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using TMPro.EditorUtilities;
using UnityEditor;
namespace Microsoft.MixedReality.Toolkit.Editor
{
/// <summary>
/// A custom TMP_SDFShaderGUI inspector for the "Mixed Reality Toolkit/TextMeshPro" shader.
/// Adds the ability to change the depth write mode, and a warning about depth write
/// when depth buffer sharing is enabled.
/// </summary>
public class MixedRealityTextMeshProShaderGUI : TMP_SDFShaderGUI
{
protected override void DoGUI()
{
BeginPanel("Mode", true);
DoModePanel();
EndPanel();
base.DoGUI();
}
protected void DoModePanel()
{
EditorGUI.indentLevel += 1;
var depthWrite = FindProperty("_ZWrite", m_Properties, false);
if (depthWrite != null)
{
m_Editor.ShaderProperty(depthWrite, depthWrite.displayName);
if (depthWrite.floatValue.Equals(0.0f))
{
if (MixedRealityToolkitShaderGUIUtilities.DisplayDepthWriteWarning(m_Editor))
{
depthWrite.floatValue = 1.0f;
}
}
}
EditorGUI.indentLevel -= 1;
EditorGUILayout.Space();
}
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Microsoft.MixedReality.Toolkit.Utilities.Facades
{
/// <summary>
/// Links service facade objects to active services.
/// </summary>
/// <remarks>
/// This feature is is being deprecated in 2.5 and will be removed in a future release.
/// The code that remains will actively seek to remove existing facades in scenes to ensure that
/// developers that update to 2.5 will get their scenes cleaned up appropriately.
/// </remarks>
[InitializeOnLoad]
public static class MixedRealityToolkitFacadeHandler
{
private static readonly List<Transform> childrenToDelete = new List<Transform>();
// While a scene save is occurring, facade creation is disabled
// and currently present facades get deleted.
private static bool sceneSaving = false;
static MixedRealityToolkitFacadeHandler()
{
#if UNITY_2019_1_OR_NEWER
SceneView.duringSceneGui += OnSceneGUI;
#else
SceneView.onSceneGUIDelegate += OnSceneGUI;
#endif
EditorSceneManager.sceneSaving += OnSceneSaving;
EditorSceneManager.sceneSaved += OnSceneSaved;
}
#region callbacks
private static void OnSceneGUI(SceneView sceneView)
{
UpdateServiceFacades();
}
private static void OnSceneSaving(Scene scene, string path)
{
sceneSaving = true;
CleanupCurrentFacades();
}
private static void OnSceneSaved(Scene scene)
{
sceneSaving = false;
}
#endregion
private static void CleanupCurrentFacades()
{
foreach (MixedRealityToolkit toolkitInstance in GameObject.FindObjectsOfType<MixedRealityToolkit>())
{
DestroyAllChildren(toolkitInstance);
}
}
private static void UpdateServiceFacades()
{
// If compiling or saving, don't modify service facades
if (sceneSaving || EditorApplication.isCompiling)
{
return;
}
// If MRTK has no active instance
// or there is no active profile for the active instance
// or we are instructed to not use service inspectors
// Return early and clean up any facade instances
if (!MixedRealityToolkit.IsInitialized ||
!MixedRealityToolkit.Instance.HasActiveProfile ||
#pragma warning disable 0618
!MixedRealityToolkit.Instance.ActiveProfile.UseServiceInspectors)
#pragma warning restore 0618
{
DestroyFacades();
return;
}
}
private static void DestroyFacades()
{
for (int i = ServiceFacade.ActiveFacadeObjects.Count - 1; i >= 0; i--)
{
var facade = ServiceFacade.ActiveFacadeObjects[i];
if (facade != null)
{
GameObjectExtensions.DestroyGameObject(facade.gameObject);
}
}
ServiceFacade.ActiveFacadeObjects.Clear();
}
private static void DestroyAllChildren(MixedRealityToolkit instance)
{
Transform instanceTransform = instance.transform;
childrenToDelete.Clear();
foreach (Transform child in instanceTransform.transform)
{
childrenToDelete.Add(child);
}
foreach (ServiceFacade facade in ServiceFacade.ActiveFacadeObjects)
{
if (!childrenToDelete.Contains(facade.transform))
{
childrenToDelete.Add(facade.transform);
}
}
foreach (Transform child in childrenToDelete)
{
GameObjectExtensions.DestroyGameObject(child.gameObject);
}
childrenToDelete.Clear();
}
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Utilities.Editor;
using Microsoft.MixedReality.Toolkit.Utilities.Editor.Search;
using UnityEditor;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.Editor
{
[CustomEditor(typeof(MixedRealityToolkit))]
public class MixedRealityToolkitInspector : UnityEditor.Editor
{
private SerializedProperty activeProfile;
private void OnEnable()
{
activeProfile = serializedObject.FindProperty("activeProfile");
}
public override void OnInspectorGUI()
{
MixedRealityToolkit instance = (MixedRealityToolkit)target;
if (MixedRealityToolkit.Instance == null && instance.isActiveAndEnabled)
{ // See if an active instance exists at all. If it doesn't register this instance preemptively.
MixedRealityToolkit.SetActiveInstance(instance);
}
if (!instance.IsActiveInstance)
{
EditorGUILayout.HelpBox("This instance of the toolkit is inactive. There can only be one active instance loaded at any time.", MessageType.Warning);
using (new EditorGUILayout.HorizontalScope())
{
if (GUILayout.Button("Select Active Instance"))
{
UnityEditor.Selection.activeGameObject = MixedRealityToolkit.Instance.gameObject;
}
if (GUILayout.Button("Make this the Active Instance"))
{
MixedRealityToolkit.SetActiveInstance(instance);
}
}
return;
}
serializedObject.Update();
// If not profile is assigned, then warn user
if (activeProfile.objectReferenceValue == null)
{
EditorGUILayout.HelpBox("MixedRealityToolkit cannot initialize unless an Active Profile is assigned!", MessageType.Error);
}
bool changed = MixedRealityInspectorUtility.DrawProfileDropDownList(activeProfile, null, activeProfile.objectReferenceValue, typeof(MixedRealityToolkitConfigurationProfile), false);
serializedObject.ApplyModifiedProperties();
if (changed)
{
MixedRealityToolkit.Instance.ResetConfiguration((MixedRealityToolkitConfigurationProfile)activeProfile.objectReferenceValue);
}
if (activeProfile.objectReferenceValue != null)
{
// For configure, show the default inspector GUI
UnityEditor.Editor activeProfileEditor = CreateEditor(activeProfile.objectReferenceValue);
activeProfileEditor.OnInspectorGUI();
}
}
[MenuItem("Mixed Reality Toolkit/Add to Scene and Configure...")]
public static void CreateMixedRealityToolkitGameObject()
{
MixedRealityInspectorUtility.AddMixedRealityToolkitToScene();
Selection.activeObject = MixedRealityToolkit.Instance;
EditorGUIUtility.PingObject(MixedRealityToolkit.Instance);
}
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Utilities;
using UnityEditor;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.Editor
{
/// <summary>
/// A collection of shared functionality for MRTK shader GUIs.
/// </summary>
public static class MixedRealityToolkitShaderGUIUtilities
{
/// <summary>
/// GUI content styles which are common among shader GUIs.
/// </summary>
public static class Styles
{
public static readonly GUIContent DepthWriteWarning = new GUIContent("<color=yellow>Warning:</color> Depth buffer sharing is enabled for this project, but this material does not write depth. Enabling depth will improve reprojection, but may cause rendering artifacts in translucent materials.");
public static readonly GUIContent DepthWriteFixNowButton = new GUIContent("Fix Now", "Enables Depth Write For This Material");
}
/// <summary>
/// Displays a depth write warning and fix button if depth buffer sharing is enabled.
/// </summary>
/// <param name="materialEditor">The material editor to display the warning in.</param>
/// <param name="dialogTitle">The title of the dialog window to display when the user selects the fix button.</param>
/// <param name="dialogMessage">The message in the dialog window when the user selects the fix button.</param>
/// <returns>True if the user opted to fix the warning, false otherwise.</returns>
public static bool DisplayDepthWriteWarning(MaterialEditor materialEditor, string dialogTitle = "Depth Write", string dialogMessage = "Change this material to write to the depth buffer?")
{
bool dialogConfirmed = false;
if (MixedRealityOptimizeUtils.IsDepthBufferSharingEnabled())
{
var defaultValue = EditorStyles.helpBox.richText;
EditorStyles.helpBox.richText = true;
if (materialEditor.HelpBoxWithButton(Styles.DepthWriteWarning, Styles.DepthWriteFixNowButton))
{
if (EditorUtility.DisplayDialog(dialogTitle, dialogMessage, "Yes", "No"))
{
dialogConfirmed = true;
}
}
EditorStyles.helpBox.richText = defaultValue;
}
return dialogConfirmed;
}
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Microsoft.MixedReality.Toolkit.Editor
{
/// <summary>
/// A custom shader inspector for the "Mixed Reality Toolkit/Wireframe" shader.
/// </summary>
public class MixedRealityWireframeShaderGUI : MixedRealityShaderGUI
{
protected static class Styles
{
public static string mainPropertiesTitle = "Main Properties";
public static string advancedOptionsTitle = "Advanced Options";
public static GUIContent baseColor = new GUIContent("Base Color", "Color of faces");
public static GUIContent wireColor = new GUIContent("Wire Color", "Color of wires");
public static GUIContent wireThickness = new GUIContent("Wire Thickness", "Thickness of wires");
}
protected MaterialProperty baseColor;
protected MaterialProperty wireColor;
protected MaterialProperty wireThickness;
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
{
Material material = (Material)materialEditor.target;
base.OnGUI(materialEditor, props);
GUILayout.Label(Styles.mainPropertiesTitle, EditorStyles.boldLabel);
materialEditor.ShaderProperty(baseColor, Styles.baseColor);
materialEditor.ShaderProperty(wireColor, Styles.wireColor);
materialEditor.ShaderProperty(wireThickness, Styles.wireThickness);
AdvancedOptions(materialEditor, material);
}
protected override void FindProperties(MaterialProperty[] props)
{
base.FindProperties(props);
baseColor = FindProperty("_BaseColor", props);
wireColor = FindProperty("_WireColor", props);
wireThickness = FindProperty("_WireThickness", props);
}
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
{
float? cullMode = GetFloatProperty(material, "_Cull");
base.AssignNewShaderToMaterial(material, oldShader, newShader);
SetShaderFeatureActive(material, null, BaseStyles.cullModeName, cullMode);
// Setup the rendering mode based on the old shader.
if (oldShader == null || !oldShader.name.Contains(LegacyShadersPath))
{
SetupMaterialWithRenderingMode(material, (RenderingMode)material.GetFloat(BaseStyles.renderingModeName), CustomRenderingMode.Opaque, -1);
}
else
{
RenderingMode mode = RenderingMode.Opaque;
if (oldShader.name.Contains(TransparentCutoutShadersPath))
{
mode = RenderingMode.Cutout;
}
else if (oldShader.name.Contains(TransparentShadersPath))
{
mode = RenderingMode.Fade;
}
material.SetFloat(BaseStyles.renderingModeName, (float)mode);
MaterialChanged(material);
}
}
protected void AdvancedOptions(MaterialEditor materialEditor, Material material)
{
GUILayout.Label(Styles.advancedOptionsTitle, EditorStyles.boldLabel);
EditorGUI.BeginChangeCheck();
materialEditor.ShaderProperty(renderQueueOverride, BaseStyles.renderQueueOverride);
if (EditorGUI.EndChangeCheck())
{
MaterialChanged(material);
}
// Show the RenderQueueField but do not allow users to directly manipulate it. That is done via the renderQueueOverride.
GUI.enabled = false;
materialEditor.RenderQueueField();
GUI.enabled = true;
materialEditor.EnableInstancingField();
}
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Utilities.Editor;
using System;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.Editor
{
/// <summary>
/// Base class for all <see cref="Microsoft.MixedReality.Toolkit.BaseMixedRealityProfile"/> Inspectors to inherit from.
/// </summary>
public abstract class BaseMixedRealityProfileInspector : UnityEditor.Editor
{
private static readonly StringBuilder dropdownKeyBuilder = new StringBuilder();
protected virtual void OnEnable()
{
if (target == null)
{
// Either when we are recompiling, or the inspector window is hidden behind another one, the target can get destroyed (null) and thereby will raise an ArgumentException when accessing serializedObject. For now, just return.
return;
}
}
/// <summary>
/// Renders a non-editable object field and an editable dropdown of a profile.
/// </summary>
public static void RenderReadOnlyProfile(SerializedProperty property)
{
using (new EditorGUILayout.HorizontalScope())
{
EditorGUI.BeginDisabledGroup(true);
EditorGUILayout.ObjectField(property.objectReferenceValue != null ? "" : property.displayName, property.objectReferenceValue, typeof(BaseMixedRealityProfile), false, GUILayout.ExpandWidth(true));
EditorGUI.EndDisabledGroup();
}
if (property.objectReferenceValue != null)
{
bool showReadOnlyProfile = SessionState.GetBool(property.name + ".ReadOnlyProfile", false);
using (new EditorGUI.IndentLevelScope())
{
RenderFoldout(ref showReadOnlyProfile, property.displayName, () =>
{
using (new EditorGUI.IndentLevelScope())
{
UnityEditor.Editor subProfileEditor = CreateEditor(property.objectReferenceValue);
// If this is a default MRTK configuration profile, ask it to render as a sub-profile
if (typeof(BaseMixedRealityToolkitConfigurationProfileInspector).IsAssignableFrom(subProfileEditor.GetType()))
{
BaseMixedRealityToolkitConfigurationProfileInspector configProfile = (BaseMixedRealityToolkitConfigurationProfileInspector)subProfileEditor;
configProfile.RenderAsSubProfile = true;
}
subProfileEditor.OnInspectorGUI();
}
});
}
SessionState.SetBool(property.name + ".ReadOnlyProfile", showReadOnlyProfile);
}
}
/// <summary>
/// Renders a <see cref="Microsoft.MixedReality.Toolkit.BaseMixedRealityProfile"/>.
/// </summary>
/// <param name="property">the <see cref="Microsoft.MixedReality.Toolkit.BaseMixedRealityProfile"/> property.</param>
/// <param name="profileType">Profile type to filter available values to set on the provided property. If null, defaults to type <see cref="Microsoft.MixedReality.Toolkit.BaseMixedRealityProfile"/></param>
/// <param name="showAddButton">If true, draw the clone button, if false, don't</param>
/// <param name="renderProfileInBox">if true, render box around profile content, if false, don't</param>
/// <param name="serviceType">Optional service type to limit available profile types.</param>
/// <returns>True, if the profile changed.</returns>
protected static bool RenderProfile(SerializedProperty property, Type profileType, bool showAddButton = true, bool renderProfileInBox = false, Type serviceType = null)
{
return RenderProfileInternal(property, profileType, showAddButton, renderProfileInBox, serviceType);
}
/// <summary>
/// Renders a <see cref="Microsoft.MixedReality.Toolkit.BaseMixedRealityProfile"/>.
/// </summary>
/// <param name="property">the <see cref="Microsoft.MixedReality.Toolkit.BaseMixedRealityProfile"/> property.</param>
/// <param name="showAddButton">If true, draw the clone button, if false, don't</param>
/// <param name="renderProfileInBox">if true, render box around profile content, if false, don't</param>
/// <param name="serviceType">Optional service type to limit available profile types.</param>
/// <returns>True, if the profile changed.</returns>
private static bool RenderProfileInternal(SerializedProperty property, Type profileType,
bool showAddButton, bool renderProfileInBox, Type serviceType = null)
{
var profile = property.serializedObject.targetObject as BaseMixedRealityProfile;
bool changed = false;
var oldObject = property.objectReferenceValue;
if (profileType != null && !profileType.IsSubclassOf(typeof(BaseMixedRealityProfile)) && profileType != typeof(BaseMixedRealityProfile))
{
// If they've drag-and-dropped a non-profile scriptable object, set it to null.
profileType = null;
}
// If we're constraining this to a service type, check whether the profile is valid
// If it isn't, issue a warning.
if (serviceType != null && oldObject != null)
{
if (!MixedRealityProfileUtility.IsProfileForService(oldObject.GetType(), serviceType))
{
EditorGUILayout.HelpBox("This profile is not supported for " + serviceType.Name + ". Using an unsupported service may result in unexpected behavior.", MessageType.Warning);
}
}
if (profileType == null)
{
// Find the profile type so we can limit the available object field options
if (serviceType != null)
{
// If GetProfileTypesForService has a count greater than one, then it won't be possible to use
// EditorGUILayout.ObjectField to restrict the set of profiles to a single type - in this
// case all profiles of BaseMixedRealityProfile will be visible in the picker.
//
// However in the case where there is just a single profile type for the service, we can improve
// upon the user experience by limiting the set of things that show in the picker by restricting
// the set of profiles listed to only that type.
var availableTypes = MixedRealityProfileUtility.GetProfileTypesForService(serviceType);
if (availableTypes.Count == 1)
{
profileType = availableTypes.First();
}
}
// If the profile type is still null, just set it to base profile type
if (profileType == null)
{
profileType = typeof(BaseMixedRealityProfile);
}
}
// Draw the profile dropdown
changed |= MixedRealityInspectorUtility.DrawProfileDropDownList(property, profile, oldObject, profileType, showAddButton);
Debug.Assert(profile != null, "No profile was set in OnEnable. Did you forget to call base.OnEnable in a derived profile class?");
// Draw the sub-profile editor
MixedRealityInspectorUtility.DrawSubProfileEditor(property.objectReferenceValue, renderProfileInBox);
return changed;
}
/// <summary>
/// Render Bold/HelpBox style Foldout
/// </summary>
/// <param name="currentState">reference bool for current visibility state of foldout</param>
/// <param name="title">Title in foldout</param>
/// <param name="renderContent">code to execute to render inside of foldout</param>
/// <param name="preferenceKey">optional argument, current show/hide state will be tracked associated with provided preference key</param>
protected static void RenderFoldout(ref bool currentState, string title, Action renderContent, string preferenceKey = null)
{
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
bool isValidPreferenceKey = !string.IsNullOrEmpty(preferenceKey);
bool state = currentState;
if (isValidPreferenceKey)
{
state = SessionState.GetBool(preferenceKey, currentState);
}
currentState = EditorGUILayout.Foldout(state, title, true, MixedRealityStylesUtility.BoldFoldoutStyle);
if (isValidPreferenceKey && currentState != state)
{
SessionState.SetBool(preferenceKey, currentState);
}
if (currentState)
{
renderContent();
}
EditorGUILayout.EndVertical();
}
private static string GetSubProfileDropdownKey(SerializedProperty property)
{
if (property.objectReferenceValue == null)
{
throw new Exception("Can't get sub profile dropdown key for a property that is null.");
}
dropdownKeyBuilder.Clear();
dropdownKeyBuilder.Append("MRTK_SubProfile_ShowDropdown_");
dropdownKeyBuilder.Append(property.name);
dropdownKeyBuilder.Append("_");
dropdownKeyBuilder.Append(property.objectReferenceValue.GetType().Name);
return dropdownKeyBuilder.ToString();
}
/// <summary>
/// Checks if the profile is locked
/// </summary>
protected static bool IsProfileLock(BaseMixedRealityProfile profile)
{
return MixedRealityProjectPreferences.LockProfiles && !profile.IsCustomProfile;
}
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Utilities;
using Microsoft.MixedReality.Toolkit.Utilities.Editor;
using Microsoft.MixedReality.Toolkit.Utilities.Editor.Search;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.Editor
{
/// <summary>
/// Base class for all Mixed Reality Toolkit specific <see cref="Microsoft.MixedReality.Toolkit.BaseMixedRealityProfile"/> inspectors to inherit from.
/// </summary>
public abstract class BaseMixedRealityToolkitConfigurationProfileInspector : BaseMixedRealityProfileInspector
{
public bool RenderAsSubProfile { get; set; }
private static GUIContent WarningIconContent = null;
/// <summary>
/// Helper function to determine if the current profile is assigned to the active instance of MRTK.
/// In some cases profile data refers to other profile data in the MRTK config profile.
/// In these cases, we don't want to render when the active instance isn't using this profile,
/// because it may produce an inaccurate combination of settings.
/// </summary>
protected abstract bool IsProfileInActiveInstance();
/// <summary>
/// Internal enum used for back navigation along profile hierarchy.
/// Indicates what type of parent profile the current profile will return to for going back
/// </summary>
protected enum BackProfileType
{
Configuration,
Input,
SpatialAwareness,
RegisteredServices
};
// NOTE: Must match number of elements in BackProfileType
protected readonly string[] BackProfileDescriptions = {
"Back to Configuration Profile",
"Back to Input Profile",
"Back to Spatial Awareness Profile",
"Back to Registered Service Providers Profile"
};
protected virtual void Awake()
{
if (WarningIconContent == null)
{
WarningIconContent = new GUIContent(EditorGUIUtility.IconContent("console.warnicon").image,
"This profile is part of the default set from the Mixed Reality Toolkit SDK. You can make a copy of this profile, and customize it if needed.");
}
}
/// <summary>
/// Render the Mixed Reality Toolkit Logo and search field.
/// </summary>
/// <returns>True if the rest of the inspector should be drawn.</returns>
protected bool RenderMRTKLogoAndSearch()
{
// If we're being rendered as a sub profile, don't show the logo
if (RenderAsSubProfile)
{
return true;
}
if (MixedRealitySearchInspectorUtility.DrawSearchInterface(target))
{
return false;
}
MixedRealityInspectorUtility.RenderMixedRealityToolkitLogo();
return true;
}
/// <summary>
/// Draws a documentation link for the service.
/// </summary>
protected void RenderDocumentation(Object profileObject)
{
if (profileObject == null)
{ // Can't proceed if profile is null.
return;
}
HelpURLAttribute helpURL = profileObject.GetType().GetCustomAttribute<HelpURLAttribute>();
if (helpURL != null)
{
InspectorUIUtility.RenderDocumentationButton(helpURL.URL);
}
}
protected bool DrawBacktrackProfileButton(BackProfileType returnProfileTarget = BackProfileType.Configuration)
{
// We cannot select the correct profile if there is no instance
if (!MixedRealityToolkit.IsInitialized)
{
return false;
}
string backText = BackProfileDescriptions[(int)returnProfileTarget];
BaseMixedRealityProfile backProfile = null;
switch (returnProfileTarget)
{
case BackProfileType.Configuration:
backProfile = MixedRealityToolkit.Instance.ActiveProfile;
break;
case BackProfileType.Input:
backProfile = MixedRealityToolkit.Instance.ActiveProfile.InputSystemProfile;
break;
case BackProfileType.SpatialAwareness:
backProfile = MixedRealityToolkit.Instance.ActiveProfile.SpatialAwarenessSystemProfile;
break;
case BackProfileType.RegisteredServices:
backProfile = MixedRealityToolkit.Instance.ActiveProfile.RegisteredServiceProvidersProfile;
break;
}
return DrawBacktrackProfileButton(backText, backProfile);
}
/// <summary>
/// Renders a button that will take user back to a specified profile object
/// </summary>
/// <returns>True if button was clicked</returns>
protected bool DrawBacktrackProfileButton(string message, UnityEngine.Object activeObject)
{
// If we're being rendered as a sub profile, don't show the button
if (RenderAsSubProfile)
{
return false;
}
if (GUILayout.Button(message))
{
Selection.activeObject = activeObject;
return true;
}
return false;
}
/// <summary>
/// Inspect the attributes of the provided system type to determine if a configuration profile is required.
/// </summary>
/// <param name="serviceType">The system type representing the service.</param>
/// <returns>
/// True if the service is decorated with an attribute indicating a profile is required, false otherwise.
/// </returns>
protected bool IsProfileRequired(SystemType serviceType)
{
// Services marked with the MixedRealityExtensionServiceAttribute (or a derivative)
// support specifying whether or not a profile is required.
MixedRealityExtensionServiceAttribute attribute = (serviceType?.Type != null) ? MixedRealityExtensionServiceAttribute.Find(serviceType.Type) : null;
return ((attribute != null) && attribute.RequiresProfile);
}
/// <summary>
/// Helper function to render header correctly for all profiles
/// </summary>
/// <param name="title">Title of profile</param>
/// <param name="description">profile tooltip describing purpose</param>
/// <param name="selectionObject">The profile object. Used to re-select the object after MRTK instance is created.</param>
/// <param name="isProfileInitialized">profile properties are full initialized for rendering</param>
/// <param name="backText">Text for back button if not rendering as sub-profile</param>
/// <param name="backProfile">Target profile to return to if not rendering as sub-profile</param>
/// <returns>True if the rest of the profile should be rendered.</returns>
protected bool RenderProfileHeader(string title, string description, Object selectionObject, bool isProfileInitialized = true, BackProfileType returnProfileTarget = BackProfileType.Configuration)
{
if (!RenderMRTKLogoAndSearch())
{
CheckEditorPlayMode();
return false;
}
var profile = target as BaseMixedRealityProfile;
if (!RenderAsSubProfile)
{
CheckEditorPlayMode();
if (!profile.IsCustomProfile)
{
EditorGUILayout.HelpBox("Default MRTK profiles cannot be edited. Create a clone of this profile to modify settings.", MessageType.Warning);
if (GUILayout.Button(new GUIContent("Clone")))
{
MixedRealityProfileCloneWindow.OpenWindow(null, (BaseMixedRealityProfile)target, null);
}
}
if (IsProfileInActiveInstance())
{
DrawBacktrackProfileButton(returnProfileTarget);
}
if (!isProfileInitialized)
{
if (!MixedRealityToolkit.IsInitialized)
{
EditorGUILayout.HelpBox("There is not a MRTK instance in your scene. Some properties may not be editable", MessageType.Error);
if (InspectorUIUtility.RenderIndentedButton(new GUIContent("Add Mixed Reality Toolkit instance to scene"), EditorStyles.miniButton))
{
MixedRealityInspectorUtility.AddMixedRealityToolkitToScene(MixedRealityInspectorUtility.GetDefaultConfigProfile());
// After the toolkit has been created, set the selection back to this item so the user doesn't get lost
Selection.activeObject = selectionObject;
}
}
else if (!MixedRealityToolkit.Instance.HasActiveProfile)
{
EditorGUILayout.HelpBox("There is no active profile assigned in the current MRTK instance. Some properties may not be editable.", MessageType.Error);
}
}
}
else
{
if (!isProfileInitialized && profile.IsCustomProfile)
{
EditorGUILayout.HelpBox("Some properties may not be editable in this profile. Please refer to the error messages below to resolve editing.", MessageType.Warning);
}
}
using (new EditorGUILayout.HorizontalScope())
{
EditorGUILayout.LabelField(new GUIContent(title, description), EditorStyles.boldLabel, GUILayout.ExpandWidth(true));
RenderDocumentation(selectionObject);
}
EditorGUILayout.LabelField(string.Empty, GUI.skin.horizontalSlider);
return true;
}
/// <summary>
/// If application is playing, then show warning to the user and disable inspector GUI
/// </summary>
/// <returns>true if application is playing, false otherwise</returns>
protected bool CheckEditorPlayMode()
{
if (Application.isPlaying)
{
EditorGUILayout.HelpBox("Mixed Reality Toolkit settings cannot be edited while in play mode.", MessageType.Warning);
GUI.enabled = false;
return true;
}
return false;
}
/// <summary>
/// Check if various input settings are set correctly to read the input actions for the active MRTK instance. If any failures, show appropriate error message
/// </summary>
protected void CheckMixedRealityInputActions()
{
if (MixedRealityToolkit.IsInitialized && MixedRealityToolkit.Instance.HasActiveProfile)
{
if (!MixedRealityToolkit.Instance.ActiveProfile.IsInputSystemEnabled)
{
EditorGUILayout.HelpBox("No input system is enabled, or you need to specify the type in the main configuration profile.", MessageType.Warning);
}
if (MixedRealityToolkit.Instance.ActiveProfile.InputSystemProfile == null)
{
EditorGUILayout.HelpBox("No input system profile found, please specify an input system profile in the main configuration.", MessageType.Error);
}
else if (MixedRealityToolkit.Instance.ActiveProfile.InputSystemProfile.InputActionsProfile == null)
{
EditorGUILayout.HelpBox("No input actions profile found, please specify an input action profile in the main configuration.", MessageType.Error);
}
else if (!IsProfileInActiveInstance())
{
EditorGUILayout.HelpBox("This profile is not assigned to the active MRTK instance in your scene. Some properties may not be editable", MessageType.Error);
}
}
}
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Utilities.Editor;
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.Editor
{
/// <summary>
/// Abstract class providing base functionality for data provider management in inspector. Useful for core systems that follow dataprovider access model.
/// Designed to target ScriptableObject profile classes that configure services who support data providers.
/// These profile ScriptableObject classes should contain an array of IMixedRealityServiceConfigurations that configure a list of data providers for this service configuration
/// </summary>
public abstract class BaseDataProviderServiceInspector : BaseMixedRealityToolkitConfigurationProfileInspector
{
/// <summary>
/// Container class used to store references to serialized properties on a <see cref="IMixedRealityServiceConfiguration"/> target
/// </summary>
protected class ServiceConfigurationProperties
{
internal SerializedProperty componentName;
internal SerializedProperty componentType;
internal SerializedProperty providerProfile;
internal SerializedProperty runtimePlatform;
}
/// <summary>
/// Returns SerializedProperty object that wraps references to array of <see cref="IMixedRealityServiceConfiguration"/> stored on the inspected target object
/// </summary>
protected abstract SerializedProperty GetDataProviderConfigurationList();
/// <summary>
/// Builds <see cref="ServiceConfigurationProperties"/> container object with SerializedProperty references to associated properties on the supplied <see cref="IMixedRealityServiceConfiguration"/> reference
/// </summary>
/// <param name="providerEntry">SerializedProperty reference pointing to <see cref="IMixedRealityServiceConfiguration"/> instance</param>
protected abstract ServiceConfigurationProperties GetDataProviderConfigurationProperties(SerializedProperty providerEntry);
/// <summary>
/// Returns direct <see cref="IMixedRealityServiceConfiguration"/> instance at provided index in target object's array of <see cref="IMixedRealityServiceConfiguration"/> configurations
/// </summary>
protected abstract IMixedRealityServiceConfiguration GetDataProviderConfiguration(int index);
private SerializedProperty providerConfigurations;
private List<bool> providerFoldouts = new List<bool>();
private static readonly GUIContent ComponentTypeLabel = new GUIContent("Type");
private static readonly GUIContent SupportedPlatformsLabel = new GUIContent("Supported Platform(s)");
/// <inheritdoc/>
protected override void OnEnable()
{
base.OnEnable();
providerConfigurations = GetDataProviderConfigurationList();
if (providerFoldouts == null || providerFoldouts.Count != providerConfigurations.arraySize)
{
providerFoldouts = new List<bool>(new bool[providerConfigurations.arraySize]);
}
}
/// <summary>
/// Adds a new data provider profile entry (i.e <see cref="IMixedRealityServiceConfiguration"/>) to array list of target object
/// Utilizes GetDataProviderConfigurationList() to get SerializedProperty object that represents array to insert against
/// </summary>
protected virtual void AddDataProvider()
{
providerConfigurations.InsertArrayElementAtIndex(providerConfigurations.arraySize);
SerializedProperty provider = providerConfigurations.GetArrayElementAtIndex(providerConfigurations.arraySize - 1);
var providerProperties = GetDataProviderConfigurationProperties(provider);
providerProperties.componentName.stringValue = $"New data provider {providerConfigurations.arraySize - 1}";
providerProperties.runtimePlatform.intValue = -1;
providerProperties.providerProfile.objectReferenceValue = null;
serializedObject.ApplyModifiedProperties();
var providerType = GetDataProviderConfiguration(providerConfigurations.arraySize - 1).ComponentType;
providerType.Type = null;
providerFoldouts.Add(false);
}
/// <summary>
/// Removed given index item from <see cref="IMixedRealityServiceConfiguration"/> array list.
/// Utilizes GetDataProviderConfigurationList() to get SerializedProperty object that represents array to delete against.
/// </summary>
protected virtual void RemoveDataProvider(int index)
{
providerConfigurations.DeleteArrayElementAtIndex(index);
serializedObject.ApplyModifiedProperties();
providerFoldouts.RemoveAt(index);
}
/// <summary>
/// Applies the given concrete dataprovider type properties to the provided <see cref="IMixedRealityServiceConfiguration"/> instance (as represented by <see cref="ServiceConfigurationProperties"/>).
/// Requires <see cref="MixedRealityDataProviderAttribute"/> on concrete type class to pull initial values
/// that will be applied to the <see cref="ServiceConfigurationProperties"/> container SerializedProperties
/// </summary>
protected virtual void ApplyProviderConfiguration(Type dataProviderType, ServiceConfigurationProperties providerProperties)
{
if (dataProviderType != null)
{
MixedRealityDataProviderAttribute providerAttribute = MixedRealityDataProviderAttribute.Find(dataProviderType) as MixedRealityDataProviderAttribute;
if (providerAttribute != null)
{
providerProperties.componentName.stringValue = !string.IsNullOrWhiteSpace(providerAttribute.Name) ? providerAttribute.Name : dataProviderType.Name;
providerProperties.providerProfile.objectReferenceValue = providerAttribute.DefaultProfile;
providerProperties.runtimePlatform.intValue = (int)providerAttribute.RuntimePlatforms;
}
else
{
providerProperties.componentName.stringValue = dataProviderType.Name;
}
serializedObject.ApplyModifiedProperties();
}
}
/// <summary>
/// Render list of data provider configuration profiles in inspector. Use provided add and remove content labels for the insert/remove buttons
/// Returns true if any property has changed in this render pass, false otherwise
/// </summary>
protected bool RenderDataProviderList(GUIContent addContentLabel, GUIContent removeContentLabel, string errorMsg, Type dataProviderProfileType = null)
{
bool changed = false;
using (new EditorGUILayout.VerticalScope())
{
if (providerConfigurations == null || providerConfigurations.arraySize == 0)
{
EditorGUILayout.HelpBox(errorMsg, MessageType.Info);
}
if (InspectorUIUtility.RenderIndentedButton(addContentLabel, EditorStyles.miniButton))
{
AddDataProvider();
return true;
}
for (int i = 0; i < providerConfigurations.arraySize; i++)
{
changed |= RenderDataProviderEntry(i, removeContentLabel, dataProviderProfileType);
}
return changed;
}
}
/// <summary>
/// Renders properties of <see cref="IMixedRealityServiceConfiguration"/> instance at provided index in inspector.
/// Also renders inspector view of data provider's profile object and its contents if applicable and foldout is expanded.
/// </summary>
protected bool RenderDataProviderEntry(int index, GUIContent removeContent, System.Type dataProviderProfileType = null)
{
bool changed = false;
SerializedProperty provider = providerConfigurations.GetArrayElementAtIndex(index);
ServiceConfigurationProperties providerProperties = GetDataProviderConfigurationProperties(provider);
var serviceType = GetDataProviderConfiguration(index).ComponentType;
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
{
using (new EditorGUILayout.HorizontalScope())
{
providerFoldouts[index] = EditorGUILayout.Foldout(providerFoldouts[index], providerProperties.componentName.stringValue, true);
if (GUILayout.Button(removeContent, EditorStyles.miniButtonRight, GUILayout.Width(24f)))
{
RemoveDataProvider(index);
return true;
}
}
if (providerFoldouts[index])
{
using (var c = new EditorGUI.ChangeCheckScope())
{
EditorGUILayout.PropertyField(providerProperties.componentType, ComponentTypeLabel);
if (c.changed)
{
serializedObject.ApplyModifiedProperties();
ApplyProviderConfiguration(serviceType.Type, providerProperties);
return true;
}
EditorGUILayout.PropertyField(providerProperties.runtimePlatform, SupportedPlatformsLabel);
changed = c.changed;
}
changed |= RenderProfile(providerProperties.providerProfile, dataProviderProfileType, true, false, serviceType);
serializedObject.ApplyModifiedProperties();
}
if (IsProfileRequired(serviceType) &&
(providerProperties.providerProfile.objectReferenceValue == null))
{
EditorGUILayout.HelpBox($"{providerProperties.componentName.stringValue} requires a profile.", MessageType.Warning);
}
}
return changed;
}
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Editor;
using Microsoft.MixedReality.Toolkit.Utilities;
using Microsoft.MixedReality.Toolkit.Utilities.Editor;
using UnityEditor;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.Boundary.Editor
{
[CustomEditor(typeof(MixedRealityBoundaryVisualizationProfile))]
public class MixedRealityBoundaryVisualizationProfileInspector : BaseMixedRealityToolkitConfigurationProfileInspector
{
private SerializedProperty boundaryHeight;
private SerializedProperty showFloor;
private SerializedProperty floorMaterial;
private SerializedProperty floorScale;
private SerializedProperty floorPhysicsLayer;
private SerializedProperty showPlayArea;
private SerializedProperty playAreaMaterial;
private SerializedProperty playAreaPhysicsLayer;
private SerializedProperty showTrackedArea;
private SerializedProperty trackedAreaMaterial;
private SerializedProperty trackedAreaPhysicsLayer;
private SerializedProperty showBoundaryWalls;
private SerializedProperty boundaryWallMaterial;
private SerializedProperty boundaryWallsPhysicsLayer;
private SerializedProperty showBoundaryCeiling;
private SerializedProperty boundaryCeilingMaterial;
private SerializedProperty ceilingPhysicsLayer;
private const string ProfileTitle = "Boundary Visualization Settings";
private const string ProfileDescription = "Boundary visualizations can help users stay oriented and comfortable in the experience.";
private readonly GUIContent showContent = new GUIContent("Show");
private readonly GUIContent scaleContent = new GUIContent("Scale");
private readonly GUIContent materialContent = new GUIContent("Material");
protected override void OnEnable()
{
base.OnEnable();
boundaryHeight = serializedObject.FindProperty("boundaryHeight");
showFloor = serializedObject.FindProperty("showFloor");
floorMaterial = serializedObject.FindProperty("floorMaterial");
floorScale = serializedObject.FindProperty("floorScale");
floorPhysicsLayer = serializedObject.FindProperty("floorPhysicsLayer");
showPlayArea = serializedObject.FindProperty("showPlayArea");
playAreaMaterial = serializedObject.FindProperty("playAreaMaterial");
playAreaPhysicsLayer = serializedObject.FindProperty("playAreaPhysicsLayer");
showTrackedArea = serializedObject.FindProperty("showTrackedArea");
trackedAreaMaterial = serializedObject.FindProperty("trackedAreaMaterial");
trackedAreaPhysicsLayer = serializedObject.FindProperty("trackedAreaPhysicsLayer");
showBoundaryWalls = serializedObject.FindProperty("showBoundaryWalls");
boundaryWallMaterial = serializedObject.FindProperty("boundaryWallMaterial");
boundaryWallsPhysicsLayer = serializedObject.FindProperty("boundaryWallsPhysicsLayer");
showBoundaryCeiling = serializedObject.FindProperty("showBoundaryCeiling");
boundaryCeilingMaterial = serializedObject.FindProperty("boundaryCeilingMaterial");
ceilingPhysicsLayer = serializedObject.FindProperty("ceilingPhysicsLayer");
}
public override void OnInspectorGUI()
{
if (!RenderProfileHeader(ProfileTitle, ProfileDescription, target))
{
return;
}
using (new EditorGUI.DisabledGroupScope(IsProfileLock((BaseMixedRealityProfile)target)))
{
serializedObject.Update();
EditorGUILayout.Space();
EditorGUILayout.LabelField("General Settings", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(boundaryHeight);
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Floor Settings", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(showFloor, showContent);
EditorGUILayout.PropertyField(floorMaterial, materialContent);
var prevWideMode = EditorGUIUtility.wideMode;
EditorGUIUtility.wideMode = true;
EditorGUILayout.PropertyField(floorScale, scaleContent, GUILayout.ExpandWidth(true));
EditorGUIUtility.wideMode = prevWideMode;
EditorGUILayout.PropertyField(floorPhysicsLayer);
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Play Area Settings", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(showPlayArea, showContent);
EditorGUILayout.PropertyField(playAreaMaterial, materialContent);
EditorGUILayout.PropertyField(playAreaPhysicsLayer);
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Tracked Area Settings", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(showTrackedArea, showContent);
EditorGUILayout.PropertyField(trackedAreaMaterial, materialContent);
EditorGUILayout.PropertyField(trackedAreaPhysicsLayer);
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Boundary Wall Settings", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(showBoundaryWalls, showContent);
EditorGUILayout.PropertyField(boundaryWallMaterial, materialContent);
EditorGUILayout.PropertyField(boundaryWallsPhysicsLayer);
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Boundary Ceiling Settings", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(showBoundaryCeiling, showContent);
EditorGUILayout.PropertyField(boundaryCeilingMaterial, materialContent);
EditorGUILayout.PropertyField(ceilingPhysicsLayer);
}
serializedObject.ApplyModifiedProperties();
}
}
protected override bool IsProfileInActiveInstance()
{
var profile = target as BaseMixedRealityProfile;
return MixedRealityToolkit.IsInitialized && profile != null &&
profile == MixedRealityToolkit.Instance.ActiveProfile.BoundaryVisualizationProfile;
}
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.CameraSystem;
using UnityEditor;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.Editor
{
/// <summary>
/// Class handles rendering inspector view of MixedRealityCameraProfile object
/// </summary>
[CustomEditor(typeof(MixedRealityCameraProfile))]
public class MixedRealityCameraProfileInspector : BaseDataProviderServiceInspector
{
private bool showProviders = false;
private const string showProvidersPreferenceKey = "ShowCameraSystem_DataProviders_PreferenceKey";
private bool showDisplaySettings = false;
private const string showDisplaySettingsPreferenceKey = "ShowCameraSystem_DisplaySettings_PreferenceKey";
private SerializedProperty opaqueNearClip;
private SerializedProperty opaqueFarClip;
private SerializedProperty opaqueClearFlags;
private SerializedProperty opaqueBackgroundColor;
private SerializedProperty opaqueQualityLevel;
private SerializedProperty transparentNearClip;
private SerializedProperty transparentFarClip;
private SerializedProperty transparentClearFlags;
private SerializedProperty transparentBackgroundColor;
private SerializedProperty transparentQualityLevel;
private const string DataProviderErrorMsg = "The Mixed Reality Camera System will use default settings.\nAdd a settings provider to customize the camera.";
private static readonly GUIContent AddProviderTitle = new GUIContent("+ Add Camera Settings Provider", "Add Camera Settings Provider");
private static readonly GUIContent RemoveProviderTitle = new GUIContent("-", "Remove Camera Settings Provider");
private readonly GUIContent nearClipTitle = new GUIContent("Near Clip");
private readonly GUIContent farClipTitle = new GUIContent("Far Clip");
private readonly GUIContent clearFlagsTitle = new GUIContent("Clear Flags");
private readonly GUIContent backgroundColorTitle = new GUIContent("Background Color");
private const string profileTitle = "Camera Settings";
private const string profileDescription = "The Camera Profile helps configure cross platform camera settings.";
/// <inheritdoc/>
protected override void OnEnable()
{
base.OnEnable();
opaqueNearClip = serializedObject.FindProperty("nearClipPlaneOpaqueDisplay");
opaqueFarClip = serializedObject.FindProperty("farClipPlaneOpaqueDisplay");
opaqueClearFlags = serializedObject.FindProperty("cameraClearFlagsOpaqueDisplay");
opaqueBackgroundColor = serializedObject.FindProperty("backgroundColorOpaqueDisplay");
opaqueQualityLevel = serializedObject.FindProperty("opaqueQualityLevel");
transparentNearClip = serializedObject.FindProperty("nearClipPlaneTransparentDisplay");
transparentFarClip = serializedObject.FindProperty("farClipPlaneTransparentDisplay");
transparentClearFlags = serializedObject.FindProperty("cameraClearFlagsTransparentDisplay");
transparentBackgroundColor = serializedObject.FindProperty("backgroundColorTransparentDisplay");
transparentQualityLevel = serializedObject.FindProperty("transparentQualityLevel");
}
/// <inheritdoc/>
public override void OnInspectorGUI()
{
if (!RenderProfileHeader(profileTitle, profileDescription, target))
{
return;
}
using (new EditorGUI.DisabledGroupScope(IsProfileLock((BaseMixedRealityProfile)target)))
{
serializedObject.Update();
RenderFoldout(ref showProviders, "Camera Settings Providers", () =>
{
using (new EditorGUI.IndentLevelScope())
{
bool changed = RenderDataProviderList(AddProviderTitle, RemoveProviderTitle, DataProviderErrorMsg, typeof(BaseCameraSettingsProfile));
if (changed && MixedRealityToolkit.IsInitialized)
{
EditorApplication.delayCall += () => MixedRealityToolkit.Instance.ResetConfiguration(MixedRealityToolkit.Instance.ActiveProfile);
}
}
}, showProvidersPreferenceKey);
RenderFoldout(ref showDisplaySettings, "Display Settings", () =>
{
using (new EditorGUI.IndentLevelScope())
{
EditorGUILayout.LabelField("Opaque", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(opaqueNearClip, nearClipTitle);
EditorGUILayout.PropertyField(opaqueFarClip, farClipTitle);
EditorGUILayout.PropertyField(opaqueClearFlags, clearFlagsTitle);
if ((CameraClearFlags)opaqueClearFlags.intValue == CameraClearFlags.Color)
{
EditorGUILayout.PropertyField(opaqueBackgroundColor, backgroundColorTitle);
}
opaqueQualityLevel.intValue = EditorGUILayout.Popup("Quality Setting", opaqueQualityLevel.intValue, QualitySettings.names);
EditorGUILayout.Space();
EditorGUILayout.LabelField("Transparent", EditorStyles.boldLabel);
EditorGUILayout.PropertyField(transparentNearClip, nearClipTitle);
EditorGUILayout.PropertyField(transparentFarClip, farClipTitle);
EditorGUILayout.PropertyField(transparentClearFlags, clearFlagsTitle);
if ((CameraClearFlags)transparentClearFlags.intValue == CameraClearFlags.Color)
{
EditorGUILayout.PropertyField(transparentBackgroundColor, backgroundColorTitle);
}
transparentQualityLevel.intValue = EditorGUILayout.Popup("Quality Setting", transparentQualityLevel.intValue, QualitySettings.names);
}
}, showDisplaySettingsPreferenceKey);
serializedObject.ApplyModifiedProperties();
}
}
/// <inheritdoc/>
protected override bool IsProfileInActiveInstance()
{
var profile = target as BaseMixedRealityProfile;
return MixedRealityToolkit.IsInitialized && profile != null &&
MixedRealityToolkit.Instance.HasActiveProfile &&
profile == MixedRealityToolkit.Instance.ActiveProfile.CameraProfile;
}
#region DataProvider Inspector Utilities
/// <inheritdoc/>
protected override SerializedProperty GetDataProviderConfigurationList()
{
return serializedObject.FindProperty("settingsConfigurations");
}
/// <inheritdoc/>
protected override ServiceConfigurationProperties GetDataProviderConfigurationProperties(SerializedProperty providerEntry)
{
return new ServiceConfigurationProperties()
{
componentName = providerEntry.FindPropertyRelative("componentName"),
componentType = providerEntry.FindPropertyRelative("componentType"),
providerProfile = providerEntry.FindPropertyRelative("settingsProfile"),
runtimePlatform = providerEntry.FindPropertyRelative("runtimePlatform"),
};
}
/// <inheritdoc/>
protected override IMixedRealityServiceConfiguration GetDataProviderConfiguration(int index)
{
var configurations = (target as MixedRealityCameraProfile)?.SettingsConfigurations;
if (configurations != null && index >= 0 && index < configurations.Length)
{
return configurations[index];
}
return null;
}
#endregion
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Utilities;
using Microsoft.MixedReality.Toolkit.Utilities.Editor;
using Microsoft.MixedReality.Toolkit.Input.UnityInput;
using System;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using Microsoft.MixedReality.Toolkit.Editor;
namespace Microsoft.MixedReality.Toolkit.Input.Editor
{
[CustomEditor(typeof(MixedRealityControllerMappingProfile))]
public class MixedRealityControllerMappingProfileInspector : BaseMixedRealityToolkitConfigurationProfileInspector
{
private readonly struct ControllerMappingSignature
{
public SupportedControllerType SupportedControllerType { get; }
public Handedness Handedness { get; }
public ControllerMappingSignature(SupportedControllerType supportedControllerType, Handedness handedness)
{
SupportedControllerType = supportedControllerType;
Handedness = handedness;
}
}
private struct ControllerRenderProfile
{
public SupportedControllerType SupportedControllerType;
public Handedness Handedness;
public MixedRealityInteractionMapping[] Interactions;
public ControllerRenderProfile(SupportedControllerType supportedControllerType, Handedness handedness, MixedRealityInteractionMapping[] interactions)
{
SupportedControllerType = supportedControllerType;
Handedness = handedness;
Interactions = interactions;
}
}
private static readonly GUIContent ControllerAddButtonContent = new GUIContent("+ Add a New Controller Definition");
private static readonly GUIContent ControllerMinusButtonContent = new GUIContent("-", "Remove Controller Definition");
private static readonly GUIContent GenericTypeContent = new GUIContent("Generic Type");
private static readonly GUIContent HandednessTypeContent = new GUIContent("Handedness");
private static MixedRealityControllerMappingProfile thisProfile;
private SerializedProperty mixedRealityControllerMappings;
private static bool showControllerDefinitions = false;
private const string ProfileTitle = "Controller Input Mapping Settings";
private const string ProfileDescription = "Use this profile to define all the controllers and their inputs your users will be able to use in your application.\n\n" +
"You'll want to define all your Input Actions first. They can then be wired up to hardware sensors, controllers, gestures, and other input devices.";
private readonly List<ControllerRenderProfile> controllerRenderList = new List<ControllerRenderProfile>();
protected override void OnEnable()
{
base.OnEnable();
mixedRealityControllerMappings = serializedObject.FindProperty("mixedRealityControllerMappings");
thisProfile = target as MixedRealityControllerMappingProfile;
}
public override void OnInspectorGUI()
{
if (!RenderProfileHeader(ProfileTitle, ProfileDescription, target, true, BackProfileType.Input))
{
return;
}
using (new EditorGUI.DisabledGroupScope(IsProfileLock((BaseMixedRealityProfile)target)))
{
serializedObject.Update();
RenderControllerList(mixedRealityControllerMappings);
serializedObject.ApplyModifiedProperties();
}
}
protected override bool IsProfileInActiveInstance()
{
var profile = target as BaseMixedRealityProfile;
return MixedRealityToolkit.IsInitialized && profile != null &&
MixedRealityToolkit.Instance.HasActiveProfile &&
MixedRealityToolkit.Instance.ActiveProfile.InputSystemProfile != null &&
profile == MixedRealityToolkit.Instance.ActiveProfile.InputSystemProfile.ControllerMappingProfile;
}
private void RenderControllerList(SerializedProperty controllerList)
{
if (thisProfile.MixedRealityControllerMappings.Length != controllerList.arraySize) { return; }
if (InspectorUIUtility.RenderIndentedButton(ControllerAddButtonContent, EditorStyles.miniButton))
{
AddController(controllerList, typeof(GenericJoystickController));
return;
}
controllerRenderList.Clear();
// Generating the set of controllers that belong to each Controller Mapping Signature
Dictionary<ControllerMappingSignature, List<string>> controllersAffectedByMappingSignatures = new Dictionary<ControllerMappingSignature, List<string>>();
for (int i = 0; i < thisProfile.MixedRealityControllerMappings.Length; i++)
{
MixedRealityControllerMapping controllerMapping = thisProfile.MixedRealityControllerMappings[i];
Type controllerType = controllerMapping.ControllerType;
if (controllerType == null) { continue; }
Handedness handedness = controllerMapping.Handedness;
bool useCustomInteractionMappings = controllerMapping.HasCustomInteractionMappings;
SupportedControllerType supportedControllerType = controllerMapping.SupportedControllerType;
var controllerMappingProperty = controllerList.GetArrayElementAtIndex(i);
var handednessProperty = controllerMappingProperty.FindPropertyRelative("handedness");
ControllerMappingSignature currentSignature = new ControllerMappingSignature(supportedControllerType, handedness);
if(!controllersAffectedByMappingSignatures.ContainsKey(currentSignature))
{
controllersAffectedByMappingSignatures.Add(currentSignature, new List<string>());
}
controllersAffectedByMappingSignatures[currentSignature].Add(controllerType.ToString());
}
showControllerDefinitions = EditorGUILayout.Foldout(showControllerDefinitions, "Controller Definitions", true);
if (showControllerDefinitions)
{
using (var outerVerticalScope = new GUILayout.VerticalScope())
{
GUILayout.HorizontalScope horizontalScope = null;
for (int i = 0; i < thisProfile.MixedRealityControllerMappings.Length; i++)
{
MixedRealityControllerMapping controllerMapping = thisProfile.MixedRealityControllerMappings[i];
Type controllerType = controllerMapping.ControllerType;
if (controllerType == null) { continue; }
Handedness handedness = controllerMapping.Handedness;
bool useCustomInteractionMappings = controllerMapping.HasCustomInteractionMappings;
SupportedControllerType supportedControllerType = controllerMapping.SupportedControllerType;
var controllerMappingProperty = controllerList.GetArrayElementAtIndex(i);
var handednessProperty = controllerMappingProperty.FindPropertyRelative("handedness");
#region Profile Migration
// Between MRTK v2 RC2 and GA, the HoloLens clicker and HoloLens voice select input were migrated from
// SupportedControllerType.WindowsMixedReality && Handedness.None to SupportedControllerType.GGVHand && Handedness.None
if (supportedControllerType == SupportedControllerType.WindowsMixedReality && handedness == Handedness.None)
{
for (int j = 0; j < thisProfile.MixedRealityControllerMappings.Length; j++)
{
if (thisProfile.MixedRealityControllerMappings[j].SupportedControllerType == SupportedControllerType.GGVHand &&
thisProfile.MixedRealityControllerMappings[j].Handedness == Handedness.None)
{
if (horizontalScope != null) { horizontalScope.Dispose(); horizontalScope = null; }
serializedObject.ApplyModifiedProperties();
for (int k = 0; k < controllerMapping.Interactions.Length; k++)
{
MixedRealityInteractionMapping currentMapping = controllerMapping.Interactions[k];
if (currentMapping.InputType == DeviceInputType.Select)
{
thisProfile.MixedRealityControllerMappings[j].Interactions[0].MixedRealityInputAction = currentMapping.MixedRealityInputAction;
}
else if (currentMapping.InputType == DeviceInputType.SpatialGrip)
{
thisProfile.MixedRealityControllerMappings[j].Interactions[1].MixedRealityInputAction = currentMapping.MixedRealityInputAction;
}
}
serializedObject.Update();
controllerList.DeleteArrayElementAtIndex(i);
EditorUtility.DisplayDialog("Mappings updated", "The \"HoloLens Voice and Clicker\" mappings have been migrated to a new serialization. Please save this asset.", "Okay, thanks!");
return;
}
}
}
#endregion Profile Migration
if (!useCustomInteractionMappings)
{
bool skip = false;
// Merge controllers with the same supported controller type.
for (int j = 0; j < controllerRenderList.Count; j++)
{
if (controllerRenderList[j].SupportedControllerType == supportedControllerType &&
controllerRenderList[j].Handedness == handedness)
{
try
{
thisProfile.MixedRealityControllerMappings[i].SynchronizeInputActions(controllerRenderList[j].Interactions);
}
catch (ArgumentException e)
{
Debug.LogError($"Controller mappings between {thisProfile.MixedRealityControllerMappings[i].Description} and {controllerMapping.Description} do not match. Error message: {e.Message}");
}
serializedObject.ApplyModifiedProperties();
skip = true;
}
}
if (skip) { continue; }
}
controllerRenderList.Add(new ControllerRenderProfile(supportedControllerType, handedness, thisProfile.MixedRealityControllerMappings[i].Interactions));
string controllerTitle = thisProfile.MixedRealityControllerMappings[i].Description;
var interactionsProperty = controllerMappingProperty.FindPropertyRelative("interactions");
if (useCustomInteractionMappings)
{
if (horizontalScope != null) { horizontalScope.Dispose(); horizontalScope = null; }
GUILayout.Space(24f);
using (var verticalScope = new GUILayout.VerticalScope())
{
using (horizontalScope = new GUILayout.HorizontalScope())
{
EditorGUILayout.LabelField(controllerTitle, EditorStyles.boldLabel);
if (GUILayout.Button(ControllerMinusButtonContent, EditorStyles.miniButtonRight, GUILayout.Width(24f)))
{
controllerList.DeleteArrayElementAtIndex(i);
return;
}
}
EditorGUI.BeginChangeCheck();
// Generic Type dropdown
Type[] genericTypes = MixedRealityControllerMappingProfile.CustomControllerMappingTypes;
var genericTypeListContent = new GUIContent[genericTypes.Length];
var genericTypeListIds = new int[genericTypes.Length];
int currentGenericType = -1;
for (int genericTypeIdx = 0; genericTypeIdx < genericTypes.Length; genericTypeIdx++)
{
var attribute = MixedRealityControllerAttribute.Find(genericTypes[genericTypeIdx]);
if (attribute != null)
{
genericTypeListContent[genericTypeIdx] = new GUIContent(attribute.SupportedControllerType.ToString().Replace("Generic", "").ToProperCase() + " Controller");
}
else
{
genericTypeListContent[genericTypeIdx] = new GUIContent("Unknown Controller");
}
genericTypeListIds[genericTypeIdx] = genericTypeIdx;
if (controllerType == genericTypes[genericTypeIdx])
{
currentGenericType = genericTypeIdx;
}
}
Debug.Assert(currentGenericType != -1);
currentGenericType = EditorGUILayout.IntPopup(GenericTypeContent, currentGenericType, genericTypeListContent, genericTypeListIds);
controllerType = genericTypes[currentGenericType];
{
// Handedness dropdown
var attribute = MixedRealityControllerAttribute.Find(controllerType);
if (attribute != null && attribute.SupportedHandedness.Length >= 1)
{
// Make sure handedness is valid for the selected controller type.
if (Array.IndexOf(attribute.SupportedHandedness, (Handedness)handednessProperty.intValue) < 0)
{
handednessProperty.intValue = (int)attribute.SupportedHandedness[0];
}
if (attribute.SupportedHandedness.Length >= 2)
{
var handednessListContent = new GUIContent[attribute.SupportedHandedness.Length];
var handednessListIds = new int[attribute.SupportedHandedness.Length];
for (int handednessIdx = 0; handednessIdx < attribute.SupportedHandedness.Length; handednessIdx++)
{
handednessListContent[handednessIdx] = new GUIContent(attribute.SupportedHandedness[handednessIdx].ToString());
handednessListIds[handednessIdx] = (int)attribute.SupportedHandedness[handednessIdx];
}
handednessProperty.intValue = EditorGUILayout.IntPopup(HandednessTypeContent, handednessProperty.intValue, handednessListContent, handednessListIds);
}
}
else
{
handednessProperty.intValue = (int)Handedness.None;
}
}
if (EditorGUI.EndChangeCheck())
{
interactionsProperty.ClearArray();
serializedObject.ApplyModifiedProperties();
thisProfile.MixedRealityControllerMappings[i].ControllerType.Type = genericTypes[currentGenericType];
thisProfile.MixedRealityControllerMappings[i].SetDefaultInteractionMapping(true);
serializedObject.ApplyModifiedProperties();
return;
}
if (InspectorUIUtility.RenderIndentedButton("Edit Input Action Map"))
{
ControllerPopupWindow.Show(controllerMapping, interactionsProperty, handedness);
}
if (InspectorUIUtility.RenderIndentedButton("Reset Input Actions"))
{
interactionsProperty.ClearArray();
serializedObject.ApplyModifiedProperties();
thisProfile.MixedRealityControllerMappings[i].SetDefaultInteractionMapping(true);
serializedObject.ApplyModifiedProperties();
}
}
}
else
{
if (handedness != Handedness.Right)
{
if (horizontalScope != null) { horizontalScope.Dispose(); horizontalScope = null; }
horizontalScope = new GUILayout.HorizontalScope();
}
var buttonContent = new GUIContent(controllerTitle, ControllerMappingLibrary.GetControllerTextureScaled(controllerType, handedness));
if (GUILayout.Button(buttonContent, MixedRealityStylesUtility.ControllerButtonStyle, GUILayout.Height(128f), GUILayout.MinWidth(32f), GUILayout.ExpandWidth(true)))
{
ControllerMappingSignature buttonSignature = new ControllerMappingSignature(supportedControllerType, handedness);
ControllerPopupWindow.Show(controllerMapping, interactionsProperty, handedness, controllersAffectedByMappingSignatures[buttonSignature]);
}
}
}
if (horizontalScope != null) { horizontalScope.Dispose(); horizontalScope = null; }
}
}
}
private void AddController(SerializedProperty controllerList, Type controllerType)
{
controllerList.InsertArrayElementAtIndex(controllerList.arraySize);
var index = controllerList.arraySize - 1;
var mixedRealityControllerMapping = controllerList.GetArrayElementAtIndex(index);
var handednessProperty = mixedRealityControllerMapping.FindPropertyRelative("handedness");
handednessProperty.intValue = (int)Handedness.None;
var interactionsProperty = mixedRealityControllerMapping.FindPropertyRelative("interactions");
interactionsProperty.ClearArray();
serializedObject.ApplyModifiedProperties();
thisProfile.MixedRealityControllerMappings[index].ControllerType.Type = controllerType;
thisProfile.MixedRealityControllerMappings[index].SetDefaultInteractionMapping(true);
}
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Utilities;
using Microsoft.MixedReality.Toolkit.Utilities.Editor;
using Microsoft.MixedReality.Toolkit.Input.UnityInput;
using UnityEditor;
using UnityEngine;
using Microsoft.MixedReality.Toolkit.Editor;
namespace Microsoft.MixedReality.Toolkit.Input.Editor
{
[CustomEditor(typeof(MixedRealityControllerVisualizationProfile))]
public class MixedRealityControllerVisualizationProfileInspector : BaseMixedRealityToolkitConfigurationProfileInspector
{
private static readonly GUIContent ControllerAddButtonContent = new GUIContent("+ Add a New Controller Definition");
private static readonly GUIContent ControllerMinusButtonContent = new GUIContent("-", "Remove Controller Definition");
private static readonly GUIContent[] HandednessSelections =
{
new GUIContent("Left Hand"),
new GUIContent("Right Hand"),
};
private SerializedProperty renderMotionControllers;
private SerializedProperty defaultControllerVisualizationType;
private SerializedProperty useDefaultModels;
private SerializedProperty defaultControllerModelMaterial;
private SerializedProperty globalLeftHandedControllerModel;
private SerializedProperty globalRightHandedControllerModel;
private SerializedProperty globalLeftHandModel;
private SerializedProperty globalRightHandModel;
private static bool showControllerDefinitions = true;
private SerializedProperty controllerVisualizationSettings;
private MixedRealityControllerVisualizationProfile thisProfile;
private float defaultLabelWidth;
private float defaultFieldWidth;
private const string ProfileTitle = "Controller Visualization Settings";
private const string ProfileDescription = "Define all the custom controller visualizations you'd like to use for each controller type when they're rendered in the scene.\n\n" +
"Global settings are the default fallback, and any specific controller definitions take precedence.";
protected override void OnEnable()
{
base.OnEnable();
defaultLabelWidth = EditorGUIUtility.labelWidth;
defaultFieldWidth = EditorGUIUtility.fieldWidth;
thisProfile = target as MixedRealityControllerVisualizationProfile;
renderMotionControllers = serializedObject.FindProperty("renderMotionControllers");
defaultControllerVisualizationType = serializedObject.FindProperty("defaultControllerVisualizationType");
useDefaultModels = serializedObject.FindProperty("useDefaultModels");
defaultControllerModelMaterial = serializedObject.FindProperty("defaultControllerModelMaterial");
globalLeftHandedControllerModel = serializedObject.FindProperty("globalLeftControllerModel");
globalRightHandedControllerModel = serializedObject.FindProperty("globalRightControllerModel");
globalLeftHandModel = serializedObject.FindProperty("globalLeftHandVisualizer");
globalRightHandModel = serializedObject.FindProperty("globalRightHandVisualizer");
controllerVisualizationSettings = serializedObject.FindProperty("controllerVisualizationSettings");
}
public override void OnInspectorGUI()
{
if (!RenderProfileHeader(ProfileTitle, ProfileDescription, target, true, BackProfileType.Input))
{
return;
}
using (new EditorGUI.DisabledGroupScope(IsProfileLock((BaseMixedRealityProfile)target)))
{
serializedObject.Update();
EditorGUILayout.LabelField("Visualization Settings", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(renderMotionControllers);
EditorGUILayout.PropertyField(defaultControllerVisualizationType);
if (thisProfile.DefaultControllerVisualizationType == null ||
thisProfile.DefaultControllerVisualizationType.Type == null)
{
EditorGUILayout.HelpBox("A default controller visualization type must be defined!", MessageType.Error);
}
}
var leftHandModelPrefab = globalLeftHandedControllerModel.objectReferenceValue as GameObject;
var rightHandModelPrefab = globalRightHandedControllerModel.objectReferenceValue as GameObject;
EditorGUILayout.Space();
EditorGUILayout.LabelField("Controller Model Settings", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(useDefaultModels);
EditorGUILayout.PropertyField(defaultControllerModelMaterial);
if (useDefaultModels.boolValue && (leftHandModelPrefab != null || rightHandModelPrefab != null))
{
EditorGUILayout.HelpBox("When default models are used, an attempt is made to obtain controller models from the platform SDK. The global left and right models are only shown if no model can be obtained.", MessageType.Warning);
}
EditorGUI.BeginChangeCheck();
leftHandModelPrefab = EditorGUILayout.ObjectField(new GUIContent(globalLeftHandedControllerModel.displayName, "Note: If the default model is not found, the fallback is the global left hand model."), leftHandModelPrefab, typeof(GameObject), false) as GameObject;
if (EditorGUI.EndChangeCheck() && CheckVisualizer(leftHandModelPrefab))
{
globalLeftHandedControllerModel.objectReferenceValue = leftHandModelPrefab;
}
EditorGUI.BeginChangeCheck();
rightHandModelPrefab = EditorGUILayout.ObjectField(new GUIContent(globalRightHandedControllerModel.displayName, "Note: If the default model is not found, the fallback is the global right hand model."), rightHandModelPrefab, typeof(GameObject), false) as GameObject;
if (EditorGUI.EndChangeCheck() && CheckVisualizer(rightHandModelPrefab))
{
globalRightHandedControllerModel.objectReferenceValue = rightHandModelPrefab;
}
EditorGUILayout.PropertyField(globalLeftHandModel);
EditorGUILayout.PropertyField(globalRightHandModel);
}
EditorGUIUtility.labelWidth = defaultLabelWidth;
EditorGUILayout.Space();
showControllerDefinitions = EditorGUILayout.Foldout(showControllerDefinitions, "Controller Definitions", true);
if (showControllerDefinitions)
{
using (new EditorGUI.IndentLevelScope())
{
RenderControllerList(controllerVisualizationSettings);
}
}
serializedObject.ApplyModifiedProperties();
}
}
protected override bool IsProfileInActiveInstance()
{
var profile = target as BaseMixedRealityProfile;
return MixedRealityToolkit.IsInitialized && profile != null &&
MixedRealityToolkit.Instance.HasActiveProfile &&
MixedRealityToolkit.Instance.ActiveProfile.InputSystemProfile != null &&
profile == MixedRealityToolkit.Instance.ActiveProfile.InputSystemProfile.ControllerVisualizationProfile;
}
private void RenderControllerList(SerializedProperty controllerList)
{
if (thisProfile.ControllerVisualizationSettings.Length != controllerList.arraySize) { return; }
EditorGUILayout.Space();
if (InspectorUIUtility.RenderIndentedButton(ControllerAddButtonContent, EditorStyles.miniButton))
{
controllerList.InsertArrayElementAtIndex(controllerList.arraySize);
var index = controllerList.arraySize - 1;
var controllerSetting = controllerList.GetArrayElementAtIndex(index);
var mixedRealityControllerMappingDescription = controllerSetting.FindPropertyRelative("description");
mixedRealityControllerMappingDescription.stringValue = typeof(GenericJoystickController).Name;
var mixedRealityControllerHandedness = controllerSetting.FindPropertyRelative("handedness");
mixedRealityControllerHandedness.intValue = 1;
serializedObject.ApplyModifiedProperties();
thisProfile.ControllerVisualizationSettings[index].ControllerType.Type = typeof(GenericJoystickController);
return;
}
for (int i = 0; i < controllerList.arraySize; i++)
{
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
var controllerSetting = controllerList.GetArrayElementAtIndex(i);
var mixedRealityControllerMappingDescription = controllerSetting.FindPropertyRelative("description");
bool hasValidType = thisProfile.ControllerVisualizationSettings[i].ControllerType != null &&
thisProfile.ControllerVisualizationSettings[i].ControllerType.Type != null;
mixedRealityControllerMappingDescription.stringValue = hasValidType
? thisProfile.ControllerVisualizationSettings[i].ControllerType.Type.Name.ToProperCase()
: "Undefined Controller";
serializedObject.ApplyModifiedProperties();
var mixedRealityControllerHandedness = controllerSetting.FindPropertyRelative("handedness");
EditorGUILayout.LabelField($"{mixedRealityControllerMappingDescription.stringValue} {((Handedness)mixedRealityControllerHandedness.intValue).ToString().ToProperCase()} Hand", EditorStyles.boldLabel);
if (GUILayout.Button(ControllerMinusButtonContent, EditorStyles.miniButtonRight, GUILayout.Width(24f)))
{
controllerList.DeleteArrayElementAtIndex(i);
EditorGUILayout.EndHorizontal();
GUILayout.EndVertical();
return;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.PropertyField(controllerSetting.FindPropertyRelative("controllerType"));
EditorGUILayout.PropertyField(controllerSetting.FindPropertyRelative("controllerVisualizationType"));
if (!hasValidType)
{
EditorGUILayout.HelpBox("A controller type must be defined!", MessageType.Error);
}
var handednessValue = mixedRealityControllerHandedness.intValue - 1;
// Reset in case it was set to something other than left or right.
if (handednessValue < 0 || handednessValue > 1) { handednessValue = 0; }
EditorGUI.BeginChangeCheck();
handednessValue = EditorGUILayout.IntPopup(new GUIContent(mixedRealityControllerHandedness.displayName, mixedRealityControllerHandedness.tooltip), handednessValue, HandednessSelections, null);
if (EditorGUI.EndChangeCheck())
{
mixedRealityControllerHandedness.intValue = handednessValue + 1;
}
var overrideModel = controllerSetting.FindPropertyRelative("overrideModel");
var overrideModelPrefab = overrideModel.objectReferenceValue as GameObject;
var controllerUseDefaultModelOverride = controllerSetting.FindPropertyRelative("useDefaultModel");
using (new GUILayout.HorizontalScope())
{
EditorGUILayout.PropertyField(controllerUseDefaultModelOverride);
var defaultModelMaterial = controllerSetting.FindPropertyRelative("defaultModelMaterial");
EditorGUILayout.PropertyField(defaultModelMaterial);
}
if (controllerUseDefaultModelOverride.boolValue && overrideModelPrefab != null)
{
EditorGUILayout.HelpBox("When default model is used, the override model will only be used if the default model cannot be loaded from the driver.", MessageType.Warning);
}
EditorGUI.BeginChangeCheck();
overrideModelPrefab = EditorGUILayout.ObjectField(new GUIContent(overrideModel.displayName, "If no override model is set, the global model is used."), overrideModelPrefab, typeof(GameObject), false) as GameObject;
if (EditorGUI.EndChangeCheck() && CheckVisualizer(overrideModelPrefab))
{
overrideModel.objectReferenceValue = overrideModelPrefab;
}
}
}
private bool CheckVisualizer(GameObject modelPrefab)
{
if (modelPrefab == null) { return true; }
if (PrefabUtility.GetPrefabAssetType(modelPrefab) == PrefabAssetType.NotAPrefab)
{
Debug.LogWarning("Assigned GameObject must be a prefab.");
return false;
}
var componentList = modelPrefab.GetComponentsInChildren<IMixedRealityControllerVisualizer>();
if (componentList == null || componentList.Length == 0)
{
if (thisProfile.DefaultControllerVisualizationType != null &&
thisProfile.DefaultControllerVisualizationType.Type != null)
{
modelPrefab.AddComponent(thisProfile.DefaultControllerVisualizationType.Type);
return true;
}
Debug.LogError("No controller visualization type specified!");
}
else if (componentList.Length == 1)
{
return true;
}
else if (componentList.Length > 1)
{
Debug.LogWarning("Found too many IMixedRealityControllerVisualizer components on your prefab. There can only be one.");
}
return false;
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Editor;
using UnityEditor;
namespace Microsoft.MixedReality.Toolkit.Diagnostics.Editor
{
[CustomEditor(typeof(MixedRealityDiagnosticsProfile))]
public class MixedRealityDiagnosticsSystemProfileInspector : BaseMixedRealityToolkitConfigurationProfileInspector
{
private SerializedProperty showDiagnostics;
private SerializedProperty showProfiler;
private SerializedProperty frameSampleRate;
private SerializedProperty windowAnchor;
private SerializedProperty windowOffset;
private SerializedProperty windowScale;
private SerializedProperty windowFollowSpeed;
private SerializedProperty showProfilerDuringMRC;
private const string ProfileTitle = "Diagnostic Settings";
private const string ProfileDescription = "Diagnostic visualizations can help monitor system resources and performance inside an application.";
// todo: coming soon
// private static bool showDebugPanelSettings = true;
// private SerializedProperty isDebugPanelVisible;
protected override void OnEnable()
{
base.OnEnable();
showDiagnostics = serializedObject.FindProperty("showDiagnostics");
showProfiler = serializedObject.FindProperty("showProfiler");
frameSampleRate = serializedObject.FindProperty("frameSampleRate");
windowAnchor = serializedObject.FindProperty("windowAnchor");
windowOffset = serializedObject.FindProperty("windowOffset");
windowScale = serializedObject.FindProperty("windowScale");
windowFollowSpeed = serializedObject.FindProperty("windowFollowSpeed");
showProfilerDuringMRC = serializedObject.FindProperty("showProfilerDuringMRC");
}
public override void OnInspectorGUI()
{
if (!RenderProfileHeader(ProfileTitle, ProfileDescription, target))
{
return;
}
using (new EditorGUI.DisabledGroupScope(IsProfileLock((BaseMixedRealityProfile)target)))
{
serializedObject.Update();
EditorGUILayout.Space();
EditorGUILayout.LabelField("General Settings", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(showDiagnostics);
if (!showDiagnostics.boolValue)
{
EditorGUILayout.Space();
EditorGUILayout.HelpBox("Diagnostic visualizations have been globally disabled.", MessageType.Info);
EditorGUILayout.Space();
}
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("Profiler Settings", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(showProfiler);
EditorGUILayout.PropertyField(frameSampleRate);
EditorGUILayout.PropertyField(windowAnchor);
EditorGUILayout.PropertyField(windowOffset);
EditorGUILayout.PropertyField(windowScale);
EditorGUILayout.PropertyField(windowFollowSpeed);
}
EditorGUILayout.Space();
EditorGUILayout.LabelField("HoloLens Settings", EditorStyles.boldLabel);
{
EditorGUILayout.PropertyField(showProfilerDuringMRC);
}
serializedObject.ApplyModifiedProperties();
}
}
protected override bool IsProfileInActiveInstance()
{
var profile = target as BaseMixedRealityProfile;
return MixedRealityToolkit.IsInitialized && profile != null &&
MixedRealityToolkit.Instance.HasActiveProfile &&
profile == MixedRealityToolkit.Instance.ActiveProfile.DiagnosticsSystemProfile;
}
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using Microsoft.MixedReality.Toolkit.Editor;
using Microsoft.MixedReality.Toolkit.Input;
using Microsoft.MixedReality.Toolkit.Utilities.Editor;
using System.Linq;
using UnityEditor;
namespace Microsoft.MixedReality.Toolkit.Inspectors
{
[CustomEditor(typeof(MixedRealityEyeTrackingProfile))]
public class MixedRealityEyeTrackingProfileInspector : BaseMixedRealityToolkitConfigurationProfileInspector
{
private SerializedProperty smoothEyeTracking;
private const string ProfileTitle = "Eye tracking Settings";
protected override void OnEnable()
{
base.OnEnable();
smoothEyeTracking = serializedObject.FindProperty("smoothEyeTracking");
}
public override void OnInspectorGUI()
{
if (!RenderProfileHeader(ProfileTitle, string.Empty, target, true, BackProfileType.Input))
{
return;
}
using (new EditorGUI.DisabledGroupScope(IsProfileLock((BaseMixedRealityProfile)target)))
{
serializedObject.Update();
EditorGUILayout.PropertyField(smoothEyeTracking);
serializedObject.ApplyModifiedProperties();
}
}
protected override bool IsProfileInActiveInstance()
{
var profile = target as BaseMixedRealityProfile;
return MixedRealityToolkit.IsInitialized && profile != null &&
MixedRealityToolkit.Instance.HasActiveProfile &&
MixedRealityToolkit.Instance.ActiveProfile.InputSystemProfile != null &&
MixedRealityToolkit.Instance.ActiveProfile.InputSystemProfile.DataProviderConfigurations != null &&
MixedRealityToolkit.Instance.ActiveProfile.InputSystemProfile.DataProviderConfigurations.Any(s => profile == s.DeviceManagerProfile);
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment