First commit for private source control. Older commits available on Github.

This commit is contained in:
2026-03-26 12:52:52 +00:00
parent a04c602626
commit 2d449c4a17
2176 changed files with 408185 additions and 0 deletions

View File

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

View File

@@ -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
}

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 234340c04eed5674a988bc6ebde7d248
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/AYellowpaper.SerializedCollections.Editor.asmdef
uploadId: 632226

View File

@@ -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

View File

@@ -0,0 +1,177 @@
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:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Assets/BurgerMenu@2x.png
uploadId: 632226

View File

@@ -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;
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: df6c2ef835e40c94c976442569324029
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
disableValidation: 0
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Assets/KeysGeneratorSelectorWindow.uss
uploadId: 632226

View File

@@ -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&amp;guid=df6c2ef835e40c94c976442569324029&amp;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>

View File

@@ -0,0 +1,17 @@
fileFormatVersion: 2
guid: 681c8a924c8b1e14b9fe53bb7397ec3d
ScriptedImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 2
userData:
assetBundleName:
assetBundleVariant:
script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Assets/KeysGeneratorSelectorWindow.uxml
uploadId: 632226

View File

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

View File

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

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 650a80186cc93b54aa5627197c23ea6e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Data/ElementData.cs
uploadId: 632226

View File

@@ -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;
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 12edfc8006691b7498459540b832c5eb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Data/ElementSettings.cs
uploadId: 632226

View File

@@ -0,0 +1,44 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace AYellowpaper.SerializedCollections.Editor.Data
{
[System.Serializable]
internal class PropertyData
{
[SerializeField]
private float _keyLabelWidth;
[SerializeField]
private ElementData _keyData;
[SerializeField]
private ElementData _valueData;
[SerializeField]
private bool _alwaysShowSearch = false;
public bool AlwaysShowSearch
{
get => _alwaysShowSearch;
set => _alwaysShowSearch = value;
}
public float KeyLabelWidth
{
get => _keyLabelWidth;
set => _keyLabelWidth = 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);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: ba2d792dfc6653e46bee7c027202acd3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Data/PropertyData.cs
uploadId: 632226

View File

@@ -0,0 +1,13 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace AYellowpaper.SerializedCollections.Editor
{
public enum DisplayType
{
Property,
PropertyNoLabel,
List
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 37ee13dd67b545846b6b063923812943
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/DisplayType.cs
uploadId: 632226

View File

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

View File

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

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: d639de5d36bbeea4496c97cc3f1f4e81
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/Implementors/EnumGenerator.cs
uploadId: 632226

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: a4203f3a582fa874fb035633bd9892b4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/Implementors/IntRangeGenerator.cs
uploadId: 632226

View File

@@ -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;
}
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 99302d4ff0ae27b4898ced57890ed32d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/Implementors/IntSteppingGenerator.cs
uploadId: 632226

View File

@@ -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);
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 08149f25a1b9c5e48a224a7c4d31a154
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/KeyListGenerator.cs
uploadId: 632226

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 0f6065c936425ab478ecc8a8cf30d38f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/KeyListGeneratorAttribute.cs
uploadId: 632226

View File

@@ -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];
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 7936217ae19613d4bb5e46e73a4a587c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/KeyListGeneratorCache.cs
uploadId: 632226

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 8992145ced672cd46a425fb2590b80bb
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/KeyListGeneratorData.cs
uploadId: 632226

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 211518bea98ede643af247b6295984bd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/KeyListGeneratorEditor.cs
uploadId: 632226

View File

@@ -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];
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: df07fe6d161e3334083f837a066dd949
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/KeyListGeneratorSelectorWindow.cs
uploadId: 632226

View File

@@ -0,0 +1,10 @@
namespace AYellowpaper.SerializedCollections
{
public enum ModificationType
{
None,
Add,
Remove,
Confine,
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: fc2030edc0a04b74a8642773bd8c98fd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/KeyListGenerators/ModificationType.cs
uploadId: 632226

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: f35ac465aece4064582910fc2c206682
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/PagingElement.cs
uploadId: 632226

View File

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

View File

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

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: f2cf86e71fb0ff04f96ac71dd9961962
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Search/Matchers/EnumMatcher.cs
uploadId: 632226

View File

@@ -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);
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 218ea85e2d8480a498e8647aad524c8d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Search/Matchers/Matcher.cs
uploadId: 632226

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 94535827bd107e549baa23442df58bef
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Search/Matchers/Matchers.cs
uploadId: 632226

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: cc3ee6ec420212140bd3a86688d548de
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Search/Matchers/NumericMatcher.cs
uploadId: 632226

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: be8bbc3471f8ad04b8da6366285443c6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Search/Matchers/StringMatcher.cs
uploadId: 632226

View File

@@ -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}";
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 33b4e4c67054c4d488fa66ff14bd3120
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Search/PropertySearchResult.cs
uploadId: 632226

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: c87dd0caf3c44ed4e82896aa40bf1b96
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Search/SearchQuery.cs
uploadId: 632226

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: d8455216ad2701d49b6dfec7f98ca88b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Search/SearchResultEntry.cs
uploadId: 632226

View File

@@ -0,0 +1,65 @@
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
{
#if ODIN_INSPECTOR
[Sirenix.OdinInspector.Editor.DrawerPriority(Sirenix.OdinInspector.Editor.DrawerPriorityLevel.SuperPriority)]
#endif
[CustomPropertyDrawer(typeof(SerializedDictionary<,>), true)]
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);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 4ccfc6d910f95ca4f94b294a9a3a8872
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/SerializedDictionaryDrawer.cs
uploadId: 632226

View File

@@ -0,0 +1,728 @@
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 const float MinKeyValueLabelWidth = 40f;
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);
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();
CheckIfNewDictionary();
CheckPaging();
var elementsPerPage = EditorUserSettings.Get().ElementsPerPage;
int pageCount = Mathf.Max(1, Mathf.CeilToInt((float)DefaultState.ListSize / elementsPerPage));
ToggleSearchBar(_propertyData.AlwaysShowSearch ? true : SCEditorUtility.ShouldShowSearch(pageCount));
}
// TODO: This works for now, but isn't perfect. This checks if the serialized dictionary was reassigned with new(), simply by comparing the count. Should be instead done by reference equality in the future
private void CheckIfNewDictionary()
{
if (_singleEditingData.IsValid && _singleEditingData.LookupTable.GetCount() != _activeState.ListSize)
{
var dictionary = SCEditorUtility.GetPropertyValue(ListProperty, ListProperty.serializedObject.targetObject);
_singleEditingData.LookupTable = GetLookupTable(dictionary);
_singleEditingData.LookupTable.RecalculateOccurences();
}
}
private void InitializeSettingsIfNeeded()
{
void InitializeSettings(bool fieldFlag)
{
var dictionaryType = FindGenericBaseType(typeof(SerializedDictionary<,>), _fieldInfo.FieldType);
var genericArgs = dictionaryType.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 static Type FindGenericBaseType(Type generic, Type toCheck)
{
while (toCheck != null && toCheck != typeof(object))
{
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
if (generic == cur) {
return toCheck;
}
toCheck = toCheck.BaseType;
}
return null;
}
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 = OnDrawUnexpandedHeader;
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.HasDrawerForProperty(property, type);
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 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 OnDrawUnexpandedHeader(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();
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)
{
var width = GetDesiredKeyLabelWidth(rect.width, 22);
Rect leftRect = rect.WithWidth(width);
Rect rightRect = leftRect.AppendRight(rect.width - width);
if (_propertyData != null)
{
if (Event.current.type == EventType.Repaint)
{
_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);
}
var changeSizeRect = leftRect.AppendRight(5);
changeSizeRect.x -= 2;
EditorGUI.BeginChangeCheck();
float newWidth = SCEditorUtility.DoHorizontalScale(changeSizeRect, _propertyData.KeyLabelWidth > 0f ? _propertyData.KeyLabelWidth : width);
if (EditorGUI.EndChangeCheck())
{
_propertyData.KeyLabelWidth = Mathf.Max(newWidth, MinKeyValueLabelWidth);
SavePropertyData();
}
}
if (ListProperty.minArraySize > 0)
{
DoDisplayTypeToggle(leftRect, SerializedDictionaryDrawer.KeyFlag);
DoDisplayTypeToggle(rightRect, SerializedDictionaryDrawer.ValueFlag);
}
EditorGUI.DrawRect(rect.AppendDown(1, -1), SerializedDictionaryDrawer.BorderColor);
}
private float GetDesiredKeyLabelWidth(float maxWidth, float offset = 0f)
{
float desiredWidth = _propertyData is { KeyLabelWidth: > 0 }
? _propertyData.KeyLabelWidth
: EditorGUIUtility.labelWidth;
return Mathf.Clamp(desiredWidth + offset, MinKeyValueLabelWidth, maxWidth - MinKeyValueLabelWidth);
}
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, _propertyData.GetElementData(SerializedDictionaryDrawer.ValueFlag).EffectiveDisplayType == DisplayType.List);
}
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(GetDesiredKeyLabelWidth(rect.width) - 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();
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 9c3b210db82056a4a93c337b45da413b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/SerializedDictionaryInstanceDrawer.cs
uploadId: 632226

View File

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

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 21353c5f0548cba4a98029e0c433a0dc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Settings/EditorUserSettings.cs
uploadId: 632226

View File

@@ -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();
}
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 01b95baf6e99cff43a84c4ba42557db4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Settings/EditorUserSettingsProvider.cs
uploadId: 632226

