特效新内容。修复gameplay致命bug和分数保存bug

This commit is contained in:
FloatGaming
2026-02-16 01:55:18 +08:00
parent 3a7a0b4669
commit 9f7c1c57b7
206 changed files with 112684 additions and 857 deletions
@@ -0,0 +1,578 @@
/* ---------------------------------------
* Author: Martin Pane (martintayx@gmail.com) (@tayx94)
* Contributors: https://github.com/Tayx94/graphy/graphs/contributors
* Project: Graphy - Ultimate Stats Monitor
* Date: 02-Jan-18
* Studio: Tayx
*
* Git repo: https://github.com/Tayx94/graphy
*
* This project is released under the MIT license.
* Attribution is not required, but it is always welcomed!
* -------------------------------------*/
using System;
using UnityEngine;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
namespace Tayx.Graphy
{
[CustomEditor( typeof( GraphyDebugger ) )]
internal class GraphyDebuggerEditor : Editor
{
#region Variables -> Private
private GraphyDebugger m_target;
private int m_newDebugPacketListSize = 0;
private int m_previouslySelectedDebugPacketIndex = 0;
private int m_currentlySelectedDebugPacketIndex = 0;
private int m_selectedDebugPacketCondition = 0;
#endregion
#region Methods -> Unity Callbacks
private void OnEnable()
{
m_target = (GraphyDebugger) target;
}
#endregion
#region Methods -> Public Override
public override void OnInspectorGUI()
{
if( m_target == null && target == null )
{
base.OnInspectorGUI();
return;
}
float defaultLabelWidth = EditorGUIUtility.labelWidth;
float defaultFieldWidth = EditorGUIUtility.fieldWidth;
//===== CONTENT REGION ========================================================================
GUILayout.Space( 20 );
#region Section -> Logo
if( GraphyEditorStyle.DebuggerLogoTexture != null )
{
GUILayout.Label
(
image: GraphyEditorStyle.DebuggerLogoTexture,
style: new GUIStyle( GUI.skin.GetStyle( "Label" ) )
{
alignment = TextAnchor.UpperCenter
}
);
GUILayout.Space( 10 );
}
else
{
EditorGUILayout.LabelField
(
label: "[ GRAPHY - DEBUGGER ]",
style: GraphyEditorStyle.HeaderStyle1
);
}
#endregion
GUILayout.Space( 5 ); //Extra pixels added when the logo is used.
#region Section -> Settings
SerializedObject serObj = serializedObject;
SerializedProperty
debugPacketList =
serObj.FindProperty( "m_debugPackets" ); // Find the List in our script and create a refrence of it
//Update our list
serObj.Update();
EditorGUILayout.LabelField( "Current [Debug Packets] list size: " + debugPacketList.arraySize );
EditorGUIUtility.fieldWidth = 32;
EditorGUILayout.BeginHorizontal();
m_newDebugPacketListSize = EditorGUILayout.IntField
(
label: "Define a new list size",
value: m_newDebugPacketListSize
);
if( GUILayout.Button( "Resize List" ) )
{
if( EditorUtility.DisplayDialog
(
title:
"Resize List",
message:
"Are you sure you want to resize the entire List?\n\n" +
"Current List Size -> " +
debugPacketList.arraySize +
"\n" +
"New List Size -> " +
m_newDebugPacketListSize +
"\n" +
"This will add default entries if the value is greater than the list size, or erase the bottom values until the new size specified.",
ok:
"Resize",
cancel:
"Cancel" )
)
{
m_currentlySelectedDebugPacketIndex = 0;
if( m_newDebugPacketListSize != debugPacketList.arraySize )
{
while( m_newDebugPacketListSize > debugPacketList.arraySize )
{
debugPacketList.InsertArrayElementAtIndex( debugPacketList.arraySize );
SetDefaultDebugPacketValues( debugPacketList );
}
while( m_newDebugPacketListSize < debugPacketList.arraySize )
{
debugPacketList.DeleteArrayElementAtIndex( debugPacketList.arraySize - 1 );
}
}
}
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.LabelField( "NOT RECOMMENDED (Only use for first initialization)",
EditorStyles.centeredGreyMiniLabel );
EditorGUILayout.Space();
EditorGUILayout.Space();
if( debugPacketList.arraySize < 1 )
{
m_previouslySelectedDebugPacketIndex = 0;
m_currentlySelectedDebugPacketIndex = 0;
m_selectedDebugPacketCondition = 0;
serializedObject.ApplyModifiedProperties();
return;
}
GraphyEditorStyle.HeaderStyle2.contentOffset = Vector2.down * 3f;
EditorGUILayout.LabelField( "Selected debug packet:" );
EditorGUILayout.BeginHorizontal();
List<string> debugPacketNames = new List<string>();
for( int i = 0; i < debugPacketList.arraySize; i++ )
{
SerializedProperty listItem = debugPacketList.GetArrayElementAtIndex( i );
// NOTE: If the Popup detects two equal strings, it just paints 1, that's why I always add the "i"
char checkMark = listItem.FindPropertyRelative( "Active" ).boolValue ? '\u2714' : '\u2718';
debugPacketNames.Add
(
(i + 1) +
" (" +
checkMark +
") " +
" - ID: " +
listItem.FindPropertyRelative( "Id" ).intValue +
" (Conditions: " +
listItem.FindPropertyRelative( "DebugConditions" ).arraySize +
")"
);
}
m_currentlySelectedDebugPacketIndex =
EditorGUILayout.Popup( m_currentlySelectedDebugPacketIndex, debugPacketNames.ToArray() );
if( m_currentlySelectedDebugPacketIndex != m_previouslySelectedDebugPacketIndex )
{
m_selectedDebugPacketCondition = 0;
m_previouslySelectedDebugPacketIndex = m_currentlySelectedDebugPacketIndex;
}
Color defaultGUIColor = GUI.color;
GUI.color = new Color( 0.7f, 1f, 0.0f, 1f );
//Or add a new item to the List<> with a button
if( GUILayout.Button( "Add", GUILayout.Width( 60 ) ) )
{
debugPacketList.InsertArrayElementAtIndex( debugPacketList.arraySize );
SetDefaultDebugPacketValues( debugPacketList );
}
GUI.color = new Color( 1f, 0.7f, 0.0f, 1f );
//Remove this index from the List
if( GUILayout.Button( "Remove", GUILayout.Width( 60 ) ) )
{
debugPacketList.DeleteArrayElementAtIndex( m_currentlySelectedDebugPacketIndex );
if( m_currentlySelectedDebugPacketIndex > 0 )
{
m_currentlySelectedDebugPacketIndex--;
}
if( debugPacketList.arraySize < 1 )
{
serializedObject.ApplyModifiedProperties();
return;
}
}
GUI.color = defaultGUIColor;
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.Space();
//Display our list to the inspector window
SerializedProperty listItemSelected =
debugPacketList.GetArrayElementAtIndex( m_currentlySelectedDebugPacketIndex );
SerializedProperty Active = listItemSelected.FindPropertyRelative( "Active" );
SerializedProperty Id = listItemSelected.FindPropertyRelative( "Id" );
SerializedProperty ExecuteOnce = listItemSelected.FindPropertyRelative( "ExecuteOnce" );
SerializedProperty InitSleepTime = listItemSelected.FindPropertyRelative( "InitSleepTime" );
SerializedProperty ExecuteSleepTime = listItemSelected.FindPropertyRelative( "ExecuteSleepTime" );
SerializedProperty ConditionEvaluation = listItemSelected.FindPropertyRelative( "ConditionEvaluation" );
SerializedProperty DebugConditions = listItemSelected.FindPropertyRelative( "DebugConditions" );
SerializedProperty MessageType = listItemSelected.FindPropertyRelative( "MessageType" );
SerializedProperty Message = listItemSelected.FindPropertyRelative( "Message" );
SerializedProperty TakeScreenshot = listItemSelected.FindPropertyRelative( "TakeScreenshot" );
SerializedProperty ScreenshotFileName = listItemSelected.FindPropertyRelative( "ScreenshotFileName" );
SerializedProperty DebugBreak = listItemSelected.FindPropertyRelative( "DebugBreak" );
SerializedProperty UnityEvents = listItemSelected.FindPropertyRelative( "UnityEvents" );
#endregion
EditorGUILayout.LabelField
(
label:
"[ PACKET ] - ID: " +
Id.intValue +
" (Conditions: " +
DebugConditions.arraySize +
")",
style: GraphyEditorStyle.HeaderStyle2
);
EditorGUIUtility.labelWidth = 150;
EditorGUIUtility.fieldWidth = 35;
Active.boolValue = EditorGUILayout.Toggle
(
new GUIContent
(
text: "Active",
tooltip: "If false, it will not be checked"
),
value: Active.boolValue
);
Id.intValue = EditorGUILayout.IntField
(
new GUIContent
(
text: "ID",
tooltip: "Optional Id. It's used to get or remove DebugPackets in runtime"
),
value: Id.intValue
);
ExecuteOnce.boolValue = EditorGUILayout.Toggle
(
new GUIContent
(
text: "Execute once",
tooltip: "If true, once the actions are executed, this DebugPacket will delete itself"
),
value: ExecuteOnce.boolValue
);
InitSleepTime.floatValue = EditorGUILayout.FloatField
(
new GUIContent
(
text: "Init sleep time",
tooltip:
"Time to wait before checking if conditions are met (use this to avoid low fps drops triggering the conditions when loading the game)"
),
value: InitSleepTime.floatValue
);
ExecuteSleepTime.floatValue = EditorGUILayout.FloatField
(
new GUIContent
(
text: "Sleep time after execute",
tooltip:
"Time to wait before checking if conditions are met again (once they have already been met and if ExecuteOnce is false)"
),
value: ExecuteSleepTime.floatValue
);
EditorGUIUtility.labelWidth = defaultLabelWidth;
EditorGUIUtility.fieldWidth = defaultFieldWidth;
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField( "[ CONDITIONS ] (" + DebugConditions.arraySize + ")",
GraphyEditorStyle.HeaderStyle2 );
EditorGUILayout.PropertyField
(
ConditionEvaluation,
new GUIContent( "Condition evaluation" )
);
EditorGUILayout.Space();
if( DebugConditions.arraySize < 1 )
{
DebugConditions.InsertArrayElementAtIndex( DebugConditions.arraySize );
m_selectedDebugPacketCondition = 0;
}
EditorGUILayout.BeginHorizontal();
List<string> debugPacketConditionNames = new List<string>();
for( int i = 0; i < DebugConditions.arraySize; i++ )
{
SerializedProperty listItem = DebugConditions.GetArrayElementAtIndex( i );
// NOTE: If the Popup detects two equal strings, it just paints 1, that's why I always add the "i"
string conditionName = (i + 1).ToString() + " - ";
conditionName +=
GetComparerStringFromDebugVariable(
(GraphyDebugger.DebugVariable) listItem.FindPropertyRelative( "Variable" ).intValue ) + " ";
conditionName +=
GetComparerStringFromDebugComparer(
(GraphyDebugger.DebugComparer) listItem.FindPropertyRelative( "Comparer" ).intValue ) + " ";
conditionName += listItem.FindPropertyRelative( "Value" ).floatValue.ToString();
debugPacketConditionNames.Add( conditionName );
}
m_selectedDebugPacketCondition =
EditorGUILayout.Popup( m_selectedDebugPacketCondition, debugPacketConditionNames.ToArray() );
GUI.color = new Color( 0.7f, 1f, 0.0f, 1f );
if( GUILayout.Button( "Add", GUILayout.Width( 60 ) ) )
{
DebugConditions.InsertArrayElementAtIndex( DebugConditions.arraySize );
}
if( DebugConditions.arraySize > 1 )
{
GUI.color = new Color( 1f, 0.7f, 0.0f, 1f );
}
else
{
GUI.color = new Color( 1f, 0.7f, 0.0f, 0.5f );
}
//Remove this index from the List
if( GUILayout.Button( "Remove", GUILayout.Width( 60 ) ) )
{
if( DebugConditions.arraySize > 1 )
{
DebugConditions.DeleteArrayElementAtIndex( m_selectedDebugPacketCondition );
if( m_selectedDebugPacketCondition > 0 )
{
m_selectedDebugPacketCondition--;
}
}
}
GUI.color = defaultGUIColor;
EditorGUILayout.EndHorizontal();
SerializedProperty conditionListItemSelected =
DebugConditions.GetArrayElementAtIndex( m_selectedDebugPacketCondition );
SerializedProperty Variable = conditionListItemSelected.FindPropertyRelative( "Variable" );
SerializedProperty Comparer = conditionListItemSelected.FindPropertyRelative( "Comparer" );
SerializedProperty Value = conditionListItemSelected.FindPropertyRelative( "Value" );
EditorGUILayout.PropertyField
(
Variable,
new GUIContent( "Variable" )
);
EditorGUILayout.PropertyField
(
Comparer,
new GUIContent( "Comparer" )
);
EditorGUILayout.PropertyField
(
Value,
new GUIContent( "Value" )
);
EditorGUILayout.Space();
EditorGUILayout.Space();
EditorGUILayout.LabelField( "[ ACTIONS ]", GraphyEditorStyle.HeaderStyle2 );
EditorGUIUtility.labelWidth = 140;
EditorGUIUtility.fieldWidth = 35;
EditorGUILayout.PropertyField
(
MessageType,
new GUIContent( "Message type" )
);
EditorGUILayout.PropertyField( Message );
TakeScreenshot.boolValue = EditorGUILayout.Toggle
(
new GUIContent
(
text: "Take screenshot",
tooltip:
"If true, it takes a screenshot and stores it. The location where the image is written to can include a directory/folder list. With no directory/folder list the image will be written into the Project folder. On mobile platforms the filename is appended to the persistent data path."
),
value: TakeScreenshot.boolValue
);
if( TakeScreenshot.boolValue )
{
EditorGUILayout.PropertyField
(
ScreenshotFileName,
new GUIContent
(
text: "Screenshot file name",
tooltip:
"Avoid this characters: * . \" / \\ [ ] : ; | = , \n\nIt will have the date appended at the end to avoid overwriting."
)
);
}
DebugBreak.boolValue = EditorGUILayout.Toggle
(
new GUIContent
(
text: "Debug Break",
tooltip: "If true, it pauses the editor"
),
DebugBreak.boolValue
);
EditorGUILayout.PropertyField( UnityEvents );
EditorGUIUtility.labelWidth = defaultLabelWidth;
EditorGUIUtility.fieldWidth = defaultFieldWidth;
serializedObject.ApplyModifiedProperties();
}
#endregion
#region Methods -> Private
private void SetDefaultDebugPacketValues( SerializedProperty debugPacketSerializedProperty )
{
GraphyDebugger.DebugPacket debugPacket = new GraphyDebugger.DebugPacket();
debugPacketSerializedProperty.GetArrayElementAtIndex( debugPacketSerializedProperty.arraySize - 1 )
.FindPropertyRelative( "Active" )
.boolValue = debugPacket.Active;
debugPacketSerializedProperty.GetArrayElementAtIndex( debugPacketSerializedProperty.arraySize - 1 )
.FindPropertyRelative( "Id" )
.intValue = debugPacketSerializedProperty.arraySize;
debugPacketSerializedProperty.GetArrayElementAtIndex( debugPacketSerializedProperty.arraySize - 1 )
.FindPropertyRelative( "ExecuteOnce" )
.boolValue = debugPacket.ExecuteOnce;
debugPacketSerializedProperty.GetArrayElementAtIndex( debugPacketSerializedProperty.arraySize - 1 )
.FindPropertyRelative( "InitSleepTime" )
.floatValue = debugPacket.InitSleepTime;
debugPacketSerializedProperty.GetArrayElementAtIndex( debugPacketSerializedProperty.arraySize - 1 )
.FindPropertyRelative( "ExecuteSleepTime" )
.floatValue = debugPacket.ExecuteSleepTime;
}
private string GetComparerStringFromDebugVariable( GraphyDebugger.DebugVariable debugVariable )
{
switch( debugVariable )
{
case GraphyDebugger.DebugVariable.Fps:
return "FPS Current";
case GraphyDebugger.DebugVariable.Fps_Min:
return "FPS Min";
case GraphyDebugger.DebugVariable.Fps_Max:
return "FPS Max";
case GraphyDebugger.DebugVariable.Fps_Avg:
return "FPS Avg";
case GraphyDebugger.DebugVariable.Ram_Allocated:
return "Ram Allocated";
case GraphyDebugger.DebugVariable.Ram_Reserved:
return "Ram Reserved";
case GraphyDebugger.DebugVariable.Ram_Mono:
return "Ram Mono";
case GraphyDebugger.DebugVariable.Audio_DB:
return "Audio DB";
default:
return null;
}
}
private string GetComparerStringFromDebugComparer( GraphyDebugger.DebugComparer debugComparer )
{
switch( debugComparer )
{
case GraphyDebugger.DebugComparer.Less_than:
return "<";
case GraphyDebugger.DebugComparer.Equals_or_less_than:
return "<=";
case GraphyDebugger.DebugComparer.Equals:
return "==";
case GraphyDebugger.DebugComparer.Equals_or_greater_than:
return ">=";
case GraphyDebugger.DebugComparer.Greater_than:
return ">";
default:
return null;
}
}
#endregion
}
}
@@ -0,0 +1,19 @@
fileFormatVersion: 2
guid: 4a96825e094d61441b5247d0c32652b3
timeCreated: 1514907656
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 105778
packageName: '[Graphy] - Ultimate FPS Counter - Stats Monitor & Debugger'
packageVersion: 3.0.5
assetPath: Assets/Graphy - Ultimate Stats Monitor/Editor/GraphyDebuggerEditor.cs
uploadId: 626547
@@ -0,0 +1,118 @@
/* ---------------------------------------
* Author: Martin Pane (martintayx@gmail.com) (@tayx94)
* Contributors: https://github.com/Tayx94/graphy/graphs/contributors
* Project: Graphy - Ultimate Stats Monitor
* Date: 02-Jan-18
* Studio: Tayx
*
* Git repo: https://github.com/Tayx94/graphy
*
* This project is released under the MIT license.
* Attribution is not required, but it is always welcomed!
* -------------------------------------*/
using System;
using System.IO;
using UnityEditor;
using UnityEngine;
namespace Tayx.Graphy
{
internal static class GraphyEditorStyle
{
#region Variables -> Private
private static Texture2D _managerLogoTexture = null;
private static Texture2D _debuggerLogoTexture = null;
private static GUISkin m_skin = null;
private static GUIStyle m_headerStyle1 = null;
private static GUIStyle m_headerStyle2 = null;
private static GUIStyle m_foldoutStyle = null;
private static string path;
#endregion
#region Properties -> Public
public static Texture2D ManagerLogoTexture => _managerLogoTexture;
public static Texture2D DebuggerLogoTexture => _debuggerLogoTexture;
public static GUISkin Skin => m_skin;
public static GUIStyle HeaderStyle1 => m_headerStyle1;
public static GUIStyle HeaderStyle2 => m_headerStyle2;
public static GUIStyle FoldoutStyle => m_foldoutStyle;
#endregion
#region Static Constructor
static GraphyEditorStyle()
{
string managerLogoGuid = AssetDatabase.FindAssets( $"Manager_Logo_{(EditorGUIUtility.isProSkin ? "White" : "Dark")}" )[ 0 ];
string debuggerLogoGuid = AssetDatabase.FindAssets( $"Debugger_Logo_{(EditorGUIUtility.isProSkin ? "White" : "Dark")}" )[ 0 ];
string guiSkinGuid = AssetDatabase.FindAssets( "GraphyGUISkin" )[ 0 ];
_managerLogoTexture = AssetDatabase.LoadAssetAtPath<Texture2D>
(
AssetDatabase.GUIDToAssetPath( managerLogoGuid )
);
_debuggerLogoTexture = AssetDatabase.LoadAssetAtPath<Texture2D>
(
AssetDatabase.GUIDToAssetPath( debuggerLogoGuid )
);
m_skin = AssetDatabase.LoadAssetAtPath<GUISkin>
(
AssetDatabase.GUIDToAssetPath( guiSkinGuid )
);
if( m_skin != null )
{
m_headerStyle1 = m_skin.GetStyle( "Header1" );
m_headerStyle2 = m_skin.GetStyle( "Header2" );
SetGuiStyleFontColor
(
guiStyle: m_headerStyle2,
color: EditorGUIUtility.isProSkin ? Color.white : Color.black
);
}
else
{
m_headerStyle1 = EditorStyles.boldLabel;
m_headerStyle2 = EditorStyles.boldLabel;
}
m_foldoutStyle = new GUIStyle( EditorStyles.foldout )
{
font = m_headerStyle2.font,
fontStyle = m_headerStyle2.fontStyle,
contentOffset = Vector2.down * 3f
};
SetGuiStyleFontColor
(
guiStyle: m_foldoutStyle,
color: EditorGUIUtility.isProSkin ? Color.white : Color.black
);
}
#endregion
#region Methods -> Private
private static void SetGuiStyleFontColor( GUIStyle guiStyle, Color color )
{
guiStyle.normal.textColor = color;
guiStyle.hover.textColor = color;
guiStyle.active.textColor = color;
guiStyle.focused.textColor = color;
guiStyle.onNormal.textColor = color;
guiStyle.onHover.textColor = color;
guiStyle.onActive.textColor = color;
guiStyle.onFocused.textColor = color;
}
#endregion
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 1bb06e7c222a60f47a476e2648224330
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 105778
packageName: '[Graphy] - Ultimate FPS Counter - Stats Monitor & Debugger'
packageVersion: 3.0.5
assetPath: Assets/Graphy - Ultimate Stats Monitor/Editor/GraphyEditorStyle.cs
uploadId: 626547
@@ -0,0 +1,873 @@
/* ---------------------------------------
* Author: Martin Pane (martintayx@gmail.com) (@tayx94)
* Contributors: https://github.com/Tayx94/graphy/graphs/contributors
* Project: Graphy - Ultimate Stats Monitor
* Date: 20-Dec-17
* Studio: Tayx
*
* Git repo: https://github.com/Tayx94/graphy
*
* This project is released under the MIT license.
* Attribution is not required, but it is always welcomed!
* -------------------------------------*/
using System;
using UnityEngine;
using System.IO;
using UnityEditor;
namespace Tayx.Graphy
{
[CustomEditor( typeof( GraphyManager ) )]
internal class GraphyManagerEditor : Editor
{
#region Variables -> Private
private GraphyManager m_target;
private int[] m_spectrumSizeValues =
{
128,
256,
512,
1024,
2048,
4096,
8192
};
#region Section -> Settings
private SerializedProperty m_graphyMode;
private SerializedProperty m_enableOnStartup;
private SerializedProperty m_keepAlive;
private SerializedProperty m_background;
private SerializedProperty m_backgroundColor;
private SerializedProperty m_enableHotkeys;
private SerializedProperty m_toggleModeKeyCode;
private SerializedProperty m_toggleModeCtrl;
private SerializedProperty m_toggleModeAlt;
private SerializedProperty m_toggleActiveKeyCode;
private SerializedProperty m_toggleActiveCtrl;
private SerializedProperty m_toggleActiveAlt;
private SerializedProperty m_graphModulePosition;
private SerializedProperty m_graphModuleOffset;
#endregion
#region Section -> FPS
private bool m_fpsModuleInspectorToggle = true;
private SerializedProperty m_fpsModuleState;
private SerializedProperty m_goodFpsColor;
private SerializedProperty m_goodFpsThreshold;
private SerializedProperty m_cautionFpsColor;
private SerializedProperty m_cautionFpsThreshold;
private SerializedProperty m_criticalFpsColor;
private SerializedProperty m_fpsGraphResolution;
private SerializedProperty m_fpsTextUpdateRate;
#endregion
#region Section -> RAM
private bool m_ramModuleInspectorToggle = true;
private SerializedProperty m_ramModuleState;
private SerializedProperty m_allocatedRamColor;
private SerializedProperty m_reservedRamColor;
private SerializedProperty m_monoRamColor;
private SerializedProperty m_ramGraphResolution;
private SerializedProperty m_ramTextUpdateRate;
#endregion
#region Section -> Audio
private bool m_audioModuleInspectorToggle = true;
private SerializedProperty m_findAudioListenerInCameraIfNull;
private SerializedProperty m_audioListener;
private SerializedProperty m_audioModuleState;
private SerializedProperty m_audioGraphColor;
private SerializedProperty m_audioGraphResolution;
private SerializedProperty m_audioTextUpdateRate;
private SerializedProperty m_FFTWindow;
private SerializedProperty m_spectrumSize;
#endregion
#region Section -> Advanced Settings
private bool m_advancedModuleInspectorToggle = true;
private SerializedProperty m_advancedModulePosition;
private SerializedProperty m_advancedModuleOffset;
private SerializedProperty m_advancedModuleState;
#endregion
#endregion
#region Methods -> Unity Callbacks
private void OnEnable()
{
m_target = (GraphyManager) target;
SerializedObject serObj = serializedObject;
#region Section -> Settings
m_graphyMode = serObj.FindProperty( "m_graphyMode" );
m_enableOnStartup = serObj.FindProperty( "m_enableOnStartup" );
m_keepAlive = serObj.FindProperty( "m_keepAlive" );
m_background = serObj.FindProperty( "m_background" );
m_backgroundColor = serObj.FindProperty( "m_backgroundColor" );
m_enableHotkeys = serObj.FindProperty( "m_enableHotkeys" );
m_toggleModeKeyCode = serObj.FindProperty( "m_toggleModeKeyCode" );
m_toggleModeCtrl = serObj.FindProperty( "m_toggleModeCtrl" );
m_toggleModeAlt = serObj.FindProperty( "m_toggleModeAlt" );
m_toggleActiveKeyCode = serObj.FindProperty( "m_toggleActiveKeyCode" );
m_toggleActiveCtrl = serObj.FindProperty( "m_toggleActiveCtrl" );
m_toggleActiveAlt = serObj.FindProperty( "m_toggleActiveAlt" );
m_graphModulePosition = serObj.FindProperty( "m_graphModulePosition" );
m_graphModuleOffset = serObj.FindProperty( "m_graphModuleOffset" );
#endregion
#region Section -> FPS
m_fpsModuleState = serObj.FindProperty( "m_fpsModuleState" );
m_goodFpsColor = serObj.FindProperty( "m_goodFpsColor" );
m_goodFpsThreshold = serObj.FindProperty( "m_goodFpsThreshold" );
m_cautionFpsColor = serObj.FindProperty( "m_cautionFpsColor" );
m_cautionFpsThreshold = serObj.FindProperty( "m_cautionFpsThreshold" );
m_criticalFpsColor = serObj.FindProperty( "m_criticalFpsColor" );
m_fpsGraphResolution = serObj.FindProperty( "m_fpsGraphResolution" );
m_fpsTextUpdateRate = serObj.FindProperty( "m_fpsTextUpdateRate" );
#endregion
#region Section -> RAM
m_ramModuleState = serObj.FindProperty( "m_ramModuleState" );
m_allocatedRamColor = serObj.FindProperty( "m_allocatedRamColor" );
m_reservedRamColor = serObj.FindProperty( "m_reservedRamColor" );
m_monoRamColor = serObj.FindProperty( "m_monoRamColor" );
m_ramGraphResolution = serObj.FindProperty( "m_ramGraphResolution" );
m_ramTextUpdateRate = serObj.FindProperty( "m_ramTextUpdateRate" );
#endregion
#region Section -> Audio
m_findAudioListenerInCameraIfNull = serObj.FindProperty( "m_findAudioListenerInCameraIfNull" );
m_audioListener = serObj.FindProperty( "m_audioListener" );
m_audioModuleState = serObj.FindProperty( "m_audioModuleState" );
m_audioGraphColor = serObj.FindProperty( "m_audioGraphColor" );
m_audioGraphResolution = serObj.FindProperty( "m_audioGraphResolution" );
m_audioTextUpdateRate = serObj.FindProperty( "m_audioTextUpdateRate" );
m_FFTWindow = serObj.FindProperty( "m_FFTWindow" );
m_spectrumSize = serObj.FindProperty( "m_spectrumSize" );
#endregion
#region Section -> Advanced Settings
m_advancedModulePosition = serObj.FindProperty( "m_advancedModulePosition" );
m_advancedModuleOffset = serObj.FindProperty( "m_advancedModuleOffset" );
m_advancedModuleState = serObj.FindProperty( "m_advancedModuleState" );
#endregion
}
#endregion
#region Methods -> Public Override
public override void OnInspectorGUI()
{
if( m_target == null && target == null )
{
base.OnInspectorGUI();
return;
}
float defaultLabelWidth = EditorGUIUtility.labelWidth;
float defaultFieldWidth = EditorGUIUtility.fieldWidth;
//===== CONTENT REGION ========================================================================
GUILayout.Space( 20 );
#region Section -> Logo
if( GraphyEditorStyle.ManagerLogoTexture != null )
{
GUILayout.Label
(
image: GraphyEditorStyle.ManagerLogoTexture,
style: new GUIStyle( GUI.skin.GetStyle( "Label" ) )
{
alignment = TextAnchor.UpperCenter
}
);
GUILayout.Space( 10 );
}
else
{
EditorGUILayout.LabelField
(
label: "[ GRAPHY - MANAGER ]",
style: GraphyEditorStyle.HeaderStyle1
);
}
#endregion
GUILayout.Space( 5 ); //Extra pixels added when the logo is used.
#region Section -> Settings
EditorGUIUtility.labelWidth = 130;
EditorGUIUtility.fieldWidth = 35;
EditorGUILayout.PropertyField
(
m_graphyMode,
new GUIContent
(
text: "Graphy Mode",
tooltip:
"LIGHT mode increases compatibility with mobile and older, less powerful GPUs, but reduces the maximum graph resolutions to 128."
)
);
GUILayout.Space( 10 );
m_enableOnStartup.boolValue = EditorGUILayout.Toggle
(
new GUIContent
(
text: "Enable On Startup",
tooltip:
"If ticked, Graphy will be displayed by default on startup, otherwise it will initiate and hide."
),
value: m_enableOnStartup.boolValue
);
// This is a neat trick to hide Graphy in the Scene if it's going to be deactivated in play mode so that it doesn't use screen space.
if( !Application.isPlaying )
{
m_target.GetComponent<Canvas>().enabled = m_enableOnStartup.boolValue;
}
m_keepAlive.boolValue = EditorGUILayout.Toggle
(
new GUIContent
(
text: "Keep Alive",
tooltip:
"If ticked, it will survive scene changes.\n\nCAREFUL, if you set Graphy as a child of another GameObject, the root GameObject will also survive scene changes. If you want to avoid that put Graphy in the root of the Scene as its own entity."
),
value: m_keepAlive.boolValue
);
GUILayout.Space( 10 );
EditorGUILayout.BeginHorizontal();
m_background.boolValue = EditorGUILayout.Toggle
(
new GUIContent
(
text: "Background",
tooltip: "If ticked, it will show a background overlay to improve readability in cluttered scenes."
),
value: m_background.boolValue
);
m_backgroundColor.colorValue = EditorGUILayout.ColorField( m_backgroundColor.colorValue );
EditorGUILayout.EndHorizontal();
GUILayout.Space( 10 );
m_enableHotkeys.boolValue = EditorGUILayout.Toggle
(
new GUIContent
(
text: "Enable Hotkeys",
tooltip:
"If ticked, it will enable the hotkeys to be able to modify Graphy in runtime with custom keyboard shortcuts."
),
value: m_enableHotkeys.boolValue
);
if( m_enableHotkeys.boolValue )
{
EditorGUILayout.BeginHorizontal();
EditorGUIUtility.labelWidth = 130;
EditorGUIUtility.fieldWidth = 35;
EditorGUILayout.PropertyField
(
m_toggleModeKeyCode,
new GUIContent
(
text: "Toggle Mode Key",
tooltip: "If ticked, it will require clicking this key and the other ones you have set up."
)
);
EditorGUIUtility.labelWidth = 30;
EditorGUIUtility.fieldWidth = 35;
m_toggleModeCtrl.boolValue = EditorGUILayout.Toggle
(
new GUIContent
(
text: "Ctrl",
tooltip: "If ticked, it will require clicking Ctrl and the other keys you have set up."
),
value: m_toggleModeCtrl.boolValue
);
m_toggleModeAlt.boolValue = EditorGUILayout.Toggle
(
new GUIContent
(
text: "Alt",
tooltip: "If ticked, it will require clicking Alt and the other keys you have set up."
),
value: m_toggleModeAlt.boolValue
);
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUIUtility.labelWidth = 130;
EditorGUIUtility.fieldWidth = 35;
EditorGUILayout.PropertyField
(
m_toggleActiveKeyCode,
new GUIContent
(
text: "Toggle Active Key",
tooltip: "If ticked, it will require clicking this key and the other ones you have set up."
)
);
EditorGUIUtility.labelWidth = 30;
EditorGUIUtility.fieldWidth = 35;
m_toggleActiveCtrl.boolValue = EditorGUILayout.Toggle
(
new GUIContent
(
text: "Ctrl",
tooltip: "If ticked, it will require clicking Ctrl and the other kesy you have set up."
),
value: m_toggleActiveCtrl.boolValue
);
m_toggleActiveAlt.boolValue = EditorGUILayout.Toggle
(
new GUIContent
(
text: "Alt",
tooltip: "If ticked, it will require clicking Alt and the other keys you have set up."
),
value: m_toggleActiveAlt.boolValue
);
EditorGUILayout.EndHorizontal();
}
GUILayout.Space( 15 );
EditorGUIUtility.labelWidth = 155;
EditorGUIUtility.fieldWidth = 35;
EditorGUILayout.PropertyField
(
m_graphModulePosition,
new GUIContent
(
text: "Graph modules position",
tooltip: "Defines in which corner the modules will be located."
)
);
EditorGUILayout.PropertyField
(
m_graphModuleOffset,
new GUIContent
(
text: "Graph modules offset",
tooltip: "Defines how far from the corner the module will be located."
)
);
#endregion
GUILayout.Space( 20 );
#region Section -> FPS
m_fpsModuleInspectorToggle = EditorGUILayout.Foldout
(
m_fpsModuleInspectorToggle,
content: " [ FPS ]",
style: GraphyEditorStyle.FoldoutStyle,
toggleOnLabelClick: true
);
GUILayout.Space( 5 );
if( m_fpsModuleInspectorToggle )
{
EditorGUILayout.PropertyField
(
m_fpsModuleState,
new GUIContent
(
text: "Module state",
tooltip: "FULL -> Text + Graph \nTEXT -> Just text \nOFF -> Turned off"
)
);
GUILayout.Space( 5 );
EditorGUILayout.LabelField( "Fps thresholds and colors:" );
EditorGUI.indentLevel++;
EditorGUILayout.BeginHorizontal();
m_goodFpsThreshold.intValue = EditorGUILayout.IntField
(
new GUIContent
(
text: "- Good",
tooltip: "When FPS rise above this value, this color will be used."
),
value: m_goodFpsThreshold.intValue
);
m_goodFpsColor.colorValue = EditorGUILayout.ColorField( m_goodFpsColor.colorValue );
EditorGUILayout.EndHorizontal();
if( m_goodFpsThreshold.intValue <= m_cautionFpsThreshold.intValue && m_goodFpsThreshold.intValue > 1 )
{
m_cautionFpsThreshold.intValue = m_goodFpsThreshold.intValue - 1;
}
else if( m_goodFpsThreshold.intValue <= 1 )
{
m_goodFpsThreshold.intValue = 2;
}
EditorGUILayout.BeginHorizontal();
m_cautionFpsThreshold.intValue = EditorGUILayout.IntField
(
new GUIContent
(
text: "- Caution",
tooltip: "When FPS falls between this and the Good value, this color will be used."
),
value: m_cautionFpsThreshold.intValue
);
m_cautionFpsColor.colorValue = EditorGUILayout.ColorField( m_cautionFpsColor.colorValue );
EditorGUILayout.EndHorizontal();
if( m_cautionFpsThreshold.intValue >= m_goodFpsThreshold.intValue )
{
m_cautionFpsThreshold.intValue = m_goodFpsThreshold.intValue - 1;
}
else if( m_cautionFpsThreshold.intValue <= 0 )
{
m_cautionFpsThreshold.intValue = 1;
}
EditorGUILayout.BeginHorizontal();
EditorGUILayout.IntField
(
new GUIContent
(
text: "- Critical",
tooltip:
"When FPS falls below the Caution value, this color will be used. (You can't have negative FPS, so this value is just for reference, it can't be changed)."
),
value: 0
);
m_criticalFpsColor.colorValue = EditorGUILayout.ColorField( m_criticalFpsColor.colorValue );
EditorGUILayout.EndHorizontal();
EditorGUI.indentLevel--;
if( m_fpsModuleState.intValue == 0 )
{
m_fpsGraphResolution.intValue = EditorGUILayout.IntSlider
(
new GUIContent
(
text: "Graph resolution",
tooltip: "Defines the amount of points in the graph"
),
m_fpsGraphResolution.intValue,
leftValue: 20,
rightValue: m_graphyMode.intValue == 0 ? 300 : 128
);
}
m_fpsTextUpdateRate.intValue = EditorGUILayout.IntSlider
(
new GUIContent
(
text: "Text update rate",
tooltip: "Defines the amount times the text is updated in 1 second."
),
m_fpsTextUpdateRate.intValue,
leftValue: 1,
rightValue: 60
);
}
#endregion
GUILayout.Space( 20 );
#region Section -> RAM
m_ramModuleInspectorToggle = EditorGUILayout.Foldout
(
m_ramModuleInspectorToggle,
content: " [ RAM ]",
style: GraphyEditorStyle.FoldoutStyle,
toggleOnLabelClick: true
);
GUILayout.Space( 5 );
if( m_ramModuleInspectorToggle )
{
EditorGUILayout.PropertyField
(
m_ramModuleState,
new GUIContent
(
text: "Module state",
tooltip: "FULL -> Text + Graph \nTEXT -> Just text \nOFF -> Turned off"
)
);
GUILayout.Space( 5 );
EditorGUILayout.LabelField( "Graph colors:" );
EditorGUI.indentLevel++;
m_allocatedRamColor.colorValue = EditorGUILayout.ColorField
(
label: "- Allocated",
value: m_allocatedRamColor.colorValue
);
m_reservedRamColor.colorValue = EditorGUILayout.ColorField
(
label: "- Reserved",
value: m_reservedRamColor.colorValue
);
m_monoRamColor.colorValue = EditorGUILayout.ColorField
(
label: "- Mono",
value: m_monoRamColor.colorValue
);
EditorGUI.indentLevel--;
if( m_ramModuleState.intValue == 0 )
{
m_ramGraphResolution.intValue = EditorGUILayout.IntSlider(
new GUIContent
(
text: "Graph resolution",
tooltip: "Defines the amount of points are in the graph"
),
m_ramGraphResolution.intValue,
leftValue: 20,
rightValue: m_graphyMode.intValue == 0 ? 300 : 128
);
}
m_ramTextUpdateRate.intValue = EditorGUILayout.IntSlider
(
new GUIContent
(
text: "Text update rate",
tooltip: "Defines the amount times the text is updated in 1 second."
),
m_ramTextUpdateRate.intValue,
leftValue: 1,
rightValue: 60
);
}
#endregion
GUILayout.Space( 20 );
#region Section -> Audio
m_audioModuleInspectorToggle = EditorGUILayout.Foldout
(
m_audioModuleInspectorToggle,
content: " [ AUDIO ]",
style: GraphyEditorStyle.FoldoutStyle,
toggleOnLabelClick: true
);
GUILayout.Space( 5 );
if( m_audioModuleInspectorToggle )
{
EditorGUILayout.PropertyField
(
m_audioModuleState,
new GUIContent
(
text: "Module state",
tooltip: "FULL -> Text + Graph \nTEXT -> Just text \nOFF -> Turned off"
)
);
GUILayout.Space( 5 );
EditorGUILayout.PropertyField
(
m_findAudioListenerInCameraIfNull,
new GUIContent
(
text: "Find audio listener",
tooltip:
"Tries to find the AudioListener in the Main camera in the scene. (if AudioListener is null)"
)
);
EditorGUILayout.PropertyField
(
m_audioListener,
new GUIContent
(
text: "Audio Listener",
tooltip:
"Graphy will take the data from this Listener. If none are specified, it will try to get it from the Main Camera in the scene."
)
);
if( m_audioModuleState.intValue == 0 )
{
m_audioGraphColor.colorValue = EditorGUILayout.ColorField
(
label: "Graph color",
value: m_audioGraphColor.colorValue
);
m_audioGraphResolution.intValue = EditorGUILayout.IntSlider
(
new GUIContent
(
text: "Graph resolution",
tooltip: "Defines the amount of points that are in the graph."
),
m_audioGraphResolution.intValue,
leftValue: 20,
rightValue: m_graphyMode.intValue == 0 ? 300 : 128
);
// Forces the value to be a multiple of 3, this way the audio graph is painted correctly
if( m_audioGraphResolution.intValue % 3 != 0 && m_audioGraphResolution.intValue < 300 )
{
m_audioGraphResolution.intValue += 3 - m_audioGraphResolution.intValue % 3;
}
//TODO: Figure out why a static version of the ForceMultipleOf3 isnt used.
}
EditorGUILayout.PropertyField
(
m_FFTWindow,
new GUIContent
(
text: "FFT Window",
tooltip:
"Used to reduce leakage between frequency bins/bands. Note, the more complex window type, the better the quality, but reduced speed. \n\nSimplest is rectangular. Most complex is BlackmanHarris"
)
);
m_spectrumSize.intValue = EditorGUILayout.IntSlider
(
new GUIContent
(
text: "Spectrum size",
tooltip:
"Has to be a power of 2 between 128-8192. The higher sample rate, the less precision but also more impact on performance. Careful with mobile devices"
),
m_spectrumSize.intValue,
leftValue: 128,
rightValue: 8192
);
int closestSpectrumIndex = 0;
int minDistanceToSpectrumValue = 100000;
for( int i = 0; i < m_spectrumSizeValues.Length; i++ )
{
int newDistance = Mathf.Abs
(
value: m_spectrumSize.intValue - m_spectrumSizeValues[ i ]
);
if( newDistance < minDistanceToSpectrumValue )
{
minDistanceToSpectrumValue = newDistance;
closestSpectrumIndex = i;
}
}
m_spectrumSize.intValue = m_spectrumSizeValues[ closestSpectrumIndex ];
m_audioTextUpdateRate.intValue = EditorGUILayout.IntSlider
(
new GUIContent
(
text: "Text update rate",
tooltip: "Defines the amount times the text is updated in 1 second"
),
m_audioTextUpdateRate.intValue,
leftValue: 1,
rightValue: 60
);
}
#endregion
GUILayout.Space( 20 );
#region Section -> Advanced Settings
m_advancedModuleInspectorToggle = EditorGUILayout.Foldout
(
m_advancedModuleInspectorToggle,
content: " [ ADVANCED DATA ]",
style: GraphyEditorStyle.FoldoutStyle,
toggleOnLabelClick: true
);
GUILayout.Space( 5 );
if( m_advancedModuleInspectorToggle )
{
EditorGUILayout.PropertyField( m_advancedModulePosition );
EditorGUILayout.PropertyField
(
m_advancedModuleOffset,
new GUIContent
(
text: "Advanced modules offset",
tooltip: "Defines how far from the corner the module will be located."
)
);
EditorGUILayout.PropertyField
(
m_advancedModuleState,
new GUIContent
(
text: "Module state",
tooltip: "FULL -> Text \nOFF -> Turned off"
)
);
}
#endregion;
EditorGUIUtility.labelWidth = defaultLabelWidth;
EditorGUIUtility.fieldWidth = defaultFieldWidth;
serializedObject.ApplyModifiedProperties();
}
#endregion
#region Methods -> Private
#endregion
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: f01a5c28e5127404da343db2a7409c10
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 105778
packageName: '[Graphy] - Ultimate FPS Counter - Stats Monitor & Debugger'
packageVersion: 3.0.5
assetPath: Assets/Graphy - Ultimate Stats Monitor/Editor/GraphyManagerEditor.cs
uploadId: 626547
@@ -0,0 +1,66 @@
/* ---------------------------------------
* Author: Martin Pane (martintayx@gmail.com) (@tayx94)
* Contributors: https://github.com/Tayx94/graphy/graphs/contributors
* Project: Graphy - Ultimate Stats Monitor
* Date: 20-Dec-17
* Studio: Tayx
*
* Git repo: https://github.com/Tayx94/graphy
*
* This project is released under the MIT license.
* Attribution is not required, but it is always welcomed!
* -------------------------------------*/
using UnityEditor;
using UnityEngine;
namespace Tayx.Graphy
{
public class GraphyMenuItem
{
[MenuItem( "Tools/Graphy/Create Prefab Variant" )]
static void CreatePrefabVariant()
{
// Directory checking
if( !AssetDatabase.IsValidFolder( "Assets/Graphy - Ultimate Stats Monitor" ) )
{
AssetDatabase.CreateFolder( "Assets", "Graphy - Ultimate Stats Monitor" );
}
if( !AssetDatabase.IsValidFolder( "Assets/Graphy - Ultimate Stats Monitor/Prefab Variants" ) )
{
AssetDatabase.CreateFolder( "Assets/Graphy - Ultimate Stats Monitor", "Prefab Variants" );
}
string graphyPrefabGuid = AssetDatabase.FindAssets( "[Graphy]" )[ 0 ];
Object originalPrefab =
(GameObject) AssetDatabase.LoadAssetAtPath( AssetDatabase.GUIDToAssetPath( graphyPrefabGuid ),
typeof( GameObject ) );
GameObject objectSource = PrefabUtility.InstantiatePrefab( originalPrefab ) as GameObject;
int prefabVariantCount =
AssetDatabase.FindAssets( "Graphy_Variant",
new[] { "Assets/Graphy - Ultimate Stats Monitor/Prefab Variants" } ).Length;
GameObject prefabVariant = PrefabUtility.SaveAsPrefabAsset( objectSource,
$"Assets/Graphy - Ultimate Stats Monitor/Prefab Variants/Graphy_Variant_{prefabVariantCount}.prefab" );
Object.DestroyImmediate( objectSource );
foreach( SceneView scene in SceneView.sceneViews )
{
scene.ShowNotification(
new GUIContent( "Prefab Variant Created at \"Assets/Graphy - Ultimate Stats Monitor/Prefab\"!" ) );
}
}
[MenuItem( "Tools/Graphy/Import Graphy Customization Scene" )]
static void ImportGraphyCustomizationScene()
{
string customizationSceneGuid = AssetDatabase.FindAssets( "Graphy_CustomizationScene" )[ 0 ];
AssetDatabase.ImportPackage( AssetDatabase.GUIDToAssetPath( customizationSceneGuid ), true );
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 68962e071a0ce0549a853f10c6af3f54
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 105778
packageName: '[Graphy] - Ultimate FPS Counter - Stats Monitor & Debugger'
packageVersion: 3.0.5
assetPath: Assets/Graphy - Ultimate Stats Monitor/Editor/GraphyMenuItem.cs
uploadId: 626547
@@ -0,0 +1,23 @@
{
"name": "Tayx.Graphy.Editor",
"references": [
"GUID:18e5109d897e1b244ab2dfeaf5482c7b"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [
{
"name": "com.unity.inputsystem",
"expression": "",
"define": "GRAPHY_NEW_INPUT"
}
],
"noEngineReferences": false
}
@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 9c59a049deefdf64bbbaa730a340bb3f
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 105778
packageName: '[Graphy] - Ultimate FPS Counter - Stats Monitor & Debugger'
packageVersion: 3.0.5
assetPath: Assets/Graphy - Ultimate Stats Monitor/Editor/Tayx.Graphy.Editor.asmdef
uploadId: 626547