Scripts/Editor/WitEditorUI.cs (331 lines of code) (raw):

/* * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ using System; using System.Collections.Generic; using UnityEditor; using UnityEngine; using Facebook.WitAi.Data.Configuration; using UnityEditor.PackageManager.UI; namespace Facebook.WitAi { public static class WitEditorUI { #region LABELS public static void LayoutLabel(string text) { LayoutLabel(text, WitStyles.Label); } public static void LayoutWrapLabel(string text) { LayoutLabel(text, WitStyles.LabelWrap); } public static void LayoutHeaderLabel(string text) { LayoutLabel(text, WitStyles.LabelHeader); } public static void LayoutSubheaderLabel(string text) { LayoutLabel(text, WitStyles.LabelSubheader); } public static void LayoutErrorLabel(string text) { LayoutLabel(text, WitStyles.LabelError); } public static void LayoutStatusLabel(string text) { EditorGUILayout.BeginVertical(WitStyles.LabelStatusBackground, GUILayout.ExpandWidth(true), GUILayout.Height(24)); EditorGUILayout.LabelField(text, WitStyles.LabelStatus, GUILayout.ExpandWidth(true)); EditorGUILayout.EndVertical(); } private static void LayoutLabel(string text, GUIStyle style) { EditorGUILayout.LabelField(text, style); } public static void LayoutKeyLabel(string key, string text) { EditorGUILayout.LabelField(key, text, WitStyles.TextField); } #endregion #region BUTTONS public static bool LayoutTextButton(string text) { GUIContent content = new GUIContent(text); float width = WitStyles.TextButton.CalcSize(content).x + WitStyles.TextButtonPadding * 2f; return LayoutButton(content, WitStyles.TextButton, new GUILayoutOption[] { GUILayout.Width(width) }); } public static bool LayoutIconButton(GUIContent icon) { return LayoutButton(icon, WitStyles.IconButton, null); } public static void LayoutTabButtons(string[] tabTitles, ref int selection) { if (tabTitles != null) { GUILayout.BeginHorizontal(); for (int i = 0; i < tabTitles.Length; i++) { GUI.enabled = selection != i; if (LayoutTabButton(tabTitles[i])) { selection = i; } } GUI.enabled = true; GUILayout.EndHorizontal(); } } public static bool LayoutTabButton(string tabTitle) { return LayoutButton(new GUIContent(tabTitle), WitStyles.TabButton, null); } private static bool LayoutButton(GUIContent content, GUIStyle style, GUILayoutOption[] options) { return GUILayout.Button(content, style, options); } // Layout header button public static void LayoutHeaderButton(Texture2D headerTexture, string headerURL) { if (headerTexture != null) { GUILayout.BeginHorizontal(); GUILayout.FlexibleSpace(); float maxWidth = EditorGUIUtility.currentViewWidth - WitStyles.WindowPaddingLeft - WitStyles.WindowPaddingRight - WitStyles.IconButton.CalcSize(WitStyles.HelpIcon).x; float headerWidth = Mathf.Min(WitStyles.HeaderWidth, maxWidth); float headerHeight = headerWidth * (float)headerTexture.height / (float)headerTexture.width; if (GUILayout.Button(headerTexture, WitStyles.HeaderButton, GUILayout.Width(headerWidth), GUILayout.Height(headerHeight)) && !string.IsNullOrEmpty(headerURL)) { Application.OpenURL(headerURL); } GUILayout.FlexibleSpace(); if (LayoutIconButton(WitStyles.HelpIcon)) { Application.OpenURL(headerURL); } GUILayout.EndHorizontal(); } } #endregion #region FOLDOUT // Foldout storage for bind objects private static Dictionary<string, bool> foldouts = new Dictionary<string, bool>(); private static string GetFoldoutID(object bindObject) { return bindObject == null ? "" : bindObject.GetHashCode().ToString(); } public static bool GetFoldoutValue(object bindObject) { string foldoutID = GetFoldoutID(bindObject); if (!string.IsNullOrEmpty(foldoutID) && foldouts.ContainsKey(foldoutID)) { return foldouts[foldoutID]; } return false; } public static void SetFoldoutValue(object bindObject, bool toFoldout) { string foldoutID = GetFoldoutID(bindObject); if (!string.IsNullOrEmpty(foldoutID)) { foldouts[foldoutID] = toFoldout; } } public static bool LayoutFoldout(GUIContent key, object bindObject) { bool wasFoldout = GetFoldoutValue(bindObject); bool isFoldout = LayoutFoldout(key, wasFoldout); if (isFoldout != wasFoldout) { SetFoldoutValue(bindObject, isFoldout); } return isFoldout; } // GUI Layout handled without bind objects public static bool LayoutFoldout(GUIContent key, bool wasFoldout) { return EditorGUILayout.Foldout(wasFoldout, key, true, WitStyles.Foldout); } #endregion #region FIELDS public static void LayoutTextField(GUIContent key, ref string fieldValue, ref bool isUpdated) { // Ensure not null if (fieldValue == null) { fieldValue = string.Empty; } // Simple layout string newFieldValue; if (key == null) { newFieldValue = EditorGUILayout.TextField(fieldValue, WitStyles.TextField); } else { newFieldValue = EditorGUILayout.TextField(key, fieldValue, WitStyles.TextField); } // Update if changed if (!string.Equals(fieldValue, newFieldValue)) { fieldValue = newFieldValue; isUpdated = true; } } public static void LayoutPasswordField(GUIContent key, ref string fieldValue, ref bool isUpdated) { // Ensure not null if (fieldValue == null) { fieldValue = string.Empty; } // Simple layout GUILayout.BeginHorizontal(); string newFieldValue; if (key == null) { newFieldValue = EditorGUILayout.PasswordField(fieldValue, WitStyles.PasswordField); } else { newFieldValue = EditorGUILayout.PasswordField(key, fieldValue, WitStyles.PasswordField); } // Layout icon if (LayoutIconButton(WitStyles.PasteIcon)) { newFieldValue = EditorGUIUtility.systemCopyBuffer; GUI.FocusControl(null); } GUILayout.EndHorizontal(); // Update if changed if (!string.Equals(fieldValue, newFieldValue)) { fieldValue = newFieldValue; isUpdated = true; } } public static void LayoutIntField(GUIContent key, ref int fieldValue, ref bool isUpdated) { // Simple layout int newFieldValue = EditorGUILayout.IntField(key, fieldValue, WitStyles.IntField); // Update if (fieldValue != newFieldValue) { fieldValue = newFieldValue; isUpdated = true; } } // Locked text field private static string unlockFieldId = ""; private static string unlockFieldText = ""; public static void LayoutLockedTextField(GUIContent key, ref string fieldValue, ref bool isUpdated) { // Determine if locked string fieldId = GetFoldoutID(key.text); bool isEditing = unlockFieldId.Equals(fieldId); // Begin Horizontal GUILayout.BeginHorizontal(); // Hide if not editing GUI.enabled = isEditing; // Layout string newFieldValue = isEditing ? unlockFieldText : fieldValue; bool newUpdate = false; LayoutTextField(key, ref newFieldValue, ref newUpdate); // Allow next item GUI.enabled = true; // Updated if (newUpdate && isEditing) { unlockFieldText = newFieldValue; } // Cancel vs Apply Buttons if (isEditing) { if (LayoutIconButton(WitStyles.ResetIcon)) { unlockFieldId = string.Empty; unlockFieldText = string.Empty; GUI.FocusControl(null); } if (LayoutIconButton(WitStyles.AcceptIcon)) { if (!string.Equals(fieldValue, unlockFieldText)) { fieldValue = unlockFieldText; isUpdated = true; } unlockFieldId = string.Empty; unlockFieldText = string.Empty; GUI.FocusControl(null); } } // Edit button else { if (LayoutIconButton(WitStyles.EditIcon)) { unlockFieldId = fieldId; unlockFieldText = fieldValue; } } // End Horizontal GUILayout.EndHorizontal(); } #endregion #region MISCELANEOUS public static void LayoutToggle(GUIContent key, ref bool toggleValue, ref bool isUpdated) { // Simple layout bool newToggleValue = EditorGUILayout.Toggle(key, toggleValue, WitStyles.Toggle); // Update if (toggleValue != newToggleValue) { toggleValue = newToggleValue; isUpdated = true; } } public static void LayoutPopup(string key, string[] options, ref int selectionValue, ref bool isUpdated) { // Simple layout int newSelectionValue = EditorGUILayout.Popup(key, selectionValue, options, WitStyles.Popup); // Update if (selectionValue != newSelectionValue) { selectionValue = newSelectionValue; isUpdated = true; } } public static bool LayoutSerializedObjectPopup(SerializedObject serializedObject, string propertyName, string[] names, ref int index) { // Get property var property = serializedObject.FindProperty(propertyName); // Get intent string intent; bool updated = false; if (names != null && names.Length > 0) { index = Mathf.Clamp(index, 0, names.Length); LayoutPopup(property.displayName, names, ref index, ref updated); intent = names[index]; } else { intent = property.stringValue; LayoutTextField(new GUIContent(property.displayName), ref intent, ref updated); } // Success if (intent != property.stringValue) { property.stringValue = intent; return true; } // Failed return false; } #endregion #region WINDOW public static void LayoutWindow(string windowTitle, Texture2D windowHeader, string windowHeaderUrl, Action windowContentLayout, ref Vector2 offset, out Vector2 size) { // Get minimum width float minWidth = WitStyles.WindowMinWidth; // Begin Header GUILayout.BeginVertical(); GUILayout.BeginHorizontal(); GUILayout.Space(WitStyles.WindowPaddingLeft); GUILayout.BeginVertical(); GUILayout.Space(WitStyles.WindowPaddingTop); // Layout header image if (windowHeader != null) { LayoutHeaderButton(windowHeader, windowHeaderUrl); } // Layout header label if (!string.IsNullOrEmpty(windowTitle)) { LayoutHeaderLabel(windowTitle); } // End Header GUILayout.EndVertical(); GUILayout.Space(WitStyles.WindowPaddingRight); GUILayout.EndHorizontal(); GUILayout.EndVertical(); // Begin Content GUILayout.BeginVertical(); offset = GUILayout.BeginScrollView(offset); GUILayout.BeginHorizontal(); GUILayout.Space(WitStyles.WindowPaddingLeft); GUILayout.BeginVertical(GUILayout.MinWidth(minWidth), GUILayout.MaxWidth(WitStyles.WindowMaxSize)); // Layout content windowContentLayout?.Invoke(); // End Content GUILayout.EndVertical(); GUILayout.Space(WitStyles.WindowPaddingRight); GUILayout.EndHorizontal(); GUILayout.Space(WitStyles.WindowPaddingBottom); GUILayout.EndScrollView(); GUILayout.EndVertical(); // Return size size = new Vector2(minWidth + WitStyles.WindowPaddingLeft + WitStyles.WindowPaddingRight + WitStyles.WindowScrollBarSize, WitStyles.WindowMinHeight); } #endregion } }