View File

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

View File

@@ -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();
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 803188ced5ea71c41b6079f7ae375573
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/States/DefaultListState.cs
uploadId: 632226

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 4b4752173882f944eb16a5720a22f3e9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/States/ListState.cs
uploadId: 632226

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 1ed2b1abf79f0c74c8224a423ec3123c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/States/SearchListState.cs
uploadId: 632226

View File

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

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: c671c12e9de22d042be004c62b6f4158
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Utility/GUIEnabledScope.cs
uploadId: 632226

View File

@@ -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;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: fd75bc249daa39f4e832a3dab9c23c82
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Utility/LabelWidth.cs
uploadId: 632226

View File

@@ -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);
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 68261ebef89d61441a35961731b0a083
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Utility/RectUtility.cs
uploadId: 632226

View File

@@ -0,0 +1,245 @@
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 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 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 HasDrawerForProperty(SerializedProperty property, Type type)
{
Type attributeUtilityType = typeof(SerializedProperty).Assembly.GetType("UnityEditor.ScriptAttributeUtility");
if (attributeUtilityType == null)
return false;
var getDrawerMethod = attributeUtilityType.GetMethod("GetDrawerTypeForPropertyAndType", BindingFlags.Static | BindingFlags.NonPublic);
if (getDrawerMethod == null)
return false;
return getDrawerMethod.Invoke(null, new object[] { property, type }) != null;
}
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;
}
}
internal static float DoHorizontalScale(Rect rect, float value)
{
var controlId = GUIUtility.GetControlID(FocusType.Passive);
var isMovingMouse = Event.current.type == EventType.MouseDrag;
DoButtonControl(rect, controlId, false, false, GUIContent.none, GUIStyle.none);
if (controlId == GUIUtility.hotControl && isMovingMouse)
{
value += Event.current.delta.x;
GUI.changed = true;
}
EditorGUIUtility.AddCursorRect(rect, MouseCursor.ResizeHorizontal);
return value;
}
internal static bool DoButtonControl(Rect rect, int id, bool on, bool hover, GUIContent content, GUIStyle style)
{
Event current = Event.current;
switch (current.type)
{
case EventType.MouseDown:
if (HitTest(rect, current.mousePosition))
{
GUIUtility.hotControl = id;
current.Use();
}
break;
case EventType.MouseUp:
if (GUIUtility.hotControl == id)
{
GUIUtility.hotControl = 0;
current.Use();
if (HitTest(rect, current.mousePosition))
{
GUI.changed = true;
return !on;
}
}
break;
case EventType.MouseDrag:
if (GUIUtility.hotControl == id)
{
current.Use();
}
break;
case EventType.KeyDown:
bool flag = current.alt || current.shift || current.command || current.control;
if ((current.keyCode == KeyCode.Space || current.keyCode == KeyCode.Return || current.keyCode == KeyCode.KeypadEnter) && !flag && GUIUtility.keyboardControl == id)
{
current.Use();
GUI.changed = true;
return !on;
}
break;
case EventType.Repaint:
style.Draw(rect, content, id, on, hover);
break;
}
return on;
}
internal static bool HitTest(Rect rect, Vector2 point) => point.x >= rect.xMin && point.x < rect.xMax && point.y >= rect.yMin && point.y < rect.yMax;
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.GetFieldRecursive(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
if (f == null)
{
var p = type.GetPropertyRecursive(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;
}
private static FieldInfo GetFieldRecursive(this Type type, string name, BindingFlags bindingFlags)
{
var fieldInfo = type.GetField(name, bindingFlags);
if (fieldInfo == null && type.BaseType != null)
return type.BaseType.GetFieldRecursive(name, bindingFlags);
return fieldInfo;
}
private static PropertyInfo GetPropertyRecursive(this Type type, string name, BindingFlags bindingFlags)
{
var propertyInfo = type.GetProperty(name, bindingFlags);
if (propertyInfo == null && type.BaseType != null)
return type.BaseType.GetPropertyRecursive(name, bindingFlags);
return propertyInfo;
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 138277cf2e7d2cd4e99c3cd7e2ecaaed
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Utility/SCEditorUtility.cs
uploadId: 632226

View File

@@ -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";
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 76def6672c756704bac4efd5a3625113
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Editor/Scripts/Utility/SCEnumUtility.cs
uploadId: 632226

Binary file not shown.

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 7d3a2360c7e15944cbf26d622f2de997
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Readme.pdf
uploadId: 632226

View File

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

View File

@@ -0,0 +1,13 @@
{
"name": "AYellowpaper.SerializedCollections",
"references": [],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [],
"noEngineReferences": false
}

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: d525ad6bd40672747bde77962f1c401e
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Runtime/AYellowpaper.SerializedCollections.asmdef
uploadId: 632226

View File

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

View File

@@ -0,0 +1,88 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace AYellowpaper.SerializedCollections
{
internal class DictionaryLookupTable<TKey, TValue> : IKeyable
{
private SerializedDictionary<TKey, TValue> _dictionary;
private Dictionary<TKey, List<int>> _occurences = new Dictionary<TKey, List<int>>();
private static readonly List<int> EmptyList = new List<int>();
public IEnumerable Keys => _dictionary.Keys;
public DictionaryLookupTable(SerializedDictionary<TKey, TValue> dictionary)
{
_dictionary = dictionary;
}
public IReadOnlyList<int> GetOccurences(object key)
{
if (key is TKey castKey && _occurences.TryGetValue(castKey, out var list))
return list;
return EmptyList;
}
public void RecalculateOccurences()
{
_occurences.Clear();
int count = _dictionary._serializedList.Count;
for (int i = 0; i < count; i++)
{
var kvp = _dictionary._serializedList[i];
if (!SerializedCollectionsUtility.IsValidKey(kvp.Key))
continue;
if (!_occurences.ContainsKey(kvp.Key))
_occurences.Add(kvp.Key, new List<int>() { i });
else
_occurences[kvp.Key].Add(i);
}
}
public void RemoveKey(object key)
{
for (int i = _dictionary._serializedList.Count - 1; i >= 0; i--)
{
var dictKey = _dictionary._serializedList[i].Key;
if (SerializedCollectionsUtility.KeysAreEqual(dictKey, key))
_dictionary._serializedList.RemoveAt(i);
}
}
public void RemoveAt(int index)
{
_dictionary._serializedList.RemoveAt(index);
}
public object GetKeyAt(int index)
{
return _dictionary._serializedList[index];
}
public int GetCount()
{
return _dictionary._serializedList.Count;
}
public void RemoveDuplicates()
{
_dictionary._serializedList = _dictionary._serializedList
.GroupBy(x => x.Key)
.Where(x => SerializedCollectionsUtility.IsValidKey(x.Key))
.Select(x => x.First()).ToList();
}
public void AddKey(object key)
{
var entry = new SerializedKeyValuePair<TKey, TValue>();
entry.Key = (TKey) key;
_dictionary._serializedList.Add(entry);
}
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: ff547989e6c74ca418db99a6a03aa653
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Runtime/LookupTables/DictionaryLookupTable.cs
uploadId: 632226

View File

@@ -0,0 +1,20 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace AYellowpaper.SerializedCollections
{
internal interface IKeyable
{
void RecalculateOccurences();
IReadOnlyList<int> GetOccurences(object key);
IEnumerable Keys { get; }
void AddKey(object key);
void RemoveKey(object key);
void RemoveAt(int index);
object GetKeyAt(int index);
int GetCount();
void RemoveDuplicates();
}
}

View File

@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 131781efcfa1f0c4a8f9480cc10f5699
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 243052
packageName: Serialized Dictionary
packageVersion: 1.0.13
assetPath: Assets/Plugins/SerializedCollections/Runtime/LookupTables/IKeyable.cs
uploadId: 632226

View File

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

Some files were not shown because too many files have changed in this diff Show More