升级6.4.升级水,升级天气
This commit is contained in:
BIN
Assets/vInspector/Read me.pdf
Normal file
BIN
Assets/vInspector/Read me.pdf
Normal file
Binary file not shown.
7
Assets/vInspector/Read me.pdf.meta
Normal file
7
Assets/vInspector/Read me.pdf.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5bc65026e2b5e458b838d06e4ef39409
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
20
Assets/vInspector/VInspector.asmdef
Normal file
20
Assets/vInspector/VInspector.asmdef
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "VInspector",
|
||||
"rootNamespace": "",
|
||||
"references": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.modules.terrainphysics",
|
||||
"expression": "",
|
||||
"define": "TERRAIN_PACKAGE_ENABLED"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
Assets/vInspector/VInspector.asmdef.meta
Normal file
7
Assets/vInspector/VInspector.asmdef.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de13f8b1675b449e6a6af1cc0f7842ec
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1571
Assets/vInspector/VInspector.cs
Normal file
1571
Assets/vInspector/VInspector.cs
Normal file
File diff suppressed because it is too large
Load Diff
11
Assets/vInspector/VInspector.cs.meta
Normal file
11
Assets/vInspector/VInspector.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb0378825d0df482cb66e646e57e5153
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
143
Assets/vInspector/VInspectorAttributes.cs
Normal file
143
Assets/vInspector/VInspectorAttributes.cs
Normal file
@@ -0,0 +1,143 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
// using static VTools.VDebug;
|
||||
#if UNITY_EDITOR
|
||||
using static VInspector.Libs.VUtils;
|
||||
#endif
|
||||
|
||||
|
||||
namespace VInspector
|
||||
{
|
||||
|
||||
public class FoldoutAttribute : Attribute
|
||||
{
|
||||
public string name;
|
||||
|
||||
public FoldoutAttribute(string name) => this.name = name;
|
||||
|
||||
}
|
||||
public class EndFoldoutAttribute : Attribute { }
|
||||
|
||||
|
||||
|
||||
public class TabAttribute : Attribute
|
||||
{
|
||||
public string name;
|
||||
|
||||
public TabAttribute(string name) => this.name = name;
|
||||
|
||||
}
|
||||
public class EndTabAttribute : Attribute { }
|
||||
|
||||
|
||||
|
||||
public class ButtonAttribute : Attribute
|
||||
{
|
||||
public string name = "";
|
||||
public int size = 30;
|
||||
public int space = 0;
|
||||
public string color = "Grey";
|
||||
|
||||
public ButtonAttribute() => this.name = "";
|
||||
public ButtonAttribute(string name) => this.name = name;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class VariantsAttribute : PropertyAttribute
|
||||
{
|
||||
public object[] variants;
|
||||
|
||||
public VariantsAttribute(params object[] variants) => this.variants = variants;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class MinMaxSliderAttribute : PropertyAttribute
|
||||
{
|
||||
public float min;
|
||||
public float max;
|
||||
|
||||
public MinMaxSliderAttribute(float min, float max) { this.min = min; this.max = max; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public abstract class IfAttribute : Attribute
|
||||
{
|
||||
public string variableName;
|
||||
public object variableValue;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public bool Evaluate(object target)
|
||||
{
|
||||
if (target.GetType().GetFieldInfo(variableName) == null &&
|
||||
target.GetType().GetPropertyInfo(variableName) == null)
|
||||
return false;
|
||||
|
||||
var curValue = target.GetMemberValue(variableName);
|
||||
|
||||
return object.Equals(curValue, variableValue);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
public IfAttribute(string boolName) { this.variableName = boolName; this.variableValue = true; }
|
||||
public IfAttribute(string variableName, object variableValue) { this.variableName = variableName; this.variableValue = variableValue; }
|
||||
|
||||
}
|
||||
public class EndIfAttribute : Attribute { }
|
||||
|
||||
public class HideIfAttribute : IfAttribute
|
||||
{
|
||||
public HideIfAttribute(string boolName) : base(boolName) { }
|
||||
public HideIfAttribute(string variableName, object variableValue) : base(variableName, variableValue) { }
|
||||
}
|
||||
public class ShowIfAttribute : IfAttribute
|
||||
{
|
||||
public ShowIfAttribute(string boolName) : base(boolName) { }
|
||||
public ShowIfAttribute(string variableName, object variableValue) : base(variableName, variableValue) { }
|
||||
}
|
||||
public class EnableIfAttribute : IfAttribute
|
||||
{
|
||||
public EnableIfAttribute(string boolName) : base(boolName) { }
|
||||
public EnableIfAttribute(string variableName, object variableValue) : base(variableName, variableValue) { }
|
||||
}
|
||||
public class DisableIfAttribute : IfAttribute
|
||||
{
|
||||
public DisableIfAttribute(string boolName) : base(boolName) { }
|
||||
public DisableIfAttribute(string variableName, object variableValue) : base(variableName, variableValue) { }
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class ReadOnlyAttribute : Attribute { }
|
||||
|
||||
|
||||
|
||||
public class ShowInInspectorAttribute : Attribute { }
|
||||
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method)]
|
||||
public class OnValueChangedAttribute : Attribute
|
||||
{
|
||||
public string[] variableOrGroupNames;
|
||||
|
||||
public OnValueChangedAttribute(string name) => this.variableOrGroupNames = new[] { name };
|
||||
public OnValueChangedAttribute(params string[] names) => this.variableOrGroupNames = names;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public class TagAttribute : PropertyAttribute { }
|
||||
public class LayerAttribute : PropertyAttribute { }
|
||||
|
||||
}
|
||||
11
Assets/vInspector/VInspectorAttributes.cs.meta
Normal file
11
Assets/vInspector/VInspectorAttributes.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c8d83838ee14b4445a0abac264bf08d8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
233
Assets/vInspector/VInspectorClipboard.cs
Normal file
233
Assets/vInspector/VInspectorClipboard.cs
Normal file
@@ -0,0 +1,233 @@
|
||||
#if UNITY_EDITOR
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.ShortcutManagement;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Type = System.Type;
|
||||
using static VInspector.Libs.VUtils;
|
||||
using static VInspector.Libs.VGUI;
|
||||
// using static VTools.VDebug;
|
||||
|
||||
|
||||
namespace VInspector
|
||||
{
|
||||
public class VInspectorClipboard : ScriptableSingleton<VInspectorClipboard>
|
||||
{
|
||||
public static void CopyComponent(Component component)
|
||||
{
|
||||
instance.RecordUndo();
|
||||
|
||||
if (instance.copiedComponetDatas.FirstOrDefault(r => r.sourceComponent == component) is ComponentData alreadyCopiedData)
|
||||
{
|
||||
instance.discardedComponentDatas.Add(alreadyCopiedData);
|
||||
instance.copiedComponetDatas.Remove(alreadyCopiedData);
|
||||
}
|
||||
else
|
||||
instance.copiedComponetDatas.Add(GetComponentData(component));
|
||||
|
||||
instance.Dirty();
|
||||
|
||||
}
|
||||
public static void PasteComponentValues(ComponentData data, Component component)
|
||||
{
|
||||
component.RecordUndo();
|
||||
|
||||
ApplyComponentData(data, component);
|
||||
|
||||
component.Dirty();
|
||||
|
||||
|
||||
|
||||
instance.RecordUndo();
|
||||
|
||||
instance.copiedComponetDatas.Remove(data);
|
||||
instance.discardedComponentDatas.Add(data);
|
||||
|
||||
instance.Dirty();
|
||||
|
||||
}
|
||||
public static void PasteComponentAsNew(ComponentData data, GameObject gameObject)
|
||||
{
|
||||
var addedComponent = Undo.AddComponent(gameObject, data.sourceComponent.GetType());
|
||||
|
||||
ApplyComponentData(data, addedComponent);
|
||||
|
||||
}
|
||||
|
||||
public static void ClearCopiedDatas()
|
||||
{
|
||||
instance.RecordUndo();
|
||||
|
||||
instance.discardedComponentDatas.AddRange(instance.copiedComponetDatas);
|
||||
instance.copiedComponetDatas.Clear();
|
||||
|
||||
instance.Dirty();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static bool CanComponentsBePastedTo(IEnumerable<GameObject> targetGos)
|
||||
{
|
||||
if (!targetGos.Any()) return false;
|
||||
|
||||
foreach (var copiedData in instance.copiedComponetDatas)
|
||||
if (nonDuplicableComponentTypes.Contains(copiedData.sourceComponent.GetType()))
|
||||
if (targetGos.Any(r => r.TryGetComponent(copiedData.sourceComponent.GetType(), out _)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
static Type[] nonDuplicableComponentTypes = new[]
|
||||
{
|
||||
typeof(Transform),
|
||||
typeof(RectTransform),
|
||||
typeof(MeshFilter),
|
||||
typeof(MeshRenderer),
|
||||
typeof(SkinnedMeshRenderer),
|
||||
typeof(Camera),
|
||||
typeof(AudioListener),
|
||||
typeof(Rigidbody),
|
||||
typeof(Rigidbody2D),
|
||||
typeof(Light),
|
||||
typeof(Canvas),
|
||||
typeof(Animation),
|
||||
typeof(Animator),
|
||||
typeof(AudioSource),
|
||||
typeof(ParticleSystem),
|
||||
typeof(TrailRenderer),
|
||||
typeof(LineRenderer),
|
||||
typeof(LensFlare),
|
||||
typeof(Projector),
|
||||
typeof(AudioReverbZone),
|
||||
typeof(AudioEchoFilter),
|
||||
#if TERRAIN_PACKAGE_ENABLED
|
||||
typeof(Terrain),
|
||||
typeof(TerrainCollider),
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
[SerializeReference] public List<ComponentData> copiedComponetDatas = new();
|
||||
|
||||
[SerializeReference] public List<ComponentData> discardedComponentDatas = new(); // removed datas get stashed here so they can be restored on undo/redo
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static void SaveComponent(Component component)
|
||||
{
|
||||
instance.RecordUndo();
|
||||
|
||||
if (instance.savedComponentDatas.FirstOrDefault(r => r.sourceComponent == component) is ComponentData alreadySavedData)
|
||||
{
|
||||
instance.discardedComponentDatas.Add(alreadySavedData);
|
||||
instance.savedComponentDatas.Remove(alreadySavedData);
|
||||
}
|
||||
else
|
||||
instance.savedComponentDatas.Add(GetComponentData(component, saveGlobalId: true));
|
||||
|
||||
instance.Dirty();
|
||||
|
||||
}
|
||||
|
||||
public static void OnPlaymodeStateChanged(PlayModeStateChange state)
|
||||
{
|
||||
if (state == PlayModeStateChange.EnteredPlayMode)
|
||||
instance.failedToSaveComponentDatas.Clear();
|
||||
|
||||
|
||||
if (state != PlayModeStateChange.EnteredEditMode) return;
|
||||
|
||||
foreach (var data in instance.savedComponentDatas)
|
||||
if (_EditorUtility_InstanceIDToObject(data.sourceComponent.GetInstanceID()) is Component sourceComponent)
|
||||
ApplyComponentData(data, sourceComponent);
|
||||
else if (data.globalId.GetObject() is Component sourceComponent_)
|
||||
ApplyComponentData(data, sourceComponent_);
|
||||
else
|
||||
instance.failedToSaveComponentDatas.Add(data);
|
||||
|
||||
instance.savedComponentDatas.Clear();
|
||||
|
||||
}
|
||||
|
||||
[SerializeReference] public List<ComponentData> savedComponentDatas = new();
|
||||
[SerializeReference] public List<ComponentData> failedToSaveComponentDatas = new();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static ComponentData GetComponentData(Component component, bool saveGlobalId = false)
|
||||
{
|
||||
var data = new ComponentData();
|
||||
|
||||
data.sourceComponent = component;
|
||||
|
||||
if (saveGlobalId)
|
||||
data.globalId = component.GetGlobalID();
|
||||
|
||||
|
||||
|
||||
var property = new SerializedObject(component).GetIterator();
|
||||
|
||||
if (!property.Next(true)) return data;
|
||||
|
||||
|
||||
do data.serializedPropertyValues_byPath[property.propertyPath] = property.GetBoxedValue();
|
||||
while (property.NextVisible(true));
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
public static void ApplyComponentData(ComponentData componentData, Component targetComponent)
|
||||
{
|
||||
foreach (var key in componentData.serializedPropertyValues_byPath.Keys.ToList())
|
||||
if (componentData.serializedPropertyValues_byPath[key] is Object unityObject && !unityObject) // sometimes object references become null after playmode in unity 6, so we have to restore them by instanceId
|
||||
componentData.serializedPropertyValues_byPath[key] = _EditorUtility_InstanceIDToObject(unityObject.GetInstanceID());
|
||||
|
||||
foreach (var kvp in componentData.serializedPropertyValues_byPath)
|
||||
{
|
||||
var so = new SerializedObject(targetComponent);
|
||||
var property = so.FindProperty(kvp.Key);
|
||||
|
||||
so.Update();
|
||||
|
||||
property.SetBoxedValue(kvp.Value);
|
||||
|
||||
so.ApplyModifiedProperties();
|
||||
|
||||
targetComponent.Dirty();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class ComponentData
|
||||
{
|
||||
public Component sourceComponent;
|
||||
public Dictionary<string, object> serializedPropertyValues_byPath = new();
|
||||
|
||||
public GlobalID globalId;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
11
Assets/vInspector/VInspectorClipboard.cs.meta
Normal file
11
Assets/vInspector/VInspectorClipboard.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e946bdceafc44945ad0c659f550d6d5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
463
Assets/vInspector/VInspectorComponentHeader.cs
Normal file
463
Assets/vInspector/VInspectorComponentHeader.cs
Normal file
@@ -0,0 +1,463 @@
|
||||
#if UNITY_EDITOR
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using static VInspector.Libs.VUtils;
|
||||
using static VInspector.Libs.VGUI;
|
||||
// using static VTools.VDebug;
|
||||
|
||||
|
||||
|
||||
namespace VInspector
|
||||
{
|
||||
public class VInspectorComponentHeader
|
||||
{
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
void masks()
|
||||
{
|
||||
if (!curEvent.isRepaint) return;
|
||||
|
||||
|
||||
Color backgroundColor;
|
||||
|
||||
void set_backgroundColor()
|
||||
{
|
||||
var hovered = EditorGUIUtility.isProSkin ? Greyscale(.28f) : Greyscale(.84f);
|
||||
var normal = EditorGUIUtility.isProSkin ? Greyscale(.244f) : Greyscale(.8f);
|
||||
|
||||
backgroundColor = normal;
|
||||
|
||||
if (headerRect.IsHovered() && !mousePressedOnBackground && EditorWindow.mouseOverWindow == window)
|
||||
backgroundColor = hovered;
|
||||
|
||||
}
|
||||
void set_buttonMaskSize()
|
||||
{
|
||||
buttonsList ??= typeof(EditorGUIUtility).GetMemberValue<IList>("s_EditorHeaderItemsMethods");
|
||||
|
||||
var buttonsCount = 1 + buttonsList.Count;
|
||||
|
||||
if (VInspectorMenu.playmodeSaveButtonEnabled && !Application.isPlaying)
|
||||
buttonsCount--;
|
||||
|
||||
|
||||
buttonMaskRect = headerRect.AddHeightFromMid(-2).SetXMax(headerRect.xMax - 3).SetWidthFromRight(buttonsCount * 20);
|
||||
|
||||
}
|
||||
|
||||
void hideArrow()
|
||||
{
|
||||
if (headerRect.IsHovered()) return;
|
||||
if (!VInspectorMenu.minimalModeEnabled) return;
|
||||
|
||||
headerRect.SetWidth(17).MoveX(-2).AddHeightFromMid(-2).AddWidthFromRight(-4).Draw(backgroundColor);
|
||||
|
||||
}
|
||||
void hideButtons()
|
||||
{
|
||||
if (headerRect.IsHovered()) return;
|
||||
if (!VInspectorMenu.minimalModeEnabled) return;
|
||||
|
||||
buttonMaskRect.Draw(backgroundColor);
|
||||
|
||||
}
|
||||
void hideScriptText()
|
||||
{
|
||||
if (component is not MonoBehaviour) return;
|
||||
if (!VInspectorMenu.minimalModeEnabled) return;
|
||||
if (imguiContainer.onGUIHandler.Method.DeclaringType.FullName.StartsWith("Sisus")) return;
|
||||
|
||||
|
||||
var name = component.GetType().Name.Decamelcase();
|
||||
|
||||
var rect = headerRect.AddHeightFromMid(-2).SetWidth(60).MoveX(name.GetLabelWidth(fontSize: 12, isBold: true) + 60 - 3);
|
||||
rect = rect.MoveX(-2);
|
||||
|
||||
rect.xMax = rect.xMax.Min(buttonMaskRect.x).Max(rect.xMin);
|
||||
|
||||
|
||||
rect.Draw(backgroundColor);
|
||||
|
||||
}
|
||||
void tintScriptIcon()
|
||||
{
|
||||
if (component is not MonoBehaviour) return;
|
||||
if (!mousePressedOnScriptIcon) return;
|
||||
|
||||
var iconRect = headerRect.MoveX(18).SetWidth(22);
|
||||
|
||||
iconRect.Draw(backgroundColor.SetAlpha(EditorGUIUtility.isProSkin ? .3f : .45f));
|
||||
|
||||
}
|
||||
void nameCurtain()
|
||||
{
|
||||
var rect = headerRect.AddHeightFromMid(-2).SetXMax(buttonMaskRect.x + 2).SetWidthFromRight(18);
|
||||
|
||||
rect.DrawCurtainLeft(backgroundColor);
|
||||
|
||||
}
|
||||
|
||||
|
||||
set_backgroundColor();
|
||||
set_buttonMaskSize();
|
||||
|
||||
hideArrow();
|
||||
hideButtons();
|
||||
hideScriptText();
|
||||
tintScriptIcon();
|
||||
nameCurtain();
|
||||
|
||||
}
|
||||
|
||||
void scriptIconClicks()
|
||||
{
|
||||
if (component is not MonoBehaviour) return;
|
||||
if (curEvent.mouseButton != 0) return;
|
||||
if (!VInspectorMenu.hideScriptFieldEnabled) return;
|
||||
|
||||
var iconRect = headerRect.MoveX(18).SetWidth(22);
|
||||
|
||||
|
||||
void mosueDown()
|
||||
{
|
||||
if (!curEvent.isMouseDown) return;
|
||||
if (!iconRect.IsHovered()) return;
|
||||
|
||||
|
||||
mousePressedOnScriptIcon = true;
|
||||
mousePressedOnScriptIcon_initPos = curEvent.mousePosition;
|
||||
|
||||
|
||||
var script = MonoScript.FromMonoBehaviour(component as MonoBehaviour);
|
||||
|
||||
// if (curEvent.holdingAlt)
|
||||
|
||||
|
||||
if (curEvent.clickCount == 2)
|
||||
AssetDatabase.OpenAsset(script);
|
||||
|
||||
|
||||
curEvent.Use();
|
||||
|
||||
}
|
||||
void mouseUp()
|
||||
{
|
||||
if (!curEvent.isMouseUp) return;
|
||||
if (!mousePressedOnScriptIcon) return;
|
||||
|
||||
var script = MonoScript.FromMonoBehaviour(component as MonoBehaviour);
|
||||
|
||||
if (curEvent.clickCount == 1)
|
||||
EditorUtils.PingObject(script);
|
||||
|
||||
mousePressedOnScriptIcon = false;
|
||||
|
||||
window.Repaint();
|
||||
|
||||
curEvent.Use();
|
||||
|
||||
}
|
||||
void startDrag()
|
||||
{
|
||||
if (!curEvent.isMouseDrag) return;
|
||||
if (!mousePressedOnScriptIcon) return;
|
||||
if ((mousePressedOnScriptIcon_initPos - curEvent.mousePosition).magnitude < 2) return;
|
||||
|
||||
DragAndDrop.PrepareStartDrag();
|
||||
DragAndDrop.objectReferences = new[] { component };
|
||||
DragAndDrop.StartDrag(component.ToString());
|
||||
|
||||
mousePressedOnScriptIcon = false;
|
||||
mousePressedOnBackground = false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
mosueDown();
|
||||
mouseUp();
|
||||
startDrag();
|
||||
|
||||
}
|
||||
|
||||
void expandWithAnimation()
|
||||
{
|
||||
if (!mousePressedOnBackground) return;
|
||||
if (!curEvent.isMouseUp) return;
|
||||
if (curEvent.mouseButton != 0) return;
|
||||
if (headerRect.SetWidth(16).MoveX(40).IsHovered()) return; // enabled toggle
|
||||
if (buttonMaskRect.IsHovered()) return; // right buttons
|
||||
|
||||
|
||||
if (curEvent.holdingShift)
|
||||
VInspector.CollapseOtherComponents(component, window);
|
||||
|
||||
else if (VInspectorMenu.componentAnimationsEnabled)
|
||||
VInspector.ToggleComponentExpanded(component, window);
|
||||
|
||||
else return;
|
||||
|
||||
|
||||
mousePressedOnBackground = false;
|
||||
|
||||
curEvent.Use();
|
||||
|
||||
EditorGUIUtility.hotControl = 0;
|
||||
|
||||
}
|
||||
void createComponentWindow()
|
||||
{
|
||||
if (!mousePressedOnBackground) return;
|
||||
if (!curEvent.isMouseDrag) return;
|
||||
if (!curEvent.holdingAlt) return;
|
||||
if (curEvent.mousePosition.DistanceTo(mousePressedOnBackground_initPos) < 2) return;
|
||||
if (!VInspectorMenu.componentWindowsEnabled) return;
|
||||
|
||||
if (VInspectorComponentWindow.draggedInstance != null) return;
|
||||
|
||||
|
||||
|
||||
var position = EditorGUIUtility.GUIToScreenPoint(headerRect.position + (curEvent.mousePosition - mousePressedOnBackground_initPos));
|
||||
|
||||
VInspectorComponentWindow.CreateDraggedInstance(component, position, headerRect.width);
|
||||
|
||||
|
||||
|
||||
EditorGUIUtility.hotControl = 0;
|
||||
|
||||
mousePressedOnBackground = false;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void set_mousePressedOnBackground()
|
||||
{
|
||||
if (curEvent.isMouseDown && !buttonMaskRect.IsHovered())
|
||||
{
|
||||
mousePressedOnBackground = true;
|
||||
mousePressedOnBackground_initPos = curEvent.mousePosition;
|
||||
}
|
||||
|
||||
if (curEvent.isMouseUp || curEvent.isDragUpdate)
|
||||
mousePressedOnBackground = false;
|
||||
|
||||
if (!imguiContainer.contentRect.IsHovered())
|
||||
mousePressedOnBackground = false;
|
||||
|
||||
}
|
||||
void set_hoveredComponentHeader()
|
||||
{
|
||||
if (!curEvent.isRepaint) return;
|
||||
|
||||
if (component is Transform)
|
||||
VInspector.hoveredComponentHeader = null;
|
||||
|
||||
if (headerRect.IsHovered())
|
||||
VInspector.hoveredComponentHeader = this;
|
||||
|
||||
}
|
||||
|
||||
void defaultHeaderGUI()
|
||||
{
|
||||
void initOffsets()
|
||||
{
|
||||
if (!VInspectorMenu.minimalModeEnabled) return;
|
||||
if (headerContentStyle != null) return;
|
||||
|
||||
headerContentStyle = typeof(EditorStyles).GetMemberValue<GUIStyle>("inspectorTitlebar");
|
||||
headerFoldoutStyle = typeof(EditorStyles).GetMemberValue<GUIStyle>("titlebarFoldout");
|
||||
|
||||
headerContentStyle_defaultLeftPadding = headerContentStyle.padding.left;
|
||||
headerFoldoutStyle_defaultLeftMargin = headerFoldoutStyle.margin.left;
|
||||
|
||||
}
|
||||
void setAdjustedOffsets()
|
||||
{
|
||||
if (!VInspectorMenu.minimalModeEnabled) return;
|
||||
|
||||
headerContentStyle.padding.left = headerContentStyle_defaultLeftPadding - 2;
|
||||
headerFoldoutStyle.margin.left = headerFoldoutStyle_defaultLeftMargin - 1;
|
||||
|
||||
}
|
||||
void setDefaultOffsets()
|
||||
{
|
||||
if (!VInspectorMenu.minimalModeEnabled) return;
|
||||
|
||||
headerContentStyle.padding.left = headerContentStyle_defaultLeftPadding;
|
||||
headerFoldoutStyle.margin.left = headerFoldoutStyle_defaultLeftMargin;
|
||||
|
||||
}
|
||||
|
||||
initOffsets();
|
||||
setAdjustedOffsets();
|
||||
defaultHeaderGUIAction.Invoke();
|
||||
setDefaultOffsets();
|
||||
|
||||
}
|
||||
|
||||
void preventKeyboardFocus()
|
||||
{
|
||||
if (!curEvent.isUsed) return;
|
||||
if (!headerRect.IsHovered()) return;
|
||||
if (imguiContainer.onGUIHandler.Method.DeclaringType.FullName.StartsWith("Sisus")) return;
|
||||
|
||||
GUIUtility.keyboardControl = 0;
|
||||
|
||||
// removes that annoying blue highlight after clicking on header
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (curEvent.isRepaint)
|
||||
defaultHeaderGUI();
|
||||
|
||||
masks();
|
||||
|
||||
scriptIconClicks();
|
||||
expandWithAnimation();
|
||||
createComponentWindow();
|
||||
|
||||
set_mousePressedOnBackground();
|
||||
set_hoveredComponentHeader();
|
||||
|
||||
if (!curEvent.isRepaint)
|
||||
defaultHeaderGUI();
|
||||
|
||||
preventKeyboardFocus();
|
||||
|
||||
}
|
||||
|
||||
static IList buttonsList;
|
||||
static Rect buttonMaskRect;
|
||||
|
||||
public bool mousePressedOnBackground;
|
||||
public bool mousePressedOnScriptIcon;
|
||||
public Vector2 mousePressedOnBackground_initPos;
|
||||
public Vector2 mousePressedOnScriptIcon_initPos;
|
||||
|
||||
public Rect headerRect
|
||||
{
|
||||
get
|
||||
{
|
||||
var contentRect = imguiContainer.contentRect;
|
||||
|
||||
if (contentRect.height == 42) // with extra lines like "Multi-object editing not supported"
|
||||
return contentRect.SetHeight(22);
|
||||
else
|
||||
return contentRect.SetHeightFromBottom(22); // fixes offset on transform header in 6000
|
||||
}
|
||||
}
|
||||
|
||||
static GUIStyle headerContentStyle;
|
||||
static GUIStyle headerFoldoutStyle;
|
||||
|
||||
static int headerContentStyle_defaultLeftPadding;
|
||||
static int headerFoldoutStyle_defaultLeftMargin;
|
||||
|
||||
public Vector2 mouseDownPos;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (imguiContainer is VisualElement v && v.panel == null) { imguiContainer.onGUIHandler = defaultHeaderGUIAction; imguiContainer = null; }
|
||||
if (imguiContainer?.onGUIHandler.Method.DeclaringType == typeof(VInspectorComponentHeader)) return;
|
||||
if (imguiContainer?.onGUIHandler.Method.DeclaringType.FullName.StartsWith("Sisus") == true) return;
|
||||
if (typeof(ScriptableObject).IsAssignableFrom(component.GetType())) return;
|
||||
if (editor.GetPropertyValue("propertyViewer") is not EditorWindow window) return;
|
||||
|
||||
|
||||
this.window = window;
|
||||
|
||||
void fixWrongWindow()
|
||||
{
|
||||
if (Application.unityVersion != "2022.3.26f1" && Application.unityVersion != "2023.2.20f1") return;
|
||||
|
||||
if (!window.hasFocus)
|
||||
window = window.GetMemberValue("m_Parent")?.GetMemberValue<List<EditorWindow>>("m_Panes")?.FirstOrDefault(r => r.hasFocus) ?? window;
|
||||
|
||||
// in some versions wrong inspector may be returned by propertyViewer when there are multiple inspectors
|
||||
// also the same instance of an editor may be used on all inspectors
|
||||
// here we fix it for cases when multiple inspectors are in the same dock area
|
||||
|
||||
}
|
||||
void findHeader(VisualElement element)
|
||||
{
|
||||
if (element == null) return;
|
||||
|
||||
if (element.GetType().Name == "EditorElement")
|
||||
{
|
||||
IMGUIContainer curHeaderImguiContainer = null;
|
||||
|
||||
foreach (var child in element.Children())
|
||||
{
|
||||
curHeaderImguiContainer ??= new[] { child as IMGUIContainer }.FirstOrDefault(r => r != null && r.name.EndsWith("Header"));
|
||||
|
||||
if (curHeaderImguiContainer is null) continue;
|
||||
if (child is not InspectorElement) continue;
|
||||
if (child.GetFieldValue("m_Editor") is not Editor editor) continue;
|
||||
if (editor.target != component) continue;
|
||||
|
||||
imguiContainer = curHeaderImguiContainer;
|
||||
|
||||
if (editingMultiselection = editor.targets.Count() > 1)
|
||||
multiselectedComponents = editor.targets.Cast<Component>().ToList();
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
foreach (var r in element.Children())
|
||||
if (imguiContainer == null)
|
||||
findHeader(r);
|
||||
|
||||
}
|
||||
void setupGUICallbacks()
|
||||
{
|
||||
if (imguiContainer == null) return;
|
||||
|
||||
defaultHeaderGUIAction = imguiContainer.onGUIHandler;
|
||||
imguiContainer.onGUIHandler = OnGUI;
|
||||
}
|
||||
|
||||
fixWrongWindow();
|
||||
findHeader(window.rootVisualElement);
|
||||
setupGUICallbacks();
|
||||
|
||||
}
|
||||
|
||||
public bool editingMultiselection;
|
||||
public List<Component> multiselectedComponents;
|
||||
|
||||
IMGUIContainer imguiContainer;
|
||||
System.Action defaultHeaderGUIAction;
|
||||
|
||||
EditorWindow window;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public VInspectorComponentHeader(Component component, Editor editor) { this.component = component; this.editor = editor; }
|
||||
|
||||
public Editor editor;
|
||||
public Component component;
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
11
Assets/vInspector/VInspectorComponentHeader.cs.meta
Normal file
11
Assets/vInspector/VInspectorComponentHeader.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 69daed4ccfde7447ba633e320119de35
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
498
Assets/vInspector/VInspectorComponentWindow.cs
Normal file
498
Assets/vInspector/VInspectorComponentWindow.cs
Normal file
@@ -0,0 +1,498 @@
|
||||
#if UNITY_EDITOR
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.ShortcutManagement;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEditor.SceneManagement;
|
||||
using Type = System.Type;
|
||||
using static VInspector.VInspector;
|
||||
using static VInspector.Libs.VUtils;
|
||||
using static VInspector.Libs.VGUI;
|
||||
// using static VTools.VDebug;
|
||||
|
||||
|
||||
namespace VInspector
|
||||
{
|
||||
public class VInspectorComponentWindow : EditorWindow
|
||||
{
|
||||
|
||||
void OnGUI()
|
||||
{
|
||||
if (!component) component = _EditorUtility_InstanceIDToObject(componentIid) as Component;
|
||||
if (!component) { Close(); return; }
|
||||
if (!editor) { Init(component); skipHeightUpdate = true; }
|
||||
|
||||
|
||||
void background()
|
||||
{
|
||||
position.SetPos(0, 0).Draw(GUIColors.windowBackground);
|
||||
}
|
||||
void header()
|
||||
{
|
||||
var headerRect = ExpandWidthLabelRect(18).Resize(-1).AddWidthFromMid(6);
|
||||
var closeButtonRect = headerRect.SetWidthFromRight(16).SetHeightFromMid(16).Move(-4, 0);
|
||||
|
||||
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;
|
||||
|
||||
|
||||
draggedInstance = this;
|
||||
|
||||
dragStartMousePos = curEvent.mousePosition_screenSpace;
|
||||
dragStartWindowPos = position.position;
|
||||
|
||||
}
|
||||
void updateDragging()
|
||||
{
|
||||
if (!isDragged) return;
|
||||
|
||||
|
||||
var draggedPosition = dragStartWindowPos + curEvent.mousePosition_screenSpace - dragStartMousePos;
|
||||
|
||||
if (!curEvent.isRepaint)
|
||||
position = position.SetPos(draggedPosition);
|
||||
|
||||
|
||||
EditorGUIUtility.hotControl = EditorGUIUtility.GetControlID(FocusType.Passive);
|
||||
|
||||
}
|
||||
void stopDragging()
|
||||
{
|
||||
if (!isDragged) return;
|
||||
if (!curEvent.isMouseMove && !curEvent.isMouseUp) return;
|
||||
|
||||
|
||||
draggedInstance = null;
|
||||
|
||||
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);
|
||||
|
||||
if (!componentIcons_byType.ContainsKey(component.GetType()))
|
||||
componentIcons_byType[component.GetType()] = EditorGUIUtility.ObjectContent(component, component.GetType()).image;
|
||||
|
||||
GUI.Label(iconRect, componentIcons_byType[component.GetType()]);
|
||||
|
||||
}
|
||||
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 = new GUIContent(EditorGUIUtility.ObjectContent(component, component.GetType())).text;
|
||||
s = s.Substring(s.LastIndexOf('(') + 1);
|
||||
s = s.Substring(0, s.Length - 1);
|
||||
|
||||
if (instances.Any(r => r.component.GetType() == component.GetType() && r.component != component))
|
||||
s += " - " + component.gameObject.name;
|
||||
|
||||
|
||||
SetLabelBold();
|
||||
|
||||
GUI.Label(nameRect, s);
|
||||
|
||||
ResetLabelStyle();
|
||||
|
||||
}
|
||||
void nameCurtain()
|
||||
{
|
||||
var flatColorRect = headerRect.SetX(closeButtonRect.x + 3).SetXMax(headerRect.xMax);
|
||||
var gradientRect = headerRect.SetXMax(flatColorRect.x).SetWidthFromRight(30);
|
||||
|
||||
flatColorRect.Draw(backgroundColor);
|
||||
gradientRect.DrawCurtainLeft(backgroundColor);
|
||||
|
||||
}
|
||||
void closeButton()
|
||||
{
|
||||
var iconName = "CrossIcon";
|
||||
var iconSize = 14;
|
||||
var color = isDarkTheme ? Greyscale(.65f) : Greyscale(.35f);
|
||||
var colorHovered = isDarkTheme ? Greyscale(.9f) : color;
|
||||
var colorPressed = color;
|
||||
|
||||
|
||||
if (!IconButton(closeButtonRect, iconName, iconSize, color, colorHovered, colorPressed)) return;
|
||||
|
||||
Close();
|
||||
|
||||
EditorGUIUtility.ExitGUI();
|
||||
|
||||
}
|
||||
void rightClick()
|
||||
{
|
||||
if (!curEvent.isMouseDown) return;
|
||||
if (curEvent.mouseButton != 1) return;
|
||||
if (!headerRect.IsHovered()) return;
|
||||
|
||||
typeof(EditorUtility).InvokeMethod("DisplayObjectContextMenu", Rect.zero.SetPos(curEvent.mousePosition), component, 0);
|
||||
|
||||
}
|
||||
|
||||
startDragging();
|
||||
updateDragging();
|
||||
stopDragging();
|
||||
|
||||
background();
|
||||
icon();
|
||||
toggle();
|
||||
name();
|
||||
nameCurtain();
|
||||
closeButton();
|
||||
rightClick();
|
||||
|
||||
}
|
||||
void body_imgui()
|
||||
{
|
||||
if (useUITK) return;
|
||||
|
||||
|
||||
EditorGUIUtility.labelWidth = (this.position.width * .4f).Max(120);
|
||||
|
||||
|
||||
scrollPosition = EditorGUILayout.BeginScrollView(Vector2.up * scrollPosition).y;
|
||||
BeginIndent(17);
|
||||
|
||||
|
||||
editor?.OnInspectorGUI();
|
||||
|
||||
updateHeight_imgui();
|
||||
|
||||
|
||||
EndIndent(1);
|
||||
EditorGUILayout.EndScrollView();
|
||||
|
||||
|
||||
EditorGUIUtility.labelWidth = 0;
|
||||
|
||||
}
|
||||
void outline()
|
||||
{
|
||||
if (Application.platform == RuntimePlatform.OSXEditor) return;
|
||||
|
||||
position.SetPos(0, 0).DrawOutline(Greyscale(.1f));
|
||||
|
||||
}
|
||||
|
||||
void updateHeight_imgui()
|
||||
{
|
||||
if (useUITK) return;
|
||||
|
||||
|
||||
ExpandWidthLabelRect(height: -5);
|
||||
|
||||
if (!curEvent.isRepaint) return;
|
||||
if (isResizingVertically) return;
|
||||
|
||||
|
||||
targetHeight = lastRect.y + 30;
|
||||
|
||||
position = position.SetHeight(targetHeight.Min(maxHeight));
|
||||
|
||||
|
||||
prevHeight = position.height;
|
||||
|
||||
}
|
||||
void updateHeight_uitk()
|
||||
{
|
||||
if (!useUITK) return;
|
||||
if (!curEvent.isRepaint) return;
|
||||
if (skipHeightUpdate) { skipHeightUpdate = false; return; } // crashses otherwise
|
||||
|
||||
|
||||
var lastElement = inspectorElement[inspectorElement.childCount - 1];
|
||||
|
||||
targetHeight = lastElement.contentRect.yMax + 33;
|
||||
|
||||
position = position.SetHeight(targetHeight);
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
void stopResize()
|
||||
{
|
||||
if (!isResizingVertically) return;
|
||||
if (!curEvent.isMouseUp) return;
|
||||
|
||||
isResizingVertically = false;
|
||||
|
||||
EditorGUIUtility.hotControl = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
EditorGUIUtility.AddCursorRect(resizeArea, MouseCursor.ResizeVertical);
|
||||
|
||||
startResize();
|
||||
updateResize();
|
||||
stopResize();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
background();
|
||||
header();
|
||||
|
||||
|
||||
horizontalResize();
|
||||
verticalResize();
|
||||
|
||||
|
||||
Space(3);
|
||||
body_imgui();
|
||||
outline();
|
||||
|
||||
Space(7);
|
||||
|
||||
updateHeight_uitk();
|
||||
|
||||
|
||||
if (isDragged)
|
||||
Repaint();
|
||||
|
||||
EditorApplication.delayCall -= Repaint;
|
||||
EditorApplication.delayCall += Repaint;
|
||||
|
||||
}
|
||||
|
||||
public bool isDragged => draggedInstance == this;
|
||||
public Vector2 dragStartMousePos;
|
||||
public Vector2 dragStartWindowPos;
|
||||
|
||||
public bool isResizingHorizontally;
|
||||
public bool isResizingVertically;
|
||||
public Vector2 resizeStartMousePos;
|
||||
public Vector2 resizeStartWindowSize;
|
||||
|
||||
public float scrollPosition;
|
||||
|
||||
bool skipHeightUpdate;
|
||||
|
||||
public float targetHeight;
|
||||
public float maxHeight;
|
||||
public float prevHeight;
|
||||
|
||||
static Dictionary<System.Type, Texture> componentIcons_byType = new();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void Init(Component component)
|
||||
{
|
||||
if (editor)
|
||||
editor.DestroyImmediate();
|
||||
|
||||
this.component = component;
|
||||
this.editor = Editor.CreateEditor(component);
|
||||
|
||||
this.componentIid = component.GetInstanceID();
|
||||
|
||||
hasCustomUITKEditor = editor.GetType().GetMethod("CreateInspectorGUI", maxBindingFlags) != null;
|
||||
|
||||
if (!instances.Contains(this))
|
||||
instances.Add(this);
|
||||
|
||||
|
||||
|
||||
if (!useUITK) return;
|
||||
|
||||
inspectorElement = new InspectorElement(editor.serializedObject);
|
||||
|
||||
inspectorElement.style.marginTop = 23;
|
||||
|
||||
this.rootVisualElement.Add(inspectorElement);
|
||||
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
editor?.DestroyImmediate();
|
||||
|
||||
if (instances.Contains(this))
|
||||
instances.Remove(this);
|
||||
|
||||
}
|
||||
|
||||
public Component component;
|
||||
public Editor editor;
|
||||
public InspectorElement inspectorElement;
|
||||
|
||||
public int componentIid;
|
||||
|
||||
bool useUITK => editor.target is MonoBehaviour && (HasUITKOnlyDrawers(editor.serializedObject) || hasCustomUITKEditor);
|
||||
bool hasCustomUITKEditor;
|
||||
|
||||
public static List<VInspectorComponentWindow> instances = new();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static void CreateDraggedInstance(Component component, Vector2 windowPosition, float windowWidth)
|
||||
{
|
||||
draggedInstance = ScriptableObject.CreateInstance<VInspectorComponentWindow>();
|
||||
|
||||
draggedInstance.ShowPopup();
|
||||
draggedInstance.Init(component);
|
||||
draggedInstance.Focus();
|
||||
|
||||
|
||||
draggedInstance.wantsMouseMove = true;
|
||||
|
||||
// draggedInstance.minSize = new Vector2(300, 50); // will make window resizeable on mac, but not on windows
|
||||
draggedInstance.maxHeight = EditorGUIUtility.GetMainWindowPosition().height * .7f;
|
||||
|
||||
|
||||
draggedInstance.position = Rect.zero.SetPos(windowPosition).SetWidth(windowWidth).SetHeight(200);
|
||||
draggedInstance.prevHeight = draggedInstance.position.height;
|
||||
|
||||
draggedInstance.dragStartMousePos = curEvent.mousePosition_screenSpace;
|
||||
draggedInstance.dragStartWindowPos = windowPosition;
|
||||
|
||||
}
|
||||
|
||||
public static VInspectorComponentWindow draggedInstance;
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
11
Assets/vInspector/VInspectorComponentWindow.cs.meta
Normal file
11
Assets/vInspector/VInspectorComponentWindow.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 295e0a9b2039246c59fbe00423b2723e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
156
Assets/vInspector/VInspectorData.cs
Normal file
156
Assets/vInspector/VInspectorData.cs
Normal file
@@ -0,0 +1,156 @@
|
||||
#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 VInspector.VInspectorState;
|
||||
using static VInspector.Libs.VUtils;
|
||||
using static VInspector.Libs.VGUI;
|
||||
// using static VTools.VDebug;
|
||||
|
||||
|
||||
namespace VInspector
|
||||
{
|
||||
public class VInspectorData : ScriptableObject
|
||||
{
|
||||
|
||||
public List<Bookmark> bookmarks = new();
|
||||
|
||||
[System.Serializable]
|
||||
public class Bookmark
|
||||
{
|
||||
|
||||
public Object obj
|
||||
{
|
||||
get
|
||||
{
|
||||
if (isSceneGameObject && _obj == null)
|
||||
{
|
||||
if (!failedToLoadSceneObject) // to prevent continuous GlobalID.GetObjects() calls if object is deleted
|
||||
VInspector.unloadedSceneBookmarks_sceneGuids.Add(globalId.guid);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return _obj ??= globalId.GetObject();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public Object _obj;
|
||||
|
||||
[System.NonSerialized]
|
||||
public bool failedToLoadSceneObject;
|
||||
|
||||
|
||||
|
||||
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 Type type => Type.GetType(_typeString) ?? typeof(DefaultAsset);
|
||||
|
||||
public string name
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!obj) return "Can't load object";
|
||||
|
||||
if (assetPath.GetExtension() == ".cs")
|
||||
return obj.name.Decamelcase();
|
||||
else
|
||||
return obj.name;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Bookmark(Object o)
|
||||
{
|
||||
globalId = o.GetGlobalID();
|
||||
|
||||
isSceneGameObject = o is GameObject go && go.scene.rootCount != 0;
|
||||
isAsset = !isSceneGameObject;
|
||||
|
||||
_typeString = o.GetType().AssemblyQualifiedName;
|
||||
|
||||
_obj = o;
|
||||
|
||||
}
|
||||
|
||||
public GlobalID globalId;
|
||||
|
||||
public bool isSceneGameObject;
|
||||
public bool isAsset;
|
||||
|
||||
public string _typeString;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[CustomEditor(typeof(VInspectorData))]
|
||||
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 stores bookmarks from vInspector's navigation bar", style);
|
||||
|
||||
EndIndent(10);
|
||||
ResetGUIEnabled();
|
||||
|
||||
// Space(15);
|
||||
// base.OnInspectorGUI();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
11
Assets/vInspector/VInspectorData.cs.meta
Normal file
11
Assets/vInspector/VInspectorData.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7915df4cd4da490ab52fc8fa9ee9127
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
500
Assets/vInspector/VInspectorDrawers.cs
Normal file
500
Assets/vInspector/VInspectorDrawers.cs
Normal file
@@ -0,0 +1,500 @@
|
||||
#if UNITY_EDITOR
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
using Type = System.Type;
|
||||
using Attribute = System.Attribute;
|
||||
using static VInspector.VInspectorState;
|
||||
using static VInspector.Libs.VUtils;
|
||||
using static VInspector.Libs.VGUI;
|
||||
// using static VTools.VDebug;
|
||||
|
||||
|
||||
namespace VInspector
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(SerializedDictionary<,>), true)]
|
||||
public class SerializedDictionaryDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect rect, SerializedProperty prop, GUIContent label)
|
||||
{
|
||||
var indentedRect = EditorGUI.IndentedRect(rect);
|
||||
|
||||
void header()
|
||||
{
|
||||
var headerRect = indentedRect.SetHeight(EditorGUIUtility.singleLineHeight);
|
||||
|
||||
void foldout()
|
||||
{
|
||||
var fullHeaderRect = headerRect.MoveX(3).AddWidthFromRight(17);
|
||||
|
||||
if (fullHeaderRect.IsHovered())
|
||||
fullHeaderRect.Draw(Greyscale(1, .07f));
|
||||
|
||||
SetGUIColor(Color.clear);
|
||||
SetGUIEnabled(true);
|
||||
|
||||
if (GUI.Button(fullHeaderRect.AddWidth(-50), ""))
|
||||
prop.isExpanded = !prop.isExpanded;
|
||||
|
||||
ResetGUIColor();
|
||||
ResetGUIEnabled();
|
||||
|
||||
|
||||
|
||||
var triangleRect = rect.SetHeight(EditorGUIUtility.singleLineHeight);
|
||||
|
||||
SetGUIEnabled(true);
|
||||
|
||||
EditorGUI.Foldout(triangleRect, prop.isExpanded, "");
|
||||
|
||||
ResetGUIEnabled();
|
||||
|
||||
|
||||
}
|
||||
void label()
|
||||
{
|
||||
SetLabelBold();
|
||||
SetLabelFontSize(12);
|
||||
SetGUIColor(Greyscale(.9f));
|
||||
SetGUIEnabled(true);
|
||||
|
||||
GUI.Label(headerRect, prop.displayName);
|
||||
|
||||
ResetGUIEnabled();
|
||||
ResetGUIColor();
|
||||
ResetLabelStyle();
|
||||
|
||||
}
|
||||
void count()
|
||||
{
|
||||
if (kvpsProp_byPropPath[prop.propertyPath].hasMultipleDifferentValues) return;
|
||||
|
||||
kvpsProp_byPropPath[prop.propertyPath].arraySize = EditorGUI.DelayedIntField(headerRect.SetWidthFromRight(48 + EditorGUI.indentLevel * 15), kvpsProp_byPropPath[prop.propertyPath].arraySize);
|
||||
|
||||
}
|
||||
void repeatedKeysWarning()
|
||||
{
|
||||
if (!curEvent.isRepaint) return;
|
||||
|
||||
|
||||
var hasRepeatedKeys = false;
|
||||
var hasNullKeys = false;
|
||||
|
||||
for (int i = 0; i < kvpsProp_byPropPath[prop.propertyPath].arraySize; i++)
|
||||
{
|
||||
hasRepeatedKeys |= kvpsProp_byPropPath[prop.propertyPath].GetArrayElementAtIndex(i).FindPropertyRelative("isKeyRepeated").boolValue;
|
||||
hasNullKeys |= kvpsProp_byPropPath[prop.propertyPath].GetArrayElementAtIndex(i).FindPropertyRelative("isKeyNull").boolValue;
|
||||
}
|
||||
|
||||
if (!hasRepeatedKeys && !hasNullKeys) return;
|
||||
|
||||
|
||||
|
||||
var warningTextRect = headerRect.AddWidthFromRight(-prop.displayName.GetLabelWidth(isBold: true));
|
||||
var warningIconRect = warningTextRect.SetHeightFromMid(20).SetWidth(20);
|
||||
|
||||
var warningText = (hasRepeatedKeys && hasNullKeys) ? "Repeated and null keys"
|
||||
: hasRepeatedKeys ? "Repeated keys"
|
||||
: hasNullKeys ? "Null keys" : "";
|
||||
|
||||
|
||||
|
||||
GUI.Label(warningIconRect, EditorGUIUtility.IconContent("Warning"));
|
||||
|
||||
|
||||
SetGUIColor(new Color(1, .9f, .03f) * 1.1f);
|
||||
|
||||
GUI.Label(warningTextRect.MoveX(16), warningText);
|
||||
|
||||
ResetGUIColor();
|
||||
|
||||
}
|
||||
|
||||
foldout();
|
||||
label();
|
||||
count();
|
||||
repeatedKeysWarning();
|
||||
|
||||
}
|
||||
void list_()
|
||||
{
|
||||
if (!prop.isExpanded) return;
|
||||
|
||||
SetupList(prop);
|
||||
|
||||
lists_byPropPath[prop.propertyPath].DoList(indentedRect.AddHeightFromBottom(-EditorGUIUtility.singleLineHeight - 3));
|
||||
}
|
||||
|
||||
|
||||
SetupProps(prop);
|
||||
|
||||
header();
|
||||
list_();
|
||||
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty prop, GUIContent label)
|
||||
{
|
||||
SetupProps(prop);
|
||||
|
||||
var height = EditorGUIUtility.singleLineHeight;
|
||||
|
||||
if (prop.isExpanded)
|
||||
{
|
||||
SetupList(prop);
|
||||
height += lists_byPropPath[prop.propertyPath].GetHeight() + 3;
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
float GetListElementHeight(int index, SerializedProperty prop)
|
||||
{
|
||||
var kvpProp = kvpsProp_byPropPath[prop.propertyPath].GetArrayElementAtIndex(index);
|
||||
var keyProp = kvpProp.FindPropertyRelative("Key");
|
||||
var valueProp = kvpProp.FindPropertyRelative("Value");
|
||||
|
||||
float propHeight(SerializedProperty prop)
|
||||
{
|
||||
// var height = typeof(Editor).Assembly.GetType("UnityEditor.ScriptAttributeUtility").InvokeMethod("GetHandler", prop).InvokeMethod<float>("GetHeight", prop, GUIContent.none, true);
|
||||
var height = EditorGUI.GetPropertyHeight(prop);
|
||||
|
||||
if (!IsSingleLine(prop) && prop.type != "EventReference")
|
||||
height -= 10;
|
||||
|
||||
return height;
|
||||
|
||||
}
|
||||
|
||||
return Mathf.Max(propHeight(keyProp), propHeight(valueProp));
|
||||
|
||||
}
|
||||
|
||||
void DrawListElement(Rect rect, int index, bool isActive, bool isFocused, SerializedProperty prop)
|
||||
{
|
||||
Rect keyRect;
|
||||
Rect valueRect;
|
||||
Rect dividerRect;
|
||||
|
||||
var kvpProp = kvpsProp_byPropPath[prop.propertyPath].GetArrayElementAtIndex(index);
|
||||
var keyProp = kvpProp.FindPropertyRelative("Key");
|
||||
var valueProp = kvpProp.FindPropertyRelative("Value");
|
||||
|
||||
void drawProp(Rect rect, SerializedProperty prop)
|
||||
{
|
||||
if (IsSingleLine(prop)) { EditorGUI.PropertyField(rect.SetHeight(EditorGUIUtility.singleLineHeight), prop, GUIContent.none); return; }
|
||||
|
||||
|
||||
prop.isExpanded = true;
|
||||
|
||||
GUI.BeginGroup(rect);
|
||||
|
||||
if (prop.type == "EventReference") // don't hide first line for FMOD EventReference
|
||||
{
|
||||
EditorGUIUtility.labelWidth = 1;
|
||||
EditorGUI.PropertyField(rect.SetPos(0, 0), prop, GUIContent.none);
|
||||
EditorGUIUtility.labelWidth = 0;
|
||||
}
|
||||
else
|
||||
EditorGUI.PropertyField(rect.SetPos(0, -20), prop, true);
|
||||
|
||||
GUI.EndGroup();
|
||||
|
||||
}
|
||||
|
||||
void rects()
|
||||
{
|
||||
var dividerWidh = 6f;
|
||||
|
||||
var dividerPos = dividerPosProp.floatValue.Clamp(.2f, .8f);
|
||||
|
||||
var fullRect = rect.AddWidthFromRight(-1).AddHeightFromMid(-2);
|
||||
|
||||
keyRect = fullRect.SetWidth(fullRect.width * dividerPos - dividerWidh / 2);
|
||||
valueRect = fullRect.SetWidthFromRight(fullRect.width * (1 - dividerPos) - dividerWidh / 2);
|
||||
dividerRect = fullRect.MoveX(fullRect.width * dividerPos - dividerWidh / 2).SetWidth(dividerWidh).Resize(-1);
|
||||
|
||||
}
|
||||
void key()
|
||||
{
|
||||
drawProp(keyRect, keyProp);
|
||||
|
||||
}
|
||||
void warning()
|
||||
{
|
||||
var isKeyRepeated = kvpProp.FindPropertyRelative("isKeyRepeated").boolValue;
|
||||
var isKeyNull = kvpProp.FindPropertyRelative("isKeyNull").boolValue;
|
||||
|
||||
if (!isKeyRepeated && !isKeyNull) return;
|
||||
|
||||
|
||||
var warningRect = keyRect.SetWidthFromRight(20).SetHeight(20).MoveY(-1);
|
||||
|
||||
if (kvpProp.FindPropertyRelative("Key").propertyType == SerializedPropertyType.ObjectReference)
|
||||
warningRect = warningRect.MoveX(-17);
|
||||
|
||||
|
||||
GUI.Label(warningRect, EditorGUIUtility.IconContent("Warning"));
|
||||
|
||||
}
|
||||
void value()
|
||||
{
|
||||
drawProp(valueRect, valueProp);
|
||||
}
|
||||
void divider()
|
||||
{
|
||||
EditorGUIUtility.AddCursorRect(dividerRect, MouseCursor.ResizeHorizontal);
|
||||
|
||||
if (!rect.IsHovered()) return;
|
||||
|
||||
if (dividerRect.IsHovered())
|
||||
{
|
||||
if (curEvent.isMouseDown)
|
||||
isDividerDragged = true;
|
||||
|
||||
if (curEvent.isMouseUp || curEvent.isMouseMove || curEvent.isMouseLeaveWindow)
|
||||
isDividerDragged = false;
|
||||
}
|
||||
|
||||
if (isDividerDragged && curEvent.isMouseDrag)
|
||||
dividerPosProp.floatValue += curEvent.mouseDelta.x / rect.width;
|
||||
|
||||
}
|
||||
|
||||
rects();
|
||||
key();
|
||||
warning();
|
||||
value();
|
||||
divider();
|
||||
|
||||
}
|
||||
|
||||
void DrawDictionaryIsEmpty(Rect rect) => GUI.Label(rect, "Dictionary is empty");
|
||||
|
||||
|
||||
|
||||
IEnumerable<SerializedProperty> GetChildren(SerializedProperty prop, bool enterVisibleGrandchildren)
|
||||
{
|
||||
var startPath = prop.propertyPath;
|
||||
|
||||
var enterVisibleChildren = true;
|
||||
|
||||
while (prop.NextVisible(enterVisibleChildren) && prop.propertyPath.StartsWith(startPath))
|
||||
{
|
||||
yield return prop;
|
||||
enterVisibleChildren = enterVisibleGrandchildren;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool IsSingleLine(SerializedProperty prop) => prop.propertyType != SerializedPropertyType.Generic || !prop.hasVisibleChildren || prop.type == "AssetReference";
|
||||
|
||||
|
||||
|
||||
public void SetupList(SerializedProperty prop)
|
||||
{
|
||||
if (lists_byPropPath.ContainsKey(prop.propertyPath)) return;
|
||||
|
||||
SetupProps(prop);
|
||||
|
||||
lists_byPropPath[prop.propertyPath] = new ReorderableList(kvpsProp_byPropPath[prop.propertyPath].serializedObject, kvpsProp_byPropPath[prop.propertyPath], true, false, true, true);
|
||||
lists_byPropPath[prop.propertyPath].drawElementCallback = (q, w, e, r) => DrawListElement(q, w, e, r, prop);
|
||||
lists_byPropPath[prop.propertyPath].elementHeightCallback = (q) => GetListElementHeight(q, prop);
|
||||
lists_byPropPath[prop.propertyPath].drawNoneElementCallback = DrawDictionaryIsEmpty;
|
||||
|
||||
}
|
||||
|
||||
Dictionary<string, ReorderableList> lists_byPropPath = new();
|
||||
// ReorderableList list;
|
||||
|
||||
bool isDividerDragged;
|
||||
|
||||
|
||||
public void SetupProps(SerializedProperty prop)
|
||||
{
|
||||
if (kvpsProp_byPropPath.ContainsKey(prop.propertyPath)) return;
|
||||
|
||||
kvpsProp_byPropPath[prop.propertyPath] = prop.FindPropertyRelative("serializedKvps");
|
||||
|
||||
this.dividerPosProp = prop.FindPropertyRelative("dividerPos");
|
||||
|
||||
|
||||
}
|
||||
|
||||
Dictionary<string, SerializedProperty> kvpsProp_byPropPath = new();
|
||||
// SerializedProperty kvpsProp;
|
||||
|
||||
SerializedProperty dividerPosProp;
|
||||
|
||||
}
|
||||
|
||||
|
||||
[CustomPropertyDrawer(typeof(VariantsAttribute))]
|
||||
public class VariantsDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect rect, SerializedProperty prop, GUIContent label)
|
||||
{
|
||||
|
||||
var variantsAttribtue = (VariantsAttribute)attribute;
|
||||
|
||||
|
||||
if (variantsAttribtue.variants.Length == 1 && variantsAttribtue.variants[0] is string dynamicCollectionName)
|
||||
{
|
||||
var target = prop.serializedObject.targetObject;
|
||||
|
||||
|
||||
|
||||
|
||||
IEnumerable ienum = null;
|
||||
|
||||
if (target.GetType().GetMember(dynamicCollectionName, maxBindingFlags).FirstOrDefault() is MemberInfo collectionMember)
|
||||
if (collectionMember is MethodInfo methodInfo)
|
||||
ienum = methodInfo.Invoke(target, null) as IEnumerable;
|
||||
else
|
||||
ienum = target.GetMemberValue(dynamicCollectionName) as IEnumerable;
|
||||
|
||||
|
||||
|
||||
if (ienum != null)
|
||||
{
|
||||
var variantsList = new List<object>();
|
||||
|
||||
foreach (var r in ienum)
|
||||
variantsList.Add(r);
|
||||
|
||||
variantsAttribtue.variants = variantsList.ToArray();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
var variantsArray = variantsAttribtue.variants;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
EditorGUI.BeginProperty(rect, label, prop);
|
||||
|
||||
var iCur = prop.hasMultipleDifferentValues ? -1 : variantsArray.ToList().IndexOf(prop.GetBoxedValue());
|
||||
|
||||
var iNew = EditorGUI.IntPopup(rect, label.text, iCur, variantsArray.Select(r => r.ToString()).ToArray(), Enumerable.Range(0, variantsArray.Length).ToArray());
|
||||
|
||||
if (iNew != -1)
|
||||
prop.SetBoxedValue(variantsArray[iNew]);
|
||||
else if (!prop.hasMultipleDifferentValues)
|
||||
prop.SetBoxedValue(variantsArray[0]);
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[CustomPropertyDrawer(typeof(MinMaxSliderAttribute))]
|
||||
public class MinMaxSliderDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect rect, SerializedProperty prop, GUIContent label)
|
||||
{
|
||||
var fieldWidth = 52;
|
||||
|
||||
var controlsRect = rect.AddWidthFromRight(-EditorGUIUtility.labelWidth);
|
||||
|
||||
var minFieldRect = controlsRect.SetWidth(fieldWidth).AddWidthFromRight(-2 + EditorGUI.indentLevel * 15);
|
||||
var maxFieldRect = controlsRect.SetWidthFromRight(fieldWidth).AddWidthFromRight(-2 + EditorGUI.indentLevel * 15);
|
||||
var sliderRect = controlsRect.AddWidthFromMid(-fieldWidth * 2 - 4).AddWidthFromRight(-2 + EditorGUI.indentLevel * 15);
|
||||
|
||||
|
||||
var isInt = prop.propertyType == SerializedPropertyType.Vector2Int;
|
||||
|
||||
var min = isInt ? prop.vector2IntValue.x : prop.vector2Value.x;
|
||||
var max = isInt ? prop.vector2IntValue.y : prop.vector2Value.y;
|
||||
|
||||
var minLimit = ((MinMaxSliderAttribute)attribute).min;
|
||||
var maxLimit = ((MinMaxSliderAttribute)attribute).max;
|
||||
|
||||
|
||||
|
||||
|
||||
EditorGUI.PrefixLabel(rect, label);
|
||||
|
||||
|
||||
EditorGUI.BeginProperty(rect, label, prop);
|
||||
|
||||
if (sliderRect.width > 14)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
EditorGUI.MinMaxSlider(sliderRect, ref min, ref max, minLimit, maxLimit);
|
||||
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
var abs = (maxLimit - minLimit).Abs();
|
||||
|
||||
var decimals = abs > 190 ?
|
||||
0 : abs > 19 ?
|
||||
1 : abs > 1.9f ?
|
||||
2 :
|
||||
3;
|
||||
|
||||
min = (float)System.Math.Round(min, decimals);
|
||||
max = (float)System.Math.Round(max, decimals);
|
||||
|
||||
// same rounding logic as for [Range]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
min = EditorGUI.DelayedFloatField(minFieldRect, min).Max(minLimit).Min(maxLimit);
|
||||
max = EditorGUI.DelayedFloatField(maxFieldRect, max).Max(min).Max(minLimit).Min(maxLimit);
|
||||
|
||||
if (isInt)
|
||||
prop.vector2IntValue = new Vector2Int(min.RoundToInt(), max.RoundToInt());
|
||||
else
|
||||
prop.vector2Value = new Vector2(min, max);
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[CustomPropertyDrawer(typeof(TagAttribute))]
|
||||
public class TagDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect rect, SerializedProperty prop, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, label, prop);
|
||||
|
||||
prop.stringValue = EditorGUI.TagField(rect, label, prop.stringValue);
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[CustomPropertyDrawer(typeof(LayerAttribute))]
|
||||
public class LayerDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect rect, SerializedProperty prop, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, label, prop);
|
||||
|
||||
prop.intValue = EditorGUI.LayerField(rect, label, prop.intValue);
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
11
Assets/vInspector/VInspectorDrawers.cs.meta
Normal file
11
Assets/vInspector/VInspectorDrawers.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 481331f9e0bfe494f98ee0fc8ebfeb84
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
2105
Assets/vInspector/VInspectorEditor.cs
Normal file
2105
Assets/vInspector/VInspectorEditor.cs
Normal file
File diff suppressed because it is too large
Load Diff
11
Assets/vInspector/VInspectorEditor.cs.meta
Normal file
11
Assets/vInspector/VInspectorEditor.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4a8eec962d2dd440196b02dca0f62e3e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
2612
Assets/vInspector/VInspectorLibs.cs
Normal file
2612
Assets/vInspector/VInspectorLibs.cs
Normal file
File diff suppressed because it is too large
Load Diff
11
Assets/vInspector/VInspectorLibs.cs.meta
Normal file
11
Assets/vInspector/VInspectorLibs.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 077bd88e5e3a2421b8bd152c5b813ea2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
162
Assets/vInspector/VInspectorMenu.cs
Normal file
162
Assets/vInspector/VInspectorMenu.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
#if UNITY_EDITOR
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Compilation;
|
||||
using static VInspector.Libs.VUtils;
|
||||
using static VInspector.Libs.VGUI;
|
||||
// using static VTools.VDebug;
|
||||
|
||||
namespace VInspector
|
||||
{
|
||||
class VInspectorMenu
|
||||
{
|
||||
public static bool navigationBarEnabled { get => EditorPrefsCached.GetBool("vInspector-navigationBarEnabled", false); set => EditorPrefsCached.SetBool("vInspector-navigationBarEnabled", value); }
|
||||
public static bool copyPasteButtonsEnabled { get => EditorPrefsCached.GetBool("vInspector-copyPasteButtonsEnabled", false); set => EditorPrefsCached.SetBool("vInspector-copyPasteButtonsEnabled", value); }
|
||||
public static bool playmodeSaveButtonEnabled { get => EditorPrefsCached.GetBool("vInspector-saveInPlaymodeButtonEnabled", false); set => EditorPrefsCached.SetBool("vInspector-saveInPlaymodeButtonEnabled", value); }
|
||||
public static bool componentWindowsEnabled { get => EditorPrefsCached.GetBool("vInspector-componentWindowsEnabled", false); set => EditorPrefsCached.SetBool("vInspector-componentWindowsEnabled", value); }
|
||||
public static bool componentAnimationsEnabled { get => EditorPrefsCached.GetBool("vInspector-componentAnimationsEnabled", false); set => EditorPrefsCached.SetBool("vInspector-componentAnimationsEnabled", value); }
|
||||
public static bool minimalModeEnabled { get => EditorPrefsCached.GetBool("vInspector-minimalModeEnabled", false); set => EditorPrefsCached.SetBool("vInspector-minimalModeEnabled", value); }
|
||||
public static bool resettableVariablesEnabled { get => EditorPrefsCached.GetBool("vInspector-resettableVariablesEnabled", false); set => EditorPrefsCached.SetBool("vInspector-resettableVariablesEnabled", value); }
|
||||
public static bool hideScriptFieldEnabled { get => EditorPrefsCached.GetBool("vInspector-hideScriptFieldEnabled", false); set => EditorPrefsCached.SetBool("vInspector-hideScriptFieldEnabled", value); }
|
||||
public static bool hideHelpButtonEnabled { get => EditorPrefsCached.GetBool("vInspector-hideHelpButtonEnabled", false); set => EditorPrefsCached.SetBool("vInspector-hideHelpButtonEnabled", value); }
|
||||
public static bool hidePresetsButtonEnabled { get => EditorPrefsCached.GetBool("vInspector-hidePresetsButtonEnabled", false); set => EditorPrefsCached.SetBool("vInspector-hidePresetsButtonEnabled", value); }
|
||||
|
||||
public static bool toggleActiveEnabled { get => EditorPrefsCached.GetBool("vInspector-toggleActiveEnabled", true); set => EditorPrefsCached.SetBool("vInspector-toggleActiveEnabled", value); }
|
||||
public static bool deleteEnabled { get => EditorPrefsCached.GetBool("vInspector-deleteEnabled", true); set => EditorPrefsCached.SetBool("vInspector-deleteEnabled", value); }
|
||||
public static bool toggleExpandedEnabled { get => EditorPrefsCached.GetBool("vInspector-toggleExpandedEnabled", true); set => EditorPrefsCached.SetBool("vInspector-toggleExpandedEnabled", value); }
|
||||
public static bool collapseEverythingElseEnabled { get => EditorPrefsCached.GetBool("vInspector-collapseEverythingElseEnabled", true); set => EditorPrefsCached.SetBool("vInspector-collapseEverythingElseEnabled", value); }
|
||||
public static bool collapseEverythingEnabled { get => EditorPrefsCached.GetBool("vInspector-collapseEverythingEnabled", true); set => EditorPrefsCached.SetBool("vInspector-collapseEverythingEnabled", value); }
|
||||
|
||||
public static bool attributesDisabled { get => EditorUtils.IsSymbolDefinedInAsmdef(nameof(VInspector), "VINSPECTOR_ATTRIBUTES_DISABLED"); set => EditorUtils.SetSymbolDefinedInAsmdef(nameof(VInspector), "VINSPECTOR_ATTRIBUTES_DISABLED", value); }
|
||||
public static bool pluginDisabled { get => ProjectPrefs.GetBool("vInspector-pluginDisabled", false); set => ProjectPrefs.SetBool("vInspector-pluginDisabled", value); }
|
||||
|
||||
|
||||
|
||||
|
||||
public static void RepaintInspectors()
|
||||
{
|
||||
Resources.FindObjectsOfTypeAll(typeof(Editor).Assembly.GetType("UnityEditor.InspectorWindow"))
|
||||
.Cast<EditorWindow>()
|
||||
.ForEach(r => r.Repaint());
|
||||
|
||||
Resources.FindObjectsOfTypeAll(typeof(Editor).Assembly.GetType("UnityEditor.PropertyEditor"))
|
||||
.Where(r => r.GetType().BaseType == typeof(EditorWindow))
|
||||
.Cast<EditorWindow>()
|
||||
.ForEach(r => r.Repaint());
|
||||
}
|
||||
|
||||
|
||||
|
||||
const string dir = "Tools/vInspector/";
|
||||
#if UNITY_EDITOR_OSX
|
||||
const string cmd = "Cmd";
|
||||
#else
|
||||
const string cmd = "Ctrl";
|
||||
#endif
|
||||
|
||||
const string navigationBar = dir + "Navigation bar";
|
||||
const string copyPasteButtons = dir + "Copy \u2215 Paste components";
|
||||
const string saveInPlaymodeButton = dir + "Save in play mode";
|
||||
const string componentWindows = dir + "Create component windows with Alt-Drag";
|
||||
const string componentAnimations = dir + "Component expand \u2215 collapse animations";
|
||||
const string minimalMode = dir + "Minimal mode";
|
||||
const string resettableVariables = dir + "Resettable variables";
|
||||
const string hideScriptField = dir + "Hide script field";
|
||||
const string hideHelpButton = dir + "Hide help button";
|
||||
const string hidePresetsButton = dir + "Hide presets button";
|
||||
|
||||
const string toggleActive = dir + "A to toggle component active";
|
||||
const string delete = dir + "X to delete component";
|
||||
const string toggleExpanded = dir + "E to expand \u2215 collapse component";
|
||||
const string collapseEverythingElse = dir + "Shift-E to isolate component";
|
||||
const string collapseEverything = dir + "Ctrl-Shift-E to expand \u2215 collapse all components";
|
||||
|
||||
const string disableAttributes = dir + "Disable attributes";
|
||||
const string disablePlugin = dir + "Disable vInspector";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[MenuItem(dir + "Features", false, 1)] static void dadsas() { }
|
||||
[MenuItem(dir + "Features", true, 1)] static bool dadsas123() => false;
|
||||
|
||||
[MenuItem(navigationBar, false, 2)] static void dadsadsadasdsadadsas() { navigationBarEnabled = !navigationBarEnabled; RepaintInspectors(); }
|
||||
[MenuItem(navigationBar, true, 2)] static bool dadsaddsasadadsdasadsas() { Menu.SetChecked(navigationBar, navigationBarEnabled); return !pluginDisabled; }
|
||||
|
||||
[MenuItem(copyPasteButtons, false, 3)] static void dadsaasddsadaasdsdsadadsas() { copyPasteButtonsEnabled = !copyPasteButtonsEnabled; VInspector.UpdateHeaderButtons(null); RepaintInspectors(); }
|
||||
[MenuItem(copyPasteButtons, true, 3)] static bool dadsaddasdsasaasddadsdasadsas() { Menu.SetChecked(copyPasteButtons, copyPasteButtonsEnabled); return !pluginDisabled; }
|
||||
|
||||
[MenuItem(saveInPlaymodeButton, false, 4)] static void dadsadsadaasasdsdsadadsas() { playmodeSaveButtonEnabled = !playmodeSaveButtonEnabled; VInspector.UpdateHeaderButtons(null); RepaintInspectors(); }
|
||||
[MenuItem(saveInPlaymodeButton, true, 4)] static bool dadsaddsasaadsasddadsdasadsas() { Menu.SetChecked(saveInPlaymodeButton, playmodeSaveButtonEnabled); return !pluginDisabled; }
|
||||
|
||||
[MenuItem(componentWindows, false, 5)] static void dadsadsadaasdsdsadadsas() { componentWindowsEnabled = !componentWindowsEnabled; RepaintInspectors(); }
|
||||
[MenuItem(componentWindows, true, 5)] static bool dadsaddsasaasddadsdasadsas() { Menu.SetChecked(componentWindows, componentWindowsEnabled); return !pluginDisabled; }
|
||||
|
||||
[MenuItem(componentAnimations, false, 6)] static void dadsadsadsadaasdsdsadadsas() { componentAnimationsEnabled = !componentAnimationsEnabled; RepaintInspectors(); }
|
||||
[MenuItem(componentAnimations, true, 6)] static bool dadsadddsasasaasddadsdasadsas() { Menu.SetChecked(componentAnimations, componentAnimationsEnabled); return !pluginDisabled; }
|
||||
|
||||
[MenuItem(minimalMode, false, 7)] static void dadsadsadsadsadasdsadadsas() { minimalModeEnabled = !minimalModeEnabled; RepaintInspectors(); }
|
||||
[MenuItem(minimalMode, true, 7)] static bool dadsadasdasddsasadadsdasadsas() { Menu.SetChecked(minimalMode, minimalModeEnabled); return !pluginDisabled; }
|
||||
|
||||
[MenuItem(resettableVariables, false, 8)] static void dadsadsadsadasdsadadsas() { resettableVariablesEnabled = !resettableVariablesEnabled; RepaintInspectors(); }
|
||||
[MenuItem(resettableVariables, true, 8)] static bool dadsadasddsasadadsdasadsas() { Menu.SetChecked(resettableVariables, resettableVariablesEnabled); return !pluginDisabled; }
|
||||
|
||||
[MenuItem(hideScriptField, false, 9)] static void dadsadsdsaadsadsadasdsadadsas() { hideScriptFieldEnabled = !hideScriptFieldEnabled; RepaintInspectors(); }
|
||||
[MenuItem(hideScriptField, true, 9)] static bool dadsadasadsdasddsasadadsdasadsas() { Menu.SetChecked(hideScriptField, hideScriptFieldEnabled); return !pluginDisabled; }
|
||||
|
||||
[MenuItem(hideHelpButton, false, 10)] static void dadsadsadsdsaadsadsadasdsadadsas() { hideHelpButtonEnabled = !hideHelpButtonEnabled; VInspector.UpdateHeaderButtons(null); RepaintInspectors(); }
|
||||
[MenuItem(hideHelpButton, true, 10)] static bool dadsaadsdasadsdasddsasadadsdasadsas() { Menu.SetChecked(hideHelpButton, hideHelpButtonEnabled); return !pluginDisabled; }
|
||||
|
||||
[MenuItem(hidePresetsButton, false, 11)] static void dadsadsdsaadssdadsadasdsadadsas() { hidePresetsButtonEnabled = !hidePresetsButtonEnabled; VInspector.UpdateHeaderButtons(null); RepaintInspectors(); }
|
||||
[MenuItem(hidePresetsButton, true, 11)] static bool dadsadasadsddsasddsasadadsdasadsas() { Menu.SetChecked(hidePresetsButton, hidePresetsButtonEnabled); return !pluginDisabled; }
|
||||
|
||||
|
||||
|
||||
|
||||
[MenuItem(dir + "Shortcuts", false, 1001)] static void dadsadsas() { }
|
||||
[MenuItem(dir + "Shortcuts", true, 1001)] static bool dadsadsas123() => false;
|
||||
|
||||
[MenuItem(toggleActive, false, 1002)] static void dadsadadsas() => toggleActiveEnabled = !toggleActiveEnabled;
|
||||
[MenuItem(toggleActive, true, 1002)] static bool dadsaddasadsas() { Menu.SetChecked(toggleActive, toggleActiveEnabled); return !pluginDisabled; }
|
||||
|
||||
[MenuItem(delete, false, 1003)] static void dadsadsadasdadsas() => deleteEnabled = !deleteEnabled;
|
||||
[MenuItem(delete, true, 1003)] static bool dadsaddsasaddasadsas() { Menu.SetChecked(delete, deleteEnabled); return !pluginDisabled; }
|
||||
|
||||
[MenuItem(toggleExpanded, false, 1004)] static void dadsaddsasadasdsadadsas() => toggleExpandedEnabled = !toggleExpandedEnabled;
|
||||
[MenuItem(toggleExpanded, true, 1004)] static bool dadsaddsdsasadadsdasadsas() { Menu.SetChecked(toggleExpanded, toggleExpandedEnabled); return !pluginDisabled; }
|
||||
|
||||
[MenuItem(collapseEverythingElse, false, 1005)] static void dadsadsasdadasdsadadsas() => collapseEverythingElseEnabled = !collapseEverythingElseEnabled;
|
||||
[MenuItem(collapseEverythingElse, true, 1005)] static bool dadsaddsdasasadadsdasadsas() { Menu.SetChecked(collapseEverythingElse, collapseEverythingElseEnabled); return !pluginDisabled; }
|
||||
|
||||
[MenuItem(collapseEverything, false, 1006)] static void dadsadsdasadasdsadadsas() => collapseEverythingEnabled = !collapseEverythingEnabled;
|
||||
[MenuItem(collapseEverything, true, 1006)] static bool dadsaddssdaasadadsdasadsas() { Menu.SetChecked(collapseEverything, collapseEverythingEnabled); return !pluginDisabled; }
|
||||
|
||||
|
||||
|
||||
|
||||
[MenuItem(dir + "More", false, 10001)] static void daasadsddsas() { }
|
||||
[MenuItem(dir + "More", true, 10001)] static bool dadsadsdasas123() => false;
|
||||
|
||||
[MenuItem(dir + "Open manual", false, 10002)]
|
||||
static void dadadssadsas() => Application.OpenURL("https://kubacho-lab.gitbook.io/vinspector2");
|
||||
|
||||
[MenuItem(dir + "Join our Discord", false, 10003)]
|
||||
static void dadasdsas() => Application.OpenURL("https://discord.gg/pUektnZeJT");
|
||||
|
||||
|
||||
|
||||
|
||||
[MenuItem(disablePlugin, false, 100001)] static void dadsadsdsdasadasdasdsadadsas() { pluginDisabled = !pluginDisabled; attributesDisabled = pluginDisabled; }
|
||||
[MenuItem(disablePlugin, true, 100001)] static bool dadsaddssdsdaasadsadadsdasadsas() { Menu.SetChecked(disablePlugin, pluginDisabled); return true; }
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
11
Assets/vInspector/VInspectorMenu.cs.meta
Normal file
11
Assets/vInspector/VInspectorMenu.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07852b6b534474f7fb57529201e123e0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
990
Assets/vInspector/VInspectorNavbar.cs
Normal file
990
Assets/vInspector/VInspectorNavbar.cs
Normal file
@@ -0,0 +1,990 @@
|
||||
#if UNITY_EDITOR
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
using Type = System.Type;
|
||||
using static VInspector.Libs.VUtils;
|
||||
using static VInspector.Libs.VGUI;
|
||||
// using static VTools.VDebug;
|
||||
using static VInspector.VInspector;
|
||||
using static VInspector.VInspectorData;
|
||||
|
||||
|
||||
|
||||
namespace VInspector
|
||||
{
|
||||
public class VInspectorNavbar
|
||||
{
|
||||
|
||||
public void OnGUI(Rect navbarRect)
|
||||
{
|
||||
void shadow()
|
||||
{
|
||||
if (!curEvent.isRepaint) return;
|
||||
|
||||
var shadowLength = 30;
|
||||
var shadowPos = 21;
|
||||
var shadowGreyscale = isDarkTheme ? .08f : .28f;
|
||||
var shadowAlpha = isDarkTheme ? .35f : .25f;
|
||||
|
||||
var minScrollPos = 10;
|
||||
var maxScrollPos = 20;
|
||||
|
||||
|
||||
var scrollPos = window.GetMemberValue<UnityEngine.UIElements.ScrollView>("m_ScrollView").scrollOffset.y;
|
||||
|
||||
var opacity = ((scrollPos - minScrollPos) / (maxScrollPos - minScrollPos)).Clamp01();
|
||||
|
||||
|
||||
navbarRect.MoveY(shadowPos).SetHeight(shadowLength).DrawCurtainDown(Greyscale(shadowGreyscale, shadowAlpha * opacity));
|
||||
|
||||
}
|
||||
void background()
|
||||
{
|
||||
if (!curEvent.isRepaint) return;
|
||||
|
||||
var backgroundColor = Greyscale(isDarkTheme ? .235f : .8f);
|
||||
var lineColor = Greyscale(isDarkTheme ? .1f : .53f);
|
||||
|
||||
navbarRect.Draw(backgroundColor);
|
||||
|
||||
navbarRect.SetHeightFromBottom(1).MoveY(1).Draw(lineColor);
|
||||
|
||||
}
|
||||
void hiddenMenu()
|
||||
{
|
||||
if (!curEvent.holdingAlt) return;
|
||||
if (!curEvent.isMouseUp) return;
|
||||
if (curEvent.mouseButton != 1) return;
|
||||
if (!navbarRect.IsHovered()) return;
|
||||
|
||||
|
||||
var menu = new GenericMenu();
|
||||
|
||||
menu.AddDisabledItem(new GUIContent("vInspector hidden menu"));
|
||||
|
||||
menu.AddSeparator("");
|
||||
menu.AddItem(new GUIContent("Select data"), false, () => Selection.activeObject = data);
|
||||
menu.AddItem(new GUIContent("Disable attributes"), VInspectorMenu.attributesDisabled, () => VInspectorMenu.attributesDisabled = !VInspectorMenu.attributesDisabled);
|
||||
|
||||
menu.ShowAsContext();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void name()
|
||||
{
|
||||
if (!curEvent.isRepaint) return;
|
||||
|
||||
var nameRect = navbarRect.MoveX(30 * 2 + 1);
|
||||
|
||||
var minScrollPos = 10;
|
||||
var maxScrollPos = 20;
|
||||
|
||||
|
||||
var scrollPos = window.GetMemberValue<UnityEngine.UIElements.ScrollView>("m_ScrollView").scrollOffset.y;
|
||||
|
||||
var opacity = (scrollPos - minScrollPos) / (maxScrollPos - minScrollPos);
|
||||
|
||||
|
||||
|
||||
SetGUIColor(Greyscale(.95f, opacity));
|
||||
SetLabelBold();
|
||||
|
||||
GUI.Label(nameRect, Selection.activeObject?.name ?? "No selection");
|
||||
|
||||
ResetLabelStyle();
|
||||
ResetGUIColor();
|
||||
|
||||
|
||||
}
|
||||
void nameCurtain()
|
||||
{
|
||||
if (!curEvent.isRepaint) return;
|
||||
if (!data) return;
|
||||
if (lastBookmarkX == default) return;
|
||||
|
||||
var backgroundColor = Greyscale(isDarkTheme ? .235f : .8f);
|
||||
|
||||
var curtainRect = navbarRect.AddHeightFromMid(-4).SetXMax(lastBookmarkX).SetWidthFromRight(20);
|
||||
var maskRect = navbarRect.AddHeightFromMid(-4).SetX(lastBookmarkX).SetWidth(123);
|
||||
|
||||
curtainRect.DrawCurtainLeft(backgroundColor);
|
||||
maskRect.Draw(backgroundColor);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void moveBackButton()
|
||||
{
|
||||
var buttonRect = navbarRect.SetWidth(30).MoveX(4);
|
||||
|
||||
if (Application.unityVersion.StartsWith("6000"))
|
||||
buttonRect = buttonRect.MoveY(-.49f);
|
||||
|
||||
|
||||
var iconName = "Chevron Left";
|
||||
var iconSize = 14;
|
||||
var colorNormal = Greyscale(isDarkTheme ? .75f : .2f);
|
||||
var colorHovered = Greyscale(isDarkTheme ? 1f : .2f);
|
||||
var colorPressed = Greyscale(isDarkTheme ? .75f : .5f);
|
||||
var colorDisabled = Greyscale(isDarkTheme ? .53f : .55f);
|
||||
|
||||
|
||||
var disabled = !VInspectorSelectionHistory.instance.prevStates.Any();
|
||||
|
||||
if (disabled) { IconButton(buttonRect, iconName, iconSize, colorDisabled, colorDisabled, colorDisabled); return; }
|
||||
|
||||
|
||||
if (!IconButton(buttonRect, iconName, iconSize, colorNormal, colorHovered, colorPressed)) return;
|
||||
|
||||
VInspectorSelectionHistory.instance.MoveBack();
|
||||
|
||||
}
|
||||
void moveForwardButton()
|
||||
{
|
||||
var buttonRect = navbarRect.SetWidth(30).MoveX(30).MoveX(1).AddWidthFromMid(-6);
|
||||
|
||||
if (Application.unityVersion.StartsWith("6000"))
|
||||
buttonRect = buttonRect.MoveY(-.49f);
|
||||
|
||||
|
||||
var iconName = "Chevron Right";
|
||||
var iconSize = 14;
|
||||
var colorNormal = Greyscale(isDarkTheme ? .75f : .2f);
|
||||
var colorHovered = Greyscale(isDarkTheme ? 1f : .2f);
|
||||
var colorPressed = Greyscale(isDarkTheme ? .75f : .5f);
|
||||
var colorDisabled = Greyscale(isDarkTheme ? .53f : .55f);
|
||||
|
||||
|
||||
var disabled = !VInspectorSelectionHistory.instance.nextStates.Any();
|
||||
|
||||
if (disabled) { IconButton(buttonRect, iconName, iconSize, colorDisabled, colorDisabled, colorDisabled); return; }
|
||||
|
||||
|
||||
if (!IconButton(buttonRect, iconName, iconSize, colorNormal, colorHovered, colorPressed)) return;
|
||||
|
||||
VInspectorSelectionHistory.instance.MoveForward();
|
||||
|
||||
}
|
||||
|
||||
void bookmarks()
|
||||
{
|
||||
void createData()
|
||||
{
|
||||
if (data) return;
|
||||
if (!navbarRect.IsHovered()) return;
|
||||
if (!DragAndDrop.objectReferences.Any()) return;
|
||||
|
||||
data = ScriptableObject.CreateInstance<VInspectorData>();
|
||||
|
||||
AssetDatabase.CreateAsset(data, GetScriptPath("VInspector").GetParentPath().CombinePath("vInspector Data.asset"));
|
||||
|
||||
}
|
||||
void repaintOnUndoRedo()
|
||||
{
|
||||
if (!data) return;
|
||||
if (curEvent.commandName != "UndoRedoPerformed") return;
|
||||
if (!repaintNeededAfterUndoRedo) return;
|
||||
|
||||
window.Repaint();
|
||||
|
||||
repaintNeededAfterUndoRedo = false;
|
||||
|
||||
}
|
||||
void gui()
|
||||
{
|
||||
if (!data) return;
|
||||
|
||||
this.navbarRect = navbarRect;
|
||||
this.bookmarksRect = navbarRect.AddWidth(-5).AddWidthFromRight(-60);
|
||||
|
||||
BookmarksGUI();
|
||||
|
||||
}
|
||||
|
||||
createData();
|
||||
repaintOnUndoRedo();
|
||||
gui();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
shadow();
|
||||
background();
|
||||
hiddenMenu();
|
||||
|
||||
name();
|
||||
nameCurtain();
|
||||
|
||||
moveBackButton();
|
||||
moveForwardButton();
|
||||
|
||||
bookmarks();
|
||||
|
||||
|
||||
if (draggingBookmark || animatingDroppedBookmark || animatingGaps || animatingTooltip)
|
||||
window.Repaint();
|
||||
|
||||
}
|
||||
|
||||
Rect navbarRect;
|
||||
Rect bookmarksRect;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void BookmarksGUI()
|
||||
{
|
||||
void bookmark(Vector2 centerPosition, Bookmark bookmark)
|
||||
{
|
||||
if (bookmark == null) return;
|
||||
if (curEvent.isLayout) return;
|
||||
|
||||
|
||||
var bookmarkRect = Rect.zero.SetSize(bookmarkWidth, bookmarksRect.height).SetMidPos(centerPosition);
|
||||
|
||||
|
||||
void shadow()
|
||||
{
|
||||
if (!draggingBookmark) return;
|
||||
if (draggedBookmark != bookmark) return;
|
||||
|
||||
bookmarkRect.SetSizeFromMid(bookmarkWidth - 4, bookmarkWidth - 4).DrawBlurred(Greyscale(0, .3f), 15);
|
||||
|
||||
}
|
||||
void background()
|
||||
{
|
||||
if (!bookmarkRect.IsHovered()) return;
|
||||
if (draggingBookmark && draggedBookmark != bookmark) return;
|
||||
|
||||
var backgroundColor = Greyscale(isDarkTheme ? .35f : .7f);
|
||||
|
||||
var backgroundRect = bookmarkRect.SetSizeFromMid(bookmarkRect.width - 2, bookmarkWidth - 2);
|
||||
|
||||
backgroundRect.DrawRounded(backgroundColor, 4);
|
||||
|
||||
|
||||
}
|
||||
void icon()
|
||||
{
|
||||
var opacity = 1f;
|
||||
var iconTexture = default(Texture);
|
||||
|
||||
void set_opacity()
|
||||
{
|
||||
var opacityNormal = .9f;
|
||||
var opacityHovered = 1f;
|
||||
var opacityPressed = .75f;
|
||||
var opacityDragged = .75f;
|
||||
var opacityDisabled = .4f;
|
||||
|
||||
var isDisabled = !bookmark.isLoadable;
|
||||
|
||||
|
||||
opacity = opacityNormal;
|
||||
|
||||
if (draggingBookmark)
|
||||
opacity = bookmark == draggedBookmark ? opacityDragged : opacityNormal;
|
||||
|
||||
else if (bookmark == pressedBookmark)
|
||||
opacity = opacityPressed;
|
||||
|
||||
else if (bookmarkRect.IsHovered())
|
||||
opacity = opacityHovered;
|
||||
|
||||
if (isDisabled)
|
||||
opacity = opacityDisabled;
|
||||
|
||||
}
|
||||
void getTexture()
|
||||
{
|
||||
if (bookmark.obj is Material)
|
||||
iconTexture = AssetPreview.GetAssetPreview(bookmark.obj) ?? AssetPreview.GetMiniThumbnail(bookmark.obj);
|
||||
|
||||
else if (bookmark.isAsset)
|
||||
iconTexture = AssetPreview.GetMiniThumbnail(bookmark.obj);
|
||||
|
||||
else if (bookmark.isSceneGameObject)
|
||||
if (mi_VHierarchy_GetIconName?.Invoke(null, new object[] { bookmark.obj }) is string iconNameFromVHierarchy && !iconNameFromVHierarchy.IsNullOrEmpty())
|
||||
iconTexture = EditorIcons.GetIcon(iconNameFromVHierarchy);
|
||||
else
|
||||
iconTexture = AssetPreview.GetMiniThumbnail(bookmark.obj);
|
||||
|
||||
}
|
||||
void drawTexture()
|
||||
{
|
||||
if (!iconTexture) return;
|
||||
|
||||
|
||||
SetGUIColor(Greyscale(1, opacity));
|
||||
|
||||
GUI.DrawTexture(bookmarkRect.SetSizeFromMid(iconSize), iconTexture);
|
||||
|
||||
ResetGUIColor();
|
||||
|
||||
}
|
||||
|
||||
set_opacity();
|
||||
getTexture();
|
||||
drawTexture();
|
||||
|
||||
}
|
||||
void selectedIndicator()
|
||||
{
|
||||
if (Selection.activeObject != bookmark.obj) return;
|
||||
if (Selection.activeObject == null) return;
|
||||
if (draggingBookmark && draggedBookmark == bookmark && centerPosition.y != bookmarksRect.center.y) return;
|
||||
|
||||
var indicatorColor = Greyscale(isDarkTheme ? .75f : 1f);
|
||||
|
||||
var rect = bookmarkRect.SetHeightFromBottom(3).MoveY(2).SetWidthFromMid(3);
|
||||
|
||||
rect.DrawRounded(indicatorColor, 1);
|
||||
|
||||
}
|
||||
void tooltip()
|
||||
{
|
||||
if (bookmark != (draggingBookmark ? (draggedBookmark) : (lastHoveredBookmark))) return;
|
||||
if (tooltipOpacity == 0) return;
|
||||
|
||||
var fontSize = 11;
|
||||
var tooltipText = bookmark.name;
|
||||
|
||||
Rect tooltipRect;
|
||||
|
||||
void set_tooltipRect()
|
||||
{
|
||||
var width = tooltipText.GetLabelWidth(fontSize) + 6;
|
||||
var height = 16 + (fontSize - 12) * 2;
|
||||
|
||||
var yOffset = 28;
|
||||
var rightMargin = -1;
|
||||
|
||||
|
||||
tooltipRect = Rect.zero.SetMidPos(centerPosition.x, centerPosition.y + yOffset).SetSizeFromMid(width, height);
|
||||
|
||||
|
||||
var maxXMax = bookmarksRect.xMax - rightMargin;
|
||||
|
||||
if (tooltipRect.xMax > maxXMax)
|
||||
tooltipRect = tooltipRect.MoveX(maxXMax - tooltipRect.xMax);
|
||||
|
||||
}
|
||||
void shadow()
|
||||
{
|
||||
var shadowAmount = .33f;
|
||||
var shadowRadius = 10;
|
||||
|
||||
tooltipRect.DrawBlurred(Greyscale(0, shadowAmount).MultiplyAlpha(tooltipOpacity), shadowRadius);
|
||||
|
||||
}
|
||||
void background()
|
||||
{
|
||||
var cornerRadius = 5;
|
||||
|
||||
var backgroundColor = Greyscale(isDarkTheme ? .13f : .9f);
|
||||
var outerEdgeColor = Greyscale(isDarkTheme ? .25f : .6f);
|
||||
var innerEdgeColor = Greyscale(isDarkTheme ? .0f : .95f);
|
||||
|
||||
tooltipRect.Resize(-1).DrawRounded(outerEdgeColor.SetAlpha(tooltipOpacity.Pow(2)), cornerRadius + 1);
|
||||
tooltipRect.Resize(0).DrawRounded(innerEdgeColor.SetAlpha(tooltipOpacity.Pow(2)), cornerRadius + 0);
|
||||
tooltipRect.Resize(1).DrawRounded(backgroundColor.SetAlpha(tooltipOpacity), cornerRadius - 1);
|
||||
|
||||
}
|
||||
void text()
|
||||
{
|
||||
var textRect = tooltipRect.MoveY(-.5f);
|
||||
|
||||
var textColor = Greyscale(1f);
|
||||
|
||||
SetLabelAlignmentCenter();
|
||||
SetLabelFontSize(fontSize);
|
||||
SetGUIColor(textColor.SetAlpha(tooltipOpacity));
|
||||
|
||||
GUI.Label(textRect, tooltipText);
|
||||
|
||||
ResetLabelStyle();
|
||||
ResetGUIColor();
|
||||
|
||||
}
|
||||
|
||||
set_tooltipRect();
|
||||
shadow();
|
||||
background();
|
||||
text();
|
||||
|
||||
}
|
||||
void click()
|
||||
{
|
||||
if (!bookmarkRect.IsHovered()) return;
|
||||
if (!curEvent.isMouseUp) return;
|
||||
if (doubleclickUnhandled) return;
|
||||
|
||||
curEvent.Use();
|
||||
|
||||
|
||||
if (draggingBookmark) return;
|
||||
if ((curEvent.mousePosition - mouseDownPosiion).magnitude > 2) return;
|
||||
if (!bookmark.isLoadable) return;
|
||||
|
||||
bookmark.obj.SelectInInspector(frameInHierarchy: false, frameInProject: false);
|
||||
|
||||
lastClickedBookmark = bookmark;
|
||||
|
||||
hideTooltip = true;
|
||||
|
||||
}
|
||||
void doubleclick()
|
||||
{
|
||||
if (!bookmarkRect.IsHovered()) return;
|
||||
if (!curEvent.isMouseUp) return;
|
||||
if (!doubleclickUnhandled) return;
|
||||
|
||||
void frameSceneGO()
|
||||
{
|
||||
if (!bookmark.isLoadable) return;
|
||||
if (!bookmark.isSceneGameObject) return;
|
||||
if (bookmark.obj is not GameObject go) return;
|
||||
|
||||
|
||||
var sv = SceneView.lastActiveSceneView;
|
||||
|
||||
if (!sv || !sv.hasFocus)
|
||||
sv = SceneView.sceneViews.ToArray().FirstOrDefault(r => (r as SceneView).hasFocus) as SceneView;
|
||||
|
||||
if (!sv)
|
||||
(sv = SceneView.lastActiveSceneView ?? SceneView.sceneViews[0] as SceneView).Focus();
|
||||
|
||||
sv.Frame(go.GetBounds(), false);
|
||||
|
||||
}
|
||||
void loadSceneAndSelect()
|
||||
{
|
||||
if (!bookmark.isSceneGameObject) return;
|
||||
if (bookmark.isLoadable) return;
|
||||
if (bookmark.isDeleted) return;
|
||||
if (Application.isPlaying) return;
|
||||
|
||||
EditorSceneManager.SaveOpenScenes();
|
||||
EditorSceneManager.OpenScene(bookmark.assetPath);
|
||||
|
||||
Selection.activeObject = bookmark.obj;
|
||||
|
||||
}
|
||||
void openPrefab()
|
||||
{
|
||||
if (!bookmark.isLoadable) return;
|
||||
if (bookmark.obj is not GameObject gameObject) return;
|
||||
if (!AssetDatabase.Contains(gameObject)) return;
|
||||
|
||||
AssetDatabase.OpenAsset(gameObject);
|
||||
|
||||
}
|
||||
|
||||
|
||||
EditorGUIUtility.PingObject(bookmark.obj);
|
||||
|
||||
frameSceneGO();
|
||||
loadSceneAndSelect();
|
||||
openPrefab();
|
||||
|
||||
doubleclickUnhandled = false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bookmarkRect.MarkInteractive();
|
||||
|
||||
shadow();
|
||||
background();
|
||||
icon();
|
||||
selectedIndicator();
|
||||
tooltip();
|
||||
click();
|
||||
doubleclick();
|
||||
|
||||
}
|
||||
|
||||
void normalBookmark(int i, float centerX)
|
||||
{
|
||||
if (data.bookmarks[i] == droppedBookmark && animatingDroppedBookmark) return;
|
||||
|
||||
var centerY = bookmarksRect.height / 2;
|
||||
|
||||
|
||||
var minX = centerX - bookmarkWidth / 2;
|
||||
|
||||
if (minX < bookmarksRect.x) return;
|
||||
|
||||
lastBookmarkX = minX;
|
||||
|
||||
|
||||
bookmark(new Vector2(centerX, centerY), data.bookmarks[i]);
|
||||
|
||||
}
|
||||
void normalBookmarks()
|
||||
{
|
||||
var curCenterX = bookmarksRect.xMax - bookmarkWidth / 2;
|
||||
|
||||
for (int i = 0; i < data.bookmarks.Count; i++)
|
||||
{
|
||||
curCenterX -= gaps[i];
|
||||
|
||||
if (!data.bookmarks[i].obj) continue;
|
||||
|
||||
|
||||
normalBookmark(i, curCenterX);
|
||||
|
||||
|
||||
curCenterX -= bookmarkWidth;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
void draggedBookmark_()
|
||||
{
|
||||
if (!draggingBookmark) return;
|
||||
|
||||
var centerX = curEvent.mousePosition.x + draggedBookmarkHoldOffset.x;
|
||||
var centerY = bookmarksRect.IsHovered() ? bookmarksRect.height / 2 : curEvent.mousePosition.y;
|
||||
|
||||
bookmark(new Vector2(centerX, centerY), draggedBookmark);
|
||||
|
||||
}
|
||||
void droppedBookmark_()
|
||||
{
|
||||
if (!animatingDroppedBookmark) return;
|
||||
|
||||
var centerX = droppedBookmarkX;
|
||||
var centerY = bookmarksRect.height / 2;
|
||||
|
||||
bookmark(new Vector2(centerX, centerY), droppedBookmark);
|
||||
|
||||
}
|
||||
|
||||
|
||||
BookmarksMouseState();
|
||||
BookmarksDragging();
|
||||
BookmarksAnimations();
|
||||
|
||||
normalBookmarks();
|
||||
draggedBookmark_();
|
||||
droppedBookmark_();
|
||||
|
||||
}
|
||||
|
||||
float bookmarkWidth => 24;
|
||||
float iconSize => 16;
|
||||
|
||||
float lastBookmarkX;
|
||||
|
||||
static bool repaintNeededAfterUndoRedo;
|
||||
|
||||
|
||||
|
||||
int GetBookmarkIndex(float mouseX)
|
||||
{
|
||||
var curBookmarkWidthSum = 0f;
|
||||
|
||||
for (int i = 0; i < data.bookmarks.Count; i++)
|
||||
{
|
||||
if (!data.bookmarks[i].obj) continue;
|
||||
|
||||
curBookmarkWidthSum += bookmarkWidth;
|
||||
|
||||
if (bookmarksRect.xMax - curBookmarkWidthSum < mouseX + .5f)
|
||||
return i;
|
||||
}
|
||||
|
||||
return data.bookmarks.IndexOfLast(r => r.obj) + 1;
|
||||
|
||||
}
|
||||
|
||||
float GetBookmarkCenterX(int i, bool includeGaps = true)
|
||||
{
|
||||
return bookmarksRect.xMax
|
||||
- bookmarkWidth / 2
|
||||
- data.bookmarks.Take(i).Sum(r => r.obj ? bookmarkWidth : 0)
|
||||
- (includeGaps ? gaps.Take(i + 1).Sum() : 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void BookmarksMouseState()
|
||||
{
|
||||
void down()
|
||||
{
|
||||
if (!curEvent.isMouseDown) return;
|
||||
|
||||
mousePressed = true;
|
||||
|
||||
mouseDownPosiion = curEvent.mousePosition;
|
||||
|
||||
var pressedBookmarkIndex = GetBookmarkIndex(mouseDownPosiion.x);
|
||||
|
||||
if (pressedBookmarkIndex.IsInRangeOf(data.bookmarks))
|
||||
pressedBookmark = data.bookmarks[pressedBookmarkIndex];
|
||||
|
||||
doubleclickUnhandled = curEvent.clickCount == 2;
|
||||
|
||||
curEvent.Use();
|
||||
|
||||
}
|
||||
void up()
|
||||
{
|
||||
if (!curEvent.isMouseUp) return;
|
||||
|
||||
mousePressed = false;
|
||||
pressedBookmark = null;
|
||||
|
||||
}
|
||||
void hover()
|
||||
{
|
||||
var hoveredBookmarkIndex = GetBookmarkIndex(curEvent.mousePosition.x);
|
||||
|
||||
mouseHoversBookmark = bookmarksRect.IsHovered() && hoveredBookmarkIndex.IsInRangeOf(data.bookmarks);
|
||||
|
||||
if (mouseHoversBookmark)
|
||||
lastHoveredBookmark = data.bookmarks[hoveredBookmarkIndex];
|
||||
|
||||
|
||||
}
|
||||
|
||||
down();
|
||||
up();
|
||||
hover();
|
||||
|
||||
}
|
||||
|
||||
bool mouseHoversBookmark;
|
||||
bool mousePressed;
|
||||
bool doubleclickUnhandled;
|
||||
|
||||
Vector2 mouseDownPosiion;
|
||||
|
||||
Bookmark pressedBookmark;
|
||||
Bookmark lastHoveredBookmark;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void BookmarksDragging()
|
||||
{
|
||||
void initFromOutside()
|
||||
{
|
||||
if (draggingBookmark) return;
|
||||
if (!bookmarksRect.IsHovered()) return;
|
||||
if (!curEvent.isDragUpdate) return;
|
||||
if (DragAndDrop.objectReferences.FirstOrDefault() is not Object draggedObject) return;
|
||||
|
||||
if (draggedObject is DefaultAsset) return;
|
||||
if (draggedObject is Component) return;
|
||||
if (draggedObject is GameObject go && StageUtility.GetCurrentStage() is PrefabStage && !AssetDatabase.Contains(go)) return;
|
||||
|
||||
animatingDroppedBookmark = false;
|
||||
|
||||
draggingBookmark = true;
|
||||
draggingBookmarkFromInside = false;
|
||||
|
||||
draggedBookmark = new Bookmark(draggedObject);
|
||||
draggedBookmarkHoldOffset = Vector2.zero;
|
||||
|
||||
}
|
||||
void initFromInside()
|
||||
{
|
||||
if (draggingBookmark) return;
|
||||
if (!mousePressed) return;
|
||||
if ((curEvent.mousePosition - mouseDownPosiion).magnitude <= 2) return;
|
||||
if (pressedBookmark == null) return;
|
||||
|
||||
var i = GetBookmarkIndex(mouseDownPosiion.x);
|
||||
|
||||
if (i >= data.bookmarks.Count) return;
|
||||
if (i < 0) return;
|
||||
|
||||
|
||||
animatingDroppedBookmark = false;
|
||||
|
||||
draggingBookmark = true;
|
||||
draggingBookmarkFromInside = true;
|
||||
|
||||
draggedBookmark = data.bookmarks[i];
|
||||
draggedBookmarkHoldOffset = new Vector2(GetBookmarkCenterX(i) - mouseDownPosiion.x, bookmarksRect.center.y - mouseDownPosiion.y);
|
||||
|
||||
gaps[i] = bookmarkWidth;
|
||||
|
||||
|
||||
data.RecordUndo();
|
||||
|
||||
data.bookmarks.Remove(draggedBookmark);
|
||||
|
||||
}
|
||||
|
||||
void acceptFromOutside()
|
||||
{
|
||||
if (!draggingBookmark) return;
|
||||
if (!curEvent.isDragPerform) return;
|
||||
if (!bookmarksRect.IsHovered()) return;
|
||||
|
||||
DragAndDrop.AcceptDrag();
|
||||
curEvent.Use();
|
||||
|
||||
data.RecordUndo();
|
||||
|
||||
accept();
|
||||
|
||||
data.Dirty();
|
||||
|
||||
}
|
||||
void acceptFromInside()
|
||||
{
|
||||
if (!draggingBookmark) return;
|
||||
if (!curEvent.isMouseUp) return;
|
||||
if (!bookmarksRect.IsHovered()) return;
|
||||
|
||||
curEvent.Use();
|
||||
EditorGUIUtility.hotControl = 0;
|
||||
|
||||
DragAndDrop.PrepareStartDrag(); // fixes phantom dragged component indicator after reordering bookmarks
|
||||
|
||||
data.RecordUndo();
|
||||
data.Dirty();
|
||||
|
||||
accept();
|
||||
|
||||
}
|
||||
void accept()
|
||||
{
|
||||
draggingBookmark = false;
|
||||
draggingBookmarkFromInside = false;
|
||||
mousePressed = false;
|
||||
|
||||
data.bookmarks.AddAt(draggedBookmark, insertDraggedBookmarkAtIndex);
|
||||
|
||||
gaps[insertDraggedBookmarkAtIndex] -= bookmarkWidth;
|
||||
gaps.AddAt(0, insertDraggedBookmarkAtIndex);
|
||||
|
||||
droppedBookmark = draggedBookmark;
|
||||
|
||||
droppedBookmarkX = curEvent.mousePosition.x + draggedBookmarkHoldOffset.x;
|
||||
droppedBookmarkXDerivative = 0;
|
||||
animatingDroppedBookmark = true;
|
||||
|
||||
draggedBookmark = null;
|
||||
|
||||
EditorGUIUtility.hotControl = 0;
|
||||
|
||||
repaintNeededAfterUndoRedo = true;
|
||||
|
||||
}
|
||||
|
||||
void cancelFromOutside()
|
||||
{
|
||||
if (!draggingBookmark) return;
|
||||
if (draggingBookmarkFromInside) return;
|
||||
if (bookmarksRect.IsHovered()) return;
|
||||
|
||||
draggingBookmark = false;
|
||||
mousePressed = false;
|
||||
|
||||
}
|
||||
void cancelFromInsideAndDelete()
|
||||
{
|
||||
if (!draggingBookmark) return;
|
||||
if (!curEvent.isMouseUp) return;
|
||||
if (bookmarksRect.IsHovered()) return;
|
||||
|
||||
draggingBookmark = false;
|
||||
|
||||
DragAndDrop.PrepareStartDrag(); // fixes phantom dragged component indicator after reordering bookmarks
|
||||
|
||||
data.Dirty();
|
||||
|
||||
repaintNeededAfterUndoRedo = true;
|
||||
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
if (!draggingBookmark) return;
|
||||
|
||||
DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
|
||||
|
||||
if (draggingBookmarkFromInside) // otherwise it breaks vTabs dragndrop
|
||||
EditorGUIUtility.hotControl = EditorGUIUtility.GetControlID(FocusType.Passive);
|
||||
|
||||
|
||||
|
||||
insertDraggedBookmarkAtIndex = GetBookmarkIndex(curEvent.mousePosition.x + draggedBookmarkHoldOffset.x);
|
||||
|
||||
}
|
||||
|
||||
|
||||
initFromOutside();
|
||||
initFromInside();
|
||||
|
||||
acceptFromOutside();
|
||||
acceptFromInside();
|
||||
|
||||
cancelFromOutside();
|
||||
cancelFromInsideAndDelete();
|
||||
|
||||
update();
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool draggingBookmark;
|
||||
bool draggingBookmarkFromInside;
|
||||
|
||||
int insertDraggedBookmarkAtIndex;
|
||||
|
||||
Vector2 draggedBookmarkHoldOffset;
|
||||
|
||||
Bookmark draggedBookmark;
|
||||
Bookmark droppedBookmark;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void BookmarksAnimations()
|
||||
{
|
||||
if (!curEvent.isLayout) return;
|
||||
|
||||
void gaps_()
|
||||
{
|
||||
var makeSpaceForDraggedBookmark = draggingBookmark && bookmarksRect.IsHovered();
|
||||
|
||||
var lerpSpeed = 12;
|
||||
|
||||
for (int i = 0; i < gaps.Count; i++)
|
||||
if (makeSpaceForDraggedBookmark && i == insertDraggedBookmarkAtIndex)
|
||||
gaps[i] = MathUtil.Lerp(gaps[i], bookmarkWidth, lerpSpeed, editorDeltaTime);
|
||||
else
|
||||
gaps[i] = MathUtil.Lerp(gaps[i], 0, lerpSpeed, editorDeltaTime);
|
||||
|
||||
|
||||
|
||||
for (int i = 0; i < gaps.Count; i++)
|
||||
if (gaps[i].Approx(0))
|
||||
gaps[i] = 0;
|
||||
|
||||
|
||||
|
||||
animatingGaps = gaps.Any(r => r > .1f);
|
||||
|
||||
|
||||
}
|
||||
void droppedBookmark_()
|
||||
{
|
||||
if (!animatingDroppedBookmark) return;
|
||||
|
||||
var lerpSpeed = 8;
|
||||
|
||||
var targX = GetBookmarkCenterX(data.bookmarks.IndexOf(droppedBookmark), includeGaps: true);
|
||||
|
||||
MathUtil.SmoothDamp(ref droppedBookmarkX, targX, lerpSpeed, ref droppedBookmarkXDerivative, editorDeltaTime);
|
||||
|
||||
if ((droppedBookmarkX - targX).Abs() < .5f)
|
||||
animatingDroppedBookmark = false;
|
||||
|
||||
}
|
||||
void tooltip()
|
||||
{
|
||||
if (!mouseHoversBookmark || lastHoveredBookmark != lastClickedBookmark)
|
||||
hideTooltip = false;
|
||||
|
||||
|
||||
var lerpSpeed = UnityEditorInternal.InternalEditorUtility.isApplicationActive ? 15 : 12321;
|
||||
|
||||
if (mouseHoversBookmark && !draggingBookmark && !hideTooltip)
|
||||
MathUtil.SmoothDamp(ref tooltipOpacity, 1, lerpSpeed, ref tooltipOpacityDerivative, editorDeltaTime);
|
||||
else
|
||||
MathUtil.SmoothDamp(ref tooltipOpacity, 0, lerpSpeed, ref tooltipOpacityDerivative, editorDeltaTime);
|
||||
|
||||
|
||||
if (tooltipOpacity > .99f)
|
||||
tooltipOpacity = 1;
|
||||
|
||||
if (tooltipOpacity < .01f)
|
||||
tooltipOpacity = 0;
|
||||
|
||||
|
||||
animatingTooltip = tooltipOpacity != 0 && tooltipOpacity != 1;
|
||||
|
||||
}
|
||||
|
||||
gaps_();
|
||||
droppedBookmark_();
|
||||
tooltip();
|
||||
|
||||
}
|
||||
|
||||
float droppedBookmarkX;
|
||||
float droppedBookmarkXDerivative;
|
||||
|
||||
float tooltipOpacity;
|
||||
float tooltipOpacityDerivative;
|
||||
|
||||
bool animatingDroppedBookmark;
|
||||
bool animatingGaps;
|
||||
bool animatingTooltip;
|
||||
|
||||
bool hideTooltip;
|
||||
|
||||
List<float> gaps
|
||||
{
|
||||
get
|
||||
{
|
||||
while (_gaps.Count < data.bookmarks.Count + 1) _gaps.Add(0);
|
||||
while (_gaps.Count > data.bookmarks.Count + 1) _gaps.RemoveLast();
|
||||
|
||||
return _gaps;
|
||||
|
||||
}
|
||||
}
|
||||
List<float> _gaps = new();
|
||||
|
||||
Bookmark lastClickedBookmark;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public VInspectorNavbar(EditorWindow window) => this.window = window;
|
||||
|
||||
public EditorWindow window;
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
11
Assets/vInspector/VInspectorNavbar.cs.meta
Normal file
11
Assets/vInspector/VInspectorNavbar.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f27f798b17a724efc8b05c54e23eff97
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
147
Assets/vInspector/VInspectorResettableVariables.cs
Normal file
147
Assets/vInspector/VInspectorResettableVariables.cs
Normal file
@@ -0,0 +1,147 @@
|
||||
#if UNITY_EDITOR
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using Type = System.Type;
|
||||
using static VInspector.VInspectorState;
|
||||
using static VInspector.Libs.VUtils;
|
||||
using static VInspector.Libs.VGUI;
|
||||
// using static VTools.VDebug;
|
||||
|
||||
|
||||
namespace VInspector
|
||||
{
|
||||
static class VInspectorResettableVariables
|
||||
{
|
||||
|
||||
public static void ResetButtonGUI(Rect fieldRect, SerializedProperty property, FieldInfo fieldInfo, IEnumerable<object> targets)
|
||||
{
|
||||
// if (!fieldRect.IsHovered()) return;
|
||||
|
||||
|
||||
object targetWithDefaultValues = GetTargetWithDefaulValues(targets.First().GetType());
|
||||
|
||||
bool isResetted(object target)
|
||||
{
|
||||
if (property.isInstantiatedPrefab && !PrefabUtility.IsAddedComponentOverride(property.serializedObject.targetObject)) return !property.prefabOverride;
|
||||
|
||||
if (targetWithDefaultValues as object == null) return true;
|
||||
|
||||
|
||||
var currentValue = fieldInfo.GetValue(target);
|
||||
var defaultValue = fieldInfo.GetValue(targetWithDefaultValues);
|
||||
|
||||
var isResetted = object.Equals(currentValue, defaultValue);
|
||||
|
||||
|
||||
if (typeof(Object).IsAssignableFrom(fieldInfo.FieldType))
|
||||
isResetted |= (defaultValue == null) && !(bool)(Object)currentValue;
|
||||
|
||||
if (fieldInfo.FieldType == typeof(string))
|
||||
isResetted |= fieldInfo.FieldType == typeof(string) && (object.Equals(currentValue, "") && object.Equals(defaultValue, null));
|
||||
|
||||
|
||||
return isResetted;
|
||||
|
||||
}
|
||||
|
||||
if (targets.All(r => isResetted(r))) return;
|
||||
|
||||
|
||||
|
||||
var iconSize = 12;
|
||||
var colorNormal = Greyscale(.41f);
|
||||
var colorHovered = Greyscale(isDarkTheme ? .9f : .0f);
|
||||
var colorPressed = Greyscale(isDarkTheme ? .65f : .6f);
|
||||
|
||||
var buttonRect = fieldRect.SetWidthFromRight(20).MoveX(typeof(Object).IsAssignableFrom(fieldInfo.FieldType) ? -18 : 1);
|
||||
|
||||
EditorGUIUtility.AddCursorRect(buttonRect, MouseCursor.CustomCursor);
|
||||
|
||||
|
||||
|
||||
if (!IconButton(buttonRect, "CrossIcon", iconSize, colorNormal, colorHovered, colorPressed)) return;
|
||||
|
||||
if (property.isInstantiatedPrefab && !PrefabUtility.IsAddedComponentOverride(property.serializedObject.targetObject))
|
||||
{
|
||||
foreach (var target in property.serializedObject.targetObjects)
|
||||
target.RecordUndo();
|
||||
|
||||
PrefabUtility.RevertPropertyOverride(property, InteractionMode.AutomatedAction);
|
||||
|
||||
}
|
||||
else
|
||||
property.SetBoxedValue(fieldInfo.GetValue(targetWithDefaultValues));
|
||||
|
||||
GUI.changed = true;
|
||||
|
||||
GUI.FocusControl(null);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static object GetTargetWithDefaulValues(Type targetType)
|
||||
{
|
||||
if (targetWithDefaulValues_byType.TryGetValue(targetType, out var cachedResult)) return cachedResult;
|
||||
|
||||
object targetWithDefaultValues = null;
|
||||
|
||||
void scriptOrSO()
|
||||
{
|
||||
if (!typeof(MonoBehaviour).IsAssignableFrom(targetType)
|
||||
&& !typeof(ScriptableObject).IsAssignableFrom(targetType)) return;
|
||||
|
||||
targetWithDefaultValues = System.Activator.CreateInstance(targetType);
|
||||
|
||||
mi_removeLogEntries.Invoke(null, new object[] { 1 << 9 });
|
||||
|
||||
}
|
||||
void customClass()
|
||||
{
|
||||
if (typeof(MonoBehaviour).IsAssignableFrom(targetType)) return;
|
||||
if (typeof(ScriptableObject).IsAssignableFrom(targetType)) return;
|
||||
if (targetType.GetConstructor(System.Type.EmptyTypes) == null) return;
|
||||
|
||||
targetWithDefaultValues = System.Activator.CreateInstance(targetType);
|
||||
|
||||
}
|
||||
|
||||
scriptOrSO();
|
||||
customClass();
|
||||
|
||||
return targetWithDefaulValues_byType[targetType] = targetWithDefaultValues;
|
||||
|
||||
}
|
||||
|
||||
static Dictionary<Type, object> targetWithDefaulValues_byType = new();
|
||||
|
||||
static MethodInfo mi_removeLogEntries = typeof(Editor).Assembly.GetType("UnityEditor.LogEntry").GetMethod("RemoveLogEntriesByMode", maxBindingFlags);
|
||||
|
||||
|
||||
|
||||
public static bool IsResettable(FieldInfo fieldInfo)
|
||||
{
|
||||
if (!VInspectorMenu.resettableVariablesEnabled) return false;
|
||||
if (Application.isPlaying) return false;
|
||||
|
||||
if (System.Attribute.IsDefined(fieldInfo, typeof(VariantsAttribute))) return false;
|
||||
|
||||
if (typeof(Object).IsAssignableFrom(fieldInfo.FieldType)) return true;
|
||||
if (fieldInfo.FieldType == typeof(int)) return true;
|
||||
if (fieldInfo.FieldType == typeof(float)) return true;
|
||||
if (fieldInfo.FieldType == typeof(double)) return true;
|
||||
if (fieldInfo.FieldType == typeof(string)) return true;
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
11
Assets/vInspector/VInspectorResettableVariables.cs.meta
Normal file
11
Assets/vInspector/VInspectorResettableVariables.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4efb7d95707f0459ba76cac7fa149875
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
129
Assets/vInspector/VInspectorSelectionHistory.cs
Normal file
129
Assets/vInspector/VInspectorSelectionHistory.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
#if UNITY_EDITOR
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.ShortcutManagement;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Type = System.Type;
|
||||
using static VInspector.Libs.VUtils;
|
||||
using static VInspector.Libs.VGUI;
|
||||
// using static VTools.VDebug;
|
||||
|
||||
|
||||
namespace VInspector
|
||||
{
|
||||
public class VInspectorSelectionHistory : ScriptableSingleton<VInspectorSelectionHistory>
|
||||
{
|
||||
|
||||
public void MoveBack()
|
||||
{
|
||||
var prevState = prevStates.Last();
|
||||
|
||||
instance.RecordUndo("VInspectorSelectionHistory.MoveBack");
|
||||
|
||||
prevStates.Remove(prevState);
|
||||
nextStates.Add(curState);
|
||||
curState = prevState;
|
||||
|
||||
|
||||
ignoreThisSelectionChange = true;
|
||||
|
||||
prevState.selectedObjects.ToArray().SelectInInspector(frameInHierarchy: false, frameInProject: false);
|
||||
|
||||
}
|
||||
public void MoveForward()
|
||||
{
|
||||
var nextState = nextStates.Last();
|
||||
|
||||
instance.RecordUndo("VInspectorSelectionHistory.MoveForward");
|
||||
|
||||
nextStates.Remove(nextState);
|
||||
prevStates.Add(curState);
|
||||
curState = nextState;
|
||||
|
||||
|
||||
ignoreThisSelectionChange = true;
|
||||
|
||||
nextState.selectedObjects.ToArray().SelectInInspector(frameInHierarchy: false, frameInProject: false);
|
||||
|
||||
}
|
||||
|
||||
static void OnSelectionChange()
|
||||
{
|
||||
if (ignoreThisSelectionChange) { ignoreThisSelectionChange = false; return; }
|
||||
|
||||
if (curEvent.modifiers == EventModifiers.Command && curEvent.keyCode == KeyCode.Z) return;
|
||||
if (curEvent.modifiers == (EventModifiers.Command | EventModifiers.Shift) && curEvent.keyCode == KeyCode.Z) return;
|
||||
|
||||
if (curEvent.modifiers == EventModifiers.Control && curEvent.keyCode == KeyCode.Z) return;
|
||||
if (curEvent.modifiers == EventModifiers.Control && curEvent.keyCode == KeyCode.Y) return;
|
||||
|
||||
|
||||
instance.RecordUndo(Undo.GetCurrentGroupName());
|
||||
|
||||
instance.prevStates.Add(instance.curState);
|
||||
instance.curState = new SelectionState() { selectedObjects = Selection.objects.ToList() };
|
||||
instance.nextStates.Clear();
|
||||
|
||||
if (instance.prevStates.Count > 50)
|
||||
instance.prevStates.RemoveAt(0);
|
||||
|
||||
}
|
||||
|
||||
static bool ignoreThisSelectionChange;
|
||||
|
||||
|
||||
public List<SelectionState> prevStates = new();
|
||||
public List<SelectionState> nextStates = new();
|
||||
public SelectionState curState;
|
||||
|
||||
[System.Serializable]
|
||||
public class SelectionState { public List<Object> selectedObjects = new(); }
|
||||
|
||||
|
||||
|
||||
[InitializeOnLoadMethod]
|
||||
static void Init()
|
||||
{
|
||||
if (VInspectorMenu.pluginDisabled) return;
|
||||
|
||||
|
||||
Selection.selectionChanged -= OnSelectionChange;
|
||||
Selection.selectionChanged += OnSelectionChange;
|
||||
|
||||
|
||||
// var globalEventHandler = typeof(EditorApplication).GetFieldValue<EditorApplication.CallbackFunction>("globalEventHandler");
|
||||
// typeof(EditorApplication).SetFieldValue("globalEventHandler", ClearHistories + (globalEventHandler - ClearHistories));
|
||||
|
||||
|
||||
instance.curState = new SelectionState() { selectedObjects = Selection.objects.ToList() };
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// static void ClearHistories() // just for debug
|
||||
// {
|
||||
// if (curEvent.holdingAnyModifierKey) return;
|
||||
// if (!curEvent.isKeyDown || curEvent.keyCode != KeyCode.Y) return;
|
||||
|
||||
// VInspectorSelectionHistory.instance.prevStates.Clear();
|
||||
// VInspectorSelectionHistory.instance.nextStates.Clear();
|
||||
|
||||
// Undo.ClearAll();
|
||||
|
||||
// VInspectorMenu.RepaintInspectors();
|
||||
|
||||
// }
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
11
Assets/vInspector/VInspectorSelectionHistory.cs.meta
Normal file
11
Assets/vInspector/VInspectorSelectionHistory.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 76c5ee368a46a4167b845f6db32ad060
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
73
Assets/vInspector/VInspectorSerializedDictionary.cs
Normal file
73
Assets/vInspector/VInspectorSerializedDictionary.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
|
||||
namespace VInspector
|
||||
{
|
||||
[System.Serializable]
|
||||
public class SerializedDictionary<TKey, TValue> : Dictionary<TKey, TValue>, ISerializationCallbackReceiver
|
||||
{
|
||||
public List<SerializedKeyValuePair<TKey, TValue>> serializedKvps = new();
|
||||
|
||||
public float dividerPos = .33f;
|
||||
|
||||
public void OnBeforeSerialize()
|
||||
{
|
||||
foreach (var kvp in this)
|
||||
if (serializedKvps.FirstOrDefault(r => this.Comparer.Equals(r.Key, kvp.Key)) is SerializedKeyValuePair<TKey, TValue> serializedKvp)
|
||||
serializedKvp.Value = kvp.Value;
|
||||
else
|
||||
serializedKvps.Add(kvp);
|
||||
|
||||
serializedKvps.RemoveAll(r => r.Key is not null && !this.ContainsKey(r.Key));
|
||||
|
||||
for (int i = 0; i < serializedKvps.Count; i++)
|
||||
serializedKvps[i].index = i;
|
||||
|
||||
}
|
||||
public void OnAfterDeserialize()
|
||||
{
|
||||
this.Clear();
|
||||
|
||||
foreach (var serializedKvp in serializedKvps)
|
||||
{
|
||||
serializedKvp.isKeyNull = serializedKvp.Key is null;
|
||||
serializedKvp.isKeyRepeated = serializedKvp.Key is not null && this.ContainsKey(serializedKvp.Key);
|
||||
|
||||
if (serializedKvp.isKeyNull) continue;
|
||||
if (serializedKvp.isKeyRepeated) continue;
|
||||
|
||||
|
||||
this.Add(serializedKvp.Key, serializedKvp.Value);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
[System.Serializable]
|
||||
public class SerializedKeyValuePair<TKey_, TValue_>
|
||||
{
|
||||
public TKey_ Key;
|
||||
public TValue_ Value;
|
||||
|
||||
public int index;
|
||||
|
||||
public bool isKeyRepeated;
|
||||
public bool isKeyNull;
|
||||
|
||||
|
||||
public SerializedKeyValuePair(TKey_ key, TValue_ value) { this.Key = key; this.Value = value; }
|
||||
|
||||
public static implicit operator SerializedKeyValuePair<TKey_, TValue_>(KeyValuePair<TKey_, TValue_> kvp) => new(kvp.Key, kvp.Value);
|
||||
public static implicit operator KeyValuePair<TKey_, TValue_>(SerializedKeyValuePair<TKey_, TValue_> kvp) => new(kvp.Key, kvp.Value);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
11
Assets/vInspector/VInspectorSerializedDictionary.cs.meta
Normal file
11
Assets/vInspector/VInspectorSerializedDictionary.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 00ee9a38e8fee47c29efb5789be8458c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
66
Assets/vInspector/VInspectorState.cs
Normal file
66
Assets/vInspector/VInspectorState.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
#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 VInspector.Libs.VUtils;
|
||||
using static VInspector.Libs.VGUI;
|
||||
// using static VTools.VDebug;
|
||||
|
||||
|
||||
namespace VInspector
|
||||
{
|
||||
[FilePath("Library/vInspector State.asset", FilePathAttribute.Location.ProjectFolder)]
|
||||
public class VInspectorState : ScriptableSingleton<VInspectorState>
|
||||
{
|
||||
|
||||
public SerializableDictionary<string, AttributesState> attributeStates_byScriptName = new();
|
||||
|
||||
[System.Serializable]
|
||||
public class AttributesState
|
||||
{
|
||||
public SerializableDictionary<string, int> selectedSubtabIndexes_byTabPath = new();
|
||||
public SerializableDictionary<string, bool> isExpandeds_byFoldoutPath = new();
|
||||
public SerializableDictionary<string, bool> isExpandeds_byButtonPath = new();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public SerializableDictionary<int, BookmarkState> bookmarkStates_byBookmarkId = new();
|
||||
|
||||
[System.Serializable]
|
||||
public class BookmarkState
|
||||
{
|
||||
public string _name;
|
||||
public string sceneGameObjectIconName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static void Clear()
|
||||
{
|
||||
instance.attributeStates_byScriptName.Clear();
|
||||
instance.bookmarkStates_byBookmarkId.Clear();
|
||||
|
||||
}
|
||||
|
||||
public static void Save() => instance.Save(true);
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
11
Assets/vInspector/VInspectorState.cs.meta
Normal file
11
Assets/vInspector/VInspectorState.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6fcb471c750b741839863cd8a7ce5785
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user