插件添加
9
EintooAR/Assets/Plugins/ParadoxNotion/CanvasCore.meta
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bd9f4941b19037f4a88460b874a8a3e1
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1538755212
|
||||||
|
licenseType: Store
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0aa2a0733358abb4c90587d3628d0ff9
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1538657332
|
||||||
|
licenseType: Store
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,5 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d4ff0b9c7cca6004d96e43fd71a2ec44
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: a6a1b03fabc29f2479f8b63c5ae861f2
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
@ -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 { }
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3f408bebe1629994794006aa2e272ae5
|
||||||
|
timeCreated: 1513958511
|
||||||
|
licenseType: Store
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: be3277af62533fc4c8d68065c61db942
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1538665292
|
||||||
|
licenseType: Store
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 133797bc4f2687b42a8a5f1baa7ba63f
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 781130fb96acf5f4384bd574f6cd9704
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1538665299
|
||||||
|
licenseType: Store
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
After Width: | Height: | Size: 3.1 KiB |
@ -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:
|
After Width: | Height: | Size: 17 KiB |
@ -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:
|
After Width: | Height: | Size: 54 KiB |
@ -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:
|
After Width: | Height: | Size: 3.1 KiB |
@ -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:
|
After Width: | Height: | Size: 48 KiB |
@ -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:
|
After Width: | Height: | Size: 2.9 KiB |
@ -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:
|
After Width: | Height: | Size: 3.1 KiB |
@ -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:
|
@ -0,0 +1,5 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3774cc9cbacfc4a41b0fb7fa91f7950f
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
@ -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
|
@ -0,0 +1,12 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3b148b00f34f1a94488008fd63cdd171
|
||||||
|
timeCreated: 1430214156
|
||||||
|
licenseType: Store
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 09cec26775978914c969e7c507315723
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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
|
@ -0,0 +1,12 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6bc5dd489056dda48ad29f55f5da5c78
|
||||||
|
timeCreated: 1513884114
|
||||||
|
licenseType: Store
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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
|
@ -0,0 +1,12 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e2177b57a40461d4484f7675d40b6fd0
|
||||||
|
timeCreated: 1510990664
|
||||||
|
licenseType: Store
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,10 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e2a7ec01cbc8b5744b88354fd6b2e310
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1541186478
|
||||||
|
licenseType: Store
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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
|
@ -0,0 +1,12 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 987618a20a0698a429059efcc504a5c9
|
||||||
|
timeCreated: 1510968237
|
||||||
|
licenseType: Store
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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
|
@ -0,0 +1,12 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 69ab7b26fef952b43af5148544cd9a0c
|
||||||
|
timeCreated: 1510968237
|
||||||
|
licenseType: Store
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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
|
@ -0,0 +1,12 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2ffba1313f15e5948a23e610947d90b8
|
||||||
|
timeCreated: 1510968237
|
||||||
|
licenseType: Store
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,5 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8d7a98bebbf5f384bad444fe79c2d315
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
@ -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
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f4676c1c75b3f474da4734cc2fd16c81
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
@ -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
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fe15795089e56c545803799233bd2512
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
@ -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
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1b2198a3a4aa5b44199f1deba4b3ed80
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
@ -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
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f82d383bba56d6a4d87929dcd962745a
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
@ -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
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b97faf2d46c8ec043a8f0b20f9024058
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
@ -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
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 94b281ae1067f0c4ba9b8d27c2fb8178
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
@ -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
|
@ -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:
|
@ -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
|
@ -0,0 +1,12 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c8364c09f7a38544ab08ff1a13a47739
|
||||||
|
timeCreated: 1510983225
|
||||||
|
licenseType: Store
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 25316af9468ffe04f8946375b92e7e79
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
@ -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
|
@ -0,0 +1,12 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9d963bfbd43f9ec4ca490225535abeef
|
||||||
|
timeCreated: 1426970318
|
||||||
|
licenseType: Store
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0758ec893fb3a1d44a1bfa3730380e94
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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
|
@ -0,0 +1,12 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f034313c7b49f4b458d0f47465b8e1c5
|
||||||
|
timeCreated: 1461581884
|
||||||
|
licenseType: Store
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8a3438334d9159844a828ec7b2425b40
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
@ -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
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1b5cb128f12595e49879464cc9185944
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
@ -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
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 415f0b2943cba19478d5fd2295fbe249
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 460225263b044784b9693cff84c19df9
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 98ed1f24cba738b4baad5b19eb93f767
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1427372418
|
||||||
|
licenseType: Store
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5164d470a6e38764b8d45186ceffdd52
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: eb2ca6ca572280149964596d794ec706
|
||||||
|
timeCreated: 1537185035
|
||||||
|
licenseType: Store
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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);
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ea94db230ea657945a86990788542830
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f17f63b2bb18a3149a3e07f5f86b5f02
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8edf60b49210fca4b84c66f4cdec0fc7
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5ce798a6776e2444ab1be31bb0fd9703
|
||||||
|
timeCreated: 1537847297
|
||||||
|
licenseType: Store
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4afd82dfa72065b448ec4d012da280f9
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 78f36360dab60254f9e297cfd18b7bf7
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3b784f41bdb7345499543912922c873d
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
@ -0,0 +1,5 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 98e4103193f629f4188bc1831efae51b
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
@ -0,0 +1,12 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ParadoxNotion.Serialization
|
||||||
|
{
|
||||||
|
public class DeserializeFromAttribute : Attribute
|
||||||
|
{
|
||||||
|
readonly public string previousTypeFullName;
|
||||||
|
public DeserializeFromAttribute(string previousTypeFullName) {
|
||||||
|
this.previousTypeFullName = previousTypeFullName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 08b3b1be3dd9c7b46b83e8993a8d969e
|
||||||
|
timeCreated: 1438645389
|
||||||
|
licenseType: Store
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4c9c2848912bd304a9e017cc2c70823c
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1458918182
|
||||||
|
licenseType: Store
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1c3453edd5a095d4a8d2ad6271ace429
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1458897573
|
||||||
|
licenseType: Store
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,9 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: edb4a1e97c2095c49a690e92967ac921
|
||||||
|
folderAsset: yes
|
||||||
|
timeCreated: 1458897573
|
||||||
|
licenseType: Store
|
||||||
|
DefaultImporter:
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -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
|
@ -0,0 +1,12 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 884587fd81d5241449463b0aa2772803
|
||||||
|
timeCreated: 1458897573
|
||||||
|
licenseType: Store
|
||||||
|
MonoImporter:
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|