This commit is contained in:
2026-06-08 23:25:33 +07:00
parent 4d83b4cdc8
commit b8b222632d
131 changed files with 21412 additions and 572 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 61e90743ef9987d44832f60b572715ef
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 842468ccf23564770b4b1cb9f7eca30e
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
{
"name": "VFavorites",
"rootNamespace": "",
"references": [],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: d8266c7db84a045d3b706b23e60aa197
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6651039474d594cdd91489768cf293f6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,225 @@
#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEditor;
using UnityEditor.ShortcutManagement;
using System.Reflection;
using System.Linq;
using UnityEngine.UIElements;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
using Type = System.Type;
using static VFavorites.VFavoritesState;
using static VFavorites.Libs.VUtils;
using static VFavorites.Libs.VGUI;
namespace VFavorites
{
public class VFavoritesData : ScriptableObject
{
public List<Page> pages = new List<Page>();
public Page curPage
{
get
{
while (curPageIndex >= pages.Count - 1)
pages.Add(new Page("Page " + (pages.Count + 1)));
return pages[curPageIndex];
}
}
public int curPageIndex { get => VFavoritesState.instance.curPageIndex; set => VFavoritesState.instance.curPageIndex = value; }
public float rowScale = 1;
[System.Serializable]
public class Page
{
public List<Item> items = new List<Item>();
public string name = "";
public Page(string name) => this.name = name;
[System.NonSerialized]
public List<float> _rowGaps = new List<float>();
public List<float> rowGaps
{
get
{
if (_rowGaps == null)
_rowGaps = new List<float>();
while (_rowGaps.Count < items.Count + 1) _rowGaps.Add(0);
while (_rowGaps.Count > items.Count + 1) _rowGaps.RemoveLast();
return _rowGaps;
}
}
public float scrollPos { get => state.scrollPos; set => state.scrollPos = value; }
public long lastItemSelectTime_ticks { get => state.lastItemSelectTime_ticks; set => state.lastItemSelectTime_ticks = value; }
public long lastItemDragTime_ticks { get => state.lastItemDragTime_ticks; set => state.lastItemDragTime_ticks = value; }
public PageState state
{
get
{
if (!VFavoritesState.instance.pageStates_byPageId.ContainsKey(id))
VFavoritesState.instance.pageStates_byPageId[id] = new PageState();
return VFavoritesState.instance.pageStates_byPageId[id];
}
}
public int id
{
get
{
if (_id == 0)
_id = Random.value.GetHashCode();
return _id;
}
}
public int _id = 0;
}
[System.Serializable]
public class Item
{
public GlobalID globalId;
public Type type => Type.GetType(_typeString) ?? typeof(DefaultAsset);
public string _typeString;
public Object obj => _obj != null ? _obj : (_obj = globalId.GetObject());
public Object _obj;
public bool isSceneGameObject;
public bool isFolder;
public bool isAsset;
public bool isLoadable => obj != null;
public bool isDeleted
{
get
{
if (!isSceneGameObject)
return !isLoadable;
if (isLoadable)
return false;
if (!AssetDatabase.LoadAssetAtPath<SceneAsset>(globalId.guid.ToPath()))
return true;
for (int i = 0; i < EditorSceneManager.sceneCount; i++)
if (EditorSceneManager.GetSceneAt(i).path == globalId.guid.ToPath())
return true;
return false;
}
}
public string assetPath => globalId.guid.ToPath();
public Item(Object o)
{
globalId = o.GetGlobalID();
isSceneGameObject = o is GameObject go && go.scene.rootCount != 0;
isFolder = AssetDatabase.IsValidFolder(o.GetPath());
isAsset = !isSceneGameObject && !isFolder;
_typeString = o.GetType().AssemblyQualifiedName;
_name = o.name;
}
public string name
{
get
{
if (!isLoadable) return _name;
if (assetPath.GetExtension() == ".cs")
_name = obj.name.Decamelcase();
else
_name = obj.name;
return _name;
}
}
public string _name { get => state._name; set => state._name = value; }
public string sceneGameObjectIconName { get => state.sceneGameObjectIconName; set => state.sceneGameObjectIconName = value; }
public long lastSelectTime_ticks { get => state.lastSelectTime_ticks; set => state.lastSelectTime_ticks = value; }
public bool isSelected { get => state.isSelected; set => state.isSelected = value; }
public ItemState state
{
get
{
if (!VFavoritesState.instance.itemStates_byItemId.ContainsKey(id))
VFavoritesState.instance.itemStates_byItemId[id] = new ItemState();
return VFavoritesState.instance.itemStates_byItemId[id];
}
}
public int id
{
get
{
if (_id == 0)
_id = Random.value.GetHashCode();
return _id;
}
}
public int _id = 0;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 066cf82f8f80d408c856e48fc8f1127b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 38092f82a4c054086826261d88277942
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,127 @@
#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using static VFavorites.Libs.VUtils;
using static VFavorites.Libs.VGUI;
namespace VFavorites
{
public class VFavoritesMenu
{
public static bool changePagesWithArrowsEnabled { get => EditorPrefs.GetBool("vFavorites-changePagesWithArrowsEnabled", true); set => EditorPrefs.SetBool("vFavorites-changePagesWithArrowsEnabled", value); }
public static bool changeSelectionWithArrowsEnabled { get => EditorPrefs.GetBool("vFavorites-changeSelectionWithArrowsEnabled", true); set => EditorPrefs.SetBool("vFavorites-changeSelectionWithArrowsEnabled", value); }
public static bool setSelectionWithNumberKeysEnabled { get => EditorPrefs.GetBool("vFavorites-setSelectionWithNumberKeysEnabled", true); set => EditorPrefs.SetBool("vFavorites-setSelectionWithNumberKeysEnabled", value); }
public static bool fadeAnimationsEnabled { get => EditorPrefs.GetBool("vFavorites-fadeAnimationsEnabled", true); set => EditorPrefs.SetBool("vFavorites-fadeAnimationsEnabled", value); }
public static bool pageScrollAnimationEnabled { get => EditorPrefs.GetBool("vFavorites-pageScrollAnimationEnabled", true); set => EditorPrefs.SetBool("vFavorites-pageScrollAnimationEnabled", value); }
public static int activeOnKeyCombination { get => EditorPrefs.GetInt("vFavorites-activeOnKeyCombination", 0); set => EditorPrefs.SetInt("vFavorites-activeOnKeyCombination", value); }
public static bool activeOnAltEnabled { get => activeOnKeyCombination == 0; set => activeOnKeyCombination = 0; }
public static bool activeOnAltShiftEnabled { get => activeOnKeyCombination == 1; set => activeOnKeyCombination = 1; }
public static bool activeOnCtrlAltEnabled { get => activeOnKeyCombination == 2; set => activeOnKeyCombination = 2; }
public static bool pluginDisabled { get => EditorPrefs.GetBool("vFavorites-pluginDisabled", false); set => EditorPrefs.SetBool("vFavorites-pluginDisabled", value); }
const string dir = "Tools/vFavorites/";
const string changePagesWithArrows = dir + "Change pages with Left or Right arrow keys";
const string changeSelectionWithArrows = dir + "Change selection with Up or Down arrow keys";
const string setSelectionWithNumberKeys = dir + "Set selection with Number keys";
const string fadeAnimations = dir + "Fade animations";
const string pageScrollAnimation = dir + "Page scroll animation";
const string activeOnAlt = dir + "Holding Alt";
const string activeOnAltShift = dir + "Holding Alt and Shift";
#if UNITY_EDITOR_OSX
const string activeOnCtrlAlt = dir + "Holding Cmd and Alt";
#else
const string activeOnCtrlAlt = dir + "Holding Ctrl and Alt";
#endif
const string disablePlugin = dir + "Disable vFavorites";
[MenuItem(dir + "Features", false, 1)] static void dadsas() { }
[MenuItem(dir + "Features", true, 1)] static bool dadsas123() => false;
[MenuItem(changePagesWithArrows, false, 2)] static void dadsadadsas() => changePagesWithArrowsEnabled = !changePagesWithArrowsEnabled;
[MenuItem(changePagesWithArrows, true, 2)] static bool dadsaddasadsas() { Menu.SetChecked(changePagesWithArrows, changePagesWithArrowsEnabled); return !pluginDisabled; }
[MenuItem(changeSelectionWithArrows, false, 3)] static void dadsadaddassas() => changeSelectionWithArrowsEnabled = !changeSelectionWithArrowsEnabled;
[MenuItem(changeSelectionWithArrows, true, 2)] static bool dadadssaddasadsas() { Menu.SetChecked(changeSelectionWithArrows, changeSelectionWithArrowsEnabled); return !pluginDisabled; }
[MenuItem(setSelectionWithNumberKeys, false, 4)] static void dadsadasdadsas() => setSelectionWithNumberKeysEnabled = !setSelectionWithNumberKeysEnabled;
[MenuItem(setSelectionWithNumberKeys, true, 4)] static bool dadsadadsdasadsas() { Menu.SetChecked(setSelectionWithNumberKeys, setSelectionWithNumberKeysEnabled); return !pluginDisabled; }
[MenuItem(dir + "Animations", false, 101)] static void dadsadsas() { }
[MenuItem(dir + "Animations", true, 101)] static bool dadadssas123() => false;
[MenuItem(fadeAnimations, false, 102)] static void dadsdasadadsas() => fadeAnimationsEnabled = !fadeAnimationsEnabled;
[MenuItem(fadeAnimations, true, 102)] static bool dadsadadsadsdasadsas() { Menu.SetChecked(fadeAnimations, fadeAnimationsEnabled); return !pluginDisabled; }
[MenuItem(pageScrollAnimation, false, 103)] static void dadsdasdasadadsas() => pageScrollAnimationEnabled = !pageScrollAnimationEnabled;
[MenuItem(pageScrollAnimation, true, 103)] static bool dadsadaddassadsdasadsas() { Menu.SetChecked(pageScrollAnimation, pageScrollAnimationEnabled); return !pluginDisabled; }
[MenuItem(dir + "Open when", false, 1001)] static void dadsaddssas() { }
[MenuItem(dir + "Open when", true, 1001)] static bool dadadsssas123() => false;
[MenuItem(activeOnAlt, false, 1002)] static void dadsdasasdadsas() => activeOnAltEnabled = !activeOnAltEnabled;
[MenuItem(activeOnAlt, true, 1002)] static bool dadsadadssdadsdasadsas() { Menu.SetChecked(activeOnAlt, activeOnAltEnabled); return !pluginDisabled; }
[MenuItem(activeOnAltShift, false, 1003)] static void dadsdasasdadsadsas() => activeOnAltShiftEnabled = !activeOnAltShiftEnabled;
[MenuItem(activeOnAltShift, true, 1003)] static bool dadsadadssdasdadsdasadsas() { Menu.SetChecked(activeOnAltShift, activeOnAltShiftEnabled); return !pluginDisabled; }
[MenuItem(activeOnCtrlAlt, false, 1004)] static void dadsdasadasadssdadsas() => activeOnCtrlAltEnabled = !activeOnCtrlAltEnabled;
[MenuItem(activeOnCtrlAlt, true, 1004)] static bool dadsadadsadssdadsdasadsas() { Menu.SetChecked(activeOnCtrlAlt, activeOnCtrlAltEnabled); return !pluginDisabled; }
[MenuItem(dir + "More", false, 10001)] static void daasadsddsas() { }
[MenuItem(dir + "More", true, 10001)] static bool dadsadsdasas123() => false;
[MenuItem(dir + "Join our Discord", false, 10002)]
static void dadasdsas() => Application.OpenURL("https://discord.gg/4dG9KsbspG");
[MenuItem(dir + "Get more Editor Enhancers/Get vHierarchy 2", false, 10003)]
static void dadadssadsas() => Application.OpenURL("https://assetstore.unity.com/packages/slug/251320?aid=1100lGLBn&pubref=menucheckout");
[MenuItem(dir + "Get more Editor Enhancers/Get vFolders 2", false, 10004)]
static void dadadssaasddsas() => Application.OpenURL("https://assetstore.unity.com/packages/slug/263644?aid=1100lGLBn&pubref=menucheckout");
[MenuItem(dir + "Get more Editor Enhancers/Get vTabs 2", false, 10005)]
static void dadadsadssaasddsas() => Application.OpenURL("https://assetstore.unity.com/packages/slug/263645?aid=1100lGLBn&pubref=menucheckout");
[MenuItem(disablePlugin, false, 100001)] static void dadsadsdasadasdasdsadadsas() { pluginDisabled = !pluginDisabled; UnityEditor.Compilation.CompilationPipeline.RequestScriptCompilation(); }
[MenuItem(disablePlugin, true, 100001)] static bool dadsaddssdaasadsadadsdasadsas() { Menu.SetChecked(disablePlugin, pluginDisabled); return true; }
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 65f8f6586ea4740238f667f8337cf6fb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,6 @@
// this file was present in a previus version and is supposed to be deleted now
// but asset store update delivery system doesn't allow deleting files
// so instead this file is now emptied
// feel free to delete it if you want

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e1b1b30cd63e14da9a295742be768842
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,57 @@
#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEditor;
using UnityEditor.ShortcutManagement;
using System.Reflection;
using System.Linq;
using UnityEngine.UIElements;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
using Type = System.Type;
using static VFavorites.Libs.VUtils;
using static VFavorites.Libs.VGUI;
namespace VFavorites
{
[FilePath("Library/vFavorites State.asset", FilePathAttribute.Location.ProjectFolder)]
public class VFavoritesState : ScriptableSingleton<VFavoritesState>
{
public int curPageIndex;
public SerializableDictionary<int, PageState> pageStates_byPageId = new SerializableDictionary<int, PageState>();
public SerializableDictionary<int, ItemState> itemStates_byItemId = new SerializableDictionary<int, ItemState>();
[System.Serializable]
public class PageState
{
public long lastItemSelectTime_ticks;
public long lastItemDragTime_ticks;
public float scrollPos;
}
[System.Serializable]
public class ItemState
{
public string _name;
public string sceneGameObjectIconName;
public long lastSelectTime_ticks;
public bool isSelected;
}
public static void Save() => instance.Save(true);
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 362e220c378db4e97ae41fa35a6fb58f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -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: 066cf82f8f80d408c856e48fc8f1127b, type: 3}
m_Name: vFavorites Data
m_EditorClassIdentifier: VFavorites::VFavorites.VFavoritesData
pages: []
rowScale: 1

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 86aa99958f6df3c46929bd75bbe78ae1
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c7dca8ae168f8ba41873023d2bbcfdb6
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 443dd991dbef94630a18f43d266b5e33
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
{
"name": "VFolders",
"rootNamespace": "",
"references": [],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3331bc437f3a24586b7e86e7bdd62b5e
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cb4ae53db31ef4fdfbfc47484afb8192
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,117 @@
#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 static VFolders.Libs.VUtils;
using static VFolders.Libs.VGUI;
namespace VFolders
{
[FilePath("Library/vFolders Cache.asset", FilePathAttribute.Location.ProjectFolder)]
public class VFoldersCache : ScriptableSingleton<VFoldersCache>
{
public Texture2D GetIcon(int key)
{
if (instance.iconTextures_byKey.ContainsKey(key)) return instance.iconTextures_byKey[key];
if (instance.iconTextureDatas_byKey.ContainsKey(key)) return instance.iconTextures_byKey[key] = instance.iconTextureDatas_byKey[key].GetTexture();
return null;
}
public void AddIcon(int key, Texture2D icon)
{
instance.iconTextures_byKey[key] = icon;
instance.iconTextureDatas_byKey[key] = new TextureData(icon);
instance.Save(true);
}
public bool HasIcon(int key) => instance.iconTextureDatas_byKey.ContainsKey(key);
public Dictionary<int, Texture2D> iconTextures_byKey = new Dictionary<int, Texture2D>();
public SerializableDictionary<int, TextureData> iconTextureDatas_byKey = new SerializableDictionary<int, TextureData>();
[System.Serializable]
public class TextureData
{
public byte[] rawData;
public int width;
public int height;
public TextureFormat format;
public int mipCount;
public float pixelsPerPoint;
public TextureData(Texture2D t)
{
rawData = t.GetRawTextureData();
width = t.width;
height = t.height;
format = t.format;
mipCount = t.mipmapCount;
pixelsPerPoint = t.GetPropertyValue<float>("pixelsPerPoint");
}
public Texture2D GetTexture()
{
var t = new Texture2D(width, height, format, mipCount, false);
t.LoadRawTextureData(rawData);
t.SetPropertyValue("pixelsPerPoint", pixelsPerPoint);
t.hideFlags = HideFlags.DontSave;
t.Apply();
return t;
}
}
public SerializableDictionary<string, FolderState> folderStates_byGuid = new SerializableDictionary<string, FolderState>();
[System.Serializable]
public class FolderState
{
public bool isEmpty;
public List<string> contentMinimapIconNames = new List<string>();
public string autoIconName = "";
public bool needsUpdate;
}
public static void Clear()
{
instance.iconTextures_byKey.Clear();
instance.iconTextureDatas_byKey.Clear();
instance.folderStates_byGuid.Clear();
instance.Save(true);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 69c14c9fceb5b4c968f55fe5786a0bee
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,90 @@
#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 static VFolders.Libs.VUtils;
using static VFolders.Libs.VGUI;
namespace VFolders
{
public class VFoldersData : ScriptableObject
{
public SerializableDictionary<string, FolderData> folderDatas_byGuid = new SerializableDictionary<string, FolderData>();
[System.Serializable]
public class FolderData
{
public int colorIndex;
public string iconNameOrGuid = "";
}
[CustomEditor(typeof(VFoldersData))]
class Editor : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
var style = EditorStyles.label;
style.wordWrap = true;
void normal()
{
if (storeDataInMetaFiles) return;
SetGUIEnabled(false);
BeginIndent(0);
Space(10);
EditorGUILayout.LabelField("This file contains data about which icons and colors are assigned to folders", style);
Space(6);
GUILayout.Label("If there are multiple people working on the project, you might want to store this data in .meta files of folders to avoid merge conflicts. To do that, click the ... button at the top right corner and click 'Store data in .meta files of folders' ", style);
EndIndent(10);
ResetGUIEnabled();
}
void meta()
{
if (!storeDataInMetaFiles) return;
SetGUIEnabled(false);
BeginIndent(0);
Space(10);
EditorGUILayout.LabelField("vFolders currently stores data in .meta files of folders", style);
Space(6);
GUILayout.Label("If you want this data to be stored in this file, click the ... button at the top right corner and click 'Store data in .meta files' ", style);
EndIndent(10);
ResetGUIEnabled();
}
normal();
meta();
}
}
public static bool storeDataInMetaFiles { get => EditorPrefs.GetBool("vFolders-storeDataInMetaFilesEnabled", false); set => EditorPrefs.SetBool("vFolders-storeDataInMetaFilesEnabled", value); }
[ContextMenu("Store data in .meta files of folders")]
public void MigrateDataBetweenMetaFilesAndSO() => storeDataInMetaFiles = !storeDataInMetaFiles; // todo
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: adb9c12a8c6c949f7af83a3d238359d0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,6 @@
// this file was present in a previus version and is supposed to be deleted now
// but asset store update delivery system doesn't allow deleting files
// so instead this file is now emptied
// feel free to delete it if you want

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fc2d205dd3ec1446d843e566b05c2eda
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d2528d4639fe84d44bfdfde62c65dc86
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,132 @@
#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using static VFolders.Libs.VUtils;
using static VFolders.Libs.VGUI;
namespace VFolders
{
class VFoldersMenu
{
public static bool hierarchyLinesEnabled { get => EditorPrefs.GetBool("vFolders-hierarchyLinesEnabled", false); set => EditorPrefs.SetBool("vFolders-hierarchyLinesEnabled", value); }
public static bool clearerRowsEnabled { get => EditorPrefs.GetBool("vFolders-clearerRowsEnabled", false); set => EditorPrefs.SetBool("vFolders-clearerRowsEnabled", value); }
public static bool minimalModeEnabled { get => EditorPrefs.GetBool("vFolders-minimalModeEnabled", false); set => EditorPrefs.SetBool("vFolders-minimalModeEnabled", value); }
public static bool zebraStripingEnabled { get => EditorPrefs.GetBool("vFolders-zebraStripingEnabled", false); set => EditorPrefs.SetBool("vFolders-zebraStripingEnabled", value); }
public static bool contentMinimapEnabled { get => EditorPrefs.GetBool("vFolders-contentMinimapEnabled", false); set => EditorPrefs.SetBool("vFolders-contentMinimapEnabled", value); }
public static bool autoIconsEnabled { get => EditorPrefs.GetBool("vFolders-autoIconsEnabled", false); set => EditorPrefs.SetBool("vFolders-autoIconsEnabled", value); }
public static bool foldersFirstEnabled { get => EditorPrefs.GetBool("vFolders-foldersFirstEnabled", false); set => EditorPrefs.SetBool("vFolders-foldersFirstEnabled", value); }
public static bool toggleExpandedEnabled { get => EditorPrefs.GetBool("vFolders-toggleExpandedEnabled", true); set => EditorPrefs.SetBool("vFolders-toggleExpandedEnabled", value); }
public static bool collapseEverythingElseEnabled { get => EditorPrefs.GetBool("vFolders-collapseEverythingElseEnabled", true); set => EditorPrefs.SetBool("vFolders-collapseEverythingElseEnabled", value); }
public static bool collapseEverythingEnabled { get => EditorPrefs.GetBool("vFolders-collapseEverythingEnabled", true); set => EditorPrefs.SetBool("vFolders-collapseEverythingEnabled", value); }
public static bool pluginDisabled { get => EditorPrefs.GetBool("vFolders-pluginDisabled", false); set => EditorPrefs.SetBool("vFolders-pluginDisabled", value); }
const string dir = "Tools/vFolders/";
const string hierarchyLines = dir + "Hierarchy lines";
const string clearerRows = dir + "Clearer rows";
const string minimalMode = dir + "Minimal mode";
const string zebraStriping = dir + "Zebra striping";
const string autoIcons = dir + "Automatic icons";
const string contentMinimap = dir + "Content minimap";
const string foldersFirst = dir + "Sort folders first";
const string toggleExpanded = dir + "E to expand or collapse";
const string collapseEverythingElse = dir + "Shift-E to collapse everything else";
const string collapseEverything = dir + "Ctrl-Shift-E to collapse everything";
const string disablePlugin = dir + "Disable vFolders";
[MenuItem(dir + "Features", false, 1)] static void daasddsas() { }
[MenuItem(dir + "Features", true, 1)] static bool dadsdasas123() => false;
[MenuItem(hierarchyLines, false, 2)] static void dadsadadsadass() { hierarchyLinesEnabled = !hierarchyLinesEnabled; EditorApplication.RepaintProjectWindow(); }
[MenuItem(hierarchyLines, true, 2)] static bool dadsaddasaasddsas() { Menu.SetChecked(hierarchyLines, hierarchyLinesEnabled); return !pluginDisabled; }
[MenuItem(clearerRows, false, 3)] static void dadsadadsadsadass() { clearerRowsEnabled = !clearerRowsEnabled; EditorApplication.RepaintProjectWindow(); }
[MenuItem(clearerRows, true, 3)] static bool dadsaddasadsaasddsas() { Menu.SetChecked(clearerRows, clearerRowsEnabled); return !pluginDisabled; }
[MenuItem(minimalMode, false, 4)] static void dadsadadsaddsasadass() { minimalModeEnabled = !minimalModeEnabled; EditorApplication.RepaintProjectWindow(); }
[MenuItem(minimalMode, true, 4)] static bool dadsaddasadsadsaasddsas() { Menu.SetChecked(minimalMode, minimalModeEnabled); return !pluginDisabled; }
[MenuItem(zebraStriping, false, 5)] static void dadsadaddsasadsadass() { zebraStripingEnabled = !zebraStripingEnabled; EditorApplication.RepaintProjectWindow(); }
[MenuItem(zebraStriping, true, 5)] static bool dadsaddadassadsaasddsas() { Menu.SetChecked(zebraStriping, zebraStripingEnabled); return !pluginDisabled; }
[MenuItem(contentMinimap, false, 6)] static void dadsadadasdsadass() { contentMinimapEnabled = !contentMinimapEnabled; EditorApplication.RepaintProjectWindow(); }
[MenuItem(contentMinimap, true, 6)] static bool dadsadddasasaasddsas() { Menu.SetChecked(contentMinimap, contentMinimapEnabled); return !pluginDisabled; }
[MenuItem(autoIcons, false, 7)] static void dadsadadsas() { autoIconsEnabled = !autoIconsEnabled; EditorApplication.RepaintProjectWindow(); }
[MenuItem(autoIcons, true, 7)] static bool dadsaddasadsas() { Menu.SetChecked(autoIcons, autoIconsEnabled); return !pluginDisabled; }
#if UNITY_EDITOR_OSX
[MenuItem(foldersFirst, false, 8)] static void dadsdsfaadsdadsas() { foldersFirstEnabled = !foldersFirstEnabled; EditorApplication.RepaintProjectWindow(); if (!foldersFirstEnabled) UnityEditor.Compilation.CompilationPipeline.RequestScriptCompilation(); }
[MenuItem(foldersFirst, true, 8)] static bool dadsasdfdadsdasadsas() { Menu.SetChecked(foldersFirst, foldersFirstEnabled); return !pluginDisabled; }
#endif
[MenuItem(dir + "Shortcuts", false, 101)] static void dadsas() { }
[MenuItem(dir + "Shortcuts", true, 101)] static bool dadsas123() => false;
[MenuItem(toggleExpanded, false, 102)] static void dadsadsadasdsadadsas() => toggleExpandedEnabled = !toggleExpandedEnabled;
[MenuItem(toggleExpanded, true, 102)] static bool dadsaddsasadadsdasadsas() { Menu.SetChecked(toggleExpanded, toggleExpandedEnabled); return !pluginDisabled; }
[MenuItem(collapseEverythingElse, false, 103)] static void dadsadsasdadasdsadadsas() => collapseEverythingElseEnabled = !collapseEverythingElseEnabled;
[MenuItem(collapseEverythingElse, true, 103)] static bool dadsaddsdasasadadsdasadsas() { Menu.SetChecked(collapseEverythingElse, collapseEverythingElseEnabled); return !pluginDisabled; }
[MenuItem(collapseEverything, false, 104)] static void dadsadsdasadasdsadadsas() => collapseEverythingEnabled = !collapseEverythingEnabled;
[MenuItem(collapseEverything, true, 104)] static bool dadsaddssdaasadadsdasadsas() { Menu.SetChecked(collapseEverything, collapseEverythingEnabled); return !pluginDisabled; }
[MenuItem(dir + "More", false, 1001)] static void daasadsddsas() { }
[MenuItem(dir + "More", true, 1001)] static bool dadsadsdasas123() => false;
[MenuItem(dir + "Join our Discord", false, 1002)]
static void dadasdsas() => Application.OpenURL("https://discord.gg/4dG9KsbspG");
[MenuItem(dir + "Check out vFavorites 2", false, 1003)]
static void dadadssadsas() => Application.OpenURL("https://assetstore.unity.com/packages/slug/263643?aid=1100lGLBn&pubref=checkoutvfav");
// [MenuItem(dir + "Get more Editor Enhancers/Get vHierarchy 2", false, 1003)]
// static void dadadssadsas() => Application.OpenURL("https://assetstore.unity.com/packages/slug/251320?aid=1100lGLBn&pubref=menucheckout");
// [MenuItem(dir + "Get more Editor Enhancers/Get vTabs 2", false, 1004)]
// static void dadadssaasddsas() => Application.OpenURL("https://assetstore.unity.com/packages/slug/263645?aid=1100lGLBn&pubref=menucheckout");
// [MenuItem(dir + "Get more Editor Enhancers/Get vFavorites 2", false, 1005)]
// static void dadadsadssaasddsas() => Application.OpenURL("https://assetstore.unity.com/packages/slug/263643?aid=1100lGLBn&pubref=menucheckout");
[MenuItem(disablePlugin, false, 10001)] static void dadsadsdasadasdasdsadadsas() { pluginDisabled = !pluginDisabled; UnityEditor.Compilation.CompilationPipeline.RequestScriptCompilation(); }
[MenuItem(disablePlugin, true, 10001)] static bool dadsaddssdaasadsadadsdasadsas() { Menu.SetChecked(disablePlugin, pluginDisabled); return true; }
// [MenuItem(dir + "Clear cache", false, 10001)]
// static void dassaadsdc() => VFoldersCache.Clear();
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f118e09f35fa241fda19f1f3b1e7c5a2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,6 @@
// this file was present in a previus version and is supposed to be deleted now
// but asset store update delivery system doesn't allow deleting files
// so instead this file is now emptied
// feel free to delete it if you want

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ec6d8bc24e3ec4cb6b055630a6425686
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,85 @@
Shader "Hidden/VFoldersOutline"
{
Properties
{
_MainTex ("Texture", Any) = "white" {}
[HDR] _Color ("Tint", Color) = (1,1,1,1)
}
CGINCLUDE
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata_t
{
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
float2 clipUV : TEXCOORD1;
};
sampler2D _MainTex;
sampler2D _GUIClipTexture;
bool _ManualTex2SRGB;
float4 _MainTex_ST;
float4 _Color;
float4x4 unity_GUIClipTextureMatrix;
v2f vert (appdata_t v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
o.vertex = UnityObjectToClipPos(v.vertex);
float3 eyePos = UnityObjectToViewPos(v.vertex);
o.clipUV = mul(unity_GUIClipTextureMatrix, float4(eyePos.xy, 0, 1.0));
o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
float4 c = tex2D(_MainTex, i.texcoord);
c.rgb = _Color.rgb;
c.a *= _Color.a;
c.a *= tex2D(_GUIClipTexture, i.clipUV).a;
return c;
}
ENDCG
SubShader
{
Blend SrcAlpha OneMinusSrcAlpha, One One
Cull Off
ZWrite Off
ZTest Always
Pass
{
CGPROGRAM
ENDCG
}
}
SubShader
{
Blend SrcAlpha OneMinusSrcAlpha
Cull Off
ZWrite Off
ZTest Always
Pass
{
CGPROGRAM
ENDCG
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 8a3e8e1270d3f40688b73ded8c1e3087
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,246 @@
#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 UnityEditorInternal;
using static VFolders.Libs.VUtils;
using static VFolders.Libs.VGUI;
namespace VFolders
{
public class VFoldersPalette : ScriptableObject
{
public List<Color> colors = new List<Color>();
public bool colorsEnabled;
public void ResetColors()
{
colors.Clear();
for (int i = 0; i < colorsCount; i++)
colors.Add(GetDefaultColor(i));
colorsEnabled = true;
this.Dirty();
}
public static Color GetDefaultColor(int colorIndex)
{
Color color = default;
void grey()
{
if (colorIndex >= greyColorsCount) return;
#if UNITY_2022_1_OR_NEWER
color = Greyscale(EditorGUIUtility.isProSkin ? .16f : .9f);
#else
color = Greyscale(EditorGUIUtility.isProSkin ? .315f : .9f);
#endif
}
void rainbowDarkTheme()
{
if (colorIndex < greyColorsCount) return;
if (!isDarkTheme) return;
var t = (colorIndex - greyColorsCount.ToFloat()) / rainbowColorsCount;
if (colorIndex == 0)
t += .01f;
if (colorIndex == 1)
t -= .02f;
if (colorIndex == 2)
t -= .015f;
if (colorIndex == 3)
t -= .01f;
if (colorIndex == 4)
t += .02f;
if (colorIndex == 5)
t += .01f;
if (colorIndex == 8)
t -= .01f;
// color = HSLToRGB(t, .61f, .57f);
color = HSLToRGB(t, .61f, .57f);
if (colorIndex == 0)
color *= 1.16f;
if (colorIndex == 1)
color *= 1.17f;
if (colorIndex == 2)
color *= 1.03f;
if (colorIndex == 6)
color *= 1.2f;
if (colorIndex == 7)
color *= 1.55f;
if (colorIndex == 8)
color *= 1.2f;
if (colorIndex == 9)
color *= 1.08f;
color.a = .1f;
}
void rainbowLightTheme()
{
if (colorIndex < greyColorsCount) return;
if (isDarkTheme) return;
color = HSLToRGB((colorIndex - greyColorsCount.ToFloat()) / rainbowColorsCount, .62f, .8f);
// color.a = .1f;
color.a = 1f;
}
grey();
rainbowDarkTheme();
rainbowLightTheme();
return color;
}
public static int greyColorsCount = 0;
public static int rainbowColorsCount = 10;
public static int colorsCount => greyColorsCount + rainbowColorsCount;
public List<IconRow> iconRows = new List<IconRow>();
[System.Serializable]
public class IconRow
{
public List<string> builtinIcons = new List<string>(); // names
public List<string> customIcons = new List<string>(); // guids
public bool enabled = true;
public bool isCustom => !builtinIcons.Any() || customIcons.Any();
public bool isEmpty => !builtinIcons.Any() && !customIcons.Any();
public int iconCount => builtinIcons.Count + customIcons.Count;
public IconRow(string[] builtinIcons) => this.builtinIcons = builtinIcons.ToList();
public IconRow() { }
}
public void ResetIcons()
{
iconRows.Clear();
iconRows.Add(new IconRow(new[]
{
"SceneAsset Icon",
"Prefab Icon",
"PrefabModel Icon",
"Material Icon",
"Texture Icon",
"Mesh Icon",
"cs Script Icon",
"Shader Icon",
"ComputeShader Icon",
"ScriptableObject Icon",
}));
iconRows.Add(new IconRow(new[]
{
"Light Icon",
"LightProbes Icon",
"LightmapParameters Icon",
"LightingDataAsset Icon",
"Cubemap Icon"
}));
iconRows.Add(new IconRow(new[]
{
"PhysicMaterial Icon",
"BoxCollider Icon",
"TerrainCollider Icon",
"MeshCollider Icon",
"WheelCollider Icon",
"Rigidbody Icon",
}));
iconRows.Add(new IconRow(new[]
{
"AudioClip Icon",
"AudioMixerController Icon",
"AudioMixerGroup Icon",
"AudioEchoFilter Icon",
"AudioSource Icon",
}));
iconRows.Add(new IconRow(new[]
{
"TextAsset Icon",
"AssemblyDefinitionAsset Icon",
"TerrainData Icon",
"Terrain Icon",
"AnimatorController Icon",
"AnimationClip Icon",
"Font Icon",
"RawImage Icon",
"Settings Icon",
}));
this.Dirty();
}
[ContextMenu("Export palette")]
public void Export()
{
var packagePath = EditorUtility.SaveFilePanel("Export vHierarchy Palette", "", this.GetPath().GetFilename(withExtension: false), "unitypackage");
var iconPaths = iconRows.SelectMany(r => r.customIcons).Select(r => r.ToPath()).Where(r => !r.IsNullOrEmpty());
AssetDatabase.ExportPackage(iconPaths.Append(this.GetPath()).ToArray(), packagePath);
EditorUtility.RevealInFinder(packagePath);
}
void Reset() { ResetColors(); ResetIcons(); }
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 618f730fcd14941fab38169a7dde8c64
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,723 @@
#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.ShortcutManagement;
using System.Reflection;
using System.Linq;
using UnityEditorInternal;
using UnityEngine.UIElements;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
using static VFolders.Libs.VUtils;
using static VFolders.Libs.VGUI;
using static VFolders.VFoldersPalette;
namespace VFolders
{
[CustomEditor(typeof(VFoldersPalette))]
public class VFoldersPaletteEditor : Editor
{
public override void OnInspectorGUI()
{
void colors()
{
var rowRect = ExpandWidthLabelRect(cellSize).SetX(rowsOffsetX).SetWidth(rowWidth);
void backgroundHovered()
{
if (!rowRect.IsHovered()) return;
if (pickingColor) return;
if (draggingRow) return;
rowRect.Draw(hoveredRowBackground);
}
void toggle()
{
var toggleRect = rowRect.SetWidth(16).MoveX(5);
var prevEnabled = palette.colorsEnabled;
var newEnabled = EditorGUI.Toggle(toggleRect, palette.colorsEnabled);
if (prevEnabled != newEnabled)
palette.RecordUndo();
palette.colorsEnabled = newEnabled;
if (prevEnabled != newEnabled)
palette.Dirty();
}
void crossIcon()
{
var crossIconRect = rowRect.SetX(rowsOffsetX + iconsOffsetX + iconSpacing / 2).SetWidth(iconSize).SetHeightFromMid(iconSize);
SetGUIColor(palette.colorsEnabled ? Color.white : disabledRowTint);
SetLabelAlignmentCenter();
GUI.Label(crossIconRect, EditorGUIUtility.IconContent("CrossIcon"));
ResetGUIColor();
ResetLabelStyle();
}
void color(int i)
{
var cellRect = rowRect.MoveX(iconsOffsetX + (i + 1) * cellSize).SetWidth(cellSize).SetHeightFromMid(cellSize);
void backgroundPicking()
{
if (!pickingColor) return;
if (i != pickingColorAtIndex) return;
cellRect.DrawWithRoundedCorners(pickingBackground, 2);
}
void color()
{
var tint = palette.colorsEnabled ? Color.white : disabledRowTint;
var brightness = 1.00f;
var outlineColor = Greyscale(.15f, .2f);
cellRect.Resize(3).DrawWithRoundedCorners(outlineColor * tint, 4);
cellRect.Resize(4).DrawWithRoundedCorners(palette.colors[i].SetAlpha(1) * brightness * tint, 3);
cellRect.Resize(4).AddWidthFromRight(-2).DrawCurtainLeft(GUIColors.windowBackground.SetAlpha((1 - palette.colors[i].a) * .5f));
}
void startPickingColorButton()
{
if (!palette.colorsEnabled) return;
if (!cellRect.IsHovered()) return;
if (pickingColor) return;
var clicked = GUI.Button(cellRect.Resize(1), "");
GUI.Label(cellRect.Resize(.5f), EditorGUIUtility.IconContent("Preset.Context"));
if (!clicked) return;
colorPicker = OpenColorPicker((c) => { palette.RecordUndo(); palette.Dirty(); palette.colors[i] = c; }, palette.colors[i], showAlpha: true, false);
colorPicker.MoveTo(EditorGUIUtility.GUIToScreenPoint(cellRect.Move(-3, 50).position));
pickingColor = true;
pickingColorAtIndex = i;
}
void updatePickingColor()
{
if (!pickingColor) return;
EditorApplication.RepaintProjectWindow();
}
void stopPickingColor()
{
if (!pickingColor) return;
if (colorPicker) return;
pickingColor = false;
}
cellRect.MarkInteractive();
backgroundPicking();
color();
startPickingColorButton();
updatePickingColor();
stopPickingColor();
}
backgroundHovered();
toggle();
crossIcon();
for (int i = 0; i < palette.colors.Count; i++)
color(i);
Space(rowSpacing - 2);
}
void icons()
{
void row(Rect rowRect, IconRow row)
{
var isLastRow = row == palette.iconRows.Last();
var isDraggedRow = row == draggedRow;
var spaceForCrossIcon = 0f;
void startPickingIcon(int i, Rect cellRect)
{
iconPicker = OpenObjectPicker<Texture2D>(AssetDatabase.LoadAssetAtPath<Texture2D>(row.customIcons[i].ToPath()), controlID: 123);
iconPicker.MoveTo(EditorGUIUtility.GUIToScreenPoint(cellRect.Move(-3, 50).position));
pickingIcon = true;
pickingIconAtIndex = i;
pickingIconAtRow = row;
}
void updatePickingIcon()
{
if (!pickingIcon) return;
if (pickingIconAtRow != row) return;
if (EditorGUIUtility.GetObjectPickerControlID() != 123) return;
if (pickingIconAtIndex >= row.customIcons.Count) return; // somehow happens if RecordUndo is used
palette.RecordUndo();
palette.Dirty();
row.customIcons[pickingIconAtIndex] = (EditorGUIUtility.GetObjectPickerObject() as Texture2D).GetPath().ToGuid();
}
void stopPickingIcon()
{
if (!pickingIcon) return;
if (pickingIconAtRow != row) return;
if (iconPicker) return;
if (pickingIconAtIndex < row.customIcons.Count)
if (row.customIcons[pickingIconAtIndex] == null)
row.customIcons.RemoveAt(pickingIconAtIndex);
pickingIcon = false;
}
void dragndrop()
{
if (!rowRect.IsHovered()) return;
if (curEvent.isDragUpdate && DragAndDrop.objectReferences.First() is Texture2D)
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
if (!curEvent.isDragPerform) return;
if (!(DragAndDrop.objectReferences.Any(r => r is Texture2D))) return;
DragAndDrop.AcceptDrag();
palette.RecordUndo();
palette.Dirty();
foreach (var icon in DragAndDrop.objectReferences.Where(r => r is Texture2D))
row.customIcons.Add(icon.GetPath().ToGuid());
}
void calcSpaceForCrossIcon()
{
if (row == curFirstEnabledRow)
spaceForCrossIcon = crossIconAnimationT * cellSize;
if (row == crossIconAnimationSourceRow)
spaceForCrossIcon = (1 - crossIconAnimationT) * cellSize;
}
void backgroundHovered()
{
if (!rowRect.IsHovered()) return;
if (pickingColor) return;
if (pickingIcon) return;
if (draggingRow) return;
rowRect.Draw(hoveredRowBackground);
}
void backgroundDragged()
{
if (!isDraggedRow) return;
rowRect.DrawBlurred(Greyscale(0, .3f), 12);
rowRect.Draw(draggedRowBackground);
}
void toggle()
{
var prevEnabled = row.enabled;
var newEnabled = EditorGUI.Toggle(rowRect.SetWidth(16).MoveX(5), row.enabled);
if (prevEnabled != newEnabled)
palette.RecordUndo();
row.enabled = newEnabled;
if (prevEnabled != newEnabled)
palette.Dirty();
}
void addIconButton()
{
if (!row.isCustom) return;
var cellRect = rowRect.MoveX(iconsOffsetX + row.customIcons.Count * cellSize + spaceForCrossIcon).SetWidth(cellSize).SetHeightFromMid(cellSize);
SetGUIColor(Greyscale(1, row.enabled ? 1 : .5f));
var clicked = GUI.Button(cellRect.Resize(1), "");
ResetGUIColor();
SetGUIColor(Greyscale(1, row.enabled ? 1 : .5f));
SetLabelAlignmentCenter();
GUI.Label(cellRect.Resize(1), EditorGUIUtility.IconContent("Toolbar Plus"));
ResetLabelStyle();
ResetGUIColor();
if (!clicked) return;
palette.RecordUndo();
row.customIcons.Add(null);
startPickingIcon(row.customIcons.Count - 1, cellRect);
}
void icon(int i)
{
var cellRect = rowRect.MoveX(iconsOffsetX + spaceForCrossIcon + i * cellSize).SetWidth(cellSize).SetHeightFromMid(cellSize);
var isCustomIcon = i > row.builtinIcons.Count - 1;
void backgroundPicking()
{
if (!pickingIcon) return;
if (row != pickingIconAtRow) return;
if (i != pickingIconAtIndex) return;
cellRect.Resize(1).DrawWithRoundedCorners(pickingBackground, 2);
}
void drawBuiltin()
{
if (isCustomIcon) return;
SetLabelAlignmentCenter();
SetGUIColor(row.enabled ? Color.white : disabledRowTint);
GUI.Label(cellRect.SetSizeFromMid(iconSize), EditorGUIUtility.IconContent(row.builtinIcons[i]));
ResetLabelStyle();
ResetGUIColor();
}
void drawCustom()
{
if (!isCustomIcon) return;
if (cellRect.IsHovered()) return;
if (!(AssetDatabase.LoadAssetAtPath<Texture2D>(row.customIcons[i - row.builtinIcons.Count].ToPath()) is Texture2D texture)) return;
SetGUIColor(row.enabled ? Color.white : disabledRowTint);
GUI.DrawTexture(cellRect.SetSizeFromMid(iconSize), texture);
ResetGUIColor();
}
void editCustomButton()
{
if (!isCustomIcon) return;
if (!cellRect.IsHovered()) return;
if (pickingIcon) return;
var clicked = GUI.Button(cellRect.Resize(1), "");
GUI.Label(cellRect.Resize(.5f), EditorGUIUtility.IconContent("Preset.Context"));
if (!clicked) return;
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent("Replace icon"), false, () => { palette.RecordUndo(); palette.Dirty(); startPickingIcon(i, cellRect.MoveY(75)); });
menu.AddItem(new GUIContent("Remove icon"), false, () => { palette.RecordUndo(); row.customIcons.RemoveAt(i); palette.Dirty(); });
menu.ShowAsContext();
}
cellRect.MarkInteractive();
backgroundPicking();
drawBuiltin();
drawCustom();
editCustomButton();
}
rowRect.MarkInteractive();
updatePickingIcon();
stopPickingIcon();
dragndrop();
calcSpaceForCrossIcon();
backgroundHovered();
backgroundDragged();
toggle();
addIconButton();
for (int i = 0; i < row.iconCount; i++)
icon(i);
}
void updateRowsCount()
{
palette.iconRows.RemoveAll(r => r.isEmpty && r != palette.iconRows.Last());
if (!palette.iconRows.Last().isEmpty)
palette.iconRows.Add(new IconRow());
}
void updateRowGapsCount()
{
while (rowGaps.Count < palette.iconRows.Count)
rowGaps.Add(0);
while (rowGaps.Count > palette.iconRows.Count)
rowGaps.RemoveLast();
}
void normalRow(int i)
{
Space(rowGaps[i] * (cellSize + rowSpacing));
if (i == 0 && lastRect.y != 0)
firstRowY = lastRect.y;
Space(cellSize + rowSpacing);
var rowRect = Rect.zero.SetPos(rowsOffsetX, lastRect.y).SetSize(rowWidth, cellSize);
if (curEvent.isRepaint)
if (rowRect.IsHovered())
hoveredRow = palette.iconRows[i];
row(rowRect, palette.iconRows[i]);
}
void draggedRow_()
{
if (!draggingRow) return;
draggedRowY = (curEvent.mousePosition.y + draggedRowHoldOffset).Clamp(firstRowY, firstRowY + (palette.iconRows.Count - 1) * (cellSize + rowSpacing));
var rowRect = Rect.zero.SetPos(rowsOffsetX, draggedRowY).SetSize(rowWidth, cellSize);
row(rowRect, draggedRow);
}
void crossIcon()
{
if (!palette.iconRows.Any(r => r.enabled)) return;
var rect = Rect.zero.SetPos(rowsOffsetX + iconsOffsetX, crossIconY).SetSize(cellSize, cellSize).Resize(iconSpacing / 2);
SetLabelAlignmentCenter();
GUI.Label(rect, EditorGUIUtility.IconContent("CrossIcon"));
ResetLabelStyle();
}
updateRowsCount();
updateRowGapsCount();
if (curEvent.isRepaint)
hoveredRow = null;
for (int i = 0; i < palette.iconRows.Count; i++)
normalRow(i);
crossIcon();
draggedRow_();
}
void tutor()
{
SetGUIEnabled(false);
GUILayout.Label("Click a color to edit it");
Space(4);
GUILayout.Label("Click '+' to add a custom icon");
Space(4);
GUILayout.Label("Click a custom icon to replace or remove it");
Space(4);
GUILayout.Label("Drag rows to reorder them");
ResetGUIEnabled();
}
Space(15);
colors();
Space(15);
icons();
Space(25);
tutor();
UpdateAnimations();
UpdateDragging();
palette.Dirty();
if (draggingRow || animatingCrossIcon)
Repaint();
}
float iconSize => 18;
float iconSpacing => 2;
float cellSize => iconSize + iconSpacing;
float rowSpacing = 1;
float rowsOffsetX => 14;
float iconsOffsetX => 27;
Color hoveredRowBackground => Greyscale(isDarkTheme ? 1 : 0, .05f);
Color draggedRowBackground => Greyscale(isDarkTheme ? .3f : .9f);
Color pickingBackground => new Color(.3f, .5f, .7f, .8f);// Greyscale(1, .17f);
Color colorOutline => Greyscale(.2f, .5f);
Color disabledRowTint => Greyscale(1, .45f);
float rowWidth => cellSize * Mathf.Max(palette.colors.Count, palette.iconRows.Max(r => r.iconCount + 1)) + 55;
bool pickingColor;
int pickingColorAtIndex;
EditorWindow colorPicker;
bool pickingIcon;
int pickingIconAtIndex;
IconRow pickingIconAtRow;
EditorWindow iconPicker;
IconRow hoveredRow;
float firstRowY = 51;
void UpdateAnimations()
{
void calcDeltaTime()
{
if (!curEvent.isLayout) return;
deltaTime = (float)(EditorApplication.timeSinceStartup - lastLayoutTime);
if (deltaTime > .05f)
deltaTime = .0166f;
lastLayoutTime = EditorApplication.timeSinceStartup;
}
void lerpRowGaps()
{
if (!curEvent.isLayout) return;
var lerpSpeed = draggingRow ? 12 : 12321;
for (int i = 0; i < rowGaps.Count; i++)
rowGaps[i] = Lerp(rowGaps[i], draggingRow && i == insertDraggedRowAtIndex ? 1 : 0, lerpSpeed, deltaTime);// todo deltatime
for (int i = 0; i < rowGaps.Count; i++)
if (rowGaps[i].Approx(0))
rowGaps[i] = 0;
else if (rowGaps[i].Approx(1))
rowGaps[i] = 1;
}
void lerpCrossIconAnimationT()
{
if (!curEvent.isLayout) return;
var lerpSpeed = 12;
Lerp(ref crossIconAnimationT, 1, lerpSpeed, deltaTime);
}
void startCrossIconAnimation()
{
if (prevFirstEnabledRow == null) { prevFirstEnabledRow = curFirstEnabledRow; return; }
if (prevFirstEnabledRow == curFirstEnabledRow) return;
crossIconAnimationT = 0;
crossIconAnimationSourceRow = prevFirstEnabledRow;
prevFirstEnabledRow = curFirstEnabledRow;
}
void stopCrossIconAnimation()
{
if (!crossIconAnimationT.Approx(1)) return;
crossIconAnimationT = 1;
crossIconAnimationSourceRow = null;
}
void calcCrossIconY()
{
var indexOfFirstEnabled = palette.iconRows.IndexOfFirst(r => r.enabled);
var yOfFirstEnabled = firstRowY + indexOfFirstEnabled * (cellSize + rowSpacing);
for (int i = 0; i < indexOfFirstEnabled + 1; i++)
yOfFirstEnabled += rowGaps[i] * (cellSize + rowSpacing);
var indexOfSourceRow = palette.iconRows.IndexOf(crossIconAnimationSourceRow);
var yOfSourceRow = firstRowY + indexOfSourceRow * (cellSize + rowSpacing);
for (int i = 0; i < indexOfSourceRow + 1; i++)
yOfSourceRow += rowGaps[i] * (cellSize + rowSpacing);
if (crossIconAnimationSourceRow == draggedRow)
yOfSourceRow = draggedRowY;
crossIconY = Lerp(yOfSourceRow, yOfFirstEnabled, crossIconAnimationT);
if (indexOfFirstEnabled == indexOfSourceRow) { crossIconAnimationT = 1; }
}
calcDeltaTime();
lerpRowGaps();
lerpCrossIconAnimationT();
startCrossIconAnimation();
stopCrossIconAnimation();
calcCrossIconY();
}
List<float> rowGaps = new List<float>();
float deltaTime;
double lastLayoutTime;
float crossIconY = 51;
float crossIconAnimationT = 1;
IconRow crossIconAnimationSourceRow;
bool animatingCrossIcon => crossIconAnimationT != 1;
IconRow prevFirstEnabledRow;
IconRow curFirstEnabledRow => palette.iconRows.FirstOrDefault(r => r.enabled);
void UpdateDragging()
{
void startDragging()
{
if (draggingRow) return;
if (!curEvent.isMouseDrag) return;
if (hoveredRow == null) return;
if (hoveredRow == palette.iconRows.Last()) return;
palette.RecordUndo();
draggingRow = true;
draggedRow = hoveredRow;
draggingRowFromIndex = palette.iconRows.IndexOf(hoveredRow);
draggedRowHoldOffset = firstRowY + draggingRowFromIndex * (cellSize + rowSpacing) - curEvent.mousePosition.y;
palette.iconRows.Remove(hoveredRow);
rowGaps[draggingRowFromIndex] = 1;
}
void updateDragging()
{
if (!draggingRow) return;
insertDraggedRowAtIndex = ((curEvent.mousePosition.y - firstRowY) / (cellSize + rowSpacing)).FloorToInt().Clamp(0, palette.iconRows.Count - 1);
EditorGUIUtility.hotControl = EditorGUIUtility.GetControlID(FocusType.Passive);
}
void stopDragging()
{
if (!draggingRow) return;
if (!curEvent.isMouseUp) return;
palette.RecordUndo();
palette.Dirty();
palette.iconRows.AddAt(draggedRow, insertDraggedRowAtIndex);
rowGaps[insertDraggedRowAtIndex] = 0;
draggingRow = false;
draggedRow = null;
EditorGUIUtility.hotControl = 0;
}
startDragging();
updateDragging();
stopDragging();
}
IconRow draggedRow;
bool draggingRow;
int draggingRowFromIndex;
float draggedRowHoldOffset;
float draggedRowY;
int insertDraggedRowAtIndex;
VFoldersPalette palette => target as VFoldersPalette;
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 085d323b143d5403fb4beda728e65139
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,566 @@
#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 Type = System.Type;
using static VFolders.Libs.VUtils;
using static VFolders.Libs.VGUI;
using static VFolders.VFolders;
using static VFolders.VFoldersData;
using static VFolders.VFoldersPalette;
using static VFolders.VFoldersCache;
namespace VFolders
{
public class VFoldersPaletteWindow : EditorWindow
{
void OnGUI()
{
if (!palette) { Close(); return; }
int hoveredColorIndex = -1;
string hoveredIconNameOrGuid = null;
void background()
{
position.SetPos(0, 0).Draw(windowBackground);
}
void outline()
{
if (Application.platform == RuntimePlatform.OSXEditor) return;
position.SetPos(0, 0).DrawOutline(Greyscale(.1f));
}
void colors()
{
if (!palette.colorsEnabled) { Space(-spaceAfterColors); return; }
var rowRect = ExpandWidthLabelRect(height: cellSize).SetX(paddingX);
void color(int i)
{
var cellRect = rowRect.MoveX(i * cellSize).SetWidth(cellSize).SetHeightFromMid(cellSize);
void backgroundSelected()
{
if (!initialColorIndexes.Contains(i)) return;
cellRect.Resize(1).DrawWithRoundedCorners(selectedBackground, 2);
}
void backgroundHovered()
{
if (!cellRect.IsHovered()) return;
cellRect.Resize(1).DrawWithRoundedCorners(this.hoveredBackground, 2);
}
void crossIcon()
{
if (i != 0) return;
SetLabelAlignmentCenter();
GUI.Label(cellRect.SetSizeFromMid(iconSize), EditorGUIUtility.IconContent("CrossIcon"));
ResetLabelStyle();
}
void color()
{
if (i == 0) return;
var brightness = 1.00f;
var outlineColor = Greyscale(.15f, .2f);
cellRect.Resize(3).DrawWithRoundedCorners(outlineColor, 4);
cellRect.Resize(4).DrawWithRoundedCorners((palette.colors[i - 1] * brightness).SetAlpha(1), 3);
cellRect.Resize(4).AddWidthFromRight(-2).DrawCurtainLeft(GUIColors.windowBackground.SetAlpha((1 - palette.colors[i - 1].a) * .45f));
// cellRect.Resize(4).AddWidthFromRight(-2).DrawCurtainLeft(GUIColors.windowBackground.SetAlpha((1 - .1f) * .45f));
}
void setHovered()
{
if (!cellRect.IsHovered()) return;
hoveredColorIndex = i;
}
void closeOnClick()
{
if (!cellRect.IsHovered()) return;
if (!curEvent.isMouseDown) return;
Close();
}
cellRect.MarkInteractive();
backgroundSelected();
backgroundHovered();
crossIcon();
color();
setHovered();
closeOnClick();
}
for (int i = 0; i < palette.colors.Count + 1; i++)
color(i);
}
void icons()
{
void row(IconRow iconRow)
{
if (!iconRow.enabled) return;
if (iconRow.isEmpty) return;
var rowRect = ExpandWidthLabelRect(height: cellSize).SetX(paddingX);
var isFirstEnabledRow = palette.iconRows.First(r => r.enabled) == iconRow;
void icon(int i)
{
var cellRect = rowRect.MoveX(i * cellSize).SetWidth(cellSize).SetHeightFromMid(cellSize);
var isCrossIcon = isFirstEnabledRow && i == 0;
var actualIconIndex = isFirstEnabledRow ? i - 1 : i;
var isBuiltinIcon = !isCrossIcon && actualIconIndex < iconRow.builtinIcons.Count;
var isCustomIcon = !isCrossIcon && actualIconIndex >= iconRow.builtinIcons.Count;
var iconNameOrGuid = isCrossIcon ? "" : isCustomIcon ? iconRow.customIcons[actualIconIndex - iconRow.builtinIcons.Count] : iconRow.builtinIcons[actualIconIndex];
void backgroundSelected()
{
if (!initialIconNamesOrGuids.Contains(iconNameOrGuid)) return;
cellRect.Resize(1).DrawWithRoundedCorners(selectedBackground, 2);
}
void backgroundHovered()
{
if (!cellRect.IsHovered()) return;
cellRect.Resize(1).DrawWithRoundedCorners(this.hoveredBackground, 2);
}
void crossIcon()
{
if (!isCrossIcon) return;
SetLabelAlignmentCenter();
GUI.Label(cellRect.SetSizeFromMid(iconSize), EditorGUIUtility.IconContent("CrossIcon"));
ResetLabelStyle();
}
void builtinIcon()
{
if (!isBuiltinIcon) return;
SetLabelAlignmentCenter();
GUI.Label(cellRect.SetSizeFromMid(iconSize), EditorGUIUtility.IconContent(iconNameOrGuid));
ResetLabelStyle();
}
void customIcon()
{
if (!isCustomIcon) return;
var texture = AssetDatabase.LoadAssetAtPath<Texture2D>(iconNameOrGuid.ToPath());
GUI.DrawTexture(cellRect.SetSizeFromMid(iconSize), texture ?? Texture2D.blackTexture);
}
void setHovered()
{
if (!cellRect.IsHovered()) return;
hoveredIconNameOrGuid = iconNameOrGuid;
}
void closeOnClick()
{
if (!cellRect.IsHovered()) return;
if (!curEvent.isMouseDown) return;
Close();
}
cellRect.MarkInteractive();
backgroundSelected();
backgroundHovered();
crossIcon();
builtinIcon();
customIcon();
setHovered();
closeOnClick();
}
for (int i = 0; i < iconRow.iconCount + (isFirstEnabledRow ? 1 : 0); i++)
icon(i);
Space(rowSpacing - 2);
}
for (int i = 0; i < palette.iconRows.Count; i++)
row(palette.iconRows[i]);
}
void setColorsAndIcons()
{
if (!curEvent.isRepaint) return;
if (palette.iconRows.Any(r => r.enabled))
if (hoveredIconNameOrGuid != null)
SetIcon(hoveredIconNameOrGuid);
else
SetInitialIcons();
if (palette.colorsEnabled)
if (hoveredColorIndex != -1)
SetColor(hoveredColorIndex);
else
SetInitialColors();
}
void updatePosition()
{
if (!curEvent.isLayout) return;
void calcDeltaTime()
{
deltaTime = (float)(EditorApplication.timeSinceStartup - lastLayoutTime);
if (deltaTime > .05f)
deltaTime = .0166f;
lastLayoutTime = EditorApplication.timeSinceStartup;
}
void resetCurPos()
{
if (currentPosition != default) return;
currentPosition = position.position; // position.position is always int, which can't be used for lerping
}
void lerpCurPos()
{
var speed = 9;
SmoothDamp(ref currentPosition, targetPosition, speed, ref positionDeriv, deltaTime);
// Lerp(ref currentPosition, targetPosition, speed, deltaTime);
}
void setCurPos()
{
position = position.SetPos(currentPosition);
}
calcDeltaTime();
resetCurPos();
lerpCurPos();
setCurPos();
if (!currentPosition.magnitude.Approx(targetPosition.magnitude))
Repaint();
}
void closeOnEscape()
{
if (!curEvent.isKeyDown) return;
if (curEvent.keyCode != KeyCode.Escape) return;
SetInitialColors();
SetInitialIcons();
Close();
}
RecordUndoOnDatas();
background();
outline();
Space(paddingY);
colors();
Space(spaceAfterColors);
icons();
setColorsAndIcons();
updatePosition();
closeOnEscape();
EditorApplication.RepaintProjectWindow();
EditorApplication.delayCall += EditorApplication.RepaintProjectWindow; // to show icons that will be generated in update
}
static float iconSize => 18;
static float iconSpacing => 2;
static float cellSize => iconSize + iconSpacing;
static float spaceAfterColors => 11;
public float rowSpacing = 1;
static float paddingX => 12;
static float paddingY => 12;
Color windowBackground => isDarkTheme ? Greyscale(.23f) : Greyscale(.7f);
Color selectedBackground => isDarkTheme ? new Color(.3f, .5f, .7f, .8f) : new Color(.3f, .5f, .7f, .4f) * 1.35f;
Color hoveredBackground = Greyscale(1, .3f);
Color colorOutline => Greyscale(.2f, .5f);
public Vector2 targetPosition;
public Vector2 currentPosition;
Vector2 positionDeriv;
float deltaTime;
double lastLayoutTime;
void SetIcon(string iconNameOrGuid)
{
foreach (var r in folderInfos)
r.iconNameOrGuid = iconNameOrGuid;
}
void SetColor(int colorIndex)
{
foreach (var r in folderInfos)
r.folderData.colorIndex = colorIndex;
}
void SetInitialIcons()
{
for (int i = 0; i < folderInfos.Count; i++)
folderInfos[i].iconNameOrGuid = initialIconNamesOrGuids[i];
}
void SetInitialColors()
{
for (int i = 0; i < folderInfos.Count; i++)
folderInfos[i].folderData.colorIndex = initialColorIndexes[i];
}
void RemoveEmptyFolderDatas()
{
if (VFoldersData.storeDataInMetaFiles) return; // empties removed from meta files in SaveData()
var toRemove = folderInfos.Select(r => r.folderData).Where(r => r.iconNameOrGuid == "" && r.colorIndex == 0);
foreach (var r in toRemove)
data.folderDatas_byGuid.RemoveValue(r);
if (toRemove.Any())
Undo.CollapseUndoOperations(Undo.GetCurrentGroup() - 1);
}
void RecordUndoOnDatas()
{
if (!VFoldersData.storeDataInMetaFiles)
if (data)
data.RecordUndo();
if (VFoldersData.storeDataInMetaFiles)
foreach (var r in guids)
AssetImporter.GetAtPath(r.ToPath()).RecordUndo();
}
void MarkDatasDirty()
{
if (!VFoldersData.storeDataInMetaFiles)
if (data)
data.Dirty();
if (VFoldersData.storeDataInMetaFiles)
VFolders.folderDatasFromMetaFiles_byGuid.Clear();
}
void SaveData()
{
if (!VFoldersData.storeDataInMetaFiles) { data.Save(); return; }
for (int i = 0; i < guids.Count; i++)
AssetImporter.GetAtPath(guids[i].ToPath()).userData = folderInfos[i].folderData.iconNameOrGuid == "" && folderInfos[i].folderData.colorIndex == 0 ? "" : JsonUtility.ToJson(folderInfos[i].folderData);
for (int i = 0; i < guids.Count; i++)
AssetImporter.GetAtPath(guids[i].ToPath()).SaveAndReimport();
}
void OnLostFocus()
{
if (curEvent.holdingAlt && EditorWindow.focusedWindow?.GetType().Name == "ProjectBrowser")
CloseNextFrameIfNotRefocused();
else
Close();
}
void CloseNextFrameIfNotRefocused()
{
EditorApplication.delayCall += () => { if (EditorWindow.focusedWindow != this) Close(); };
}
public void Init(List<string> guids)
{
void createData()
{
if (VFolders.data) return;
VFolders.data = ScriptableObject.CreateInstance<VFoldersData>();
AssetDatabase.CreateAsset(VFolders.data, GetScriptPath("VFolders").GetParentPath().CombinePath("vFolders Data.asset"));
}
void createPalette()
{
if (VFolders.palette) return;
VFolders.palette = ScriptableObject.CreateInstance<VFoldersPalette>();
AssetDatabase.CreateAsset(VFolders.palette, GetScriptPath("VFolders").GetParentPath().CombinePath("vFolders Palette.asset"));
}
void setSize()
{
var rowCellCounts = new List<int>();
if (palette.colorsEnabled)
rowCellCounts.Add(palette.colors.Count + 1);
foreach (var r in palette.iconRows.Where(r => r.enabled))
rowCellCounts.Add(r.iconCount + (r == palette.iconRows.First(r => r.enabled) ? 1 : 0));
var width = rowCellCounts.Max() * cellSize + paddingX * 2;
var iconRowCount = palette.iconRows.Count(r => r.enabled && !r.isEmpty);
var rowCount = iconRowCount + (palette.colorsEnabled ? 1 : 0);
var height = rowCount * (cellSize + rowSpacing) + (palette.colorsEnabled && palette.iconRows.Any(r => r.enabled && !r.isEmpty) ? spaceAfterColors : 0) + paddingY * 2;
position = position.SetSize(width, height).SetPos(targetPosition);
}
void getInfos()
{
folderInfos.Clear();
foreach (var r in guids)
folderInfos.Add(VFolders.GetFolderInfo(r, createDataIfDoesntExist: true));
}
void getInitColorsAndIcons()
{
initialColorIndexes.Clear();
initialIconNamesOrGuids.Clear();
foreach (var r in folderInfos)
initialColorIndexes.Add(r.folderData.colorIndex);
foreach (var r in folderInfos)
initialIconNamesOrGuids.Add(r.iconNameOrGuid);
}
this.guids = guids;
RecordUndoOnDatas();
createData();
createPalette();
setSize();
getInfos();
getInitColorsAndIcons();
Undo.undoRedoPerformed -= EditorApplication.RepaintProjectWindow;
Undo.undoRedoPerformed += EditorApplication.RepaintProjectWindow;
}
void OnDestroy()
{
RemoveEmptyFolderDatas();
MarkDatasDirty();
SaveData();
}
public List<string> guids = new List<string>();
public List<FolderInfo> folderInfos = new List<FolderInfo>();
public List<int> initialColorIndexes = new List<int>();
public List<string> initialIconNamesOrGuids = new List<string>();
static VFoldersPalette palette => VFolders.palette;
static VFoldersData data => VFolders.data;
public static void CreateInstance(Vector2 position)
{
instance = ScriptableObject.CreateInstance<VFoldersPaletteWindow>();
instance.ShowPopup();
instance.position = instance.position.SetPos(position).SetSize(200, 300);
instance.targetPosition = position;
}
public static VFoldersPaletteWindow instance;
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 68011e63381a84f3bacee6e5ee9e0b82
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: dd2b9e231b0ec4a9f97e258072ae2b33
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: d8e44b0f278584fbfa8ae00d01b2ce3f
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
{
"name": "VHierarchy",
"rootNamespace": "",
"references": [],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 2c3f48364a5004fd3a152fbdf5fea703
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 67e949be20d3641adbc9494ed5bd764e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,62 @@
#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 Type = System.Type;
using static VHierarchy.VHierarchyData;
using static VHierarchy.Libs.VUtils;
using static VHierarchy.Libs.VGUI;
namespace VHierarchy
{
[FilePath("Library/vHierarchy Cache.asset", FilePathAttribute.Location.ProjectFolder)]
public class VHierarchyCache : ScriptableSingleton<VHierarchyCache>
{
// used for finding SceneData and SceneIdMap for objects that were moved out of their original scene
public SerializableDictionary<int, string> originalSceneGuids_byInstanceId = new SerializableDictionary<int, string>();
// used as cache for converting GlobalID to InstanceID and as a way to find GameObjectData for prefabs in playmode (when prefabs produce invalid GlobalIDs)
public SerializableDictionary<string, SceneIdMap> sceneIdMaps_bySceneGuid = new SerializableDictionary<string, SceneIdMap>();
// used for fetching icons set inside prefab instances in playmode (when prefabs produce invalid GlobalIDs)
public SerializableDictionary<int, GlobalID> prefabInstanceGlobalIds_byInstanceIds = new SerializableDictionary<int, GlobalID>();
[System.Serializable]
public class SceneIdMap
{
public SerializableDictionary<int, GlobalID> globalIds_byInstanceId = new SerializableDictionary<int, GlobalID>();
public int instanceIdsHash;
public int globalIdsHash;
}
public static void Clear()
{
instance.originalSceneGuids_byInstanceId.Clear();
instance.sceneIdMaps_bySceneGuid.Clear();
instance.Save(true);
}
// public static void Save() => instance.Save(true); // cache is never saved to disk, it just needs to survive domain reloads
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3fd3b966dd497472d86df0d7c9271088
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,6 @@
// this file was present in a previus version and is supposed to be deleted now
// but asset store update delivery system doesn't allow deleting files
// so instead this file is now emptied
// feel free to delete it if you want

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d51d8117d96b64eaa9a83667bf4297d6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,575 @@
#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 Type = System.Type;
using static VHierarchy.VHierarchyData;
using static VHierarchy.Libs.VUtils;
using static VHierarchy.Libs.VGUI;
namespace VHierarchy
{
public class VHierarchyComponentWindow : EditorWindow
{
void OnGUI()
{
if (!component) { Close(); return; } // todo script components break on playmode
void background()
{
position.SetPos(0, 0).Draw(GUIColors.windowBackground);
}
void outline()
{
if (Application.platform == RuntimePlatform.OSXEditor) return;
position.SetPos(0, 0).DrawOutline(Greyscale(.1f));
}
void header()
{
var headerRect = ExpandWidthLabelRect(18).Resize(-1).AddWidthFromMid(6);
var pinButtonRect = headerRect.SetWidthFromRight(17).SetHeightFromMid(17).Move(-21, .5f);
var closeButtonRect = headerRect.SetWidthFromRight(16).SetHeightFromMid(16).Move(-3, .5f);
var backgroundColor = isDarkTheme ? Greyscale(.25f) : GUIColors.windowBackground;
void startDragging()
{
if (isResizingVertically) return;
if (isResizingHorizontally) return;
if (isDragged) return;
if (!curEvent.isMouseDrag) return;
if (!headerRect.IsHovered()) return;
isDragged = true;
dragStartMousePos = EditorGUIUtility.GUIToScreenPoint(curEvent.mousePosition);
dragStartWindowPos = position.position;
isPinned = true;
if (floatingInstance == this)
floatingInstance = null;
EditorApplication.RepaintHierarchyWindow();
}
void updateDragging()
{
if (!isDragged) return;
var draggedPosition = dragStartWindowPos + EditorGUIUtility.GUIToScreenPoint(curEvent.mousePosition) - dragStartMousePos;
if (!curEvent.isRepaint)
position = position.SetPos(draggedPosition);
EditorGUIUtility.hotControl = EditorGUIUtility.GetControlID(FocusType.Passive);
}
void stopDragging()
{
if (!isDragged) return;
if (!curEvent.isMouseUp) return;
isDragged = false;
EditorGUIUtility.hotControl = 0;
}
void background()
{
headerRect.Draw(backgroundColor);
headerRect.SetHeightFromBottom(1).Draw(isDarkTheme ? Greyscale(.2f) : Greyscale(.7f));
}
void icon()
{
var iconRect = headerRect.SetWidth(20).MoveX(14).MoveY(-1);
GUI.Label(iconRect, VHierarchy.GetComponentIcon(component));
}
void toggle()
{
var toggleRect = headerRect.MoveX(36).SetSize(20, 20);
var pi_enabled = component.GetType().GetProperty("enabled") ??
component.GetType().BaseType?.GetProperty("enabled") ??
component.GetType().BaseType?.BaseType?.GetProperty("enabled") ??
component.GetType().BaseType?.BaseType?.BaseType?.GetProperty("enabled");
if (pi_enabled == null) return;
var enabled = (bool)pi_enabled.GetValue(component);
if (GUI.Toggle(toggleRect, enabled, "") == enabled) return;
component.RecordUndo();
pi_enabled.SetValue(component, !enabled);
}
void name()
{
var nameRect = headerRect.MoveX(54).MoveY(-1);
var s = VHierarchy.GetComponentName(component);
if (isPinned)
s += " of " + component.gameObject.name;
SetLabelBold();
GUI.Label(nameRect, s);
ResetLabelStyle();
}
void nameCurtain()
{
var flatColorRect = headerRect.SetX(pinButtonRect.x + 3).SetXMax(headerRect.xMax);
var gradientRect = headerRect.SetXMax(flatColorRect.x).SetWidthFromRight(30);
flatColorRect.Draw(backgroundColor);
gradientRect.DrawCurtainLeft(backgroundColor);
}
void pinButton()
{
if (!isPinned && closeButtonRect.IsHovered()) return;
var normalColor = isDarkTheme ? Greyscale(.65f) : Greyscale(.8f);
var hoveredColor = isDarkTheme ? Greyscale(.9f) : normalColor;
var activeColor = Color.white;
SetGUIColor(isPinned ? activeColor : pinButtonRect.IsHovered() ? hoveredColor : normalColor);
GUI.Label(pinButtonRect, EditorGUIUtility.IconContent("pinned"));
ResetGUIColor();
SetGUIColor(Color.clear);
var clicked = GUI.Button(pinButtonRect, "");
ResetGUIColor();
if (!clicked) return;
isPinned = !isPinned;
if (isPinned && floatingInstance == this)
floatingInstance = null;
if (!isPinned && !floatingInstance)
floatingInstance = this;
EditorApplication.RepaintHierarchyWindow();
}
void closeButton()
{
SetGUIColor(Color.clear);
if (GUI.Button(closeButtonRect, ""))
Close();
ResetGUIColor();
var normalColor = isDarkTheme ? Greyscale(.65f) : Greyscale(.35f);
var hoveredColor = isDarkTheme ? Greyscale(.9f) : normalColor;
SetGUIColor(closeButtonRect.IsHovered() ? hoveredColor : normalColor);
GUI.Label(closeButtonRect, EditorGUIUtility.IconContent("CrossIcon"));
ResetGUIColor();
if (isPinned) return;
var escRect = closeButtonRect.Move(-22, -1).SetWidth(70);
SetGUIEnabled(false);
if (closeButtonRect.IsHovered())
GUI.Label(escRect, "Esc");
ResetGUIEnabled();
}
startDragging();
updateDragging();
stopDragging();
background();
icon();
toggle();
name();
nameCurtain();
pinButton();
closeButton();
}
void body()
{
EditorGUIUtility.labelWidth = (this.position.width * .4f).Max(120);
scrollPosition = EditorGUILayout.BeginScrollView(Vector2.up * scrollPosition).y;
BeginIndent(17);
editor?.OnInspectorGUI();
updateHeight();
EndIndent(1);
EditorGUILayout.EndScrollView();
EditorGUIUtility.labelWidth = 0;
}
void updateHeight()
{
ExpandWidthLabelRect(height: -5);
if (!curEvent.isRepaint) return;
if (isResizingVertically) return;
targetHeight = lastRect.y + 30;
position = position.SetHeight(targetHeight.Min(maxHeight));
prevHeight = position.height;
}
void updatePosition()
{
if (!curEvent.isLayout) return;
void calcDeltaTime()
{
deltaTime = (float)(EditorApplication.timeSinceStartup - lastLayoutTime);
if (deltaTime > .05f)
deltaTime = .0166f;
lastLayoutTime = EditorApplication.timeSinceStartup;
}
void resetCurPos()
{
if (currentPosition != default && !isPinned) return;
currentPosition = position.position; // position.position is always int, which can't be used for lerping
}
void lerpCurPos()
{
if (isPinned) return;
var speed = 9;
SmoothDamp(ref currentPosition, targetPosition, speed, ref positionDeriv, deltaTime);
// Lerp(ref currentPosition, targetPosition, speed, deltaTime);
}
void setCurPos()
{
if (isPinned) return;
position = position.SetPos(currentPosition);
}
calcDeltaTime();
resetCurPos();
lerpCurPos();
setCurPos();
}
void closeOnEscape()
{
if (!curEvent.isKeyDown) return;
if (curEvent.keyCode != KeyCode.Escape) return;
Close();
}
void horizontalResize()
{
var showingScrollbar = targetHeight > maxHeight;
var resizeArea = this.position.SetPos(0, 0).SetWidthFromRight(showingScrollbar ? 3 : 5).AddHeightFromBottom(-20);
void startResize()
{
if (isDragged) return;
if (isResizingHorizontally) return;
if (!curEvent.isMouseDown && !curEvent.isMouseDrag) return;
if (!resizeArea.IsHovered()) return;
isResizingHorizontally = true;
resizeStartMousePos = curEvent.mousePosition_screenSpace;
resizeStartWindowSize = this.position.size;
}
void updateResize()
{
if (!isResizingHorizontally) return;
var resizedWidth = resizeStartWindowSize.x + curEvent.mousePosition_screenSpace.x - resizeStartMousePos.x;
var width = resizedWidth.Max(300);
if (!curEvent.isRepaint)
position = position.SetWidth(width);
EditorGUIUtility.hotControl = EditorGUIUtility.GetControlID(FocusType.Passive);
// GUI.focused
}
void stopResize()
{
if (!isResizingHorizontally) return;
if (!curEvent.isMouseUp) return;
isResizingHorizontally = false;
EditorGUIUtility.hotControl = 0;
}
EditorGUIUtility.AddCursorRect(resizeArea, MouseCursor.ResizeHorizontal);
startResize();
updateResize();
stopResize();
}
void verticalResize()
{
var resizeArea = this.position.SetPos(0, 0).SetHeightFromBottom(5);
void startResize()
{
if (isDragged) return;
if (isResizingVertically) return;
if (!curEvent.isMouseDown && !curEvent.isMouseDrag) return;
if (!resizeArea.IsHovered()) return;
isResizingVertically = true;
resizeStartMousePos = curEvent.mousePosition_screenSpace;
resizeStartWindowSize = this.position.size;
}
void updateResize()
{
if (!isResizingVertically) return;
var resizedHeight = resizeStartWindowSize.y + curEvent.mousePosition_screenSpace.y - resizeStartMousePos.y;
var height = resizedHeight.Min(targetHeight).Max(50);
if (!curEvent.isRepaint)
position = position.SetHeight(height);
maxHeight = height;
EditorGUIUtility.hotControl = EditorGUIUtility.GetControlID(FocusType.Passive);
// GUI.focused
}
void stopResize()
{
if (!isResizingVertically) return;
if (!curEvent.isMouseUp) return;
isResizingVertically = false;
EditorGUIUtility.hotControl = 0;
}
EditorGUIUtility.AddCursorRect(resizeArea, MouseCursor.ResizeVertical);
startResize();
updateResize();
stopResize();
}
background();
outline();
horizontalResize();
verticalResize();
header();
Space(3);
body();
Space(7);
updatePosition();
closeOnEscape();
if (!isPinned)
Repaint();
}
public Vector2 targetPosition;
public Vector2 currentPosition;
Vector2 positionDeriv;
float deltaTime;
double lastLayoutTime;
bool isDragged;
Vector2 dragStartMousePos;
Vector2 dragStartWindowPos;
public bool isResizingHorizontally;
public bool isResizingVertically;
public Vector2 resizeStartMousePos;
public Vector2 resizeStartWindowSize;
public float scrollPosition;
public float targetHeight;
public float maxHeight;
public float prevHeight;
void OnLostFocus()
{
if (isPinned) return;
if (curEvent.holdingAlt && EditorWindow.focusedWindow.GetType().Name == "SceneHierarchyWindow")
CloseNextFrameIfNotRefocused();
else
Close();
}
void CloseNextFrameIfNotRefocused()
{
EditorApplication.delayCall += () => { if (EditorWindow.focusedWindow != this) Close(); };
}
public bool isPinned;
public void Init(Component component)
{
if (editor)
editor.DestroyImmediate();
this.component = component;
this.editor = Editor.CreateEditor(component);
}
void OnDestroy()
{
editor?.DestroyImmediate();
editor = null;
component = null;
EditorPrefs.SetFloat("vHierarchy-componentWindowWidth", position.width);
}
public Component component;
public Editor editor;
public static void CreateFloatingInstance(Vector2 position)
{
floatingInstance = ScriptableObject.CreateInstance<VHierarchyComponentWindow>();
floatingInstance.ShowPopup();
floatingInstance.maxHeight = EditorGUIUtility.GetMainWindowPosition().height * .7f;
var savedWidth = EditorPrefs.GetFloat("vHierarchy-componentWindowWidth", minWidth);
var width = savedWidth.Max(minWidth);
floatingInstance.position = Rect.zero.SetPos(position).SetWidth(width).SetHeight(200);
floatingInstance.prevHeight = floatingInstance.position.height;
floatingInstance.targetPosition = position;
}
public static VHierarchyComponentWindow floatingInstance;
public static float minWidth => 300;
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4b48d49a631ab443990f28938cbdedb8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,76 @@
#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 static VHierarchy.Libs.VUtils;
using static VHierarchy.Libs.VGUI;
namespace VHierarchy
{
public class VHierarchyData : ScriptableObject, ISerializationCallbackReceiver
{
public SerializableDictionary<string, SceneData> sceneDatas_byGuid = new SerializableDictionary<string, SceneData>();
[System.Serializable]
public class SceneData
{
public SerializableDictionary<GlobalID, GameObjectData> goDatas_byGlobalId = new SerializableDictionary<GlobalID, GameObjectData>();
}
[System.Serializable]
public class GameObjectData
{
public int colorIndex;
public string iconNameOrGuid = ""; // name for buildin icons, guid for custom ones
[System.NonSerialized] // set in GetGameObjectData
public SceneData sceneData;
}
public void OnBeforeSerialize() => VHierarchy.firstDataCacheLayer.Clear();
public void OnAfterDeserialize() => VHierarchy.firstDataCacheLayer.Clear();
[CustomEditor(typeof(VHierarchyData))]
class Editor : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
var style = new GUIStyle(EditorStyles.label) { wordWrap = true };
SetGUIEnabled(false);
BeginIndent(0);
Space(10);
EditorGUILayout.LabelField("This file contains data about which icons and colors are assigned to objects", style);
Space(6);
GUILayout.Label("If there are multiple people working on the project, you might want to store this data in scenes to avoid merge conflicts. To do that, create a script that inherits from VHierarchy.VHierarchyDataComponent and add it to any object in the scene", style);
EndIndent(10);
ResetGUIEnabled();
}
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3a9752b0c8e144801967e6897679604b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,95 @@
#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.Experimental.SceneManagement;
using Type = System.Type;
using static VHierarchy.VHierarchyData;
using static VHierarchy.Libs.VUtils;
using static VHierarchy.Libs.VGUI;
namespace VHierarchy
{
[ExecuteInEditMode]
public abstract class VHierarchyDataComponent : MonoBehaviour, ISerializationCallbackReceiver
{
public void Awake()
{
void register()
{
VHierarchy.dataComponents_byScene[gameObject.scene] = this;
}
void handleSceneDuplication()
{
if (sceneData == null) return;
if (!sceneData.goDatas_byGlobalId.Any()) return;
var curSceneGuid = gameObject.scene.path.ToGuid();
var dataSceneGuid = sceneData.goDatas_byGlobalId.Keys.First().guid;
if (curSceneGuid == dataSceneGuid) return;
var newDic = new SerializableDictionary<GlobalID, GameObjectData>();
foreach (var kvp in sceneData.goDatas_byGlobalId)
newDic[new GlobalID(kvp.Key.ToString().Replace(dataSceneGuid, curSceneGuid))] = kvp.Value;
sceneData.goDatas_byGlobalId = newDic;
EditorSceneManager.MarkSceneDirty(gameObject.scene);
EditorSceneManager.SaveScene(gameObject.scene);
}
register();
handleSceneDuplication();
}
public SceneData sceneData;
public void OnBeforeSerialize() => VHierarchy.firstDataCacheLayer.Clear();
public void OnAfterDeserialize() => VHierarchy.firstDataCacheLayer.Clear();
[CustomEditor(typeof(VHierarchyDataComponent), true)]
class Editor : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
var style = EditorStyles.label;
style.wordWrap = true;
SetGUIEnabled(false);
BeginIndent(0);
Space(4);
EditorGUILayout.LabelField("This component stores vHierarchy icons and colors that are assigned to objects in this scene", style);
Space(2);
EndIndent(10);
ResetGUIEnabled();
}
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9e20c7ea1a24b4a899ba82e98ad2b375
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,6 @@
// this file was present in a previus version and is supposed to be deleted now
// but asset store update delivery system doesn't allow deleting files
// so instead this file is now emptied
// feel free to delete it if you want

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8710ada63f66c4909ab73d206f31e954
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cd278e4ae9a8649f59f016c7d739ce1a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,353 @@
#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.SceneManagement;
using UnityEditor.SceneManagement;
using static VHierarchy.Libs.VUtils;
using static VHierarchy.Libs.VGUI;
namespace VHierarchy
{
public class VHierarchyLightingWindow : EditorWindow
{
void OnGUI()
{
void updateSize()
{
var r = ExpandWidthLabelRect();
if (!curEvent.isRepaint) return;
var curHeight = r.y;
this.position = position.SetWidth(initWidth).SetHeight(curHeight);
this.minSize = Vector2.zero;
this.maxSize = Vector2.one * 123212;
}
void header()
{
var height = 22f;
var headerRect = Rect.zero.SetHeight(height).SetWidth(position.width);
var pinButtonRect = headerRect.SetWidthFromRight(17).SetHeightFromMid(17).Move(-21, .5f);
var closeButtonRect = headerRect.SetWidthFromRight(16).SetHeightFromMid(16).Move(-3, .5f);
void startDragging()
{
if (isDragged) return;
if (!curEvent.isMouseDrag) return;
if (!headerRect.IsHovered()) return;
isDragged = true;
dragStartMousePos = EditorGUIUtility.GUIToScreenPoint(curEvent.mousePosition);
dragStartWindowPos = position.position;
isPinned = true;
EditorApplication.RepaintHierarchyWindow();
}
void updateDragging()
{
if (!isDragged) return;
if (!curEvent.isRepaint) // ??
position = position.SetPos(dragStartWindowPos + EditorGUIUtility.GUIToScreenPoint(curEvent.mousePosition) - dragStartMousePos);
EditorGUIUtility.hotControl = EditorGUIUtility.GetControlID(FocusType.Passive);
}
void stopDragging()
{
if (!isDragged) return;
if (!curEvent.isMouseUp) return;
isDragged = false;
EditorGUIUtility.hotControl = 0;
}
void background()
{
headerRect.Draw(EditorGUIUtility.isProSkin ? Greyscale(.185f) : Greyscale(.7f));
}
void title_()
{
SetGUIColor(Greyscale(.8f));
SetLabelAlignmentCenter();
GUI.Label(headerRect, "Lighting");
ResetLabelStyle();
ResetGUIColor();
}
void pinButton()
{
if (!isPinned && closeButtonRect.IsHovered()) return;
var normalColor = isDarkTheme ? Greyscale(.65f) : Greyscale(.8f);
var hoveredColor = isDarkTheme ? Greyscale(.9f) : normalColor;
var activeColor = Color.white;
SetGUIColor(isPinned ? activeColor : pinButtonRect.IsHovered() ? hoveredColor : normalColor);
GUI.Label(pinButtonRect, EditorGUIUtility.IconContent("pinned"));
ResetGUIColor();
SetGUIColor(Color.clear);
var clicked = GUI.Button(pinButtonRect, "");
ResetGUIColor();
if (!clicked) return;
isPinned = !isPinned;
}
void closeButton()
{
SetGUIColor(Color.clear);
if (GUI.Button(closeButtonRect, "") || (curEvent.isKeyDown && curEvent.keyCode == KeyCode.Escape))
Close();
ResetGUIColor();
var normalColor = isDarkTheme ? Greyscale(.65f) : Greyscale(.35f);
var hoveredColor = isDarkTheme ? Greyscale(.9f) : normalColor;
SetGUIColor(closeButtonRect.IsHovered() ? hoveredColor : normalColor);
GUI.Label(closeButtonRect, EditorGUIUtility.IconContent("CrossIcon"));
ResetGUIColor();
if (isPinned) return;
var escRect = closeButtonRect.Move(-22, -1).SetWidth(70);
SetGUIEnabled(false);
if (closeButtonRect.IsHovered())
GUI.Label(escRect, "Esc");
ResetGUIEnabled();
}
startDragging();
updateDragging();
stopDragging();
background();
title_();
pinButton();
closeButton();
Space(height);
}
void directionalLight()
{
var light = FindObjects<Light>().Where(r => r.type == LightType.Directional && r.gameObject.scene == EditorSceneManager.GetActiveScene()).FirstOrDefault();
if (!light) return;
light.RecordUndo();
light.transform.RecordUndo();
ObjectFieldWidhoutPicker("Directional Light", light);
Space(2);
BeginIndent(8);
EditorGUIUtility.labelWidth += 2;
var rotX = light.transform.eulerAngles.x.Loop(-180, 180).Round();
var rotY = light.transform.eulerAngles.y.Loop(-180, 180).Round();
rotX = EditorGUILayout.Slider("Rotation X", rotX, 0, 90);
rotY = EditorGUILayout.Slider("Rotation Y", rotY, -179, 180);
if (light.transform.rotation != Quaternion.Euler(rotX, rotY, light.transform.eulerAngles.z))
light.transform.rotation = Quaternion.Euler(rotX, rotY, light.transform.eulerAngles.z);
Space(3);
light.intensity = EditorGUILayout.Slider("Intensity", light.intensity, 0, 2);
light.color = SmallColorField(ExpandWidthLabelRect().AddWidthFromMid(-1).MoveX(-.5f), "Color", light.color, true);
EndIndent();
}
void ambientLight()
{
RenderSettings.ambientMode = (UnityEngine.Rendering.AmbientMode)EditorGUILayout.IntPopup("Ambient Light", (int)RenderSettings.ambientMode, new[] { "\u2009Skybox", "\u2009Gradient", "\u2009Color" }, new[] { 0, 1, 3 });
foreach (var r in FindObjects<RenderSettings>())
r.RecordUndo();
Space(2);
BeginIndent(8);
EditorGUIUtility.labelWidth += 4;
if (RenderSettings.ambientMode == UnityEngine.Rendering.AmbientMode.Flat)
{
Color.RGBToHSV(RenderSettings.ambientSkyColor, out float h, out float s, out float v);
v = EditorGUILayout.Slider("Intensity", v, .01f, 2);
RenderSettings.ambientSkyColor = Color.HSVToRGB(h, s, v, true);
RenderSettings.ambientSkyColor = SmallColorField("Color", RenderSettings.ambientSkyColor, false, true);
}
if (RenderSettings.ambientMode == UnityEngine.Rendering.AmbientMode.Skybox)
RenderSettings.ambientIntensity = EditorGUILayout.Slider("Intensity", RenderSettings.ambientIntensity, 0, 2);
if (RenderSettings.ambientMode == UnityEngine.Rendering.AmbientMode.Trilight)
{
RenderSettings.ambientSkyColor = SmallColorField("Color Sky", RenderSettings.ambientSkyColor, false, true);
RenderSettings.ambientEquatorColor = SmallColorField("Color Horizon", RenderSettings.ambientEquatorColor, false, true);
RenderSettings.ambientGroundColor = SmallColorField("Color Ground", RenderSettings.ambientGroundColor, false, true);
}
EndIndent();
}
void fog()
{
var mode = EditorGUILayout.IntPopup("Fog", RenderSettings.fog ? (int)RenderSettings.fogMode : 0, new[] { "\u2009Off", "\u2009Linear", "\u2009Exponential", "\u2009Exponential Squared" }, new[] { 0, 1, 2, 3 });
if (RenderSettings.fog = mode != 0)
RenderSettings.fogMode = (FogMode)mode;
if (!RenderSettings.fog) return;
Space(2);
BeginIndent(8);
EditorGUIUtility.labelWidth += 4;
if (RenderSettings.fogMode == FogMode.Linear)
{
RenderSettings.fogStartDistance = EditorGUILayout.FloatField("Start", RenderSettings.fogStartDistance);
RenderSettings.fogEndDistance = EditorGUILayout.FloatField("End", RenderSettings.fogEndDistance);
}
else
RenderSettings.fogDensity = ExpSlider(ExpandWidthLabelRect().AddWidthFromRight(1.5f), "Density", RenderSettings.fogDensity, 0, .05f);
RenderSettings.fogColor = SmallColorField("Color", RenderSettings.fogColor, true, false);
EndIndent();
}
header();
BeginIndent(6);
EditorGUIUtility.labelWidth = 115;
Space(11);
directionalLight();
Space(18);
ambientLight();
Space(18);
fog();
EndIndent(6);
Space(21);
updateSize();
if (Application.platform != RuntimePlatform.OSXEditor)
position.SetPos(0, 0).DrawOutline(Greyscale(.1f));
EditorGUIUtility.labelWidth = 0;
Repaint();
}
bool isDragged;
Vector2 dragStartMousePos;
Vector2 dragStartWindowPos;
void OnLostFocus()
{
if (isPinned) return;
Close();
}
public bool isPinned;
public static void CreateInstance(Vector2 position)
{
instance = ScriptableObject.CreateInstance<VHierarchyLightingWindow>();
instance.ShowPopup();
instance.position = Rect.zero.SetPos(position).SetSize(initWidth, initHeight);
instance.minSize = Vector2.zero;
instance.maxSize = Vector2.one * 123212;
}
public static VHierarchyLightingWindow instance;
static float initWidth => 250;
static float initHeight => 320;
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 25324ddc1ebdc4ee5b1d9902a8efafa7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,151 @@
#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using static VHierarchy.Libs.VUtils;
using static VHierarchy.Libs.VGUI;
namespace VHierarchy
{
class VHierarchyMenu
{
public static bool componentMinimapEnabled { get => EditorPrefsCached.GetBool("vHierarchy-componentMinimapEnabled", false); set => EditorPrefsCached.SetBool("vHierarchy-componentMinimapEnabled", value); }
public static bool hierarchyLinesEnabled { get => EditorPrefsCached.GetBool("vHierarchy-hierarchyLinesEnabled", false); set => EditorPrefsCached.SetBool("vHierarchy-hierarchyLinesEnabled", value); }
public static bool minimalModeEnabled { get => EditorPrefsCached.GetBool("vHierarchy-minimalModeEnabled", false); set => EditorPrefsCached.SetBool("vHierarchy-minimalModeEnabled", value); }
public static bool zebraStripingEnabled { get => EditorPrefsCached.GetBool("vHierarchy-zebraStripingEnabled", false); set => EditorPrefsCached.SetBool("vHierarchy-zebraStripingEnabled", value); }
public static bool activationToggleEnabled { get => EditorPrefsCached.GetBool("vHierarchy-acctivationToggleEnabled", false); set => EditorPrefsCached.SetBool("vHierarchy-acctivationToggleEnabled", value); }
public static bool collapseAllButtonEnabled { get => EditorPrefsCached.GetBool("vHierarchy-collapseAllButtonEnabled", false); set => EditorPrefsCached.SetBool("vHierarchy-collapseAllButtonEnabled", value); }
public static bool editLightingButtonEnabled { get => EditorPrefsCached.GetBool("vHierarchy-editLightingButtonEnabled", false); set => EditorPrefsCached.SetBool("vHierarchy-editLightingButtonEnabled", value); }
public static bool toggleActiveEnabled { get => EditorPrefsCached.GetBool("vHierarchy-toggleActiveEnabled", true); set => EditorPrefsCached.SetBool("vHierarchy-toggleActiveEnabled", value); }
public static bool focusEnabled { get => EditorPrefsCached.GetBool("vHierarchy-focusEnabled", true); set => EditorPrefsCached.SetBool("vHierarchy-focusEnabled", value); }
public static bool deleteEnabled { get => EditorPrefsCached.GetBool("vHierarchy-deleteEnabled", true); set => EditorPrefsCached.SetBool("vHierarchy-deleteEnabled", value); }
public static bool toggleExpandedEnabled { get => EditorPrefsCached.GetBool("vHierarchy-toggleExpandedEnabled", true); set => EditorPrefsCached.SetBool("vHierarchy-toggleExpandedEnabled", value); }
public static bool collapseEverythingElseEnabled { get => EditorPrefsCached.GetBool("vHierarchy-collapseEverythingElseEnabled", true); set => EditorPrefsCached.SetBool("vHierarchy-collapseEverythingElseEnabled", value); }
public static bool collapseEverythingEnabled { get => EditorPrefsCached.GetBool("vHierarchy-collapseEverythingEnabled", true); set => EditorPrefsCached.SetBool("vHierarchy-collapseEverythingEnabled", value); }
public static bool pluginDisabled { get => EditorPrefsCached.GetBool("vHierarchy-pluginDisabled", false); set => EditorPrefsCached.SetBool("vHierarchy-pluginDisabled", value); }
const string dir = "Tools/vHierarchy/";
const string componentMinimap = dir + "Component minimap";
const string hierarchyLines = dir + "Hierarchy lines";
const string minimalMode = dir + "Minimal mode";
const string zebraStriping = dir + "Zebra striping";
const string activationToggle = dir + "Activation toggle";
const string collapseAllButton = dir + "Collapse All button";
const string editLightingButton = dir + "Edit Lighting button";
const string toggleActive = dir + "A to toggle active";
const string focus = dir + "F to focus";
const string delete = dir + "X to delete";
const string toggleExpanded = dir + "E to expand or collapse";
const string collapseEverythingElse = dir + "Shift-E to isolate";
const string collapseEverything = dir + "Ctrl-Shift-E to collapse all";
const string disablePlugin = dir + "Disable vHierarchy";
[MenuItem(dir + "Features", false, 1)] static void daasddsas() { }
[MenuItem(dir + "Features", true, 1)] static bool dadsdasas123() => false;
[MenuItem(componentMinimap, false, 2)] static void daadsdsadasdadsas() { componentMinimapEnabled = !componentMinimapEnabled; EditorApplication.RepaintHierarchyWindow(); }
[MenuItem(componentMinimap, true, 2)] static bool dadsadasddasadsas() { Menu.SetChecked(componentMinimap, componentMinimapEnabled); return !pluginDisabled; }
[MenuItem(hierarchyLines, false, 3)] static void dadsadadsadadasss() { hierarchyLinesEnabled = !hierarchyLinesEnabled; EditorApplication.RepaintHierarchyWindow(); }
[MenuItem(hierarchyLines, true, 3)] static bool dadsaddasdasaasddsas() { Menu.SetChecked(hierarchyLines, hierarchyLinesEnabled); return !pluginDisabled; }
[MenuItem(minimalMode, false, 4)] static void dadsadadasdsdasadadasss() { minimalModeEnabled = !minimalModeEnabled; EditorApplication.RepaintHierarchyWindow(); }
[MenuItem(minimalMode, true, 4)] static bool dadsaddadsasdadsasaasddsas() { Menu.SetChecked(minimalMode, minimalModeEnabled); return !pluginDisabled; }
[MenuItem(zebraStriping, false, 5)] static void dadsadadadssadsadass() { zebraStripingEnabled = !zebraStripingEnabled; EditorApplication.RepaintHierarchyWindow(); }
[MenuItem(zebraStriping, true, 5)] static bool dadsaddadaadsssadsaasddsas() { Menu.SetChecked(zebraStriping, zebraStripingEnabled); return !pluginDisabled; }
[MenuItem(activationToggle, false, 6)] static void daadsdsadadsasdadsas() { activationToggleEnabled = !activationToggleEnabled; EditorApplication.RepaintHierarchyWindow(); }
[MenuItem(activationToggle, true, 6)] static bool dadsadasdsaddasadsas() { Menu.SetChecked(activationToggle, activationToggleEnabled); return !pluginDisabled; }
[MenuItem(collapseAllButton, false, 7)] static void daadsdsadadsadadsas() { collapseAllButtonEnabled = !collapseAllButtonEnabled; EditorApplication.RepaintHierarchyWindow(); }
[MenuItem(collapseAllButton, true, 7)] static bool dadsadasdsaddasdsas() { Menu.SetChecked(collapseAllButton, collapseAllButtonEnabled); return !pluginDisabled; }
[MenuItem(editLightingButton, false, 8)] static void daadsdsasdadadsadadsas() { editLightingButtonEnabled = !editLightingButtonEnabled; EditorApplication.RepaintHierarchyWindow(); }
[MenuItem(editLightingButton, true, 8)] static bool dadsadasdsadsaddasdsas() { Menu.SetChecked(editLightingButton, editLightingButtonEnabled); return !pluginDisabled; }
[MenuItem(dir + "Shortcuts", false, 101)] static void dadsas() { }
[MenuItem(dir + "Shortcuts", true, 101)] static bool dadsas123() => false;
[MenuItem(toggleActive, false, 102)] static void dadsadadsas() => toggleActiveEnabled = !toggleActiveEnabled;
[MenuItem(toggleActive, true, 102)] static bool dadsaddasadsas() { Menu.SetChecked(toggleActive, toggleActiveEnabled); return !pluginDisabled; }
[MenuItem(focus, false, 103)] static void dadsadasdadsas() => focusEnabled = !focusEnabled;
[MenuItem(focus, true, 103)] static bool dadsadsaddasadsas() { Menu.SetChecked(focus, focusEnabled); return !pluginDisabled; }
[MenuItem(delete, false, 104)] static void dadsadsadasdadsas() => deleteEnabled = !deleteEnabled;
[MenuItem(delete, true, 104)] static bool dadsaddsasaddasadsas() { Menu.SetChecked(delete, deleteEnabled); return !pluginDisabled; }
[MenuItem(toggleExpanded, false, 105)] static void dadsadsadasdsadadsas() => toggleExpandedEnabled = !toggleExpandedEnabled;
[MenuItem(toggleExpanded, true, 105)] static bool dadsaddsasadadsdasadsas() { Menu.SetChecked(toggleExpanded, toggleExpandedEnabled); return !pluginDisabled; }
[MenuItem(collapseEverythingElse, false, 106)] static void dadsadsasdadasdsadadsas() => collapseEverythingElseEnabled = !collapseEverythingElseEnabled;
[MenuItem(collapseEverythingElse, true, 106)] static bool dadsaddsdasasadadsdasadsas() { Menu.SetChecked(collapseEverythingElse, collapseEverythingElseEnabled); return !pluginDisabled; }
[MenuItem(collapseEverything, false, 107)] static void dadsadsdasadasdsadadsas() => collapseEverythingEnabled = !collapseEverythingEnabled;
[MenuItem(collapseEverything, true, 107)] static bool dadsaddssdaasadadsdasadsas() { Menu.SetChecked(collapseEverything, collapseEverythingEnabled); return !pluginDisabled; }
[MenuItem(dir + "More", false, 1001)] static void daasadsddsas() { }
[MenuItem(dir + "More", true, 1001)] static bool dadsadsdasas123() => false;
[MenuItem(dir + "Open manual", false, 1002)]
static void dadadsasdsadsas() => AssetDatabase.OpenAsset(AssetDatabase.LoadAssetAtPath<Object>(GetScriptPath("VHierarchy").GetParentPath().CombinePath("Manual.pdf")));
[MenuItem(dir + "Join our Discord", false, 1003)]
static void dadasdsas() => Application.OpenURL("https://discord.gg/4dG9KsbspG");
[MenuItem(dir + "Deals ending soon/Get vFolders 2 at 50% off", false, 1004)]
static void dadadssadasdsas() => Application.OpenURL("https://assetstore.unity.com/packages/slug/255470?aid=1100lGLBn&pubref=deal50menu");
[MenuItem(dir + "Deals ending soon/Get vInspector 2 at 50% off", false, 1005)]
static void dadadssadsas() => Application.OpenURL("https://assetstore.unity.com/packages/slug/252297?aid=1100lGLBn&pubref=deal50menu");
[MenuItem(dir + "Deals ending soon/Get vTabs 2 at 50% off", false, 1006)]
static void dadadadsssadsas() => Application.OpenURL("https://assetstore.unity.com/packages/slug/263645?aid=1100lGLBn&pubref=deal50menu");
[MenuItem(dir + "Deals ending soon/Get vFavorites 2 at 50% off", false, 1007)]
static void dadadadsssadsadsas() => Application.OpenURL("https://assetstore.unity.com/packages/slug/263643?aid=1100lGLBn&pubref=deal50menu");
[MenuItem(disablePlugin, false, 10001)] static void dadsadsdasadasdasdsadadsas() { pluginDisabled = !pluginDisabled; UnityEditor.Compilation.CompilationPipeline.RequestScriptCompilation(); }
[MenuItem(disablePlugin, true, 10001)] static bool dadsaddssdaasadsadadsdasadsas() { Menu.SetChecked(disablePlugin, pluginDisabled); return true; }
// [MenuItem(dir + "Clear cache", false, 10001)]
// static void dassaadsdc() => VHierarchyCache.Clear();
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4d7f0448bdeda4aad9cfdd9e7c7ee27f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,6 @@
// this file was present in a previus version and is supposed to be deleted now
// but asset store update delivery system doesn't allow deleting files
// so instead this file is now emptied
// feel free to delete it if you want

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9ddf1decb62f94768bcaec3173017c87
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,217 @@
#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 UnityEditorInternal;
using static VHierarchy.Libs.VUtils;
using static VHierarchy.Libs.VGUI;
namespace VHierarchy
{
public class VHierarchyPalette : ScriptableObject
{
public List<Color> colors = new List<Color>();
public bool colorsEnabled;
public void ResetColors()
{
colors.Clear();
for (int i = 0; i < colorsCount; i++)
colors.Add(GetDefaultColor(i));
colorsEnabled = true;
this.Dirty();
}
public static Color GetDefaultColor(int colorIndex)
{
Color color = default;
void grey()
{
if (colorIndex >= greyColorsCount) return;
#if UNITY_2022_1_OR_NEWER
color = Greyscale(isDarkTheme ? .16f : .9f);
#else
color = Greyscale(isDarkTheme ? .315f : .9f);
#endif
}
void rainbowDarkTheme()
{
if (colorIndex < greyColorsCount) return;
if (!isDarkTheme) return;
color = HSLToRGB((colorIndex - greyColorsCount.ToFloat()) / rainbowColorsCount, .45f, .35f);
if (colorIndex == 1)
color *= 1.2f;
if (colorIndex == 2)
color *= 1.1f;
if (colorIndex == 6)
color *= 1.35f;
if (colorIndex == 7)
color *= 1.3f;
if (colorIndex == 8)
color *= 1.05f;
color.a = .1f;
}
void rainbowLightTheme()
{
if (colorIndex < greyColorsCount) return;
if (isDarkTheme) return;
color = HSLToRGB((colorIndex - greyColorsCount.ToFloat()) / rainbowColorsCount, .62f, .8f);
color.a = .1f;
}
grey();
rainbowDarkTheme();
rainbowLightTheme();
return color;
}
public static int greyColorsCount = 1;
public static int rainbowColorsCount = 8;
public static int colorsCount => greyColorsCount + rainbowColorsCount;
public List<IconRow> iconRows = new List<IconRow>();
[System.Serializable]
public class IconRow
{
public List<string> builtinIcons = new List<string>(); // names
public List<string> customIcons = new List<string>(); // guids
public bool enabled = true;
public bool isCustom => !builtinIcons.Any() || customIcons.Any();
public bool isEmpty => !builtinIcons.Any() && !customIcons.Any();
public int iconCount => builtinIcons.Count + customIcons.Count;
public IconRow(string[] builtinIcons) => this.builtinIcons = builtinIcons.ToList();
public IconRow() { }
}
public void ResetIcons()
{
iconRows.Clear();
iconRows.Add(new IconRow(new[]
{
"Folder Icon",
"Canvas Icon",
"AvatarMask On Icon",
"cs Script Icon",
"StandaloneInputModule Icon",
"EventSystem Icon",
"Terrain Icon",
"ScriptableObject Icon",
}));
iconRows.Add(new IconRow(new[]
{
"Camera Icon",
"ParticleSystem Icon",
"TrailRenderer Icon",
"Material Icon",
"ReflectionProbe Icon",
}));
iconRows.Add(new IconRow(new[]
{
"Light Icon",
"DirectionalLight Icon",
"LightmapParameters Icon",
"LightProbes Icon",
}));
iconRows.Add(new IconRow(new[]
{
"Rigidbody Icon",
"BoxCollider Icon",
"SphereCollider Icon",
"CapsuleCollider Icon",
"WheelCollider Icon",
"MeshCollider Icon",
}));
iconRows.Add(new IconRow(new[]
{
"AudioSource Icon",
"AudioClip Icon",
"AudioListener Icon",
"AudioEchoFilter Icon",
"AudioReverbZone Icon",
}));
iconRows.Add(new IconRow(new[]
{
"PreMatCube",
"PreMatSphere",
"PreMatCylinder",
"PreMatQuad",
"Favorite",
#if UNITY_2021_3_OR_NEWER
"Settings Icon",
#endif
}));
this.Dirty();
}
[ContextMenu("Export palette")]
public void Export()
{
var packagePath = EditorUtility.SaveFilePanel("Export vHierarchy Palette", "", this.GetPath().GetFilename(withExtension: false), "unitypackage");
var iconPaths = iconRows.SelectMany(r => r.customIcons).Select(r => r.ToPath()).Where(r => !r.IsNullOrEmpty());
AssetDatabase.ExportPackage(iconPaths.Append(this.GetPath()).ToArray(), packagePath);
EditorUtility.RevealInFinder(packagePath);
}
void Reset() { ResetColors(); ResetIcons(); }
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 61290d425f1c94a8cbfb56f754ca6757
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,723 @@
#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.ShortcutManagement;
using System.Reflection;
using System.Linq;
using UnityEditorInternal;
using UnityEngine.UIElements;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
using static VHierarchy.Libs.VUtils;
using static VHierarchy.Libs.VGUI;
using static VHierarchy.VHierarchyPalette;
namespace VHierarchy
{
[CustomEditor(typeof(VHierarchyPalette))]
public class VHierarchyPaletteEditor : Editor
{
public override void OnInspectorGUI()
{
void colors()
{
var rowRect = ExpandWidthLabelRect(cellSize).SetX(rowsOffsetX).SetWidth(rowWidth);
void backgroundHovered()
{
if (!rowRect.IsHovered()) return;
if (pickingColor) return;
if (draggingRow) return;
rowRect.Draw(hoveredRowBackground);
}
void toggle()
{
var toggleRect = rowRect.SetWidth(16).MoveX(5);
var prevEnabled = palette.colorsEnabled;
var newEnabled = EditorGUI.Toggle(toggleRect, palette.colorsEnabled);
if (prevEnabled != newEnabled)
palette.RecordUndo();
palette.colorsEnabled = newEnabled;
if (prevEnabled != newEnabled)
palette.Dirty();
}
void crossIcon()
{
var crossIconRect = rowRect.SetX(rowsOffsetX + iconsOffsetX + iconSpacing / 2).SetWidth(iconSize).SetHeightFromMid(iconSize);
SetGUIColor(palette.colorsEnabled ? Color.white : disabledRowTint);
SetLabelAlignmentCenter();
GUI.Label(crossIconRect, EditorGUIUtility.IconContent("CrossIcon"));
ResetGUIColor();
ResetLabelStyle();
}
void color(int i)
{
var cellRect = rowRect.MoveX(iconsOffsetX + (i + 1) * cellSize).SetWidth(cellSize).SetHeightFromMid(cellSize);
void backgroundPicking()
{
if (!pickingColor) return;
if (i != pickingColorAtIndex) return;
cellRect.DrawWithRoundedCorners(pickingBackground, 2);
}
void color()
{
var tint = palette.colorsEnabled ? Color.white : disabledRowTint;
var brightness = i < VHierarchyPalette.greyColorsCount ? 1.02f : 1.35f;
var outlineColor = i < VHierarchyPalette.greyColorsCount ? Greyscale(.0f, .4f) : Greyscale(.15f, .2f);
cellRect.Resize(3).DrawWithRoundedCorners(outlineColor * tint, 4);
cellRect.Resize(4).DrawWithRoundedCorners(palette.colors[i].SetAlpha(1) * brightness * tint, 3);
cellRect.Resize(4).AddWidthFromRight(-2).DrawCurtainLeft(GUIColors.windowBackground.SetAlpha((1 - palette.colors[i].a) * .5f));
}
void startPickingColorButton()
{
if (!palette.colorsEnabled) return;
if (!cellRect.IsHovered()) return;
if (pickingColor) return;
var clicked = GUI.Button(cellRect.Resize(1), "");
GUI.Label(cellRect.Resize(.5f), EditorGUIUtility.IconContent("Preset.Context"));
if (!clicked) return;
colorPicker = OpenColorPicker((c) => { palette.RecordUndo(); palette.Dirty(); palette.colors[i] = c; }, palette.colors[i], true, false);
colorPicker.MoveTo(EditorGUIUtility.GUIToScreenPoint(cellRect.Move(-3, 50).position));
pickingColor = true;
pickingColorAtIndex = i;
}
void updatePickingColor()
{
if (!pickingColor) return;
EditorApplication.RepaintHierarchyWindow();
}
void stopPickingColor()
{
if (!pickingColor) return;
if (colorPicker) return;
pickingColor = false;
}
cellRect.MarkInteractive();
backgroundPicking();
color();
startPickingColorButton();
updatePickingColor();
stopPickingColor();
}
backgroundHovered();
toggle();
crossIcon();
for (int i = 0; i < palette.colors.Count; i++)
color(i);
Space(rowSpacing - 2);
}
void icons()
{
void row(Rect rowRect, IconRow row)
{
var isLastRow = row == palette.iconRows.Last();
var isDraggedRow = row == draggedRow;
var spaceForCrossIcon = 0f;
void startPickingIcon(int i, Rect cellRect)
{
iconPicker = OpenObjectPicker<Texture2D>(AssetDatabase.LoadAssetAtPath<Texture2D>(row.customIcons[i].ToPath()), controlID: 123);
iconPicker.MoveTo(EditorGUIUtility.GUIToScreenPoint(cellRect.Move(-3, 50).position));
pickingIcon = true;
pickingIconAtIndex = i;
pickingIconAtRow = row;
}
void updatePickingIcon()
{
if (!pickingIcon) return;
if (pickingIconAtRow != row) return;
if (EditorGUIUtility.GetObjectPickerControlID() != 123) return;
if (pickingIconAtIndex >= row.customIcons.Count) return; // somehow happens if RecordUndo is used
palette.RecordUndo();
palette.Dirty();
row.customIcons[pickingIconAtIndex] = (EditorGUIUtility.GetObjectPickerObject() as Texture2D).GetPath().ToGuid();
}
void stopPickingIcon()
{
if (!pickingIcon) return;
if (pickingIconAtRow != row) return;
if (iconPicker) return;
if (pickingIconAtIndex < row.customIcons.Count)
if (row.customIcons[pickingIconAtIndex] == null)
row.customIcons.RemoveAt(pickingIconAtIndex);
pickingIcon = false;
}
void dragndrop()
{
if (!rowRect.IsHovered()) return;
if (curEvent.isDragUpdate && DragAndDrop.objectReferences.First() is Texture2D)
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
if (!curEvent.isDragPerform) return;
if (!(DragAndDrop.objectReferences.Any(r => r is Texture2D))) return;
DragAndDrop.AcceptDrag();
palette.RecordUndo();
palette.Dirty();
foreach (var icon in DragAndDrop.objectReferences.Where(r => r is Texture2D))
row.customIcons.Add(icon.GetPath().ToGuid());
}
void calcSpaceForCrossIcon()
{
if (row == curFirstEnabledRow)
spaceForCrossIcon = crossIconAnimationT * cellSize;
if (row == crossIconAnimationSourceRow)
spaceForCrossIcon = (1 - crossIconAnimationT) * cellSize;
}
void backgroundHovered()
{
if (!rowRect.IsHovered()) return;
if (pickingColor) return;
if (pickingIcon) return;
if (draggingRow) return;
rowRect.Draw(hoveredRowBackground);
}
void backgroundDragged()
{
if (!isDraggedRow) return;
rowRect.DrawBlurred(Greyscale(0, .3f), 12);
rowRect.Draw(draggedRowBackground);
}
void toggle()
{
var prevEnabled = row.enabled;
var newEnabled = EditorGUI.Toggle(rowRect.SetWidth(16).MoveX(5), row.enabled);
if (prevEnabled != newEnabled)
palette.RecordUndo();
row.enabled = newEnabled;
if (prevEnabled != newEnabled)
palette.Dirty();
}
void addIconButton()
{
if (!row.isCustom) return;
var cellRect = rowRect.MoveX(iconsOffsetX + row.customIcons.Count * cellSize + spaceForCrossIcon).SetWidth(cellSize).SetHeightFromMid(cellSize);
SetGUIColor(Greyscale(1, row.enabled ? 1 : .5f));
var clicked = GUI.Button(cellRect.Resize(1), "");
ResetGUIColor();
SetGUIColor(Greyscale(1, row.enabled ? 1 : .5f));
SetLabelAlignmentCenter();
GUI.Label(cellRect.Resize(1), EditorGUIUtility.IconContent("Toolbar Plus"));
ResetLabelStyle();
ResetGUIColor();
if (!clicked) return;
palette.RecordUndo();
row.customIcons.Add(null);
startPickingIcon(row.customIcons.Count - 1, cellRect);
}
void icon(int i)
{
var cellRect = rowRect.MoveX(iconsOffsetX + spaceForCrossIcon + i * cellSize).SetWidth(cellSize).SetHeightFromMid(cellSize);
var isCustomIcon = i > row.builtinIcons.Count - 1;
void backgroundPicking()
{
if (!pickingIcon) return;
if (row != pickingIconAtRow) return;
if (i != pickingIconAtIndex) return;
cellRect.Resize(1).DrawWithRoundedCorners(pickingBackground, 2);
}
void drawBuiltin()
{
if (isCustomIcon) return;
SetLabelAlignmentCenter();
SetGUIColor(row.enabled ? Color.white : disabledRowTint);
GUI.Label(cellRect.SetSizeFromMid(iconSize), EditorGUIUtility.IconContent(row.builtinIcons[i]));
ResetLabelStyle();
ResetGUIColor();
}
void drawCustom()
{
if (!isCustomIcon) return;
if (cellRect.IsHovered()) return;
if (!(AssetDatabase.LoadAssetAtPath<Texture2D>(row.customIcons[i - row.builtinIcons.Count].ToPath()) is Texture2D texture)) return;
SetGUIColor(row.enabled ? Color.white : disabledRowTint);
GUI.DrawTexture(cellRect.SetSizeFromMid(iconSize), texture);
ResetGUIColor();
}
void editCustomButton()
{
if (!isCustomIcon) return;
if (!cellRect.IsHovered()) return;
if (pickingIcon) return;
var clicked = GUI.Button(cellRect.Resize(1), "");
GUI.Label(cellRect.Resize(.5f), EditorGUIUtility.IconContent("Preset.Context"));
if (!clicked) return;
GenericMenu menu = new GenericMenu();
menu.AddItem(new GUIContent("Replace icon"), false, () => { palette.RecordUndo(); palette.Dirty(); startPickingIcon(i, cellRect.MoveY(75)); });
menu.AddItem(new GUIContent("Remove icon"), false, () => { palette.RecordUndo(); row.customIcons.RemoveAt(i); palette.Dirty(); });
menu.ShowAsContext();
}
cellRect.MarkInteractive();
backgroundPicking();
drawBuiltin();
drawCustom();
editCustomButton();
}
rowRect.MarkInteractive();
updatePickingIcon();
stopPickingIcon();
dragndrop();
calcSpaceForCrossIcon();
backgroundHovered();
backgroundDragged();
toggle();
addIconButton();
for (int i = 0; i < row.iconCount; i++)
icon(i);
}
void updateRowsCount()
{
palette.iconRows.RemoveAll(r => r.isEmpty && r != palette.iconRows.Last());
if (!palette.iconRows.Last().isEmpty)
palette.iconRows.Add(new IconRow());
}
void updateRowGapsCount()
{
while (rowGaps.Count < palette.iconRows.Count)
rowGaps.Add(0);
while (rowGaps.Count > palette.iconRows.Count)
rowGaps.RemoveLast();
}
void normalRow(int i)
{
Space(rowGaps[i] * (cellSize + rowSpacing));
if (i == 0 && lastRect.y != 0)
firstRowY = lastRect.y;
Space(cellSize + rowSpacing);
var rowRect = Rect.zero.SetPos(rowsOffsetX, lastRect.y).SetSize(rowWidth, cellSize);
if (curEvent.isRepaint)
if (rowRect.IsHovered())
hoveredRow = palette.iconRows[i];
row(rowRect, palette.iconRows[i]);
}
void draggedRow_()
{
if (!draggingRow) return;
draggedRowY = (curEvent.mousePosition.y + draggedRowHoldOffset).Clamp(firstRowY, firstRowY + (palette.iconRows.Count - 1) * (cellSize + rowSpacing));
var rowRect = Rect.zero.SetPos(rowsOffsetX, draggedRowY).SetSize(rowWidth, cellSize);
row(rowRect, draggedRow);
}
void crossIcon()
{
if (!palette.iconRows.Any(r => r.enabled)) return;
var rect = Rect.zero.SetPos(rowsOffsetX + iconsOffsetX, crossIconY).SetSize(cellSize, cellSize).Resize(iconSpacing / 2);
SetLabelAlignmentCenter();
GUI.Label(rect, EditorGUIUtility.IconContent("CrossIcon"));
ResetLabelStyle();
}
updateRowsCount();
updateRowGapsCount();
if (curEvent.isRepaint)
hoveredRow = null;
for (int i = 0; i < palette.iconRows.Count; i++)
normalRow(i);
crossIcon();
draggedRow_();
}
void tutor()
{
SetGUIEnabled(false);
GUILayout.Label("Click a color to edit it");
Space(4);
GUILayout.Label("Click '+' to add a custom icon");
Space(4);
GUILayout.Label("Click a custom icon to replace or remove it");
Space(4);
GUILayout.Label("Drag rows to reorder them");
ResetGUIEnabled();
}
Space(15);
colors();
Space(15);
icons();
Space(25);
tutor();
UpdateAnimations();
UpdateDragging();
palette.Dirty();
if (draggingRow || animatingCrossIcon)
Repaint();
}
float iconSize => 18;
float iconSpacing => 2;
float cellSize => iconSize + iconSpacing;
float rowSpacing = 1;
float rowsOffsetX => 14;
float iconsOffsetX => 27;
Color hoveredRowBackground => Greyscale(isDarkTheme ? 1 : 0, .05f);
Color draggedRowBackground => Greyscale(isDarkTheme ? .3f : .9f);
Color pickingBackground => Greyscale(1, .17f);
Color disabledRowTint => Greyscale(1, .45f);
float rowWidth => cellSize * Mathf.Max(palette.colors.Count, palette.iconRows.Max(r => r.iconCount + 1)) + 55;
bool pickingColor;
int pickingColorAtIndex;
EditorWindow colorPicker;
bool pickingIcon;
int pickingIconAtIndex;
IconRow pickingIconAtRow;
EditorWindow iconPicker;
IconRow hoveredRow;
float firstRowY = 51;
void UpdateAnimations()
{
void calcDeltaTime()
{
if (!curEvent.isLayout) return;
deltaTime = (float)(EditorApplication.timeSinceStartup - lastLayoutTime);
if (deltaTime > .05f)
deltaTime = .0166f;
lastLayoutTime = EditorApplication.timeSinceStartup;
}
void lerpRowGaps()
{
if (!curEvent.isLayout) return;
var lerpSpeed = draggingRow ? 12 : 12321;
for (int i = 0; i < rowGaps.Count; i++)
rowGaps[i] = Lerp(rowGaps[i], draggingRow && i == insertDraggedRowAtIndex ? 1 : 0, lerpSpeed, deltaTime);// todo deltatime
for (int i = 0; i < rowGaps.Count; i++)
if (rowGaps[i].Approx(0))
rowGaps[i] = 0;
else if (rowGaps[i].Approx(1))
rowGaps[i] = 1;
}
void lerpCrossIconAnimationT()
{
if (!curEvent.isLayout) return;
var lerpSpeed = 12;
Lerp(ref crossIconAnimationT, 1, lerpSpeed, deltaTime);
}
void startCrossIconAnimation()
{
if (prevFirstEnabledRow == null) { prevFirstEnabledRow = curFirstEnabledRow; return; }
if (prevFirstEnabledRow == curFirstEnabledRow) return;
crossIconAnimationT = 0;
crossIconAnimationSourceRow = prevFirstEnabledRow;
prevFirstEnabledRow = curFirstEnabledRow;
}
void stopCrossIconAnimation()
{
if (!crossIconAnimationT.Approx(1)) return;
crossIconAnimationT = 1;
crossIconAnimationSourceRow = null;
}
void calcCrossIconY()
{
var indexOfFirstEnabled = palette.iconRows.IndexOfFirst(r => r.enabled);
var yOfFirstEnabled = firstRowY + indexOfFirstEnabled * (cellSize + rowSpacing);
for (int i = 0; i < indexOfFirstEnabled + 1; i++)
yOfFirstEnabled += rowGaps[i] * (cellSize + rowSpacing);
var indexOfSourceRow = palette.iconRows.IndexOf(crossIconAnimationSourceRow);
var yOfSourceRow = firstRowY + indexOfSourceRow * (cellSize + rowSpacing);
for (int i = 0; i < indexOfSourceRow + 1; i++)
yOfSourceRow += rowGaps[i] * (cellSize + rowSpacing);
if (crossIconAnimationSourceRow == draggedRow)
yOfSourceRow = draggedRowY;
crossIconY = Lerp(yOfSourceRow, yOfFirstEnabled, crossIconAnimationT);
if (indexOfFirstEnabled == indexOfSourceRow) { crossIconAnimationT = 1; }
}
calcDeltaTime();
lerpRowGaps();
lerpCrossIconAnimationT();
startCrossIconAnimation();
stopCrossIconAnimation();
calcCrossIconY();
}
List<float> rowGaps = new List<float>();
float deltaTime;
double lastLayoutTime;
float crossIconY = 51;
float crossIconAnimationT = 1;
IconRow crossIconAnimationSourceRow;
bool animatingCrossIcon => crossIconAnimationT != 1;
IconRow prevFirstEnabledRow;
IconRow curFirstEnabledRow => palette.iconRows.FirstOrDefault(r => r.enabled);
void UpdateDragging()
{
void startDragging()
{
if (draggingRow) return;
if (!curEvent.isMouseDrag) return;
if (hoveredRow == null) return;
if (hoveredRow == palette.iconRows.Last()) return;
palette.RecordUndo();
draggingRow = true;
draggedRow = hoveredRow;
draggingRowFromIndex = palette.iconRows.IndexOf(hoveredRow);
draggedRowHoldOffset = firstRowY + draggingRowFromIndex * (cellSize + rowSpacing) - curEvent.mousePosition.y;
palette.iconRows.Remove(hoveredRow);
rowGaps[draggingRowFromIndex] = 1;
}
void updateDragging()
{
if (!draggingRow) return;
insertDraggedRowAtIndex = ((curEvent.mousePosition.y - firstRowY) / (cellSize + rowSpacing)).FloorToInt().Clamp(0, palette.iconRows.Count - 1);
EditorGUIUtility.hotControl = EditorGUIUtility.GetControlID(FocusType.Passive);
}
void stopDragging()
{
if (!draggingRow) return;
if (!curEvent.isMouseUp) return;
palette.RecordUndo();
palette.Dirty();
palette.iconRows.AddAt(draggedRow, insertDraggedRowAtIndex);
rowGaps[insertDraggedRowAtIndex] = 0;
draggingRow = false;
draggedRow = null;
EditorGUIUtility.hotControl = 0;
}
startDragging();
updateDragging();
stopDragging();
}
IconRow draggedRow;
bool draggingRow;
int draggingRowFromIndex;
float draggedRowHoldOffset;
float draggedRowY;
int insertDraggedRowAtIndex;
VHierarchyPalette palette => target as VHierarchyPalette;
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2b7dce55e9e9b476fb5d1d669c006123
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,550 @@
#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 Type = System.Type;
using static VHierarchy.VHierarchyData;
using static VHierarchy.VHierarchyPalette;
using static VHierarchy.Libs.VUtils;
using static VHierarchy.Libs.VGUI;
namespace VHierarchy
{
public class VHierarchyPaletteWindow : EditorWindow
{
void OnGUI()
{
if (!palette) { Close(); return; }
int hoveredColorIndex = -1;
string hoveredIconNameOrGuid = null;
void background()
{
position.SetPos(0, 0).Draw(windowBackground);
}
void outline()
{
if (Application.platform == RuntimePlatform.OSXEditor) return;
position.SetPos(0, 0).DrawOutline(Greyscale(.1f));
}
void colors()
{
if (!palette.colorsEnabled) { Space(-spaceAfterColors); return; }
var rowRect = ExpandWidthLabelRect(height: cellSize).SetX(paddingX);
void color(int i)
{
var cellRect = rowRect.MoveX(i * cellSize).SetWidth(cellSize).SetHeightFromMid(cellSize);
void backgroundSelected()
{
if (!initialColorIndexes.Contains(i)) return;
cellRect.Resize(1).DrawWithRoundedCorners(selectedBackground, 2);
}
void backgroundHovered()
{
if (!cellRect.IsHovered()) return;
cellRect.Resize(1).DrawWithRoundedCorners(this.hoveredBackground, 2);
}
void crossIcon()
{
if (i != 0) return;
SetLabelAlignmentCenter();
GUI.Label(cellRect.SetSizeFromMid(iconSize), EditorGUIUtility.IconContent("CrossIcon"));
ResetLabelStyle();
}
void color()
{
if (i == 0) return;
var brightness = i <= VHierarchyPalette.greyColorsCount ? 1.02f : 1.35f;
var outlineColor = i <= VHierarchyPalette.greyColorsCount ? Greyscale(.0f, .4f) : Greyscale(.15f, .2f);
cellRect.Resize(3).DrawWithRoundedCorners(outlineColor, 4);
cellRect.Resize(4).DrawWithRoundedCorners((palette.colors[i - 1] * brightness).SetAlpha(1), 3);
cellRect.Resize(4).AddWidthFromRight(-2).DrawCurtainLeft(GUIColors.windowBackground.SetAlpha((1 - palette.colors[i - 1].a) * .45f));
}
void setHovered()
{
if (!cellRect.IsHovered()) return;
hoveredColorIndex = i;
}
void closeOnClick()
{
if (!cellRect.IsHovered()) return;
if (!curEvent.isMouseDown) return;
Close();
}
cellRect.MarkInteractive();
backgroundSelected();
backgroundHovered();
crossIcon();
color();
setHovered();
closeOnClick();
}
for (int i = 0; i < palette.colors.Count + 1; i++)
color(i);
}
void icons()
{
void row(IconRow iconRow)
{
if (!iconRow.enabled) return;
if (iconRow.isEmpty) return;
var rowRect = ExpandWidthLabelRect(height: cellSize).SetX(paddingX);
var isFirstEnabledRow = palette.iconRows.First(r => r.enabled) == iconRow;
void icon(int i)
{
var cellRect = rowRect.MoveX(i * cellSize).SetWidth(cellSize).SetHeightFromMid(cellSize);
var isCrossIcon = isFirstEnabledRow && i == 0;
var actualIconIndex = isFirstEnabledRow ? i - 1 : i;
var isBuiltinIcon = !isCrossIcon && actualIconIndex < iconRow.builtinIcons.Count;
var isCustomIcon = !isCrossIcon && actualIconIndex >= iconRow.builtinIcons.Count;
var iconNameOrGuid = isCrossIcon ? "" : isCustomIcon ? iconRow.customIcons[actualIconIndex - iconRow.builtinIcons.Count] : iconRow.builtinIcons[actualIconIndex];
void backgroundSelected()
{
if (!initialIconNamesOrGuids.Contains(iconNameOrGuid)) return;
cellRect.Resize(1).DrawWithRoundedCorners(selectedBackground, 2);
}
void backgroundHovered()
{
if (!cellRect.IsHovered()) return;
cellRect.Resize(1).DrawWithRoundedCorners(this.hoveredBackground, 2);
}
void crossIcon()
{
if (!isCrossIcon) return;
SetLabelAlignmentCenter();
GUI.Label(cellRect.SetSizeFromMid(iconSize), EditorGUIUtility.IconContent("CrossIcon"));
ResetLabelStyle();
}
void builtinIcon()
{
if (!isBuiltinIcon) return;
SetLabelAlignmentCenter();
GUI.Label(cellRect.SetSizeFromMid(iconSize), EditorGUIUtility.IconContent(iconNameOrGuid));
ResetLabelStyle();
}
void customIcon()
{
if (!isCustomIcon) return;
var texture = AssetDatabase.LoadAssetAtPath<Texture2D>(iconNameOrGuid.ToPath());
GUI.DrawTexture(cellRect.SetSizeFromMid(iconSize), texture ?? Texture2D.blackTexture);
}
void setHovered()
{
if (!cellRect.IsHovered()) return;
hoveredIconNameOrGuid = iconNameOrGuid;
}
void closeOnClick()
{
if (!cellRect.IsHovered()) return;
if (!curEvent.isMouseDown) return;
Close();
}
cellRect.MarkInteractive();
backgroundSelected();
backgroundHovered();
crossIcon();
builtinIcon();
customIcon();
setHovered();
closeOnClick();
}
for (int i = 0; i < iconRow.iconCount + (isFirstEnabledRow ? 1 : 0); i++)
icon(i);
Space(rowSpacing - 2);
}
for (int i = 0; i < palette.iconRows.Count; i++)
row(palette.iconRows[i]);
}
void setColorsAndIcons()
{
if (!curEvent.isRepaint) return;
if (palette.iconRows.Any(r => r.enabled))
if (hoveredIconNameOrGuid != null)
SetIcon(hoveredIconNameOrGuid);
else
SetInitialIcons();
if (palette.colorsEnabled)
if (hoveredColorIndex != -1)
SetColor(hoveredColorIndex);
else
SetInitialColors();
}
void updatePosition()
{
if (!curEvent.isLayout) return;
void calcDeltaTime()
{
deltaTime = (float)(EditorApplication.timeSinceStartup - lastLayoutTime);
if (deltaTime > .05f)
deltaTime = .0166f;
lastLayoutTime = EditorApplication.timeSinceStartup;
}
void resetCurPos()
{
if (currentPosition != default) return;
currentPosition = position.position; // position.position is always int, which can't be used for lerping
}
void lerpCurPos()
{
var speed = 9;
SmoothDamp(ref currentPosition, targetPosition, speed, ref positionDeriv, deltaTime);
// Lerp(ref currentPosition, targetPosition, speed, deltaTime);
}
void setCurPos()
{
position = position.SetPos(currentPosition);
}
calcDeltaTime();
resetCurPos();
lerpCurPos();
setCurPos();
if (!currentPosition.y.Approx(targetPosition.y))
Repaint();
}
void closeOnEscape()
{
if (!curEvent.isKeyDown) return;
if (curEvent.keyCode != KeyCode.Escape) return;
SetInitialColors();
SetInitialIcons();
Close();
}
RecordUndoOnDatas();
background();
outline();
Space(paddingY);
colors();
Space(spaceAfterColors);
icons();
setColorsAndIcons();
updatePosition();
closeOnEscape();
EditorApplication.RepaintHierarchyWindow();
}
static float iconSize => 18;
static float iconSpacing => 2;
static float cellSize => iconSize + iconSpacing;
static float spaceAfterColors => 11;
public float rowSpacing = 1;
static float paddingX => 12;
static float paddingY => 12;
Color windowBackground => isDarkTheme ? Greyscale(.23f) : Greyscale(.7f);
Color selectedBackground => isDarkTheme ? new Color(.3f, .5f, .7f, .8f) : new Color(.3f, .5f, .7f, .4f) * 1.35f;
Color hoveredBackground = Greyscale(1, .3f);
public Vector2 targetPosition;
public Vector2 currentPosition;
Vector2 positionDeriv;
float deltaTime;
double lastLayoutTime;
void SetIcon(string iconNameOrGuid)
{
foreach (var r in goDatas)
r.iconNameOrGuid = iconNameOrGuid;
}
void SetColor(int colorIndex)
{
foreach (var r in goDatas)
r.colorIndex = colorIndex;
}
void SetInitialIcons()
{
for (int i = 0; i < goDatas.Count; i++)
goDatas[i].iconNameOrGuid = initialIconNamesOrGuids[i];
}
void SetInitialColors()
{
for (int i = 0; i < goDatas.Count; i++)
goDatas[i].colorIndex = initialColorIndexes[i];
}
void RemoveEmptyGoDatas()
{
var toRemove = goDatas.Where(r => r.iconNameOrGuid == "" && r.colorIndex == 0);
foreach (var goData in toRemove)
goData.sceneData.goDatas_byGlobalId.RemoveValue(goData);
if (toRemove.Any())
Undo.CollapseUndoOperations(Undo.GetCurrentGroup() - 1);
}
void RecordUndoOnDatas()
{
if (usingDataSO)
if (data)
data.RecordUndo();
foreach (var r in usedDataComponents)
r.RecordUndo();
}
void MarkDatasDirty()
{
if (usingDataSO)
if (data)
data.Dirty();
foreach (var r in usedDataComponents)
r.Dirty();
}
void SaveData()
{
if (usingDataSO)
data.Save();
}
bool usingDataSO => !gameObjects.Select(r => r.scene).All(r => VHierarchy.dataComponents_byScene.GetValueOrDefault(r) != null);
IEnumerable<VHierarchyDataComponent> usedDataComponents => VHierarchy.dataComponents_byScene.Where(kvp => kvp.Value && gameObjects.Select(r => r.scene).Contains(kvp.Key)).Select(kvp => kvp.Value);
void OnLostFocus()
{
if (curEvent.holdingAlt && EditorWindow.focusedWindow?.GetType().Name == "SceneHierarchyWindow")
CloseNextFrameIfNotRefocused();
else
Close();
}
void CloseNextFrameIfNotRefocused()
{
EditorApplication.delayCall += () => { if (EditorWindow.focusedWindow != this) Close(); };
}
public void Init(List<GameObject> gameObjects)
{
void createData()
{
if (VHierarchy.data) return;
VHierarchy.data = ScriptableObject.CreateInstance<VHierarchyData>();
AssetDatabase.CreateAsset(VHierarchy.data, GetScriptPath("VHierarchy").GetParentPath().CombinePath("vHierarchy Data.asset"));
}
void createPalette()
{
if (VHierarchy.palette) return;
VHierarchy.palette = ScriptableObject.CreateInstance<VHierarchyPalette>();
AssetDatabase.CreateAsset(VHierarchy.palette, GetScriptPath("VHierarchy").GetParentPath().CombinePath("vHierarchy Palette.asset"));
}
void setSize()
{
var rowCellCounts = new List<int>();
if (palette.colorsEnabled)
rowCellCounts.Add(palette.colors.Count + 1);
foreach (var r in palette.iconRows.Where(r => r.enabled))
rowCellCounts.Add(r.iconCount + (r == palette.iconRows.First(r => r.enabled) ? 1 : 0));
var width = rowCellCounts.Max() * cellSize + paddingX * 2;
var iconRowCount = palette.iconRows.Count(r => r.enabled && !r.isEmpty);
var rowCount = iconRowCount + (palette.colorsEnabled ? 1 : 0);
var height = rowCount * (cellSize + rowSpacing) + (palette.colorsEnabled && palette.iconRows.Any(r => r.enabled && !r.isEmpty) ? spaceAfterColors : 0) + paddingY * 2;
position = position.SetSize(width, height).SetPos(targetPosition);
}
void getDatas()
{
goDatas.Clear();
foreach (var r in gameObjects)
goDatas.Add(VHierarchy.GetGameObjectData(r, createDataIfDoesntExist: true));
}
void getInitColorsAndIcons()
{
initialColorIndexes.Clear();
initialIconNamesOrGuids.Clear();
foreach (var r in goDatas)
initialColorIndexes.Add(r.colorIndex);
foreach (var r in goDatas)
initialIconNamesOrGuids.Add(r.iconNameOrGuid);
}
this.gameObjects = gameObjects;
RecordUndoOnDatas();
createData();
createPalette();
setSize();
getDatas();
getInitColorsAndIcons();
}
void OnDestroy()
{
RemoveEmptyGoDatas();
MarkDatasDirty();
SaveData();
}
public List<GameObject> gameObjects = new List<GameObject>();
public List<GameObjectData> goDatas = new List<GameObjectData>();
public List<int> initialColorIndexes = new List<int>();
public List<string> initialIconNamesOrGuids = new List<string>();
static VHierarchyPalette palette => VHierarchy.palette;
static VHierarchyData data => VHierarchy.data;
public static void CreateInstance(Vector2 position)
{
instance = ScriptableObject.CreateInstance<VHierarchyPaletteWindow>();
instance.ShowPopup();
instance.position = instance.position.SetPos(position).SetSize(200, 300);
instance.targetPosition = position;
}
public static VHierarchyPaletteWindow instance;
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8ae240588f29744208e627125db9c9e4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 98436d729d10ab240aea4ae08fcedb45
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 67456a8acc76240a8a8ad9986c0a6a10
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,16 @@
{
"name": "VTabs",
"rootNamespace": "",
"references": [],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 06ab1c341392b4a318f67b84e0da6aab
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fc570418b0cd44cd49a39403a3ba1cf7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 91d4456e469254096af9035b29263ca5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,141 @@
#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 static VTabs.Libs.VUtils;
namespace VTabs
{
public static class VTabsMenu
{
public static bool dragndropEnabled { get => EditorPrefs.GetBool("vTabs-dragndropEnabled", true); set => EditorPrefs.SetBool("vTabs-dragndropEnabled", value); }
public static bool switchTabsEnabled { get => EditorPrefs.GetBool("vTabs-switchTabsEnabled", true); set => EditorPrefs.SetBool("vTabs-switchTabsEnabled", value); }
public static bool moveTabsEnabled { get => EditorPrefs.GetBool("vTabs-moveTabsEnabled", true); set => EditorPrefs.SetBool("vTabs-moveTabsEnabled", value); }
public static bool addTabEnabled { get => EditorPrefs.GetBool("vTabs-addTabEnabled", true); set => EditorPrefs.SetBool("vTabs-addTabEnabled", value); }
public static bool closeTabEnabled { get => EditorPrefs.GetBool("vTabs-closeTabEnabled", true); set => EditorPrefs.SetBool("vTabs-closeTabEnabled", value); }
public static bool reopenTabEnabled { get => EditorPrefs.GetBool("vTabs-reopenTabEnabled", true); set => EditorPrefs.SetBool("vTabs-reopenTabEnabled", value); }
public static bool sidescrollEnabled { get => EditorPrefs.GetBool("vTabs-sidescrollEnabled", Application.platform == RuntimePlatform.OSXEditor); set => EditorPrefs.SetBool("vTabs-sidescrollEnabled", value); }
public static bool reverseScrollDirectionEnabled { get => EditorPrefs.GetBool("vTabs-reverseScrollDirectionDirection", false); set => EditorPrefs.SetBool("vTabs-reverseScrollDirectionDirection", value); }
public static float sidescrollSensitivity { get => EditorPrefs.GetFloat("vTabs-sidescrollSensitivity", 1); set => EditorPrefs.SetFloat("vTabs-sidescrollSensitivity", value); }
public static bool pluginDisabled { get => EditorPrefs.GetBool("vTabs-pluginDisabled", false); set => EditorPrefs.SetBool("vTabs-pluginDisabled", value); }
const string dir = "Tools/vTabs/";
#if UNITY_EDITOR_OSX
const string cmd = "Cmd";
#else
const string cmd = "Ctrl";
#endif
const string dragndrop = dir + "Create tabs with Drag-and-Drop";
const string switchTabs = dir + "Switch tabs with Shift-Scroll";
const string moveTabs = dir + "Move tabs with " + cmd + "-Shift-Scroll";
const string addTab = dir + cmd + "-T to add tab";
const string closeTab = dir + cmd + "-W to close tab";
const string reopenTab = dir + cmd + "-Shift-T to reopen closed tab";
const string sidescroll = dir + "Horizontal Scroll as Shift-Scroll";
const string reverseScrollDirection = dir + "Reverse direction";
const string increaseSensitivity = dir + "Increase sensitivity";
const string decreaseSensitivity = dir + "Decrease sensitivity";
const string disablePlugin = dir + "Disable vTabs";
[MenuItem(dir + "Features", false, 1)] static void dadsas() { }
[MenuItem(dir + "Features", true, 1)] static bool dadsas123() => false;
[MenuItem(dragndrop, false, 2)] static void dadsadsadasdsadadsas() => dragndropEnabled = !dragndropEnabled;
[MenuItem(dragndrop, true, 2)] static bool dadsaddsasadadsdasadsas() { Menu.SetChecked(dragndrop, dragndropEnabled); return !pluginDisabled; }
[MenuItem(switchTabs, false, 3)] static void dadsadsadsadsadasdsadadsas() => switchTabsEnabled = !switchTabsEnabled;
[MenuItem(switchTabs, true, 3)] static bool dadsadasdasddsasadadsdasadsas() { Menu.SetChecked(switchTabs, switchTabsEnabled); return !pluginDisabled; }
[MenuItem(moveTabs, false, 4)] static void dadsadsadsadasdsadadsas() => moveTabsEnabled = !moveTabsEnabled;
[MenuItem(moveTabs, true, 4)] static bool dadsadasddsasadadsdasadsas() { Menu.SetChecked(moveTabs, moveTabsEnabled); return !pluginDisabled; }
[MenuItem(dir + "Shortcuts", false, 101)] static void daaadsas() { }
[MenuItem(dir + "Shortcuts", true, 101)] static bool daadsdsas123() => false;
[MenuItem(addTab, false, 102)] static void dadsadadsas() => addTabEnabled = !addTabEnabled;
[MenuItem(addTab, true, 102)] static bool dadsaddasadsas() { Menu.SetChecked(addTab, addTabEnabled); return !pluginDisabled; }
[MenuItem(closeTab, false, 103)] static void dadsadasdadsas() => closeTabEnabled = !closeTabEnabled;
[MenuItem(closeTab, true, 103)] static bool dadsadsaddasadsas() { Menu.SetChecked(closeTab, closeTabEnabled); return !pluginDisabled; }
[MenuItem(reopenTab, false, 104)] static void dadsadsadasdadsas() => reopenTabEnabled = !reopenTabEnabled;
[MenuItem(reopenTab, true, 104)] static bool dadsaddsasaddasadsas() { Menu.SetChecked(reopenTab, reopenTabEnabled); return !pluginDisabled; }
[MenuItem(dir + "Scrolling", false, 1001)] static void daadsdsadsas() { }
[MenuItem(dir + "Scrolling", true, 1001)] static bool dadsasasdads() => false;
[MenuItem(sidescroll, false, 1002)] static void dadsadsadsadsadasdadssadadsas() => sidescrollEnabled = !sidescrollEnabled;
[MenuItem(sidescroll, true, 1002)] static bool dadsadasdasddsadassadadsdasadsas() { Menu.SetChecked(sidescroll, sidescrollEnabled); return !pluginDisabled; }
[MenuItem(reverseScrollDirection, false, 1003)] static void dadsadadssadsadsadasdadssadadsas() => reverseScrollDirectionEnabled = !reverseScrollDirectionEnabled;
[MenuItem(reverseScrollDirection, true, 1003)] static bool dadsadasdadsasddsadassadadsdasadsas() { Menu.SetChecked(reverseScrollDirection, reverseScrollDirectionEnabled); return !pluginDisabled; }
[MenuItem(increaseSensitivity, false, 1004)] static void qdadadsssa() { sidescrollSensitivity += .2f; Debug.Log("vTabs: scrolling sensitivity increased to " + sidescrollSensitivity * 100 + "%"); }
[MenuItem(increaseSensitivity, true, 1004)] static bool qdaddasadsssa() => !pluginDisabled;
[MenuItem(decreaseSensitivity, false, 1005)] static void qdasadsssa() { sidescrollSensitivity -= .2f; Debug.Log("vTabs: scrolling sensitivity decreased to " + sidescrollSensitivity * 100 + "%"); }
[MenuItem(decreaseSensitivity, true, 1005)] static bool qdaddasdsaadsssa() => !pluginDisabled;
[MenuItem(dir + "More", false, 10001)] static void daasadsddsas() { }
[MenuItem(dir + "More", true, 10001)] static bool dadsadsdasas123() => false;
[MenuItem(dir + "Join our Discord", false, 10002)]
static void dadasdsas() => Application.OpenURL("https://discord.gg/4dG9KsbspG");
[MenuItem(dir + "Check out vFavorites 2", false, 10003)]
static void dadadssadsas() => Application.OpenURL("https://assetstore.unity.com/packages/slug/263643?aid=1100lGLBn&pubref=checkoutvfav");
// [MenuItem(dir + "Get more Editor Enhancers/Get vHierarchy 2", false, 10003)]
// static void dadadssadsas() => Application.OpenURL("https://assetstore.unity.com/packages/slug/251320?aid=1100lGLBn&pubref=menucheckout");
// [MenuItem(dir + "Get more Editor Enhancers/Get vFolders 2", false, 10004)]
// static void dadadssaasddsas() => Application.OpenURL("https://assetstore.unity.com/packages/slug/263644?aid=1100lGLBn&pubref=menucheckout");
// [MenuItem(dir + "Get more Editor Enhancers/Get vFavorites 2", false, 10005)]
// static void dadadsadssaasddsas() => Application.OpenURL("https://assetstore.unity.com/packages/slug/263643?aid=1100lGLBn&pubref=menucheckout");
[MenuItem(disablePlugin, false, 100001)] static void dadsadsdasadasdasdsadadsas() { pluginDisabled = !pluginDisabled; UnityEditor.Compilation.CompilationPipeline.RequestScriptCompilation(); }
[MenuItem(disablePlugin, true, 100001)] static bool dadsaddssdaasadsadadsdasadsas() { Menu.SetChecked(disablePlugin, pluginDisabled); return true; }
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3cf48ada98a1147c4881faf7b79475e6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,6 @@
// this file was present in a previus version and is supposed to be deleted now
// but asset store update delivery system doesn't allow deleting files
// so instead this file is now emptied
// feel free to delete it if you want

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 102836a637c684c11b7581d444fecb04
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: