diff --git a/org.mixedrealitytoolkit.standardassets/Fonts/Selawik-Semibold-MRTKIcons.asset b/org.mixedrealitytoolkit.standardassets/Fonts/Selawik-Semibold-MRTKIcons.asset index 843ea507b..7ecd4089a 100644 --- a/org.mixedrealitytoolkit.standardassets/Fonts/Selawik-Semibold-MRTKIcons.asset +++ b/org.mixedrealitytoolkit.standardassets/Fonts/Selawik-Semibold-MRTKIcons.asset @@ -14,52 +14,8 @@ MonoBehaviour: m_EditorClassIdentifier: glyphIconsByName: entries: - - key: Icon 137 - value: 63518 - - key: Icon 136 - value: 63357 - - key: Icon 135 - value: 63323 - - key: Icon 134 - value: 63252 - - key: Icon 133 - value: 63248 - - key: Icon 132 - value: 63146 - - key: Icon 131 - value: 63130 - - key: Icon 130 - value: 63120 - - key: Icon 129 - value: 63104 - - key: Icon 128 - value: 63074 - - key: Icon 127 - value: 63033 - - key: Icon 126 - value: 63022 - - key: Icon 125 - value: 63019 - - key: Icon 124 - value: 62991 - - key: Icon 123 - value: 62984 - - key: Icon 122 - value: 62982 - - key: Icon 121 - value: 62980 - - key: Icon 120 - value: 62978 - - key: Icon 119 - value: 62950 - - key: Icon 118 - value: 62945 - - key: Icon 117 - value: 62910 - key: Icon 116 value: 62893 - - key: Icon 115 - value: 62889 - key: Icon 114 value: 62858 - key: Icon 113 @@ -70,56 +26,22 @@ MonoBehaviour: value: 62828 - key: Icon 110 value: 62822 - - key: Icon 109 - value: 62817 - key: Icon 108 value: 62815 - - key: Icon 107 - value: 62810 - - key: Icon 106 - value: 62807 - - key: Icon 105 - value: 62785 - - key: Icon 104 - value: 62727 - - key: Icon 103 - value: 62713 - - key: Icon 102 - value: 62700 - - key: Icon 101 - value: 62693 - - key: Icon 100 - value: 62679 - - key: Icon 99 - value: 62649 - key: Icon 98 value: 62632 - - key: Icon 97 - value: 62628 - key: Icon 96 value: 62624 - - key: Icon 95 - value: 62601 - - key: Icon 94 - value: 62593 - - key: Icon 93 - value: 62591 - key: Icon 92 value: 62586 - key: Icon 91 value: 62578 - key: Icon 90 value: 62555 - - key: Icon 89 - value: 62489 - key: Icon 88 value: 62476 - - key: Icon 87 - value: 62450 - key: Icon 86 value: 62433 - - key: Icon 85 - value: 62430 - key: Icon 84 value: 62427 - key: Icon 83 @@ -128,24 +50,14 @@ MonoBehaviour: value: 62329 - key: Icon 81 value: 62326 - - key: Icon 80 - value: 62318 - - key: Icon 79 - value: 62314 - - key: Icon 78 - value: 62303 - key: Icon 77 value: 62298 - - key: Icon 76 - value: 62285 - key: Icon 75 value: 62277 - key: Icon 74 value: 62274 - key: Icon 73 value: 62269 - - key: Icon 72 - value: 62267 - key: Icon 71 value: 62240 - key: Icon 70 @@ -164,78 +76,32 @@ MonoBehaviour: value: 62178 - key: Icon 63 value: 62174 - - key: Icon 62 - value: 62166 - - key: Icon 61 - value: 62135 - - key: Icon 60 - value: 62129 - - key: Icon 59 - value: 62123 - - key: Icon 58 - value: 62116 - - key: Icon 57 - value: 62101 - key: Icon 56 value: 62087 - - key: Icon 55 - value: 62061 - key: Icon 54 value: 62059 - - key: Icon 53 - value: 62037 - - key: Icon 52 - value: 62024 - key: Icon 51 value: 61972 - key: Icon 50 value: 61967 - - key: Icon 49 - value: 61942 - key: Icon 48 value: 61923 - - key: Icon 47 - value: 61919 - key: Icon 46 value: 61877 - - key: Icon 45 - value: 61866 - - key: Icon 44 - value: 61852 - key: Icon 43 value: 61835 - - key: Icon 42 - value: 61826 - - key: Icon 41 - value: 61810 - key: Icon 40 value: 61801 - - key: Icon 39 - value: 61788 - - key: Icon 38 - value: 61769 - key: Icon 37 value: 61760 - - key: Icon 36 - value: 61758 - - key: Icon 35 - value: 61752 - key: Icon 34 value: 61733 - key: Icon 33 value: 61731 - - key: Icon 32 - value: 61721 - - key: Icon 31 - value: 61717 - key: Icon 30 value: 61709 - - key: Icon 29 - value: 61706 - key: Icon 28 value: 60390 - - key: Icon 27 - value: 60235 - key: Icon 26 value: 60227 - key: Icon 25 @@ -246,18 +112,8 @@ MonoBehaviour: value: 59532 - key: Icon 22 value: 59531 - - key: Icon 21 - value: 59529 - - key: Icon 20 - value: 59527 - key: Icon 19 value: 59526 - - key: Icon 18 - value: 59525 - - key: Icon 17 - value: 59524 - - key: Icon 16 - value: 59523 - key: Icon 15 value: 59522 - key: Icon 14 @@ -266,37 +122,180 @@ MonoBehaviour: value: 59519 - key: Icon 12 value: 59518 - - key: Icon 11 - value: 59517 - - key: Icon 10 - value: 59512 - - key: Icon 9 - value: 59511 - - key: Icon 8 - value: 59508 - - key: Icon 7 - value: 59476 - - key: Icon 6 - value: 59461 - key: Icon 2 value: 59416 - key: Icon 3 value: 59440 - - key: Icon 4 - value: 59456 - key: Icon 1 value: 59407 - - key: Icon 5 + - key: Icon 142 + value: 63742 + - key: Add Favorite + value: 63252 + - key: Favorite + value: 63248 + - key: Settings + value: 63146 + - key: Send + value: 63130 + - key: Search + value: 63120 + - key: Save + value: 63104 + - key: Question Mark + value: 63033 + - key: Play + value: 62982 + - key: Play Circle + value: 62984 + - key: Brightness + value: 59456 + - key: Unpin + value: 62980 + - key: Pin + value: 62978 + - key: Devices + value: 62950 + - key: Phone + value: 62945 + - key: Person + value: 62910 + - key: Block + value: 63022 + - key: Print + value: 63019 + - key: Stop Circle + value: 63323 + - key: Bluetooth + value: 61919 + - key: Calendar value: 59460 - - key: Icon 138 + - key: Record Circle + value: 63074 + - key: Paste + value: 62166 + - key: Camera + value: 62037 + - key: Add + value: 61706 + - key: Home + value: 62593 + - key: Mute + value: 60235 + - key: Power Button + value: 62991 + - key: Link + value: 62693 + - key: Mic Off + value: 62785 + - key: Lightbulb + value: 62679 + - key: People + value: 62889 + - key: Visibility Off + value: 59512 + - key: Movie + value: 62810 + - key: Thumb Up + value: 63518 + - key: Location On + value: 62713 + - key: Refresh + value: 61758 + - key: Location Off + value: 59523 + - key: Thumb Down value: 63520 - - key: Icon 139 + - key: Videocam value: 63565 - - key: Icon 140 - value: 63594 - - key: Icon 141 + - key: Undo value: 63703 - - key: Icon 142 - value: 63742 + - key: Tag + value: 63357 + - key: Menu + value: 62817 + - key: More Vertical + value: 62807 + - key: Mail + value: 62727 + - key: Delete + value: 62285 + - key: Attach + value: 61866 + - key: Chevron Up + value: 62135 + - key: Chevron Right + value: 62129 + - key: Chevron Left + value: 62123 + - key: Chevron Down + value: 62116 + - key: Arrow Up + value: 61852 + - key: Arrow Right + value: 61826 + - key: Arrow Left + value: 61788 + - key: Arrow Down + value: 61769 + - key: More Horizontal + value: 59529 + - key: Mic + value: 59527 + - key: Apps + value: 59517 + - key: Repeat + value: 61810 + - key: Unlock + value: 59525 + - key: Lock + value: 59524 + - key: Cast + value: 62061 + - key: Visibility On + value: 59511 + - key: Erase + value: 59508 + - key: Clipboard + value: 59476 + - key: History + value: 62591 + - key: Folder + value: 62489 + - key: Edit + value: 62430 + - key: Check + value: 62101 + - key: Call End + value: 62024 + - key: List + value: 61752 + - key: Call + value: 59461 + - key: Bookmark + value: 61942 + - key: Notifications Off + value: 61721 + - key: Notifications + value: 61717 + - key: Keyboard + value: 62649 + - key: Info + value: 62628 + - key: Warning + value: 63594 + - key: Error + value: 62450 + - key: Photo + value: 62601 + - key: Dialpad + value: 62303 + - key: Close + value: 62314 + - key: Cancel + value: 62318 + - key: Cut + value: 62267 iconFontAsset: {fileID: 11400000, guid: 533bdd8d5c92b52448ee2ecf7bd828a4, type: 2} optionalEditorMaterial: {fileID: 0} + fontIconSetDefinition: {fileID: 11400000, guid: e63daff880b56ed439a2e852b6e6993a, type: 2} diff --git a/org.mixedrealitytoolkit.uxcore/Editor/Inspectors/FontIconSet/FontIconSelectorInspector.cs b/org.mixedrealitytoolkit.uxcore/Editor/Inspectors/FontIconSet/FontIconSelectorInspector.cs index 115528aeb..3a3d83296 100644 --- a/org.mixedrealitytoolkit.uxcore/Editor/Inspectors/FontIconSet/FontIconSelectorInspector.cs +++ b/org.mixedrealitytoolkit.uxcore/Editor/Inspectors/FontIconSet/FontIconSelectorInspector.cs @@ -1,4 +1,3 @@ - // Copyright (c) Mixed Reality Toolkit Contributors // Licensed under the BSD 3-Clause @@ -13,12 +12,6 @@ namespace MixedReality.Toolkit.Editor [CanEditMultipleObjects] class FontIconSelectorInspector : UnityEditor.Editor { - - private const string defaultShaderName = "TextMeshPro/Distance Field SSD"; - private float fontTileSize = 32; - - private static Material fontRenderMaterial; - private const string noFontIconsMessage = "No IconFontSet profile selected. No icons available."; private const string emptyFontIconSetMessage = "The selected IconFontSet profile has no icons defined. Please edit the IconFontSet."; @@ -29,6 +22,7 @@ class FontIconSelectorInspector : UnityEditor.Editor private GUIStyle currentButtonStyle; private bool initializedStyle = false; + private float fontTileSize = 32; /// /// A Unity event function that is called when the script component has been enabled. @@ -38,7 +32,6 @@ private void OnEnable() fontIconsProp = serializedObject.FindProperty("fontIcons"); currentIconNameProp = serializedObject.FindProperty("currentIconName"); tmProProp = serializedObject.FindProperty("textMeshProComponent"); - } /// @@ -90,7 +83,6 @@ public override void OnInspectorGUI() } private int numColumns = 4; - private Vector2 scrollAmount; public void DrawIconGrid(FontIconSelector fontIconSelector, float tileSize) @@ -101,45 +93,42 @@ public void DrawIconGrid(FontIconSelector fontIconSelector, float tileSize) scrollAmount = EditorGUILayout.BeginScrollView(scrollAmount, GUILayout.MaxHeight(128), GUILayout.MinHeight(64)); EditorGUILayout.BeginHorizontal(); - + foreach (string iconName in fontIconSet.GlyphIconsByName.Keys) { uint unicodeValue = fontIconSet.GlyphIconsByName[iconName]; - bool selected = (iconName == fontIconSelector.CurrentIconName); + if (column >= numColumns) { column = 0; EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); } + if (GUILayout.Button(" ", - GUILayout.MinHeight(tileSize), - GUILayout.MaxHeight(tileSize), - GUILayout.MinWidth(tileSize), - GUILayout.MaxWidth(tileSize))) + GUILayout.Height(tileSize), + GUILayout.Width(tileSize))) { - Undo.RecordObjects(new UnityEngine.Object[]{fontIconSelector, fontIconSelector.TextMeshProComponent}, "Changed icon"); + Undo.RecordObjects(new Object[] { fontIconSelector, fontIconSelector.TextMeshProComponent }, "Changed icon"); fontIconSelector.CurrentIconName = iconName; PrefabUtility.RecordPrefabInstancePropertyModifications(fontIconSelector); PrefabUtility.RecordPrefabInstancePropertyModifications(fontIconSelector.TextMeshProComponent); } + Rect textureRect = GUILayoutUtility.GetLastRect(); if (textureRect.yMin + 8 < scrollAmount.y || textureRect.yMax - 8 > scrollAmount.y + 128) { unicodeValue = 0; } - textureRect.width = tileSize; textureRect.height = tileSize; - FontIconSetInspector.EditorDrawTMPGlyph(textureRect, unicodeValue, fontAsset, selected); + FontIconSetInspector.EditorDrawTMPGlyph(textureRect, unicodeValue, fontAsset, iconName == fontIconSelector.CurrentIconName); + column++; } - if (column > 0) - { - EditorGUILayout.EndHorizontal(); - } - + EditorGUILayout.EndHorizontal(); + if (Event.current.type == EventType.Repaint) { float editorWindowWidth = GUILayoutUtility.GetLastRect().width; diff --git a/org.mixedrealitytoolkit.uxcore/Editor/Inspectors/FontIconSet/FontIconSetInspector.cs b/org.mixedrealitytoolkit.uxcore/Editor/Inspectors/FontIconSet/FontIconSetInspector.cs index f500e5882..bb53b8f8f 100644 --- a/org.mixedrealitytoolkit.uxcore/Editor/Inspectors/FontIconSet/FontIconSetInspector.cs +++ b/org.mixedrealitytoolkit.uxcore/Editor/Inspectors/FontIconSet/FontIconSetInspector.cs @@ -1,4 +1,3 @@ - // Copyright (c) Mixed Reality Toolkit Contributors // Licensed under the BSD 3-Clause @@ -23,35 +22,25 @@ public class FontIconSetInspector : UnityEditor.Editor private const string AvailableIconsFoldoutKey = "MixedRealityToolkit.FontIconSet.ShowAvailableIcons"; private const string SelectedIconsFoldoutKey = "MixedRealityToolkit.FontIconSet.ShowSelectedIcons"; - private const string defaultShaderName = "TextMeshPro/Distance Field SSD"; // Only used for presentation in inspector, not at runtime. - private const int glyphDrawSize = 75; - private const int buttonWidth = 75; - private const int buttonHeight = 90; - private const int maxButtonsPerColumn = 6; - - private static Material fontRenderMaterial; + private const string DefaultShaderName = "TextMeshPro/Distance Field SSD"; // Only used for presentation in inspector, not at runtime. + private const int GlyphDrawSize = 75; + private const int ButtonDimension = 75; + private const int MaxButtonsPerColumn = 6; - private const string noIconFontMessage = "No icon font asset selected. Icon fonts will be unavailable."; - private const string downloadIconFontMessage = "For instructions on how to install the HoloLens icon font asset, click the button below."; - private const string hololensIconFontUrl = "https://docs.microsoft.com/windows/mixed-reality/mrtk-unity/features/ux-building-blocks/button"; - private const string mdl2IconFontName = "holomdl2"; - private const string textMeshProMenuItem = "Window/TextMeshPro/Font Asset Creator"; + private const string NoIconFontMessage = "No icon font asset selected. Icon fonts will be unavailable."; + private const string DownloadIconFontMessage = "For instructions on how to install the HoloLens icon font asset, click the button below."; + private const string HoloLensIconFontUrl = "https://docs.microsoft.com/windows/mixed-reality/mrtk-unity/features/ux-building-blocks/button"; + private const string MDL2IconFontName = "holomdl2"; + private const string TextMeshProMenuItem = "Window/TextMeshPro/Font Asset Creator"; private SerializedProperty iconFontAssetProp = null; + private SerializedProperty fontIconSetDefinitionProp = null; + private bool anyInvalidName = false; - private class IconEntry - { - public string Name; - public uint UnicodeValue; - - public IconEntry(string name, uint unicodeValue) - { - Name = name; - UnicodeValue = unicodeValue; - } - } - - private List iconEntries = new List(); + private SortedList iconEntries = new SortedList(); + private List validNames = new List(); + private List availableNames = new List(); + private string[] availableNamesArray = Array.Empty(); /// /// A Unity event function that is called when the script component has been enabled. @@ -60,11 +49,12 @@ private void OnEnable() { FontIconSet fontIconSet = (FontIconSet)target; iconFontAssetProp = serializedObject.FindProperty("iconFontAsset"); + fontIconSetDefinitionProp = serializedObject.FindProperty("fontIconSetDefinition"); // Make a list out of dictionary to avoid changing order while editing names foreach (KeyValuePair kv in fontIconSet.GlyphIconsByName) { - iconEntries.Add(new IconEntry(kv.Key, kv.Value)); + iconEntries.Add(kv.Value, kv.Key); } } @@ -73,39 +63,38 @@ private void OnEnable() /// public override void OnInspectorGUI() { - FontIconSet fontIconSet = (FontIconSet)target; - bool showGlyphIconFoldout = SessionState.GetBool(ShowGlyphIconsFoldoutKey, false); bool showAvailableIcons = SessionState.GetBool(AvailableIconsFoldoutKey, true); bool showSelectedIcons = SessionState.GetBool(SelectedIconsFoldoutKey, true); serializedObject.Update(); - showGlyphIconFoldout = EditorGUILayout.BeginFoldoutHeaderGroup(showGlyphIconFoldout, "Font Icons"); - EditorGUILayout.EndFoldoutHeaderGroup(); - + showGlyphIconFoldout = EditorGUILayout.Foldout(showGlyphIconFoldout, "Font Icons", true); if (showGlyphIconFoldout) { EditorGUILayout.PropertyField(iconFontAssetProp); + EditorGUILayout.PropertyField(fontIconSetDefinitionProp); if (iconFontAssetProp.objectReferenceValue == null) { - EditorGUILayout.HelpBox(noIconFontMessage, MessageType.Warning); - if (!CheckIfHololensIconFontExists()) + EditorGUILayout.HelpBox(NoIconFontMessage, MessageType.Warning); + if (!CheckIfHoloLensIconFontExists()) { - EditorGUILayout.HelpBox(downloadIconFontMessage, MessageType.Info); + EditorGUILayout.HelpBox(DownloadIconFontMessage, MessageType.Info); if (GUILayout.Button("View Font Asset Icons Documentation")) { - EditorApplication.ExecuteMenuItem(textMeshProMenuItem); - Application.OpenURL(hololensIconFontUrl); + EditorApplication.ExecuteMenuItem(TextMeshProMenuItem); + Application.OpenURL(HoloLensIconFontUrl); } } } else { - TMP_FontAsset fontAsset = (TMP_FontAsset)iconFontAssetProp.objectReferenceValue; + FontIconSet fontIconSet = target as FontIconSet; + TMP_FontAsset fontAsset = iconFontAssetProp.objectReferenceValue as TMP_FontAsset; + FontIconSetDefinition setDefinition = fontIconSetDefinitionProp.objectReferenceValue as FontIconSetDefinition; - showAvailableIcons = EditorGUILayout.BeginFoldoutHeaderGroup(showAvailableIcons, "Available Icons"); + showAvailableIcons = EditorGUILayout.Foldout(showAvailableIcons, "Available Icons", true); if (showAvailableIcons) { if (fontAsset.characterTable.Count == 0) @@ -113,7 +102,7 @@ public override void OnInspectorGUI() EditorGUILayout.HelpBox("No icons are available in this font. The font may be configured incorrectly.", MessageType.Warning); if (GUILayout.Button("Open Font Editor")) { - Selection.activeObject = fontIconSet.IconFontAsset; + Selection.activeObject = fontAsset; } } else @@ -121,55 +110,122 @@ public override void OnInspectorGUI() EditorGUILayout.HelpBox("Click an icon to add it to your selected icons.", MessageType.Info); if (GUILayout.Button("Open Font Editor")) { - Selection.activeObject = fontIconSet.IconFontAsset; + Selection.activeObject = fontAsset; } - DrawFontGlyphsGrid(fontIconSet, maxButtonsPerColumn); + DrawFontGlyphsGrid(fontAsset, fontIconSet, MaxButtonsPerColumn); } EditorGUILayout.Space(); } - EditorGUILayout.EndFoldoutHeaderGroup(); - showSelectedIcons = EditorGUILayout.BeginFoldoutHeaderGroup(showSelectedIcons, "Selected Icons"); + showSelectedIcons = EditorGUILayout.Foldout(showSelectedIcons, "Selected Icons", true); if (showSelectedIcons) { if (fontIconSet.GlyphIconsByName.Count > 0) { EditorGUILayout.HelpBox("These icons will appear in the button config helper inspector. Click an icon to remove it from this list.", MessageType.Info); - using (new EditorGUILayout.VerticalScope()) + if (fontIconSetDefinitionProp.objectReferenceValue == null) + { + EditorGUILayout.HelpBox("It's recommended to use a Font Icon Set Definition to ensure consistent icon names across icon sets.", MessageType.Warning); + } + else + { + if (anyInvalidName) + { + EditorGUILayout.HelpBox("Icon names highlighted yellow are not present in the selected Font Icon Set Definition and should be updated.", MessageType.Warning); + anyInvalidName = false; + } + + validNames.Clear(); + availableNames.Clear(); + // Reserve space for the current icon's name + availableNames.Add(string.Empty); + foreach (string name in setDefinition.IconNames) + { + validNames.Add(name); + if (!iconEntries.ContainsValue(name)) + { + availableNames.Add(name); + } + } + + availableNamesArray = availableNames.ToArray(); + } + + int column = 0; + string iconToRemove = null; + string iconToRename = null; + EditorGUILayout.BeginHorizontal(); + foreach (KeyValuePair iconEntry in iconEntries) { - string iconToRemove = null; - foreach (IconEntry iconEntry in iconEntries) + if (column >= MaxButtonsPerColumn) + { + column = 0; + EditorGUILayout.EndHorizontal(); + EditorGUILayout.BeginHorizontal(); + } + + EditorGUILayout.BeginVertical(GUILayout.Width(ButtonDimension)); + + if (GUILayout.Button(" ", + GUILayout.Height(ButtonDimension), + GUILayout.MaxWidth(ButtonDimension))) + { + iconToRemove = iconEntry.Value; + } + + Rect textureRect = GUILayoutUtility.GetLastRect(); + textureRect.width = GlyphDrawSize; + textureRect.height = GlyphDrawSize; + EditorDrawTMPGlyph(textureRect, iconEntry.Key, fontAsset); + + if (fontIconSetDefinitionProp.objectReferenceValue != null) { - using (new EditorGUILayout.HorizontalScope()) + // Place the current icon's name in the array + availableNamesArray[0] = iconEntry.Value; + + using (var check = new EditorGUI.ChangeCheckScope()) { - if (GUILayout.Button(" ", GUILayout.MinHeight(buttonHeight), GUILayout.MaxHeight(buttonHeight), GUILayout.MaxWidth(buttonWidth))) + // If the currently selected name isn't in our icon set map names, highlight the popup + Color oldColor = GUI.backgroundColor; + if (!validNames.Contains(iconEntry.Value)) { - iconToRemove = iconEntry.Name; + GUI.backgroundColor = Color.yellow; + anyInvalidName = true; } - Rect textureRect = GUILayoutUtility.GetLastRect(); - textureRect.width = glyphDrawSize; - textureRect.height = glyphDrawSize; - EditorDrawTMPGlyph(textureRect, iconEntry.UnicodeValue, fontAsset); - - string currentName = iconEntry.Name; - currentName = EditorGUILayout.TextField(currentName); - if (currentName != iconEntry.Name) + int selected = EditorGUILayout.Popup(string.Empty, 0, availableNamesArray, GUILayout.MaxWidth(ButtonDimension)); + if (check.changed) { - UpdateIconName(fontIconSet, iconEntry.Name, currentName); + iconToRename = availableNamesArray[selected]; + iconToRemove = iconEntry.Value; } - EditorGUILayout.Space(); + GUI.backgroundColor = oldColor; } - - EditorGUILayout.Space(); } - - if (iconToRemove != null) + else { - RemoveIcon(fontIconSet, iconToRemove); + string currentName = EditorGUILayout.TextField(iconEntry.Value); + if (currentName != iconEntry.Value) + { + iconToRename = currentName; + iconToRemove = iconEntry.Value; + } } + EditorGUILayout.EndVertical(); + + column++; + } + EditorGUILayout.EndHorizontal(); + + if (iconToRename != null) + { + UpdateIconName(fontIconSet, iconToRemove, iconToRename); + } + else if (iconToRemove != null) + { + RemoveIcon(fontIconSet, iconToRemove); } } else @@ -177,8 +233,6 @@ public override void OnInspectorGUI() EditorGUILayout.HelpBox("No icons added yet. Click available icons to add.", MessageType.Info); } } - - EditorGUILayout.EndFoldoutHeaderGroup(); } } @@ -194,9 +248,20 @@ public override void OnInspectorGUI() /// /// The set of font glyphs to draw. /// The number of buttons per column. + [Obsolete("This method has been removed.")] public void DrawFontGlyphsGrid(FontIconSet fontIconSet, int maxButtonsPerColumn) { - TMP_FontAsset fontAsset = fontIconSet.IconFontAsset; + DrawFontGlyphsGrid(fontIconSet.IconFontAsset, fontIconSet, maxButtonsPerColumn); + } + + /// + /// Draw a grid of buttons than can be clicked to select a glyph from a set up glyphs. + /// + /// The font asset containing the glyphs. + /// The set of font glyphs to draw. + /// The number of buttons per column. + private void DrawFontGlyphsGrid(TMP_FontAsset fontAsset, FontIconSet fontIconSet, int maxButtonsPerColumn) + { int column = 0; EditorGUILayout.BeginHorizontal(); for (int i = 0; i < fontAsset.characterTable.Count; i++) @@ -207,79 +272,65 @@ public void DrawFontGlyphsGrid(FontIconSet fontIconSet, int maxButtonsPerColumn) EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); } - if (GUILayout.Button(" ", - GUILayout.MinHeight(buttonHeight), - GUILayout.MaxHeight(buttonHeight), - GUILayout.MaxWidth(buttonWidth))) + + using (new EditorGUI.DisabledGroupScope(fontIconSet.GlyphIconsByName.ContainsValue(fontAsset.characterTable[i].unicode))) { - AddIcon(fontIconSet, fontAsset.characterTable[i].unicode); - EditorUtility.SetDirty(target); + if (GUILayout.Button(" ", + GUILayout.Height(ButtonDimension), + GUILayout.MaxWidth(ButtonDimension))) + { + AddIcon(fontIconSet, fontAsset.characterTable[i].unicode); + EditorUtility.SetDirty(target); + } + + Rect textureRect = GUILayoutUtility.GetLastRect(); + textureRect.width = GlyphDrawSize; + textureRect.height = GlyphDrawSize; + EditorDrawTMPGlyph(textureRect, fontAsset, fontAsset.characterTable[i]); } - Rect textureRect = GUILayoutUtility.GetLastRect(); - textureRect.width = glyphDrawSize; - textureRect.height = glyphDrawSize; - EditorDrawTMPGlyph(textureRect, fontAsset, fontAsset.characterTable[i]); - column++; - } - if (column > 0) - { - EditorGUILayout.EndHorizontal(); + column++; } + EditorGUILayout.EndHorizontal(); } private bool AddIcon(FontIconSet fontIconSet, uint unicodeValue) { - string name = "Icon " + (iconEntries.Count + 1); + string name = $"Icon {unicodeValue}"; if (fontIconSet.AddIcon(name, unicodeValue)) { - iconEntries.Add(new IconEntry(name, unicodeValue)); + iconEntries.Add(unicodeValue, name); + EditorUtility.SetDirty(fontIconSet); + return true; } - return true; + return false; } private bool RemoveIcon(FontIconSet fontIconSet, string iconName) { - bool removed = fontIconSet.RemoveIcon(iconName); - if (removed) - { - if (FindIconIndexByName(iconName, out int index)) - { - iconEntries.RemoveAt(index); - } - } - return removed; - } - - private bool FindIconIndexByName(string iconName, out int outIndex) - { - for (outIndex = 0; outIndex < iconEntries.Count; outIndex++) + if (fontIconSet.TryGetGlyphIcon(iconName, out uint unicodeValue) && fontIconSet.RemoveIcon(iconName)) { - if (iconEntries[outIndex].Name == iconName) - { - return true; - } + iconEntries.Remove(unicodeValue); + EditorUtility.SetDirty(fontIconSet); + return true; } - outIndex = -1; return false; } private void UpdateIconName(FontIconSet fontIconSet, string oldName, string newName) { - if (fontIconSet.UpdateIconName(oldName, newName)) + if (fontIconSet.UpdateIconName(oldName, newName) && fontIconSet.TryGetGlyphIcon(newName, out uint unicodeValue)) { - if (FindIconIndexByName(oldName, out int index)) - { - iconEntries[index].Name = newName; - } + iconEntries[unicodeValue] = newName; + EditorUtility.SetDirty(fontIconSet); } } - private bool CheckIfHololensIconFontExists() + private bool CheckIfHoloLensIconFontExists() { - foreach (string guid in AssetDatabase.FindAssets($"t:{typeof(UnityEngine.Font).Name}")) + foreach (string guid in AssetDatabase.FindAssets($"t:{nameof(Font)}")) { - if (AssetDatabase.GUIDToAssetPath(guid).Contains(mdl2IconFontName)) + if (AssetDatabase.GUIDToAssetPath(guid).Contains(MDL2IconFontName)) { return true; } @@ -307,7 +358,7 @@ public static void EditorDrawTMPGlyph(Rect glyphRect, TMP_FontAsset fontAsset, T { try { - float iconSizeMultiplier = 0.625f; + const float IconSizeMultiplier = 0.625f; // Get a reference to the Glyph Table int glyphIndex = (int)character.glyphIndex; @@ -325,20 +376,12 @@ public static void EditorDrawTMPGlyph(Rect glyphRect, TMP_FontAsset fontAsset, T { if (fontRenderMaterial == null) { - fontRenderMaterial = new Material(Shader.Find(defaultShaderName)); + fontRenderMaterial = new Material(Shader.Find(DefaultShaderName)); } Material glyphMaterial = fontRenderMaterial; glyphMaterial.mainTexture = atlasTexture; - - if (selected) - { - glyphMaterial.SetColor("_Color", Color.green); - } - else - { - glyphMaterial.SetColor("_Color", Color.white); - } + glyphMaterial.SetColor("_FaceColor", selected ? Color.green : Color.white); int glyphOriginX = glyph.glyphRect.x; int glyphOriginY = glyph.glyphRect.y; @@ -346,13 +389,13 @@ public static void EditorDrawTMPGlyph(Rect glyphRect, TMP_FontAsset fontAsset, T int glyphHeight = glyph.glyphRect.height; float normalizedHeight = fontAsset.faceInfo.ascentLine - fontAsset.faceInfo.descentLine; - float scale = Mathf.Min(glyphRect.width, glyphRect.height) / normalizedHeight * iconSizeMultiplier; + float scale = Mathf.Min(glyphRect.width, glyphRect.height) / normalizedHeight * IconSizeMultiplier; // Compute the normalized texture coordinates Rect texCoords = new Rect((float)glyphOriginX / atlasTexture.width, (float)glyphOriginY / atlasTexture.height, (float)glyphWidth / atlasTexture.width, (float)glyphHeight / atlasTexture.height); - glyphWidth = (int)Mathf.Min(glyphDrawSize, glyphWidth * scale); - glyphHeight = (int)Mathf.Min(glyphDrawSize, glyphHeight * scale); + glyphWidth = (int)Mathf.Min(GlyphDrawSize, glyphWidth * scale); + glyphHeight = (int)Mathf.Min(GlyphDrawSize, glyphHeight * scale); glyphRect.x += (glyphRect.width - glyphWidth) / 2; glyphRect.y += (glyphRect.height - glyphHeight) / 2; diff --git a/org.mixedrealitytoolkit.uxcore/FontIcons/FontIconSelector.cs b/org.mixedrealitytoolkit.uxcore/FontIcons/FontIconSelector.cs index 54e81f646..19fee1a50 100644 --- a/org.mixedrealitytoolkit.uxcore/FontIcons/FontIconSelector.cs +++ b/org.mixedrealitytoolkit.uxcore/FontIcons/FontIconSelector.cs @@ -1,7 +1,7 @@ // Copyright (c) Mixed Reality Toolkit Contributors // Licensed under the BSD 3-Clause -using System; +using System.Collections.Generic; using TMPro; using UnityEngine; @@ -11,7 +11,7 @@ namespace MixedReality.Toolkit.UX /// Allows the user to select a specific icon for display via a Unity text component. /// [AddComponentMenu("MRTK/UX/Font Icon Selector")] - public class FontIconSelector : MonoBehaviour + public class FontIconSelector : MonoBehaviour, ISerializationCallbackReceiver { [Tooltip("The FontIconSet that contains the icons available for use.")] [SerializeField] @@ -52,6 +52,11 @@ public string CurrentIconName /// public TMP_Text TextMeshProComponent => textMeshProComponent; + // A temporary variable used to migrate instances of FontIconSelector to use new FontIconSetDefinition names. + // TODO: Remove this after some time to ensure users have successfully migrated. + [SerializeField, HideInInspector] + private bool migratedSuccessfully = false; + /// /// A Unity event function that is called when an enabled script instance is being loaded. /// @@ -83,12 +88,32 @@ private void OnValidate() private void SetIcon(string newIconName) { - if (fontIcons != null && textMeshProComponent != null) + if (fontIcons != null && textMeshProComponent != null && fontIcons.TryGetGlyphIcon(newIconName, out uint unicodeValue)) + { + currentIconName = newIconName; + textMeshProComponent.text = FontIconSet.ConvertUnicodeToHexString(unicodeValue); + } + } + + void ISerializationCallbackReceiver.OnBeforeSerialize() { } + + void ISerializationCallbackReceiver.OnAfterDeserialize() + { + if (!migratedSuccessfully && fontIcons != null && fontIcons.FontIconSetDefinition != null && textMeshProComponent != null) { - if (fontIcons.TryGetGlyphIcon(newIconName, out uint unicodeValue)) + uint unicodeValue = FontIconSet.ConvertHexStringToUnicode(textMeshProComponent.text); + foreach (KeyValuePair kv in fontIcons.GlyphIconsByName) { - currentIconName = newIconName; - textMeshProComponent.text = FontIconSet.ConvertUnicodeToHexString(unicodeValue); + if (kv.Value == unicodeValue) + { + if (currentIconName != kv.Key) + { + Debug.Log($"[{nameof(FontIconSelector)}] Successfully migrated icon: \"{currentIconName}\" to \"{kv.Key}\"", this); + currentIconName = kv.Key; + migratedSuccessfully = true; + } + break; + } } } } diff --git a/org.mixedrealitytoolkit.uxcore/FontIcons/FontIconSet.cs b/org.mixedrealitytoolkit.uxcore/FontIcons/FontIconSet.cs index 730ad7324..0948b64f6 100644 --- a/org.mixedrealitytoolkit.uxcore/FontIcons/FontIconSet.cs +++ b/org.mixedrealitytoolkit.uxcore/FontIcons/FontIconSet.cs @@ -30,8 +30,8 @@ public class FontIconSet : ScriptableObject /// public SerializableDictionary GlyphIconsByName => glyphIconsByName; - [Tooltip("Any TextMeshPro Font Asset that contains the desired icons as glyphs that map to Unicode character values.")] [SerializeField] + [Tooltip("Any TextMeshPro Font Asset that contains the desired icons as glyphs that map to Unicode character values.")] private TMP_FontAsset iconFontAsset = null; /// @@ -39,8 +39,8 @@ public class FontIconSet : ScriptableObject /// public TMP_FontAsset IconFontAsset => iconFontAsset; - [Tooltip("Optional material to use for rendering glyphs in editor.")] [SerializeField] + [Tooltip("Optional material to use for rendering glyphs in editor.")] private Material optionalEditorMaterial; /// @@ -48,6 +48,15 @@ public class FontIconSet : ScriptableObject /// public Material OptionalEditorMaterial => optionalEditorMaterial; + [SerializeField] + [Tooltip("Optional definition to provide consistent icon names.")] + private FontIconSetDefinition fontIconSetDefinition; + + /// + /// Optional definition to provide consistent icon names. + /// + public FontIconSetDefinition FontIconSetDefinition => fontIconSetDefinition; + /// /// Try to get a glyph icon's unicode value by name. /// @@ -56,7 +65,6 @@ public class FontIconSet : ScriptableObject /// if icon name found, otherwise . public bool TryGetGlyphIcon(string iconName, out uint unicodeValue) { - unicodeValue = 0; return glyphIconsByName.TryGetValue(iconName, out unicodeValue); } @@ -68,15 +76,7 @@ public bool TryGetGlyphIcon(string iconName, out uint unicodeValue) /// Whether it was able to add this icon. public bool AddIcon(string name, uint unicodeValue) { - if (glyphIconsByName.ContainsValue(unicodeValue)) - { - return false; - } - else - { - glyphIconsByName[name] = unicodeValue; - return true; - } + return !glyphIconsByName.ContainsValue(unicodeValue) && glyphIconsByName.TryAdd(name, unicodeValue); } /// @@ -86,15 +86,7 @@ public bool AddIcon(string name, uint unicodeValue) /// Whether it was able to find the name and remove it. public bool RemoveIcon(string iconName) { - if (glyphIconsByName.ContainsKey(iconName)) - { - glyphIconsByName.Remove(iconName); - return true; - } - else - { - return false; - } + return glyphIconsByName.Remove(iconName); } /// @@ -109,16 +101,7 @@ public bool RemoveIcon(string iconName) /// if it was able to find and update the name. public bool UpdateIconName(string oldName, string newName) { - if (glyphIconsByName.ContainsKey(oldName) && !glyphIconsByName.ContainsKey(newName)) - { - glyphIconsByName[newName] = glyphIconsByName[oldName]; - glyphIconsByName.Remove(oldName); - return true; - } - else - { - return false; - } + return glyphIconsByName.TryGetValue(oldName, out uint unicodeValue) && glyphIconsByName.TryAdd(newName, unicodeValue) && glyphIconsByName.Remove(oldName); } /// diff --git a/org.mixedrealitytoolkit.uxcore/FontIcons/FontIconSetDefinition.cs b/org.mixedrealitytoolkit.uxcore/FontIcons/FontIconSetDefinition.cs new file mode 100644 index 000000000..8688d2f8a --- /dev/null +++ b/org.mixedrealitytoolkit.uxcore/FontIcons/FontIconSetDefinition.cs @@ -0,0 +1,20 @@ +// Copyright (c) Mixed Reality Toolkit Contributors +// Licensed under the BSD 3-Clause + +using System.Collections.Generic; +using UnityEngine; + +namespace MixedReality.Toolkit.UX +{ + [CreateAssetMenu(fileName = "FontIconSetDefinition", menuName = "MRTK/UX/Font Icon Set Definition")] + public class FontIconSetDefinition : ScriptableObject + { + [SerializeField] + private string[] iconNames; + + /// + /// The list of icon names defined by this asset. + /// + public IReadOnlyList IconNames => iconNames; + } +} diff --git a/org.mixedrealitytoolkit.uxcore/FontIcons/FontIconSetDefinition.cs.meta b/org.mixedrealitytoolkit.uxcore/FontIcons/FontIconSetDefinition.cs.meta new file mode 100644 index 000000000..d2f677246 --- /dev/null +++ b/org.mixedrealitytoolkit.uxcore/FontIcons/FontIconSetDefinition.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 073dfa6d3114b214d8a2d2954d572301 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/org.mixedrealitytoolkit.uxcore/FontIcons/MRTKFontIconSetDefinition.asset b/org.mixedrealitytoolkit.uxcore/FontIcons/MRTKFontIconSetDefinition.asset new file mode 100644 index 000000000..2ac6c526d --- /dev/null +++ b/org.mixedrealitytoolkit.uxcore/FontIcons/MRTKFontIconSetDefinition.asset @@ -0,0 +1,106 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!114 &11400000 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 073dfa6d3114b214d8a2d2954d572301, type: 3} + m_Name: MRTKFontIconSetDefinition + m_EditorClassIdentifier: + iconNames: + - Wifi + - Bluetooth + - Brightness + - Airplane + - Settings + - People + - Pin + - Bookmark + - Stop Circle + - Add Favorite + - Favorite + - Send + - Search + - Save + - Record Circle + - Question Mark + - Block + - Print + - Power Button + - Play Circle + - Play + - Unpin + - Devices + - Phone + - Person + - Home + - Zoom + - Calendar + - Camera + - Paste + - Phone + - Add + - Mail + - Mute + - Mic Off + - Copy + - Visibility On + - Visibility Off + - Link + - Attach + - Lightbulb + - Movie + - Thumb Up + - Thumb Down + - Thumb Down + - Videocam + - Location On + - Location Off + - Mic + - Undo + - Apps + - Tag + - Arrow Left + - Arrow Right + - Arrow Up + - Arrow Down + - Refresh + - Menu + - More Vertical + - More Horizontal + - Delete + - Chevron Left + - Chevron Right + - Chevron Up + - Chevron Down + - Lock + - Unlock + - Repeat + - Cast + - Clipboard + - Erase + - History + - Notifications + - Notifications Off + - List + - Call + - Call End + - Check + - Edit + - Folder + - Alarm Off + - Warning + - Info + - Error + - Keyboard + - Cancel + - Dialpad + - Photo + - Save As + - Close + - Cut diff --git a/org.mixedrealitytoolkit.uxcore/FontIcons/MRTKFontIconSetDefinition.asset.meta b/org.mixedrealitytoolkit.uxcore/FontIcons/MRTKFontIconSetDefinition.asset.meta new file mode 100644 index 000000000..d0756e855 --- /dev/null +++ b/org.mixedrealitytoolkit.uxcore/FontIcons/MRTKFontIconSetDefinition.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e63daff880b56ed439a2e852b6e6993a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: