diff --git a/Client/Assets/InputGlyphDatabase.asset b/Client/Assets/InputGlyphDatabase.asset new file mode 100644 index 0000000..6197176 --- /dev/null +++ b/Client/Assets/InputGlyphDatabase.asset @@ -0,0 +1,16 @@ +%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: 53ed017cef844d11842ba16553c6391d, type: 3} + m_Name: InputGlyphDatabase + m_EditorClassIdentifier: + tables: [] + placeholderSprite: {fileID: 0} diff --git a/Client/Assets/InputGlyphDatabase.asset.meta b/Client/Assets/InputGlyphDatabase.asset.meta new file mode 100644 index 0000000..bbe948d --- /dev/null +++ b/Client/Assets/InputGlyphDatabase.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e43c1733d8e85a5419c0754bbd597e3b +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Client/Assets/Scripts/CustomeModule/InputGlyph/Editor/InputGlyphDatabaseEditor.cs b/Client/Assets/Scripts/CustomeModule/InputGlyph/Editor/InputGlyphDatabaseEditor.cs index c10b7fb..734a534 100644 --- a/Client/Assets/Scripts/CustomeModule/InputGlyph/Editor/InputGlyphDatabaseEditor.cs +++ b/Client/Assets/Scripts/CustomeModule/InputGlyph/Editor/InputGlyphDatabaseEditor.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using UnityEditor; -using UnityEditorInternal; using UnityEngine; using UnityEngine.InputSystem; @@ -19,15 +18,22 @@ public sealed class InputGlyphDatabaseEditor : Editor private const float PreviewSize = 52f; private const float ListPreviewSize = 56f; private const int MaxValidationIssuesToShow = 10; + private const int DefaultEntriesPerPage = 50; private static readonly string[] DefaultTableNames = { "Keyboard", "Xbox", "PlayStation", "Other" }; + private static readonly int[] EntriesPerPageOptions = { 25, 50, 100, 200 }; + private static readonly string[] EntriesPerPageLabels = { "25 / 页", "50 / 页", "100 / 页", "200 / 页" }; private sealed class TableEditorState { public Sprite PendingSprite; public bool ShowValidation = true; - public ReorderableList EntriesList; - public string EntriesPropertyPath; + public string EntrySearch = string.Empty; + public int CurrentPage; + public int EntriesPerPage = DefaultEntriesPerPage; + public readonly List FilteredEntryIndices = new(); + public string CachedSearch = string.Empty; + public int CachedEntryCount = -1; } private readonly List _tableStates = new(); @@ -92,6 +98,7 @@ public sealed class InputGlyphDatabaseEditor : Editor if (serializedObject.ApplyModifiedProperties()) { + InvalidateAllEntryViews(); NotifyDatabaseChanged(); } } @@ -103,6 +110,7 @@ public sealed class InputGlyphDatabaseEditor : Editor if (GUILayout.Button("Save Asset", EditorStyles.toolbarButton, GUILayout.Width(90f))) { serializedObject.ApplyModifiedProperties(); + InvalidateAllEntryViews(); NotifyDatabaseChanged(true); } @@ -217,13 +225,13 @@ public sealed class InputGlyphDatabaseEditor : Editor private void DrawDatabaseValidationPanel() { List issues = CollectDatabaseValidationIssues(); - string title = issues.Count == 0 ? "Database Validation" : $"Database Validation ({issues.Count})"; + string title = issues.Count == 0 ? "数据库校验" : $"数据库校验 ({issues.Count})"; _showDatabaseValidation = EditorGUILayout.BeginFoldoutHeaderGroup(_showDatabaseValidation, title); if (_showDatabaseValidation) { if (issues.Count == 0) { - EditorGUILayout.HelpBox("No database-level issues found.", MessageType.Info); + EditorGUILayout.HelpBox("未发现数据库级别的问题。", MessageType.Info); } else { @@ -314,13 +322,13 @@ public sealed class InputGlyphDatabaseEditor : Editor private void DrawTableValidationPanel(int tableIndex, TableEditorState state) { List issues = CollectTableValidationIssues(tableIndex); - string title = issues.Count == 0 ? "Validation" : $"Validation ({issues.Count})"; + string title = issues.Count == 0 ? "校验结果" : $"校验结果 ({issues.Count})"; state.ShowValidation = EditorGUILayout.BeginFoldoutHeaderGroup(state.ShowValidation, title); if (state.ShowValidation) { if (issues.Count == 0) { - EditorGUILayout.HelpBox("No table-level issues found.", MessageType.Info); + EditorGUILayout.HelpBox("未发现当前表的问题。", MessageType.Info); } else { @@ -341,120 +349,198 @@ public sealed class InputGlyphDatabaseEditor : Editor if (issues.Count > visibleCount) { - EditorGUILayout.HelpBox($"{issues.Count - visibleCount} more issues are hidden to keep the inspector readable.", MessageType.None); + EditorGUILayout.HelpBox($"还有 {issues.Count - visibleCount} 条问题未展开显示,以保持检视面板可读。", MessageType.None); } } private void DrawEntriesList(int tableIndex, SerializedProperty entriesProperty) - { - EditorGUILayout.LabelField("Entries", EditorStyles.boldLabel); - ReorderableList list = GetEntriesList(tableIndex, entriesProperty); - list.DoLayoutList(); - } - private ReorderableList GetEntriesList(int tableIndex, SerializedProperty entriesProperty) { TableEditorState state = _tableStates[tableIndex]; - if (state.EntriesList != null && state.EntriesPropertyPath == entriesProperty.propertyPath) + EditorGUILayout.LabelField("Entries", EditorStyles.boldLabel); + DrawEntriesControls(state, entriesProperty.arraySize); + + if (entriesProperty.arraySize == 0) { - return state.EntriesList; + EditorGUILayout.HelpBox("当前表里还没有任何条目。", MessageType.Info); + return; } - ReorderableList list = new ReorderableList(serializedObject, entriesProperty, true, true, false, true); - state.EntriesList = list; - state.EntriesPropertyPath = entriesProperty.propertyPath; - - list.drawHeaderCallback = rect => + List filteredIndices = GetFilteredEntryIndices(tableIndex, entriesProperty, state); + if (filteredIndices.Count == 0) { - EditorGUI.LabelField(rect, $"Entries ({entriesProperty.arraySize}) - drag to reorder"); - }; + EditorGUILayout.HelpBox("没有匹配搜索条件的条目。", MessageType.Info); + return; + } - list.elementHeightCallback = index => + int entriesPerPage = Mathf.Max(1, state.EntriesPerPage); + int totalPages = Mathf.Max(1, Mathf.CeilToInt(filteredIndices.Count / (float)entriesPerPage)); + state.CurrentPage = Mathf.Clamp(state.CurrentPage, 0, totalPages - 1); + + DrawEntriesPagination(state, filteredIndices.Count, entriesProperty.arraySize); + EditorGUILayout.Space(4f); + + int startIndex = state.CurrentPage * entriesPerPage; + int endIndex = Mathf.Min(startIndex + entriesPerPage, filteredIndices.Count); + for (int i = startIndex; i < endIndex; i++) { - if (index < 0 || index >= entriesProperty.arraySize) - { - return EditorGUIUtility.singleLineHeight + 8f; - } + int entryIndex = filteredIndices[i]; + DrawEntryElement(tableIndex, entryIndex, entriesProperty.GetArrayElementAtIndex(entryIndex)); + EditorGUILayout.Space(4f); + } - return GetEntryElementHeight(entriesProperty.GetArrayElementAtIndex(index)); - }; - - list.drawElementCallback = (rect, index, active, focused) => + if (totalPages > 1) { - if (index < 0 || index >= entriesProperty.arraySize) - { - return; - } - - DrawEntryElement(rect, entriesProperty.GetArrayElementAtIndex(index)); - }; - - list.onReorderCallback = _ => - { - ApplyPendingInspectorChanges(); - }; - - list.onRemoveCallback = currentList => - { - if (currentList.index < 0 || currentList.index >= entriesProperty.arraySize) - { - return; - } - - if (!EditorUtility.DisplayDialog("Remove Entry", "Remove the selected entry from the table?", "Remove", "Cancel")) - { - return; - } - - Undo.RecordObject(_database, "Remove glyph entry"); - entriesProperty.DeleteArrayElementAtIndex(currentList.index); - serializedObject.ApplyModifiedProperties(); - InvalidateEntriesList(tableIndex); - NotifyDatabaseChanged(); - }; - - return list; + DrawEntriesPagination(state, filteredIndices.Count, entriesProperty.arraySize); + } } - private float GetEntryElementHeight(SerializedProperty entryProperty) + private void DrawEntriesControls(TableEditorState state, int totalEntries) { - SerializedProperty spriteProperty = entryProperty.FindPropertyRelative(EntrySpritePropertyName); - SerializedProperty actionProperty = entryProperty.FindPropertyRelative(EntryActionPropertyName); - float spriteHeight = EditorGUI.GetPropertyHeight(spriteProperty, true); - float actionHeight = EditorGUI.GetPropertyHeight(actionProperty, true); - float fieldHeight = spriteHeight + actionHeight + 10f; - return Mathf.Max(ListPreviewSize + 10f, fieldHeight + 8f); + string search = EditorGUILayout.TextField("Search", state.EntrySearch); + if (!string.Equals(search, state.EntrySearch, StringComparison.Ordinal)) + { + state.EntrySearch = search; + state.CurrentPage = 0; + InvalidateEntryView(state); + } + + using (new EditorGUILayout.HorizontalScope()) + { + int entriesPerPage = EditorGUILayout.IntPopup("Page Size", state.EntriesPerPage, EntriesPerPageLabels, EntriesPerPageOptions); + if (entriesPerPage != state.EntriesPerPage) + { + state.EntriesPerPage = entriesPerPage; + state.CurrentPage = 0; + } + + GUILayout.FlexibleSpace(); + EditorGUILayout.LabelField($"总数: {totalEntries}", EditorStyles.miniLabel, GUILayout.Width(80f)); + + using (new EditorGUI.DisabledScope(string.IsNullOrEmpty(state.EntrySearch))) + { + if (GUILayout.Button("Clear Search", GUILayout.Width(100f))) + { + state.EntrySearch = string.Empty; + state.CurrentPage = 0; + InvalidateEntryView(state); + GUI.FocusControl(null); + } + } + } } - private void DrawEntryElement(Rect rect, SerializedProperty entryProperty) + private void DrawEntriesPagination(TableEditorState state, int filteredCount, int totalEntries) + { + int entriesPerPage = Mathf.Max(1, state.EntriesPerPage); + int totalPages = Mathf.Max(1, Mathf.CeilToInt(filteredCount / (float)entriesPerPage)); + int startEntry = filteredCount == 0 ? 0 : state.CurrentPage * entriesPerPage + 1; + int endEntry = Mathf.Min(filteredCount, (state.CurrentPage + 1) * entriesPerPage); + + using (new EditorGUILayout.HorizontalScope(EditorStyles.helpBox)) + { + EditorGUILayout.LabelField( + $"显示 {startEntry}-{endEntry} / {filteredCount} 条", + EditorStyles.miniLabel, + GUILayout.Width(140f)); + + if (filteredCount != totalEntries) + { + EditorGUILayout.LabelField($"(筛选自 {totalEntries} 条)", EditorStyles.miniLabel, GUILayout.Width(100f)); + } + + GUILayout.FlexibleSpace(); + + using (new EditorGUI.DisabledScope(state.CurrentPage <= 0)) + { + if (GUILayout.Button("<<", GUILayout.Width(32f))) + { + state.CurrentPage = 0; + } + + if (GUILayout.Button("<", GUILayout.Width(28f))) + { + state.CurrentPage--; + } + } + + GUILayout.Label($"第 {state.CurrentPage + 1} / {totalPages} 页", EditorStyles.miniLabel, GUILayout.Width(72f)); + + using (new EditorGUI.DisabledScope(state.CurrentPage >= totalPages - 1)) + { + if (GUILayout.Button(">", GUILayout.Width(28f))) + { + state.CurrentPage++; + } + + if (GUILayout.Button(">>", GUILayout.Width(32f))) + { + state.CurrentPage = totalPages - 1; + } + } + } + } + + private void DrawEntryElement(int tableIndex, int entryIndex, SerializedProperty entryProperty) { SerializedProperty spriteProperty = entryProperty.FindPropertyRelative(EntrySpritePropertyName); SerializedProperty actionProperty = entryProperty.FindPropertyRelative(EntryActionPropertyName); Sprite sprite = spriteProperty.objectReferenceValue as Sprite; - - rect.y += 4f; - rect.height -= 8f; - - Rect previewRect = new Rect(rect.x, rect.y, ListPreviewSize, ListPreviewSize); - Rect fieldsRect = new Rect(rect.x + ListPreviewSize + 8f, rect.y, rect.width - ListPreviewSize - 44f, rect.height); - Rect pingRect = new Rect(rect.xMax - 30f, rect.y, 30f, EditorGUIUtility.singleLineHeight); - - DrawSpritePreview(previewRect, sprite); - - float currentY = fieldsRect.y; - float spriteHeight = EditorGUI.GetPropertyHeight(spriteProperty, true); - Rect spriteRect = new Rect(fieldsRect.x, currentY, fieldsRect.width, spriteHeight); - EditorGUI.PropertyField(spriteRect, spriteProperty, new GUIContent("Sprite"), true); - - currentY += spriteHeight + 4f; - float actionHeight = EditorGUI.GetPropertyHeight(actionProperty, true); - Rect actionRect = new Rect(fieldsRect.x, currentY, fieldsRect.width, actionHeight); - EditorGUI.PropertyField(actionRect, actionProperty, new GUIContent("Action"), true); - - using (new EditorGUI.DisabledScope(sprite == null)) + using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) { - if (GUI.Button(pingRect, "Ping")) + using (new EditorGUILayout.HorizontalScope()) { - EditorGUIUtility.PingObject(sprite); + GUILayout.Label(GetEntryTitle(tableIndex, entryIndex), EditorStyles.boldLabel); + GUILayout.FlexibleSpace(); + + using (new EditorGUI.DisabledScope(entryIndex <= 0)) + { + if (GUILayout.Button("↑", GUILayout.Width(28f))) + { + ApplyPendingInspectorChanges(); + MoveEntry(tableIndex, entryIndex, entryIndex - 1); + GUIUtility.ExitGUI(); + } + } + + using (new EditorGUI.DisabledScope(entryIndex >= _database.tables[tableIndex].entries.Count - 1)) + { + if (GUILayout.Button("↓", GUILayout.Width(28f))) + { + ApplyPendingInspectorChanges(); + MoveEntry(tableIndex, entryIndex, entryIndex + 1); + GUIUtility.ExitGUI(); + } + } + + using (new EditorGUI.DisabledScope(sprite == null)) + { + if (GUILayout.Button("Ping", GUILayout.Width(48f))) + { + EditorGUIUtility.PingObject(sprite); + } + } + + if (GUILayout.Button("Remove", GUILayout.Width(64f))) + { + if (EditorUtility.DisplayDialog("Remove Entry", "Remove the selected entry from the table?", "Remove", "Cancel")) + { + ApplyPendingInspectorChanges(); + RemoveEntry(tableIndex, entryIndex); + GUIUtility.ExitGUI(); + } + } + } + + using (new EditorGUILayout.HorizontalScope()) + { + Rect previewRect = GUILayoutUtility.GetRect(ListPreviewSize, ListPreviewSize, GUILayout.Width(ListPreviewSize), GUILayout.Height(ListPreviewSize)); + DrawSpritePreview(previewRect, sprite); + + using (new EditorGUILayout.VerticalScope()) + { + EditorGUILayout.PropertyField(spriteProperty, new GUIContent("Sprite"), true); + EditorGUILayout.PropertyField(actionProperty, new GUIContent("Action"), true); + } } } } @@ -509,14 +595,14 @@ public sealed class InputGlyphDatabaseEditor : Editor List issues = new(); if (_database.tables == null || _database.tables.Count == 0) { - issues.Add("The database has no tables. Runtime glyph lookup will always fall back to the placeholder sprite."); + issues.Add("数据库中没有任何表,运行时查询将始终回退到占位图标。"); return issues; } List missingTables = GetMissingDefaultTables(); if (missingTables.Count > 0) { - issues.Add($"Recommended tables are missing: {string.Join(", ", missingTables)}."); + issues.Add($"缺少推荐表: {string.Join(", ", missingTables)}。"); } HashSet seenNames = new(StringComparer.OrdinalIgnoreCase); @@ -526,7 +612,7 @@ public sealed class InputGlyphDatabaseEditor : Editor string tableName = _database.tables[i] != null ? _database.tables[i].deviceName : string.Empty; if (string.IsNullOrWhiteSpace(tableName)) { - issues.Add($"Table {i + 1} has an empty device name."); + issues.Add($"表 {i + 1} 的设备名称为空。"); continue; } @@ -538,7 +624,7 @@ public sealed class InputGlyphDatabaseEditor : Editor foreach (string duplicateName in duplicateNames) { - issues.Add($"Duplicate table name '{duplicateName}' detected."); + issues.Add($"检测到重复的表名 '{duplicateName}'。"); } return issues; @@ -549,14 +635,14 @@ public sealed class InputGlyphDatabaseEditor : Editor List issues = new(); if (!IsValidTableIndex(tableIndex)) { - issues.Add("The selected table is invalid."); + issues.Add("当前选中的表无效。"); return issues; } DeviceGlyphTable table = _database.tables[tableIndex]; if (table.entries == null || table.entries.Count == 0) { - issues.Add("This table has no entries."); + issues.Add("当前表没有任何条目。"); return issues; } @@ -571,7 +657,7 @@ public sealed class InputGlyphDatabaseEditor : Editor GlyphEntry entry = table.entries[i]; if (entry == null) { - issues.Add($"Entry {i + 1} is null."); + issues.Add($"条目 {i + 1} 为空。"); continue; } @@ -601,16 +687,17 @@ public sealed class InputGlyphDatabaseEditor : Editor if (missingSpriteCount > 0) { - issues.Add($"{missingSpriteCount} entr{(missingSpriteCount == 1 ? "y has" : "ies have")} no sprite assigned."); + issues.Add($"{missingSpriteCount} 个条目未绑定 Sprite。"); } if (missingActionCount > 0) { - issues.Add($"{missingActionCount} entr{(missingActionCount == 1 ? "y has" : "ies have")} no action assigned. Those entries will not participate in runtime path lookup."); + issues.Add($"{missingActionCount} 个条目未绑定 Action,这些条目不会参与运行时路径查找。"); } + foreach (string spriteName in duplicateSprites) { - issues.Add($"Duplicate sprite name '{spriteName}' found in this table."); + issues.Add($"当前表中存在重复的 Sprite 名称 '{spriteName}'。"); } foreach (KeyValuePair> pair in bindingOwners) @@ -620,7 +707,7 @@ public sealed class InputGlyphDatabaseEditor : Editor continue; } - issues.Add($"Binding '{pair.Key}' is mapped by multiple entries: {string.Join(", ", pair.Value)}. Runtime lookup keeps the first match."); + issues.Add($"绑定 '{pair.Key}' 被多个条目共用: {string.Join(", ", pair.Value)}。运行时只会保留第一个匹配项。"); } return issues; @@ -658,7 +745,7 @@ public sealed class InputGlyphDatabaseEditor : Editor table.entries ??= new List(); table.entries.Add(new GlyphEntry { Sprite = sprite, action = null }); serializedObject.Update(); - InvalidateEntriesList(tableIndex); + InvalidateEntryView(tableIndex); NotifyDatabaseChanged(); } @@ -674,7 +761,7 @@ public sealed class InputGlyphDatabaseEditor : Editor table.entries ??= new List(); table.entries.Clear(); serializedObject.Update(); - InvalidateEntriesList(tableIndex); + InvalidateEntryView(tableIndex); NotifyDatabaseChanged(); } @@ -691,7 +778,7 @@ public sealed class InputGlyphDatabaseEditor : Editor }); SyncTableStates(); serializedObject.Update(); - InvalidateAllEntriesLists(); + InvalidateAllEntryViews(); NotifyDatabaseChanged(); } @@ -707,7 +794,7 @@ public sealed class InputGlyphDatabaseEditor : Editor SyncTableStates(); ClampSelectedTab(); serializedObject.Update(); - InvalidateAllEntriesLists(); + InvalidateAllEntryViews(); NotifyDatabaseChanged(); } @@ -734,7 +821,7 @@ public sealed class InputGlyphDatabaseEditor : Editor SyncTableStates(); serializedObject.Update(); - InvalidateAllEntriesLists(); + InvalidateAllEntryViews(); NotifyDatabaseChanged(); } @@ -822,7 +909,7 @@ public sealed class InputGlyphDatabaseEditor : Editor } serializedObject.Update(); - InvalidateEntriesList(tableIndex); + InvalidateEntryView(tableIndex); NotifyDatabaseChanged(); Debug.Log($"[InputGlyphDatabase] Merged sprite sheet '{table.spriteSheetTexture.name}' into '{table.deviceName}'. sprites={sprites.Count}, replaced={replaced}, added={added}, total={table.entries.Count}"); } @@ -831,6 +918,7 @@ public sealed class InputGlyphDatabaseEditor : Editor { if (serializedObject.ApplyModifiedProperties()) { + InvalidateAllEntryViews(); NotifyDatabaseChanged(); } } @@ -865,23 +953,163 @@ public sealed class InputGlyphDatabaseEditor : Editor _selectedTab = Mathf.Clamp(_selectedTab, 0, maxIndex); } - private void InvalidateEntriesList(int tableIndex) + private void MoveEntry(int tableIndex, int fromIndex, int toIndex) + { + if (!IsValidTableIndex(tableIndex)) + { + return; + } + + List entries = _database.tables[tableIndex].entries; + if (entries == null || fromIndex < 0 || fromIndex >= entries.Count || toIndex < 0 || toIndex >= entries.Count || fromIndex == toIndex) + { + return; + } + + Undo.RecordObject(_database, "Move glyph entry"); + GlyphEntry entry = entries[fromIndex]; + entries.RemoveAt(fromIndex); + entries.Insert(toIndex, entry); + serializedObject.Update(); + InvalidateEntryView(tableIndex); + NotifyDatabaseChanged(); + } + + private void RemoveEntry(int tableIndex, int entryIndex) + { + if (!IsValidTableIndex(tableIndex)) + { + return; + } + + List entries = _database.tables[tableIndex].entries; + if (entries == null || entryIndex < 0 || entryIndex >= entries.Count) + { + return; + } + + Undo.RecordObject(_database, "Remove glyph entry"); + entries.RemoveAt(entryIndex); + serializedObject.Update(); + InvalidateEntryView(tableIndex); + NotifyDatabaseChanged(); + } + + private List GetFilteredEntryIndices(int tableIndex, SerializedProperty entriesProperty, TableEditorState state) + { + string search = state.EntrySearch != null ? state.EntrySearch.Trim() : string.Empty; + if (state.CachedEntryCount == entriesProperty.arraySize && string.Equals(state.CachedSearch, search, StringComparison.Ordinal)) + { + return state.FilteredEntryIndices; + } + + state.FilteredEntryIndices.Clear(); + for (int i = 0; i < entriesProperty.arraySize; i++) + { + if (DoesEntryMatchSearch(tableIndex, i, search)) + { + state.FilteredEntryIndices.Add(i); + } + } + + state.CachedEntryCount = entriesProperty.arraySize; + state.CachedSearch = search; + return state.FilteredEntryIndices; + } + + private bool DoesEntryMatchSearch(int tableIndex, int entryIndex, string search) + { + if (string.IsNullOrWhiteSpace(search)) + { + return true; + } + + if (!IsValidTableIndex(tableIndex)) + { + return false; + } + + List entries = _database.tables[tableIndex].entries; + if (entries == null || entryIndex < 0 || entryIndex >= entries.Count) + { + return false; + } + + GlyphEntry entry = entries[entryIndex]; + if (entry == null) + { + return ContainsIgnoreCase("null", search); + } + + if (ContainsIgnoreCase(entry.Sprite != null ? entry.Sprite.name : string.Empty, search) + || ContainsIgnoreCase(entry.action != null ? entry.action.name : string.Empty, search)) + { + return true; + } + + if (entry.action == null) + { + return false; + } + + for (int i = 0; i < entry.action.bindings.Count; i++) + { + InputBinding binding = entry.action.bindings[i]; + if (ContainsIgnoreCase(binding.path, search) || ContainsIgnoreCase(binding.effectivePath, search)) + { + return true; + } + } + + return false; + } + + private static bool ContainsIgnoreCase(string value, string search) + { + return !string.IsNullOrEmpty(value) && value.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0; + } + + private string GetEntryTitle(int tableIndex, int entryIndex) + { + if (!IsValidTableIndex(tableIndex)) + { + return $"Entry #{entryIndex + 1}"; + } + + List entries = _database.tables[tableIndex].entries; + if (entries == null || entryIndex < 0 || entryIndex >= entries.Count) + { + return $"Entry #{entryIndex + 1}"; + } + + GlyphEntry entry = entries[entryIndex]; + string spriteName = entry?.Sprite != null ? entry.Sprite.name : "No Sprite"; + string actionName = entry?.action != null ? entry.action.name : "No Action"; + return $"#{entryIndex + 1} {spriteName} / {actionName}"; + } + + private void InvalidateEntryView(int tableIndex) { if (tableIndex < 0 || tableIndex >= _tableStates.Count) { return; } - _tableStates[tableIndex].EntriesList = null; - _tableStates[tableIndex].EntriesPropertyPath = null; + InvalidateEntryView(_tableStates[tableIndex]); } - private void InvalidateAllEntriesLists() + private static void InvalidateEntryView(TableEditorState state) + { + state.FilteredEntryIndices.Clear(); + state.CachedSearch = string.Empty; + state.CachedEntryCount = -1; + } + + private void InvalidateAllEntryViews() { for (int i = 0; i < _tableStates.Count; i++) { - _tableStates[i].EntriesList = null; - _tableStates[i].EntriesPropertyPath = null; + InvalidateEntryView(_tableStates[i]); } } diff --git a/Client/Packages/com.alicizax.unity.framework b/Client/Packages/com.alicizax.unity.framework index a978c68..e7c6b17 160000 --- a/Client/Packages/com.alicizax.unity.framework +++ b/Client/Packages/com.alicizax.unity.framework @@ -1 +1 @@ -Subproject commit a978c68586cf761c577842532dfa6af5847851a4 +Subproject commit e7c6b174fe953381196760a54432048990f74c99