unity-vendor-packages/vfolders2/vHierarchy/VHierarchySceneSelectorWind...

1189 lines
32 KiB
C#
Raw Normal View History

2025-08-19 10:13:59 +08:00
#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.ShortcutManagement;
using System.Reflection;
using System.Linq;
using UnityEngine.UIElements;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
using UnityEditor.IMGUI.Controls;
using System.Diagnostics;
using Type = System.Type;
using Delegate = System.Delegate;
using Action = System.Action;
using static VHierarchy.VHierarchy;
using static VHierarchy.Libs.VUtils;
using static VHierarchy.Libs.VGUI;
// using static VTools.VDebug;
namespace VHierarchy
{
public class VHierarchySceneSelectorWindow : EditorWindow
{
void OnGUI()
{
void background()
{
windowRect.Draw(windowBackground);
}
void closeOnEscape()
{
if (!curEvent.isKeyDown) return;
if (curEvent.keyCode != KeyCode.Escape) return;
Close();
EditorApplication.RepaintHierarchyWindow();
GUIUtility.ExitGUI();
}
void addTabOnEnter()
{
// if (!curEvent.isKeyDown) return; // searchfield steals fpcus
if (curEvent.keyCode != KeyCode.Return) return;
if (keyboardFocusedRowIndex == -1) return;
if (keyboardFocusedEntry == null) return;
OpenScene(keyboardFocusedEntry, curEvent.holdingAlt);
this.Close();
}
void arrowNavigation()
{
if (!curEvent.isKeyDown) return;
if (curEvent.keyCode != KeyCode.UpArrow && curEvent.keyCode != KeyCode.DownArrow) return;
curEvent.Use();
if (curEvent.keyCode == KeyCode.UpArrow)
if (keyboardFocusedRowIndex == 0)
keyboardFocusedRowIndex = rowCount - 1;
else
keyboardFocusedRowIndex--;
if (curEvent.keyCode == KeyCode.DownArrow)
if (keyboardFocusedRowIndex == rowCount - 1)
keyboardFocusedRowIndex = 0;
else
keyboardFocusedRowIndex++;
keyboardFocusedRowIndex = keyboardFocusedRowIndex.Clamp(0, rowCount - 1);
}
void updateSearch()
{
if (searchString == prevSearchString) return;
prevSearchString = searchString;
if (searchString == "") { keyboardFocusedRowIndex = -1; return; }
UpdateSearch();
keyboardFocusedRowIndex = 0;
}
void searchField_()
{
var searchRect = windowRect.SetHeight(18).MoveY(1).AddWidthFromMid(-2);
if (searchField == null)
{
searchField = new SearchField();
searchField.SetFocus();
}
searchString = searchField.OnGUI(searchRect, searchString);
}
void rows()
{
void bookmarked()
{
if (searchString != "") return;
if (!bookmarkedEntries.Any()) return;
bookmarksRect = windowRect.SetHeight(bookmarkedEntries.Count * rowHeight + gaps.Sum());
BookmarksGUI();
}
void divider()
{
if (searchString != "") return;
if (!bookmarkedEntries.Any()) return;
var splitterColor = Greyscale(.36f);
var splitterRect = bookmarksRect.SetHeightFromBottom(0).SetHeight(dividerHeight).SetHeightFromMid(1).AddWidthFromMid(-10);
splitterRect.Draw(splitterColor);
}
void notBookmarked()
{
if (searchString != "") return;
if (bookmarkedEntries.Any())
nextRowY = bookmarksRect.yMax + dividerHeight;
foreach (var entry in allEntries)
{
if (bookmarkedEntries.Contains(entry)) continue;
if (entry == draggedBookmark) continue;
RowGUI(windowRect.SetHeight(rowHeight).SetY(nextRowY), entry);
nextRowY += rowHeight;
nextRowIndex++;
}
}
void searched()
{
if (searchString == "") return;
foreach (var entry in searchedEntries)
{
RowGUI(windowRect.SetHeight(rowHeight).SetY(nextRowY), entry);
nextRowY += rowHeight;
nextRowIndex++;
}
}
scrollPos = GUI.BeginScrollView(windowRect.AddHeightFromBottom(-firstRowOffsetTop), Vector2.up * scrollPos, windowRect.SetHeight(scrollAreaHeight), GUIStyle.none, GUIStyle.none).y;
nextRowY = 0;
nextRowIndex = 0;
bookmarked();
divider();
notBookmarked();
searched();
scrollAreaHeight = nextRowY + 23;
rowCount = nextRowIndex;
GUI.EndScrollView();
}
void noResults()
{
if (searchString == "") return;
if (searchedEntries.Any()) return;
GUI.enabled = false;
GUI.skin.label.alignment = TextAnchor.MiddleCenter;
GUI.Label(windowRect.AddHeightFromBottom(-14), "No results");
GUI.skin.label.alignment = TextAnchor.MiddleLeft;
GUI.enabled = true;
}
void outline()
{
if (Application.platform == RuntimePlatform.OSXEditor) return;
position.SetPos(0, 0).DrawOutline(Greyscale(.1f));
}
// void resizing()
// {
// }
background();
closeOnEscape();
addTabOnEnter();
arrowNavigation();
updateSearch();
searchField_();
rows();
noResults();
outline();
if (draggingBookmark || animatingDroppedBookmark || animatingGaps)
this.Repaint();
}
Rect windowRect => position.SetPos(0, 0);
Rect bookmarksRect;
SearchField searchField;
Color windowBackground => Greyscale(isDarkTheme ? .23f : .8f);
string searchString = "";
string prevSearchString = "";
float scrollPos;
float rowHeight => 22;
float dividerHeight => 11;
float firstRowOffsetTop => bookmarkedEntries.Any() && searchString == "" ? 21 : 20;
int nextRowIndex;
float nextRowY;
float scrollAreaHeight = 1232;
int rowCount = 123;
int keyboardFocusedRowIndex = -1;
void RowGUI(Rect rowRect, SceneEntry entry)
{
var isHovered = rowRect.IsHovered();
var isPressed = entry == pressedEntry;
var isDragged = draggingBookmark && draggedBookmark == entry;
var isDropped = animatingDroppedBookmark && droppedBookmark == entry;
var isFocused = entry == keyboardFocusedEntry;
var isBookmarked = bookmarkedEntries.Contains(entry) || entry == draggedBookmark;
if (isDropped)
isHovered = rowRect.SetY(droppedBookmarkYTarget).IsHovered();
var showBlueBackground = isFocused || isPressed || isDragged;
var showAdditiveIndicator = curEvent.holdingAlt && ((keyboardFocusedEntry?.scenePath).IsNullOrEmpty() ? isHovered : isFocused);
var showStarButton = (isHovered || (isBookmarked && !isFocused)) && !showAdditiveIndicator;
var showEnterHint = (isFocused && !isHovered && isDarkTheme) && !showAdditiveIndicator;
void draggedShadow()
{
if (!curEvent.isRepaint) return;
if (!isDragged) return;
var shadowRect = rowRect.AddHeightFromMid(-4);
var shadowOpacity = .3f;
var shadowRadius = 13;
shadowRect.DrawBlurred(Greyscale(0, shadowOpacity), shadowRadius);
}
void blueBackground()
{
if (!curEvent.isRepaint) return;
if (!showBlueBackground) return;
var backgroundRect = rowRect.AddHeightFromMid(-3);
backgroundRect.Draw(GUIColors.selectedBackground);
}
void icon()
{
if (!curEvent.isRepaint) return;
Texture iconTexture = EditorIcons.GetIcon("SceneAsset Icon");
if (!iconTexture) return;
var iconRect = rowRect.SetWidth(16).SetHeightFromMid(16).MoveX(4 + 1);
iconRect = iconRect.SetWidthFromMid(iconRect.height * iconTexture.width / iconTexture.height);
GUI.DrawTexture(iconRect, iconTexture);
}
void name()
{
if (!curEvent.isRepaint) return;
var nameRect = rowRect.MoveX(21 + 1);
var nameText = searchString != "" ? namesFormattedForFuzzySearch_byEntry[entry]
: entry.sceneName;
if (entry.scenePath == sceneToReplace.path)
{
SetLabelBold();
SetGUIColor(Greyscale(1.15f));
GUI.skin.label.richText = true;
GUI.Label(nameRect, nameText);
GUI.skin.label.richText = false;
ResetGUIColor();
ResetLabelStyle();
}
else
{
var color = showBlueBackground ? Greyscale(123, 123)
: isHovered && !isPressed ? Greyscale(1.1f)
: Greyscale(1);
SetGUIColor(color);
GUI.skin.label.richText = true;
GUI.Label(nameRect, nameText);
GUI.skin.label.richText = false;
ResetGUIColor();
}
}
void curtain()
{
if (!curEvent.isRepaint) return;
var curtainWidth = 20;
var curtainColor = showBlueBackground ? GUIColors.selectedBackground : windowBackground;
var curtainXMax = rowRect.xMax - (showStarButton ? 21 : showEnterHint ? 33 : showAdditiveIndicator ? 80 : 0);
rowRect.SetHeightFromMid(18).SetXMax(curtainXMax).SetWidthFromRight(curtainWidth).DrawCurtainLeft(curtainColor);
rowRect.SetHeightFromMid(18).SetX(curtainXMax).SetXMax(rowRect.xMax).Draw(curtainColor);
}
void starButton()
{
if (!showStarButton) return;
var buttonRect = rowRect.SetWidthFromRight(16).MoveX(-6 + 1).SetSizeFromMid(rowHeight);
var iconName = isBookmarked ^ buttonRect.IsHovered() ? "Star" : "Star Hollow";
var iconSize = 16;
var colorNormal = Greyscale(isDarkTheme ? (isBookmarked ? .5f : .7f) : .3f);
var colorHovered = Greyscale(isDarkTheme ? (isBookmarked ? .9f : 1) : 0f);
var colorPressed = Greyscale(isDarkTheme ? .75f : .5f);
var colorDisabled = Greyscale(isDarkTheme ? .53f : .55f);
if (!IconButton(buttonRect, iconName, iconSize, colorNormal, colorHovered, colorPressed)) return;
if (isBookmarked)
bookmarkedEntries.Remove(entry);
else
bookmarkedEntries.Add(entry);
}
void enterHint()
{
if (!curEvent.isRepaint) return;
if (!showEnterHint) return;
var hintRect = rowRect.SetWidthFromRight(33);
SetLabelFontSize(10);
SetGUIColor(Greyscale(.9f));
GUI.Label(hintRect, "Enter");
ResetGUIColor();
ResetLabelStyle();
}
void additiveIndicator()
{
if (!curEvent.isRepaint) return;
if (!showAdditiveIndicator) return;
var indicatorRect = rowRect.SetWidthFromRight(81);
SetLabelFontSize(10);
SetGUIColor(Greyscale(.9f));
GUI.Label(indicatorRect, "Load additively");
ResetGUIColor();
ResetLabelStyle();
}
void hoverHighlight()
{
if (!curEvent.isRepaint) return;
if (!isHovered) return;
if (isPressed || isDragged) return;
var backgroundRect = rowRect.AddHeightFromMid(-2);
var backgroundColor = Greyscale(isDarkTheme ? 1 : 0, isPressed ? .085f : .12f);
backgroundRect.Draw(backgroundColor);
}
void mouse()
{
void down()
{
if (!curEvent.isMouseDown) return;
if (!rowRect.IsHovered()) return;
isMousePressedOnEntry = true;
pressedEntry = entry;
mouseDownPosition = curEvent.mousePosition;
this.Repaint();
}
void up()
{
if (!curEvent.isMouseUp) return;
isMousePressedOnEntry = false;
pressedEntry = null;
this.Repaint();
if (!isHovered) return;
if (draggingBookmark) return;
if ((curEvent.mousePosition - mouseDownPosition).magnitude > 2) return;
curEvent.Use();
OpenScene(entry, curEvent.holdingAlt);
this.Close();
}
down();
up();
}
void setFocusedEntry()
{
var rowIndex = (rowRect.y / rowHeight).FloorToInt();
if (rowIndex == keyboardFocusedRowIndex)
keyboardFocusedEntry = entry;
}
rowRect.MarkInteractive();
draggedShadow();
blueBackground();
icon();
name();
curtain();
starButton();
enterHint();
additiveIndicator();
hoverHighlight();
mouse();
setFocusedEntry();
}
SceneEntry pressedEntry;
bool isMousePressedOnEntry;
Vector2 mouseDownPosition;
SceneEntry keyboardFocusedEntry;
void OpenScene(SceneEntry entry, bool openAdditive)
{
if (!Application.isPlaying)
if (!EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo()) return; // if clicked cancel
void openScene(string path, bool additive)
{
if (!EditorApplication.isPlaying)
EditorSceneManager.OpenScene(path, additive ? OpenSceneMode.Additive : OpenSceneMode.Single);
else
SceneManager.LoadScene(path, additive ? LoadSceneMode.Additive : LoadSceneMode.Single);
}
if (openAdditive)
openScene(entry.scenePath, additive: true);
else if (EditorSceneManager.sceneCount == 1)
openScene(entry.scenePath, additive: false);
else
{
var openedScene = EditorSceneManager.OpenScene(entry.scenePath, OpenSceneMode.Additive);
EditorSceneManager.MoveSceneAfter(openedScene, sceneToReplace);
if (EditorSceneManager.GetActiveScene() == sceneToReplace)
EditorSceneManager.SetActiveScene(openedScene);
EditorSceneManager.CloseScene(sceneToReplace, removeScene: true);
}
}
public void BookmarksGUI()
{
void normalBookmark(int i)
{
if (bookmarkedEntries[i] == droppedBookmark && animatingDroppedBookmark) return;
var bookmarkRect = bookmarksRect.SetHeight(rowHeight)
.SetY(GetBookmarY(i));
RowGUI(bookmarkRect, bookmarkedEntries[i]);
}
void normalBookmarks()
{
for (int i = 0; i < bookmarkedEntries.Count; i++)
normalBookmark(i);
}
void draggedBookmark_()
{
if (!draggingBookmark) return;
var bookmarkRect = bookmarksRect.SetHeight(rowHeight)
.SetY(draggedBookmarkY);
RowGUI(bookmarkRect, draggedBookmark);
}
void droppedBookmark_()
{
if (!animatingDroppedBookmark) return;
var bookmarkRect = bookmarksRect.SetHeight(rowHeight)
.SetY(droppedBookmarkY);
RowGUI(bookmarkRect, droppedBookmark);
}
BookmarksDragging();
BookmarksAnimations();
normalBookmarks();
draggedBookmark_();
droppedBookmark_();
}
int GetBookmarkIndex(float mouseY)
{
return ((mouseY - bookmarksRect.y) / rowHeight).FloorToInt();
}
float GetBookmarY(int i, bool includeGaps = true)
{
var centerY = bookmarksRect.y
+ i * rowHeight
+ (includeGaps ? gaps.Take(i + 1).Sum() : 0);
return centerY;
}
void BookmarksDragging()
{
void init()
{
if (draggingBookmark) return;
if ((curEvent.mousePosition - mouseDownPosition).magnitude <= 2) return;
if (!isMousePressedOnEntry) return;
if (!bookmarkedEntries.Contains(pressedEntry)) return;
var i = GetBookmarkIndex(mouseDownPosition.y);
if (i >= bookmarkedEntries.Count) return;
if (i < 0) return;
animatingDroppedBookmark = false;
draggingBookmark = true;
draggedBookmark = bookmarkedEntries[i];
draggedBookmarkHoldOffsetY = GetBookmarY(i) - mouseDownPosition.y;
gaps[i] = rowHeight;
this.RecordUndo();
bookmarkedEntries.Remove(draggedBookmark);
}
void update()
{
if (!draggingBookmark) return;
EditorGUIUtility.hotControl = EditorGUIUtility.GetControlID(FocusType.Passive);
draggedBookmarkY = (curEvent.mousePosition.y + draggedBookmarkHoldOffsetY).Clamp(0, bookmarksRect.yMax - rowHeight);
insertDraggedBookmarkAtIndex = GetBookmarkIndex(curEvent.mousePosition.y + draggedBookmarkHoldOffsetY + rowHeight / 2).Clamp(0, bookmarkedEntries.Count);
}
void accept()
{
if (!draggingBookmark) return;
if (!curEvent.isMouseUp && !curEvent.isIgnore) return;
curEvent.Use();
EditorGUIUtility.hotControl = 0;
// DragAndDrop.PrepareStartDrag(); // fixes phantom dragged component indicator after reordering bookmarks
this.RecordUndo();
draggingBookmark = false;
isMousePressedOnEntry = false;
bookmarkedEntries.AddAt(draggedBookmark, insertDraggedBookmarkAtIndex);
gaps[insertDraggedBookmarkAtIndex] -= rowHeight;
gaps.AddAt(0, insertDraggedBookmarkAtIndex);
droppedBookmark = draggedBookmark;
droppedBookmarkY = draggedBookmarkY;
droppedBookmarkYDerivative = 0;
animatingDroppedBookmark = true;
draggedBookmark = null;
pressedEntry = null;
EditorGUIUtility.hotControl = 0;
}
init();
accept();
update();
}
bool draggingBookmark;
float draggedBookmarkHoldOffsetY;
float draggedBookmarkY;
int insertDraggedBookmarkAtIndex;
SceneEntry draggedBookmark;
SceneEntry droppedBookmark;
void BookmarksAnimations()
{
if (!curEvent.isLayout) return;
void gaps_()
{
var makeSpaceForDraggedBookmark = draggingBookmark;
// var lerpSpeed = 1;
var lerpSpeed = 11;
for (int i = 0; i < gaps.Count; i++)
if (makeSpaceForDraggedBookmark && i == insertDraggedBookmarkAtIndex)
gaps[i] = MathUtil.Lerp(gaps[i], rowHeight, lerpSpeed, editorDeltaTime);
else
gaps[i] = MathUtil.Lerp(gaps[i], 0, lerpSpeed, editorDeltaTime);
for (int i = 0; i < gaps.Count; i++)
if (gaps[i].Approx(0))
gaps[i] = 0;
animatingGaps = gaps.Any(r => r > .1f);
}
void droppedBookmark_()
{
if (!animatingDroppedBookmark) return;
// var lerpSpeed = 1;
var lerpSpeed = 8;
droppedBookmarkYTarget = GetBookmarY(bookmarkedEntries.IndexOf(droppedBookmark), includeGaps: false);
MathUtil.SmoothDamp(ref droppedBookmarkY, droppedBookmarkYTarget, lerpSpeed, ref droppedBookmarkYDerivative, editorDeltaTime);
if ((droppedBookmarkY - droppedBookmarkYTarget).Abs() < .5f)
animatingDroppedBookmark = false;
}
gaps_();
droppedBookmark_();
}
float droppedBookmarkY;
float droppedBookmarkYTarget;
float droppedBookmarkYDerivative;
bool animatingDroppedBookmark;
bool animatingGaps;
List<float> gaps
{
get
{
while (_gaps.Count < bookmarkedEntries.Count + 1) _gaps.Add(0);
while (_gaps.Count > bookmarkedEntries.Count + 1) _gaps.RemoveLast();
return _gaps;
}
}
List<float> _gaps = new();
public static void UpdateAllEntries()
{
void fillWithAllScenes()
{
allEntries.Clear();
allEntries = AssetDatabase.FindAssets("t:scene")
.Select(r => new SceneEntry() { scenePath = r.ToPath() })
.ToList();
allEntries.SortBy(r => r.scenePath.GetFilename());
}
// void removeAllOpen()
// {
// for (int i = 0; i < EditorSceneManager.sceneCount; i++)
// allEntries.RemoveAll(r => r.scenePath == EditorSceneManager.GetSceneAt(i).path);
// }
fillWithAllScenes();
// removeAllOpen();
}
static List<SceneEntry> allEntries = new();
[System.Serializable]
public class SceneEntry
{
public string scenePath = "";
public string sceneName => scenePath.GetFilename(withExtension: false);
}
void GetBookmarkedEntries()
{
bookmarkedEntries = data.bookmarkedScenePaths.Select(r => allEntries.FirstOrDefault(rr => rr.scenePath == r))
.Where(r => r != null)
.ToList();
}
void SaveBookmarkedEntries()
{
data.bookmarkedScenePaths = bookmarkedEntries.Select(r => r.scenePath).ToList();
data.Dirty();
}
List<SceneEntry> bookmarkedEntries = new();
void OnEnable() { UpdateAllEntries(); GetBookmarkedEntries(); }
void OnDisable() { SaveBookmarkedEntries(); }
void UpdateSearch()
{
bool tryMatch(string name, string query, int[] matchIndexes, ref float cost)
{
var wordInitialsIndexes = new List<int> { 0 };
for (int i = 1; i < name.Length; i++)
{
var separators = new[] { ' ', '-', '_', '.', '(', ')', '[', ']', };
var prevChar = name[i - 1];
var curChar = name[i];
var nextChar = i + 1 < name.Length ? name[i + 1] : default(char);
var isSeparatedWordStart = separators.Contains(prevChar) && !separators.Contains(curChar);
var isCamelcaseHump = (curChar.IsUpper() && prevChar.IsLower()) || (curChar.IsUpper() && nextChar.IsLower());
var isNumberStart = curChar.IsDigit() && (!prevChar.IsDigit() || prevChar == '0');
var isAfterNumber = prevChar.IsDigit() && !curChar.IsDigit();
if (isSeparatedWordStart || isCamelcaseHump || isNumberStart || isAfterNumber)
wordInitialsIndexes.Add(i);
}
var nextWordInitialsIndexMap = new int[name.Length];
var nextWordIndex = 0;
for (int i = 0; i < name.Length; i++)
{
if (i == wordInitialsIndexes[nextWordIndex])
if (nextWordIndex + 1 < wordInitialsIndexes.Count)
nextWordIndex++;
else break;
nextWordInitialsIndexMap[i] = wordInitialsIndexes[nextWordIndex];
}
var iName = 0;
var iQuery = 0;
var prevMatchIndex = -1;
void registerMatch(int matchIndex)
{
matchIndexes[iQuery] = matchIndex;
iQuery++;
iName = matchIndex + 1;
prevMatchIndex = matchIndex;
}
cost = 0;
while (iName < name.Length && iQuery < query.Length)
{
var curQuerySymbol = query[iQuery].ToLower();
var curNameSymbol = name[iName].ToLower();
if (curNameSymbol == curQuerySymbol)
{
var gapLength = iName - prevMatchIndex - 1;
cost += gapLength;
registerMatch(iName);
continue;
// consecutive matches cost 0
// distance between index 0 and first match also counts as a gap
}
var nextWordInitialIndex = nextWordInitialsIndexMap[iName]; // wordInitialsIndexes.FirstOrDefault(i => i > iName);
var nextWordInitialSymbol = nextWordInitialIndex == default ? default : name[nextWordInitialIndex].ToLower();
if (nextWordInitialSymbol == curQuerySymbol)
{
var gapLength = nextWordInitialIndex - prevMatchIndex - 1;
cost += (gapLength * .01f).ClampMax(.9f);
registerMatch(nextWordInitialIndex);
continue;
// word-initial match costs less than a gap (1+)
// but more than a consecutive match (0)
}
iName++;
}
var allCharsMatched = iQuery >= query.Length;
return allCharsMatched;
// this search works great in practice
// but fails in more theoretical scenarios, mostly when user skips first letters of words
// eg searching "arn" won't find "barn_a" because search will jump to last a (word-initial) and fail afterwards
// so unity search is used as a fallback
}
bool tryMatch_unitySearch(string name, string query, int[] matchIndexes, ref float cost)
{
long score = 0;
List<int> matchIndexesList = new();
var matched = UnityEditor.Search.FuzzySearch.FuzzyMatch(searchString, name, ref score, matchIndexesList);
for (int i = 0; i < matchIndexesList.Count; i++)
matchIndexes[i] = matchIndexesList[i];
cost = 123212 - score;
return matched;
// this search is fast but isn't tuned for real use cases
// quering "vis" ranks "Invisible" higher than "VInspectorState"
// quering "lst" ranks "SmallShadowTemp" higher than "List"
// also sometimes it favors matches that are further away from zeroth index
}
string formatName(string name, IEnumerable<int> matchIndexes)
{
var formattedName = "";
for (int i = 0; i < name.Length; i++)
if (matchIndexes.Contains(i))
formattedName += "<b>" + name[i] + "</b>";
else
formattedName += name[i];
return formattedName;
}
var costs_byEntry = new Dictionary<SceneEntry, float>();
var matchIndexes = new int[searchString.Length];
var matchCost = 0f;
foreach (var entry in allEntries)
if (tryMatch(entry.sceneName, searchString, matchIndexes, ref matchCost) || tryMatch_unitySearch(entry.sceneName, searchString, matchIndexes, ref matchCost))
{
costs_byEntry[entry] = matchCost;
namesFormattedForFuzzySearch_byEntry[entry] = formatName(entry.sceneName, matchIndexes);
}
searchedEntries = costs_byEntry.Keys.OrderBy(r => costs_byEntry[r])
.ThenBy(r => r.sceneName)
.ToList();
}
List<SceneEntry> searchedEntries = new();
Dictionary<SceneEntry, string> namesFormattedForFuzzySearch_byEntry = new();
void OnLostFocus()
{
EditorApplication.delayCall += () =>
{
if (EditorWindow.focusedWindow != this)
{
EditorApplication.RepaintHierarchyWindow();
Close();
}
};
// delay is needed to prevent reopening after clicking + button for the second time
}
public static void Open(Vector2 rowPos, Scene sceneToReplace)
{
if (!VHierarchy.data)
{
VHierarchy.data = ScriptableObject.CreateInstance<VHierarchyData>();
AssetDatabase.CreateAsset(VHierarchy.data, GetScriptPath("VHierarchy").GetParentPath().CombinePath("vHierarchy Data.asset"));
}
instance = ScriptableObject.CreateInstance<VHierarchySceneSelectorWindow>();
instance.ShowPopup();
instance.Focus();
var width = 190;
var height = 296;
var offsetX = -14;
var offsetY = 18;
instance.position = instance.position.SetPos(rowPos + new Vector2(offsetX, offsetY)).SetSize(width, height);
instance.sceneToReplace = sceneToReplace;
}
public Scene sceneToReplace;
public static VHierarchySceneSelectorWindow instance;
}
}
#endif