插件添加

This commit is contained in:
SnowShow 2025-04-22 16:06:03 +08:00
parent b517b39a7e
commit b10fd8681a
2318 changed files with 178644 additions and 0 deletions

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: bd9f4941b19037f4a88460b874a8a3e1
folderAsset: yes
timeCreated: 1538755212
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 0aa2a0733358abb4c90587d3628d0ff9
folderAsset: yes
timeCreated: 1538657332
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: d4ff0b9c7cca6004d96e43fd71a2ec44
folderAsset: yes
DefaultImporter:
userData:

View File

@ -0,0 +1,112 @@
using System;
namespace ParadoxNotion.Design
{
///<summary>Marker attribute to include generic type or a type's generic methods in the AOT spoof generation</summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Delegate)]
public class SpoofAOTAttribute : Attribute { }
///<summary>To exclude a type from being listed. Abstract classes are not listed anyway.</summary>
[AttributeUsage(AttributeTargets.Class)]
public class DoNotListAttribute : Attribute { }
///<summary>When a type should for some reason be marked as protected so to always have one instance active.</summary>
[AttributeUsage(AttributeTargets.Class)]
public class ProtectedSingletonAttribute : Attribute { }
///<summary>Use for execution prioratizing when it matters.</summary>
[AttributeUsage(AttributeTargets.Class)]
public class ExecutionPriorityAttribute : Attribute
{
readonly public int priority;
public ExecutionPriorityAttribute(int priority) {
this.priority = priority;
}
}
///<summary>Marks a generic type to be exposed at it's base definition rather than wrapping all preferred types around it.</summary>
[AttributeUsage(AttributeTargets.Class)]
public class ExposeAsDefinitionAttribute : Attribute { }
///<summary>Marks a field to be exposed for inspection even if private (within the context of custom inspector).</summary>
///<summary>In custom inspector, private fields even if with [SerializedField] are not exposed by default.</summary>
[AttributeUsage(AttributeTargets.Field)]
public class ExposeFieldAttribute : Attribute { }
///<summary>Options attribute for list inspector editors</summary>
[AttributeUsage(AttributeTargets.Field)]
public class ListInspectorOptionAttribute : Attribute
{
readonly public bool allowAdd;
readonly public bool allowRemove;
readonly public bool showFoldout;
public ListInspectorOptionAttribute(bool allowAdd, bool allowRemove, bool alwaysExpanded) {
this.allowAdd = allowAdd;
this.allowRemove = allowRemove;
this.showFoldout = alwaysExpanded;
}
}
///----------------------------------------------------------------------------------------------
///<summary>Use for friendly names and optional priority in relation to naming only</summary>
[AttributeUsage(AttributeTargets.All)]
public class NameAttribute : Attribute
{
readonly public string name;
readonly public int priority;
public NameAttribute(string name, int priority = 0) {
this.name = name;
this.priority = priority;
}
}
///<summary>Use for categorization</summary>
[AttributeUsage(AttributeTargets.All)]
public class CategoryAttribute : Attribute
{
readonly public string category;
public CategoryAttribute(string category) {
this.category = category;
}
}
///<summary>Use to give a description</summary>
[AttributeUsage(AttributeTargets.All)]
public class DescriptionAttribute : Attribute
{
readonly public string description;
public DescriptionAttribute(string description) {
this.description = description;
}
}
///<summary>When a type is associated with an icon</summary>
[AttributeUsage(AttributeTargets.Class)]
public class IconAttribute : Attribute
{
readonly public string iconName;
readonly public bool fixedColor;
readonly public string runtimeIconTypeCallback;
readonly public Type fromType;
public IconAttribute(string iconName = "", bool fixedColor = false, string runtimeIconTypeCallback = "") {
this.iconName = iconName;
this.fixedColor = fixedColor;
this.runtimeIconTypeCallback = runtimeIconTypeCallback;
}
public IconAttribute(Type fromType) {
this.fromType = fromType;
}
}
///<summary>When a type is associated with a color (provide in hex string without "#")</summary>
[AttributeUsage(AttributeTargets.Class)]
public class ColorAttribute : Attribute
{
readonly public string hexColor;
public ColorAttribute(string hexColor) {
this.hexColor = hexColor;
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a6a1b03fabc29f2479f8b63c5ae861f2
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,155 @@
using System;
namespace ParadoxNotion.Design
{
///<summary>Derive this to create custom attributes to be drawn with an AttributeDrawer<T>.</summary>
[AttributeUsage(AttributeTargets.Field)]
abstract public class DrawerAttribute : Attribute
{
virtual public int priority { get { return int.MaxValue; } }
virtual public bool isDecorator { get { return false; } }
}
///----------------------------------------------------------------------------------------------
///<summary>Will dim control for bool, int, float, string if its default value (or empty for string)</summary>
[AttributeUsage(AttributeTargets.Field)]
public class HeaderAttribute : DrawerAttribute
{
readonly public string title;
public override bool isDecorator { get { return true; } }
public HeaderAttribute(string title) {
this.title = title;
}
}
///<summary>Will dim control for bool, int, float, string if its default value (or empty for string)</summary>
[AttributeUsage(AttributeTargets.Field)]
public class DimIfDefaultAttribute : DrawerAttribute
{
public override bool isDecorator { get { return true; } }
public override int priority { get { return 0; } }
}
///<summary>Use on top of any field to show it only if the provided field is equal to the provided check value</summary>
[AttributeUsage(AttributeTargets.Field)]
public class ShowIfAttribute : DrawerAttribute
{
readonly public string fieldName;
readonly public int checkValue;
public override bool isDecorator { get { return true; } }
public override int priority { get { return 1; } }
public ShowIfAttribute(string fieldName, int checkValue) {
this.fieldName = fieldName;
this.checkValue = checkValue;
}
}
///<summary>Helper attribute. Denotes that the field is required not to be null or string.empty</summary>
[AttributeUsage(AttributeTargets.Field)]
public class RequiredFieldAttribute : DrawerAttribute
{
public override bool isDecorator { get { return false; } }
public override int priority { get { return 2; } }
}
///<summary>Show a button above field</summary>
[AttributeUsage(AttributeTargets.Field)]
public class ShowButtonAttribute : DrawerAttribute
{
readonly public string buttonTitle;
readonly public string methodName;
public override bool isDecorator { get { return true; } }
public override int priority { get { return 3; } }
public ShowButtonAttribute(string buttonTitle, string methodnameCallback) {
this.buttonTitle = buttonTitle;
this.methodName = methodnameCallback;
}
}
///<summary>Will invoke a callback method when the field is changed</summary>
[AttributeUsage(AttributeTargets.Field)]
public class CallbackAttribute : DrawerAttribute
{
readonly public string methodName;
public override bool isDecorator { get { return true; } }
public override int priority { get { return 4; } }
public CallbackAttribute(string methodName) {
this.methodName = methodName;
}
}
///----------------------------------------------------------------------------------------------
///<summary>Will clamp float or int value to min</summary>
[AttributeUsage(AttributeTargets.Field)]
public class MinValueAttribute : DrawerAttribute
{
public override int priority { get { return 5; } }
readonly public float min;
public MinValueAttribute(float min) {
this.min = min;
}
public MinValueAttribute(int min) {
this.min = min;
}
}
///----------------------------------------------------------------------------------------------
///<summary>Makes float, int or string field show in a delayed control</summary>
[AttributeUsage(AttributeTargets.Field)]
public class DelayedFieldAttribute : DrawerAttribute { }
///<summary>Makes the int field show as layerfield</summary>
[AttributeUsage(AttributeTargets.Field)]
public class LayerFieldAttribute : DrawerAttribute { }
///<summary>Makes the string field show as tagfield</summary>
[AttributeUsage(AttributeTargets.Field)]
public class TagFieldAttribute : DrawerAttribute { }
///<summary>Makes the string field show as text field with specified number of lines</summary>
[AttributeUsage(AttributeTargets.Field)]
public class TextAreaFieldAttribute : DrawerAttribute
{
readonly public int numberOfLines;
public TextAreaFieldAttribute(int numberOfLines) {
this.numberOfLines = numberOfLines;
}
}
///<summary>Use on top of any type of field to restict values to the provided ones through a popup by providing a params array of options.</summary>
[AttributeUsage(AttributeTargets.Field)]
public class PopupFieldAttribute : DrawerAttribute
{
readonly public object[] options;
public PopupFieldAttribute(params object[] options) {
this.options = options;
}
}
///<summary>Makes the float or integer field show as slider</summary>
[AttributeUsage(AttributeTargets.Field)]
public class SliderFieldAttribute : DrawerAttribute
{
readonly public float min;
readonly public float max;
public SliderFieldAttribute(float min, float max) {
this.min = min;
this.max = max;
}
public SliderFieldAttribute(int min, int max) {
this.min = min;
this.max = max;
}
}
///<summary>Forces the field to show as a Unity Object field. Usefull for interface fields</summary>
[AttributeUsage(AttributeTargets.Field)]
public class ForceObjectFieldAttribute : DrawerAttribute { }
///<summary>Can be used on an interface type field to popup select a concrete implementation.<summary>
[AttributeUsage(AttributeTargets.Field)]
public class ReferenceFieldAttribute : DrawerAttribute { }
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3f408bebe1629994794006aa2e272ae5
timeCreated: 1513958511
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: be3277af62533fc4c8d68065c61db942
folderAsset: yes
timeCreated: 1538665292
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,55 @@
#if UNITY_EDITOR
using System.Linq;
using UnityEditor;
namespace ParadoxNotion.Design
{
///<summary>Utility for handling player setting defines</summary>
public static class DefinesManager
{
///<summary>Is define..defined in player settings for current target?</summary>
public static bool HasDefineForCurrentTargetGroup(string define) {
var currentTarget = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
var defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(currentTarget).Split(';');
return defines.Contains(define);
}
///<summary>Set define for current target</summary>
public static void SetDefineActiveForCurrentTargetGroup(string define, bool enable) {
var currentTarget = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
SetDefineActiveForTargetGroup(currentTarget, define, enable);
}
///<summary>Set define for target</summary>
public static void SetDefineActiveForTargetGroup(BuildTargetGroup target, string define, bool enable) {
var defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(target).Split(';').ToList();
if ( enable == true && !defines.Contains(define) ) {
defines.Add(define);
}
if ( enable == false ) {
defines.Remove(define);
}
PlayerSettings.SetScriptingDefineSymbolsForGroup(target, string.Join(";", defines));
}
///<summary>Toggle define in player settings for all targets</summary>
public static void SetDefineActiveForAllTargetGroups(string define, bool enable) {
foreach ( BuildTargetGroup target in System.Enum.GetValues(typeof(BuildTargetGroup)) ) {
if ( target == BuildTargetGroup.Unknown ) {
continue;
}
if ( typeof(BuildTargetGroup).GetField(target.ToString()).IsDefined(typeof(System.ObsoleteAttribute), true) ) {
continue;
}
SetDefineActiveForTargetGroup(target, define, enable);
}
}
}
}
#endif

View File

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

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 781130fb96acf5f4384bd574f6cd9704
folderAsset: yes
timeCreated: 1538665299
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: 17c9c4eff9e8ef144ba8beb631fefc75
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
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
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
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
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: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -0,0 +1,56 @@
fileFormatVersion: 2
guid: ae3fd876b2e88a94e9391b1ad6bbf549
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
cubemapConvolution: 0
cubemapConvolutionSteps: 7
cubemapConvolutionExponent: 1.5
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 1024
textureSettings:
filterMode: 1
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
rGBM: 0
compressionQuality: 50
allowsAlphaSplitting: 0
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

View File

@ -0,0 +1,58 @@
fileFormatVersion: 2
guid: d0aaf9b1e5a05024d9fe4e3215b9f73f
timeCreated: 1464506051
licenseType: Store
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 0
linearTexture: 1
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
cubemapConvolution: 0
cubemapConvolutionSteps: 7
cubemapConvolutionExponent: 1.5
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 2048
textureSettings:
filterMode: 0
aniso: 1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
rGBM: 0
compressionQuality: 50
allowsAlphaSplitting: 0
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 2
buildTargetSettings: []
spriteSheet:
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,103 @@
fileFormatVersion: 2
guid: 7db3c001bdf39ca46ab6bb3bbfe58d00
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 10
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
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
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
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
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: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@ -0,0 +1,104 @@
fileFormatVersion: 2
guid: f0b6a905426516149a73490df47637cc
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
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
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
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
applyGammaDecoding: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
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: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,103 @@
fileFormatVersion: 2
guid: 18c197a350b700d4f96e039071ffd2b6
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 10
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
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
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
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
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: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,103 @@
fileFormatVersion: 2
guid: 70b53005eb048f14ab18fcbb26bf6774
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 10
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
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: -100
wrapU: 1
wrapV: 1
wrapW: -1
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
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
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: []
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: 3774cc9cbacfc4a41b0fb7fa91f7950f
folderAsset: yes
DefaultImporter:
userData:

View File

@ -0,0 +1,242 @@
#if UNITY_EDITOR
using System;
using System.IO;
using System.Text;
using System.Linq;
using UnityEngine;
using System.Collections.Generic;
using System.Reflection;
namespace ParadoxNotion.Design
{
public static class AOTClassesGenerator
{
//always spoof those for shake of convenience
static readonly List<Type> defaultSpoofTypes = new List<Type>
{
typeof(bool),
typeof(float),
typeof(int),
typeof(Vector2),
typeof(Vector3),
typeof(Vector4),
typeof(Quaternion),
typeof(Keyframe),
typeof(Bounds),
typeof(Color),
typeof(Rect),
typeof(ContactPoint),
typeof(ContactPoint2D),
typeof(Collision),
typeof(Collision2D),
typeof(RaycastHit),
typeof(RaycastHit2D),
typeof(Ray),
typeof(Space),
};
///<summary>Custom generic types to spoof were we cant use [SpoofAOT]</summary>
static readonly List<Type> customGenericSpoof = new List<Type>
{
typeof(System.Action<>),
typeof(System.Func<>),
typeof(UnityEngine.Events.UnityAction<>),
typeof(IList<>),
typeof(List<>),
typeof(Nullable<>),
};
///<summary>Generates AOT classes file out of preferred types list</summary>
public static void GenerateAOTClasses(string path, Type[] targetTypes) {
if ( string.IsNullOrEmpty(path) ) {
return;
}
var spoofTypes = defaultSpoofTypes.Where(t => t.IsValueType).ToList();
spoofTypes.AddRange(targetTypes.Where(t => t.IsValueType && !spoofTypes.Contains(t)));
spoofTypes = spoofTypes.Distinct().ToList();
var types = ReflectionTools.GetAllTypes(true).Where(t => t.RTIsDefined(typeof(SpoofAOTAttribute), true)).Distinct();
var nTypes = 0;
var nMethods = 0;
var sb = new StringBuilder();
sb.AppendLine("#pragma warning disable 0219, 0168, 0612");
sb.AppendLine("namespace ParadoxNotion.Internal{");
sb.AppendLine();
sb.AppendLine("\t//Auto generated classes for AOT support, where using undeclared generic classes with value types is limited. These are not actualy used but rather just declared for the compiler");
sb.AppendLine("\tpartial class AOTDummy{");
sb.AppendLine();
sb.AppendLine("\t\tobject o = null;");
sb.AppendLine("\t\t///----------------------------------------------------------------------------------------------");
//Generic Types
foreach ( var type in types ) {
if ( !type.IsAbstract && type.IsGenericTypeDefinition && type.RTGetGenericArguments().Length == 1 ) {
var constrains = type.RTGetGenericArguments()[0].GetGenericParameterConstraints();
if ( constrains.Length == 0 || constrains[0].IsValueType || constrains[0] == typeof(Enum) ) {
if ( typeof(Delegate).IsAssignableFrom(type) ) {
nTypes++;
sb.AppendLine(string.Format("\t\tvoid {0}()", type.FriendlyName(true).Replace(".", "_").Replace("<T>", "_Delegate")) + "{");
foreach ( var spoofType in spoofTypes ) {
var a = type.FriendlyName(true).Replace("<T>", "<" + spoofType.FullName + ">").Replace("+", ".");
var b = "_" + type.FriendlyName(true).Replace(".", "_").Replace("<T>", "_" + spoofType.FullName.Replace(".", "_").Replace("+", "_"));
sb.AppendLine(string.Format("\t\t\t{0} {1};", a, b));
}
sb.AppendLine("\t\t}");
} else {
foreach ( var spoofType in spoofTypes ) {
if ( constrains.Length == 1 && constrains[0] == typeof(Enum) && !spoofType.IsEnum ) { continue; }
nTypes++;
var a = type.FriendlyName(true).Replace("<T>", "<" + spoofType.FullName + ">").Replace("+", ".");
var b = type.FriendlyName(true).Replace(".", "_").Replace("<T>", "_" + spoofType.FullName.Replace(".", "_").Replace("+", "_"));
sb.AppendLine(string.Format("\t\t{0} {1};", a, b));
}
}
sb.AppendLine();
}
}
}
sb.AppendLine("\t\t///----------------------------------------------------------------------------------------------");
//Generic Methods
foreach ( var type in types ) {
var index = 0;
foreach ( var method in type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly) ) {
if ( method.IsObsolete() ) { continue; }
if ( method.IsGenericMethodDefinition && method.RTGetGenericArguments().Length == 1 ) {
var constrains = method.RTGetGenericArguments()[0].GetGenericParameterConstraints();
if ( constrains.Length == 0 || constrains[0].IsValueType ) {
index++;
var decType = method.DeclaringType;
var varName = "_" + decType.FullName.Replace(".", "_");
sb.AppendLine(string.Format("\t\tvoid {0}_{1}_{2}()", decType.FullName.Replace(".", "_"), method.Name, index) + " {");
if ( !method.IsStatic ) {
sb.AppendLine(string.Format("\t\t\t{0} {1} = default({2});", decType.FullName, varName, decType.FullName));
}
foreach ( var spoofType in spoofTypes ) {
nMethods++;
var a = method.IsStatic ? decType.FullName : varName;
var b = method.Name;
var c = spoofType.FullName.Replace("+", ".");
var paramsString = "";
var parameters = method.GetParameters();
for ( var i = 0; i < parameters.Length; i++ ) {
var parameter = parameters[i];
var toString = parameter.ParameterType.FullName;
if ( parameter.ParameterType.IsGenericParameter ) {
toString = spoofType.FullName;
}
if ( parameter.ParameterType.IsGenericType ) {
toString = parameter.ParameterType.FriendlyName(true).Replace("<T>", "<" + spoofType.FullName + ">");
toString = toString.Replace("[[T]]", "");
}
toString = toString.Replace("+", ".");
paramsString += string.Format("({0})o", toString);
if ( i < parameters.Length - 1 ) {
paramsString += ", ";
}
}
var d = paramsString;
sb.AppendLine(string.Format("\t\t\t{0}.{1}<{2}>( {3} );", a, b, c, d));
}
sb.AppendLine("\t\t}");
sb.AppendLine();
}
}
}
}
sb.AppendLine("\t\t///----------------------------------------------------------------------------------------------");
//custom stuff
sb.AppendLine("\t\tvoid CustomSpoof(){");
foreach ( var spoofType in spoofTypes ) {
var sName = spoofType.FullName.Replace("+", ".");
var fName = spoofType.FullName.Replace(".", "_").Replace("+", "_");
foreach ( var genericType in customGenericSpoof ) {
nTypes++;
var a = genericType.FriendlyName(true).Replace("<T>", "<" + sName + ">");
var b = genericType.FriendlyName(true).Replace(".", "_").Replace("<T>", "_") + fName;
sb.AppendLine(string.Format("\t\t\t{0} {1};", a, b));
}
nTypes++;
sb.AppendLine(string.Format("\t\t\tSystem.Collections.Generic.IDictionary<System.String, {0}> IDict_{1};", sName, fName));
sb.AppendLine(string.Format("\t\t\tSystem.Collections.Generic.Dictionary<System.String, {0}> Dict_{1};", sName, fName));
sb.AppendLine("\t\t\t///------");
}
sb.AppendLine("\t\t}");
sb.AppendLine("\t}");
sb.AppendLine("}");
sb.AppendLine();
sb.AppendLine(string.Format("//{0} Types | {1} Methods spoofed", nTypes, nMethods));
sb.AppendLine("#pragma warning restore 0219, 0168, 0612");
File.WriteAllText(path, sb.ToString());
}
///<summary>Generates a link.xml file out of preferred types list</summary>
public static void GenerateLinkXML(string path, Type[] targetTypes) {
if ( string.IsNullOrEmpty(path) ) {
return;
}
var spoofTypes = defaultSpoofTypes;
spoofTypes.AddRange(targetTypes);
var pairs = new Dictionary<string, List<Type>>();
foreach ( var type in spoofTypes ) {
var asmName = type.Assembly.GetName().Name;
if ( !pairs.ContainsKey(asmName) ) {
pairs[asmName] = new List<Type>();
}
pairs[asmName].Add(type);
}
var sb = new StringBuilder();
sb.AppendLine("<linker>");
sb.AppendLine("\t<assembly fullname=\"Assembly-CSharp\" preserve=\"all\">");
sb.AppendLine("\t</assembly>");
//get assembly from a common paradoxnotion *runtime* type
var paradoxAsmName = typeof(ParadoxNotion.Serialization.JSONSerializer).Assembly.GetName().Name;
sb.AppendLine(string.Format("\t<assembly fullname=\"{0}\" preserve=\"all\">", paradoxAsmName));
sb.AppendLine("\t</assembly>");
foreach ( var pair in pairs ) {
sb.AppendLine(string.Format("\t<assembly fullname=\"{0}\">", pair.Key));
foreach ( var type in pair.Value ) {
sb.AppendLine("\t\t<type fullname=\"" + type.FullName + "\" preserve=\"all\"/>");
}
sb.AppendLine("\t</assembly>");
}
sb.AppendLine("</linker>");
File.WriteAllText(path, sb.ToString());
}
}
}
#endif

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3b148b00f34f1a94488008fd63cdd171
timeCreated: 1430214156
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,86 @@
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEditor;
using System.Linq;
namespace ParadoxNotion.Design
{
///<summary>Can track assets of specific type when required. This is faster than requesting AssetDabase all the time and can also be used in separate thread.</summary>
public class AssetTracker : AssetPostprocessor
{
public static event System.Action<string[]> onAssetsImported;
public static event System.Action<string[]> onAssetsDeleted;
public static event System.Action<string[], string[]> onAssetsMoved;
public static Dictionary<string, UnityEngine.Object> trackedAssets { get; private set; }
public static List<System.Type> trackedTypes { get; private set; }
///<summary>Call this to start tracking assets of specified type (and assignables to that)</summary>
public static void BeginTrackingAssetsOfType(System.Type type) {
if ( trackedAssets == null ) { trackedAssets = new Dictionary<string, UnityEngine.Object>(); }
if ( trackedTypes == null ) { trackedTypes = new List<System.Type>(); }
if ( trackedTypes.Contains(type) ) {
UnityEngine.Debug.LogError("Asset type is already tracked: " + type);
return;
}
trackedTypes.Add(type);
//we need to immediately fetch them here now
var assetGUIDS = AssetDatabase.FindAssets(string.Format("t:{0}", type.Name));
foreach ( var guid in assetGUIDS ) {
var path = AssetDatabase.GUIDToAssetPath(guid);
var asset = AssetDatabase.LoadAssetAtPath(path, type);
trackedAssets[path] = asset;
}
}
//unity callback
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths) {
AssetsImported(importedAssets);
if ( onAssetsImported != null ) { onAssetsImported(importedAssets); }
AssetsDeleted(deletedAssets);
if ( onAssetsDeleted != null ) { onAssetsDeleted(deletedAssets); }
AssetsMoved(movedAssets, movedFromAssetPaths);
if ( onAssetsMoved != null ) { onAssetsMoved(movedAssets, movedFromAssetPaths); }
}
//..
static void AssetsImported(string[] paths) {
if ( trackedTypes == null ) { return; }
foreach ( var path in paths ) {
var asset = AssetDatabase.LoadAssetAtPath(path, typeof(UnityEngine.Object));
if ( asset != null && trackedTypes.Any(t => t.IsAssignableFrom(asset.GetType())) ) {
trackedAssets[path] = asset;
}
}
}
//..
static void AssetsDeleted(string[] paths) {
if ( trackedTypes == null ) { return; }
foreach ( var path in paths ) {
if ( trackedAssets.ContainsKey(path) ) {
trackedAssets.Remove(path);
}
}
}
//..
static void AssetsMoved(string[] moveToPaths, string[] moveFromPaths) {
if ( trackedTypes == null ) { return; }
AssetsDeleted(moveFromPaths);
AssetsImported(moveToPaths);
}
}
}
#endif

View File

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

View File

@ -0,0 +1,256 @@
#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
using System.Linq;
namespace ParadoxNotion.Design
{
///<summary>Used to create header / separators similar to Unity's Header attribute</summary>
public class HeaderDrawer : AttributeDrawer<HeaderAttribute>
{
public override object OnGUI(GUIContent content, object instance) {
GUILayout.Space(8);
GUILayout.Label(string.Format("<b>- {0}</b>", attribute.title));
return MoveNextDrawer();
}
}
///<summary>Will dim control for bool, int, float, string if its default value (or empty for string)</summary>
public class DimIfDefaultDrawer : AttributeDrawer<DimIfDefaultAttribute>
{
public override object OnGUI(GUIContent content, object instance) {
var dim = false;
if ( fieldInfo.FieldType.IsClass ) {
dim = instance == null;
}
if ( fieldInfo.FieldType == typeof(bool) ) {
dim = (bool)instance == false;
}
if ( fieldInfo.FieldType == typeof(int) ) {
dim = (int)instance == 0;
}
if ( fieldInfo.FieldType == typeof(float) ) {
dim = (float)instance == 0;
}
if ( fieldInfo.FieldType == typeof(string) ) {
dim = string.IsNullOrEmpty((string)instance);
}
if ( dim ) { GUI.color = GUI.color.WithAlpha(0.5f); }
instance = MoveNextDrawer();
GUI.color = Color.white;
return instance;
}
}
///<summary>Will show value only if another field or prop is equal to target</summary>
public class ShowIfDrawer : AttributeDrawer<ShowIfAttribute>
{
public override object OnGUI(GUIContent content, object instance) {
var member = context.GetType().RTGetFieldOrProp(attribute.fieldName);
if ( member != null ) {
var memberValue = member.RTGetFieldOrPropValue(context);
var memberType = memberValue?.GetType();
int intValue;
if ( memberType == null || !memberType.IsValueType ) {
intValue = memberValue != null ? 1 : 0;
} else {
intValue = (int)System.Convert.ChangeType(memberValue, typeof(int));
}
if ( intValue != attribute.checkValue ) {
return instance; //return instance without any editor (thus hide it)
}
}
return MoveNextDrawer();
}
}
///<summary>Will show in red if value is null or empty</summary>
public class RequiredFieldDrawer : AttributeDrawer<RequiredFieldAttribute>
{
public override object OnGUI(GUIContent content, object instance) {
var isNull = instance == null || instance.Equals(null) || ( ( instance is string ) && string.IsNullOrEmpty((string)instance) );
instance = MoveNextDrawer();
if ( isNull ) { EditorUtils.MarkLastFieldError("An instance is required."); }
return instance;
}
}
///<summary>Will show a button above field</summary>
public class ShowButtonDrawer : AttributeDrawer<ShowButtonAttribute>
{
public override object OnGUI(GUIContent content, object instance) {
if ( !string.IsNullOrEmpty(attribute.methodName) ) {
var method = info.wrapperInstanceContext.GetType().RTGetMethod(attribute.methodName);
if ( method != null && method.GetParameters().Length == 0 ) {
if ( GUILayout.Button(attribute.buttonTitle) ) {
method.Invoke(info.wrapperInstanceContext, null);
}
} else {
GUILayout.Label(string.Format("Can't find ShowIf method '{0}'.", attribute.methodName));
}
}
return MoveNextDrawer();
}
}
///<summary>Will invoke a callback method when value change</summary>
public class CallbackDrawer : AttributeDrawer<CallbackAttribute>
{
public override object OnGUI(GUIContent content, object instance) {
var newValue = MoveNextDrawer();
if ( !Equals(newValue, instance) ) {
var method = info.wrapperInstanceContext.GetType().RTGetMethod(attribute.methodName);
if ( method != null && method.GetParameters().Length == 0 ) {
fieldInfo.SetValue(context, newValue); //manual set field before invoke
method.Invoke(info.wrapperInstanceContext, null);
} else {
GUILayout.Label(string.Format("Can't find Callback method '{0}'.", attribute.methodName));
}
}
return newValue;
}
}
///----------------------------------------------------------------------------------------------
///<summary>Will clamp float or int value to min</summary>
public class MinValueDrawer : AttributeDrawer<MinValueAttribute>
{
public override object OnGUI(GUIContent content, object instance) {
if ( fieldInfo.FieldType == typeof(float) ) {
return Mathf.Max((float)MoveNextDrawer(), (float)attribute.min);
}
if ( fieldInfo.FieldType == typeof(int) ) {
return Mathf.Max((int)MoveNextDrawer(), (int)attribute.min);
}
return MoveNextDrawer();
}
}
///----------------------------------------------------------------------------------------------
///<summary>Will make float, int or string field show in a delayed control</summary>
public class DelayedFieldDrawer : AttributeDrawer<DelayedFieldAttribute>
{
public override object OnGUI(GUIContent content, object instance) {
if ( fieldInfo.FieldType == typeof(float) ) {
return EditorGUILayout.DelayedFloatField(content, (float)instance);
}
if ( fieldInfo.FieldType == typeof(int) ) {
return EditorGUILayout.DelayedIntField(content, (int)instance);
}
if ( fieldInfo.FieldType == typeof(string) ) {
return EditorGUILayout.DelayedTextField(content, (string)instance);
}
return MoveNextDrawer();
}
}
///<summary>Will force to use ObjectField editor, usefull for interfaces</summary>
public class ForceObjectFieldDrawer : AttributeDrawer<ForceObjectFieldAttribute>
{
public override object OnGUI(GUIContent content, object instance) {
if ( typeof(UnityEngine.Object).IsAssignableFrom(fieldInfo.FieldType) || fieldInfo.FieldType.IsInterface ) {
return EditorGUILayout.ObjectField(content, instance as UnityEngine.Object, fieldInfo.FieldType, true);
}
return MoveNextDrawer();
}
}
///<summary>Will restrict selection on provided values</summary>
public class PopupFieldDrawer : AttributeDrawer<PopupFieldAttribute>
{
public override object OnGUI(GUIContent content, object instance) {
if ( attribute.options != null && attribute.options.Length > 0 ) {
var optType = attribute.options[0].GetType();
if ( fieldInfo.FieldType.IsAssignableFrom(optType) ) {
return EditorUtils.Popup<object>(content, instance, attribute.options);
}
}
return MoveNextDrawer();
}
}
///<summary>Will show a slider for int and float values</summary>
public class SliderFieldDrawer : AttributeDrawer<SliderFieldAttribute>
{
public override object OnGUI(GUIContent content, object instance) {
if ( fieldInfo.FieldType == typeof(float) ) {
return EditorGUILayout.Slider(content, (float)instance, (float)attribute.min, (float)attribute.max);
}
if ( fieldInfo.FieldType == typeof(int) ) {
return EditorGUILayout.IntSlider(content, (int)instance, (int)attribute.min, (int)attribute.max);
}
return MoveNextDrawer();
}
}
///<summary>Will show a layer selection for int values</summary>
public class LayerFieldDrawer : AttributeDrawer<LayerFieldAttribute>
{
public override object OnGUI(GUIContent content, object instance) {
if ( fieldInfo.FieldType == typeof(int) ) {
return EditorGUILayout.LayerField(content, (int)instance);
}
return MoveNextDrawer();
}
}
///<summary>Will show a Tag selection for string values</summary>
public class TagFieldDrawer : AttributeDrawer<TagFieldAttribute>
{
public override object OnGUI(GUIContent content, object instance) {
if ( fieldInfo.FieldType == typeof(string) ) {
return EditorGUILayout.TagField(content, (string)instance);
}
return MoveNextDrawer();
}
}
///<summary>Will show a text area for string values</summary>
public class TextAreaDrawer : AttributeDrawer<TextAreaFieldAttribute>
{
private static GUIStyle areaStyle;
static TextAreaDrawer() {
areaStyle = new GUIStyle(GUI.skin.GetStyle("TextArea"));
areaStyle.wordWrap = true;
}
public override object OnGUI(GUIContent content, object instance) {
if ( fieldInfo.FieldType == typeof(string) ) {
GUILayout.Label(content);
return EditorGUILayout.TextArea((string)instance, areaStyle, GUILayout.Height(attribute.numberOfLines * areaStyle.lineHeight));
}
return MoveNextDrawer();
}
}
///<summary>Can be used on an interface to popup select a concrete implementation.<summary>
public class ReferenceFieldDrawer : AttributeDrawer<ReferenceFieldAttribute>
{
public override object OnGUI(GUIContent content, object instance)
{
var options = ReflectionTools.GetImplementationsOf(fieldInfo.FieldType);
var selection = EditorUtils.Popup<System.Type>(content, instance != null? instance.GetType() : fieldInfo.FieldType, options);
if (selection == null){ return instance = null; }
if (instance == null || instance.GetType() != selection ) {
if (!typeof(UnityEngine.Object).IsAssignableFrom(selection)){
return System.Activator.CreateInstance(selection);
}
}
EditorGUI.indentLevel++;
EditorUtils.ReflectedObjectInspector(instance, contextUnityObject);
EditorGUI.indentLevel--;
return instance;
}
}
}
#endif

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 6bc5dd489056dda48ad29f55f5da5c78
timeCreated: 1513884114
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,74 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using ParadoxNotion.Serialization;
namespace ParadoxNotion.Design
{
///<summary>A very simple pool to handle Copy/Pasting</summary>
public static class CopyBuffer
{
private static Dictionary<Type, string> cachedCopies = new Dictionary<Type, string>();
private static Dictionary<Type, object> cachedObjects = new Dictionary<Type, object>();
public static void FlushMem() {
cachedCopies = new Dictionary<Type, string>();
cachedObjects = new Dictionary<Type, object>();
}
///<summary>Is copy available?</summary>
public static bool Has<T>() {
return ( cachedCopies.TryGetValue(typeof(T), out string json) );
}
///<summary>Returns true if copy exist and the copy</summary>
public static bool TryGet<T>(out T copy) {
copy = Get<T>();
return object.Equals(copy, default(T)) == false;
}
///<summary>Returns a copy</summary>
public static T Get<T>() {
if ( cachedCopies.TryGetValue(typeof(T), out string json) ) {
return JSONSerializer.Deserialize<T>(json);
}
return default(T);
}
///<summary>Sets a copy</summary>
public static void Set<T>(T obj) {
cachedCopies[typeof(T)] = JSONSerializer.Serialize(typeof(T), obj); ;
}
///----------------------------------------------------------------------------------------------
///<summary></summary>
public static bool HasCache<T>() {
return ( cachedObjects.TryGetValue(typeof(T), out object obj) );
}
///<summary></summary>
public static bool TryGetCache<T>(out T copy) {
copy = GetCache<T>();
return object.Equals(copy, default(T)) == false;
}
///<summary></summary>
public static T GetCache<T>() {
if ( cachedObjects.TryGetValue(typeof(T), out object obj) ) {
return (T)obj;
}
return default(T);
}
///<summary></summary>
public static void SetCache<T>(T obj) {
cachedObjects[typeof(T)] = obj;
}
}
}
#endif

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e2177b57a40461d4484f7675d40b6fd0
timeCreated: 1510990664
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: e2a7ec01cbc8b5744b88354fd6b2e310
folderAsset: yes
timeCreated: 1541186478
licenseType: Store
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,53 @@
#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
namespace ParadoxNotion.Design
{
[InitializeOnLoad]
public static class Colors
{
static Colors() { Load(); }
[InitializeOnLoadMethod]
static void Load() {
lightOrange = EditorGUIUtility.isProSkin ? new Color(1, 0.9f, 0.4f) : Color.white;
lightBlue = EditorGUIUtility.isProSkin ? new Color(0.8f, 0.8f, 1) : Color.white;
lightRed = EditorGUIUtility.isProSkin ? new Color(1, 0.5f, 0.5f, 0.8f) : Color.white;
prefabOverrideColor = new Color(0.05f, 0.5f, 0.75f, 1f);
}
public const string HEX_LIGHT = "#d2d2d2";
public const string HEX_DARK = "#333333";
public static Color lightOrange { get; private set; }
public static Color lightBlue { get; private set; }
public static Color lightRed { get; private set; }
public static Color prefabOverrideColor { get; private set; }
///----------------------------------------------------------------------------------------------
///<summary>A greyscale color</summary>
public static Color Grey(float value) {
return new Color(value, value, value);
}
///----------------------------------------------------------------------------------------------
///<summary>Return a color for a type.</summary>
public static Color GetTypeColor(System.Type type) {
return TypePrefs.GetTypeColor(type);
}
///<summary>Return a string hex color for a type.</summary>
public static string GetTypeHexColor(System.Type type) {
return TypePrefs.GetTypeHexColor(type);
}
}
}
#endif

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 987618a20a0698a429059efcc504a5c9
timeCreated: 1510968237
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,71 @@
#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
namespace ParadoxNotion.Design
{
///<summary>Common Icons Database</summary>
[InitializeOnLoad]
public static class Icons
{
static Icons() { Load(); }
[InitializeOnLoadMethod]
static void Load() {
playIcon = EditorGUIUtility.FindTexture("d_PlayButton");
pauseIcon = EditorGUIUtility.FindTexture("d_PauseButton");
stepIcon = EditorGUIUtility.FindTexture("d_StepButton");
viewIcon = EditorGUIUtility.FindTexture("d_ViewToolOrbit On");
csIcon = EditorGUIUtility.FindTexture("cs Script Icon");
tagIcon = EditorGUIUtility.FindTexture("d_FilterByLabel");
searchIcon = EditorGUIUtility.FindTexture("Search Icon");
infoIcon = EditorGUIUtility.FindTexture("d_console.infoIcon.sml");
warningIcon = EditorGUIUtility.FindTexture("d_console.warnicon.sml");
warningIconBig = EditorGUIUtility.FindTexture("d_console.warnicon");
errorIcon = EditorGUIUtility.FindTexture("d_console.erroricon.sml");
errorIconBig = EditorGUIUtility.FindTexture("d_console.erroricon");
folderIcon = EditorGUIUtility.FindTexture("Folder Icon");
favoriteIcon = EditorGUIUtility.FindTexture("Favorite Icon");
gearPopupIcon = EditorGUIUtility.FindTexture("d__Popup");
gearIcon = EditorGUIUtility.FindTexture("EditorSettings Icon");
scaleIcon = EditorGUIUtility.FindTexture("d_ScaleTool");
minMaxIcon = EditorGUIUtility.FindTexture("d_winbtn_win_max");
plusIcon = EditorGUIUtility.FindTexture("d_CreateAddNew");
helpIcon = EditorGUIUtility.FindTexture("d__Help");
}
public static Texture2D playIcon { get; private set; }
public static Texture2D pauseIcon { get; private set; }
public static Texture2D stepIcon { get; private set; }
public static Texture2D viewIcon { get; private set; }
public static Texture2D csIcon { get; private set; }
public static Texture2D tagIcon { get; private set; }
public static Texture2D searchIcon { get; private set; }
public static Texture2D infoIcon { get; private set; }
public static Texture2D warningIcon { get; private set; }
public static Texture2D warningIconBig { get; private set; }
public static Texture2D errorIcon { get; private set; }
public static Texture2D errorIconBig { get; private set; }
public static Texture2D folderIcon { get; private set; }
public static Texture2D favoriteIcon { get; private set; }
public static Texture2D gearPopupIcon { get; private set; }
public static Texture2D gearIcon { get; private set; }
public static Texture2D scaleIcon { get; private set; }
public static Texture2D minMaxIcon { get; private set; }
public static Texture2D plusIcon { get; private set; }
public static Texture2D helpIcon { get; private set; }
///----------------------------------------------------------------------------------------------
///<summary>Returns a type icon</summary>
public static Texture GetTypeIcon(System.Type type) {
return TypePrefs.GetTypeIcon(type);
}
}
}
#endif

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 69ab7b26fef952b43af5148544cd9a0c
timeCreated: 1510968237
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,231 @@
#if UNITY_EDITOR
using UnityEngine;
namespace ParadoxNotion.Design
{
///<summary>Common Styles Database</summary>
public static class Styles
{
private static GUIStyle _centerLabel;
public static GUIStyle centerLabel {
get
{
if ( _centerLabel == null ) {
_centerLabel = new GUIStyle(GUI.skin.label);
_centerLabel.richText = true;
_centerLabel.fontSize = 11;
_centerLabel.alignment = TextAnchor.MiddleCenter;
}
return _centerLabel;
}
}
private static GUIStyle _topCenterLabel;
public static GUIStyle topCenterLabel {
get
{
if ( _topCenterLabel == null ) {
_topCenterLabel = new GUIStyle(GUI.skin.label);
_topCenterLabel.richText = true;
_topCenterLabel.fontSize = 11;
_topCenterLabel.alignment = TextAnchor.UpperCenter;
}
return _topCenterLabel;
}
}
private static GUIStyle _leftLabel;
public static GUIStyle leftLabel {
get
{
if ( _leftLabel == null ) {
_leftLabel = new GUIStyle(GUI.skin.label);
_leftLabel.richText = true;
_leftLabel.fontSize = 11;
_leftLabel.alignment = TextAnchor.MiddleLeft;
_leftLabel.padding.right = 6;
}
return _leftLabel;
}
}
private static GUIStyle _rightLabel;
public static GUIStyle rightLabel {
get
{
if ( _rightLabel == null ) {
_rightLabel = new GUIStyle(GUI.skin.label);
_rightLabel.richText = true;
_rightLabel.fontSize = 11;
_rightLabel.alignment = TextAnchor.MiddleRight;
_rightLabel.padding.left = 6;
}
return _rightLabel;
}
}
private static GUIStyle _topLeftLabel;
public static GUIStyle topLeftLabel {
get
{
if ( _topLeftLabel == null ) {
_topLeftLabel = new GUIStyle(GUI.skin.label);
_topLeftLabel.richText = true;
_topLeftLabel.fontSize = 11;
_topLeftLabel.alignment = TextAnchor.UpperLeft;
_topLeftLabel.padding.right = 6;
}
return _topLeftLabel;
}
}
private static GUIStyle _topRight;
public static GUIStyle topRightLabel {
get
{
if ( _topRight == null ) {
_topRight = new GUIStyle(GUI.skin.label);
_topRight.richText = true;
_topRight.fontSize = 11;
_topRight.alignment = TextAnchor.UpperRight;
_topRight.padding.left = 6;
}
return _topRight;
}
}
private static GUIStyle _bottomCenter;
public static GUIStyle bottomCenterLabel {
get
{
if ( _bottomCenter == null ) {
_bottomCenter = new GUIStyle(GUI.skin.label);
_bottomCenter.richText = true;
_bottomCenter.fontSize = 11;
_bottomCenter.alignment = TextAnchor.LowerCenter;
}
return _bottomCenter;
}
}
///----------------------------------------------------------------------------------------------
private static GUIStyle _portContentImage;
public static GUIStyle proxyContentImage {
get
{
if ( _portContentImage == null ) {
_portContentImage = new GUIStyle(GUI.skin.label);
_portContentImage.alignment = TextAnchor.MiddleCenter;
_portContentImage.padding = new RectOffset(0, 0, _portContentImage.padding.top, _portContentImage.padding.bottom);
_portContentImage.margin = new RectOffset(0, 0, _portContentImage.margin.top, _portContentImage.margin.bottom);
}
return _portContentImage;
}
}
private static GUIStyle _proxyRightContentLabel;
public static GUIStyle proxyRightContentLabel {
get
{
if ( _proxyRightContentLabel == null ) {
_proxyRightContentLabel = new GUIStyle(ParadoxNotion.Design.Styles.rightLabel);
_proxyRightContentLabel.margin = new RectOffset(0, 0, _proxyRightContentLabel.margin.top, _proxyRightContentLabel.margin.bottom);
_proxyRightContentLabel.padding = new RectOffset(8, 0, _proxyRightContentLabel.padding.top, _proxyRightContentLabel.padding.bottom);
}
return _proxyRightContentLabel;
}
}
private static GUIStyle _proxyLeftContentLabel;
public static GUIStyle proxyLeftContentLabel {
get
{
if ( _proxyLeftContentLabel == null ) {
_proxyLeftContentLabel = new GUIStyle(ParadoxNotion.Design.Styles.leftLabel);
_proxyLeftContentLabel.margin = new RectOffset(0, 0, _proxyLeftContentLabel.margin.top, _proxyLeftContentLabel.margin.bottom);
_proxyLeftContentLabel.padding = new RectOffset(0, 8, _proxyLeftContentLabel.padding.top, _proxyLeftContentLabel.padding.bottom);
}
return _proxyLeftContentLabel;
}
}
///----------------------------------------------------------------------------------------------
private static GUIStyle _wrapTextArea;
public static GUIStyle wrapTextArea {
get
{
if ( _wrapTextArea == null ) {
_wrapTextArea = new GUIStyle(GUI.skin.textArea);
_wrapTextArea.wordWrap = true;
}
return _wrapTextArea;
}
}
///----------------------------------------------------------------------------------------------
private static GUIStyle _roundedBox;
public static GUIStyle roundedBox {
get
{
if ( _roundedBox != null ) { return _roundedBox; }
_roundedBox = new GUIStyle((GUIStyle)"ShurikenEffectBg");
if ( !UnityEditor.EditorGUIUtility.isProSkin ) {
_roundedBox.normal.background = null;
}
return _roundedBox;
}
}
private static GUIStyle _buttonLeft;
public static GUIStyle buttonLeft {
get { return _buttonLeft ?? ( _buttonLeft = new GUIStyle((GUIStyle)"AppCommandLeft") ); }
}
private static GUIStyle _buttonMid;
public static GUIStyle buttonMid {
get { return _buttonMid ?? ( _buttonMid = new GUIStyle((GUIStyle)"AppCommandMid") ); }
}
private static GUIStyle _buttonRight;
public static GUIStyle buttonRight {
get { return _buttonRight ?? ( _buttonRight = new GUIStyle((GUIStyle)"AppCommandRight") ); }
}
private static GUIStyle _highlightBox;
public static GUIStyle highlightBox {
get { return _highlightBox ?? ( _highlightBox = new GUIStyle((GUIStyle)"LightmapEditorSelectedHighlight") ); }
}
private static GUIStyle _toolbarSearchField;
public static GUIStyle toolbarSearchTextField {
get { return _toolbarSearchField ?? ( _toolbarSearchField = new GUIStyle((GUIStyle)"ToolbarSearchTextField") ); }
}
private static GUIStyle _toolbarSearchButton;
public static GUIStyle toolbarSearchCancelButton {
get { return _toolbarSearchButton ?? ( _toolbarSearchButton = new GUIStyle((GUIStyle)"ToolbarSearchCancelButton") ); }
}
private static GUIStyle _shadowedBackground;
public static GUIStyle shadowedBackground {
get { return _shadowedBackground ?? ( _shadowedBackground = new GUIStyle((GUIStyle)"CurveEditorBackground") ); }
}
///----------------------------------------------------------------------------------------------
///<summary>Same as box, but saves me the trouble of writing string.empty all the time</summary>
public static void Draw(Rect position, GUIStyle style) {
GUI.Box(position, string.Empty, style);
}
}
}
#endif

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2ffba1313f15e5948a23e610947d90b8
timeCreated: 1510968237
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: 8d7a98bebbf5f384bad444fe79c2d315
folderAsset: yes
DefaultImporter:
userData:

View File

@ -0,0 +1,120 @@
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using System.Linq;
namespace ParadoxNotion.Design
{
///<summary> AssetDatabase related utility</summary>
partial class EditorUtils
{
///<summary>Create asset of type T with a dialog prompt to chose path</summary>
public static T CreateAsset<T>() where T : ScriptableObject {
return (T)CreateAsset(typeof(T));
}
///<summary>Create asset of type T at target path</summary>
public static T CreateAsset<T>(string path) where T : ScriptableObject {
return (T)CreateAsset(typeof(T), path);
}
///<summary>Create asset of type and show or not the File Panel</summary>
public static ScriptableObject CreateAsset(System.Type type) {
ScriptableObject asset = null;
var path = EditorUtility.SaveFilePanelInProject(
"Create Asset of type " + type.ToString(),
type.Name + ".asset",
"asset", "");
asset = CreateAsset(type, path);
return asset;
}
///<summary>Create asset of type at target path</summary>
public static ScriptableObject CreateAsset(System.Type type, string path) {
if ( string.IsNullOrEmpty(path) ) {
return null;
}
ScriptableObject data = null;
data = ScriptableObject.CreateInstance(type);
AssetDatabase.CreateAsset(data, path);
AssetDatabase.SaveAssets();
return data;
}
///----------------------------------------------------------------------------------------------
///<summary>Get a unique path at current project selection for creating an asset, providing the "filename.type"</summary>
public static string GetAssetUniquePath(string fileName) {
var path = AssetDatabase.GetAssetPath(Selection.activeObject);
if ( path == "" ) {
path = "Assets";
}
if ( System.IO.Path.GetExtension(path) != "" ) {
path = path.Replace(System.IO.Path.GetFileName(AssetDatabase.GetAssetPath(Selection.activeObject)), "");
}
return AssetDatabase.GenerateUniqueAssetPath(path + "/" + fileName);
}
///<summary>Get MonoScript reference from type if able</summary>
public static MonoScript MonoScriptFromType(System.Type targetType) {
if ( targetType == null ) return null;
var typeName = targetType.Name;
if ( targetType.IsGenericType ) {
targetType = targetType.GetGenericTypeDefinition();
typeName = typeName.Substring(0, typeName.IndexOf('`'));
}
return AssetDatabase.FindAssets(string.Format("{0} t:MonoScript", typeName))
.Select(AssetDatabase.GUIDToAssetPath)
.Select(AssetDatabase.LoadAssetAtPath<MonoScript>)
.FirstOrDefault(m => m != null && m.GetClass() == targetType);
}
///<summary>Opens the MonoScript of a type if able</summary>
public static bool OpenScriptOfType(System.Type type) {
var mono = MonoScriptFromType(type);
if ( mono != null ) {
AssetDatabase.OpenAsset(mono);
return true;
}
ParadoxNotion.Services.Logger.Log(string.Format("Can't open script of type '{0}', because a script with the same name does not exist.", type.FriendlyName()));
return false;
}
///<summary>Asset path to absolute system path</summary>
public static string AssetToSystemPath(UnityEngine.Object obj) {
var assetPath = AssetDatabase.GetAssetPath(obj);
return AssetToSystemPath(assetPath);
}
///<summary>Asset path to absolute system path</summary>
public static string AssetToSystemPath(string assetPath) {
if ( !string.IsNullOrEmpty(assetPath) ) {
return Application.dataPath.Remove(Application.dataPath.LastIndexOf('/')) + '/' + assetPath;
}
return null;
}
///<summary>Get all scene names (added in build settings)</summary>
public static List<string> GetSceneNames() {
var allSceneNames = new List<string>();
foreach ( var scene in EditorBuildSettings.scenes ) {
if ( scene.enabled ) {
var name = scene.path.Substring(scene.path.LastIndexOf("/") + 1);
name = name.Substring(0, name.Length - 6);
allSceneNames.Add(name);
}
}
return allSceneNames;
}
}
}
#endif

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f4676c1c75b3f474da4734cc2fd16c81
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,408 @@
#if UNITY_EDITOR
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
namespace ParadoxNotion.Design
{
///<summary> ContextMenus, mostly reflection ones</summary>
partial class EditorUtils
{
///<summary>A generic purpose menu to pick an item</summary>
public static GenericMenu GetMenu<T>(List<T> options, T current, Action<T> callback) {
var menu = new GenericMenu();
foreach ( var _option in options ) {
var option = _option;
var label = option != null ? option.ToString() : "null";
menu.AddItem(new GUIContent(label), object.Equals(current, option), () => { callback(option); });
}
return menu;
}
///<summary>Get a selection menu of types deriving base type</summary>
public static GenericMenu GetTypeSelectionMenu(Type baseType, Action<Type> callback, GenericMenu menu = null, string subCategory = null) {
if ( menu == null ) {
menu = new GenericMenu();
}
if ( subCategory != null ) {
subCategory = subCategory + "/";
}
GenericMenu.MenuFunction2 Selected = delegate (object selectedType)
{
callback((Type)selectedType);
};
var scriptInfos = GetScriptInfosOfType(baseType);
foreach ( var info in scriptInfos.Where(info => string.IsNullOrEmpty(info.category)) ) {
menu.AddItem(new GUIContent(subCategory + info.name), false, info.type != null ? Selected : null, info.type);
}
foreach ( var info in scriptInfos.Where(info => !string.IsNullOrEmpty(info.category)) ) {
menu.AddItem(new GUIContent(subCategory + info.category + "/" + info.name), false, info.type != null ? Selected : null, info.type);
}
return menu;
}
///<summary> !* Providing an open GenericTypeDefinition for 'baseType', wraps the Preferred Types wihin the 1st Generic Argument of that Definition *!</summary>
public static GenericMenu GetPreferedTypesSelectionMenu(Type baseType, Action<Type> callback, GenericMenu menu = null, string subCategory = null, bool showAddTypeOption = false) {
if ( menu == null ) {
menu = new GenericMenu();
}
if ( subCategory != null ) {
subCategory = subCategory + "/";
}
var constrainType = baseType;
var isGenericDefinition = baseType.IsGenericTypeDefinition && baseType.RTGetGenericArguments().Length == 1;
var genericDefinitionType = isGenericDefinition ? baseType : null;
if ( isGenericDefinition ) {
constrainType = genericDefinitionType.GetFirstGenericParameterConstraintType();
}
GenericMenu.MenuFunction2 Selected = (object t) => { callback((Type)t); };
var listTypes = new Dictionary<Type, string>();
var dictTypes = new Dictionary<Type, string>();
foreach ( var t in TypePrefs.GetPreferedTypesList(constrainType, true) ) {
var nsString = t.NamespaceToPath() + "/";
var finalType = isGenericDefinition && genericDefinitionType.TryMakeGeneric(t, out Type genericType) ? genericType : t;
var finalString = nsString + finalType.FriendlyName();
menu.AddItem(new GUIContent(subCategory + finalString), false, Selected, finalType);
var listType = typeof(List<>).MakeGenericType(t);
var finalListType = isGenericDefinition && genericDefinitionType.TryMakeGeneric(listType, out Type genericListType) ? genericListType : listType;
if ( constrainType.IsAssignableFrom(finalListType) ) {
listTypes[finalListType] = nsString;
}
var dictType = typeof(Dictionary<,>).MakeGenericType(typeof(string), t);
var finalDictType = isGenericDefinition && genericDefinitionType.TryMakeGeneric(dictType, out Type genericDictType) ? genericDictType : dictType;
if ( constrainType.IsAssignableFrom(finalDictType) ) {
dictTypes[finalDictType] = nsString;
}
//by request extra append dictionary <string, List<T>>
var dictListType = typeof(Dictionary<,>).MakeGenericType(typeof(string), typeof(List<>).MakeGenericType(t));
var finalDictListType = isGenericDefinition && genericDefinitionType.TryMakeGeneric(dictListType, out Type genericDictListType) ? genericDictListType : dictListType;
if ( constrainType.IsAssignableFrom(finalDictListType) ) {
dictTypes[finalDictListType] = nsString;
}
}
foreach ( var pair in listTypes ) {
menu.AddItem(new GUIContent(subCategory + TypePrefs.LIST_MENU_STRING + pair.Value + pair.Key.FriendlyName()), false, Selected, pair.Key);
}
foreach ( var pair in dictTypes ) {
menu.AddItem(new GUIContent(subCategory + TypePrefs.DICT_MENU_STRING + pair.Value + pair.Key.FriendlyName()), false, Selected, pair.Key);
}
if ( showAddTypeOption ) {
menu.AddItem(new GUIContent(subCategory + "Add Type..."), false, () => { TypePrefsEditorWindow.ShowWindow(); });
}
if ( menu.GetItemCount() == 0 ) {
menu.AddDisabledItem(new GUIContent(string.Format("No {0} derived types found in Preferred Types List", baseType.Name)));
}
return menu;
}
//...
public static void ShowPreferedTypesSelectionMenu(Type type, Action<Type> callback) {
GetPreferedTypesSelectionMenu(type, callback).ShowAsBrowser("Select Type");
}
///----------------------------------------------------------------------------------------------
public static GenericMenu GetInstanceFieldSelectionMenu(Type type, Type fieldType, Action<FieldInfo> callback, GenericMenu menu = null, string subMenu = null) {
return Internal_GetFieldSelectionMenu(BindingFlags.Public | BindingFlags.Instance, type, fieldType, callback, menu, subMenu);
}
public static GenericMenu GetStaticFieldSelectionMenu(Type type, Type fieldType, Action<FieldInfo> callback, GenericMenu menu = null, string subMenu = null) {
return Internal_GetFieldSelectionMenu(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy, type, fieldType, callback, menu, subMenu);
}
///<summary>Get a GenericMenu for field selection in a type</summary>
static GenericMenu Internal_GetFieldSelectionMenu(BindingFlags flags, Type type, Type fieldType, Action<FieldInfo> callback, GenericMenu menu = null, string subMenu = null) {
if ( menu == null ) {
menu = new GenericMenu();
}
if ( subMenu != null ) {
subMenu = subMenu + "/";
}
GenericMenu.MenuFunction2 Selected = delegate (object selectedField)
{
callback((FieldInfo)selectedField);
};
foreach ( var field in type.GetFields(flags).Where(field => fieldType.IsAssignableFrom(field.FieldType)) ) {
var inherited = field.DeclaringType != type;
var category = inherited ? subMenu + type.FriendlyName() + "/Inherited" : subMenu + type.FriendlyName();
menu.AddItem(new GUIContent(string.Format("{0}/{1} : {2}", category, field.Name, field.FieldType.FriendlyName())), false, Selected, field);
}
return menu;
}
///----------------------------------------------------------------------------------------------
public static GenericMenu GetInstancePropertySelectionMenu(Type type, Type propType, Action<PropertyInfo> callback, bool mustRead = true, bool mustWrite = true, GenericMenu menu = null, string subMenu = null) {
return Internal_GetPropertySelectionMenu(BindingFlags.Public | BindingFlags.Instance, type, propType, callback, mustRead, mustWrite, menu, subMenu);
}
public static GenericMenu GetStaticPropertySelectionMenu(Type type, Type propType, Action<PropertyInfo> callback, bool mustRead = true, bool mustWrite = true, GenericMenu menu = null, string subMenu = null) {
return Internal_GetPropertySelectionMenu(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy, type, propType, callback, mustRead, mustWrite, menu, subMenu);
}
///<summary>Get a GenericMenu for properties of a type optionaly specifying mustRead & mustWrite</summary>
static GenericMenu Internal_GetPropertySelectionMenu(BindingFlags flags, Type type, Type propType, Action<PropertyInfo> callback, bool mustRead = true, bool mustWrite = true, GenericMenu menu = null, string subMenu = null) {
if ( menu == null ) {
menu = new GenericMenu();
}
if ( subMenu != null ) {
subMenu = subMenu + "/";
}
GenericMenu.MenuFunction2 Selected = delegate (object selectedProperty)
{
callback((PropertyInfo)selectedProperty);
};
foreach ( var prop in type.GetProperties(flags) ) {
if ( !prop.CanRead && mustRead ) {
continue;
}
if ( !prop.CanWrite && mustWrite ) {
continue;
}
if ( !propType.IsAssignableFrom(prop.PropertyType) ) {
continue;
}
if ( prop.GetCustomAttributes(typeof(System.ObsoleteAttribute), true).FirstOrDefault() != null ) {
continue;
}
var inherited = prop.DeclaringType != type;
var category = inherited ? subMenu + type.FriendlyName() + "/Inherited" : subMenu + type.FriendlyName();
menu.AddItem(new GUIContent(string.Format("{0}/{1} : {2}", category, prop.Name, prop.PropertyType.FriendlyName())), false, Selected, prop);
}
return menu;
}
///----------------------------------------------------------------------------------------------
///<summary>Get a menu for instance methods</summary>
public static GenericMenu GetInstanceMethodSelectionMenu(Type type, Type returnType, Type acceptedParamsType, System.Action<MethodInfo> callback, int maxParameters, bool propertiesOnly, bool excludeVoid = false, GenericMenu menu = null, string subMenu = null) {
return Internal_GetMethodSelectionMenu(BindingFlags.Public | BindingFlags.Instance, type, returnType, acceptedParamsType, callback, maxParameters, propertiesOnly, excludeVoid, menu, subMenu);
}
///<summary>Get a menu for static methods</summary>
public static GenericMenu GetStaticMethodSelectionMenu(Type type, Type returnType, Type acceptedParamsType, System.Action<MethodInfo> callback, int maxParameters, bool propertiesOnly, bool excludeVoid = false, GenericMenu menu = null, string subMenu = null) {
return Internal_GetMethodSelectionMenu(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy, type, returnType, acceptedParamsType, callback, maxParameters, propertiesOnly, excludeVoid, menu, subMenu);
}
///<summary>Get a GenericMenu for method or property get/set methods selection in a type</summary>
static GenericMenu Internal_GetMethodSelectionMenu(BindingFlags flags, Type type, Type returnType, Type acceptedParamsType, System.Action<MethodInfo> callback, int maxParameters, bool propertiesOnly, bool excludeVoid = false, GenericMenu menu = null, string subMenu = null) {
if ( menu == null ) {
menu = new GenericMenu();
}
if ( subMenu != null ) {
subMenu = subMenu + "/";
}
GenericMenu.MenuFunction2 Selected = delegate (object selectedMethod)
{
callback((MethodInfo)selectedMethod);
};
foreach ( var method in type.GetMethods(flags) ) {
if ( propertiesOnly != method.IsPropertyAccessor() ) {
continue;
}
if ( method.IsGenericMethod ) {
continue;
}
if ( !returnType.IsAssignableFrom(method.ReturnType) ) {
continue;
}
if ( method.ReturnType == typeof(void) && excludeVoid ) {
continue;
}
var parameters = method.GetParameters();
if ( parameters.Length > maxParameters && maxParameters != -1 ) {
continue;
}
if ( parameters.Length > 0 ) {
if ( acceptedParamsType != typeof(object) && parameters.Any(param => !acceptedParamsType.IsAssignableFrom(param.ParameterType)) ) {
continue;
}
}
MemberInfo member = method;
//get the actual property to check for ObsoleteAttribute
if ( method.Name.StartsWith("get_") || method.Name.StartsWith("set_") ) {
member = method.DeclaringType.GetProperty(method.Name.Replace("get_", "").Replace("set_", ""));
}
if ( member == null || member.RTIsDefined(typeof(System.ObsoleteAttribute), true) ) {
continue;
}
var inherited = method.DeclaringType != type;
var category = inherited ? subMenu + type.FriendlyName() + "/Inherited" : subMenu + type.FriendlyName();
menu.AddItem(new GUIContent(category + "/" + method.SignatureName()), false, Selected, method);
}
return menu;
}
///----------------------------------------------------------------------------------------------
///<summary>Get a GenericMenu for Instance Events of the type and only event handler type of System.Action</summary>
public static GenericMenu GetInstanceEventSelectionMenu(Type type, Type argType, Action<EventInfo> callback, GenericMenu menu = null, string subMenu = null) {
return Internal_GetEventSelectionMenu(BindingFlags.Public | BindingFlags.Instance, type, argType, callback, menu, subMenu);
}
///<summary>Get a GenericMenu for Static Events of the type and only event handler type of System.Action</summary>
public static GenericMenu GetStaticEventSelectionMenu(Type type, Type argType, Action<EventInfo> callback, GenericMenu menu = null, string subMenu = null) {
return Internal_GetEventSelectionMenu(BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy, type, argType, callback, menu, subMenu);
}
///<summary>Get a GenericMenu for Events of the type and only event handler type of System.Action</summary>
static GenericMenu Internal_GetEventSelectionMenu(BindingFlags flags, Type type, Type argType, Action<EventInfo> callback, GenericMenu menu = null, string subMenu = null) {
if ( menu == null ) {
menu = new GenericMenu();
}
if ( subMenu != null ) {
subMenu = subMenu + "/";
}
GenericMenu.MenuFunction2 Selected = delegate (object selectedEvent)
{
callback((EventInfo)selectedEvent);
};
var eventType = argType == null ? typeof(System.Action) : typeof(System.Action<>).MakeGenericType(new Type[] { argType });
foreach ( var e in type.GetEvents(flags) ) {
if ( e.EventHandlerType == eventType ) {
var eventInfoString = string.Format("{0}({1})", e.Name, argType != null ? argType.FriendlyName() : "");
menu.AddItem(new GUIContent(subMenu + type.FriendlyName() + "/" + eventInfoString), false, Selected, e);
}
}
return menu;
}
///----------------------------------------------------------------------------------------------
///<summary>MenuItemInfo exposition</summary>
public struct MenuItemInfo
{
public bool isValid { get; private set; }
public GUIContent content;
public bool separator;
public bool selected;
public GenericMenu.MenuFunction func;
public GenericMenu.MenuFunction2 func2;
public object userData;
public MenuItemInfo(GUIContent c, bool sep, bool slc, GenericMenu.MenuFunction f1, GenericMenu.MenuFunction2 f2, object o) {
isValid = true;
content = c;
separator = sep;
selected = slc;
func = f1;
func2 = f2;
userData = o;
}
}
///<summary>Gets an array of MenuItemInfo out of the GenericMenu provided</summary>
public static MenuItemInfo[] GetMenuItems(GenericMenu menu) {
var itemField = typeof(GenericMenu).GetField("menuItems", BindingFlags.Instance | BindingFlags.NonPublic);
if ( itemField == null ) { itemField = typeof(GenericMenu).GetField("m_MenuItems", BindingFlags.Instance | BindingFlags.NonPublic); }
var items = itemField.GetValue(menu) as IList;
if ( items.Count == 0 ) {
return new MenuItemInfo[0];
}
var itemType = items[0].GetType();
var contentGetter = ReflectionTools.GetFieldGetter<object, GUIContent>(itemType.GetField("content"));
var sepGetter = ReflectionTools.GetFieldGetter<object, bool>(itemType.GetField("separator"));
var selectedGetter = ReflectionTools.GetFieldGetter<object, bool>(itemType.GetField("on"));
var func1Getter = ReflectionTools.GetFieldGetter<object, GenericMenu.MenuFunction>(itemType.GetField("func"));
var func2Getter = ReflectionTools.GetFieldGetter<object, GenericMenu.MenuFunction2>(itemType.GetField("func2"));
var dataGetter = ReflectionTools.GetFieldGetter<object, object>(itemType.GetField("userData"));
var result = new List<MenuItemInfo>();
foreach ( var item in items ) {
var content = contentGetter(item);
var separator = sepGetter(item);
var selected = selectedGetter(item);
var func1 = func1Getter(item);
var func2 = func2Getter(item);
var userData = dataGetter(item);
result.Add(new MenuItemInfo(content, separator, selected, func1, func2, userData));
}
return result.ToArray();
}
///<summary>Shows the Generic Menu as a browser with CompleteContextMenu.</summary>
public static void ShowAsBrowser(this GenericMenu menu, Vector2 pos, string title, System.Type keyType = null) {
if ( menu != null ) { GenericMenuBrowser.Show(menu, pos, title, keyType); }
}
///<summary>Shows the Generic Menu as a browser with CompleteContextMenu.</summary>
public static void ShowAsBrowser(this GenericMenu menu, string title, System.Type keyType = null) {
if ( menu != null ) { GenericMenuBrowser.Show(menu, Event.current.mousePosition, title, keyType); }
}
///<summary>Shortcut</summary>
public static void Show(this GenericMenu menu, bool asBrowser, string title, System.Type keyType = null) {
if ( asBrowser ) { menu.ShowAsBrowser(title, keyType); } else { menu.ShowAsContext(); Event.current.Use(); }
}
}
}
#endif

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fe15795089e56c545803799233bd2512
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,382 @@
#if UNITY_EDITOR
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityObject = UnityEngine.Object;
using Logger = ParadoxNotion.Services.Logger;
namespace ParadoxNotion.Design
{
///<summary> Specific Editor GUIs</summary>
partial class EditorUtils
{
///<summary>Stores fold states</summary>
private static readonly Dictionary<Type, bool> registeredEditorFoldouts = new Dictionary<Type, bool>();
///<summary>A cool label :-P (for headers)</summary>
public static void CoolLabel(string text) {
GUI.skin.label.richText = true;
GUI.color = Colors.lightOrange;
GUILayout.Label("<b><size=14>" + text + "</size></b>", Styles.topLeftLabel);
GUI.color = Color.white;
GUILayout.Space(2);
}
///<summary>Combines the rest functions for a header style label</summary>
public static void TitledSeparator(string title) {
GUILayout.Space(1);
BoldSeparator();
CoolLabel(title + " ▼");
Separator();
}
///<summary>A thin separator</summary>
public static void Separator() {
var lastRect = GUILayoutUtility.GetLastRect();
GUILayout.Space(7);
GUI.color = new Color(0, 0, 0, 0.3f);
GUI.DrawTexture(Rect.MinMaxRect(lastRect.xMin, lastRect.yMax + 4, lastRect.xMax, lastRect.yMax + 6), Texture2D.whiteTexture);
GUI.color = Color.white;
}
///<summary>A thick separator</summary>
public static void BoldSeparator() {
var lastRect = GUILayoutUtility.GetLastRect();
GUILayout.Space(14);
GUI.color = new Color(0, 0, 0, 0.3f);
GUI.DrawTexture(new Rect(0, lastRect.yMax + 6, Screen.width, 4), Texture2D.whiteTexture);
GUI.DrawTexture(new Rect(0, lastRect.yMax + 6, Screen.width, 1), Texture2D.whiteTexture);
GUI.DrawTexture(new Rect(0, lastRect.yMax + 9, Screen.width, 1), Texture2D.whiteTexture);
GUI.color = Color.white;
}
///<summary>Just a fancy ending for inspectors</summary>
public static void EndOfInspector() {
var lastRect = GUILayoutUtility.GetLastRect();
GUILayout.Space(8);
GUI.color = new Color(0, 0, 0, 0.4f);
GUI.DrawTexture(new Rect(0, lastRect.yMax + 6, Screen.width, 4), Texture2D.whiteTexture);
GUI.DrawTexture(new Rect(0, lastRect.yMax + 4, Screen.width, 1), Texture2D.whiteTexture);
GUI.color = Color.white;
}
///<summary>A Search Field</summary>
public static string SearchField(string search) {
GUILayout.BeginHorizontal();
search = EditorGUILayout.TextField(search, Styles.toolbarSearchTextField);
if ( !string.IsNullOrEmpty(search) && GUILayout.Button(string.Empty, Styles.toolbarSearchCancelButton) ) {
search = string.Empty;
GUIUtility.keyboardControl = 0;
}
GUILayout.EndHorizontal();
return search;
}
///<summary>Used just after a textfield with no prefix to show an italic transparent text inside when empty</summary>
public static void CommentLastTextField(string check, string comment = "Comments...") {
if ( string.IsNullOrEmpty(check) ) {
var lastRect = GUILayoutUtility.GetLastRect();
GUI.Label(lastRect, " <i>" + comment + "</i>", Styles.topLeftLabel);
}
}
///<summary>Used just after a field to highlight it</summary>
public static void HighlightLastField() {
var lastRect = GUILayoutUtility.GetLastRect();
lastRect.xMin += 2;
lastRect.xMax -= 2;
lastRect.yMax -= 4;
Styles.Draw(lastRect, Styles.highlightBox);
}
///<summary>Used just after a field to mark it as a prefab override (similar to native unity's one)</summary>
public static void MarkLastFieldOverride() {
var rect = GUILayoutUtility.GetLastRect();
rect.x -= 3; rect.width = 2;
GUI.color = Colors.prefabOverrideColor;
GUI.DrawTexture(rect, Texture2D.whiteTexture);
GUI.color = Color.white;
}
///<summary>Used just after a field to mark warning icon to it</summary>
public static void MarkLastFieldWarning(string tooltip) {
Internal_MarkLastField(ParadoxNotion.Design.Icons.warningIcon, tooltip);
}
///<summary>Used just after a field to mark warning icon to it</summary>
public static void MarkLastFieldError(string tooltip) {
Internal_MarkLastField(ParadoxNotion.Design.Icons.errorIcon, tooltip);
}
//...
static void Internal_MarkLastField(Texture2D icon, string tooltip) {
var rect = GUILayoutUtility.GetLastRect();
rect.x += UnityEditor.EditorGUIUtility.labelWidth;
rect.x -= 16;
rect.y += 1;
rect.width = 16;
rect.height = 16;
GUI.Box(rect, EditorUtils.GetTempContent(null, icon, tooltip), GUIStyle.none);
}
// public static Rect BeginHighlightArea() {
// var rect = GUILayoutUtility.GetLastRect();
// GUILayout.BeginVertical();
// return rect;
// }
// public static void EndHighlightArea(Rect beginRect) {
// GUILayout.EndVertical();
// var last = GUILayoutUtility.GetLastRect();
// var rect = Rect.MinMaxRect(beginRect.xMin, beginRect.yMin, last.xMax, last.yMax);
// Styles.Draw(rect, Styles.highlightBox);
// }
///<summary>Editor for LayerMask</summary>
public static LayerMask LayerMaskField(string prefix, LayerMask layerMask, params GUILayoutOption[] layoutOptions) {
return LayerMaskField(string.IsNullOrEmpty(prefix) ? GUIContent.none : new GUIContent(prefix), layerMask, layoutOptions);
}
///<summary>Editor for LayerMask</summary>
public static LayerMask LayerMaskField(GUIContent content, LayerMask layerMask, params GUILayoutOption[] layoutOptions) {
LayerMask tempMask = EditorGUILayout.MaskField(content, UnityEditorInternal.InternalEditorUtility.LayerMaskToConcatenatedLayersMask(layerMask), UnityEditorInternal.InternalEditorUtility.layers, layoutOptions);
layerMask = UnityEditorInternal.InternalEditorUtility.ConcatenatedLayersMaskToLayerMask(tempMask);
return layerMask;
}
///<summary>Do a cached editor Foldout based on provided key object</summary>
public static bool CachedFoldout(Type key, GUIContent content) {
var foldout = false;
registeredEditorFoldouts.TryGetValue(key, out foldout);
foldout = EditorGUILayout.Foldout(foldout, content);
return registeredEditorFoldouts[key] = foldout;
}
///<summary>An IList editor (List<T> and Arrays)</summary>
public static IList ListEditor(GUIContent content, IList list, Type listType, InspectedFieldInfo info) {
var optionsAtt = info.attributes?.FirstOrDefault(x => x is ListInspectorOptionAttribute) as ListInspectorOptionAttribute;
var argType = listType.GetEnumerableElementType();
if ( argType == null ) {
return list;
}
if ( object.Equals(list, null) ) {
GUILayout.Label("Null List");
return list;
}
if ( optionsAtt == null || optionsAtt.showFoldout ) {
if ( !CachedFoldout(listType, content) ) {
return list;
}
} else {
GUILayout.Label(content.text);
}
GUILayout.BeginVertical();
EditorGUI.indentLevel++;
var options = new ReorderableListOptions();
options.allowAdd = optionsAtt == null || optionsAtt.allowAdd;
options.allowRemove = optionsAtt == null || optionsAtt.allowRemove;
options.unityObjectContext = info.unityObjectContext;
list = EditorUtils.ReorderableList(list, options, (i, r) =>
{
list[i] = ReflectedFieldInspector("Element " + i, list[i], argType, info);
});
EditorGUI.indentLevel--;
Separator();
GUILayout.EndVertical();
return list;
}
///<summary>A IDictionary editor</summary>
public static IDictionary DictionaryEditor(GUIContent content, IDictionary dict, Type dictType, InspectedFieldInfo info) {
var keyType = dictType.RTGetGenericArguments()[0];
var valueType = dictType.RTGetGenericArguments()[1];
if ( object.Equals(dict, null) ) {
GUILayout.Label("Null Dictionary");
return dict;
}
if ( !CachedFoldout(dictType, content) ) {
return dict;
}
GUILayout.BeginVertical();
var keys = dict.Keys.Cast<object>().ToList();
var values = dict.Values.Cast<object>().ToList();
if ( GUILayout.Button("Add Element") ) {
if ( !typeof(UnityObject).IsAssignableFrom(keyType) ) {
object newKey = null;
if ( keyType == typeof(string) ) {
newKey = string.Empty;
} else {
newKey = Activator.CreateInstance(keyType);
}
if ( dict.Contains(newKey) ) {
Logger.LogWarning(string.Format("Key '{0}' already exists in Dictionary", newKey.ToString()), "Editor");
return dict;
}
keys.Add(newKey);
} else {
Logger.LogWarning("Can't add a 'null' Dictionary Key", "Editor");
return dict;
}
values.Add(valueType.IsValueType ? Activator.CreateInstance(valueType) : null);
}
for ( var i = 0; i < keys.Count; i++ ) {
GUILayout.BeginHorizontal("box");
GUILayout.Box("", GUILayout.Width(6), GUILayout.Height(35));
GUILayout.BeginVertical();
keys[i] = ReflectedFieldInspector("K:", keys[i], keyType, info);
values[i] = ReflectedFieldInspector("V:", values[i], valueType, info);
GUILayout.EndVertical();
if ( GUILayout.Button("X", GUILayout.Width(18), GUILayout.Height(34)) ) {
keys.RemoveAt(i);
values.RemoveAt(i);
}
GUILayout.EndHorizontal();
}
//clear and reconstruct on separate pass after GUI controls
dict.Clear();
for ( var i = 0; i < keys.Count; i++ ) {
try { dict.Add(keys[i], values[i]); }
catch { Logger.Log("Dictionary Key removed due to duplicate found", "Editor"); }
}
Separator();
GUILayout.EndVertical();
return dict;
}
///<summary>An editor field where if the component is null simply shows an object field, but if its not, shows a dropdown popup to select the specific component from within the gameobject</summary>
public static Component ComponentField(GUIContent content, Component comp, Type type, params GUILayoutOption[] GUIOptions) {
if ( comp == null ) {
return EditorGUILayout.ObjectField(content, comp, type, true, GUIOptions) as Component;
}
var components = comp.GetComponents(type).ToList();
var componentNames = components.Where(c => c != null).Select(c => c.GetType().FriendlyName() + " (" + c.gameObject.name + ")").ToList();
componentNames.Insert(0, "[NONE]");
var index = components.IndexOf(comp);
index = EditorGUILayout.Popup(content, index, componentNames.Select(n => new GUIContent(n)).ToArray(), GUIOptions);
return index == 0 ? null : components[index];
}
///<summary>A popup that is based on the string rather than the index</summary>
public static string StringPopup(GUIContent content, string selected, IEnumerable<string> options, params GUILayoutOption[] GUIOptions) {
EditorGUILayout.BeginVertical();
var index = 0;
var copy = new List<string>(options);
copy.Insert(0, "[NONE]");
index = copy.Contains(selected) ? copy.IndexOf(selected) : 0;
index = EditorGUILayout.Popup(content, index, copy.Select(n => new GUIContent(n)).ToArray(), GUIOptions);
EditorGUILayout.EndVertical();
return index == 0 ? string.Empty : copy[index];
}
///<summary>Generic Popup for selection of any element within a list</summary>
public static T Popup<T>(T selected, IEnumerable<T> options, params GUILayoutOption[] GUIOptions) {
return Popup<T>(GUIContent.none, selected, options, GUIOptions);
}
///<summary>Generic Popup for selection of any element within a list</summary>
public static T Popup<T>(string prefix, T selected, IEnumerable<T> options, params GUILayoutOption[] GUIOptions) {
return Popup<T>(string.IsNullOrEmpty(prefix) ? GUIContent.none : new GUIContent(prefix), selected, options, GUIOptions);
}
///<summary>Generic Popup for selection of any element within a list</summary>
public static T Popup<T>(GUIContent content, T selected, IEnumerable<T> options, params GUILayoutOption[] GUIOptions) {
var listOptions = new List<T>(options);
listOptions.Insert(0, default(T));
var stringedOptions = new List<string>(listOptions.Select(o => o != null ? o.ToString() : "[NONE]"));
stringedOptions[0] = listOptions.Count == 1 ? "[NONE AVAILABLE]" : "[NONE]";
var index = 0;
if ( listOptions.Contains(selected) ) {
index = listOptions.IndexOf(selected);
}
var wasEnable = GUI.enabled;
GUI.enabled = wasEnable && stringedOptions.Count > 1;
index = EditorGUILayout.Popup(content, index, stringedOptions.Select(s => new GUIContent(s)).ToArray(), GUIOptions);
GUI.enabled = wasEnable;
return index == 0 ? default(T) : listOptions[index];
}
///<summary>Generic Button Popup for selection of any element within a list</summary>
public static void ButtonPopup<T>(string prefix, T selected, List<T> options, Action<T> Callback) {
ButtonPopup<T>(string.IsNullOrEmpty(prefix) ? GUIContent.none : new GUIContent(prefix), selected, options, Callback);
}
///<summary>Generic Button Popup for selection of any element within a list</summary>
public static void ButtonPopup<T>(GUIContent content, T selected, List<T> options, Action<T> Callback) {
var buttonText = selected != null ? selected.ToString() : "[NONE]";
GUILayout.BeginHorizontal();
if ( content != null && content != GUIContent.none ) {
GUILayout.Label(content, GUILayout.Width(0), GUILayout.ExpandWidth(true));
}
if ( GUILayout.Button(buttonText, (GUIStyle)"MiniPopup", GUILayout.Width(0), GUILayout.ExpandWidth(true)) ) {
var menu = new GenericMenu();
foreach ( var _option in options ) {
var option = _option;
menu.AddItem(new GUIContent(option != null ? option.ToString() : "[NONE]"), object.Equals(selected, option), () => { Callback(option); });
}
menu.ShowAsBrowser("Select Option");
}
GUILayout.EndHorizontal();
}
///<summary>Specialized Type button popup</summary>
public static void ButtonTypePopup(string prefix, Type selected, Action<Type> Callback) {
ButtonTypePopup(string.IsNullOrEmpty(prefix) ? GUIContent.none : new GUIContent(prefix), selected, Callback);
}
///<summary>Specialized Type button popup</summary>
public static void ButtonTypePopup(GUIContent content, Type selected, Action<Type> Callback) {
var buttonText = selected != null ? selected.FriendlyName() : "[NONE]";
GUILayout.BeginHorizontal();
if ( content != null && content != GUIContent.none ) {
GUILayout.Label(content, GUILayout.Width(0), GUILayout.ExpandWidth(true));
}
if ( GUILayout.Button(buttonText, (GUIStyle)"MiniPopup", GUILayout.Width(0), GUILayout.ExpandWidth(true)) ) {
var menu = EditorUtils.GetPreferedTypesSelectionMenu(typeof(object), Callback);
menu.ShowAsBrowser("Select Type");
}
GUILayout.EndHorizontal();
}
}
}
#endif

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1b2198a3a4aa5b44199f1deba4b3ed80
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,309 @@
#if UNITY_EDITOR
using System;
using System.Collections;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityObject = UnityEngine.Object;
namespace ParadoxNotion.Design
{
///<summary>Automatic Inspector functions</summary>
partial class EditorUtils
{
private static GUIContent tempContent;
///<summary>A cached temporary content</summary>
public static GUIContent GetTempContent(string text = "", Texture image = null, string tooltip = null) {
if ( tempContent == null ) { tempContent = new GUIContent(); }
tempContent.text = text;
tempContent.image = image;
tempContent.tooltip = tooltip;
return tempContent;
}
///<summary>A cached temporary content</summary>
public static GUIContent GetTempContent(Texture image = null, string tooltip = null) {
return GetTempContent(null, image, tooltip);
}
///<summary>Show an automatic editor GUI inspector for target object, taking into account drawer attributes</summary>
public static void ReflectedObjectInspector(object target, UnityObject unityObjectContext) {
if ( target == null ) {
return;
}
var fields = target.GetType().RTGetFields();
for ( var i = 0; i < fields.Length; i++ ) {
var field = fields[i];
//no statics
if ( field.IsStatic ) { continue; }
//hide type altogether?
if ( field.FieldType.RTIsDefined(typeof(HideInInspector), true) ) { continue; }
//inspect only public fields or private fields with the [ExposeField] attribute
if ( field.IsPublic || field.RTIsDefined(typeof(ExposeFieldAttribute), true) ) {
var attributes = field.RTGetAllAttributes();
//Hide field?
if ( attributes.Any(a => a is HideInInspector) ) { continue; }
var serializationInfo = new InspectedFieldInfo(unityObjectContext, field, target, attributes);
var currentValue = field.GetValue(target);
var newValue = ReflectedFieldInspector(field.Name, currentValue, field.FieldType, serializationInfo);
var changed = !object.Equals(newValue, currentValue);
if ( changed ) { UndoUtility.RecordObject(unityObjectContext, field.Name); }
if ( changed || field.FieldType.IsValueType ) {
field.SetValue(target, newValue);
}
if ( changed ) { UndoUtility.SetDirty(unityObjectContext); }
}
}
}
///<summary>Draws an Editor field for object of type directly WITH taking into acount object drawers and drawer attributes</summary>
public static object ReflectedFieldInspector(string name, object value, Type t, InspectedFieldInfo info) {
var content = GetTempContent(name.SplitCamelCase());
if ( info.attributes != null ) {
//Create proper GUIContent
var nameAtt = info.attributes.FirstOrDefault(a => a is NameAttribute) as NameAttribute;
if ( nameAtt != null ) { content.text = nameAtt.name; }
var tooltipAtt = info.attributes.FirstOrDefault(a => a is TooltipAttribute) as TooltipAttribute;
if ( tooltipAtt != null ) { content.tooltip = tooltipAtt.tooltip; }
}
return ReflectedFieldInspector(content, value, t, info);
}
///<summary>Draws an Editor field for object of type directly WITH taking into acount object drawers and drawer attributes</summary>
public static object ReflectedFieldInspector(GUIContent content, object value, Type t, InspectedFieldInfo info) {
if ( t == null ) {
GUILayout.Label("NO TYPE PROVIDED!");
return value;
}
//Use drawers
var objectDrawer = PropertyDrawerFactory.GetObjectDrawer(t);
var newValue = objectDrawer.DrawGUI(content, value, info);
var changed = !object.Equals(newValue, value);
if ( changed ) { UndoUtility.RecordObjectComplete(info.unityObjectContext, content.text + "Field Change"); }
value = newValue;
if ( changed ) { UndoUtility.SetDirty(info.unityObjectContext); }
return value;
}
///<summary>Draws an Editor field for object of type directly WITHOUT taking into acount object drawers and drawer attributes unless provided</summary>
public static object DrawEditorFieldDirect(GUIContent content, object value, Type t, InspectedFieldInfo info) {
///----------------------------------------------------------------------------------------------
bool handled;
EditorGUI.BeginChangeCheck();
var newValue = DirectFieldControl(content, value, t, info.unityObjectContext, info.attributes, out handled);
var changed = !object.Equals(newValue, value) || EditorGUI.EndChangeCheck();
if ( changed ) { UndoUtility.RecordObjectComplete(info.unityObjectContext, content.text + "Field Change"); }
value = newValue;
if ( changed ) { UndoUtility.SetDirty(info.unityObjectContext); }
if ( handled ) { return value; }
///----------------------------------------------------------------------------------------------
if ( typeof(IList).IsAssignableFrom(t) ) {
return ListEditor(content, (IList)value, t, info);
}
if ( typeof(IDictionary).IsAssignableFrom(t) ) {
return DictionaryEditor(content, (IDictionary)value, t, info);
}
//show nested class members recursively, avoid all collections not handles above manually
if ( value != null && ( t.IsClass || t.IsValueType ) && !typeof(ICollection).IsAssignableFrom(t) ) {
if ( EditorGUI.indentLevel <= 8 ) {
if ( !CachedFoldout(t, content) ) {
return value;
}
EditorGUI.indentLevel++;
ReflectedObjectInspector(value, info.unityObjectContext);
EditorGUI.indentLevel--;
}
} else {
EditorGUILayout.LabelField(content, new GUIContent(string.Format("NonInspectable ({0})", t.FriendlyName())));
}
return value;
}
//...
public static object DirectFieldControl(GUIContent content, object value, Type t, UnityEngine.Object unityObjectContext, object[] attributes, out bool handled, params GUILayoutOption[] options) {
handled = true;
//Check scene object type for UnityObjects. Consider Interfaces as scene object type. Assume that user uses interfaces with UnityObjects
if ( typeof(UnityObject).IsAssignableFrom(t) || t.IsInterface ) {
if ( value == null || value is UnityObject ) { //check this to avoid case of interface but no unityobject
var isSceneObjectType = ( typeof(Component).IsAssignableFrom(t) || t == typeof(GameObject) || t == typeof(UnityObject) || t.IsInterface );
var newValue = EditorGUILayout.ObjectField(content, (UnityObject)value, t, isSceneObjectType, options);
if ( unityObjectContext != null && newValue != null ) {
if ( !Application.isPlaying && EditorUtility.IsPersistent(unityObjectContext) && !EditorUtility.IsPersistent(newValue as UnityEngine.Object) ) {
ParadoxNotion.Services.Logger.LogWarning("Assets can not have scene object references", "Editor", unityObjectContext);
newValue = value as UnityObject;
}
}
return newValue;
}
}
//Check Type second
if ( t == typeof(Type) ) {
return Popup<Type>(content, (Type)value, TypePrefs.GetPreferedTypesList(true), options);
}
//get real current type
t = value != null ? value.GetType() : t;
//for these just show type information
if ( t.IsAbstract || t == typeof(object) || typeof(Delegate).IsAssignableFrom(t) || typeof(UnityEngine.Events.UnityEventBase).IsAssignableFrom(t) ) {
EditorGUILayout.LabelField(content, new GUIContent(string.Format("({0})", t.FriendlyName())), options);
return value;
}
//create instance for value types
if ( value == null && t.RTIsValueType() ) {
value = System.Activator.CreateInstance(t);
}
//create new instance with button for non value types
if ( value == null && !t.IsAbstract && !t.IsInterface && ( t.IsArray || t.GetConstructor(Type.EmptyTypes) != null ) ) {
if ( content != GUIContent.none ) {
GUILayout.BeginHorizontal();
EditorGUILayout.PrefixLabel(content, GUI.skin.button);
}
if ( GUILayout.Button("(null) Create", options) ) {
value = t.IsArray ? Array.CreateInstance(t.GetElementType(), 0) : Activator.CreateInstance(t);
}
if ( content != GUIContent.none ) { GUILayout.EndHorizontal(); }
return value;
}
///----------------------------------------------------------------------------------------------
if ( t == typeof(string) ) {
return EditorGUILayout.TextField(content, (string)value, options);
}
if ( t == typeof(char) ) {
var c = (char)value;
var s = c.ToString();
s = EditorGUILayout.TextField(content, s, options);
return string.IsNullOrEmpty(s) ? (char)c : (char)s[0];
}
if ( t == typeof(bool) ) {
return EditorGUILayout.Toggle(content, (bool)value, options);
}
if ( t == typeof(int) ) {
return EditorGUILayout.IntField(content, (int)value, options);
}
if ( t == typeof(float) ) {
return EditorGUILayout.FloatField(content, (float)value, options);
}
if ( t == typeof(byte) ) {
return Convert.ToByte(Mathf.Clamp(EditorGUILayout.IntField(content, (byte)value, options), 0, 255));
}
if ( t == typeof(long) ) {
return EditorGUILayout.LongField(content, (long)value, options);
}
if ( t == typeof(double) ) {
return EditorGUILayout.DoubleField(content, (double)value, options);
}
if ( t == typeof(Vector2) ) {
return EditorGUILayout.Vector2Field(content, (Vector2)value, options);
}
if ( t == typeof(Vector2Int) ) {
return EditorGUILayout.Vector2IntField(content, (Vector2Int)value, options);
}
if ( t == typeof(Vector3) ) {
return EditorGUILayout.Vector3Field(content, (Vector3)value, options);
}
if ( t == typeof(Vector3Int) ) {
return EditorGUILayout.Vector3IntField(content, (Vector3Int)value, options);
}
if ( t == typeof(Vector4) ) {
return EditorGUILayout.Vector4Field(content, (Vector4)value, options);
}
if ( t == typeof(Quaternion) ) {
var quat = (Quaternion)value;
var vec4 = new Vector4(quat.x, quat.y, quat.z, quat.w);
vec4 = EditorGUILayout.Vector4Field(content, vec4, options);
return new Quaternion(vec4.x, vec4.y, vec4.z, vec4.w);
}
if ( t == typeof(Color) ) {
var att = attributes?.FirstOrDefault(a => a is ColorUsageAttribute) as ColorUsageAttribute;
var hdr = att != null ? att.hdr : false;
var showAlpha = att != null ? att.showAlpha : true;
return EditorGUILayout.ColorField(content, (Color)value, true, showAlpha, hdr, options);
}
if ( t == typeof(Gradient) ) {
return EditorGUILayout.GradientField(content, (Gradient)value, options);
}
if ( t == typeof(Rect) ) {
return EditorGUILayout.RectField(content, (Rect)value, options);
}
if ( t == typeof(AnimationCurve) ) {
return EditorGUILayout.CurveField(content, (AnimationCurve)value, options);
}
if ( t == typeof(Bounds) ) {
return EditorGUILayout.BoundsField(content, (Bounds)value, options);
}
if ( t == typeof(LayerMask) ) {
return LayerMaskField(content, (LayerMask)value, options);
}
if ( t.IsSubclassOf(typeof(System.Enum)) ) {
if ( t.RTIsDefined(typeof(FlagsAttribute), true) ) {
return EditorGUILayout.EnumFlagsField(content, (System.Enum)value, options);
}
return EditorGUILayout.EnumPopup(content, (System.Enum)value, options);
}
handled = false;
return value;
}
}
}
#endif

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f82d383bba56d6a4d87929dcd962745a
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,217 @@
#if UNITY_EDITOR
using System.Collections;
using System.Linq;
using UnityEditor;
using UnityEngine;
using UnityObject = UnityEngine.Object;
namespace ParadoxNotion.Design
{
partial class EditorUtils
{
public delegate void ReorderableListCallback(int index, bool isPicked);
private static int pickedListIndex = -1;
private static IList pickedList;
public struct ReorderableListOptions
{
public delegate GenericMenu GetItemMenuDelegate(int i);
public bool blockReorder;
public bool allowAdd;
public bool allowRemove;
public UnityObject unityObjectContext;
public GetItemMenuDelegate customItemMenu;
}
///<summary> A simple reorderable list. Pass the list and a function to call for GUI. The callback comes with the current iterated element index in the list</summary>
public static IList ReorderableList(IList list, ReorderableListCallback GUICallback) {
return ReorderableList(list, default(ReorderableListOptions), GUICallback);
}
///<summary> A simple reorderable list. Pass the list and a function to call for GUI. The callback comes with the current iterated element index in the list</summary>
public static IList ReorderableList(IList list, ReorderableListOptions options, ReorderableListCallback GUICallback) {
if ( list == null ) {
return null;
}
var listType = list.GetType();
var argType = listType.GetEnumerableElementType();
if ( argType == null ) {
return list;
}
var e = Event.current;
if ( options.allowAdd ) {
var dropRefs = DragAndDrop.objectReferences;
//Drag And Drop.
if ( dropRefs.Length > 0 ) {
if ( dropRefs.Any(r => argType.IsAssignableFrom(r.GetType()) || ( r.GetType() == typeof(GameObject) && typeof(Component).IsAssignableFrom(argType) )) ) {
var dropRect = GUILayoutUtility.GetRect(0, 20, GUILayout.ExpandWidth(true));
dropRect.xMin += 5;
dropRect.xMax -= 5;
Styles.Draw(dropRect, Styles.roundedBox);
GUI.Box(dropRect, "Drop Here to Enlist", Styles.centerLabel);
if ( dropRect.Contains(e.mousePosition) ) {
if ( e.type == EventType.DragUpdated ) {
DragAndDrop.visualMode = DragAndDropVisualMode.Copy;
e.Use();
}
if ( e.type == EventType.DragPerform ) {
for ( var i = 0; i < dropRefs.Length; i++ ) {
var dropRef = dropRefs[i];
var dropRefType = dropRef.GetType();
if ( argType.IsAssignableFrom(dropRefType) ) {
UndoUtility.RecordObject(options.unityObjectContext, "Drag Add Item");
list.Add(dropRef);
GUI.changed = true;
UndoUtility.SetDirty(options.unityObjectContext);
continue;
}
if ( dropRefType == typeof(GameObject) && typeof(Component).IsAssignableFrom(argType) ) {
var componentToAdd = ( dropRef as GameObject ).GetComponent(argType);
if ( componentToAdd != null ) {
UndoUtility.RecordObject(options.unityObjectContext, "Drag Add Item");
list.Add(componentToAdd);
GUI.changed = true;
UndoUtility.SetDirty(options.unityObjectContext);
}
continue;
}
}
e.Use();
}
}
}
}
//Add new default element
if ( dropRefs.Length == 0 ) {
if ( GUILayout.Button("Add Element") ) {
UndoUtility.RecordObject(options.unityObjectContext, "Add Item");
var o = argType.IsValueType ? argType.CreateObjectUninitialized() : null;
if ( listType.IsArray ) {
list = ReflectionTools.Resize((System.Array)list, list.Count + 1);
} else {
list.Add(o);
}
GUI.changed = true;
UndoUtility.SetDirty(options.unityObjectContext);
return list;
}
}
}
if ( list.Count == 0 ) {
return list;
}
for ( var i = 0; i < list.Count; i++ ) {
GUILayout.BeginHorizontal();
GUILayout.Space(16);
GUILayout.BeginVertical();
GUICallback(i, pickedListIndex == i && pickedList == list);
GUILayout.EndVertical();
var lastRect = GUILayoutUtility.GetLastRect();
var pickRect = Rect.MinMaxRect(lastRect.xMin - 16, lastRect.yMin, lastRect.xMin, lastRect.yMax);
GUI.color = new Color(1, 1, 1, 0.5f);
GUI.Label(pickRect, options.blockReorder ? EditorUtils.GetTempContent("■", null, "Re-Ordering Is Disabled") : EditorUtils.GetTempContent("☰"), Styles.centerLabel);
GUI.color = Color.white;
if ( options.customItemMenu != null ) {
GUILayout.Space(18);
var buttonRect = Rect.MinMaxRect(lastRect.xMax, lastRect.yMin, lastRect.xMax + 22, lastRect.yMax + 1);
EditorGUIUtility.AddCursorRect(buttonRect, MouseCursor.Link);
GUI.color = EditorGUIUtility.isProSkin ? Color.white : Color.grey;
if ( GUI.Button(buttonRect, Icons.gearPopupIcon, Styles.centerLabel) ) {
UndoUtility.RecordObject(options.unityObjectContext, "Menu Item");
options.customItemMenu(i).ShowAsContext();
GUI.changed = true;
GUIUtility.hotControl = 0;
GUIUtility.keyboardControl = 0;
UndoUtility.SetDirty(options.unityObjectContext);
}
GUI.color = Color.white;
}
if ( options.allowRemove ) {
GUILayout.Space(20);
var buttonRect = Rect.MinMaxRect(lastRect.xMax + 2, lastRect.yMin, lastRect.xMax + 20, lastRect.yMax);
if ( GUI.Button(buttonRect, "X") ) {
UndoUtility.RecordObject(options.unityObjectContext, "Remove Item");
if ( listType.IsArray ) {
list = ReflectionTools.Resize((System.Array)list, list.Count - 1);
} else {
list.RemoveAt(i);
}
GUI.changed = true;
GUIUtility.hotControl = 0;
GUIUtility.keyboardControl = 0;
UndoUtility.SetDirty(options.unityObjectContext);
}
}
GUILayout.EndHorizontal();
GUI.color = Color.white;
GUI.backgroundColor = Color.white;
if ( !options.blockReorder ) { EditorGUIUtility.AddCursorRect(pickRect, MouseCursor.MoveArrow); }
var boundRect = GUILayoutUtility.GetLastRect();
if ( pickRect.Contains(e.mousePosition) && e.type == EventType.MouseDown && !options.blockReorder ) {
pickedList = list;
pickedListIndex = i;
GUIUtility.hotControl = 0;
GUIUtility.keyboardControl = 0;
e.Use();
}
if ( pickedList == list ) {
if ( pickedListIndex == i ) {
GUI.Box(boundRect, string.Empty);
}
if ( pickedListIndex != -1 && pickedListIndex != i && boundRect.Contains(e.mousePosition) ) {
var markRect = new Rect(boundRect.x, boundRect.y - 2, boundRect.width, 2);
if ( pickedListIndex < i ) {
markRect.y = boundRect.yMax - 2;
}
GUI.DrawTexture(markRect, Texture2D.whiteTexture);
if ( e.type == EventType.MouseUp ) {
UndoUtility.RecordObject(options.unityObjectContext, "Reorder Item");
var pickObj = list[pickedListIndex];
list.RemoveAt(pickedListIndex);
list.Insert(i, pickObj);
GUI.changed = true;
UndoUtility.SetDirty(options.unityObjectContext);
pickedList = null;
pickedListIndex = -1;
e.Use();
}
}
}
}
//just rest in case out of rect
if ( e.rawType == EventType.MouseUp ) {
if ( list == pickedList ) {
pickedList = null;
pickedListIndex = -1;
}
}
return list;
}
}
}
#endif

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b97faf2d46c8ec043a8f0b20f9024058
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,150 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
namespace ParadoxNotion.Design
{
//reflection meta info
partial class EditorUtils
{
[InitializeOnLoadMethod]
static void Initialize_ScriptInfos() {
TypePrefs.onPreferredTypesChanged -= FlushScriptInfos;
TypePrefs.onPreferredTypesChanged += FlushScriptInfos;
}
//Flush script infos cache
public static void FlushScriptInfos() {
cachedInfos = null;
}
//For gathering script/type meta-information
public struct ScriptInfo
{
public bool isValid { get; private set; }
public Type originalType;
public string originalName;
public string originalCategory;
public Type type;
public string name;
public string category;
public int priority;
public ScriptInfo(Type type, string name, string category, int priority) {
this.isValid = true;
this.originalType = type;
this.originalName = name;
this.originalCategory = category;
this.type = type;
this.name = name;
this.category = category;
this.priority = priority;
}
}
///<summary>Get a list of ScriptInfos of the baseType excluding: the base type, abstract classes, Obsolete classes and those with the DoNotList attribute, categorized as a list of ScriptInfo</summary>
private static Dictionary<Type, List<ScriptInfo>> cachedInfos;
public static List<ScriptInfo> GetScriptInfosOfType(Type baseType) {
if ( cachedInfos == null ) { cachedInfos = new Dictionary<Type, List<ScriptInfo>>(); }
List<ScriptInfo> infosResult;
if ( cachedInfos.TryGetValue(baseType, out infosResult) ) {
return infosResult.ToList();
}
infosResult = new List<ScriptInfo>();
var subTypes = baseType.IsGenericTypeDefinition ? new Type[] { baseType } : ReflectionTools.GetImplementationsOf(baseType);
foreach ( var subType in subTypes ) {
if ( subType.IsAbstract || subType.RTIsDefined(typeof(DoNotListAttribute), true) || subType.RTIsDefined(typeof(ObsoleteAttribute), true) ) {
continue;
}
var isGeneric = subType.IsGenericTypeDefinition && subType.RTGetGenericArguments().Length == 1;
var scriptName = subType.FriendlyName().SplitCamelCase();
var scriptCategory = string.Empty;
var scriptPriority = 0;
var nameAttribute = subType.RTGetAttribute<NameAttribute>(true);
if ( nameAttribute != null ) {
scriptPriority = nameAttribute.priority;
scriptName = nameAttribute.name;
if ( isGeneric && !scriptName.EndsWith("<T>") ) {
scriptName += " (T)";
}
}
var categoryAttribute = subType.RTGetAttribute<CategoryAttribute>(true);
if ( categoryAttribute != null ) {
scriptCategory = categoryAttribute.category;
}
var info = new ScriptInfo(subType, scriptName, scriptCategory, scriptPriority);
//add the generic types based on constrains and prefered types list
if ( isGeneric ) {
var exposeAsBaseDefinition = NodeCanvas.Editor.Prefs.collapseGenericTypes || subType.RTIsDefined<ExposeAsDefinitionAttribute>(true);
if ( !exposeAsBaseDefinition ) {
var typesToWrap = TypePrefs.GetPreferedTypesList(true);
foreach ( var t in typesToWrap ) {
infosResult.Add(info.MakeGenericInfo(t, string.Format("/{0}/{1}", info.name, t.NamespaceToPath())));
infosResult.Add(info.MakeGenericInfo(typeof(List<>).MakeGenericType(t), string.Format("/{0}/{1}{2}", info.name, TypePrefs.LIST_MENU_STRING, t.NamespaceToPath()), -1));
infosResult.Add(info.MakeGenericInfo(typeof(Dictionary<,>).MakeGenericType(typeof(string), t), string.Format("/{0}/{1}{2}", info.name, TypePrefs.DICT_MENU_STRING, t.NamespaceToPath()), -2));
//by request extra append dictionary <string, List<T>>
infosResult.Add(info.MakeGenericInfo(typeof(Dictionary<,>).MakeGenericType(typeof(string), typeof(List<>).MakeGenericType (t) ), string.Format("/{0}/{1}{2}", info.name, TypePrefs.DICT_MENU_STRING, t.NamespaceToPath()), -2));
}
continue;
}
}
infosResult.Add(info);
}
infosResult = infosResult
.Where(s => s.isValid)
.OrderBy(s => s.originalCategory)
.ThenBy(s => s.priority * -1)
.ThenBy(s => s.originalName)
.ToList();
cachedInfos[baseType] = infosResult;
return infosResult;
}
///<summary>Makes and returns a closed generic ScriptInfo for targetType out of an existing ScriptInfo</summary>
public static ScriptInfo MakeGenericInfo(this ScriptInfo info, Type targetType, string subCategory = null, int priorityShift = 0) {
if ( !info.isValid || !info.originalType.IsGenericTypeDefinition ) {
return default(ScriptInfo);
}
if ( info.originalType.TryMakeGeneric(targetType, out Type genericType) ) {
var genericCategory = info.originalCategory + subCategory;
var genericName = info.originalName.Replace("(T)", string.Format("({0})", targetType.FriendlyName()));
var newInfo = new ScriptInfo(genericType, genericName, genericCategory, info.priority + priorityShift);
newInfo.originalType = info.originalType;
newInfo.originalName = info.originalName;
newInfo.originalCategory = info.originalCategory;
return newInfo;
}
return default(ScriptInfo);
}
///<summary>Not really. Only for purposes of menus usage.</summary>
static string NamespaceToPath(this Type type) {
if ( type == null ) { return string.Empty; }
return string.IsNullOrEmpty(type.Namespace) ? "No Namespace" : type.Namespace.Split('.').First();
}
}
}
#endif

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 94b281ae1067f0c4ba9b8d27c2fb8178
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,7 @@
#if UNITY_EDITOR
namespace ParadoxNotion.Design
{
///<summary>Have some commonly stuff used across most inspectors and helper functions. Keep outside of Editor folder since many runtime classes use this in #if UNITY_EDITOR. This is a partial class. Different implementation provide different tools, so that everything is referenced from within one class.</summary>
public static partial class EditorUtils { }
}
#endif

View File

@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 9eb95ac4d073bc449b98b80fb983d1d1
timeCreated: 1543951637
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,131 @@
#if UNITY_EDITOR
using System;
using System.Reflection;
namespace ParadoxNotion.Design
{
///<summary>Factory for EditorObjectWrappers</summary>
public static class EditorWrapperFactory
{
private static WeakReferenceTable<object, EditorObjectWrapper> cachedEditors = new WeakReferenceTable<object, EditorObjectWrapper>();
///<summary>Returns a cached EditorObjectWrapper of type T for target object</summary>
public static T GetEditor<T>(object target) where T : EditorObjectWrapper {
EditorObjectWrapper wrapper;
if ( cachedEditors.TryGetValueWithRefCheck(target, out wrapper) ) {
return (T)wrapper;
}
wrapper = (T)( typeof(T).CreateObject() );
wrapper.Enable(target);
cachedEditors.Add(target, wrapper);
return (T)wrapper;
}
}
///----------------------------------------------------------------------------------------------
///<summary>Wrapper Editor for objects</summary>
abstract public class EditorObjectWrapper : IDisposable
{
private WeakReference<object> _targetRef;
//The target
public object target {
get
{
_targetRef.TryGetTarget(out object reference);
return reference;
}
}
//...
void IDisposable.Dispose() { OnDisable(); }
///<summary>Init for target</summary>
public void Enable(object target) {
this._targetRef = new WeakReference<object>(target);
OnEnable();
}
///<summary>Create Property and Method wrappers here or other stuff.</summary>
virtual protected void OnEnable() { }
///<summary>Cleanup</summary>
virtual protected void OnDisable() { }
///<summary>Get a wrapped editor serialized field on target</summary>
public EditorPropertyWrapper<T> CreatePropertyWrapper<T>(string name) {
var type = target.GetType();
var field = type.RTGetField(name, /*include private base*/ true);
if ( field != null ) {
var wrapper = (EditorPropertyWrapper<T>)typeof(EditorPropertyWrapper<>).MakeGenericType(typeof(T)).CreateObject();
wrapper.Init(this, field);
return wrapper;
}
return null;
}
///<summary>Get a wrapped editor method on target</summary>
public EditorMethodWrapper CreateMethodWrapper(string name) {
var type = target.GetType();
var method = type.RTGetMethod(name);
if ( method != null ) {
var wrapper = new EditorMethodWrapper();
wrapper.Init(this, method);
return wrapper;
}
return null;
}
}
///<summary>Wrapper Editor for objects</summary>
abstract public class EditorObjectWrapper<T> : EditorObjectWrapper
{
new public T target { get { return (T)base.target; } }
}
///----------------------------------------------------------------------------------------------
///<summary>An editor wrapped field</summary>
sealed public class EditorPropertyWrapper<T>
{
private EditorObjectWrapper editor { get; set; }
private FieldInfo field { get; set; }
public T value {
get
{
var o = field.GetValue(editor.target);
return o != null ? (T)o : default(T);
}
set
{
field.SetValue(editor.target, value);
}
}
public void Init(EditorObjectWrapper editor, FieldInfo field) {
this.editor = editor;
this.field = field;
}
}
///----------------------------------------------------------------------------------------------
///<summary>An editor wrapped method</summary>
sealed public class EditorMethodWrapper
{
private EditorObjectWrapper editor { get; set; }
private MethodInfo method { get; set; }
public void Invoke(params object[] args) {
method.Invoke(editor.target, args);
}
public void Init(EditorObjectWrapper editor, MethodInfo method) {
this.editor = editor;
this.method = method;
}
}
}
#endif

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: c8364c09f7a38544ab08ff1a13a47739
timeCreated: 1510983225
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,104 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
namespace ParadoxNotion.Design
{
///<summary>A generic popup editor</summary>
public class GenericInspectorWindow : EditorWindow
{
private static GenericInspectorWindow current;
private string friendlyTitle;
private System.Type targetType;
private Object unityObjectContext;
private System.Func<object> read;
private System.Action<object> write;
private Vector2 scrollPos;
private bool willRepaint;
// ...
void OnEnable() {
titleContent = new GUIContent("Object Editor");
current = this;
#if UNITY_2017_2_OR_NEWER
EditorApplication.playModeStateChanged -= PlayModeChange;
EditorApplication.playModeStateChanged += PlayModeChange;
#else
EditorApplication.playmodeStateChanged -= PlayModeChange;
EditorApplication.playmodeStateChanged += PlayModeChange;
#endif
}
//...
void OnDisable() {
#if UNITY_2017_2_OR_NEWER
EditorApplication.playModeStateChanged -= PlayModeChange;
#else
EditorApplication.playmodeStateChanged -= PlayModeChange;
#endif
}
#if UNITY_2017_2_OR_NEWER
void PlayModeChange(PlayModeStateChange state) { Close(); }
#else
void PlayModeChange(){ Close(); }
#endif
///<summary>Open utility window to inspect target object of type in context using read/write delegates.</summary>
public static void Show(string title, System.Type targetType, Object unityObjectContext, System.Func<object> read, System.Action<object> write) {
var window = current != null ? current : CreateInstance<GenericInspectorWindow>();
window.friendlyTitle = title;
window.targetType = targetType;
window.unityObjectContext = unityObjectContext;
window.write = write;
window.read = read;
window.ShowUtility();
}
//...
void Update() {
if ( willRepaint ) {
willRepaint = false;
Repaint();
}
}
//...
void OnGUI() {
if ( targetType == null ) {
return;
}
var e = Event.current;
if ( e.type == EventType.ValidateCommand && e.commandName == "UndoRedoPerformed" ) {
GUIUtility.hotControl = 0;
GUIUtility.keyboardControl = 0;
e.Use();
return;
}
GUILayout.Space(10);
GUILayout.Label(string.Format("<size=14><b>{0}</b></size>", targetType.FriendlyName()), Styles.centerLabel);
EditorUtils.Separator();
GUILayout.Space(10);
scrollPos = GUILayout.BeginScrollView(scrollPos);
var serializationInfo = new InspectedFieldInfo(unityObjectContext, null, null, null);
var oldValue = read();
var newValue = EditorUtils.ReflectedFieldInspector(friendlyTitle, oldValue, targetType, serializationInfo);
if ( !Equals(oldValue, newValue) || GUI.changed ) {
write(newValue);
}
GUILayout.EndScrollView();
willRepaint = true;
}
}
}
#endif

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 25316af9468ffe04f8946375b92e7e79
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,645 @@
#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using ParadoxNotion.Serialization;
using ParadoxNotion.Services;
using System.Threading.Tasks;
namespace ParadoxNotion.Design
{
///<summary>Proviving a UnityEditor.GenericMenu, shows a complete popup browser.</summary>
public class GenericMenuBrowser : PopupWindowContent
{
//class node used in browser
class Node
{
public string name;
public string fullPath;
public bool unfolded;
public EditorUtils.MenuItemInfo item;
public Node parent;
public Dictionary<string, Node> children;
public Node() {
children = new Dictionary<string, Node>(System.StringComparer.Ordinal);
unfolded = true;
}
//Leafs have menu items
public bool isLeaf {
get { return item.isValid; }
}
public string category {
get { return parent != null ? parent.fullPath : string.Empty; }
}
//Is node favorite?
public bool isFavorite {
get
{
if ( current.favorites.Contains(fullPath) ) {
return true;
}
var p = parent;
while ( p != null ) {
if ( p.isFavorite ) {
return true;
}
p = p.parent;
}
return false;
}
}
//Does node has any favorite children?
public bool HasAnyFavoriteChild() {
if ( !string.IsNullOrEmpty(fullPath) ) {
return current.favorites.Any(p => p.StartsWith(fullPath + "/"));
}
return false;
}
//Toggle favorite state
public void ToggleFavorite() {
SetFavorite(!isFavorite);
}
//Set favorite state
void SetFavorite(bool fav) {
if ( fav == true && !isFavorite ) {
current.AddFavorite(fullPath);
}
if ( fav == false && isFavorite ) {
current.RemoveFavorite(fullPath);
}
}
}
///----------------------------------------------------------------------------------------------
///<summary>Browser preferences and saved favorites per key</summary>
class SerializationData
{
public Dictionary<string, List<string>> allFavorites;
public bool filterFavorites;
public SerializationData() {
allFavorites = new Dictionary<string, List<string>>(System.StringComparer.Ordinal);
filterFavorites = false;
}
}
///----------------------------------------------------------------------------------------------
public static GenericMenuBrowser current { get; private set; }
private const string PREFERENCES_KEY = "ParadoxNotion.ContextBrowserPreferences_2";
private const float HELP_RECT_HEIGHT = 58;
private readonly Color hoverColor = new Color(0.5f, 0.5f, 1, 0.3f);
private static System.Threading.Thread menuGenerationThread;
private static System.Threading.Thread treeGenerationThread;
private static System.Threading.Thread searchGenerationThread;
private SerializationData data;
private System.Type currentKeyType;
private List<string> favorites;
private bool _filterFavorites;
private bool filterFavorites {
get { return _filterFavorites && currentKeyType != null; }
set { _filterFavorites = value; }
}
private GenericMenu boundMenu;
private EditorUtils.MenuItemInfo[] items;
private Node rootNode;
private List<Node> leafNodes;
private Node currentNode;
private bool willRepaint;
private float loadProgress;
private string headerTitle;
private Vector2 scrollPos;
private string lastSearch;
private string search;
private int lastHoveringIndex;
private int hoveringIndex;
private float helpRectRequiredHeight;
private System.Type wasFocusedWindowType;
///----------------------------------------------------------------------------------------------
private GUIStyle _helpStyle;
private GUIStyle helpStyle {
get
{
if ( _helpStyle == null ) {
_helpStyle = new GUIStyle(Styles.topLeftLabel);
_helpStyle.wordWrap = true;
}
return _helpStyle;
}
}
///----------------------------------------------------------------------------------------------
//...
public override Vector2 GetWindowSize() { return new Vector2(480, Mathf.Max(500 + helpRectRequiredHeight, 500)); }
///<summary>Shows the popup menu at position and with title. getMenu is called async</summary>
public static void ShowAsync(Vector2 pos, string title, System.Type keyType, System.Func<GenericMenu> getMenu) {
current = new GenericMenuBrowser(null, title, keyType);
menuGenerationThread = Threader.StartFunction(menuGenerationThread, getMenu, (m) =>
{
if ( current != null ) { current.SetMenu(m); }
menuGenerationThread = null;
});
PopupWindow.Show(new Rect(pos.x, pos.y, 0, 0), current);
}
///<summary>Shows the popup menu at position and with title</summary>
public static GenericMenuBrowser Show(GenericMenu newMenu, Vector2 pos, string title, System.Type keyType) {
current = new GenericMenuBrowser(newMenu, title, keyType);
PopupWindow.Show(new Rect(pos.x, pos.y, 0, 0), current);
return current;
}
///<summary>constructor</summary>
GenericMenuBrowser(GenericMenu newMenu, string title, System.Type keyType) {
current = this;
headerTitle = title;
currentKeyType = keyType;
rootNode = new Node();
currentNode = rootNode;
lastHoveringIndex = -1;
hoveringIndex = -1;
SetMenu(newMenu);
}
///<summary>Set another menu after it's open</summary>
void SetMenu(GenericMenu newMenu) {
if ( newMenu == null ) {
return;
}
willRepaint = true;
boundMenu = newMenu;
treeGenerationThread = Threader.StartAction(treeGenerationThread, current.GenerateTree, () =>
{
treeGenerationThread = null;
willRepaint = true;
});
}
//editor opened
public override void OnOpen() {
EditorApplication.update -= OnEditorUpdate;
EditorApplication.update += OnEditorUpdate;
wasFocusedWindowType = EditorWindow.focusedWindow?.GetType();
LoadPrefs();
}
//editor closed
public override void OnClose() {
SavePrefs();
EditorApplication.update -= OnEditorUpdate;
// if ( menuGenerationThread != null && menuGenerationThread.IsAlive ) { menuGenerationThread.Abort(); menuGenerationThread = null; }
if ( treeGenerationThread != null && treeGenerationThread.IsAlive ) { treeGenerationThread.Abort(); treeGenerationThread = null; }
if ( searchGenerationThread != null && searchGenerationThread.IsAlive ) { searchGenerationThread.Abort(); searchGenerationThread = null; }
current = null;
if ( wasFocusedWindowType != null ) { EditorWindow.FocusWindowIfItsOpen(wasFocusedWindowType); }
}
//check flag and repaint?
void OnEditorUpdate() {
if ( willRepaint ) {
willRepaint = false;
base.editorWindow.Repaint();
}
}
//...
void LoadPrefs() {
if ( data == null ) {
var json = EditorPrefs.GetString(PREFERENCES_KEY);
if ( !string.IsNullOrEmpty(json) ) { data = JSONSerializer.Deserialize<SerializationData>(json); }
if ( data == null ) { data = new SerializationData(); }
filterFavorites = data.filterFavorites;
if ( currentKeyType != null ) {
data.allFavorites.TryGetValue(currentKeyType.Name, out favorites);
}
if ( favorites == null ) {
favorites = new List<string>();
}
}
}
//...
void SavePrefs() {
data.filterFavorites = filterFavorites;
if ( currentKeyType != null ) {
data.allFavorites[currentKeyType.Name] = favorites;
}
EditorPrefs.SetString(PREFERENCES_KEY, JSONSerializer.Serialize(typeof(SerializationData), data));
}
//...
void AddFavorite(string path) {
if ( !favorites.Contains(path) ) {
favorites.Add(path);
}
}
//...
void RemoveFavorite(string path) {
if ( favorites.Contains(path) ) {
favorites.Remove(path);
}
}
//Generate the tree node structure out of the items
void GenerateTree() {
loadProgress = 0;
var tempItems = EditorUtils.GetMenuItems(boundMenu);
var tempLeafNodes = new List<Node>();
var tempRoot = new Node();
for ( var i = 0; i < tempItems.Length; i++ ) {
loadProgress = i / (float)tempItems.Length;
var item = tempItems[i];
var itemPath = item.content.text;
var parts = itemPath.Split('/');
Node current = tempRoot;
var path = string.Empty;
for ( var j = 0; j < parts.Length; j++ ) {
var part = parts[j];
path += '/' + part;
Node child = null;
if ( !current.children.TryGetValue(part, out child) ) {
child = new Node { name = part, parent = current };
child.fullPath = path;
current.children[part] = child;
if ( part == parts.Last() ) {
child.item = item;
tempLeafNodes.Add(child);
}
}
current = child;
}
}
items = tempItems;
leafNodes = tempLeafNodes;
rootNode = tempRoot;
currentNode = rootNode;
}
//generate search results and return in a Node (that should be set as root node)
Node GenerateSearchResults() {
var searchRootNode = new Node() { name = "Search Root" };
searchRootNode.children = leafNodes
.Where(x => ( filterFavorites ? x.isFavorite : true ) && StringUtils.SearchMatch(search, x.name, x.category))
.OrderBy(x => StringUtils.ScoreSearchMatch(search, x.name, x.category) * ( x.isFavorite ? 0.5f : 1 ))
.ToDictionary(x => x.fullPath, y => y);
return searchRootNode;
}
//Show stuff
public override void OnGUI(Rect rect) {
var e = Event.current;
EditorGUIUtility.SetIconSize(Vector2.zero);
hoveringIndex = Mathf.Clamp(hoveringIndex, -1, currentNode.children.Count - 1);
if ( EditorGUIUtility.isProSkin ) {
Styles.Draw(rect, Styles.shadowedBackground);
}
var headerHeight = currentNode.parent != null ? 95 : 60;
var headerRect = new Rect(0, 0, rect.width, headerHeight);
DoHeader(headerRect, e);
if ( ( treeGenerationThread != null && treeGenerationThread.ThreadState != System.Threading.ThreadState.Stopped ) || items == null || items.Length == 0 ) {
var progressRect = new Rect(0, 0, 200, 20);
progressRect.center = rect.center;
EditorGUI.ProgressBar(progressRect, loadProgress, "Loading...");
willRepaint = true;
} else {
var treeRect = Rect.MinMaxRect(0, headerHeight, rect.width, rect.height - HELP_RECT_HEIGHT);
DoTree(treeRect, e);
}
var helpRect = Rect.MinMaxRect(2, rect.height - HELP_RECT_HEIGHT + 2, rect.width - 2, rect.height - 2);
DoFooter(helpRect, e);
//handle the events
HandeEvents(e);
EditorGUIUtility.SetIconSize(Vector2.zero);
}
//...
void DoHeader(Rect headerRect, Event e) {
//HEADER
GUILayout.Space(5);
GUILayout.Label(string.Format("<color=#{0}><size=14><b>{1}</b></size></color>", EditorGUIUtility.isProSkin ? "dddddd" : "222222", headerTitle), Styles.topCenterLabel);
//SEARCH
if ( e.keyCode == KeyCode.DownArrow ) { GUIUtility.keyboardControl = 0; }
if ( e.keyCode == KeyCode.UpArrow ) { GUIUtility.keyboardControl = 0; }
if ( e.keyCode == KeyCode.Return ) { GUIUtility.keyboardControl = 0; }
GUILayout.BeginHorizontal();
GUILayout.Space(4);
GUI.SetNextControlName("SearchToolbar");
search = EditorUtils.SearchField(search);
if ( currentKeyType != null ) {
filterFavorites = EditorGUILayout.ToggleLeft("FavOnly", filterFavorites, GUILayout.Width(70));
}
GUILayout.EndHorizontal();
EditorUtils.BoldSeparator();
//BACK
if ( currentNode.parent != null && string.IsNullOrEmpty(search) ) {
GUILayout.BeginHorizontal("box");
if ( GUILayout.Button(string.Format("<b><size=14>◄ {0}/{1}</size></b>", currentNode.parent.name, currentNode.name), Styles.leftLabel) ) {
currentNode = currentNode.parent;
}
GUILayout.EndHorizontal();
var lastRect = GUILayoutUtility.GetLastRect();
if ( lastRect.Contains(e.mousePosition) ) {
GUI.color = hoverColor;
GUI.DrawTexture(lastRect, EditorGUIUtility.whiteTexture);
GUI.color = Color.white;
willRepaint = true;
hoveringIndex = -1;
}
}
}
//THE TREE
void DoTree(Rect treeRect, Event e) {
if ( treeGenerationThread != null ) {
return;
}
if ( search != lastSearch ) {
lastSearch = search;
hoveringIndex = -1;
if ( !string.IsNullOrEmpty(search) ) {
// //provide null reference thread (thus no aborting) so that results update all the time
searchGenerationThread = Threader.StartFunction(null, GenerateSearchResults, (resultNode) =>
{
currentNode = resultNode;
searchGenerationThread = null;
if ( current != null ) { willRepaint = true; }
});
} else {
currentNode = rootNode;
}
}
GUILayout.BeginArea(treeRect);
scrollPos = EditorGUILayout.BeginScrollView(scrollPos, false, false);
GUILayout.BeginVertical();
///----------------------------------------------------------------------------------------------
var i = 0;
var itemAdded = false;
string lastSearchCategory = null;
var isSearch = !string.IsNullOrEmpty(search);
foreach ( var childPair in currentNode.children ) {
if ( isSearch && i >= 200 ) {
EditorGUILayout.HelpBox("There are more than 200 results. Please try refine your search input.", MessageType.Info);
break;
}
var node = childPair.Value;
var memberInfo = node.isLeaf ? node.item.userData as MemberInfo : null;
var isDisabled = node.isLeaf && node.item.func == null && node.item.func2 == null;
var icon = node.isLeaf ? node.item.content.image : Icons.folderIcon;
if ( icon == null && memberInfo != null ) {
icon = TypePrefs.GetTypeIcon(memberInfo);
}
//when within search, show category on top
if ( isSearch ) {
var searchCategory = lastSearchCategory;
if ( memberInfo == null || memberInfo is System.Type ) {
searchCategory = node.parent.fullPath != null ? node.parent.fullPath.Split(new char[] { '/' }, System.StringSplitOptions.RemoveEmptyEntries).FirstOrDefault() : null;
} else {
searchCategory = memberInfo.ReflectedType.FriendlyName();
}
if ( searchCategory != lastSearchCategory ) {
lastSearchCategory = searchCategory;
GUI.color = EditorGUIUtility.isProSkin ? Color.black : Color.white;
GUILayout.BeginHorizontal("box");
GUI.color = Color.white;
GUILayout.Label(searchCategory, Styles.leftLabel, GUILayout.Height(16));
GUILayout.EndHorizontal();
}
}
//
if ( filterFavorites && !node.isFavorite && !node.HasAnyFavoriteChild() ) {
continue;
}
if ( node.isLeaf && node.item.separator ) {
if ( itemAdded ) {
EditorUtils.Separator();
}
continue;
}
itemAdded = true;
GUI.color = Color.clear;
GUILayout.BeginHorizontal("box");
GUI.color = Color.white;
//Prefix icon
GUILayout.Label(icon, GUILayout.Width(22), GUILayout.Height(16));
GUI.enabled = !isDisabled;
//Favorite
if ( currentKeyType != null ) {
GUI.color = node.isFavorite ? Color.white : ( node.HasAnyFavoriteChild() ? new Color(1, 1, 1, 0.2f) : new Color(0f, 0f, 0f, 0.4f) );
if ( GUILayout.Button(Icons.favoriteIcon, GUIStyle.none, GUILayout.Width(16), GUILayout.Height(16)) ) {
node.ToggleFavorite();
}
GUI.color = Color.white;
}
//Content
var label = node.name;
var hexColor = EditorGUIUtility.isProSkin ? "#B8B8B8" : "#262626";
hexColor = isDisabled ? "#666666" : hexColor;
var text = string.Format("<color={0}><size=11>{1}</size></color>", hexColor, ( !node.isLeaf ? string.Format("<b>{0}</b>", label) : label ));
GUILayout.Label(text, Styles.leftLabel, GUILayout.Width(0), GUILayout.ExpandWidth(true));
GUILayout.Label(node.isLeaf ? "●" : "►", Styles.leftLabel, GUILayout.Width(20));
GUILayout.EndHorizontal();
var elementRect = GUILayoutUtility.GetLastRect();
if ( e.type == EventType.MouseDown && e.button == 0 && elementRect.Contains(e.mousePosition) ) {
e.Use();
if ( node.isLeaf ) {
ExecuteItemFunc(node.item);
break;
} else {
currentNode = node;
hoveringIndex = 0;
break;
}
}
if ( e.type == EventType.MouseMove && elementRect.Contains(e.mousePosition) ) {
hoveringIndex = i;
}
if ( hoveringIndex == i ) {
GUI.color = hoverColor;
GUI.DrawTexture(elementRect, EditorGUIUtility.whiteTexture);
GUI.color = Color.white;
}
i++;
GUI.enabled = true;
}
if ( hoveringIndex != lastHoveringIndex ) {
willRepaint = true;
lastHoveringIndex = hoveringIndex;
}
if ( !itemAdded ) {
GUILayout.Label("No results to display with current search and filter combination");
}
GUILayout.EndVertical();
EditorGUILayout.EndScrollView();
GUILayout.EndArea();
}
//HELP AREA
void DoFooter(Rect helpRect, Event e) {
helpRectRequiredHeight = 0;
var hoveringNode = hoveringIndex >= 0 && currentNode.children.Count > 0 ? currentNode.children.Values.ToList()[hoveringIndex] : null;
GUI.color = new Color(0, 0, 0, 0.3f);
Styles.Draw(helpRect, GUI.skin.textField);
GUI.color = Color.white;
GUILayout.BeginArea(helpRect);
GUILayout.BeginVertical();
var doc = string.Empty;
if ( hoveringNode != null && hoveringNode.isLeaf ) {
doc = hoveringNode.item.content.tooltip;
var memberInfo = hoveringNode.item.userData as MemberInfo;
if ( memberInfo != null && string.IsNullOrEmpty(doc) ) {
if ( memberInfo is System.Type ) {
doc = TypePrefs.GetTypeDoc(memberInfo);
} else {
doc = XMLDocs.GetMemberSummary(memberInfo);
}
}
}
GUILayout.Label(string.Format("<size=11>{0}</size>", doc), helpStyle);
GUILayout.EndVertical();
GUILayout.EndArea();
}
///----------------------------------------------------------------------------------------------
//Executes the item's registered delegate
void ExecuteItemFunc(EditorUtils.MenuItemInfo item) {
if ( item.func != null ) {
item.func();
} else {
item.func2(item.userData);
}
base.editorWindow.Close();
}
//Handle events
void HandeEvents(Event e) {
//Go back with right click as well...
if ( e.type == EventType.MouseDown && e.button == 1 ) {
if ( currentNode.parent != null ) {
currentNode = currentNode.parent;
}
e.Use();
}
if ( e.type == EventType.KeyDown ) {
if ( e.keyCode == KeyCode.RightArrow || e.keyCode == KeyCode.Return ) {
if ( hoveringIndex >= 0 ) {
var next = currentNode.children.Values.ToList()[hoveringIndex];
if ( e.keyCode == KeyCode.Return && next.isLeaf ) {
ExecuteItemFunc(next.item);
} else if ( !next.isLeaf ) {
currentNode = next;
hoveringIndex = 0;
}
e.Use();
return;
}
}
if ( e.keyCode == KeyCode.LeftArrow ) {
var previous = currentNode.parent;
if ( previous != null ) {
hoveringIndex = currentNode.parent.children.Values.ToList().IndexOf(currentNode);
currentNode = previous;
}
e.Use();
return;
}
if ( e.keyCode == KeyCode.DownArrow ) {
hoveringIndex++;
e.Use();
return;
}
if ( e.keyCode == KeyCode.UpArrow ) {
hoveringIndex = Mathf.Max(hoveringIndex - 1, 0);
e.Use();
return;
}
if ( e.keyCode == KeyCode.Escape ) {
base.editorWindow.Close();
e.Use();
return;
}
EditorGUI.FocusTextInControl("SearchToolbar");
}
}
}
}
#endif

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9d963bfbd43f9ec4ca490225535abeef
timeCreated: 1426970318
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,33 @@
#if UNITY_EDITOR
using System.Reflection;
namespace ParadoxNotion.Design
{
///<summary>Contains info about inspected field rin regards to reflected inspector and object/attribute drawers</summary>
public struct InspectedFieldInfo
{
///<summary>The field inspected</summary>
public FieldInfo field;
///<summary>the unityengine object serialization context</summary>
public UnityEngine.Object unityObjectContext;
///<summary>the parent instance the field lives within</summary>
public object parentInstanceContext;
///<summary>In case instance lives in wrapped context (eg lists) otherwise the same as parentInstanceContext</summary>
public object wrapperInstanceContext;
///<summary>attributes found on field</summary>
public object[] attributes;
//...
public InspectedFieldInfo(UnityEngine.Object unityObjectContext, FieldInfo field, object parentInstanceContext, object[] attributes) {
this.unityObjectContext = unityObjectContext;
this.field = field;
this.parentInstanceContext = parentInstanceContext;
this.wrapperInstanceContext = parentInstanceContext;
this.attributes = attributes;
}
}
}
#endif

View File

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

View File

@ -0,0 +1,243 @@
#if UNITY_EDITOR
using UnityEngine;
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Linq;
namespace ParadoxNotion.Design
{
///<summary>Provides object and attribute property drawers</summary>
public static class PropertyDrawerFactory
{
//Type to drawer instance map
private static Dictionary<Type, IObjectDrawer> objectDrawers = new Dictionary<Type, IObjectDrawer>();
private static Dictionary<Type, IAttributeDrawer> attributeDrawers = new Dictionary<Type, IAttributeDrawer>();
public static void FlushMem() {
objectDrawers = new Dictionary<Type, IObjectDrawer>();
attributeDrawers = new Dictionary<Type, IAttributeDrawer>();
}
///<summary>Return an object drawer instance of target inspected type</summary>
public static IObjectDrawer GetObjectDrawer(Type objectType) {
IObjectDrawer result = null;
if ( objectDrawers.TryGetValue(objectType, out result) ) {
return result;
}
// look for specific drawer first
Type fallbackDrawerType = null;
foreach ( var drawerType in ReflectionTools.GetImplementationsOf(typeof(IObjectDrawer)) ) {
if ( drawerType != typeof(DefaultObjectDrawer) ) {
var args = drawerType.BaseType.RTGetGenericArguments();
if ( args.Length == 1 ) {
if ( args[0].IsEquivalentTo(objectType) ) {
return objectDrawers[objectType] = Activator.CreateInstance(drawerType) as IObjectDrawer;
}
if ( args[0].IsAssignableFrom(objectType) ) { fallbackDrawerType = drawerType; }
}
}
}
if ( fallbackDrawerType != null ) {
return objectDrawers[objectType] = Activator.CreateInstance(fallbackDrawerType) as IObjectDrawer;
}
// foreach ( var drawerType in ReflectionTools.GetImplementationsOf(typeof(IObjectDrawer)) ) {
// if ( drawerType != typeof(DefaultObjectDrawer) ) {
// var args = drawerType.BaseType.RTGetGenericArguments();
// if ( args.Length == 1 && args[0].IsAssignableFrom(objectType) ) {
// return objectDrawers[objectType] = Activator.CreateInstance(drawerType) as IObjectDrawer;
// }
// }
// }
return objectDrawers[objectType] = new DefaultObjectDrawer(objectType);
}
///<summary>Return an attribute drawer instance of target attribute instance</summary>
public static IAttributeDrawer GetAttributeDrawer(DrawerAttribute att) { return GetAttributeDrawer(att.GetType()); }
///<summary>Return an attribute drawer instance of target attribute type</summary>
public static IAttributeDrawer GetAttributeDrawer(Type attributeType) {
IAttributeDrawer result = null;
if ( attributeDrawers.TryGetValue(attributeType, out result) ) {
return result;
}
foreach ( var drawerType in ReflectionTools.GetImplementationsOf(typeof(IAttributeDrawer)) ) {
if ( drawerType != typeof(DefaultAttributeDrawer) ) {
var args = drawerType.BaseType.RTGetGenericArguments();
if ( args.Length == 1 && args[0].IsAssignableFrom(attributeType) ) {
return attributeDrawers[attributeType] = Activator.CreateInstance(drawerType) as IAttributeDrawer;
}
}
}
return attributeDrawers[attributeType] = new DefaultAttributeDrawer(attributeType);
}
}
///----------------------------------------------------------------------------------------------
public interface IObjectDrawer
{
object DrawGUI(GUIContent content, object instance, InspectedFieldInfo info);
object MoveNextDrawer();
}
public interface IAttributeDrawer
{
object DrawGUI(IObjectDrawer objectDrawer, GUIContent content, object instance, DrawerAttribute attribute, InspectedFieldInfo info);
}
///----------------------------------------------------------------------------------------------
///<summary>Derive this to create custom drawers for T assignable object types.</summary>
abstract public class ObjectDrawer<T> : IObjectDrawer
{
///<summary>info</summary>
protected InspectedFieldInfo info { get; private set; }
///<summary>The GUIContent</summary>
protected GUIContent content { get; private set; }
///<summary>The instance of the object being drawn</summary>
protected T instance { get; private set; }
///<summary>The set of Drawer Attributes found on field</summary>
protected DrawerAttribute[] attributes { get; private set; }
///<summary>Current attribute index drawn</summary>
private int attributeIndex { get; set; }
///<summary>The reflected FieldInfo representation</summary>
protected FieldInfo fieldInfo { get { return info.field; } }
///<summary>The parent object the instance is drawn within</summary>
protected object context { get { return info.parentInstanceContext; } }
///<summary>The Unity object the instance serialized within</summary>
protected UnityEngine.Object contextUnityObject { get { return info.unityObjectContext; } }
///<summary>Begin GUI</summary>
object IObjectDrawer.DrawGUI(GUIContent content, object instance, InspectedFieldInfo info) {
this.content = content;
this.instance = (T)instance;
this.info = info;
this.attributes = info.attributes != null ? info.attributes.OfType<DrawerAttribute>().OrderBy(a => a.priority).ToArray() : null;
this.attributeIndex = -1;
var result = ( this as IObjectDrawer ).MoveNextDrawer();
// //flush references
this.info = default(InspectedFieldInfo);
this.content = null;
this.instance = default(T);
this.attributes = null;
return result;
}
///<summary>Show the next attribute drawer in order, or the object drawer itself of no attribute drawer is left to show.</summary>
object IObjectDrawer.MoveNextDrawer() {
attributeIndex++;
if ( attributes != null && attributeIndex < attributes.Length ) {
var currentDrawerAttribute = attributes[attributeIndex];
var drawer = PropertyDrawerFactory.GetAttributeDrawer(currentDrawerAttribute);
return drawer.DrawGUI(this, content, instance, currentDrawerAttribute, info);
}
return OnGUI(content, instance);
}
///<summary>Override to implement GUI. Return the modified instance at the end.</summary>
abstract public T OnGUI(GUIContent content, T instance);
}
///<summary>The default object drawer implementation able to inspect most types</summary>
public class DefaultObjectDrawer : ObjectDrawer<object>
{
private Type objectType;
public DefaultObjectDrawer(Type objectType) {
this.objectType = objectType;
}
public override object OnGUI(GUIContent content, object instance) {
return EditorUtils.DrawEditorFieldDirect(content, instance, objectType, info);
}
}
///----------------------------------------------------------------------------------------------
///<summary>Derive this to create custom drawers for T DrawerAttribute.</summary>
abstract public class AttributeDrawer<T> : IAttributeDrawer where T : DrawerAttribute
{
///<summary>info</summary>
protected InspectedFieldInfo info { get; private set; }
///<summary>The GUIContent</summary>
protected GUIContent content { get; private set; }
///<summary>The instance of the object being drawn</summary>
protected object instance { get; private set; }
///<summary>The reflected FieldInfo representation</summary>
///<summary>The attribute instance</summary>
protected T attribute { get; private set; }
///<summary>The ObjectDrawer currently in use</summary>
protected IObjectDrawer objectDrawer { get; private set; }
protected FieldInfo fieldInfo { get { return info.field; } }
///<summary>The parent object the instance is drawn within</summary>
protected object context { get { return info.parentInstanceContext; } }
///<summary>The Unity object the instance serialized within</summary>
protected UnityEngine.Object contextUnityObject { get { return info.unityObjectContext; } }
///<summary>Begin GUI</summary>
object IAttributeDrawer.DrawGUI(IObjectDrawer objectDrawer, GUIContent content, object instance, DrawerAttribute attribute, InspectedFieldInfo info) {
this.objectDrawer = objectDrawer;
this.content = content;
this.instance = instance;
this.attribute = (T)attribute;
this.info = info;
var result = OnGUI(content, instance);
//flush references
this.info = default(InspectedFieldInfo);
this.content = null;
this.instance = null;
this.attribute = null;
this.objectDrawer = null;
return result;
}
///<summary>Override to implement GUI. Return the modified instance at the end.</summary>
abstract public object OnGUI(GUIContent content, object instance);
///<summary>Show the next attribute drawer in order, or the object drawer itself of no attribute drawer is left to show.</summary>
protected object MoveNextDrawer() { return objectDrawer.MoveNextDrawer(); }
}
///<summary>The default attribute drawer implementation for when an actual implementation is not found</summary>
public class DefaultAttributeDrawer : AttributeDrawer<DrawerAttribute>
{
private Type attributeType;
public DefaultAttributeDrawer(Type attributeType) {
this.attributeType = attributeType;
}
public override object OnGUI(GUIContent content, object instance) {
GUILayout.Label(string.Format("Implementation of '{0}' drawer attribute not found.", attributeType));
return MoveNextDrawer();
}
}
}
#endif

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f034313c7b49f4b458d0f47465b8e1c5
timeCreated: 1461581884
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,440 @@
#if UNITY_EDITOR
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using System;
using System.Collections;
using System.Reflection;
using NavMesh = UnityEngine.AI.NavMesh;
using NavMeshAgent = UnityEngine.AI.NavMeshAgent;
using ParadoxNotion.Serialization;
namespace ParadoxNotion.Design
{
///<summary>Collection of preferred user types and utilities for types, type colors and icons</summary>
public static class TypePrefs
{
//Raised when the preferred types list change
public static event Action onPreferredTypesChanged;
public const string SYNC_FILE_NAME = "PreferredTypes.typePrefs";
public const string LIST_MENU_STRING = "Collections/List (T)/";
public const string DICT_MENU_STRING = "Collections/Dictionary (T)/";
private static readonly string TYPES_PREFS_KEY = string.Format("ParadoxNotion.{0}.PreferedTypes", PlayerSettings.productName);
private static List<Type> _preferedTypesAll;
private static List<Type> _preferedTypesFiltered;
private static readonly List<Type> defaultTypesList = new List<Type>
{
typeof(object),
typeof(System.Type),
//Primitives
typeof(string),
typeof(float),
typeof(int),
typeof(bool),
//Unity basics
typeof(Vector2),
typeof(Vector3),
typeof(Vector4),
typeof(Quaternion),
typeof(Color),
typeof(LayerMask),
typeof(AnimationCurve),
typeof(RaycastHit),
typeof(RaycastHit2D),
//Unity functional classes
typeof(Debug),
typeof(Application),
typeof(Mathf),
typeof(Physics),
typeof(Physics2D),
typeof(Input),
typeof(NavMesh),
typeof(PlayerPrefs),
typeof(UnityEngine.Random),
typeof(Time),
typeof(UnityEngine.SceneManagement.SceneManager),
//Unity Objects
typeof(UnityEngine.Object),
typeof(UnityEngine.MonoBehaviour),
typeof(UnityEngine.ScriptableObject),
typeof(GameObject),
typeof(Transform),
typeof(Animator),
typeof(Rigidbody),
typeof(Rigidbody2D),
typeof(Collider),
typeof(Collider2D),
typeof(NavMeshAgent),
typeof(CharacterController),
typeof(AudioSource),
typeof(Camera),
typeof(Light),
typeof(Renderer),
//UGUI
typeof(UnityEngine.UI.Button),
typeof(UnityEngine.UI.Slider),
//Unity Asset Objects
typeof(Texture2D),
typeof(Sprite),
typeof(Material),
typeof(AudioClip),
typeof(AnimationClip),
typeof(UnityEngine.Audio.AudioMixer),
typeof(TextAsset),
};
//These types will be filtered out when requesting types with 'filterOutFunctionalOnlyTypes' true.
//The problem with these is that they are not static thus instance can be made, but still, there is no reason to have an instance cause their members are static.
//Most of them are also probably singletons.
//Hopefully this made sense :)
public static readonly List<Type> functionalTypesBlacklist = new List<Type>
{
typeof(Debug),
typeof(Application),
typeof(Mathf),
typeof(Physics),
typeof(Physics2D),
typeof(Input),
typeof(NavMesh),
typeof(PlayerPrefs),
typeof(UnityEngine.Random),
typeof(Time),
typeof(UnityEngine.SceneManagement.SceneManager),
};
//The default prefered types list
private static string defaultTypesListString {
get { return string.Join("|", defaultTypesList.OrderBy(t => t.Namespace).ThenBy(t => t.Name).Select(t => t.FullName).ToArray()); }
}
///----------------------------------------------------------------------------------------------
[InitializeOnLoadMethod]
static void LoadTypes() {
_preferedTypesAll = new List<Type>();
if ( TryLoadSyncFile(ref _preferedTypesAll) ) {
SetPreferedTypesList(_preferedTypesAll);
return;
}
foreach ( var s in EditorPrefs.GetString(TYPES_PREFS_KEY, defaultTypesListString).Split('|') ) {
var resolvedType = ReflectionTools.GetType(s, /*fallback?*/ true);
if ( resolvedType != null ) {
_preferedTypesAll.Add(resolvedType);
} else { ParadoxNotion.Services.Logger.Log("Missing type in Preferred Types Editor. Type removed."); }
}
//re-write back, so that fallback type resolved are saved
SetPreferedTypesList(_preferedTypesAll);
}
///<summary>Get the prefered types set by the user.</summary>
public static List<Type> GetPreferedTypesList(bool filterOutFunctionalOnlyTypes = false) { return GetPreferedTypesList(typeof(object), filterOutFunctionalOnlyTypes); }
public static List<Type> GetPreferedTypesList(Type baseType, bool filterOutFunctionalOnlyTypes = false) {
if ( _preferedTypesAll == null || _preferedTypesFiltered == null ) {
LoadTypes();
}
if ( baseType == typeof(object) ) {
return filterOutFunctionalOnlyTypes ? _preferedTypesFiltered : _preferedTypesAll;
}
if ( filterOutFunctionalOnlyTypes ) {
return _preferedTypesFiltered.Where(t => t != null && baseType.IsAssignableFrom(t)).ToList();
}
return _preferedTypesAll.Where(t => t != null && baseType.IsAssignableFrom(t)).ToList();
}
///<summary>Set the prefered types list for the user</summary>
public static void SetPreferedTypesList(List<Type> types) {
var finalTypes = types
.Where(t => t != null && !t.IsGenericType)
.OrderBy(t => t.Namespace)
.ThenBy(t => t.Name)
.ToList();
var joined = string.Join("|", finalTypes.Select(t => t.FullName).ToArray());
EditorPrefs.SetString(TYPES_PREFS_KEY, joined);
_preferedTypesAll = finalTypes;
var finalTypesFiltered = finalTypes
.Where(t => !functionalTypesBlacklist.Contains(t) /*&& !t.IsInterface && !t.IsAbstract*/ )
.ToList();
_preferedTypesFiltered = finalTypesFiltered;
TrySaveSyncFile(finalTypes);
if ( onPreferredTypesChanged != null ) {
onPreferredTypesChanged();
}
}
///<summary>Append a type to the list</summary>
public static void AddType(Type type) {
var current = GetPreferedTypesList(typeof(object));
if ( !current.Contains(type) ) {
current.Add(type);
}
SetPreferedTypesList(current);
}
///<summary>Reset the prefered types to the default ones</summary>
public static void ResetTypeConfiguration() {
SetPreferedTypesList(defaultTypesList);
}
///----------------------------------------------------------------------------------------------
///<summary>Is there a typePrefs file in sync? returns it's path.</summary>
public static string SyncFilePath() {
var syncFile = EditorGUIUtility.Load(SYNC_FILE_NAME);
var absPath = EditorUtils.AssetToSystemPath(syncFile);
if ( !string.IsNullOrEmpty(absPath) ) {
return absPath;
}
return null;
}
///<summary>Will try load from file found in DefaultEditorResources</summary>
static bool TryLoadSyncFile(ref List<Type> result) {
var absPath = SyncFilePath();
if ( !string.IsNullOrEmpty(absPath) ) {
var json = System.IO.File.ReadAllText(absPath);
var temp = JSONSerializer.Deserialize<List<Type>>(json);
if ( temp != null ) {
result = temp;
return true;
}
}
return false;
}
///<summary>Will try save to file found in DefaultEditorResources</summary>
static void TrySaveSyncFile(List<Type> types) {
var absPath = SyncFilePath();
if ( !string.IsNullOrEmpty(absPath) ) {
var json = JSONSerializer.Serialize(typeof(List<Type>), types, null, true);
System.IO.File.WriteAllText(absPath, json);
}
}
//----------------------------------------------------------------------------------------------
private static readonly Color DEFAULT_TYPE_COLOR = Colors.Grey(0.75f);
///<summary>A Type to color lookup initialized with some types already</summary>
private static Dictionary<Type, Color> typeColors = new Dictionary<Type, Color>()
{
{typeof(Delegate), new Color(1,0.4f,0.4f)},
{typeof(bool?), new Color(1,0.4f,0.4f)},
{typeof(float?), new Color(0.6f,0.6f,1)},
{typeof(int?), new Color(0.5f,1,0.5f)},
{typeof(string), new Color(0.55f,0.55f,0.55f)},
{typeof(Vector2?), new Color(1f,0.7f,0.2f)},
{typeof(Vector3?), new Color(1f,0.7f,0.2f)},
{typeof(Vector4?), new Color(1f,0.7f,0.2f)},
{typeof(Quaternion?), new Color(1f,0.7f,0.2f)},
{typeof(GameObject), new Color(0.537f, 0.415f, 0.541f)},
{typeof(UnityEngine.Object), Color.grey}
};
///<summary>Get color for type</summary>
public static Color GetTypeColor(MemberInfo info) {
if ( !EditorGUIUtility.isProSkin ) { return Color.white; }
if ( info == null ) { return Color.black; }
var type = info is Type ? info as Type : info.ReflectedType;
if ( type == null ) { return Color.black; }
Color color;
if ( typeColors.TryGetValue(type, out color) ) {
return color;
}
foreach ( var pair in typeColors ) {
if ( pair.Key.IsAssignableFrom(type) ) {
return typeColors[type] = pair.Value;
}
if ( typeof(IEnumerable).IsAssignableFrom(type) ) {
var elementType = type.GetEnumerableElementType();
if ( elementType != null ) {
return typeColors[type] = GetTypeColor(elementType);
}
}
}
return typeColors[type] = DEFAULT_TYPE_COLOR;
}
///<summary>Get the hex color preference for a type</summary>
public static string GetTypeHexColor(Type type) {
if ( !EditorGUIUtility.isProSkin ) {
return "#000000";
}
return ColorUtils.ColorToHex(GetTypeColor(type));
}
//----------------------------------------------------------------------------------------------
private const string DEFAULT_TYPE_ICON_NAME = "System.Object";
private const string IMPLICIT_ICONS_PATH = "TypeIcons/Implicit/";
private const string EXPLICIT_ICONS_PATH = "TypeIcons/Explicit/";
///<summary>A Type.FullName to texture lookup. Use string instead of type to also handle attributes</summary>
private static Dictionary<string, Texture> typeIcons = new Dictionary<string, Texture>(StringComparer.OrdinalIgnoreCase);
///<summary>Get icon for type</summary>
public static Texture GetTypeIcon(MemberInfo info, bool fallbackToDefault = true) {
if ( info == null ) { return null; }
var type = info is Type ? info as Type : info.ReflectedType;
if ( type == null ) { return null; }
Texture texture = null;
if ( typeIcons.TryGetValue(type.FullName, out texture) ) {
if ( texture != null ) {
if ( texture.name != DEFAULT_TYPE_ICON_NAME || fallbackToDefault ) {
return texture;
}
}
return null;
}
if ( texture == null ) {
if ( type.IsEnumerableCollection() ) {
var elementType = type.GetEnumerableElementType();
if ( elementType != null ) {
texture = GetTypeIcon(elementType);
}
}
}
if ( typeof(UnityEngine.Object).IsAssignableFrom(type) ) {
texture = AssetPreview.GetMiniTypeThumbnail(type);
if ( texture == null && ( typeof(MonoBehaviour).IsAssignableFrom(type) || typeof(ScriptableObject).IsAssignableFrom(type) ) ) {
texture = EditorGUIUtility.ObjectContent(EditorUtils.MonoScriptFromType(type), null).image;
if ( texture == null ) {
texture = Icons.csIcon;
}
}
}
if ( texture == null ) {
texture = Resources.Load<Texture>(IMPLICIT_ICONS_PATH + type.FullName);
}
///<summary>Explicit icons not in dark theme</summary>
if ( EditorGUIUtility.isProSkin ) {
if ( texture == null ) {
var iconAtt = type.RTGetAttribute<ParadoxNotion.Design.IconAttribute>(true);
if ( iconAtt != null ) {
texture = GetTypeIcon(iconAtt, null);
}
}
}
if ( texture == null ) {
var current = type.BaseType;
while ( current != null ) {
texture = Resources.Load<Texture>(IMPLICIT_ICONS_PATH + current.FullName);
current = current.BaseType;
if ( texture != null ) {
break;
}
}
}
if ( texture == null ) {
texture = Resources.Load<Texture>(IMPLICIT_ICONS_PATH + DEFAULT_TYPE_ICON_NAME);
}
typeIcons[type.FullName] = texture;
if ( texture != null ) { //it should not be
if ( texture.name != DEFAULT_TYPE_ICON_NAME || fallbackToDefault ) {
return texture;
}
}
return null;
}
///<summary>Get icon from [ParadoxNotion.Design.IconAttribute] info</summary>
public static Texture GetTypeIcon(IconAttribute iconAttribute, object instance = null) {
if ( iconAttribute == null ) { return null; }
if ( instance != null && !string.IsNullOrEmpty(iconAttribute.runtimeIconTypeCallback) ) {
var callbackMethod = instance.GetType().RTGetMethod(iconAttribute.runtimeIconTypeCallback);
return callbackMethod != null && callbackMethod.ReturnType == typeof(Type) ? GetTypeIcon((Type)callbackMethod.Invoke(instance, null), false) : null;
}
if ( iconAttribute.fromType != null ) {
return GetTypeIcon(iconAttribute.fromType, true);
}
Texture texture = null;
if ( typeIcons.TryGetValue(iconAttribute.iconName, out texture) ) {
return texture;
}
if ( !string.IsNullOrEmpty(iconAttribute.iconName) ) {
texture = Resources.Load<Texture>(EXPLICIT_ICONS_PATH + iconAttribute.iconName);
if ( texture == null ) { //for user made icons where user don't have to know the path
texture = Resources.Load<Texture>(iconAttribute.iconName);
}
if ( texture == null ) { //for user made icons where user provide a non resources path
texture = AssetDatabase.LoadAssetAtPath<Texture>(iconAttribute.iconName);
}
}
return typeIcons[iconAttribute.iconName] = texture;
}
///----------------------------------------------------------------------------------------------
///<summary>A Type.FullName to documentation lookup</summary>
private static Dictionary<string, string> typeDocs = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
///<summary>Get documentation for type fetched either by the [Description] attribute, or it's xml doc.</summary>
public static string GetTypeDoc(MemberInfo info) {
if ( info == null ) { return null; }
var type = info is Type ? info as Type : info.ReflectedType;
if ( type == null ) { return null; }
string doc = null;
if ( typeDocs.TryGetValue(type.FullName, out doc) ) {
return doc;
}
var descAtt = type.RTGetAttribute<DescriptionAttribute>(true);
if ( descAtt != null ) {
doc = descAtt.description;
}
if ( doc == null ) {
doc = XMLDocs.GetMemberSummary(type);
}
if ( doc == null ) {
doc = "No Documentation";
}
return typeDocs[type.FullName] = doc;
}
}
}
#endif

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8a3438334d9159844a828ec7b2425b40
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,217 @@
#if UNITY_EDITOR
using System.Collections.Generic;
using ParadoxNotion.Serialization;
using UnityEditor;
using UnityEngine;
using System.Linq;
namespace ParadoxNotion.Design
{
///<summary>An editor for preferred types</summary>
public class TypePrefsEditorWindow : EditorWindow
{
private List<System.Type> typeList;
private List<System.Type> alltypes;
private Vector2 scrollPos;
///<summary>Open window</summary>
public static void ShowWindow() {
var window = GetWindow<TypePrefsEditorWindow>();
window.Show();
}
//...
void OnEnable() {
titleContent = new GUIContent("Preferred Types");
typeList = TypePrefs.GetPreferedTypesList();
alltypes = ReflectionTools.GetAllTypes(true).Where(t => !t.IsGenericType && !t.IsGenericTypeDefinition).ToList();
}
//...
void OnGUI() {
GUI.skin.label.richText = true;
EditorGUILayout.HelpBox("Here you can specify frequently used types for your project and for easier access wherever you need to select a type, like for example when you create a new blackboard variable or using any refelection based actions. Furthermore, it is essential when working with AOT platforms like iOS or WebGL, that you generate an AOT Classes and link.xml files with the relevant button bellow. To add types in the list quicker, you can also Drag&Drop an object, or a Script file in this editor window.\n\nIf you save a preset in your 'Editor Default Resources/" + TypePrefs.SYNC_FILE_NAME + "' it will automatically sync with the list. Useful when working with others on source control.", MessageType.Info);
if ( GUILayout.Button("Add New Type", EditorStyles.miniButton) ) {
GenericMenu.MenuFunction2 Selected = delegate (object o)
{
if ( o is System.Type ) {
AddType((System.Type)o);
}
if ( o is string ) { //namespace
foreach ( var type in alltypes ) {
if ( type.Namespace == (string)o ) {
AddType(type);
}
}
}
};
var menu = new GenericMenu();
var namespaces = new List<string>();
menu.AddItem(new GUIContent("Classes/System/Object"), false, Selected, typeof(object));
foreach ( var t in alltypes ) {
var a = ( string.IsNullOrEmpty(t.Namespace) ? "No Namespace/" : t.Namespace.Replace(".", "/") + "/" ) + t.FriendlyName();
var b = string.IsNullOrEmpty(t.Namespace) ? string.Empty : " (" + t.Namespace + ")";
var friendlyName = a + b;
var category = "Classes/";
if ( t.IsValueType ) category = "Structs/";
if ( t.IsInterface ) category = "Interfaces/";
if ( t.IsEnum ) category = "Enumerations/";
menu.AddItem(new GUIContent(category + friendlyName), typeList.Contains(t), Selected, t);
if ( t.Namespace != null && !namespaces.Contains(t.Namespace) ) {
namespaces.Add(t.Namespace);
}
}
menu.AddSeparator("/");
foreach ( var ns in namespaces ) {
var path = "Whole Namespaces/" + ns.Replace(".", "/") + "/Add " + ns;
menu.AddItem(new GUIContent(path), false, Selected, ns);
}
menu.ShowAsBrowser("Add Preferred Type");
}
if ( GUILayout.Button("Generate AOTClasses.cs and link.xml Files", EditorStyles.miniButton) ) {
if ( EditorUtility.DisplayDialog("Generate AOT Classes", "A script relevant to AOT compatibility for certain platforms will now be generated.", "OK") ) {
var path = EditorUtility.SaveFilePanelInProject("AOT Classes File", "AOTClasses", "cs", "");
if ( !string.IsNullOrEmpty(path) ) {
AOTClassesGenerator.GenerateAOTClasses(path, TypePrefs.GetPreferedTypesList(true).ToArray());
}
}
if ( EditorUtility.DisplayDialog("Generate link.xml File", "A file relevant to 'code stripping' for platforms that have code stripping enabled will now be generated.", "OK") ) {
var path = EditorUtility.SaveFilePanelInProject("AOT link.xml", "link", "xml", "");
if ( !string.IsNullOrEmpty(path) ) {
AOTClassesGenerator.GenerateLinkXML(path, TypePrefs.GetPreferedTypesList().ToArray());
}
}
AssetDatabase.Refresh();
}
GUILayout.BeginHorizontal();
if ( GUILayout.Button("Reset Defaults", EditorStyles.miniButtonLeft) ) {
if ( EditorUtility.DisplayDialog("Reset Preferred Types", "Are you sure?", "Yes", "NO!") ) {
TypePrefs.ResetTypeConfiguration();
typeList = TypePrefs.GetPreferedTypesList();
Save();
}
}
if ( GUILayout.Button("Save Preset", EditorStyles.miniButtonMid) ) {
var path = EditorUtility.SaveFilePanelInProject("Save Types Preset", "PreferredTypes", "typePrefs", "");
if ( !string.IsNullOrEmpty(path) ) {
System.IO.File.WriteAllText(path, JSONSerializer.Serialize(typeof(List<System.Type>), typeList, null, true));
AssetDatabase.Refresh();
}
}
if ( GUILayout.Button("Load Preset", EditorStyles.miniButtonRight) ) {
var path = EditorUtility.OpenFilePanel("Load Types Preset", "Assets", "typePrefs");
if ( !string.IsNullOrEmpty(path) ) {
var json = System.IO.File.ReadAllText(path);
typeList = JSONSerializer.Deserialize<List<System.Type>>(json);
Save();
}
}
GUILayout.EndHorizontal();
GUILayout.Space(5);
var syncPath = TypePrefs.SyncFilePath();
EditorGUILayout.HelpBox(syncPath != null ? "List synced with file: " + syncPath.Replace(Application.dataPath, ".../Assets") : "No sync file found in '.../Assets/Editor Default Resources'. Types are currently saved in Unity EditorPrefs only.", MessageType.None);
GUILayout.Space(5);
scrollPos = GUILayout.BeginScrollView(scrollPos);
for ( int i = 0; i < typeList.Count; i++ ) {
if ( EditorGUIUtility.isProSkin ) { GUI.color = Color.black.WithAlpha(i % 2 == 0 ? 0.3f : 0); }
if ( !EditorGUIUtility.isProSkin ) { GUI.color = Color.white.WithAlpha(i % 2 == 0 ? 0.3f : 0); }
GUILayout.BeginHorizontal("box");
GUI.color = Color.white;
var type = typeList[i];
if ( type == null ) {
GUILayout.Label("MISSING TYPE", GUILayout.Width(300));
GUILayout.Label("---");
} else {
var name = type.FriendlyName();
var icon = TypePrefs.GetTypeIcon(type);
GUILayout.Label(icon, GUILayout.Width(16), GUILayout.Height(16));
GUILayout.Label(name, GUILayout.Width(300));
GUILayout.Label(type.Namespace);
}
if ( GUILayout.Button("X", GUILayout.Width(18)) ) {
RemoveType(type);
}
GUILayout.EndHorizontal();
}
GUILayout.EndScrollView();
AcceptDrops();
Repaint();
}
//Handles Drag&Drop operations
void AcceptDrops() {
var e = Event.current;
if ( e.type == EventType.DragUpdated ) {
DragAndDrop.visualMode = DragAndDropVisualMode.Link;
}
if ( e.type == EventType.DragPerform ) {
DragAndDrop.AcceptDrag();
foreach ( var o in DragAndDrop.objectReferences ) {
if ( o == null ) {
continue;
}
if ( o is MonoScript ) {
var type = ( o as MonoScript ).GetClass();
if ( type != null ) {
AddType(type);
}
continue;
}
AddType(o.GetType());
}
}
}
///<summary>Add a type</summary>
void AddType(System.Type t) {
if ( !typeList.Contains(t) ) {
typeList.Add(t);
Save();
ShowNotification(new GUIContent(string.Format("Type '{0}' Added!", t.FriendlyName())));
return;
}
ShowNotification(new GUIContent(string.Format("Type '{0}' is already in the list.", t.FriendlyName())));
}
///<summary>Remove a type</summary>
void RemoveType(System.Type t) {
typeList.Remove(t);
Save();
ShowNotification(new GUIContent(string.Format("Type '{0}' Removed.", t.FriendlyName())));
}
///<summary>Save changes</summary>
void Save() {
TypePrefs.SetPreferedTypesList(typeList);
}
}
}
#endif

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1b5cb128f12595e49879464cc9185944
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,103 @@
#if UNITY_EDITOR
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Xml;
namespace ParadoxNotion.Design
{
///<summary>Documentation from XML</summary>
public static class XMLDocs
{
private static Dictionary<MemberInfo, XmlElement> cachedElements = new Dictionary<MemberInfo, XmlElement>();
private static Dictionary<MemberInfo, string> cachedSummaries = new Dictionary<MemberInfo, string>();
///<summary>Returns a chached summary info for member</summary>
public static string GetMemberSummary(MemberInfo memberInfo) {
string result;
if ( cachedSummaries.TryGetValue(memberInfo, out result) ) { return result; }
var element = GetXmlElementForMember(memberInfo);
return cachedSummaries[memberInfo] = ( element != null ? element["summary"].InnerText.Trim() : "No Documentation Found" );
}
///<summary>Returns a chached return info for method</summary>
public static string GetMethodReturn(MethodBase method) {
var element = GetXmlElementForMember(method);
return element != null ? element["returns"].InnerText.Trim() : null;
}
///<summary>Returns a semi-chached method parameter info for method</summary>
public static string GetMethodParameter(MethodBase method, ParameterInfo parameter) { return GetMethodParameter(method, parameter.Name); }
///<summary>Returns a semi-chached method parameter info for method</summary>
public static string GetMethodParameter(MethodBase method, string parameterName) {
var methodElement = GetXmlElementForMember(method);
if ( methodElement != null ) {
foreach ( var element in methodElement ) {
var xmlElement = element as XmlElement;
if ( xmlElement == null ) { continue; }
var found = xmlElement.Attributes["name"];
if ( found != null && found.Value == parameterName ) {
return xmlElement.InnerText.Trim();
}
}
}
return null;
}
///<summary>Returns a cached XML elements for member</summary>
static XmlElement GetXmlElementForMember(MemberInfo memberInfo) {
if ( memberInfo is MethodInfo ) {
var method = (MethodInfo)memberInfo;
if ( method.IsPropertyAccessor() ) { memberInfo = method.GetAccessorProperty(); }
}
if ( memberInfo == null ) { return null; }
XmlElement element;
if ( cachedElements.TryGetValue(memberInfo, out element) ) { return element; }
if ( memberInfo is MethodInfo ) {
element = GetMemberDoc((MethodInfo)memberInfo);
} else if ( memberInfo is Type ) {
element = GetTypeDoc((Type)memberInfo);
} else {
element = GetMemberDoc(memberInfo);
}
return cachedElements[memberInfo] = element;
}
static XmlElement GetTypeDoc(Type type) { return GetDoc(type, $"T:{type.FullName}"); }
static XmlElement GetMemberDoc(MemberInfo memberInfo) {
if ( memberInfo is MethodInfo ) {
var methodInfo = (MethodInfo)memberInfo;
var parameters = methodInfo.GetParameters();
if ( parameters.Length == 0 ) {
return GetDoc(methodInfo.DeclaringType, $"M:{methodInfo.DeclaringType.FullName}.{methodInfo.Name}");
}
var parametersString = string.Empty;
for ( var i = 0; i < parameters.Length; i++ ) {
parametersString += parameters[i].ParameterType.FullName + ( i < parameters.Length - 1 ? "," : string.Empty );
}
return GetDoc(methodInfo.DeclaringType, $"M:{methodInfo.DeclaringType.FullName}.{methodInfo.Name}({parametersString})");
}
return GetDoc(memberInfo.DeclaringType, $"{memberInfo.MemberType.ToString()[0]}:{memberInfo.DeclaringType.FullName}.{memberInfo.Name}");
}
static XmlElement GetDoc(Type type, string pathName) {
var xmlPath = Path.ChangeExtension(type.Assembly.CodeBase.Substring(8), ".xml");
if ( !File.Exists(xmlPath) ) { return null; }
var xmlDocument = new XmlDocument();
xmlDocument.Load(xmlPath);
return xmlDocument.SelectSingleNode("//member[starts-with(@name, '" + pathName + "')]") as XmlElement;
}
}
}
#endif

View File

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

View File

@ -0,0 +1,81 @@
using System.Diagnostics;
using UnityEngine;
namespace ParadoxNotion.Design
{
///<summary> A simple Undo utility to avoid checking application playing, nulls and if unity editor all the time</summary>
public static class UndoUtility
{
public static string lastOperationName { get; private set; }
///<summary>Same as Undo.RecordObject. Checks null and only takes place in editor time</summary>
[Conditional("UNITY_EDITOR")]
public static void RecordObject(Object target, string name) {
#if UNITY_EDITOR
if ( Application.isPlaying || UnityEditor.EditorApplication.isUpdating || target == null ) { return; }
lastOperationName = name;
UnityEditor.Undo.RecordObject(target, name);
#endif
}
///<summary>Same as Undo.RegisterCompleteObjectUndo. Checks null and only takes place in editor time</summary>
[Conditional("UNITY_EDITOR")]
public static void RecordObjectComplete(Object target, string name) {
#if UNITY_EDITOR
if ( Application.isPlaying || UnityEditor.EditorApplication.isUpdating || target == null ) { return; }
lastOperationName = name;
UnityEditor.Undo.RegisterCompleteObjectUndo(target, name);
#endif
}
///<summary>Same as EditorUtility.SetDirty. Checks null and only takes place in editor time</summary>
[Conditional("UNITY_EDITOR")]
public static void SetDirty(Object target) {
#if UNITY_EDITOR
if ( Application.isPlaying || UnityEditor.EditorApplication.isUpdating || target == null ) { return; }
UnityEditor.EditorUtility.SetDirty(target);
#endif
}
[Conditional("UNITY_EDITOR")]
public static void RecordObject(Object target, string name, System.Action operation) {
RecordObject(target, name);
operation();
SetDirty(target);
}
[Conditional("UNITY_EDITOR")]
public static void RecordObjectComplete(Object target, string name, System.Action operation) {
RecordObjectComplete(target, name);
operation();
SetDirty(target);
}
///<summary>Shortcut to return the last undo operation name or the one provided</summary>
public static string GetLastOperationNameOr(string operation) {
return string.IsNullOrEmpty(lastOperationName) ? operation : lastOperationName;
}
///----------------------------------------------------------------------------------------------
///<summary>Checks some commong event types and records undo if that is the case</summary>
public static void CheckUndo(Object target, string name) {
var e = Event.current;
if (
( e.type == EventType.MouseDown ) ||
( e.type == EventType.KeyDown ) ||
( e.type == EventType.DragPerform ) ||
( e.type == EventType.ExecuteCommand )
) {
lastOperationName = name;
RecordObject(target, name);
}
}
///<summary>Set target dirty if gui changed</summary>
public static void CheckDirty(Object target) {
if ( GUI.changed ) { SetDirty(target); }
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 460225263b044784b9693cff84c19df9
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 98ed1f24cba738b4baad5b19eb93f767
folderAsset: yes
timeCreated: 1427372418
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@ -0,0 +1,261 @@
//Adapted from Robert Penner equations
namespace ParadoxNotion.Animation
{
using UnityEngine;
using System;
public enum EaseType
{
Linear,
QuadraticIn,
QuadraticOut,
QuadraticInOut,
QuarticIn,
QuarticOut,
QuarticInOut,
QuinticIn,
QuinticOut,
QuinticInOut,
CubicIn,
CubicOut,
CubicInOut,
ExponentialIn,
ExponentialOut,
ExponentialInOut,
CircularIn,
CircularOut,
CircularInOut,
SinusoidalIn,
SinusoidalOut,
SinusoidalInOut,
ElasticIn,
ElasticOut,
ElasticInOut,
BounceIn,
BounceOut,
BounceInOut,
BackIn,
BackOut,
BackInOut
}
///<summary>Easing functions to be used for interpolation</summary>
public static class Easing
{
///----------------------------------------------------------------------------------------------
public static float Ease(EaseType type, float from, float to, float t) {
if ( t <= 0 ) { return from; }
if ( t >= 1 ) { return to; }
return Mathf.LerpUnclamped(from, to, Function(type)(t));
}
public static Vector3 Ease(EaseType type, Vector3 from, Vector3 to, float t) {
if ( t <= 0 ) { return from; }
if ( t >= 1 ) { return to; }
return Vector3.LerpUnclamped(from, to, Function(type)(t));
}
public static Quaternion Ease(EaseType type, Quaternion from, Quaternion to, float t) {
if ( t <= 0 ) { return from; }
if ( t >= 1 ) { return to; }
return Quaternion.LerpUnclamped(from, to, Function(type)(t));
}
public static Color Ease(EaseType type, Color from, Color to, float t) {
if ( t <= 0 ) { return from; }
if ( t >= 1 ) { return to; }
return Color.LerpUnclamped(from, to, Function(type)(t));
}
///----------------------------------------------------------------------------------------------
public static Func<float, float> Function(EaseType type) {
switch ( type ) {
case EaseType.Linear: return Linear;
case EaseType.QuadraticIn: return QuadraticIn;
case EaseType.QuadraticOut: return QuadraticOut;
case EaseType.QuadraticInOut: return QuadraticInOut;
case EaseType.QuarticIn: return QuarticIn;
case EaseType.QuarticOut: return QuarticOut;
case EaseType.QuarticInOut: return QuarticInOut;
case EaseType.QuinticIn: return QuinticIn;
case EaseType.QuinticOut: return QuinticOut;
case EaseType.QuinticInOut: return QuinticInOut;
case EaseType.CubicIn: return CubicIn;
case EaseType.CubicOut: return CubicOut;
case EaseType.CubicInOut: return CubicInOut;
case EaseType.ExponentialIn: return ExponentialIn;
case EaseType.ExponentialOut: return ExponentialOut;
case EaseType.ExponentialInOut: return ExponentialInOut;
case EaseType.CircularIn: return CircularIn;
case EaseType.CircularOut: return CircularOut;
case EaseType.CircularInOut: return CircularInOut;
case EaseType.SinusoidalIn: return SinusoidalIn;
case EaseType.SinusoidalOut: return SinusoidalOut;
case EaseType.SinusoidalInOut: return SinusoidalInOut;
case EaseType.ElasticIn: return ElasticIn;
case EaseType.ElasticOut: return ElasticOut;
case EaseType.ElasticInOut: return ElasticInOut;
case EaseType.BounceIn: return BounceIn;
case EaseType.BounceOut: return BounceOut;
case EaseType.BounceInOut: return BounceInOut;
case EaseType.BackIn: return BackIn;
case EaseType.BackOut: return BackOut;
case EaseType.BackInOut: return BackInOut;
default: throw new ArgumentOutOfRangeException();
}
}
///----------------------------------------------------------------------------------------------
public static float Linear(float t) {
return t;
}
public static float QuadraticIn(float t) {
return t * t;
}
public static float QuadraticOut(float t) {
return 1f - ( 1f - t ) * ( 1f - t );
}
public static float QuadraticInOut(float t) {
return t < 0.5f ? 2f * t * t : 1f - Mathf.Pow(-2f * t + 2f, 2f) / 2f;
}
public static float QuarticIn(float t) {
return t * t * t * t;
}
public static float QuarticOut(float t) {
return 1f - ( --t * t * t * t );
}
public static float QuarticInOut(float t) {
if ( ( t *= 2f ) < 1f )
return 0.5f * t * t * t * t;
return -0.5f * ( ( t -= 2f ) * t * t * t - 2f );
}
public static float QuinticIn(float t) {
return t * t * t * t * t;
}
public static float QuinticOut(float t) {
return --t * t * t * t * t + 1f;
}
public static float QuinticInOut(float t) {
if ( ( t *= 2f ) < 1 )
return 0.5f * t * t * t * t * t;
return 0.5f * ( ( t -= 2f ) * t * t * t * t + 2f );
}
public static float CubicIn(float t) {
return t * t * t;
}
public static float CubicOut(float t) {
return --t * t * t + 1f;
}
public static float CubicInOut(float t) {
return t < 0.5 ? 4f * t * t * t : 1f - Mathf.Pow(-2f * t + 2f, 3f) / 2f;
}
public static float SinusoidalIn(float t) {
return 1f - Mathf.Cos(t * Mathf.PI / 2f);
}
public static float SinusoidalOut(float t) {
return Mathf.Sin(t * Mathf.PI / 2f);
}
public static float SinusoidalInOut(float t) {
return 0.5f * ( 1f - Mathf.Cos(Mathf.PI * t) );
}
public static float ExponentialIn(float t) {
return t == 0f ? 0f : Mathf.Pow(2f, 10f * t - 10f);
}
public static float ExponentialOut(float t) {
return t == 1f ? 1f : 1f - Mathf.Pow(2f, -10f * t);
}
public static float ExponentialInOut(float t) {
return t < 0.5f ? Mathf.Pow(2f, 20f * t - 10f) / 2f : ( 2f - Mathf.Pow(2f, -20f * t + 10f) ) / 2f;
}
public static float CircularIn(float t) {
return 1f - Mathf.Sqrt(1f - t * t);
}
public static float CircularOut(float t) {
return Mathf.Sqrt(1f - ( --t * t ));
}
public static float CircularInOut(float t) {
return t < 0.5f ? ( Mathf.Sqrt(1f - t * t) - 1f ) / 2 : ( Mathf.Sqrt(1f - ( t -= 2f ) * t) + 1f ) / 2;
}
public static float ElasticIn(float t) {
float x = ( 2f * Mathf.PI ) / 3f;
return -Mathf.Pow(2f, 10f * t - 10f) * Mathf.Sin(( t * 10f - 10.75f ) * x);
}
public static float ElasticOut(float t) {
float x = ( 2f * Mathf.PI ) / 3f;
return Mathf.Pow(2f, -10f * t) * Mathf.Sin(( t * 10f - 0.75f ) * x) + 1f;
}
public static float ElasticInOut(float t) {
float x = ( 2f * Mathf.PI ) / 4.5f;
if ( t < 0.5f )
return -( Mathf.Pow(2f, 20f * t - 10f) * Mathf.Sin(( 20f * t - 11.125f ) * x) ) / 2f;
return ( Mathf.Pow(2f, -20f * t + 10f) * Mathf.Sin(( 20f * t - 11.125f ) * x) ) / 2f + 1f;
}
public static float BounceIn(float t) {
return 1f - BounceOut(1f - t);
}
public static float BounceOut(float t) {
if ( t < ( 1f / 2.75f ) ) {
return 7.5625f * t * t;
} else if ( t < ( 2f / 2.75f ) ) {
return 7.5625f * ( t -= ( 1.5f / 2.75f ) ) * t + 0.75f;
} else if ( t < ( 2.5f / 2.75f ) ) {
return 7.5625f * ( t -= ( 2.25f / 2.75f ) ) * t + 0.9375f;
} else {
return 7.5625f * ( t -= ( 2.625f / 2.75f ) ) * t + 0.984375f;
}
}
public static float BounceInOut(float t) {
return t < 0.5f ? BounceIn(t * 2f) * 0.5f : BounceOut(t * 2f - 1f) * 0.5f + 0.5f;
}
public static float BackIn(float t) {
float s = 1.70158f;
return t * t * ( ( s + 1f ) * t - s );
}
public static float BackOut(float t) {
float s = 1.70158f;
return --t * t * ( ( s + 1f ) * t + s ) + 1f;
}
public static float BackInOut(float t) {
float s = 1.70158f * 1.525f;
if ( ( t *= 2f ) < 1f )
return 0.5f * ( t * t * ( ( s + 1 ) * t - s ) );
return 0.5f * ( ( t -= 2f ) * t * ( ( s + 1f ) * t + s ) + 2f );
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: eb2ca6ca572280149964596d794ec706
timeCreated: 1537185035
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,24 @@
//common generic delegates
namespace ParadoxNotion
{
public delegate void ActionCall();
public delegate void ActionCall<T1>(T1 a);
public delegate void ActionCall<T1, T2>(T1 a, T2 b);
public delegate void ActionCall<T1, T2, T3>(T1 a, T2 b, T3 c);
public delegate void ActionCall<T1, T2, T3, T4>(T1 a, T2 b, T3 c, T4 d);
public delegate void ActionCall<T1, T2, T3, T4, T5>(T1 a, T2 b, T3 c, T4 d, T5 e);
public delegate void ActionCall<T1, T2, T3, T4, T5, T6>(T1 a, T2 b, T3 c, T4 d, T5 e, T6 f);
public delegate void ActionCall<T1, T2, T3, T4, T5, T6, T7>(T1 a, T2 b, T3 c, T4 d, T5 e, T6 f, T7 g);
public delegate void ActionCall<T1, T2, T3, T4, T5, T6, T7, T8>(T1 a, T2 b, T3 c, T4 d, T5 e, T6 f, T7 g, T8 h);
public delegate TResult FunctionCall<TResult>();
public delegate TResult FunctionCall<T1, TResult>(T1 a);
public delegate TResult FunctionCall<T1, T2, TResult>(T1 a, T2 b);
public delegate TResult FunctionCall<T1, T2, T3, TResult>(T1 a, T2 b, T3 c);
public delegate TResult FunctionCall<T1, T2, T3, T4, TResult>(T1 a, T2 b, T3 c, T4 d);
public delegate TResult FunctionCall<T1, T2, T3, T4, T5, TResult>(T1 a, T2 b, T3 c, T4 d, T5 e);
public delegate TResult FunctionCall<T1, T2, T3, T4, T5, T6, TResult>(T1 a, T2 b, T3 c, T4 d, T5 e, T6 f);
public delegate TResult FunctionCall<T1, T2, T3, T4, T5, T6, T7, TResult>(T1 a, T2 b, T3 c, T4 d, T5 e, T6 f, T7 g);
public delegate TResult FunctionCall<T1, T2, T3, T4, T5, T6, T7, T8, TResult>(T1 a, T2 b, T3 c, T4 d, T5 e, T6 f, T7 g, T8 h);
}

View File

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

View File

@ -0,0 +1,51 @@
using System;
using UnityEngine;
namespace ParadoxNotion
{
///<summary>Defines a dynamic (type-wise) parameter.</summary>
[Serializable]
sealed public class DynamicParameterDefinition : ISerializationCallbackReceiver
{
void ISerializationCallbackReceiver.OnBeforeSerialize() {
if ( type != null ) { _type = type.FullName; }
}
void ISerializationCallbackReceiver.OnAfterDeserialize() {
type = ReflectionTools.GetType(_type, /*fallback?*/ true);
}
[SerializeField] private string _ID;
[SerializeField] private string _name;
[SerializeField] private string _type;
//The ID of the definition
public string ID {
get
{
//for correct update prior versions
if ( string.IsNullOrEmpty(_ID) ) { _ID = name; }
return _ID;
}
private set { _ID = value; }
}
//The name of the definition
public string name {
get { return _name; }
set { _name = value; }
}
///<summary>The Type of the definition</summary>
public Type type { get; set; }
public DynamicParameterDefinition() { }
public DynamicParameterDefinition(string name, Type type) {
this.ID = Guid.NewGuid().ToString();
this.name = name;
this.type = type;
}
}
}

View File

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

View File

@ -0,0 +1,117 @@
namespace ParadoxNotion
{
///<summary> Enumeration for comparisons</summary>
public enum CompareMethod
{
EqualTo,
GreaterThan,
LessThan,
GreaterOrEqualTo,
LessOrEqualTo
}
///<summary> Enumeration for Operations (Add, Subtract, Equality etc)</summary>
public enum OperationMethod
{
Set,
Add,
Subtract,
Multiply,
Divide
}
///<summary> Enumeration for mouse button keys</summary>
public enum ButtonKeys
{
Left = 0,
Right = 1,
Middle = 2
}
///<summary> Enumeration for press types for inputs</summary>
public enum PressTypes
{
Down,
Up,
Pressed
}
///<summary> Enumeration for mouse press</summary>
public enum MouseClickEvent
{
MouseDown = 0,
MouseUp = 1
}
///<summary> Enumeration for trigger unity events</summary>
public enum TriggerTypes
{
TriggerEnter = 0,
TriggerExit = 1,
TriggerStay = 2
}
///<summary> Enumeration for collision unity events</summary>
public enum CollisionTypes
{
CollisionEnter = 0,
CollisionExit = 1,
CollisionStay = 2
}
///<summary> Enumeration for mouse unity events</summary>
public enum MouseInteractionTypes
{
MouseEnter = 0,
MouseExit = 1,
MouseOver = 2
}
///<summary> Enumeration for boolean status result</summary>
public enum CompactStatus
{
Failure = 0,
Success = 1
}
///<summary> Enumeration for Animation playing direction</summary>
public enum PlayDirections
{
Forward,
Backward,
Toggle
}
///<summary> Enumeration for planar direction</summary>
public enum PlanarDirection
{
Horizontal,
Vertical,
Auto
}
///<summary> Enumeration Alignment 2x2</summary>
public enum Alignment2x2
{
Default,
Left,
Right,
Top,
Bottom
}
///<summary> Enumeration Alignment 3x3</summary>
public enum Alignment3x3
{
TopLeft,
TopCenter,
TopRight,
MiddleLeft,
MiddleCenter,
MiddleRight,
BottomLeft,
BottomCenter,
BottomRight
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 8edf60b49210fca4b84c66f4cdec0fc7
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,85 @@
using System.Collections.Generic;
namespace ParadoxNotion
{
///<summary>A simple general purpose hierarchical tree.</summary>
public class HierarchyTree
{
//..with nothing inside right now
///<summary>A simple general purpose hierarchical tree element.</summary>
public class Element
{
private object _reference;
private Element _parent;
private List<Element> _children;
public object reference => _reference;
public Element parent => _parent;
public IEnumerable<Element> children => _children;
public Element(object reference) {
this._reference = reference;
}
///<summary>Add a child element</summary>
public Element AddChild(Element child) {
if ( _children == null ) { _children = new List<Element>(); }
child._parent = this;
_children.Add(child);
return child;
}
///<summary>Remove a child element</summary>
public void RemoveChild(Element child) {
if ( _children != null ) {
_children.Remove(child);
}
}
///<summary>Get root element</summary>
public Element GetRoot() {
var current = _parent;
while ( current != null ) {
current = current._parent;
}
return current;
}
///<summary>Returns the first found Element that references target object</summary>
public Element FindReferenceElement(object target) {
if ( this._reference == target ) { return this; }
if ( _children == null ) { return null; }
for ( var i = 0; i < _children.Count; i++ ) {
var sub = _children[i].FindReferenceElement(target);
if ( sub != null ) {
return sub;
}
}
return null;
}
///<summary>Get first parent reference of type T, including self element</summary>
public T GetFirstParentReferenceOfType<T>() {
if ( this._reference is T ) { return (T)_reference; }
return _parent != null ? _parent.GetFirstParentReferenceOfType<T>() : default(T);
}
///<summary>Get all children references of type T recursively</summary>
public IEnumerable<T> GetAllChildrenReferencesOfType<T>() {
if ( _children == null ) { yield break; }
for ( var i = 0; i < _children.Count; i++ ) {
var element = _children[i];
if ( element._reference is T ) {
yield return (T)element._reference;
}
foreach ( var deep in element.GetAllChildrenReferencesOfType<T>() ) {
yield return deep;
}
}
}
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 5ce798a6776e2444ab1be31bb0fd9703
timeCreated: 1537847297
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,45 @@
using UnityEngine;
namespace ParadoxNotion
{
///<summary>Common interface between EventData and EventData<T></summary>
public interface IEventData
{
GameObject receiver { get; }
object sender { get; }
object valueBoxed { get; }
}
///<summary>Dispatched within EventRouter and contains data about the event</summary>
public struct EventData : IEventData
{
public GameObject receiver { get; private set; }
public object sender { get; private set; }
public object value { get; private set; }
public object valueBoxed => value;
public EventData(object value, GameObject receiver, object sender) {
this.value = value;
this.receiver = receiver;
this.sender = sender;
}
public EventData(GameObject receiver, object sender) {
this.value = null;
this.receiver = receiver;
this.sender = sender;
}
}
///<summary>Dispatched within EventRouter and contains data about the event</summary>
public struct EventData<T> : IEventData
{
public GameObject receiver { get; private set; }
public object sender { get; private set; }
public T value { get; private set; }
public object valueBoxed => value;
public EventData(T value, GameObject receiver, object sender) {
this.receiver = receiver;
this.sender = sender;
this.value = value;
}
}
}

View File

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

View File

@ -0,0 +1,125 @@
using UnityEngine;
namespace ParadoxNotion
{
///<summary> Has some prety common operations amongst values.</summary>
public static class OperationTools
{
public static string GetOperationString(OperationMethod om) {
if ( om == OperationMethod.Set )
return " = ";
if ( om == OperationMethod.Add )
return " += ";
if ( om == OperationMethod.Subtract )
return " -= ";
if ( om == OperationMethod.Multiply )
return " *= ";
if ( om == OperationMethod.Divide )
return " /= ";
return string.Empty;
}
public static float Operate(float a, float b, OperationMethod om, float delta = 1f) {
if ( om == OperationMethod.Set )
return b;
if ( om == OperationMethod.Add )
return a + ( b * delta );
if ( om == OperationMethod.Subtract )
return a - ( b * delta );
if ( om == OperationMethod.Multiply )
return a * ( b * delta );
if ( om == OperationMethod.Divide )
return a / ( b * delta );
return a;
}
public static int Operate(int a, int b, OperationMethod om) {
if ( om == OperationMethod.Set )
return b;
if ( om == OperationMethod.Add )
return a + b;
if ( om == OperationMethod.Subtract )
return a - b;
if ( om == OperationMethod.Multiply )
return a * b;
if ( om == OperationMethod.Divide )
return a / b;
return a;
}
public static Vector3 Operate(Vector3 a, Vector3 b, OperationMethod om, float delta = 1f) {
if ( om == OperationMethod.Set )
return b;
if ( om == OperationMethod.Add )
return a + ( b * delta );
if ( om == OperationMethod.Subtract )
return a - ( b * delta );
if ( om == OperationMethod.Multiply )
return Vector3.Scale(a, ( b * delta ));
if ( om == OperationMethod.Divide ) {
b *= delta;
return new Vector3(( a ).x / ( b ).x, ( a ).y / ( b ).y, ( a ).z / ( b ).z);
}
return a;
}
public static string GetCompareString(CompareMethod cm) {
if ( cm == CompareMethod.EqualTo )
return " == ";
if ( cm == CompareMethod.GreaterThan )
return " > ";
if ( cm == CompareMethod.LessThan )
return " < ";
if ( cm == CompareMethod.GreaterOrEqualTo )
return " >= ";
if ( cm == CompareMethod.LessOrEqualTo )
return " <= ";
return string.Empty;
}
public static bool Compare(float a, float b, CompareMethod cm, float floatingPoint) {
if ( cm == CompareMethod.EqualTo )
return Mathf.Abs(a - b) <= floatingPoint;
if ( cm == CompareMethod.GreaterThan )
return a > b;
if ( cm == CompareMethod.LessThan )
return a < b;
if ( cm == CompareMethod.GreaterOrEqualTo )
return a >= b;
if ( cm == CompareMethod.LessOrEqualTo )
return a <= b;
return true;
}
public static bool Compare(int a, int b, CompareMethod cm) {
if ( cm == CompareMethod.EqualTo )
return a == b;
if ( cm == CompareMethod.GreaterThan )
return a > b;
if ( cm == CompareMethod.LessThan )
return a < b;
if ( cm == CompareMethod.GreaterOrEqualTo )
return a >= b;
if ( cm == CompareMethod.LessOrEqualTo )
return a <= b;
return true;
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 78f36360dab60254f9e297cfd18b7bf7
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3b784f41bdb7345499543912922c873d
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,5 @@
fileFormatVersion: 2
guid: 98e4103193f629f4188bc1831efae51b
folderAsset: yes
DefaultImporter:
userData:

View File

@ -0,0 +1,12 @@
using System;
namespace ParadoxNotion.Serialization
{
public class DeserializeFromAttribute : Attribute
{
readonly public string previousTypeFullName;
public DeserializeFromAttribute(string previousTypeFullName) {
this.previousTypeFullName = previousTypeFullName;
}
}
}

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 08b3b1be3dd9c7b46b83e8993a8d969e
timeCreated: 1438645389
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 4c9c2848912bd304a9e017cc2c70823c
folderAsset: yes
timeCreated: 1458918182
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 1c3453edd5a095d4a8d2ad6271ace429
folderAsset: yes
timeCreated: 1458897573
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: edb4a1e97c2095c49a690e92967ac921
folderAsset: yes
timeCreated: 1458897573
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,43 @@
#if !NO_UNITY
using System;
using System.Collections.Generic;
using UnityEngine;
namespace ParadoxNotion.Serialization.FullSerializer.Internal.DirectConverters
{
public class AnimationCurve_DirectConverter : fsDirectConverter<AnimationCurve>
{
protected override fsResult DoSerialize(AnimationCurve model, Dictionary<string, fsData> serialized) {
var result = fsResult.Success;
result += SerializeMember(serialized, null, "keys", model.keys);
result += SerializeMember(serialized, null, "preWrapMode", model.preWrapMode);
result += SerializeMember(serialized, null, "postWrapMode", model.postWrapMode);
return result;
}
protected override fsResult DoDeserialize(Dictionary<string, fsData> data, ref AnimationCurve model) {
var result = fsResult.Success;
var t0 = model.keys;
result += DeserializeMember(data, null, "keys", out t0);
model.keys = t0;
var t1 = model.preWrapMode;
result += DeserializeMember(data, null, "preWrapMode", out t1);
model.preWrapMode = t1;
var t2 = model.postWrapMode;
result += DeserializeMember(data, null, "postWrapMode", out t2);
model.postWrapMode = t2;
return result;
}
public override object CreateInstance(fsData data, Type storageType) {
return new AnimationCurve();
}
}
}
#endif

View File

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 884587fd81d5241449463b0aa2772803
timeCreated: 1458897573
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

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