mixedreality/com.microsoft.mixedreality..../Core/Inspectors/PropertyDrawers/ScenePickPropertyDrawer.cs

120 lines
4.2 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using UnityEditor;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.Editor
{
/// <summary>
/// Creates a custom picker based on the list of scene in the build settings.
/// </summary>
/// <example>
/// <code>
/// [ScenePick]
/// public int SceneId;
/// </code>
/// </example>
[CustomPropertyDrawer(typeof(ScenePickAttribute))]
public class ScenePickPropertyDrawer : PropertyDrawer
{
/// <summary>
/// List of Options extracted from the Editor
/// </summary>
private static GUIContent[] Options;
/// <summary>
/// List of Scene GUIDS for the scenes
/// </summary>
private static string[] PropertyData;
/// <summary>
/// Select this option to remove the event string
/// </summary>
private static readonly string UnselectedText = "-- None --";
/// <summary>
/// Text to display when an entry is missing
/// </summary>
private static readonly string MissingText = "-- Missing --";
/// <summary>
/// Function called by unity to draw the GUI for this property
/// We are replacing the int value of the backing field with a dropdown list of scene names
/// </summary>
/// <param name="position">See base class</param>
/// <param name="property">See base class</param>
/// <param name="label">See base class</param>
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
BuildOptions();
var currentGuid = property.stringValue.Split(';')[0];
var currentId = System.Array.FindIndex(PropertyData, (x) => x.Contains(currentGuid));
if (currentId == -1)
{
// Not found, display the missing text
currentId = Options.Length - 1;
}
else if (currentId > 0 && property.stringValue != PropertyData[currentId])
{
// If the string has changed, update the property.
// This will happen if the scene is renamed.
property.stringValue = PropertyData[currentId];
EditorUtility.SetDirty(property.serializedObject.targetObject);
}
EditorGUI.BeginProperty(position, new GUIContent(property.name), property);
var newId = EditorGUI.Popup(position, label, currentId, Options);
if (newId != currentId)
{
property.stringValue = PropertyData[newId];
EditorUtility.SetDirty(property.serializedObject.targetObject);
}
EditorGUI.EndProperty();
}
/// <summary>
/// Build the list of scene names
/// Note: Scene 0 is the no-scene option.
/// </summary>
private static void BuildOptions()
{
var scenes = EditorBuildSettings.scenes;
if (scenes.Length > 0)
{
Options = new GUIContent[scenes.Length + 2];
PropertyData = new string[scenes.Length + 2];
Options[0] = new GUIContent(UnselectedText);
PropertyData[0] = string.Empty;
for (int i = 0; i < scenes.Length; i++)
{
// Right, replace '/' with '\' otherwise the list displays like a menu where '/' denotes a sub-menu.
Options[i + 1] = new GUIContent(scenes[i].path.Replace("/", "\\"));
PropertyData[i + 1] = scenes[i].guid.ToString() + ";" + scenes[i].path;
}
Options[scenes.Length + 1] = new GUIContent(MissingText);
PropertyData[scenes.Length + 1] = MissingText;
}
else
{
Options = new GUIContent[2];
PropertyData = new string[2];
Options[0] = new GUIContent(UnselectedText);
PropertyData[0] = string.Empty;
Options[1] = new GUIContent(MissingText);
PropertyData[1] = MissingText;
}
}
}
}