forked from Shardstone/trail-into-darkness
changed directory structure
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "AYellowpaper.SerializedCollections.Editor",
|
||||
"references": [
|
||||
"GUID:d525ad6bd40672747bde77962f1c401e"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 234340c04eed5674a988bc6ebde7d248
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: edb739dfb1824234681f6480c75cd523
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
@@ -0,0 +1,170 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8deddfed9f39d7740879d2cb0fcf7ce0
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 11
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMasterTextureLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 0
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 2
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 3
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 8192
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 8192
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 8192
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Android
|
||||
maxTextureSize: 8192
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Windows Store Apps
|
||||
maxTextureSize: 8192
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: Server
|
||||
maxTextureSize: 8192
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 3
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 8192
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
nameFileIdTable: {}
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,110 @@
|
||||
.sc-close-button {
|
||||
background-image: resource('d_winbtn_win_close@2x');
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
position: absolute;
|
||||
right: 2px;
|
||||
top: 2px;
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
border-left-width: 0;
|
||||
border-right-width: 0;
|
||||
border-top-width: 0;
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
.sc-close-button:hover {
|
||||
background-color: rgba(80, 80, 80, 255);
|
||||
}
|
||||
|
||||
.sc-close-button:active {
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.sc-text-toggle {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sc-text-toggle:checked {
|
||||
-unity-font-style: bold;
|
||||
}
|
||||
|
||||
.sc-text-toggle > Label {
|
||||
min-width: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.sc-text-toggle > .unity-radio-button__input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sc-title {
|
||||
background-color: rgba(40, 40, 40, 0.35);
|
||||
padding-left: 4px;
|
||||
padding-right: 3px;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
border-left-color: rgb(25, 25, 25);
|
||||
border-right-color: rgb(25, 25, 25);
|
||||
border-top-color: rgb(25, 25, 25);
|
||||
border-bottom-color: rgb(25, 25, 25);
|
||||
border-bottom-width: 1px;
|
||||
-unity-font-style: bold;
|
||||
}
|
||||
|
||||
.sc-generator-toggle {
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
}
|
||||
|
||||
.sc-generator-toggle:hover {
|
||||
background-color: rgb(48, 48, 48);
|
||||
}
|
||||
|
||||
.sc-generator-toggle:checked {
|
||||
background-color: rgb(77, 77, 77);
|
||||
}
|
||||
|
||||
.sc-modification-toggle {
|
||||
flex-basis: 100%;
|
||||
flex-shrink: 1;
|
||||
border-left-color: rgb(41, 41, 41);
|
||||
border-right-color: rgb(41, 41, 41);
|
||||
border-top-color: rgb(41, 41, 41);
|
||||
border-bottom-color: rgb(41, 41, 41);
|
||||
border-left-width: 1px;
|
||||
border-right-width: 1px;
|
||||
border-top-width: 1px;
|
||||
border-bottom-width: 1px;
|
||||
-unity-font-style: normal;
|
||||
-unity-text-align: middle-center;
|
||||
padding-left: 2px;
|
||||
padding-right: 2px;
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.sc-modification-toggle:hover {
|
||||
background-color: rgb(70, 70, 70);
|
||||
}
|
||||
|
||||
.sc-modification-toggle:checked {
|
||||
background-color: rgb(80, 80, 80);
|
||||
}
|
||||
|
||||
.sc-radio-button-group {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.sc-radio-button-group > Label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#generators-group {
|
||||
flex-direction: column;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: df6c2ef835e40c94c976442569324029
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
|
||||
disableValidation: 0
|
||||
@@ -0,0 +1,26 @@
|
||||
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
|
||||
<Style src="project://database/Assets/Plugins/SerializedCollections/Editor/Assets/KeysGeneratorSelectorWindow.uss?fileID=7433441132597879392&guid=df6c2ef835e40c94c976442569324029&type=3#KeysGeneratorSelectorWindow" />
|
||||
<ui:VisualElement style="flex-direction: row; flex-grow: 1; border-left-color: rgb(97, 97, 97); border-right-color: rgb(97, 97, 97); border-top-color: rgb(97, 97, 97); border-bottom-color: rgb(97, 97, 97); border-left-width: 2px; border-right-width: 2px; border-top-width: 2px; border-bottom-width: 2px;">
|
||||
<ui:VisualElement name="LeftContent" style="flex-basis: 66%; border-left-color: rgb(25, 25, 25); border-right-color: rgb(25, 25, 25); border-top-color: rgb(25, 25, 25); border-bottom-color: rgb(25, 25, 25); border-right-width: 1px;">
|
||||
<ui:Label text="Generators" display-tooltip-when-elided="true" class="sc-title" />
|
||||
<ui:ScrollView scroll-deceleration-rate="0,135" elasticity="0,1" name="generators-content" style="flex-grow: 1;" />
|
||||
</ui:VisualElement>
|
||||
<ui:VisualElement name="RightContent" style="flex-basis: 100%;">
|
||||
<ui:Label text="Inspector" display-tooltip-when-elided="true" class="sc-title" />
|
||||
<ui:IMGUIContainer name="imgui-inspector" style="flex-grow: 1; margin-left: 4px; margin-right: 4px; margin-top: 4px; margin-bottom: 4px;" />
|
||||
<ui:Label text="4 Elements " display-tooltip-when-elided="true" name="generated-count-label" style="padding-left: 2px; padding-right: 2px; padding-top: 2px; padding-bottom: 2px;" />
|
||||
<ui:VisualElement style="flex-direction: row;">
|
||||
<ui:RadioButtonGroup label="Radio Button Group" value="-1" name="modification-group" class="sc-radio-button-group" style="flex-grow: 1;">
|
||||
<ui:RadioButton label="Add" name="add-modification" tooltip="Add the generated missing keys to the target." class="sc-text-toggle sc-modification-toggle" />
|
||||
<ui:RadioButton label="Remove" name="remove-modification" tooltip="Remove the generated keys form the target." class="sc-text-toggle sc-modification-toggle" />
|
||||
<ui:RadioButton label="Confine" name="confine-modification" tooltip="Remove all keys that are not part of the generated keys from the target." class="sc-text-toggle sc-modification-toggle" />
|
||||
</ui:RadioButtonGroup>
|
||||
</ui:VisualElement>
|
||||
<ui:VisualElement style="flex-direction: row;">
|
||||
<ui:Label display-tooltip-when-elided="true" name="result-label" style="flex-grow: 1; -unity-text-align: middle-left; padding-left: 2px; padding-right: 2px; padding-top: 2px; padding-bottom: 2px;" />
|
||||
<ui:Button text="Apply" display-tooltip-when-elided="true" name="apply-button" style="width: 100px;" />
|
||||
</ui:VisualElement>
|
||||
</ui:VisualElement>
|
||||
<ui:Button display-tooltip-when-elided="true" class="sc-close-button" />
|
||||
</ui:VisualElement>
|
||||
</ui:UXML>
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 681c8a924c8b1e14b9fe53bb7397ec3d
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6398825db0c1d5348b5ec85b0c12d9c0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 81bf46994f9232b4e8dcf467c109f046
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor.Data
|
||||
{
|
||||
[System.Serializable]
|
||||
internal class ElementData
|
||||
{
|
||||
[SerializeField]
|
||||
private bool _isListToggleActive = false;
|
||||
|
||||
public ElementSettings Settings { get; }
|
||||
public bool ShowAsList => Settings.HasListDrawerToggle && IsListToggleActive;
|
||||
public bool IsListToggleActive { get => _isListToggleActive; set => _isListToggleActive = value; }
|
||||
public DisplayType EffectiveDisplayType => ShowAsList ? DisplayType.List : Settings.DisplayType;
|
||||
|
||||
public ElementData(ElementSettings elementSettings)
|
||||
{
|
||||
Settings = elementSettings;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 650a80186cc93b54aa5627197c23ea6e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor.Data
|
||||
{
|
||||
public class ElementSettings
|
||||
{
|
||||
public const string DefaultName = "Not Set";
|
||||
|
||||
public string DisplayName { get; set; } = DefaultName;
|
||||
public DisplayType DisplayType { get; set; } = DisplayType.PropertyNoLabel;
|
||||
public bool HasListDrawerToggle { get; set; } = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 12edfc8006691b7498459540b832c5eb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor.Data
|
||||
{
|
||||
[System.Serializable]
|
||||
internal class PropertyData
|
||||
{
|
||||
[SerializeField]
|
||||
private ElementData _keyData;
|
||||
[SerializeField]
|
||||
private ElementData _valueData;
|
||||
[SerializeField]
|
||||
private bool _alwaysShowSearch = false;
|
||||
|
||||
public bool AlwaysShowSearch
|
||||
{
|
||||
get => _alwaysShowSearch;
|
||||
set => _alwaysShowSearch = value;
|
||||
}
|
||||
|
||||
public ElementData GetElementData(bool fieldType)
|
||||
{
|
||||
return fieldType == SCEditorUtility.KeyFlag ? _keyData : _valueData;
|
||||
}
|
||||
|
||||
public PropertyData() : this(new ElementSettings(), new ElementSettings()) { }
|
||||
|
||||
public PropertyData(ElementSettings keySettings, ElementSettings valueSettings)
|
||||
{
|
||||
_keyData = new ElementData(keySettings);
|
||||
_valueData = new ElementData(valueSettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba2d792dfc6653e46bee7c027202acd3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor
|
||||
{
|
||||
public enum DisplayType
|
||||
{
|
||||
Property,
|
||||
PropertyNoLabel,
|
||||
List
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37ee13dd67b545846b6b063923812943
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d74b279cd03ebfb4ca7d2606f3f4f11e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 10b0c99dadaea0e42b49e323700f2eb9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.KeysGenerators
|
||||
{
|
||||
[KeyListGenerator("Populate Enum", typeof(System.Enum), false)]
|
||||
public class EnumGenerator : KeyListGenerator
|
||||
{
|
||||
public override IEnumerable GetKeys(System.Type type)
|
||||
{
|
||||
return System.Enum.GetValues(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d639de5d36bbeea4496c97cc3f1f4e81
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.KeysGenerators
|
||||
{
|
||||
[KeyListGenerator("Int Range", typeof(int))]
|
||||
public class IntRangeGenerator : KeyListGenerator
|
||||
{
|
||||
[SerializeField]
|
||||
private int _startValue = 1;
|
||||
[SerializeField]
|
||||
private int _endValue = 10;
|
||||
|
||||
public override IEnumerable GetKeys(Type type)
|
||||
{
|
||||
int dir = Math.Sign(_endValue - _startValue);
|
||||
dir = dir == 0 ? 1 : dir;
|
||||
for (int i = _startValue; i != _endValue; i += dir)
|
||||
yield return i;
|
||||
yield return _endValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a4203f3a582fa874fb035633bd9892b4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.KeysGenerators
|
||||
{
|
||||
[KeyListGenerator("Int Stepping", typeof(int))]
|
||||
public class IntSteppingGenerator : KeyListGenerator
|
||||
{
|
||||
[SerializeField]
|
||||
private int _startIndex = 0;
|
||||
[SerializeField]
|
||||
private int _stepDistance = 10;
|
||||
[SerializeField, Min(0)]
|
||||
private int _stepCount = 1;
|
||||
|
||||
public override IEnumerable GetKeys(Type type)
|
||||
{
|
||||
for (int i = 0; i <= _stepCount; i++)
|
||||
{
|
||||
yield return _startIndex + i * _stepDistance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 99302d4ff0ae27b4898ced57890ed32d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,11 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.KeysGenerators
|
||||
{
|
||||
public abstract class KeyListGenerator : ScriptableObject
|
||||
{
|
||||
public abstract IEnumerable GetKeys(System.Type type);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08149f25a1b9c5e48a224a7c4d31a154
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.KeysGenerators
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class KeyListGeneratorAttribute : Attribute
|
||||
{
|
||||
public readonly string Name;
|
||||
public readonly Type TargetType;
|
||||
public readonly bool NeedsWindow;
|
||||
|
||||
public KeyListGeneratorAttribute(string name, Type targetType, bool needsWindow = true)
|
||||
{
|
||||
Name = name;
|
||||
TargetType = targetType;
|
||||
NeedsWindow = needsWindow;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0f6065c936425ab478ecc8a8cf30d38f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.KeysGenerators
|
||||
{
|
||||
public static class KeyListGeneratorCache
|
||||
{
|
||||
private static List<KeyListGeneratorData> _populators;
|
||||
private static Dictionary<Type, List<KeyListGeneratorData>> _populatorsByType;
|
||||
|
||||
static KeyListGeneratorCache()
|
||||
{
|
||||
_populators = new List<KeyListGeneratorData>();
|
||||
_populatorsByType = new Dictionary<Type, List<KeyListGeneratorData>>();
|
||||
var populatorTypes = TypeCache.GetTypesDerivedFrom<KeyListGenerator>();
|
||||
foreach (var populatorType in populatorTypes.Where(x => !x.IsAbstract))
|
||||
{
|
||||
var attributes = populatorType.GetCustomAttributes<KeyListGeneratorAttribute>();
|
||||
foreach (var attribute in attributes)
|
||||
_populators.Add(new KeyListGeneratorData(attribute.Name, attribute.TargetType, populatorType, attribute.NeedsWindow));
|
||||
}
|
||||
}
|
||||
|
||||
public static IReadOnlyList<KeyListGeneratorData> GetPopulatorsForType(Type type)
|
||||
{
|
||||
if (!_populatorsByType.ContainsKey(type))
|
||||
_populatorsByType.Add(type, new List<KeyListGeneratorData>(_populators.Where(x => x.TargetType.IsAssignableFrom(type))));
|
||||
return _populatorsByType[type];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7936217ae19613d4bb5e46e73a4a587c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.KeysGenerators
|
||||
{
|
||||
public class KeyListGeneratorData
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public Type TargetType { get; set; }
|
||||
public Type GeneratorType { get; set; }
|
||||
public bool NeedsWindow { get; set; }
|
||||
|
||||
public KeyListGeneratorData(string name, Type targetType, Type populatorType, bool needsWindow)
|
||||
{
|
||||
Name = name;
|
||||
TargetType = targetType;
|
||||
GeneratorType = populatorType;
|
||||
NeedsWindow = needsWindow;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8992145ced672cd46a425fb2590b80bb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.KeysGenerators
|
||||
{
|
||||
[CustomEditor(typeof(KeyListGenerator), true)]
|
||||
public class KeyListGeneratorEditor : UnityEditor.Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
var iterator = serializedObject.GetIterator();
|
||||
if (iterator.Next(true))
|
||||
{
|
||||
// skip script name
|
||||
iterator.NextVisible(true);
|
||||
while (iterator.NextVisible(true))
|
||||
{
|
||||
EditorGUILayout.PropertyField(iterator);
|
||||
}
|
||||
}
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 211518bea98ede643af247b6295984bd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,182 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.KeysGenerators
|
||||
{
|
||||
public class KeyListGeneratorSelectorWindow : EditorWindow
|
||||
{
|
||||
[SerializeField]
|
||||
private int _selectedIndex;
|
||||
[SerializeField]
|
||||
private ModificationType _modificationType;
|
||||
|
||||
private KeyListGenerator _generator;
|
||||
private UnityEditor.Editor _editor;
|
||||
private List<KeyListGeneratorData> _generatorsData;
|
||||
private Type _targetType;
|
||||
private int _undoStart;
|
||||
private Dictionary<Type, KeyListGenerator> _keysGenerators = new Dictionary<Type, KeyListGenerator>();
|
||||
private string _detailsText;
|
||||
|
||||
public event Action<KeyListGenerator, ModificationType> OnApply;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
VisualTreeAsset document = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Plugins/SerializedCollections/Editor/Assets/KeysGeneratorSelectorWindow.uxml");
|
||||
var element = document.CloneTree();
|
||||
element.style.height = new StyleLength(new Length(100, LengthUnit.Percent));
|
||||
rootVisualElement.Add(element);
|
||||
}
|
||||
|
||||
public void Initialize(IEnumerable<KeyListGeneratorData> generatorsData, Type type)
|
||||
{
|
||||
_targetType = type;
|
||||
_selectedIndex = 0;
|
||||
_modificationType = ModificationType.Add;
|
||||
_undoStart = Undo.GetCurrentGroup();
|
||||
_generatorsData = new List<KeyListGeneratorData>(generatorsData);
|
||||
SetGeneratorIndex(0);
|
||||
Undo.undoRedoPerformed += HandleUndoCallback;
|
||||
|
||||
rootVisualElement.Q<Button>(className: "sc-close-button").clicked += Close;
|
||||
|
||||
rootVisualElement.Q<RadioButton>(name = "add-modification").userData = ModificationType.Add;
|
||||
rootVisualElement.Q<RadioButton>(name = "remove-modification").userData = ModificationType.Remove;
|
||||
rootVisualElement.Q<RadioButton>(name = "confine-modification").userData = ModificationType.Confine;
|
||||
|
||||
var modificationToggles = rootVisualElement.Query<RadioButton>(className: "sc-modification-toggle");
|
||||
modificationToggles.ForEach(InitializeModificationToggle);
|
||||
|
||||
rootVisualElement.Q<IMGUIContainer>(name = "imgui-inspector").onGUIHandler = EditorGUIHandler;
|
||||
rootVisualElement.Q<Button>(name = "apply-button").clicked += ApplyButtonClicked;
|
||||
|
||||
var generatorsContent = rootVisualElement.Q<ScrollView>(name = "generators-content");
|
||||
var radioButtonGroup = new RadioButtonGroup();
|
||||
radioButtonGroup.name = "generators-group";
|
||||
radioButtonGroup.AddToClassList("sc-radio-button-group");
|
||||
generatorsContent.Add(radioButtonGroup);
|
||||
|
||||
for (int i = 0; i < _generatorsData.Count; i++)
|
||||
{
|
||||
var generatorData = _generatorsData[i];
|
||||
|
||||
var radioButton = new RadioButton(generatorData.Name);
|
||||
radioButton.value = i == 0;
|
||||
radioButton.AddToClassList("sc-text-toggle");
|
||||
radioButton.AddToClassList("sc-generator-toggle");
|
||||
radioButton.userData = i;
|
||||
radioButton.RegisterValueChangedCallback(OnGeneratorClicked);
|
||||
radioButtonGroup.Add(radioButton);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyButtonClicked()
|
||||
{
|
||||
OnApply?.Invoke(_editor.target as KeyListGenerator, _modificationType);
|
||||
OnApply = null;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void EditorGUIHandler()
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
_editor.OnInspectorGUI();
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
UpdateDetailsText();
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeModificationToggle(RadioButton obj)
|
||||
{
|
||||
if ((ModificationType)obj.userData == _modificationType)
|
||||
obj.value = true;
|
||||
obj.RegisterValueChangedCallback(OnModificationToggleClicked);
|
||||
}
|
||||
|
||||
private void OnModificationToggleClicked(ChangeEvent<bool> evt)
|
||||
{
|
||||
if (!evt.newValue)
|
||||
return;
|
||||
|
||||
var modificationType = (ModificationType)((VisualElement)evt.target).userData;
|
||||
_modificationType = modificationType;
|
||||
}
|
||||
|
||||
private void UpdateDetailsText()
|
||||
{
|
||||
var enumerable = _generator.GetKeys(_targetType);
|
||||
int count = 0;
|
||||
var enumerator = enumerable.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
{
|
||||
count++;
|
||||
if (count > 100)
|
||||
{
|
||||
_detailsText = "over 100 Elements";
|
||||
return;
|
||||
}
|
||||
}
|
||||
_detailsText = $"{count} Elements";
|
||||
|
||||
rootVisualElement.Q<Label>(name = "generated-count-label").text = _detailsText;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
Undo.undoRedoPerformed -= HandleUndoCallback;
|
||||
Undo.RevertAllDownToGroup(_undoStart);
|
||||
foreach (var keyGenerator in _keysGenerators)
|
||||
DestroyImmediate(keyGenerator.Value);
|
||||
}
|
||||
|
||||
private void OnGeneratorClicked(ChangeEvent<bool> evt)
|
||||
{
|
||||
if (!evt.newValue)
|
||||
return;
|
||||
|
||||
SetGeneratorIndex((int)(evt.target as VisualElement).userData);
|
||||
}
|
||||
|
||||
private void HandleUndoCallback()
|
||||
{
|
||||
UpdateGeneratorAndEditorIfNeeded();
|
||||
Repaint();
|
||||
}
|
||||
|
||||
private void SetGeneratorIndex(int index)
|
||||
{
|
||||
Undo.RecordObject(this, "Change Window");
|
||||
_selectedIndex = index;
|
||||
UpdateGeneratorAndEditorIfNeeded();
|
||||
}
|
||||
|
||||
private void UpdateGeneratorAndEditorIfNeeded()
|
||||
{
|
||||
var targetType = _generatorsData[_selectedIndex].GeneratorType;
|
||||
if (_generator != null && _generator.GetType() == targetType)
|
||||
return;
|
||||
|
||||
_generator = GetOrCreateKeysGenerator(targetType);
|
||||
if (_editor != null)
|
||||
DestroyImmediate(_editor);
|
||||
_editor = UnityEditor.Editor.CreateEditor(_generator);
|
||||
|
||||
UpdateDetailsText();
|
||||
}
|
||||
|
||||
private KeyListGenerator GetOrCreateKeysGenerator(Type type)
|
||||
{
|
||||
if (!_keysGenerators.ContainsKey(type))
|
||||
{
|
||||
var so = (KeyListGenerator)CreateInstance(type);
|
||||
so.hideFlags = HideFlags.DontSave;
|
||||
_keysGenerators.Add(type, so);
|
||||
}
|
||||
return _keysGenerators[type];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: df07fe6d161e3334083f837a066dd949
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace AYellowpaper.SerializedCollections
|
||||
{
|
||||
public enum ModificationType
|
||||
{
|
||||
None,
|
||||
Add,
|
||||
Remove,
|
||||
Confine,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc2030edc0a04b74a8642773bd8c98fd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,68 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor
|
||||
{
|
||||
public class PagingElement
|
||||
{
|
||||
public int Page
|
||||
{
|
||||
get => _page;
|
||||
set
|
||||
{
|
||||
_page = value;
|
||||
EnsureValidPageIndex();
|
||||
}
|
||||
}
|
||||
public int PageCount
|
||||
{
|
||||
get => _pageCount;
|
||||
set
|
||||
{
|
||||
Debug.Assert(value >= 1, $"{nameof(PageCount)} needs to be 1 or larger but is {value}.");
|
||||
_pageCount = value;
|
||||
EnsureValidPageIndex();
|
||||
}
|
||||
}
|
||||
|
||||
private const int buttonWidth = 20;
|
||||
private const int inputWidth = 20;
|
||||
private const int labelWidth = 30;
|
||||
|
||||
private int _page = 1;
|
||||
private int _pageCount = 1;
|
||||
|
||||
public PagingElement(int pageCount = 1)
|
||||
{
|
||||
PageCount = pageCount;
|
||||
}
|
||||
|
||||
public float GetDesiredWidth()
|
||||
{
|
||||
return buttonWidth * 2 + inputWidth + labelWidth;
|
||||
}
|
||||
|
||||
public void OnGUI(Rect rect)
|
||||
{
|
||||
Rect leftButton = rect.WithXAndWidth(rect.x, buttonWidth);
|
||||
Rect inputRect = leftButton.AppendRight(inputWidth);
|
||||
Rect labelRect = inputRect.AppendRight(labelWidth);
|
||||
Rect rightButton = labelRect.AppendRight(buttonWidth);
|
||||
using (new GUIEnabledScope(Page != 1))
|
||||
if (GUI.Button(leftButton, "<"))
|
||||
Page--;
|
||||
using (new GUIEnabledScope(Page != PageCount))
|
||||
if (GUI.Button(rightButton, ">"))
|
||||
Page++;
|
||||
Page = EditorGUI.IntField(inputRect, Page);
|
||||
GUI.Label(labelRect, "/" + PageCount.ToString());
|
||||
}
|
||||
|
||||
private void EnsureValidPageIndex()
|
||||
{
|
||||
_page = Mathf.Clamp(_page, 1, PageCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f35ac465aece4064582910fc2c206682
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bead4ae311155bd46af1e99788f1d932
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 77b8ccff4f0c60943b9a54ce8d698d7f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using UnityEditor;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor.Search
|
||||
{
|
||||
public class EnumMatcher : Matcher
|
||||
{
|
||||
public override bool IsMatch(SerializedProperty property)
|
||||
{
|
||||
if (property.propertyType == SerializedPropertyType.Enum && SCEditorUtility.TryGetTypeFromProperty(property, out var type))
|
||||
{
|
||||
foreach (var text in SCEnumUtility.GetEnumCache(type).GetNamesForValue(property.enumValueFlag))
|
||||
{
|
||||
if (text.Contains(SearchString, StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f2cf86e71fb0ff04f96ac71dd9961962
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,20 @@
|
||||
using UnityEditor;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor.Search
|
||||
{
|
||||
public abstract class Matcher
|
||||
{
|
||||
public string SearchString { get; private set; }
|
||||
|
||||
public void Prepare(string searchString)
|
||||
{
|
||||
SearchString = ProcessSearchString(searchString);
|
||||
}
|
||||
|
||||
public virtual string ProcessSearchString(string searchString)
|
||||
{
|
||||
return searchString;
|
||||
}
|
||||
public abstract bool IsMatch(SerializedProperty property);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 218ea85e2d8480a498e8647aad524c8d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,30 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor.Search
|
||||
{
|
||||
public static class Matchers
|
||||
{
|
||||
public static IEnumerable<Matcher> RegisteredMatchers => _registeredMatchers;
|
||||
|
||||
private static List<Matcher> _registeredMatchers = new List<Matcher>();
|
||||
|
||||
static Matchers()
|
||||
{
|
||||
_registeredMatchers.Add(new NumericMatcher());
|
||||
_registeredMatchers.Add(new StringMatcher());
|
||||
_registeredMatchers.Add(new EnumMatcher());
|
||||
}
|
||||
|
||||
public static void AddMatcher(Matcher matcher)
|
||||
{
|
||||
_registeredMatchers.Add(matcher);
|
||||
}
|
||||
|
||||
public static bool RemoveMatcher(Matcher matcher)
|
||||
{
|
||||
return _registeredMatchers.Remove(matcher);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 94535827bd107e549baa23442df58bef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,109 @@
|
||||
using System.Globalization;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor.Search
|
||||
{
|
||||
public class NumericMatcher : Matcher
|
||||
{
|
||||
public override string ProcessSearchString(string searchString)
|
||||
{
|
||||
return searchString.Replace(',', '.');
|
||||
}
|
||||
|
||||
public override bool IsMatch(SerializedProperty property)
|
||||
{
|
||||
if (property.propertyType == SerializedPropertyType.Float)
|
||||
{
|
||||
return IsFloatMatch(property.floatValue);
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Integer)
|
||||
{
|
||||
return IsIntMatch(property.intValue);
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Quaternion)
|
||||
{
|
||||
var quat = property.quaternionValue;
|
||||
return IsFloatMatch(quat.x) || IsFloatMatch(quat.y) || IsFloatMatch(quat.z) || IsFloatMatch(quat.w);
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Bounds)
|
||||
{
|
||||
var bounds = property.boundsValue;
|
||||
return IsVector3Match(bounds.center) || IsVector3Match(bounds.size);
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.BoundsInt)
|
||||
{
|
||||
var bounds = property.boundsIntValue;
|
||||
return IsVector3Match(bounds.center) || IsVector3IntMatch(bounds.size);
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Rect)
|
||||
{
|
||||
var rect = property.rectValue;
|
||||
return IsVector2Match(rect.size) || IsVector2Match(rect.position);
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.RectInt)
|
||||
{
|
||||
var rect = property.rectIntValue;
|
||||
return IsVector2IntMatch(rect.size) || IsVector2IntMatch(rect.position);
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Vector2)
|
||||
{
|
||||
return IsVector2Match(property.vector2Value);
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Vector2Int)
|
||||
{
|
||||
return IsVector2IntMatch(property.vector2IntValue);
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Vector3)
|
||||
{
|
||||
return IsVector3Match(property.vector3Value);
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Vector3Int)
|
||||
{
|
||||
return IsVector3IntMatch(property.vector3IntValue);
|
||||
}
|
||||
else if (property.propertyType == SerializedPropertyType.Vector4)
|
||||
{
|
||||
return IsVector4Match(property.vector4Value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool IsFloatMatch(float val)
|
||||
{
|
||||
var str = val.ToString(CultureInfo.InvariantCulture);
|
||||
return str.Contains(SearchString, System.StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private bool IsIntMatch(int val)
|
||||
{
|
||||
var str = val.ToString(CultureInfo.InvariantCulture);
|
||||
return str.Contains(SearchString, System.StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private bool IsVector2Match(Vector2 vector)
|
||||
{
|
||||
return IsFloatMatch(vector.x) || IsFloatMatch(vector.y);
|
||||
}
|
||||
|
||||
private bool IsVector2IntMatch(Vector2Int vector)
|
||||
{
|
||||
return IsIntMatch(vector.x) || IsIntMatch(vector.y);
|
||||
}
|
||||
|
||||
private bool IsVector3Match(Vector3 vector)
|
||||
{
|
||||
return IsFloatMatch(vector.x) || IsFloatMatch(vector.y) || IsFloatMatch(vector.z);
|
||||
}
|
||||
|
||||
private bool IsVector3IntMatch(Vector3Int vector)
|
||||
{
|
||||
return IsIntMatch(vector.x) || IsIntMatch(vector.y) || IsIntMatch(vector.z);
|
||||
}
|
||||
|
||||
private bool IsVector4Match(Vector4 vector)
|
||||
{
|
||||
return IsFloatMatch(vector.x) || IsFloatMatch(vector.y) || IsFloatMatch(vector.z) || IsFloatMatch(vector.w);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc3ee6ec420212140bd3a86688d548de
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Globalization;
|
||||
using UnityEditor;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor.Search
|
||||
{
|
||||
public class StringMatcher : Matcher
|
||||
{
|
||||
public override bool IsMatch(SerializedProperty property)
|
||||
{
|
||||
if ((property.propertyType is SerializedPropertyType.String or SerializedPropertyType.Character) && property.stringValue.Contains(SearchString, System.StringComparison.OrdinalIgnoreCase))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be8bbc3471f8ad04b8da6366285443c6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor.Search
|
||||
{
|
||||
public class PropertySearchResult
|
||||
{
|
||||
public SerializedProperty Property;
|
||||
|
||||
public PropertySearchResult(SerializedProperty property)
|
||||
{
|
||||
Property = property;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Found match in in {Property.propertyPath}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33b4e4c67054c4d488fa66ff14bd3120
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,66 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor.Search
|
||||
{
|
||||
public class SearchQuery
|
||||
{
|
||||
public string SearchString
|
||||
{
|
||||
get => _text;
|
||||
set
|
||||
{
|
||||
if (_text == value)
|
||||
return;
|
||||
|
||||
_text = value;
|
||||
foreach (var matcher in _matchers)
|
||||
matcher.Prepare(_text);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<Matcher> _matchers;
|
||||
private string _text;
|
||||
|
||||
public SearchQuery(IEnumerable<Matcher> matchers)
|
||||
{
|
||||
_matchers = matchers;
|
||||
}
|
||||
|
||||
public List<PropertySearchResult> ApplyToProperty(SerializedProperty property)
|
||||
{
|
||||
TryGetMatchingProperties(property.Copy(), out var properties);
|
||||
return properties;
|
||||
}
|
||||
|
||||
public IEnumerable<SearchResultEntry> ApplyToArrayProperty(SerializedProperty property)
|
||||
{
|
||||
int arrayCount = property.arraySize;
|
||||
for (int i = 0; i < arrayCount; i++)
|
||||
{
|
||||
var prop = property.GetArrayElementAtIndex(i);
|
||||
if (TryGetMatchingProperties(prop.Copy(), out var properties))
|
||||
yield return new SearchResultEntry(i, prop, properties);
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetMatchingProperties(SerializedProperty property, out List<PropertySearchResult> matchingProperties)
|
||||
{
|
||||
matchingProperties = null;
|
||||
foreach (var child in SCEditorUtility.GetChildren(property, true))
|
||||
{
|
||||
foreach (var matcher in _matchers)
|
||||
{
|
||||
if (matcher.IsMatch(child))
|
||||
{
|
||||
if (matchingProperties == null)
|
||||
matchingProperties = new();
|
||||
matchingProperties.Add(new PropertySearchResult(child.Copy()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matchingProperties != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c87dd0caf3c44ed4e82896aa40bf1b96
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,31 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor.Search
|
||||
{
|
||||
public class SearchResultEntry
|
||||
{
|
||||
public readonly int Index;
|
||||
public readonly SerializedProperty Property;
|
||||
public readonly IEnumerable<PropertySearchResult> MatchingResults;
|
||||
|
||||
public SearchResultEntry(int index, SerializedProperty property, IEnumerable<PropertySearchResult> matchingResults)
|
||||
{
|
||||
Index = index;
|
||||
Property = property;
|
||||
MatchingResults = matchingResults;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine($"{Index}: {Property.propertyPath}");
|
||||
foreach (var matchingResult in MatchingResults)
|
||||
sb.AppendLine(matchingResult.ToString());
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d8455216ad2701d49b6dfec7f98ca88b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,62 @@
|
||||
using AYellowpaper.SerializedCollections.Editor.Data;
|
||||
using AYellowpaper.SerializedCollections.Editor.States;
|
||||
using AYellowpaper.SerializedCollections.KeysGenerators;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(SerializedDictionary<,>))]
|
||||
public class SerializedDictionaryDrawer : PropertyDrawer
|
||||
{
|
||||
public const string KeyName = nameof(SerializedKeyValuePair<int, int>.Key);
|
||||
public const string ValueName = nameof(SerializedKeyValuePair<int, int>.Value);
|
||||
public const string SerializedListName = nameof(SerializedDictionary<int, int>._serializedList);
|
||||
public const string LookupTableName = nameof(SerializedDictionary<int, int>.LookupTable);
|
||||
|
||||
public const int TopHeaderClipHeight = 20;
|
||||
public const int TopHeaderHeight = 19;
|
||||
public const int SearchHeaderHeight = 20;
|
||||
public const int KeyValueHeaderHeight = 18;
|
||||
public const bool KeyFlag = true;
|
||||
public const bool ValueFlag = false;
|
||||
public static readonly Color BorderColor = new Color(36 / 255f, 36 / 255f, 36 / 255f);
|
||||
public static readonly List<int> NoEntriesList = new List<int>();
|
||||
internal static GUIContent DisplayTypeToggleContent
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_displayTypeToggleContent == null)
|
||||
{
|
||||
var texture = AssetDatabase.LoadAssetAtPath<Texture>("Assets/Plugins/SerializedCollections/Editor/Assets/BurgerMenu@2x.png");
|
||||
_displayTypeToggleContent = new GUIContent(texture, "Toggle to either draw existing editor or draw properties manually.");
|
||||
}
|
||||
return _displayTypeToggleContent;
|
||||
}
|
||||
}
|
||||
private static GUIContent _displayTypeToggleContent;
|
||||
|
||||
private Dictionary<string, SerializedDictionaryInstanceDrawer> _arrayData = new();
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
if (!_arrayData.ContainsKey(property.propertyPath))
|
||||
_arrayData.Add(property.propertyPath, new SerializedDictionaryInstanceDrawer(property, fieldInfo));
|
||||
_arrayData[property.propertyPath].OnGUI(position, label);
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
if (!_arrayData.ContainsKey(property.propertyPath))
|
||||
_arrayData.Add(property.propertyPath, new SerializedDictionaryInstanceDrawer(property, fieldInfo));
|
||||
return _arrayData[property.propertyPath].GetPropertyHeight(label);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ccfc6d910f95ca4f94b294a9a3a8872
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,689 @@
|
||||
using AYellowpaper.SerializedCollections.Editor.Data;
|
||||
using AYellowpaper.SerializedCollections.Editor.States;
|
||||
using AYellowpaper.SerializedCollections.KeysGenerators;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEditor.IMGUI.Controls;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor
|
||||
{
|
||||
public class SerializedDictionaryInstanceDrawer
|
||||
{
|
||||
private FieldInfo _fieldInfo;
|
||||
private ReorderableList _unexpandedList;
|
||||
private SingleEditingData _singleEditingData;
|
||||
private FieldInfo _keyFieldInfo;
|
||||
private GUIContent _label;
|
||||
private Rect _totalRect;
|
||||
private GUIStyle _keyValueStyle;
|
||||
private SerializedDictionaryAttribute _dictionaryAttribute;
|
||||
private PropertyData _propertyData;
|
||||
private bool _propertyListSettingsInitialized = false;
|
||||
private List<int> _pagedIndices;
|
||||
private PagingElement _pagingElement;
|
||||
private int _lastListSize = -1;
|
||||
private IReadOnlyList<KeyListGeneratorData> _keyGeneratorsWithoutWindow;
|
||||
private IReadOnlyList<KeyListGeneratorData> _keyGeneratorsWithWindow;
|
||||
private SearchField _searchField;
|
||||
private GUIContent _shortDetailsContent;
|
||||
private GUIContent _detailsContent;
|
||||
private bool _showSearchBar = false;
|
||||
private ListState _activeState;
|
||||
|
||||
internal ReorderableList ReorderableList { get; private set; }
|
||||
internal SerializedProperty ListProperty { get; private set; }
|
||||
internal string SearchText { get; private set; } = string.Empty;
|
||||
internal SearchListState SearchState { get; private set; }
|
||||
internal DefaultListState DefaultState { get; private set; }
|
||||
|
||||
private class SingleEditingData
|
||||
{
|
||||
public bool IsValid => LookupTable != null;
|
||||
public IKeyable LookupTable;
|
||||
|
||||
public void Invalidate()
|
||||
{
|
||||
LookupTable = null;
|
||||
}
|
||||
}
|
||||
|
||||
public SerializedDictionaryInstanceDrawer(SerializedProperty property, FieldInfo fieldInfo)
|
||||
{
|
||||
_fieldInfo = fieldInfo;
|
||||
ListProperty = property.FindPropertyRelative(SerializedDictionaryDrawer.SerializedListName);
|
||||
|
||||
_keyValueStyle = new GUIStyle(EditorStyles.toolbarButton);
|
||||
_keyValueStyle.padding = new RectOffset(0, 0, 0, 0);
|
||||
_keyValueStyle.border = new RectOffset(0, 0, 0, 0);
|
||||
_keyValueStyle.alignment = TextAnchor.MiddleCenter;
|
||||
|
||||
DefaultState = new DefaultListState(this);
|
||||
SearchState = new SearchListState(this);
|
||||
_activeState = DefaultState;
|
||||
|
||||
_dictionaryAttribute = _fieldInfo.GetCustomAttribute<SerializedDictionaryAttribute>();
|
||||
|
||||
_propertyData = SCEditorUtility.GetPropertyData(ListProperty);
|
||||
_propertyData.GetElementData(SCEditorUtility.KeyFlag).Settings.DisplayName = _dictionaryAttribute?.KeyName ?? "Key";
|
||||
_propertyData.GetElementData(SCEditorUtility.ValueFlag).Settings.DisplayName = _dictionaryAttribute?.ValueName ?? "Value";
|
||||
SavePropertyData();
|
||||
|
||||
_pagingElement = new PagingElement();
|
||||
_pagedIndices = new List<int>();
|
||||
UpdatePaging();
|
||||
|
||||
ReorderableList = MakeList();
|
||||
_unexpandedList = MakeUnexpandedList();
|
||||
_searchField = new SearchField();
|
||||
|
||||
var listField = _fieldInfo.FieldType.GetField(SerializedDictionaryDrawer.SerializedListName, BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
var entryType = listField.FieldType.GetGenericArguments()[0];
|
||||
_keyFieldInfo = entryType.GetField(SerializedDictionaryDrawer.KeyName);
|
||||
|
||||
_singleEditingData = new SingleEditingData();
|
||||
|
||||
var keyGenerators = KeyListGeneratorCache.GetPopulatorsForType(_keyFieldInfo.FieldType);
|
||||
_keyGeneratorsWithWindow = keyGenerators.Where(x => x.NeedsWindow).ToList();
|
||||
_keyGeneratorsWithoutWindow = keyGenerators.Where(x => !x.NeedsWindow).ToList();
|
||||
|
||||
UpdateAfterInput();
|
||||
}
|
||||
|
||||
public void OnGUI(Rect position, GUIContent label)
|
||||
{
|
||||
_totalRect = position;
|
||||
_label = new GUIContent(label);
|
||||
|
||||
// Only call Update() in EditorWindow contexts where it's required.
|
||||
// In PropertyDrawers for MonoBehaviours/ScriptableObjects, Unity manages serialization
|
||||
// and calling Update() interferes with pending edits, causing values to revert.
|
||||
if (ListProperty.serializedObject.targetObject is EditorWindow)
|
||||
ListProperty.serializedObject.Update();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
DoList(position);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
ListProperty.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
|
||||
public float GetPropertyHeight(GUIContent label)
|
||||
{
|
||||
if (!ListProperty.isExpanded)
|
||||
return SerializedDictionaryDrawer.TopHeaderClipHeight;
|
||||
|
||||
return ReorderableList.GetHeight();
|
||||
}
|
||||
|
||||
private void DoList(Rect position)
|
||||
{
|
||||
if (ListProperty.isExpanded)
|
||||
ReorderableList.DoList(position);
|
||||
else
|
||||
{
|
||||
using (new GUI.ClipScope(new Rect(0, position.y, position.width + position.x, SerializedDictionaryDrawer.TopHeaderClipHeight)))
|
||||
{
|
||||
_unexpandedList.DoList(position.WithY(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessState()
|
||||
{
|
||||
var newState = _activeState.OnUpdate();
|
||||
if (newState != null && newState != _activeState)
|
||||
{
|
||||
_activeState.OnExit();
|
||||
_activeState = newState;
|
||||
newState.OnEnter();
|
||||
}
|
||||
}
|
||||
|
||||
private SerializedProperty GetElementProperty(SerializedProperty property, bool fieldFlag)
|
||||
{
|
||||
return property.FindPropertyRelative(fieldFlag == SerializedDictionaryDrawer.KeyFlag ? SerializedDictionaryDrawer.KeyName : SerializedDictionaryDrawer.ValueName);
|
||||
}
|
||||
|
||||
internal static float CalculateHeightOfElement(SerializedProperty property, bool drawKeyAsList, bool drawValueAsList)
|
||||
{
|
||||
SerializedProperty keyProperty = property.FindPropertyRelative(SerializedDictionaryDrawer.KeyName);
|
||||
SerializedProperty valueProperty = property.FindPropertyRelative(SerializedDictionaryDrawer.ValueName);
|
||||
return Mathf.Max(SCEditorUtility.CalculateHeight(keyProperty, drawKeyAsList), SCEditorUtility.CalculateHeight(valueProperty, drawValueAsList));
|
||||
}
|
||||
|
||||
private void UpdateAfterInput()
|
||||
{
|
||||
InitializeSettingsIfNeeded();
|
||||
ProcessState();
|
||||
CheckPaging();
|
||||
var elementsPerPage = EditorUserSettings.Get().ElementsPerPage;
|
||||
int pageCount = Mathf.Max(1, Mathf.CeilToInt((float)DefaultState.ListSize / elementsPerPage));
|
||||
ToggleSearchBar(_propertyData.AlwaysShowSearch ? true : SCEditorUtility.ShouldShowSearch(pageCount));
|
||||
}
|
||||
|
||||
private void InitializeSettingsIfNeeded()
|
||||
{
|
||||
void InitializeSettings(bool fieldFlag)
|
||||
{
|
||||
var genericArgs = _fieldInfo.FieldType.GetGenericArguments();
|
||||
var firstProperty = ListProperty.GetArrayElementAtIndex(0);
|
||||
var keySettings = CreateDisplaySettings(GetElementProperty(firstProperty, fieldFlag), genericArgs[fieldFlag == SCEditorUtility.KeyFlag ? 0 : 1]);
|
||||
var settings = _propertyData.GetElementData(fieldFlag).Settings;
|
||||
settings.DisplayType = keySettings.displayType;
|
||||
settings.HasListDrawerToggle = keySettings.canToggleListDrawer;
|
||||
}
|
||||
|
||||
if (!_propertyListSettingsInitialized && ListProperty.minArraySize > 0)
|
||||
{
|
||||
_propertyListSettingsInitialized = true;
|
||||
InitializeSettings(SCEditorUtility.KeyFlag);
|
||||
InitializeSettings(SCEditorUtility.ValueFlag);
|
||||
SavePropertyData();
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckPaging()
|
||||
{
|
||||
// TODO: Is there a better solution to check for Revert/delete/add?
|
||||
if (_lastListSize != _activeState.ListSize)
|
||||
{
|
||||
_lastListSize = _activeState.ListSize;
|
||||
UpdateSingleEditing();
|
||||
UpdatePaging();
|
||||
}
|
||||
}
|
||||
|
||||
private void SavePropertyData()
|
||||
{
|
||||
SCEditorUtility.SavePropertyData(ListProperty, _propertyData);
|
||||
}
|
||||
|
||||
private void UpdateSingleEditing()
|
||||
{
|
||||
if (ListProperty.serializedObject.isEditingMultipleObjects && _singleEditingData.IsValid)
|
||||
_singleEditingData.Invalidate();
|
||||
else if (!ListProperty.serializedObject.isEditingMultipleObjects && !_singleEditingData.IsValid)
|
||||
{
|
||||
var dictionary = SCEditorUtility.GetPropertyValue(ListProperty, ListProperty.serializedObject.targetObject);
|
||||
_singleEditingData.LookupTable = GetLookupTable(dictionary);
|
||||
}
|
||||
}
|
||||
|
||||
private IKeyable GetLookupTable(object dictionary)
|
||||
{
|
||||
var propInfo = dictionary.GetType().GetProperty(SerializedDictionaryDrawer.LookupTableName, BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
return (IKeyable)propInfo.GetValue(dictionary);
|
||||
}
|
||||
|
||||
private void UpdatePaging()
|
||||
{
|
||||
var elementsPerPage = EditorUserSettings.Get().ElementsPerPage;
|
||||
_pagingElement.PageCount = Mathf.Max(1, Mathf.CeilToInt((float)_activeState.ListSize / elementsPerPage));
|
||||
|
||||
_pagedIndices.Clear();
|
||||
_pagedIndices.Capacity = Mathf.Max(elementsPerPage, _pagedIndices.Capacity);
|
||||
|
||||
int startIndex = (_pagingElement.Page - 1) * elementsPerPage;
|
||||
int endIndex = Mathf.Min(startIndex + elementsPerPage, _activeState.ListSize);
|
||||
for (int i = startIndex; i < endIndex; i++)
|
||||
_pagedIndices.Add(i);
|
||||
|
||||
string shortDetailsString = (_activeState.ListSize + " " + (_pagedIndices.Count == 1 ? "Element" : "Elements"));
|
||||
string detailsString = _pagingElement.PageCount > 1
|
||||
? $"{_pagedIndices[0] + 1}..{_pagedIndices.Last() + 1} / {_activeState.ListSize} Elements"
|
||||
: shortDetailsString;
|
||||
_detailsContent = new GUIContent(detailsString);
|
||||
_shortDetailsContent = new GUIContent(shortDetailsString);
|
||||
}
|
||||
|
||||
private ReorderableList MakeList()
|
||||
{
|
||||
var list = new ReorderableList(_pagedIndices, typeof(int), true, true, true, true);
|
||||
list.onAddCallback += OnAdd;
|
||||
list.onRemoveCallback += OnRemove;
|
||||
list.onReorderCallbackWithDetails += OnReorder;
|
||||
list.drawElementCallback += OnDrawElement;
|
||||
list.elementHeightCallback += OnGetElementHeight;
|
||||
list.drawHeaderCallback += OnDrawHeader;
|
||||
list.drawNoneElementCallback += OnDrawNoneElement;
|
||||
return list;
|
||||
}
|
||||
|
||||
private ReorderableList MakeUnexpandedList()
|
||||
{
|
||||
var list = new ReorderableList(SerializedDictionaryDrawer.NoEntriesList, typeof(int));
|
||||
list.drawHeaderCallback = DrawUnexpandedHeader;
|
||||
return list;
|
||||
}
|
||||
|
||||
private void ToggleSearchBar(bool flag)
|
||||
{
|
||||
_showSearchBar = flag;
|
||||
ReorderableList.headerHeight = SerializedDictionaryDrawer.TopHeaderClipHeight + SerializedDictionaryDrawer.KeyValueHeaderHeight + (_showSearchBar ? SerializedDictionaryDrawer.SearchHeaderHeight : 0);
|
||||
if (!_showSearchBar)
|
||||
{
|
||||
if (_searchField.HasFocus())
|
||||
GUI.FocusControl(null);
|
||||
SearchText = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDrawNoneElement(Rect rect)
|
||||
{
|
||||
EditorGUI.LabelField(rect, EditorGUIUtility.TrTextContent(_activeState.NoElementsText));
|
||||
}
|
||||
|
||||
private (DisplayType displayType, bool canToggleListDrawer) CreateDisplaySettings(SerializedProperty property, Type type)
|
||||
{
|
||||
bool hasCustomEditor = SCEditorUtility.HasDrawerForType(type, property.propertyType == SerializedPropertyType.ManagedReference);
|
||||
bool isGenericWithChildren = property.propertyType == SerializedPropertyType.Generic && property.hasVisibleChildren;
|
||||
bool isArray = property.isArray && property.propertyType != SerializedPropertyType.String;
|
||||
bool canToggleListDrawer = isArray || (isGenericWithChildren && hasCustomEditor);
|
||||
DisplayType displayType = DisplayType.PropertyNoLabel;
|
||||
if (canToggleListDrawer)
|
||||
displayType = DisplayType.Property;
|
||||
else if (!isArray && isGenericWithChildren && !hasCustomEditor)
|
||||
displayType = DisplayType.List;
|
||||
return (displayType, canToggleListDrawer);
|
||||
}
|
||||
|
||||
private void DrawUnexpandedHeader(Rect rect)
|
||||
{
|
||||
EditorGUI.BeginProperty(rect, _label, ListProperty);
|
||||
ListProperty.isExpanded = EditorGUI.Foldout(rect.WithX(rect.x - 5), ListProperty.isExpanded, _label, true);
|
||||
|
||||
var detailsStyle = EditorStyles.miniLabel;
|
||||
var detailsRect = rect.AppendRight(0).AppendLeft(detailsStyle.CalcSize(_shortDetailsContent).x);
|
||||
GUI.Label(detailsRect, _shortDetailsContent, detailsStyle);
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
private void DoPaging(Rect rect)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
_pagingElement.OnGUI(rect);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
ReorderableList.ClearSelection();
|
||||
UpdatePaging();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDrawHeader(Rect rect)
|
||||
{
|
||||
Rect topRect = rect.WithHeight(SerializedDictionaryDrawer.TopHeaderHeight);
|
||||
Rect adjustedTopRect = topRect.WithXAndWidth(_totalRect.x + 1, _totalRect.width - 1);
|
||||
|
||||
DoMainHeader(adjustedTopRect.CutLeft(topRect.x - adjustedTopRect.x));
|
||||
if (_showSearchBar)
|
||||
{
|
||||
adjustedTopRect = adjustedTopRect.AppendDown(SerializedDictionaryDrawer.SearchHeaderHeight);
|
||||
DoSearch(adjustedTopRect);
|
||||
}
|
||||
DoKeyValueRect(adjustedTopRect.AppendDown(SerializedDictionaryDrawer.KeyValueHeaderHeight));
|
||||
|
||||
UpdateAfterInput();
|
||||
}
|
||||
|
||||
private void DoMainHeader(Rect rect)
|
||||
{
|
||||
Rect lastTopRect = rect.AppendRight(0).WithHeight(EditorGUIUtility.singleLineHeight);
|
||||
|
||||
lastTopRect = lastTopRect.AppendLeft(20);
|
||||
DoOptionsButton(lastTopRect);
|
||||
lastTopRect = lastTopRect.AppendLeft(5);
|
||||
|
||||
if (_pagingElement.PageCount > 1)
|
||||
{
|
||||
lastTopRect = lastTopRect.AppendLeft(_pagingElement.GetDesiredWidth());
|
||||
DoPaging(lastTopRect);
|
||||
}
|
||||
|
||||
var detailsStyle = EditorStyles.miniLabel;
|
||||
lastTopRect = lastTopRect.AppendLeft(detailsStyle.CalcSize(_detailsContent).x, 5);
|
||||
GUI.Label(lastTopRect, _detailsContent, detailsStyle);
|
||||
|
||||
if (!_singleEditingData.IsValid)
|
||||
{
|
||||
lastTopRect = lastTopRect.AppendLeft(lastTopRect.height + 5);
|
||||
var guicontent = EditorGUIUtility.TrIconContent(EditorGUIUtility.Load("d_console.infoicon") as Texture, "Conflict checking, duplicate key removal and populators not supported in multi object editing mode.");
|
||||
GUI.Label(lastTopRect, guicontent);
|
||||
}
|
||||
|
||||
EditorGUI.BeginProperty(rect, _label, ListProperty);
|
||||
ListProperty.isExpanded = EditorGUI.Foldout(rect.WithXAndWidth(rect.x - 5, lastTopRect.x - rect.x), ListProperty.isExpanded, _label, true);
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
private void DoOptionsButton(Rect rect)
|
||||
{
|
||||
var screenRect = GUIUtility.GUIToScreenRect(rect);
|
||||
if (GUI.Button(rect, EditorGUIUtility.IconContent("pane options@2x"), EditorStyles.iconButton))
|
||||
{
|
||||
var gm = new GenericMenu();
|
||||
SCEditorUtility.AddGenericMenuItem(gm, false, ListProperty.minArraySize > 0, new GUIContent("Clear"), () => QueueAction(ClearList));
|
||||
SCEditorUtility.AddGenericMenuItem(gm, false, true, new GUIContent("Remove Conflicts"), () => QueueAction(RemoveConflicts));
|
||||
SCEditorUtility.AddGenericMenuItem(gm, false, _keyGeneratorsWithWindow.Count > 0, new GUIContent("Bulk Edit..."), () => OpenKeysGeneratorSelectorWindow(screenRect));
|
||||
if (_keyGeneratorsWithoutWindow.Count > 0)
|
||||
{
|
||||
gm.AddSeparator(string.Empty);
|
||||
foreach (var generatorData in _keyGeneratorsWithoutWindow)
|
||||
{
|
||||
SCEditorUtility.AddGenericMenuItem(gm, false, true, new GUIContent(generatorData.Name), OnPopulatorDataSelected, generatorData);
|
||||
}
|
||||
}
|
||||
gm.AddSeparator(string.Empty);
|
||||
SCEditorUtility.AddGenericMenuItem(gm, _propertyData.AlwaysShowSearch, true, new GUIContent("Always Show Search"), ToggleAlwaysShowSearchPropertyData);
|
||||
gm.AddItem(new GUIContent("Preferences..."), false, () => SettingsService.OpenUserPreferences(EditorUserSettingsProvider.PreferencesPath));
|
||||
gm.DropDown(rect);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPopulatorDataSelected(object userData)
|
||||
{
|
||||
var data = (KeyListGeneratorData)userData;
|
||||
var so = (KeyListGenerator)ScriptableObject.CreateInstance(data.GeneratorType);
|
||||
so.hideFlags = HideFlags.DontSave;
|
||||
ApplyPopulatorQueued(so, ModificationType.Add);
|
||||
}
|
||||
|
||||
private void OpenKeysGeneratorSelectorWindow(Rect rect)
|
||||
{
|
||||
var window = ScriptableObject.CreateInstance<KeyListGeneratorSelectorWindow>();
|
||||
window.Initialize(_keyGeneratorsWithWindow, _keyFieldInfo.FieldType);
|
||||
window.ShowAsDropDown(rect, new Vector2(400, 200));
|
||||
window.OnApply += ApplyPopulatorQueued;
|
||||
}
|
||||
|
||||
private void ToggleAlwaysShowSearchPropertyData()
|
||||
{
|
||||
_propertyData.AlwaysShowSearch = !_propertyData.AlwaysShowSearch;
|
||||
SavePropertyData();
|
||||
}
|
||||
|
||||
private void DoKeyValueRect(Rect rect)
|
||||
{
|
||||
float width = EditorGUIUtility.labelWidth + 22;
|
||||
Rect leftRect = rect.WithWidth(width);
|
||||
Rect rightRect = leftRect.AppendRight(rect.width - width);
|
||||
|
||||
if (Event.current.type == EventType.Repaint && _propertyData != null)
|
||||
{
|
||||
_keyValueStyle.Draw(leftRect, EditorGUIUtility.TrTextContent(_propertyData.GetElementData(SerializedDictionaryDrawer.KeyFlag).Settings.DisplayName), false, false, false, false);
|
||||
_keyValueStyle.Draw(rightRect, EditorGUIUtility.TrTextContent(_propertyData.GetElementData(SerializedDictionaryDrawer.ValueFlag).Settings.DisplayName), false, false, false, false);
|
||||
}
|
||||
|
||||
if (ListProperty.minArraySize > 0)
|
||||
{
|
||||
DoDisplayTypeToggle(leftRect, SerializedDictionaryDrawer.KeyFlag);
|
||||
DoDisplayTypeToggle(rightRect, SerializedDictionaryDrawer.ValueFlag);
|
||||
}
|
||||
|
||||
EditorGUI.DrawRect(rect.AppendDown(1, -1), SerializedDictionaryDrawer.BorderColor);
|
||||
}
|
||||
|
||||
private void DoSearch(Rect rect)
|
||||
{
|
||||
EditorGUI.DrawRect(rect.AppendLeft(1), SerializedDictionaryDrawer.BorderColor);
|
||||
EditorGUI.DrawRect(rect.AppendRight(1, -1), SerializedDictionaryDrawer.BorderColor);
|
||||
EditorGUI.DrawRect(rect.AppendDown(1, -1), SerializedDictionaryDrawer.BorderColor);
|
||||
|
||||
SearchText = _searchField.OnToolbarGUI(rect.CutTop(2).CutHorizontal(6), SearchText);
|
||||
}
|
||||
|
||||
private void ApplyPopulatorQueued(KeyListGenerator populator, ModificationType modificationType)
|
||||
{
|
||||
var array = populator.GetKeys(_keyFieldInfo.FieldType).OfType<object>().ToArray();
|
||||
QueueAction(() => ApplyPopulator(array, modificationType));
|
||||
}
|
||||
|
||||
private void QueueAction(EditorApplication.CallbackFunction action)
|
||||
{
|
||||
EditorApplication.delayCall += action;
|
||||
}
|
||||
|
||||
private void ApplyPopulator(IEnumerable<object> elements, ModificationType modificationType)
|
||||
{
|
||||
foreach (var targetObject in ListProperty.serializedObject.targetObjects)
|
||||
{
|
||||
Undo.RecordObject(targetObject, "Populate");
|
||||
var dictionary = SCEditorUtility.GetPropertyValue(ListProperty, targetObject);
|
||||
var lookupTable = GetLookupTable(dictionary);
|
||||
|
||||
if (modificationType == ModificationType.Add)
|
||||
AddElements(lookupTable, elements);
|
||||
else if (modificationType == ModificationType.Remove)
|
||||
RemoveElements(lookupTable, elements);
|
||||
else if (modificationType == ModificationType.Confine)
|
||||
ConfineElements(lookupTable, elements);
|
||||
|
||||
lookupTable.RecalculateOccurences();
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(targetObject);
|
||||
}
|
||||
|
||||
ListProperty.serializedObject.Update();
|
||||
ActiveEditorTracker.sharedTracker.ForceRebuild();
|
||||
}
|
||||
|
||||
private static void AddElements(IKeyable lookupTable, IEnumerable<object> elements)
|
||||
{
|
||||
foreach (var key in elements)
|
||||
{
|
||||
var occurences = lookupTable.GetOccurences(key);
|
||||
if (occurences.Count > 0)
|
||||
continue;
|
||||
lookupTable.AddKey(key);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ConfineElements(IKeyable lookupTable, IEnumerable<object> elements)
|
||||
{
|
||||
var keysToRemove = lookupTable.Keys.OfType<object>().ToHashSet();
|
||||
foreach (var key in elements)
|
||||
keysToRemove.Remove(key);
|
||||
|
||||
RemoveElements(lookupTable, keysToRemove);
|
||||
}
|
||||
|
||||
private static void RemoveElements(IKeyable lookupTable, IEnumerable<object> elements)
|
||||
{
|
||||
var indicesToRemove = elements.SelectMany(x => lookupTable.GetOccurences(x)).OrderByDescending(index => index);
|
||||
foreach (var index in indicesToRemove)
|
||||
{
|
||||
lookupTable.RemoveAt(index);
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearList()
|
||||
{
|
||||
ListProperty.ClearArray();
|
||||
ListProperty.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
private void RemoveConflicts()
|
||||
{
|
||||
foreach (var targetObject in ListProperty.serializedObject.targetObjects)
|
||||
{
|
||||
Undo.RecordObject(targetObject, "Remove Conflicts");
|
||||
var dictionary = SCEditorUtility.GetPropertyValue(ListProperty, targetObject);
|
||||
var lookupTable = GetLookupTable(dictionary);
|
||||
|
||||
List<int> duplicateIndices = new List<int>();
|
||||
|
||||
foreach (var key in lookupTable.Keys)
|
||||
{
|
||||
var occurences = lookupTable.GetOccurences(key);
|
||||
for (int i = 1; i < occurences.Count; i++)
|
||||
duplicateIndices.Add(occurences[i]);
|
||||
}
|
||||
|
||||
foreach (var indexToRemove in duplicateIndices.OrderByDescending(x => x))
|
||||
{
|
||||
lookupTable.RemoveAt(indexToRemove);
|
||||
}
|
||||
|
||||
lookupTable.RecalculateOccurences();
|
||||
PrefabUtility.RecordPrefabInstancePropertyModifications(targetObject);
|
||||
}
|
||||
|
||||
ListProperty.serializedObject.Update();
|
||||
ActiveEditorTracker.sharedTracker.ForceRebuild();
|
||||
}
|
||||
|
||||
private void DoDisplayTypeToggle(Rect contentRect, bool fieldFlag)
|
||||
{
|
||||
var displayData = _propertyData.GetElementData(fieldFlag);
|
||||
|
||||
if (displayData.Settings.HasListDrawerToggle)
|
||||
{
|
||||
Rect rightRectToggle = new Rect(contentRect);
|
||||
rightRectToggle.x += rightRectToggle.width - 18;
|
||||
rightRectToggle.width = 18;
|
||||
EditorGUI.BeginChangeCheck();
|
||||
bool newValue = GUI.Toggle(rightRectToggle, displayData.IsListToggleActive, SerializedDictionaryDrawer.DisplayTypeToggleContent, EditorStyles.toolbarButton);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
displayData.IsListToggleActive = newValue;
|
||||
SavePropertyData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float OnGetElementHeight(int index)
|
||||
{
|
||||
int actualIndex = _pagedIndices[index];
|
||||
var element = _activeState.GetPropertyAtIndex(actualIndex);
|
||||
return CalculateHeightOfElement(element, _propertyData.GetElementData(SerializedDictionaryDrawer.KeyFlag).EffectiveDisplayType == DisplayType.List ? true : false, _propertyData.GetElementData(SerializedDictionaryDrawer.ValueFlag).EffectiveDisplayType == DisplayType.List ? true : false);
|
||||
}
|
||||
|
||||
private void OnDrawElement(Rect rect, int index, bool isActive, bool isFocused)
|
||||
{
|
||||
const int lineLeftSpace = 2;
|
||||
const int lineWidth = 1;
|
||||
const int lineRightSpace = 12;
|
||||
const int totalSpace = lineLeftSpace + lineWidth + lineRightSpace;
|
||||
|
||||
int actualIndex = _pagedIndices[index];
|
||||
|
||||
SerializedProperty kvp = _activeState.GetPropertyAtIndex(actualIndex);
|
||||
Rect keyRect = rect.WithSize(EditorGUIUtility.labelWidth - lineLeftSpace, EditorGUIUtility.singleLineHeight);
|
||||
Rect lineRect = keyRect.WithXAndWidth(keyRect.x + keyRect.width + lineLeftSpace, lineWidth).WithHeight(rect.height);
|
||||
Rect valueRect = keyRect.AppendRight(rect.width - keyRect.width - totalSpace, totalSpace);
|
||||
|
||||
var keyProperty = kvp.FindPropertyRelative(SerializedDictionaryDrawer.KeyName);
|
||||
var valueProperty = kvp.FindPropertyRelative(SerializedDictionaryDrawer.ValueName);
|
||||
|
||||
Color prevColor = GUI.color;
|
||||
if (_singleEditingData.IsValid)
|
||||
{
|
||||
var keyObject = _keyFieldInfo.GetValue(_singleEditingData.LookupTable.GetKeyAt(actualIndex));
|
||||
var occurences = _singleEditingData.LookupTable.GetOccurences(keyObject);
|
||||
if (occurences.Count > 1)
|
||||
{
|
||||
GUI.color = occurences[0] == actualIndex ? Color.yellow : Color.red;
|
||||
}
|
||||
if (!SerializedCollectionsUtility.IsValidKey(keyObject))
|
||||
{
|
||||
GUI.color = Color.red;
|
||||
}
|
||||
}
|
||||
|
||||
var keyDisplayData = _propertyData.GetElementData(SerializedDictionaryDrawer.KeyFlag);
|
||||
DrawGroupedElement(keyRect, 20, keyProperty, keyDisplayData.EffectiveDisplayType);
|
||||
|
||||
EditorGUI.DrawRect(lineRect, new Color(36 / 255f, 36 / 255f, 36 / 255f));
|
||||
GUI.color = prevColor;
|
||||
|
||||
var valueDisplayData = _propertyData.GetElementData(SerializedDictionaryDrawer.ValueFlag);
|
||||
DrawGroupedElement(valueRect, lineRightSpace, valueProperty, valueDisplayData.EffectiveDisplayType);
|
||||
}
|
||||
|
||||
private void DrawGroupedElement(Rect rect, int spaceForProperty, SerializedProperty property, DisplayType displayType)
|
||||
{
|
||||
using (new LabelWidth(rect.width * 0.4f))
|
||||
{
|
||||
float height = SCEditorUtility.CalculateHeight(property.Copy(), displayType);
|
||||
Rect groupRect = rect.CutLeft(-spaceForProperty).WithHeight(height);
|
||||
GUI.BeginGroup(groupRect);
|
||||
|
||||
Rect elementRect = new Rect(spaceForProperty, 0, rect.width, height);
|
||||
_activeState.DrawElement(elementRect, property, displayType);
|
||||
|
||||
DrawInvisibleProperty(rect.WithWidth(spaceForProperty), property);
|
||||
|
||||
GUI.EndGroup();
|
||||
}
|
||||
}
|
||||
|
||||
internal static void DrawInvisibleProperty(Rect rect, SerializedProperty property)
|
||||
{
|
||||
const int propertyOffset = 5;
|
||||
|
||||
GUI.BeginClip(rect.CutLeft(-propertyOffset));
|
||||
EditorGUI.BeginProperty(rect, GUIContent.none, property);
|
||||
EditorGUI.EndProperty();
|
||||
GUI.EndClip();
|
||||
}
|
||||
|
||||
internal static void DrawElement(Rect rect, SerializedProperty property, DisplayType displayType, Action<SerializedProperty> BeforeDrawingCallback = null, Action<SerializedProperty> AfterDrawingCallback = null)
|
||||
{
|
||||
switch (displayType)
|
||||
{
|
||||
case DisplayType.Property:
|
||||
BeforeDrawingCallback?.Invoke(property);
|
||||
EditorGUI.PropertyField(rect, property, true);
|
||||
AfterDrawingCallback?.Invoke(property);
|
||||
break;
|
||||
case DisplayType.PropertyNoLabel:
|
||||
BeforeDrawingCallback?.Invoke(property);
|
||||
EditorGUI.PropertyField(rect, property, GUIContent.none, true);
|
||||
AfterDrawingCallback?.Invoke(property);
|
||||
break;
|
||||
case DisplayType.List:
|
||||
Rect childRect = rect.WithHeight(0);
|
||||
foreach (SerializedProperty prop in SCEditorUtility.GetChildren(property.Copy()))
|
||||
{
|
||||
childRect = childRect.AppendDown(EditorGUI.GetPropertyHeight(prop, true));
|
||||
BeforeDrawingCallback?.Invoke(prop);
|
||||
EditorGUI.PropertyField(childRect, prop, true);
|
||||
AfterDrawingCallback?.Invoke(prop);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAdd(ReorderableList list)
|
||||
{
|
||||
int targetIndex = list.selectedIndices.Count > 0 && list.selectedIndices[0] >= 0 ? list.selectedIndices[0] : 0;
|
||||
int actualTargetIndex = targetIndex < _pagedIndices.Count ? _pagedIndices[targetIndex] : 0;
|
||||
_activeState.InserElementAt(actualTargetIndex);
|
||||
}
|
||||
|
||||
private void OnReorder(ReorderableList list, int oldIndex, int newIndex)
|
||||
{
|
||||
UpdatePaging();
|
||||
ListProperty.MoveArrayElement(_pagedIndices[oldIndex], _pagedIndices[newIndex]);
|
||||
}
|
||||
|
||||
private void OnRemove(ReorderableList list)
|
||||
{
|
||||
_activeState.RemoveElementAt(_pagedIndices[list.index]);
|
||||
UpdatePaging();
|
||||
//int actualIndex = _pagedIndices[list.index];
|
||||
//ListProperty.DeleteArrayElementAtIndex(actualIndex);
|
||||
//UpdatePaging();
|
||||
//if (actualIndex >= ListProperty.minArraySize)
|
||||
// list.index = _pagedIndices.Count - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c3b210db82056a4a93c337b45da413b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7691132b92786be418f91bf39639db87
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,60 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.IO;
|
||||
using System;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor
|
||||
{
|
||||
public sealed class EditorUserSettings : ScriptableObject
|
||||
{
|
||||
[SerializeField]
|
||||
private bool _alwaysShowSearch = false;
|
||||
[SerializeField, Range(1, 10)]
|
||||
private int _pageCountForSearch = 1;
|
||||
[SerializeField, Min(1)]
|
||||
private int _elementsPerPage = 10;
|
||||
|
||||
public bool AlwaysShowSearch => _alwaysShowSearch;
|
||||
public int PageCountForSearch => _pageCountForSearch;
|
||||
public int ElementsPerPage => _elementsPerPage;
|
||||
|
||||
private static EditorUserSettings _instance;
|
||||
|
||||
private const string _filePath = "UserSettings/SerializedCollectionsEditorSettings.asset";
|
||||
|
||||
public static EditorUserSettings Get()
|
||||
{
|
||||
if (_instance == null)
|
||||
{
|
||||
_instance = CreateInstance<EditorUserSettings>();
|
||||
LoadInto(_instance);
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
||||
private static void LoadInto(EditorUserSettings settings)
|
||||
{
|
||||
if (!File.Exists(_filePath)) return;
|
||||
|
||||
try
|
||||
{
|
||||
string json = File.ReadAllText(_filePath);
|
||||
EditorJsonUtility.FromJsonOverwrite(json, settings);
|
||||
return;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Save()
|
||||
{
|
||||
string contents = EditorJsonUtility.ToJson(Get());
|
||||
File.WriteAllText(_filePath, contents);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 21353c5f0548cba4a98029e0c433a0dc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,82 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.AnimatedValues;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor
|
||||
{
|
||||
public class EditorUserSettingsProvider : SettingsProvider
|
||||
{
|
||||
public const string PreferencesPath = "Preferences/Serialized Collections";
|
||||
|
||||
private SerializedObject _serializedObject;
|
||||
private SerializedProperty _alwaysShowSearch;
|
||||
private SerializedProperty _pageCountForSearch;
|
||||
private SerializedProperty _elementsPerPage;
|
||||
private AnimBool _searchAnimBool;
|
||||
|
||||
class Styles
|
||||
{
|
||||
}
|
||||
|
||||
[SettingsProvider]
|
||||
public static SettingsProvider CreateProvider()
|
||||
{
|
||||
var provider = new EditorUserSettingsProvider(PreferencesPath, SettingsScope.User);
|
||||
|
||||
provider.keywords = GetSearchKeywordsFromGUIContentProperties<Styles>();
|
||||
return provider;
|
||||
}
|
||||
|
||||
public EditorUserSettingsProvider(string path, SettingsScope scope = SettingsScope.User) : base(path, scope) { }
|
||||
|
||||
public static bool IsSettingsAvailable() => EditorUserSettings.Get() != null;
|
||||
|
||||
public override void OnActivate(string searchContext, VisualElement rootElement)
|
||||
{
|
||||
EnsureSerializedObjectExists();
|
||||
}
|
||||
|
||||
private void EnsureSerializedObjectExists()
|
||||
{
|
||||
if (_serializedObject == null)
|
||||
{
|
||||
_searchAnimBool = new AnimBool();
|
||||
_searchAnimBool.valueChanged.AddListener(new UnityAction(Repaint));
|
||||
_serializedObject = new SerializedObject(EditorUserSettings.Get());
|
||||
_alwaysShowSearch = _serializedObject.FindProperty("_alwaysShowSearch");
|
||||
_pageCountForSearch = _serializedObject.FindProperty("_pageCountForSearch");
|
||||
_elementsPerPage = _serializedObject.FindProperty("_elementsPerPage");
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnGUI(string searchContext)
|
||||
{
|
||||
EnsureSerializedObjectExists();
|
||||
|
||||
EditorGUI.indentLevel = 1;
|
||||
|
||||
_serializedObject.UpdateIfRequiredOrScript();
|
||||
|
||||
EditorGUILayout.PropertyField(_alwaysShowSearch);
|
||||
_searchAnimBool.target = !_alwaysShowSearch.boolValue;
|
||||
using (var group = new EditorGUILayout.FadeGroupScope(_searchAnimBool.faded))
|
||||
{
|
||||
if (group.visible)
|
||||
{
|
||||
EditorGUILayout.PropertyField(_pageCountForSearch);
|
||||
}
|
||||
}
|
||||
EditorGUILayout.PropertyField(_elementsPerPage);
|
||||
|
||||
bool changed =_serializedObject.ApplyModifiedProperties();
|
||||
if (changed)
|
||||
{
|
||||
EditorUserSettings.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01b95baf6e99cff43a84c4ba42557db4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b07f70f96e8585f45976044096080ecd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,55 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using static AYellowpaper.SerializedCollections.Editor.SerializedDictionaryDrawer;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor.States
|
||||
{
|
||||
internal class DefaultListState : ListState
|
||||
{
|
||||
public override int ListSize => Drawer.ListProperty.minArraySize;
|
||||
|
||||
public DefaultListState(SerializedDictionaryInstanceDrawer serializedDictionaryDrawer) : base(serializedDictionaryDrawer)
|
||||
{
|
||||
}
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
Drawer.ReorderableList.draggable = true;
|
||||
}
|
||||
|
||||
public override void OnExit()
|
||||
{
|
||||
}
|
||||
|
||||
public override ListState OnUpdate()
|
||||
{
|
||||
if (Drawer.SearchText.Length > 0)
|
||||
return Drawer.SearchState;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public override void DrawElement(Rect rect, SerializedProperty property, DisplayType displayType)
|
||||
{
|
||||
SerializedDictionaryInstanceDrawer.DrawElement(rect, property, displayType);
|
||||
}
|
||||
|
||||
public override SerializedProperty GetPropertyAtIndex(int index)
|
||||
{
|
||||
return Drawer.ListProperty.GetArrayElementAtIndex(index);
|
||||
}
|
||||
|
||||
public override void RemoveElementAt(int index)
|
||||
{
|
||||
Drawer.ListProperty.DeleteArrayElementAtIndex(index);
|
||||
}
|
||||
|
||||
public override void InserElementAt(int index)
|
||||
{
|
||||
Drawer.ListProperty.InsertArrayElementAtIndex(index);
|
||||
Drawer.ListProperty.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 803188ced5ea71c41b6079f7ae375573
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,34 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using static AYellowpaper.SerializedCollections.Editor.SerializedDictionaryDrawer;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor.States
|
||||
{
|
||||
internal abstract class ListState
|
||||
{
|
||||
public abstract int ListSize { get; }
|
||||
public virtual string NoElementsText => "List is Empty.";
|
||||
|
||||
public readonly SerializedDictionaryInstanceDrawer Drawer;
|
||||
|
||||
public ListState(SerializedDictionaryInstanceDrawer serializedDictionaryDrawer)
|
||||
{
|
||||
Drawer = serializedDictionaryDrawer;
|
||||
}
|
||||
|
||||
public abstract SerializedProperty GetPropertyAtIndex(int index);
|
||||
public abstract ListState OnUpdate();
|
||||
public abstract void OnEnter();
|
||||
public abstract void OnExit();
|
||||
public abstract void DrawElement(Rect rect, SerializedProperty property, DisplayType displayType);
|
||||
public abstract void RemoveElementAt(int index);
|
||||
public abstract void InserElementAt(int index);
|
||||
|
||||
public virtual float GetHeightAtIndex(int index, bool drawKeyAsList, bool drawValueAsList)
|
||||
{
|
||||
return SerializedDictionaryInstanceDrawer.CalculateHeightOfElement(GetPropertyAtIndex(index), drawKeyAsList, drawValueAsList);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b4752173882f944eb16a5720a22f3e9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,109 @@
|
||||
using AYellowpaper.SerializedCollections.Editor.Search;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using static AYellowpaper.SerializedCollections.Editor.SerializedDictionaryDrawer;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor.States
|
||||
{
|
||||
internal class SearchListState : ListState
|
||||
{
|
||||
public override int ListSize => _searchResults.Count;
|
||||
public override string NoElementsText => "No Results";
|
||||
public bool OnlyShowMatchingValues { get; set; }
|
||||
|
||||
private string _lastSearch = string.Empty;
|
||||
private List<SearchResultEntry> _searchResults = new List<SearchResultEntry>();
|
||||
private HashSet<string> _foundProperties;
|
||||
private Color _previousColor;
|
||||
|
||||
public SearchListState(SerializedDictionaryInstanceDrawer serializedDictionaryDrawer) : base(serializedDictionaryDrawer)
|
||||
{
|
||||
}
|
||||
|
||||
public override void DrawElement(Rect rect, SerializedProperty property, DisplayType displayType)
|
||||
{
|
||||
SerializedDictionaryInstanceDrawer.DrawElement(rect, property, displayType, BeforeDrawingProperty, AfterDrawingProperty);
|
||||
}
|
||||
|
||||
private void BeforeDrawingProperty(SerializedProperty obj)
|
||||
{
|
||||
_previousColor = GUI.backgroundColor;
|
||||
if (_foundProperties.Contains(obj.propertyPath))
|
||||
{
|
||||
GUI.backgroundColor = Color.blue;
|
||||
}
|
||||
}
|
||||
|
||||
private void AfterDrawingProperty(SerializedProperty obj)
|
||||
{
|
||||
GUI.backgroundColor = _previousColor;
|
||||
}
|
||||
|
||||
public override void OnEnter()
|
||||
{
|
||||
Drawer.ReorderableList.draggable = false;
|
||||
UpdateSearch();
|
||||
}
|
||||
|
||||
public override void OnExit()
|
||||
{
|
||||
}
|
||||
|
||||
public override ListState OnUpdate()
|
||||
{
|
||||
if (Drawer.SearchText.Length == 0)
|
||||
return Drawer.DefaultState;
|
||||
|
||||
UpdateSearch();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private void UpdateSearch()
|
||||
{
|
||||
if (_lastSearch != Drawer.SearchText)
|
||||
{
|
||||
_lastSearch = Drawer.SearchText;
|
||||
PerformSearch(Drawer.SearchText);
|
||||
}
|
||||
}
|
||||
|
||||
public void PerformSearch(string searchString)
|
||||
{
|
||||
var query = new SearchQuery(Matchers.RegisteredMatchers);
|
||||
query.SearchString = searchString;
|
||||
_searchResults.Clear();
|
||||
_searchResults.AddRange(query.ApplyToArrayProperty(Drawer.ListProperty));
|
||||
|
||||
_foundProperties = _searchResults.SelectMany(x => x.MatchingResults, (x, y) => y.Property.propertyPath).ToHashSet();
|
||||
}
|
||||
|
||||
public override SerializedProperty GetPropertyAtIndex(int index)
|
||||
{
|
||||
return _searchResults[index].Property;
|
||||
}
|
||||
|
||||
public override float GetHeightAtIndex(int index, bool drawKeyAsList, bool drawValueAsList)
|
||||
{
|
||||
return base.GetHeightAtIndex(index, drawKeyAsList, drawValueAsList);
|
||||
}
|
||||
|
||||
public override void RemoveElementAt(int index)
|
||||
{
|
||||
var indexToDelete = _searchResults[index].Index;
|
||||
Drawer.ListProperty.DeleteArrayElementAtIndex(indexToDelete);
|
||||
PerformSearch(_lastSearch);
|
||||
}
|
||||
|
||||
public override void InserElementAt(int index)
|
||||
{
|
||||
var indexToAdd = _searchResults[index].Index;
|
||||
Drawer.ListProperty.InsertArrayElementAtIndex(indexToAdd);
|
||||
PerformSearch(_lastSearch);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1ed2b1abf79f0c74c8224a423ec3123c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ce09595c06b9854abdd9a22a57e16bd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor
|
||||
{
|
||||
public struct GUIEnabledScope : IDisposable
|
||||
{
|
||||
public readonly bool PreviouslyEnabled;
|
||||
|
||||
public GUIEnabledScope(bool enabled)
|
||||
{
|
||||
PreviouslyEnabled = GUI.enabled;
|
||||
GUI.enabled = enabled;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GUI.enabled = PreviouslyEnabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c671c12e9de22d042be004c62b6f4158
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor
|
||||
{
|
||||
public struct LabelWidth : IDisposable
|
||||
{
|
||||
public float PreviousWidth { get; }
|
||||
|
||||
public LabelWidth(float width)
|
||||
{
|
||||
PreviousWidth = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = width;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
EditorGUIUtility.labelWidth = PreviousWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fd75bc249daa39f4e832a3dab9c23c82
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,41 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor
|
||||
{
|
||||
public static class RectUtility
|
||||
{
|
||||
public static Rect WithX(this Rect rect, float x) => new Rect(x, rect.y, rect.width, rect.height);
|
||||
public static Rect WithY(this Rect rect, float y) => new Rect(rect.x, y, rect.width, rect.height);
|
||||
public static Rect WithWidth(this Rect rect, float width) => new Rect(rect.x, rect.y, width, rect.height);
|
||||
public static Rect WithHeight(this Rect rect, float height) => new Rect(rect.x, rect.y, rect.width, height);
|
||||
public static Rect WithPosition(this Rect rect, Vector2 position) => new Rect(position, rect.size);
|
||||
public static Rect WithPosition(this Rect rect, float x, float y) => new Rect(new Vector2(x, y), rect.size);
|
||||
public static Rect WithSize(this Rect rect, Vector2 size) => new Rect(rect.position, size);
|
||||
public static Rect WithSize(this Rect rect, float width, float height) => new Rect(rect.position, new Vector2(width, height));
|
||||
|
||||
public static Rect WithXAndWidth(this Rect rect, float x, float width) => new Rect(x, rect.y, width, rect.height);
|
||||
public static Rect WithYAndHeight(this Rect rect, float y, float height) => new Rect(rect.x, y, rect.width, height);
|
||||
|
||||
public static Rect AppendRight(this Rect rect, float width) => new Rect(rect.x + rect.width, rect.y, width, rect.height);
|
||||
public static Rect AppendRight(this Rect rect, float width, float space) => new Rect(rect.x + rect.width + space, rect.y, width, rect.height);
|
||||
public static Rect AppendLeft(this Rect rect, float width) => new Rect(rect.x - width, rect.y, width, rect.height);
|
||||
public static Rect AppendLeft(this Rect rect, float width, float space) => new Rect(rect.x - space - width, rect.y, width, rect.height);
|
||||
public static Rect AppendUp(this Rect rect, float height) => new Rect(rect.x, rect.y - height, rect.width, height);
|
||||
public static Rect AppendUp(this Rect rect, float height, float space) => new Rect(rect.x, rect.y - space - height, rect.width, height);
|
||||
public static Rect AppendDown(this Rect rect, float height) => new Rect(rect.x, rect.y + rect.height, rect.width, height);
|
||||
public static Rect AppendDown(this Rect rect, float height, float space) => new Rect(rect.x, rect.y + rect.height + space, rect.width, height);
|
||||
|
||||
public static Rect CutLeft(this Rect rect, float width) => new Rect(rect.x + width, rect.y, rect.width - width, rect.height);
|
||||
public static Rect CutRight(this Rect rect, float width) => new Rect(rect.x, rect.y, rect.width - width, rect.height);
|
||||
public static Rect CutTop(this Rect rect, float height) => new Rect(rect.x, rect.y + height, rect.width, rect.height - height);
|
||||
public static Rect CutBottom(this Rect rect, float height) => new Rect(rect.x, rect.y, rect.width, rect.height - height);
|
||||
|
||||
public static Rect CutHorizontal(this Rect rect, float leftAndRight) => CutHorizontal(rect, leftAndRight, leftAndRight);
|
||||
public static Rect CutHorizontal(this Rect rect, float left, float right) => new Rect(rect.x + left, rect.y, rect.width - left - right, rect.height);
|
||||
public static Rect CutVertical(this Rect rect, float topAndBottom) => CutVertical(rect, topAndBottom, topAndBottom);
|
||||
public static Rect CutVertical(this Rect rect, float top, float bottom) => new Rect(rect.x, rect.y + top, rect.width, rect.height - top - bottom);
|
||||
|
||||
public static Rect Cut(this Rect rect, float topBottom, float leftRight) => Cut(rect, topBottom, leftRight, topBottom, leftRight);
|
||||
public static Rect Cut(this Rect rect, float top, float right, float bottom, float left) => new Rect(rect.x + left, rect.y + top, rect.width - left - right, rect.height - top - bottom);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 68261ebef89d61441a35961731b0a083
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,201 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using System.Linq;
|
||||
using AYellowpaper.SerializedCollections.Editor.Data;
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor
|
||||
{
|
||||
internal static class SCEditorUtility
|
||||
{
|
||||
public const string EditorPrefsPrefix = "SC_";
|
||||
public const bool KeyFlag = true;
|
||||
public const bool ValueFlag = false;
|
||||
|
||||
public static bool GetPersistentBool(string path, bool defaultValue)
|
||||
{
|
||||
return EditorPrefs.GetBool(EditorPrefsPrefix + path, defaultValue);
|
||||
}
|
||||
|
||||
public static bool HasKey(string path)
|
||||
{
|
||||
return EditorPrefs.HasKey( EditorPrefsPrefix + path );
|
||||
}
|
||||
|
||||
public static void SetPersistentBool(string path, bool value)
|
||||
{
|
||||
EditorPrefs.SetBool(EditorPrefsPrefix + path, value);
|
||||
}
|
||||
|
||||
public static float CalculateHeight(SerializedProperty property, DisplayType displayType)
|
||||
{
|
||||
return CalculateHeight(property, displayType == DisplayType.List ? true : false);
|
||||
}
|
||||
|
||||
public static float CalculateHeight(SerializedProperty property, bool drawAsList)
|
||||
{
|
||||
if (drawAsList)
|
||||
{
|
||||
float height = 0;
|
||||
foreach (SerializedProperty child in GetChildren(property))
|
||||
height += EditorGUI.GetPropertyHeight(child, true);
|
||||
return height;
|
||||
}
|
||||
|
||||
return EditorGUI.GetPropertyHeight(property, true);
|
||||
}
|
||||
|
||||
public static IEnumerable<SerializedProperty> GetChildren(SerializedProperty property, bool recursive = false)
|
||||
{
|
||||
if (!property.hasVisibleChildren)
|
||||
{
|
||||
yield return property;
|
||||
yield break;
|
||||
}
|
||||
|
||||
SerializedProperty end = property.GetEndProperty();
|
||||
property.NextVisible(true);
|
||||
do
|
||||
{
|
||||
yield return property;
|
||||
} while (property.NextVisible(recursive) && !SerializedProperty.EqualContents(property, end));
|
||||
}
|
||||
|
||||
public static int GetActualArraySize(SerializedProperty arrayProperty)
|
||||
{
|
||||
return GetChildren(arrayProperty).Count() - 1;
|
||||
}
|
||||
|
||||
public static PropertyData GetPropertyData(SerializedProperty property)
|
||||
{
|
||||
var data = new PropertyData();
|
||||
var json = EditorPrefs.GetString(EditorPrefsPrefix + property.propertyPath, null);
|
||||
if (json != null)
|
||||
EditorJsonUtility.FromJsonOverwrite(json, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
public static void SavePropertyData(SerializedProperty property, PropertyData propertyData)
|
||||
{
|
||||
var json = EditorJsonUtility.ToJson(propertyData);
|
||||
EditorPrefs.SetString(EditorPrefsPrefix + property.propertyPath, json);
|
||||
}
|
||||
|
||||
public static bool ShouldShowSearch(int pages)
|
||||
{
|
||||
var settings = EditorUserSettings.Get();
|
||||
return settings.AlwaysShowSearch ? true : pages >= settings.PageCountForSearch;
|
||||
}
|
||||
|
||||
public static bool HasDrawerForType(Type type, bool isPropertyManagedReferenceType)
|
||||
{
|
||||
Type attributeUtilityType = typeof(SerializedProperty).Assembly.GetType("UnityEditor.ScriptAttributeUtility");
|
||||
if (attributeUtilityType == null)
|
||||
return false;
|
||||
var getDrawerMethod = attributeUtilityType.GetMethod("GetDrawerTypeForType", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
if (getDrawerMethod == null)
|
||||
return false;
|
||||
|
||||
#if UNITY_2022_3_OR_NEWER
|
||||
if (getDrawerMethod.GetParameters().Length == 2)
|
||||
{
|
||||
return getDrawerMethod.Invoke(type, new object[] { type, isPropertyManagedReferenceType }) != null;
|
||||
} else if(getDrawerMethod.GetParameters().Length == 3)
|
||||
{
|
||||
return getDrawerMethod.Invoke(type, new object[] { type, new Type[0], isPropertyManagedReferenceType }) != null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return getDrawerMethod.Invoke(type, new object[] { type }) != null;
|
||||
}
|
||||
#else
|
||||
return getDrawerMethod.Invoke(type, new object[] { type }) != null;
|
||||
#endif
|
||||
}
|
||||
|
||||
internal static void AddGenericMenuItem(GenericMenu genericMenu, bool isOn, bool isEnabled, GUIContent content, GenericMenu.MenuFunction action)
|
||||
{
|
||||
if (isEnabled)
|
||||
genericMenu.AddItem(content, isOn, action);
|
||||
else
|
||||
genericMenu.AddDisabledItem(content);
|
||||
}
|
||||
|
||||
internal static void AddGenericMenuItem(GenericMenu genericMenu, bool isOn, bool isEnabled, GUIContent content, GenericMenu.MenuFunction2 action, object userData)
|
||||
{
|
||||
if (isEnabled)
|
||||
genericMenu.AddItem(content, isOn, action, userData);
|
||||
else
|
||||
genericMenu.AddDisabledItem(content);
|
||||
}
|
||||
|
||||
internal static bool TryGetTypeFromProperty(SerializedProperty property, out Type type)
|
||||
{
|
||||
try
|
||||
{
|
||||
var classType = typeof(EditorGUI).Assembly.GetType("UnityEditor.ScriptAttributeUtility");
|
||||
var methodInfo = classType.GetMethod("GetFieldInfoFromProperty", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
var parameters = new object[] { property, null };
|
||||
methodInfo.Invoke(null, parameters);
|
||||
type = (Type) parameters[1];
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
type = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static object GetPropertyValue(SerializedProperty prop, object target)
|
||||
{
|
||||
var path = prop.propertyPath.Replace(".Array.data[", "[");
|
||||
var elements = path.Split('.');
|
||||
foreach (var element in elements.Take(elements.Length - 1))
|
||||
{
|
||||
if (element.Contains("["))
|
||||
{
|
||||
var elementName = element.Substring(0, element.IndexOf("["));
|
||||
var index = Convert.ToInt32(element.Substring(element.IndexOf("[")).Replace("[", "").Replace("]", ""));
|
||||
target = GetValue(target, elementName, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
target = GetValue(target, element);
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
public static object GetValue(object source, string name)
|
||||
{
|
||||
if (source == null)
|
||||
return null;
|
||||
var type = source.GetType();
|
||||
var f = type.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||
if (f == null)
|
||||
{
|
||||
var p = type.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
||||
if (p == null)
|
||||
return null;
|
||||
return p.GetValue(source, null);
|
||||
}
|
||||
return f.GetValue(source);
|
||||
}
|
||||
|
||||
public static object GetValue(object source, string name, int index)
|
||||
{
|
||||
var enumerable = GetValue(source, name) as IEnumerable;
|
||||
var enm = enumerable.GetEnumerator();
|
||||
while (index-- >= 0)
|
||||
enm.MoveNext();
|
||||
return enm.Current;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 138277cf2e7d2cd4e99c3cd7e2ecaaed
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AYellowpaper.SerializedCollections.Editor
|
||||
{
|
||||
internal static class SCEnumUtility
|
||||
{
|
||||
private static Dictionary<Type, EnumCache> _cache = new Dictionary<Type, EnumCache>();
|
||||
|
||||
internal static EnumCache GetEnumCache(Type enumType)
|
||||
{
|
||||
if (_cache.TryGetValue(enumType, out var val))
|
||||
return val;
|
||||
|
||||
try
|
||||
{
|
||||
var classType = typeof(EditorGUI).Assembly.GetType("UnityEditor.EnumDataUtility");
|
||||
var methodInfo = classType.GetMethod("GetCachedEnumData", BindingFlags.Static | BindingFlags.NonPublic);
|
||||
var parameters = new object[] { enumType, true };
|
||||
var result = methodInfo.Invoke(null, parameters);
|
||||
var flagValues = (int[])result.GetType().GetField("flagValues").GetValue(result);
|
||||
var names = (string[])result.GetType().GetField("names").GetValue(result);
|
||||
var cache = new EnumCache(enumType, flagValues, names);
|
||||
_cache.Add(enumType, cache);
|
||||
return cache;
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal record EnumCache
|
||||
{
|
||||
public readonly Type Type;
|
||||
public readonly bool IsFlag;
|
||||
public readonly int Length;
|
||||
public readonly int[] FlagValues;
|
||||
public readonly string[] Names;
|
||||
|
||||
private readonly Dictionary<int, string[]> _namesByValue = new Dictionary<int, string[]>();
|
||||
|
||||
public EnumCache(Type type, int[] flagValues, string[] displayNames)
|
||||
{
|
||||
Type = type;
|
||||
FlagValues = flagValues;
|
||||
Names = displayNames;
|
||||
Length = flagValues.Length;
|
||||
IsFlag = Type.IsDefined(typeof(FlagsAttribute));
|
||||
}
|
||||
|
||||
internal string[] GetNamesForValue(int value)
|
||||
{
|
||||
if (_namesByValue.TryGetValue(value, out var list))
|
||||
return list;
|
||||
|
||||
string[] array = IsFlag ? GetFlagValues(value).ToArray() : new[] { GetEnumValue(value) };
|
||||
|
||||
_namesByValue.Add(value, array);
|
||||
return array;
|
||||
}
|
||||
|
||||
private string GetEnumValue(int value)
|
||||
{
|
||||
for (int i = 0; i < Length; i++)
|
||||
{
|
||||
if (FlagValues[i] == value)
|
||||
return Names[i];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetFlagValues(int flagValue)
|
||||
{
|
||||
if (flagValue == 0)
|
||||
{
|
||||
yield return FlagValues[0] == 0 ? Names[0] : "Nothing";
|
||||
yield break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < Length; i++)
|
||||
{
|
||||
int fv = FlagValues[i];
|
||||
if ((fv & flagValue) == fv && fv != 0)
|
||||
yield return Names[i];
|
||||
}
|
||||
|
||||
if (FlagValues[Length - 1] != -1 && flagValue == -1)
|
||||
yield return "Everything";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 76def6672c756704bac4efd5a3625113
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user