demo: add performance demo
parent
d9e7eb9732
commit
6b11e7c588
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: ca0fd7c7ead2c49b1ae139b7963de126
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 839afb79f79094e6c942050ec5413ebf
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,88 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: UIParticle_PerformanceDemo_Fire
|
||||
m_Shader: {fileID: 4800000, guid: ecfa8f5732b504ef98fba10aa18d0326, type: 3}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 2800000, guid: 294c5667b05cc4edcac3885a5899cc65, type: 3}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _ColorMask: 15
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Glow: 1
|
||||
- _InvFade: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UVSec: 0
|
||||
- _UseUIAlphaClip: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _TintColor: {r: 1, g: 1, b: 1, a: 1}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3dc66b79cada243e59bcaf09f804373d
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
After Width: | Height: | Size: 585 KiB |
|
@ -0,0 +1,121 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 294c5667b05cc4edcac3885a5899cc65
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 9
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 1
|
||||
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: 2
|
||||
aniso: 16
|
||||
mipBias: -100
|
||||
wrapU: -1
|
||||
wrapV: -1
|
||||
wrapW: -1
|
||||
nPOTScale: 1
|
||||
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: 0
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 0
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 4096
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 2
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 4096
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 2
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Android
|
||||
maxTextureSize: 4096
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 2
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 4096
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 2
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID:
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,88 @@
|
|||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2100000
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: UIParticle_PerformanceDemo_Spread
|
||||
m_Shader: {fileID: 4800000, guid: ecfa8f5732b504ef98fba10aa18d0326, type: 3}
|
||||
m_ShaderKeywords:
|
||||
m_LightmapFlags: 4
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
- _BumpMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailAlbedoMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailMask:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _DetailNormalMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _EmissionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MainTex:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _MetallicGlossMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _OcclusionMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
- _ParallaxMap:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Floats:
|
||||
- _BumpScale: 1
|
||||
- _ColorMask: 15
|
||||
- _Cutoff: 0.5
|
||||
- _DetailNormalMapScale: 1
|
||||
- _DstBlend: 0
|
||||
- _GlossMapScale: 1
|
||||
- _Glossiness: 0.5
|
||||
- _GlossyReflections: 1
|
||||
- _Glow: 1
|
||||
- _InvFade: 1
|
||||
- _Metallic: 0
|
||||
- _Mode: 0
|
||||
- _OcclusionStrength: 1
|
||||
- _Parallax: 0.02
|
||||
- _SmoothnessTextureChannel: 0
|
||||
- _SpecularHighlights: 1
|
||||
- _SrcBlend: 1
|
||||
- _Stencil: 0
|
||||
- _StencilComp: 8
|
||||
- _StencilOp: 0
|
||||
- _StencilReadMask: 255
|
||||
- _StencilWriteMask: 255
|
||||
- _UVSec: 0
|
||||
- _UseUIAlphaClip: 0
|
||||
- _ZWrite: 1
|
||||
m_Colors:
|
||||
- _ClipRect: {r: -32767, g: -32767, b: 32767, a: 32767}
|
||||
- _Color: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _TintColor: {r: 1, g: 1, b: 1, a: 1}
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b7ac7640c2f1047c887aa52ff1ce9fcc
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 2100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c5a6b37697e71473cb1ecc90047622d0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b888c253a15224f1fa518bed74028211
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
|
@ -0,0 +1,22 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 70069a8db1df148ae8b4c8108c079acf
|
||||
TrueTypeFontImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 4
|
||||
fontSize: 26
|
||||
forceTextureCase: 0
|
||||
characterSpacing: 0
|
||||
characterPadding: 1
|
||||
includeFontData: 1
|
||||
fontName: Falstin
|
||||
fontNames:
|
||||
- Falstin
|
||||
fallbackFontReferences: []
|
||||
customCharacters:
|
||||
fontRenderingMode: 1
|
||||
ascentCalculationMode: 1
|
||||
useLegacyBoundsCalculation: 0
|
||||
shouldRoundAdvanceValue: 1
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fa6e3b593bf274861b2eab47082d9b1e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 784696794bc6345bc80bf49623581c2e
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f0b370726e57248da97c1c2f3bfd8bdf
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"name": "Coffee.NanoMonitor",
|
||||
"references": [],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": []
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3d6cc132218a845708ce317bd33e5500
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,268 @@
|
|||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
using UnityEngine.UI;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
|
||||
#endif
|
||||
|
||||
namespace Coffee.NanoMonitor
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[CustomEditor(typeof(NanoMonitor))]
|
||||
internal class NanoMonitorEditor : Editor
|
||||
{
|
||||
private UnityEditorInternal.ReorderableList m_MonitorItemList;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
var items = serializedObject.FindProperty("m_CustomMonitorItems");
|
||||
m_MonitorItemList = new UnityEditorInternal.ReorderableList(serializedObject, items)
|
||||
{
|
||||
draggable = false,
|
||||
drawHeaderCallback = r => { EditorGUI.LabelField(r, new GUIContent("Custom Monitor Items")); },
|
||||
drawElementCallback = (r, i, _, __) =>
|
||||
{
|
||||
EditorGUI.LabelField(new Rect(r.x, r.y, r.width, r.height - 2), GUIContent.none, EditorStyles.textArea);
|
||||
var labelWidth = EditorGUIUtility.labelWidth;
|
||||
EditorGUIUtility.labelWidth = 80;
|
||||
EditorGUI.PropertyField(new Rect(r.x + 2, r.y + 3, r.width - 4, r.height - 4), items.GetArrayElementAtIndex(i), true);
|
||||
EditorGUIUtility.labelWidth = labelWidth;
|
||||
},
|
||||
elementHeightCallback = i => EditorGUI.GetPropertyHeight(items.GetArrayElementAtIndex(i)) + 6,
|
||||
};
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
base.OnInspectorGUI();
|
||||
|
||||
m_MonitorItemList.DoLayoutList();
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
[DisallowMultipleComponent]
|
||||
public sealed class NanoMonitor : MonoBehaviour
|
||||
{
|
||||
//################################
|
||||
// Serialize Members.
|
||||
//################################
|
||||
// Settings
|
||||
[Header("Settings")] [SerializeField] [Range(0.01f, 2f)]
|
||||
private float m_Interval = 1f;
|
||||
|
||||
[SerializeField] [Range(0, 3)] private int m_Precision = 2;
|
||||
[SerializeField] private Font m_Font;
|
||||
|
||||
// Foldout
|
||||
[Header("Foldout")] [SerializeField] private bool m_Opened = false;
|
||||
|
||||
[FormerlySerializedAs("m_Collapse")] [SerializeField]
|
||||
private GameObject m_FoldoutObject = null;
|
||||
|
||||
[SerializeField] private Button m_OpenButton = null;
|
||||
[SerializeField] private Button m_CloseButton = null;
|
||||
|
||||
// View
|
||||
[Header("View")] [SerializeField] private MonitorUI m_Fps = null;
|
||||
[SerializeField] private MonitorUI m_Gc = null;
|
||||
[SerializeField] private MonitorUI m_MonoUsage = null;
|
||||
[SerializeField] private MonitorUI m_UnityUsage = null;
|
||||
|
||||
[HideInInspector] [SerializeField] private CustomMonitorItem[] m_CustomMonitorItems = new CustomMonitorItem[0];
|
||||
|
||||
|
||||
//################################
|
||||
// Public Members.
|
||||
//################################
|
||||
public void Clean()
|
||||
{
|
||||
Resources.UnloadUnusedAssets();
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
// Private Members.
|
||||
//################################
|
||||
private double _elapsed;
|
||||
private double _fpsElapsed;
|
||||
private int _frames;
|
||||
|
||||
private void Open()
|
||||
{
|
||||
_frames = 0;
|
||||
_elapsed = m_Interval;
|
||||
_fpsElapsed = 0;
|
||||
|
||||
if (m_FoldoutObject)
|
||||
{
|
||||
m_FoldoutObject.SetActive(true);
|
||||
}
|
||||
|
||||
if (m_CloseButton)
|
||||
{
|
||||
m_CloseButton.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
if (m_OpenButton)
|
||||
{
|
||||
m_OpenButton.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void Close()
|
||||
{
|
||||
if (m_FoldoutObject)
|
||||
{
|
||||
m_FoldoutObject.SetActive(false);
|
||||
}
|
||||
|
||||
if (m_CloseButton)
|
||||
{
|
||||
m_CloseButton.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
if (m_OpenButton)
|
||||
{
|
||||
m_OpenButton.gameObject.SetActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
// Unity Callbacks.
|
||||
//################################
|
||||
private void OnEnable()
|
||||
{
|
||||
if (m_OpenButton)
|
||||
{
|
||||
m_OpenButton.onClick.AddListener(Open);
|
||||
}
|
||||
|
||||
if (m_CloseButton)
|
||||
{
|
||||
m_CloseButton.onClick.AddListener(Close);
|
||||
}
|
||||
|
||||
if (m_Opened)
|
||||
{
|
||||
Open();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (m_OpenButton)
|
||||
{
|
||||
m_OpenButton.onClick.RemoveListener(Open);
|
||||
}
|
||||
|
||||
if (m_CloseButton)
|
||||
{
|
||||
m_CloseButton.onClick.RemoveListener(Close);
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
_frames++;
|
||||
_elapsed += Time.unscaledDeltaTime;
|
||||
_fpsElapsed += Time.unscaledDeltaTime;
|
||||
if (_elapsed < m_Interval) return;
|
||||
|
||||
if (m_Fps)
|
||||
{
|
||||
m_Fps.SetText("FPS: {0}", (int) (_frames / _fpsElapsed));
|
||||
}
|
||||
|
||||
if (m_Gc)
|
||||
{
|
||||
m_Gc.SetText("GC: {0}", GC.CollectionCount(0));
|
||||
}
|
||||
|
||||
if (m_MonoUsage)
|
||||
{
|
||||
var monoUsed = (UnityEngine.Profiling.Profiler.GetMonoUsedSizeLong() >> 10) / 1024f;
|
||||
var monoTotal = (UnityEngine.Profiling.Profiler.GetMonoHeapSizeLong() >> 10) / 1024f;
|
||||
if (m_Precision == 3)
|
||||
{
|
||||
m_MonoUsage.SetText("Mono: {0:N3}/{1:N3}MB", monoUsed, monoTotal);
|
||||
}
|
||||
else if (m_Precision == 2)
|
||||
{
|
||||
m_MonoUsage.SetText("Mono: {0:N2}/{1:N2}MB", monoUsed, monoTotal);
|
||||
}
|
||||
else if (m_Precision == 1)
|
||||
{
|
||||
m_MonoUsage.SetText("Mono: {0:N1}/{1:N1}MB", monoUsed, monoTotal);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_MonoUsage.SetText("Mono: {0:N0}/{1:N0}MB", monoUsed, monoTotal);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_UnityUsage)
|
||||
{
|
||||
var unityUsed = (UnityEngine.Profiling.Profiler.GetTotalAllocatedMemoryLong() >> 10) / 1024f;
|
||||
var unityTotal = (UnityEngine.Profiling.Profiler.GetTotalReservedMemoryLong() >> 10) / 1024f;
|
||||
if (m_Precision == 3)
|
||||
{
|
||||
m_UnityUsage.SetText("Unity: {0:N3}/{1:N3}MB", unityUsed, unityTotal);
|
||||
}
|
||||
else if (m_Precision == 2)
|
||||
{
|
||||
m_UnityUsage.SetText("Unity: {0:N2}/{1:N2}MB", unityUsed, unityTotal);
|
||||
}
|
||||
else if (m_Precision == 1)
|
||||
{
|
||||
m_UnityUsage.SetText("Unity: {0:N1}/{1:N1}MB", unityUsed, unityTotal);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_UnityUsage.SetText("Unity: {0:N0}/{1:N0}MB", unityUsed, unityTotal);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var item in m_CustomMonitorItems)
|
||||
{
|
||||
item.UpdateText();
|
||||
}
|
||||
|
||||
_frames = 0;
|
||||
_elapsed %= m_Interval;
|
||||
_fpsElapsed = 0;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
if (m_Font)
|
||||
{
|
||||
foreach (var ui in GetComponentsInChildren<MonitorUI>(true))
|
||||
{
|
||||
ui.font = m_Font;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_Opened)
|
||||
{
|
||||
Open();
|
||||
}
|
||||
else
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 19e83f45e7d5648f2bd10122dc7fed14
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: affee221821a14cfb842a0b0e8514a4e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,138 @@
|
|||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Coffee.NanoMonitor{
|
||||
public class FixedFont
|
||||
{
|
||||
private readonly UIVertex[] _tmpVerts = new UIVertex[4];
|
||||
private static readonly Dictionary<Font, FixedFont> _fonts = new Dictionary<Font, FixedFont>();
|
||||
private static readonly TextGenerator _textGenerator = new TextGenerator(100);
|
||||
|
||||
private static TextGenerationSettings _settings = new TextGenerationSettings
|
||||
{
|
||||
scaleFactor = 1,
|
||||
horizontalOverflow = HorizontalWrapMode.Overflow,
|
||||
verticalOverflow = VerticalWrapMode.Overflow,
|
||||
alignByGeometry = true,
|
||||
textAnchor = TextAnchor.MiddleCenter,
|
||||
color = Color.white
|
||||
};
|
||||
|
||||
private int _resolution = 0;
|
||||
private readonly Font _font;
|
||||
private UIVertex[] _verts;
|
||||
private UICharInfo[] _charInfos;
|
||||
|
||||
private FixedFont(Font font)
|
||||
{
|
||||
_font = font;
|
||||
}
|
||||
|
||||
public int fontSize => _font.dynamic ? 32 : _font.fontSize;
|
||||
|
||||
public static FixedFont GetOrCreate(Font font)
|
||||
{
|
||||
if (font == null) return null;
|
||||
if (_fonts.TryGetValue(font, out var data)) return data;
|
||||
|
||||
data = new FixedFont(font);
|
||||
_fonts.Add(font, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
public void Invalidate()
|
||||
{
|
||||
_resolution = 0;
|
||||
}
|
||||
|
||||
public void UpdateFont()
|
||||
{
|
||||
if (!_font) return;
|
||||
|
||||
var mat = _font.material;
|
||||
if (!mat) return;
|
||||
|
||||
var tex = mat.mainTexture;
|
||||
if (!tex) return;
|
||||
|
||||
var currentResolution = tex.width * tex.height;
|
||||
|
||||
if (_resolution == currentResolution) return;
|
||||
_resolution = currentResolution;
|
||||
|
||||
_settings.font = _font;
|
||||
_textGenerator.Invalidate();
|
||||
_textGenerator.Populate("_!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", _settings);
|
||||
|
||||
_verts = _textGenerator.GetVerticesArray();
|
||||
_charInfos = _textGenerator.GetCharactersArray();
|
||||
|
||||
float offsetX = 0;
|
||||
for (var i = 0; i < _verts.Length; i++)
|
||||
{
|
||||
if ((i & 3) == 0)
|
||||
offsetX = _verts[i].position.x;
|
||||
|
||||
var v = _verts[i];
|
||||
v.position -= new Vector3(offsetX, 0);
|
||||
_verts[i] = v;
|
||||
}
|
||||
}
|
||||
|
||||
public float Layout(char c, float offset, float scale)
|
||||
{
|
||||
if (_charInfos == null) return offset;
|
||||
if (c < 0x20 || 0x7e < c) return offset;
|
||||
var ci = c - 0x20;
|
||||
|
||||
return offset + _charInfos[ci].charWidth * scale;
|
||||
}
|
||||
|
||||
public float Append(VertexHelper toFill, char c, float offset, float scale, Color color)
|
||||
{
|
||||
if (_verts == null || _charInfos == null) return offset;
|
||||
if (c < 0x20 || 0x7e < c) return offset;
|
||||
var ci = c - 0x20;
|
||||
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
_tmpVerts[i] = _verts[ci * 4 + i];
|
||||
_tmpVerts[i].position = _tmpVerts[i].position * scale + new Vector3(offset, 0);
|
||||
_tmpVerts[i].color = ci == 0 ? Color.clear : color;
|
||||
}
|
||||
|
||||
toFill.AddUIVertexQuad(_tmpVerts);
|
||||
return offset + _charInfos[ci].charWidth * scale;
|
||||
}
|
||||
|
||||
public void Fill(VertexHelper toFill, Color color, RectTransform tr)
|
||||
{
|
||||
if (_verts == null || _charInfos == null) return;
|
||||
const int ci = '*' - 0x20;
|
||||
var uv = (_verts[ci * 4].uv0 + _verts[ci * 4 + 2].uv0) / 2;
|
||||
|
||||
var rect = tr.rect;
|
||||
var size = rect.size / 2;
|
||||
var offset = (new Vector2(0.5f, 0.5f) - tr.pivot) * rect.size;
|
||||
|
||||
for (var i = 0; i < 4; i++)
|
||||
{
|
||||
_tmpVerts[i] = new UIVertex();
|
||||
_tmpVerts[i].uv0 = uv;
|
||||
_tmpVerts[i].color = color;
|
||||
|
||||
if (i == 0)
|
||||
_tmpVerts[i].position = new Vector2(-size.x, -size.y) + offset;
|
||||
else if (i == 1)
|
||||
_tmpVerts[i].position = new Vector2(-size.x, size.y) + offset;
|
||||
else if (i == 2)
|
||||
_tmpVerts[i].position = new Vector2(size.x, size.y) + offset;
|
||||
else
|
||||
_tmpVerts[i].position = new Vector2(size.x, -size.y) + offset;
|
||||
}
|
||||
|
||||
toFill.AddUIVertexQuad(_tmpVerts);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9a8c5c555d4bf4361ab3435c318c0699
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- m_Material: {fileID: 2100000, guid: 4da4639f724144ddead57bffca64e71f, type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,236 @@
|
|||
using System.Text;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Coffee.NanoMonitor{
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
|
||||
[CustomEditor(typeof(MonitorUI))]
|
||||
public class MonitorTextEditor : Editor
|
||||
{
|
||||
private SerializedProperty m_Mode;
|
||||
private SerializedProperty m_TextAnchor;
|
||||
private SerializedProperty m_FontSize;
|
||||
private SerializedProperty m_Font;
|
||||
private SerializedProperty m_Text;
|
||||
private SerializedProperty m_Color;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
m_Mode = serializedObject.FindProperty("m_Mode");
|
||||
|
||||
m_Text = serializedObject.FindProperty("m_Text");
|
||||
m_Color = serializedObject.FindProperty("m_Color");
|
||||
var fontData = serializedObject.FindProperty("m_FontData");
|
||||
m_FontSize = fontData.FindPropertyRelative("m_FontSize");
|
||||
m_Font = fontData.FindPropertyRelative("m_Font");
|
||||
m_TextAnchor = serializedObject.FindProperty("m_TextAnchor");
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
EditorGUILayout.PropertyField(m_Mode);
|
||||
if ((MonitorUI.Mode) m_Mode.intValue == MonitorUI.Mode.Text)
|
||||
{
|
||||
EditorGUILayout.PropertyField(m_Text);
|
||||
EditorGUILayout.PropertyField(m_FontSize);
|
||||
EditorGUILayout.PropertyField(m_TextAnchor);
|
||||
|
||||
//EditorGUI.BeginDisabledGroup(true);
|
||||
EditorGUILayout.PropertyField(m_Font);
|
||||
//EditorGUI.EndDisabledGroup();
|
||||
}
|
||||
|
||||
EditorGUILayout.PropertyField(m_Color);
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public class MonitorUI : Text
|
||||
{
|
||||
public enum Mode
|
||||
{
|
||||
Text,
|
||||
Fill,
|
||||
}
|
||||
|
||||
public enum TextAnchor
|
||||
{
|
||||
Left,
|
||||
Center,
|
||||
Right
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
// Serialize Members.
|
||||
//################################
|
||||
[SerializeField] private Mode m_Mode = Mode.Text;
|
||||
[SerializeField] private TextAnchor m_TextAnchor;
|
||||
|
||||
|
||||
//################################
|
||||
// Public Members.
|
||||
//################################
|
||||
public override string text
|
||||
{
|
||||
get => m_StringBuilder.ToString();
|
||||
set
|
||||
{
|
||||
m_Text = value;
|
||||
if (m_StringBuilder.IsEqual(m_Text)) return;
|
||||
|
||||
m_StringBuilder.Length = 0;
|
||||
m_StringBuilder.Append(m_Text);
|
||||
SetVerticesDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public TextAnchor textAnchor
|
||||
{
|
||||
get => m_TextAnchor;
|
||||
set
|
||||
{
|
||||
if (m_TextAnchor == value) return;
|
||||
|
||||
m_TextAnchor = value;
|
||||
SetVerticesDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public override bool raycastTarget
|
||||
{
|
||||
get => m_Mode == Mode.Fill;
|
||||
set { }
|
||||
}
|
||||
|
||||
public void SetText(string format, double arg0 = 0, double arg1 = 0, double arg2 = 0, double arg3 = 0)
|
||||
{
|
||||
m_StringBuilder.Length = 0;
|
||||
m_StringBuilder.AppendFormatNoAlloc(format, arg0, arg1, arg2, arg3);
|
||||
SetVerticesDirty();
|
||||
}
|
||||
|
||||
public void SetText(StringBuilder builder)
|
||||
{
|
||||
m_StringBuilder.Length = 0;
|
||||
m_StringBuilder.Append(builder);
|
||||
SetVerticesDirty();
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
// Private Members.
|
||||
//################################
|
||||
private readonly StringBuilder m_StringBuilder = new StringBuilder(64);
|
||||
|
||||
private void UpdateFont()
|
||||
{
|
||||
//var globalFont = NNanoMonitorttings.Instance.font;
|
||||
//if (globalFont)
|
||||
//{
|
||||
// font = globalFont;
|
||||
//}
|
||||
|
||||
var fontData = FixedFont.GetOrCreate(font);
|
||||
if (fontData != null)
|
||||
{
|
||||
fontData.Invalidate();
|
||||
fontData.UpdateFont();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
// Unity Callbacks.
|
||||
//################################
|
||||
protected override void OnEnable()
|
||||
{
|
||||
//NaNanoMonitortings.Instance.onFontChanged += UpdateFont;
|
||||
RegisterDirtyMaterialCallback(UpdateFont);
|
||||
|
||||
base.OnEnable();
|
||||
raycastTarget = false;
|
||||
maskable = false;
|
||||
m_StringBuilder.Length = 0;
|
||||
m_StringBuilder.Append(m_Text);
|
||||
}
|
||||
|
||||
protected override void OnDisable()
|
||||
{
|
||||
//NanNanoMonitorings.Instance.onFontChanged -= UpdateFont;
|
||||
UnregisterDirtyMaterialCallback(UpdateFont);
|
||||
|
||||
base.OnDisable();
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate()
|
||||
{
|
||||
base.OnValidate();
|
||||
|
||||
if (!m_StringBuilder.IsEqual(m_Text))
|
||||
{
|
||||
m_StringBuilder.Length = 0;
|
||||
m_StringBuilder.Append(m_Text);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
protected override void OnPopulateMesh(VertexHelper toFill)
|
||||
{
|
||||
toFill.Clear();
|
||||
|
||||
var fontData = FixedFont.GetOrCreate(font);
|
||||
if (fontData == null) return;
|
||||
|
||||
fontData.UpdateFont();
|
||||
|
||||
if (m_Mode == Mode.Fill)
|
||||
{
|
||||
fontData.Fill(toFill, color, rectTransform);
|
||||
return;
|
||||
}
|
||||
|
||||
var scale = (float) fontSize / fontData.fontSize;
|
||||
float offset = 0;
|
||||
switch (textAnchor)
|
||||
{
|
||||
case TextAnchor.Left:
|
||||
offset = rectTransform.rect.xMin;
|
||||
break;
|
||||
case TextAnchor.Center:
|
||||
for (var i = 0; i < m_StringBuilder.Length; i++)
|
||||
offset = fontData.Layout(m_StringBuilder[i], offset, scale);
|
||||
offset = -offset / 2;
|
||||
break;
|
||||
case TextAnchor.Right:
|
||||
for (var i = 0; i < m_StringBuilder.Length; i++)
|
||||
offset = fontData.Layout(m_StringBuilder[i], offset, scale);
|
||||
offset = rectTransform.rect.xMax - offset;
|
||||
break;
|
||||
}
|
||||
|
||||
for (var i = 0; i < m_StringBuilder.Length; i++)
|
||||
{
|
||||
offset = fontData.Append(toFill, m_StringBuilder[i], offset, scale, color);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateMaterial()
|
||||
{
|
||||
base.UpdateMaterial();
|
||||
|
||||
var fontData = FixedFont.GetOrCreate(font);
|
||||
if (fontData != null)
|
||||
{
|
||||
fontData.UpdateFont();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b0e08c6080a2e4d8186f97c60518830f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- m_Material: {fileID: 2100000, guid: 4da4639f724144ddead57bffca64e71f, type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,55 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace Coffee.MiniProfiler
|
||||
{
|
||||
internal class MiniProfilerSettings : ScriptableSettings<MiniProfilerSettings>
|
||||
{
|
||||
[Header("UI")]
|
||||
[SerializeField] private Font m_Font = null;
|
||||
|
||||
[Header("Instantiate On Boot")]
|
||||
[SerializeField] private GameObject miniProfilerPrefab = null;
|
||||
[SerializeField] private string[] m_SceneNames = new string[0];
|
||||
|
||||
public Font font => m_Font;
|
||||
public event Action onFontChanged;
|
||||
|
||||
protected override void OnBoot()
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
SceneManager.sceneLoaded += OnSceneLoaded;
|
||||
}
|
||||
|
||||
public void OnSceneLoaded(Scene scene, LoadSceneMode __)
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
if (!miniProfilerPrefab || !m_SceneNames.Contains(scene.name)) return;
|
||||
|
||||
var go = Instantiate(miniProfilerPrefab);
|
||||
if (Application.isPlaying)
|
||||
DontDestroyOnLoad(go);
|
||||
}
|
||||
|
||||
protected override bool bootOnPlayMode => true;
|
||||
protected override bool bootOnEditorMode => false;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
protected override void OnValidate()
|
||||
{
|
||||
onFontChanged?.Invoke();
|
||||
base.OnValidate();
|
||||
}
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
m_Font = UnityEngine.Resources.GetBuiltinResource<Font>("Arial.ttf");
|
||||
}
|
||||
|
||||
[UnityEditor.SettingsProvider]
|
||||
private static UnityEditor.SettingsProvider CreateSettingsProvider() => new ScriptableSettingsProvider<MiniProfilerSettings>();
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 647dad4f8226a49b9874b68b79413d64
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- miniProfilerPrefab: {fileID: 7211429669315726685, guid: 784696794bc6345bc80bf49623581c2e,
|
||||
type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,280 @@
|
|||
using UnityEngine;
|
||||
using System;
|
||||
using System.Linq;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
|
||||
#endif
|
||||
|
||||
namespace Coffee.MiniProfiler
|
||||
{
|
||||
internal abstract class ScriptableSettings : ScriptableObject
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
public virtual string GetSettingPath()
|
||||
{
|
||||
return GetSettingPath(GetType());
|
||||
}
|
||||
|
||||
internal static string GetSettingPath(Type type)
|
||||
{
|
||||
return $"Project/{ObjectNames.NicifyVariableName(type.Name.Replace("ProjectSettings", ""))}";
|
||||
}
|
||||
#endif
|
||||
|
||||
public virtual string GetDefaultAssetPath()
|
||||
{
|
||||
return $"Assets/ProjectSettings/{GetType().Name}.asset";
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class ScriptableSettings<T> : ScriptableSettings
|
||||
where T : ScriptableSettings<T>
|
||||
{
|
||||
//################################
|
||||
// Public Members.
|
||||
//################################
|
||||
public static T Instance => _instance ? _instance : _instance = GetOrCreate();
|
||||
|
||||
private static T _instance;
|
||||
|
||||
protected virtual bool bootOnEditorMode => true;
|
||||
protected virtual bool bootOnPlayMode => true;
|
||||
|
||||
protected abstract void OnBoot();
|
||||
|
||||
#if UNITY_EDITOR
|
||||
//################################
|
||||
// Private Members.
|
||||
//################################
|
||||
private bool enabled;
|
||||
|
||||
private static T GetOrCreate()
|
||||
{
|
||||
return PlayerSettings.GetPreloadedAssets()
|
||||
.OfType<T>()
|
||||
.FirstOrDefault() ?? CreateInstance<T>();
|
||||
}
|
||||
|
||||
private void OnPlayModeStateChanged(PlayModeStateChange state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case PlayModeStateChange.EnteredEditMode:
|
||||
enabled = true;
|
||||
Boot();
|
||||
break;
|
||||
case PlayModeStateChange.ExitingEditMode:
|
||||
case PlayModeStateChange.ExitingPlayMode:
|
||||
enabled = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void Boot()
|
||||
{
|
||||
var preloadedAssets = PlayerSettings.GetPreloadedAssets();
|
||||
var assets = preloadedAssets.OfType<T>().ToArray();
|
||||
var first = assets.FirstOrDefault() ?? this as T;
|
||||
|
||||
// If there are no preloaded assets, registry the first asset.
|
||||
// If there are multiple preloaded assets, unregisters all but the first one.
|
||||
if (assets.Length != 1)
|
||||
{
|
||||
// The first asset is not saved.
|
||||
if (string.IsNullOrEmpty(AssetDatabase.GetAssetPath(first)))
|
||||
{
|
||||
if (!AssetDatabase.IsValidFolder("Assets/ProjectSettings"))
|
||||
AssetDatabase.CreateFolder("Assets", "ProjectSettings");
|
||||
|
||||
var assetName = ObjectNames.NicifyVariableName(first.GetType().Name.Replace("ProjectSettings", ""));
|
||||
var assetPath = AssetDatabase.GenerateUniqueAssetPath($"Assets/ProjectSettings/{assetName}.asset");
|
||||
AssetDatabase.CreateAsset(first, assetPath);
|
||||
}
|
||||
|
||||
PlayerSettings.SetPreloadedAssets(preloadedAssets
|
||||
.Where(x => x)
|
||||
.Except(assets)
|
||||
.Concat(new[] {first})
|
||||
.ToArray());
|
||||
}
|
||||
|
||||
// Another asset is registered as a preload asset.
|
||||
if (first != this)
|
||||
{
|
||||
UnityEngine.Debug.LogError($"Another asset '{first}' is registered as a preload '{typeof(T).Name}' asset." +
|
||||
$"\nThis instance ('{this}') will be ignored. Check 'Project Settings > Player > Preload Assets'", this);
|
||||
return;
|
||||
}
|
||||
|
||||
_instance = first;
|
||||
|
||||
// Do nothing on editor mode.
|
||||
if (!bootOnEditorMode && !EditorApplication.isPlayingOrWillChangePlaymode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Do nothing on play mode.
|
||||
if (!bootOnPlayMode && EditorApplication.isPlayingOrWillChangePlaymode)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
OnBoot();
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
// Unity Callbacks.
|
||||
//################################
|
||||
private void OnEnable()
|
||||
{
|
||||
enabled = true;
|
||||
Boot();
|
||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
|
||||
}
|
||||
|
||||
protected virtual void OnValidate()
|
||||
{
|
||||
if (enabled)
|
||||
Boot();
|
||||
}
|
||||
#else
|
||||
private static T GetOrCreate()
|
||||
{
|
||||
return CreateInstance<T>();
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (!bootOnPlayMode) return;
|
||||
|
||||
_instance = this as T;
|
||||
OnBoot();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
[CustomEditor(typeof(ScriptablePreferenceSettings<>), true)]
|
||||
internal class ScriptablePreferenceSettingsEditor : Editor
|
||||
{
|
||||
private static readonly GUIContent _button = new GUIContent("Open Project Settings");
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
if (GUILayout.Button(_button))
|
||||
{
|
||||
SettingsService.OpenProjectSettings(((ScriptableSettings) target).GetSettingPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class ScriptablePreferenceSettings<T> : ScriptableSingleton<T>
|
||||
where T : ScriptablePreferenceSettings<T>
|
||||
{
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[CustomEditor(typeof(ScriptableSettings), true)]
|
||||
internal class ScriptableSettingsEditor : Editor
|
||||
{
|
||||
private static readonly GUIContent _button = new GUIContent("Open Project Settings");
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
if (GUILayout.Button(_button))
|
||||
{
|
||||
SettingsService.OpenProjectSettings(((ScriptableSettings) target).GetSettingPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class ScriptableSettingsProvider<T> : SettingsProvider where T : ScriptableSettings<T>
|
||||
{
|
||||
public ScriptableSettingsProvider(string path) : base(path)
|
||||
{
|
||||
}
|
||||
|
||||
public ScriptableSettingsProvider() : base(ScriptableSettings.GetSettingPath(typeof(T)))
|
||||
{
|
||||
}
|
||||
|
||||
protected SerializedObject serializedObject { get; private set; }
|
||||
protected ScriptableSettings<T> target { get; private set; }
|
||||
|
||||
public sealed override void OnGUI(string searchContext)
|
||||
{
|
||||
if (!target)
|
||||
{
|
||||
target = ScriptableSettings<T>.Instance;
|
||||
serializedObject = new SerializedObject(target);
|
||||
}
|
||||
|
||||
OnGUI();
|
||||
}
|
||||
|
||||
protected virtual void OnGUI()
|
||||
{
|
||||
serializedObject.UpdateIfRequiredOrScript();
|
||||
var iterator = serializedObject.GetIterator();
|
||||
var enterChildren = true;
|
||||
while (iterator.NextVisible(enterChildren))
|
||||
{
|
||||
if (iterator.propertyPath != "m_Script")
|
||||
EditorGUILayout.PropertyField(iterator, true);
|
||||
|
||||
enterChildren = false;
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
|
||||
internal class ScriptablePreferenceSettingsProvider<T> : SettingsProvider where T : ScriptableSettings<T>
|
||||
{
|
||||
public ScriptablePreferenceSettingsProvider(string path) : base(path, SettingsScope.User)
|
||||
{
|
||||
}
|
||||
|
||||
public ScriptablePreferenceSettingsProvider() : base(ScriptableSettings.GetSettingPath(typeof(T)), SettingsScope.User)
|
||||
{
|
||||
}
|
||||
|
||||
protected SerializedObject serializedObject { get; private set; }
|
||||
protected ScriptableSettings<T> target { get; private set; }
|
||||
|
||||
public sealed override void OnGUI(string searchContext)
|
||||
{
|
||||
if (!target)
|
||||
{
|
||||
target = ScriptableSettings<T>.Instance;
|
||||
serializedObject = new SerializedObject(target);
|
||||
}
|
||||
|
||||
OnGUI();
|
||||
}
|
||||
|
||||
protected virtual void OnGUI()
|
||||
{
|
||||
serializedObject.UpdateIfRequiredOrScript();
|
||||
var iterator = serializedObject.GetIterator();
|
||||
var enterChildren = true;
|
||||
while (iterator.NextVisible(enterChildren))
|
||||
{
|
||||
if (iterator.propertyPath != "m_Script")
|
||||
EditorGUILayout.PropertyField(iterator, true);
|
||||
|
||||
enterChildren = false;
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6ea9606f69cee413e9f96f52de99fa5e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 1051ed7e3f1474ed59ca41b33b00029b
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,47 @@
|
|||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace Coffee.NanoMonitor
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[CustomPropertyDrawer(typeof(CustomMonitorItem))]
|
||||
internal sealed class CustomMonitorItemDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect p, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.PropertyField(new Rect(p.x, p.y + 18 * 0, p.width, 16), property.FindPropertyRelative("m_Text"));
|
||||
EditorGUI.PropertyField(new Rect(p.x, p.y + 18 * 1, p.width, 16), property.FindPropertyRelative("m_Format"));
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUI.PropertyField(new Rect(p.x, p.y + 18 * 2, p.width, 16), property.FindPropertyRelative("m_Arg0"));
|
||||
EditorGUI.PropertyField(new Rect(p.x, p.y + 18 * 3, p.width, 16), property.FindPropertyRelative("m_Arg1"));
|
||||
EditorGUI.PropertyField(new Rect(p.x, p.y + 18 * 4, p.width, 16), property.FindPropertyRelative("m_Arg2"));
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
return (EditorGUIUtility.singleLineHeight + 2) * 5;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
[System.Serializable]
|
||||
public class CustomMonitorItem
|
||||
{
|
||||
[SerializeField] private MonitorUI m_Text = null;
|
||||
[SerializeField] private string m_Format = "";
|
||||
[SerializeField] private NumericProperty m_Arg0 = null;
|
||||
[SerializeField] private NumericProperty m_Arg1 = null;
|
||||
[SerializeField] private NumericProperty m_Arg2 = null;
|
||||
|
||||
public void UpdateText()
|
||||
{
|
||||
if (m_Text)
|
||||
m_Text.SetText(m_Format, m_Arg0.Get(), m_Arg1.Get(), m_Arg2.Get());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5c50c6434f4ad4488bfc5b0928dbb4c4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,199 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
|
||||
#endif
|
||||
|
||||
namespace Coffee.NanoMonitor
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[CustomPropertyDrawer(typeof(NumericProperty))]
|
||||
internal sealed class NumericPropertyDrawer : PropertyDrawer
|
||||
{
|
||||
private static Action<PropertyInfo> s_OnMenuSelected;
|
||||
private static GenericMenu s_PropertyMenu;
|
||||
|
||||
private static readonly Dictionary<Type, string> s_SupportedTypes = new Dictionary<Type, string>
|
||||
{
|
||||
{typeof(bool), "bool"},
|
||||
{typeof(sbyte), "sbyte"},
|
||||
{typeof(short), "short"},
|
||||
{typeof(int), "int"},
|
||||
{typeof(long), "long"},
|
||||
{typeof(byte), "byte"},
|
||||
{typeof(ushort), "ushort"},
|
||||
{typeof(uint), "uint"},
|
||||
{typeof(ulong), "ulong"},
|
||||
{typeof(float), "float"},
|
||||
{typeof(double), "double"},
|
||||
{typeof(decimal), "decimal"},
|
||||
};
|
||||
|
||||
private static void Init()
|
||||
{
|
||||
if (s_PropertyMenu != null) return;
|
||||
|
||||
var properties = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(assembly => assembly.GetTypes())
|
||||
.SelectMany(type => type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.GetProperty))
|
||||
.Where(pi => pi.GetMethod != null && s_SupportedTypes.ContainsKey(pi.PropertyType))
|
||||
.OrderBy(pi => ConvertToMenuItem(pi, false))
|
||||
.ToArray();
|
||||
|
||||
s_PropertyMenu = new GenericMenu();
|
||||
s_PropertyMenu.AddItem(new GUIContent("No Property"), false, arg => s_OnMenuSelected?.Invoke(arg as PropertyInfo), null);
|
||||
s_PropertyMenu.AddItem(new GUIContent("(Non Public Properties)/"), false, ()=>{});
|
||||
s_PropertyMenu.AddSeparator("");
|
||||
|
||||
foreach (var pi in properties)
|
||||
{
|
||||
s_PropertyMenu.AddItem(new GUIContent(ConvertToMenuItem(pi, true)), false, arg => s_OnMenuSelected?.Invoke(arg as PropertyInfo), pi);
|
||||
}
|
||||
}
|
||||
|
||||
private static string ConvertToMenuItem(PropertyInfo p, bool propertyType)
|
||||
{
|
||||
var type = p.DeclaringType;
|
||||
if (type == null) return "";
|
||||
var category = p.GetMethod.IsPublic && type.IsPublic ? "" : "(Non Public Properties)/";
|
||||
var typeName = type.FullName;
|
||||
var asmName = type.Assembly.GetName().Name;
|
||||
if (asmName == "UnityEngine.CoreModule")
|
||||
asmName = "UnityEngine";
|
||||
return propertyType
|
||||
? $"{category}{asmName}/{typeName}/{s_SupportedTypes[p.PropertyType]} {p.Name}"
|
||||
: $"{category}{asmName}/{typeName}/{p.Name}";
|
||||
}
|
||||
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
Init();
|
||||
label = EditorGUI.BeginProperty(position, label, property);
|
||||
|
||||
var path = property.FindPropertyRelative("m_Path");
|
||||
var split = path.stringValue.Split(';', ' ', ',');
|
||||
var name = split.Length == 4 ? $"{split[0]}.{split[3]}" : "No Property";
|
||||
|
||||
position = EditorGUI.PrefixLabel(position, label);
|
||||
if (GUI.Button(position, name, EditorStyles.popup))
|
||||
{
|
||||
s_OnMenuSelected = p =>
|
||||
{
|
||||
path.stringValue = p == null ? "" : $"{p.DeclaringType?.FullName}, {p.DeclaringType?.Assembly.GetName().Name};{p.Name}";
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
};
|
||||
s_PropertyMenu.DropDown(position);
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
[Serializable]
|
||||
public class NumericProperty : ISerializationCallbackReceiver
|
||||
{
|
||||
//################################
|
||||
// Serialized Members.
|
||||
//################################
|
||||
[SerializeField] private string m_Path = "";
|
||||
|
||||
|
||||
//################################
|
||||
// Public Members.
|
||||
//################################
|
||||
public double Get()
|
||||
{
|
||||
return _get?.Invoke() ?? -1;
|
||||
}
|
||||
|
||||
|
||||
//################################
|
||||
// Private Members.
|
||||
//################################
|
||||
private Func<double> _get = null;
|
||||
|
||||
private static PropertyInfo GetPropertyInfo(string path)
|
||||
{
|
||||
var p = path.Split(';');
|
||||
if (p.Length != 2) return null;
|
||||
|
||||
var type = Type.GetType(p[0]);
|
||||
if (type == null)
|
||||
{
|
||||
UnityEngine.Debug.LogException(new Exception($"Type '{p[0]}' is not found"));
|
||||
return null;
|
||||
}
|
||||
|
||||
var pInfo = type.GetProperty(p[1], BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Static);
|
||||
if (pInfo == null)
|
||||
{
|
||||
UnityEngine.Debug.LogException(new Exception($"Member '{p[1]}' is not found in type '{type}'"));
|
||||
}
|
||||
|
||||
return pInfo;
|
||||
}
|
||||
|
||||
private static Func<double> CreateFunc(MethodInfo mInfo)
|
||||
{
|
||||
if (mInfo == null) return null;
|
||||
switch (Type.GetTypeCode(mInfo.ReturnType))
|
||||
{
|
||||
case TypeCode.Boolean:
|
||||
var f_bool = (Func<bool>) mInfo.CreateDelegate(typeof(Func<bool>));
|
||||
return () => f_bool() ? 1 : 0;
|
||||
case TypeCode.Byte:
|
||||
var f_byte = (Func<byte>) mInfo.CreateDelegate(typeof(Func<byte>));
|
||||
return () => f_byte();
|
||||
case TypeCode.SByte:
|
||||
var f_sbyte = (Func<sbyte>) mInfo.CreateDelegate(typeof(Func<sbyte>));
|
||||
return () => f_sbyte();
|
||||
case TypeCode.UInt16:
|
||||
var f_ushort = (Func<ushort>) mInfo.CreateDelegate(typeof(Func<ushort>));
|
||||
return () => f_ushort();
|
||||
case TypeCode.UInt32:
|
||||
var f_uint = (Func<uint>) mInfo.CreateDelegate(typeof(Func<uint>));
|
||||
return () => f_uint();
|
||||
case TypeCode.UInt64:
|
||||
var f_ulong = (Func<ulong>) mInfo.CreateDelegate(typeof(Func<ulong>));
|
||||
return () => f_ulong();
|
||||
case TypeCode.Int16:
|
||||
var f_short = (Func<short>) mInfo.CreateDelegate(typeof(Func<short>));
|
||||
return () => f_short();
|
||||
case TypeCode.Int32:
|
||||
var f_int = (Func<int>) mInfo.CreateDelegate(typeof(Func<int>));
|
||||
return () => f_int();
|
||||
case TypeCode.Int64:
|
||||
var f_long = (Func<long>) mInfo.CreateDelegate(typeof(Func<long>));
|
||||
return () => f_long();
|
||||
case TypeCode.Decimal:
|
||||
var f_decimal = (Func<decimal>) mInfo.CreateDelegate(typeof(Func<decimal>));
|
||||
return () => (double) f_decimal();
|
||||
case TypeCode.Double:
|
||||
var f_double = (Func<double>) mInfo.CreateDelegate(typeof(Func<double>));
|
||||
return f_double;
|
||||
case TypeCode.Single:
|
||||
var f_float = (Func<float>) mInfo.CreateDelegate(typeof(Func<float>));
|
||||
return () => f_float();
|
||||
default:
|
||||
UnityEngine.Debug.LogException(new Exception(string.Format("Method '{1}.{0}' is not supported.", mInfo.Name, mInfo.DeclaringType)));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
void ISerializationCallbackReceiver.OnBeforeSerialize()
|
||||
{
|
||||
}
|
||||
|
||||
void ISerializationCallbackReceiver.OnAfterDeserialize()
|
||||
{
|
||||
var pInfo = GetPropertyInfo(m_Path);
|
||||
_get = CreateFunc(pInfo?.GetMethod);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 87fefa9f373e8411596b00238a65f3c3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,236 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
[assembly: InternalsVisibleTo("Coffee.NanoMonitor.Tests")]
|
||||
|
||||
namespace Coffee.NanoMonitor
|
||||
{
|
||||
internal static class StringBuilderExtensions
|
||||
{
|
||||
public static bool IsEqual(this StringBuilder sb, string other)
|
||||
{
|
||||
if (sb == null || other == null) return false;
|
||||
if (sb.Length != other.Length) return false;
|
||||
|
||||
for (var i = 0; i < sb.Length; i++)
|
||||
{
|
||||
if (sb[i] != other[i]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void AppendFormatNoAlloc(this StringBuilder sb, string format, double arg0 = 0, double arg1 = 0, double arg2 = 0, double arg3 = 0)
|
||||
{
|
||||
for (var i = 0; i < format.Length; i++)
|
||||
{
|
||||
var c = format[i];
|
||||
|
||||
// Append formatted value
|
||||
if (c == '{')
|
||||
{
|
||||
i = GetFormat(format, i, out var argIndex, out var padding, out var precision, out var alignment);
|
||||
|
||||
switch (argIndex)
|
||||
{
|
||||
case 0:
|
||||
sb.AppendDouble(arg0, padding, precision, alignment);
|
||||
break;
|
||||
case 1:
|
||||
sb.AppendDouble(arg1, padding, precision, alignment);
|
||||
break;
|
||||
case 2:
|
||||
sb.AppendDouble(arg2, padding, precision, alignment);
|
||||
break;
|
||||
case 3:
|
||||
sb.AppendDouble(arg3, padding, precision, alignment);
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Append character
|
||||
sb.Append(c);
|
||||
}
|
||||
}
|
||||
|
||||
internal static void AppendInteger(this StringBuilder sb, double number, int padding, int precision, int alignment)
|
||||
{
|
||||
number = Math.Truncate(number);
|
||||
var sign = number < 0;
|
||||
number = sign ? -number : number;
|
||||
|
||||
var startIndex = sb.Length;
|
||||
do
|
||||
{
|
||||
var n = Math.Truncate(number % 10);
|
||||
number /= 10;
|
||||
|
||||
sb.Append((char) (n + 48));
|
||||
} while (1 <= number || (sb.Length - startIndex) < padding);
|
||||
|
||||
if (sign)
|
||||
{
|
||||
sb.Append('-');
|
||||
}
|
||||
|
||||
var endIndex = sb.Length - 1;
|
||||
|
||||
sb.Reverse(startIndex, endIndex);
|
||||
sb.Alignment(alignment, startIndex, endIndex);
|
||||
}
|
||||
|
||||
internal static void AppendDouble(this StringBuilder sb, double number, int padding, int precision, int alignment)
|
||||
{
|
||||
var integer = Math.Truncate(number);
|
||||
var startIndex = sb.Length;
|
||||
sb.AppendInteger(integer, padding, precision, 0);
|
||||
|
||||
if (0 < precision)
|
||||
{
|
||||
sb.Append('.');
|
||||
number -= integer;
|
||||
number = Math.Round(number, precision);
|
||||
for (var p = 0; p < precision; p++)
|
||||
{
|
||||
number *= 10;
|
||||
integer = (long) number;
|
||||
sb.Append((char) (integer + 48));
|
||||
number -= integer;
|
||||
number = Math.Round(number, precision);
|
||||
}
|
||||
}
|
||||
|
||||
sb.Alignment(alignment, startIndex, sb.Length - 1);
|
||||
}
|
||||
|
||||
internal static void Reverse(this StringBuilder sb, int start, int end)
|
||||
{
|
||||
while (start < end)
|
||||
{
|
||||
var c = sb[start];
|
||||
sb[start] = sb[end];
|
||||
sb[end] = c;
|
||||
|
||||
start++;
|
||||
end--;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Alignment(this StringBuilder sb, int alignment, int start, int end)
|
||||
{
|
||||
if (alignment == 0) return;
|
||||
|
||||
var len = end - start + 1;
|
||||
if (0 < alignment && len < alignment)
|
||||
{
|
||||
sb.Append(' ', alignment - len);
|
||||
for (var i = 0; i < len; i++)
|
||||
{
|
||||
var c = sb[end - i];
|
||||
sb[end - i] = sb[start + alignment - i - 1];
|
||||
sb[start + alignment - i - 1] = c;
|
||||
}
|
||||
}
|
||||
else if (alignment < 0 && len < -alignment)
|
||||
{
|
||||
sb.Append(' ', -alignment - len);
|
||||
}
|
||||
}
|
||||
|
||||
internal static int GetFormat(string format, int i, out int argIndex, out int padding, out int precision, out int alignment)
|
||||
{
|
||||
argIndex = -1;
|
||||
padding = 0;
|
||||
precision = 0;
|
||||
alignment = 0;
|
||||
|
||||
var alignmentSign = false;
|
||||
var readFlag = 0;
|
||||
|
||||
for (; i < format.Length; i++)
|
||||
{
|
||||
var c = format[i];
|
||||
|
||||
// End format
|
||||
if (c == '}')
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
// Start format
|
||||
if (c == '{')
|
||||
{
|
||||
readFlag = 1;
|
||||
}
|
||||
|
||||
// After '{': Read argument index and format
|
||||
else if (readFlag == 1)
|
||||
{
|
||||
if ('0' <= c && c <= '3')
|
||||
{
|
||||
argIndex = c - 48;
|
||||
}
|
||||
else if (c == ',')
|
||||
{
|
||||
readFlag = 2;
|
||||
}
|
||||
else if (c == ':')
|
||||
{
|
||||
readFlag = 3;
|
||||
}
|
||||
}
|
||||
|
||||
//After ',': Read alignment value
|
||||
else if (readFlag == 2)
|
||||
{
|
||||
if ('0' <= c && c <= '9')
|
||||
{
|
||||
alignment = alignment * 10 + (alignmentSign ? 48 - c : c - 48);
|
||||
}
|
||||
else if (c == '-')
|
||||
{
|
||||
alignmentSign = true;
|
||||
}
|
||||
else if (c == ':')
|
||||
{
|
||||
readFlag = 3;
|
||||
}
|
||||
}
|
||||
|
||||
// After ':': Read format for integral
|
||||
else if (readFlag == 3)
|
||||
{
|
||||
if (c == '.')
|
||||
{
|
||||
precision = 0;
|
||||
readFlag = 4;
|
||||
}
|
||||
else if (c == '0')
|
||||
{
|
||||
padding++;
|
||||
}
|
||||
// Legacy mode
|
||||
else if ('1' <= c && c <= '9')
|
||||
{
|
||||
precision = c - 48;
|
||||
}
|
||||
}
|
||||
|
||||
// After '.': Read decimal precision value
|
||||
else if (readFlag == 4)
|
||||
{
|
||||
if (c == '0')
|
||||
{
|
||||
precision++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
argIndex = -1;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 23b4d6d0f5b8644b0981a065d7e47478
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences:
|
||||
- m_Material: {fileID: 2100000, guid: 4da4639f724144ddead57bffca64e71f, type: 3}
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "com.coffee.nano-monitor",
|
||||
"displayName": "Nano Monitor",
|
||||
"description": "This package displays FPS, memory status and any static properties.\n- extremely fast\n- no allocations (on build)\n-1 set pass call only\n- open/close/refresh (GC) buttons",
|
||||
"version": "1.0.0",
|
||||
"unity": "2018.3",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/mob-sakai/MaskTweaksForUGUI.git"
|
||||
},
|
||||
"author": "mob-sakai <sakai861104@gmail.com> (https://github.com/mob-sakai)",
|
||||
"dependencies": {},
|
||||
"keywords": [
|
||||
"monitor",
|
||||
"utility"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: be075f23fcc314d319e4f4ebfa6eefdd
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: db256ad6e34f94a4a95dedcbce09ddf1
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "Coffee.UIParticle.PerformanceDemo",
|
||||
"references": [
|
||||
"Coffee.UIParticle"
|
||||
],
|
||||
"optionalUnityReferences": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": []
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9c1a1a5e813ba46d2b837936f34e33a7
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,135 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace Coffee.UIExtensions.Demo
|
||||
{
|
||||
public class UIParticle_PerformanceDemo : MonoBehaviour
|
||||
{
|
||||
public GameObject copyOrigin;
|
||||
public int copyCount;
|
||||
public Canvas root;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Application.targetFrameRate = 60;
|
||||
|
||||
if (copyOrigin)
|
||||
{
|
||||
copyOrigin.SetActive(false);
|
||||
|
||||
var parent = copyOrigin.transform.parent;
|
||||
for (var i = 0; i < copyCount; i++)
|
||||
{
|
||||
var go = GameObject.Instantiate(copyOrigin, parent, false);
|
||||
go.name = string.Format("{0} {1}", copyOrigin.name, i + 1);
|
||||
go.hideFlags = HideFlags.DontSave;
|
||||
|
||||
go.SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ChangeScreenSize()
|
||||
{
|
||||
if (Screen.width == 400 && Screen.height == 720)
|
||||
Screen.SetResolution(720, 720, false);
|
||||
else if (Screen.width == 720 && Screen.height == 720)
|
||||
Screen.SetResolution(720, 400, false);
|
||||
else
|
||||
Screen.SetResolution(400, 720, false);
|
||||
}
|
||||
|
||||
public void EnableAnimations(bool enabled)
|
||||
{
|
||||
foreach (var animator in FindObjectsOfType<Animator>())
|
||||
{
|
||||
animator.enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
public void UIParticle_Enable(bool enabled)
|
||||
{
|
||||
|
||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
||||
{
|
||||
uip.enabled = enabled;
|
||||
}
|
||||
if (!enabled)
|
||||
{
|
||||
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
||||
{
|
||||
ps.Play(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void UIParticle_MeshSharing(bool enabled)
|
||||
{
|
||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
||||
{
|
||||
uip.meshSharing = enabled ? UIParticle.MeshSharing.Auto : UIParticle.MeshSharing.None;
|
||||
}
|
||||
}
|
||||
|
||||
public void UIParticle_RandomGroup(bool enabled)
|
||||
{
|
||||
foreach (var uip in root.GetComponentsInChildren<UIParticle>(true))
|
||||
{
|
||||
uip.groupMaxId = enabled ? 4 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void UIParticle_Scale(float scale)
|
||||
{
|
||||
foreach (var uip in FindObjectsOfType<UIParticle>())
|
||||
{
|
||||
uip.scale = scale;
|
||||
}
|
||||
}
|
||||
|
||||
public void ParticleSystem_WorldSpaseSimulation(bool enabled)
|
||||
{
|
||||
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
||||
{
|
||||
var main = ps.main;
|
||||
main.simulationSpace = enabled ? ParticleSystemSimulationSpace.World : ParticleSystemSimulationSpace.Local;
|
||||
}
|
||||
}
|
||||
|
||||
public void ParticleSystem_SetScale(float scale)
|
||||
{
|
||||
foreach (var ps in FindObjectsOfType<ParticleSystem>())
|
||||
{
|
||||
ps.transform.localScale = new Vector3(scale, scale, scale);
|
||||
}
|
||||
}
|
||||
|
||||
public void Canvas_WorldSpace(bool flag)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
var canvas = FindObjectOfType<Canvas>();
|
||||
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
||||
canvas.renderMode = RenderMode.WorldSpace;
|
||||
canvas.transform.rotation = Quaternion.Euler(new Vector3(0, 10, 0));
|
||||
}
|
||||
}
|
||||
|
||||
public void Canvas_CameraSpace(bool flag)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
var canvas = FindObjectOfType<Canvas>();
|
||||
canvas.renderMode = RenderMode.ScreenSpaceCamera;
|
||||
}
|
||||
}
|
||||
|
||||
public void Canvas_Overlay(bool flag)
|
||||
{
|
||||
if (flag)
|
||||
{
|
||||
var canvas = FindObjectOfType<Canvas>();
|
||||
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3a595cf9cf93f4e0686f247a5e7e19ce
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: aacefbb114f024ec0bd6d3153b28bb36
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
|
@ -0,0 +1,132 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fc4e1d816001842709cf8a393c69dd14
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 9
|
||||
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: 1
|
||||
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: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: iPhone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
- serializedVersion: 2
|
||||
buildTarget: WebGL
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: de8a1691f8aae4be18d66008040aa1a7
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
|
@ -0,0 +1,88 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 9b9aa386e19cb4bf4b7e055e962419e2
|
||||
TextureImporter:
|
||||
fileIDToRecycleName: {}
|
||||
externalObjects: {}
|
||||
serializedVersion: 9
|
||||
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: 16
|
||||
mipBias: -100
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 1
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
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: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 2
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 84e9fd7e25cf94cfc81bd77bc4f1d566
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
spritePackingTag:
|
||||
pSDRemoveMatte: 0
|
||||
pSDShowRemoveMatteOption: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 870ee15d24ba04925bce26ece2edb10e
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a4669dfbba654429bbcddf0c9b79fb8b
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -23,6 +23,12 @@ namespace Coffee.UIExtensions
|
|||
ImportSample(k_JsonGuid, "Cartoon FX & War FX Demo");
|
||||
}
|
||||
|
||||
[MenuItem("Assets/Samples/" + k_DisplayName + "/Cartoon FX & War FX Demo")]
|
||||
private static void ImportSample_PerformanceDemo()
|
||||
{
|
||||
ImportSample(k_JsonGuid, "Performance Demo");
|
||||
}
|
||||
|
||||
private static void ImportSample(string jsonGuid, string sampleName)
|
||||
{
|
||||
var jsonPath = AssetDatabase.GUIDToAssetPath(jsonGuid);
|
||||
|
|
|
@ -25,6 +25,11 @@
|
|||
"displayName": "Cartoon FX & War FX Demo",
|
||||
"description": "Cartoon FX & War FX Demo",
|
||||
"path": "Samples~/Cartoon FX & War FX Demo"
|
||||
},
|
||||
{
|
||||
"displayName": "Performance Demo",
|
||||
"description": "Performance Demo",
|
||||
"path": "Samples~/Performance Demo"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue