添加debug工具
This commit is contained in:
.gitignore
Assets
CSAssets
Editor
Plugins
IngameDebugConsole.meta
IngameDebugConsole
Android.meta
RuntimeInspector.metaAndroid
DebugLogLogcatListener.csDebugLogLogcatListener.cs.metaIngameDebugConsole.aarIngameDebugConsole.aar.meta
Editor.metaEditor
DebugLogManagerEditor.csDebugLogManagerEditor.cs.metaIngameDebugConsole.Editor.asmdefIngameDebugConsole.Editor.asmdef.meta
IngameDebugConsole.Runtime.asmdefIngameDebugConsole.Runtime.asmdef.metaIngameDebugConsole.prefabIngameDebugConsole.prefab.metaPrefabs.metaPrefabs
README.txtREADME.txt.metaScripts.metaScripts
CircularBuffer.csCircularBuffer.cs.metaCommands.meta
Sprites.metaCommands
PlayerPrefsCommands.csPlayerPrefsCommands.cs.metaSceneCommands.csSceneCommands.cs.metaTimeCommands.csTimeCommands.cs.meta
ConsoleMethodAttribute.csConsoleMethodAttribute.cs.metaDebugLogConsole.csDebugLogConsole.cs.metaDebugLogEntry.csDebugLogEntry.cs.metaDebugLogIndexList.csDebugLogIndexList.cs.metaDebugLogItem.csDebugLogItem.cs.metaDebugLogItemCopyWebGL.csDebugLogItemCopyWebGL.cs.metaDebugLogManager.csDebugLogManager.cs.metaDebugLogPopup.csDebugLogPopup.cs.metaDebugLogRecycledListView.csDebugLogRecycledListView.cs.metaDebugLogResizeListener.csDebugLogResizeListener.cs.metaDebugsOnScrollListener.csDebugsOnScrollListener.cs.metaEventSystemHandler.csEventSystemHandler.cs.metaSprites
IconClear.psdIconClear.psd.metaIconCollapse.psdIconCollapse.psd.metaIconError.psdIconError.psd.metaIconHide.psdIconHide.psd.metaIconInfo.psdIconInfo.psd.metaIconResizeAllDirections.psdIconResizeAllDirections.psd.metaIconResizeVertialOnly.psdIconResizeVertialOnly.psd.metaIconSnapToBottom.psdIconSnapToBottom.psd.metaIconSnapToBottomBg.psdIconSnapToBottomBg.psd.metaIconWarning.psdIconWarning.psd.metaIngameDebugConsoleSpriteAtlas.spriteatlasIngameDebugConsoleSpriteAtlas.spriteatlas.metaSearchIcon.psdSearchIcon.psd.metaSlicedBackground.psdSlicedBackground.psd.metaSlicedBackground2.psdSlicedBackground2.psd.metaSlicedBackground3.psdSlicedBackground3.psd.metaUnused.meta
WebGL.metaUnused
WebGL
iOS.metaiOS
RuntimeInspector
ExternalResources.meta
ExternalResources
ColorWheel.meta
InternalSettings.assetInternalSettings.asset.metaPrefabs.metaColorWheel
Prefabs
RuntimeHierarchy.meta
README.txtREADME.txt.metaResources.metaRuntimeHierarchy
RuntimeInspector.metaRuntimeInspector
Fields.meta
Fields
ArrayField.prefabArrayField.prefab.metaBoolField.prefabBoolField.prefab.metaBoundsField.prefabBoundsField.prefab.metaColorField.prefabColorField.prefab.metaEnumField.prefabEnumField.prefab.metaExposedMethodField.prefabExposedMethodField.prefab.metaGameObjectField.prefabGameObjectField.prefab.metaNumberField.prefabNumberField.prefab.metaNumberRangeField.prefabNumberRangeField.prefab.metaObjectField.prefabObjectField.prefab.metaObjectReferenceField.prefabObjectReferenceField.prefab.metaRectField.prefabRectField.prefab.metaStringField.prefabStringField.prefab.metaTextureReferenceField.prefabTextureReferenceField.prefab.metaTransformField.prefabTransformField.prefab.metaVector2Field.prefabVector2Field.prefab.metaVector3Field.prefabVector3Field.prefab.metaVector4Field.prefabVector4Field.prefab.meta
Helpers.metaHelpers
Resources
RuntimeInspector.meta
RuntimeHierarchy.prefabRuntimeHierarchy.prefab.metaRuntimeInspector.Runtime.asmdefRuntimeInspector.Runtime.asmdef.metaRuntimeInspector.prefabRuntimeInspector.prefab.metaScripts.metaRuntimeInspector
Scripts
RuntimeHierarchy.csRuntimeHierarchy.cs.metaRuntimeHierarchy.meta
Shaders.metaRuntimeHierarchy
Helpers.meta
RuntimeInspector.csRuntimeInspector.cs.metaRuntimeInspector.metaHelpers
HierarchyDragDropListener.csHierarchyDragDropListener.cs.metaPseudoSceneSourceTransform.csPseudoSceneSourceTransform.cs.meta
HierarchyData.csHierarchyData.cs.metaHierarchyDataRoot.csHierarchyDataRoot.cs.metaHierarchyDataRootPseudoScene.csHierarchyDataRootPseudoScene.cs.metaHierarchyDataRootScene.csHierarchyDataRootScene.cs.metaHierarchyDataRootSearch.csHierarchyDataRootSearch.cs.metaHierarchyDataTransform.csHierarchyDataTransform.cs.metaHierarchyField.csHierarchyField.cs.metaRuntimeInspector
Attributes.meta
Attributes
RuntimeInspectorButtonAttribute.csRuntimeInspectorButtonAttribute.cs.metaRuntimeInspectorCustomEditorAttribute.csRuntimeInspectorCustomEditorAttribute.cs.meta
Fields.metaFields
ArrayField.csArrayField.cs.metaBoolField.csBoolField.cs.metaBoundsField.csBoundsField.cs.metaColorField.csColorField.cs.metaEnumField.csEnumField.cs.metaExposedMethodField.csExposedMethodField.cs.metaGameObjectField.csGameObjectField.cs.metaInspectorField.csInspectorField.cs.metaNumberField.csNumberField.cs.metaNumberRangeField.csNumberRangeField.cs.metaObjectField.csObjectField.cs.metaObjectReferenceField.csObjectReferenceField.cs.metaRectField.csRectField.cs.metaStringField.csStringField.cs.metaTextureReferenceField.csTextureReferenceField.cs.metaTransformField.csTransformField.cs.metaVector2Field.csVector2Field.cs.metaVector3Field.csVector3Field.cs.metaVector4Field.csVector4Field.cs.meta
Helpers.metaHelpers
BoundInputField.csBoundInputField.cs.metaBoundSlider.csBoundSlider.cs.metaColorPicker.meta
Skin.metaColorPicker
DraggedReferenceItem.csDraggedReferenceItem.cs.metaDraggedReferenceSourceCamera.csDraggedReferenceSourceCamera.cs.metaDraggedReferenceSourceUI.csDraggedReferenceSourceUI.cs.metaExposedMethod.csExposedMethod.cs.metaExposedVariablesEnumerator.csExposedVariablesEnumerator.cs.metaNonDrawingGraphic.csNonDrawingGraphic.cs.metaNonDrawingMaskableGraphic.csNonDrawingMaskableGraphic.cs.metaNumberHandlers.csNumberHandlers.cs.metaObjectReferencePicker.metaObjectReferencePicker
ObjectReferencePicker.csObjectReferencePicker.cs.metaObjectReferencePickerItem.csObjectReferencePickerItem.cs.meta
PointerEventListener.csPointerEventListener.cs.metaPopupBase.csPopupBase.cs.metaRecycledListView.metaRecycledListView
IListViewAdapter.csIListViewAdapter.cs.metaRecycledListItem.csRecycledListItem.cs.metaRecycledListView.csRecycledListView.cs.meta
RuntimeInspectorSettings.csRuntimeInspectorSettings.cs.metaRuntimeInspectorUtils.csRuntimeInspectorUtils.cs.metaTooltip.csTooltip.cs.metaTooltipArea.csTooltipArea.cs.metaTooltipListener.csTooltipListener.cs.metaVariableSet.csVariableSet.cs.metaWindowDragHandler.csWindowDragHandler.cs.metaSkin
Shaders
ColorPickerAlphaMaterial.matColorPickerAlphaMaterial.mat.metaColorPickerAlphaShader.shaderColorPickerAlphaShader.shader.meta
Skins.metaSkins
Sprites.metaSprites
ButtonBg.psdButtonBg.psd.metaCheckmark.psdCheckmark.psd.metaColorFieldBg.psdColorFieldBg.psd.metaColorFieldTransparentBg.psdColorFieldTransparentBg.psd.metaDownArrow.psdDownArrow.psd.metaDragAndDropBg.psdDragAndDropBg.psd.metaExpandArrow.psdExpandArrow.psd.metaInputFieldBg.psdInputFieldBg.psd.metaInspectReferenceArrow.psdInspectReferenceArrow.psd.metaSearchIcon.psdSearchIcon.psd.metaSliderBg.psdSliderBg.psd.metaSliderThumb.psdSliderThumb.psd.metaWhite.pngWhite.png.meta
ThirdPartyNotices.txtThirdPartyNotices.txt.metaProject
GameRes
DummyMaterial
1005278527.mat.meta1027421493.mat.meta1029769654.mat.meta103973718.mat.meta1098675164.mat.meta1105669650.mat.meta1129907047.mat.meta1183509003.mat.meta1184956560.mat.meta1192151891.mat.meta1209964436.mat.meta1248213280.mat.meta1274362148.mat.meta1288468513.mat.meta1296894701.mat.meta130217613.mat.meta1381407051.mat.meta1423995325.mat.meta1456853423.mat.meta1459214389.mat.meta1500675633.mat.meta1503927734.mat.meta1511286178.mat.meta1519698979.mat.meta1521666193.mat.meta1556632090.mat.meta1568252347.mat.meta1580009455.mat.meta1659897039.mat.meta1670160698.mat.meta1692493091.mat.meta1704837334.mat.meta1717444261.mat.meta1739460917.mat.meta1767002623.mat.meta1772791499.mat.meta1841997986.mat.meta1846757793.mat.meta1847907842.mat.meta1849660902.mat.meta1892877949.mat.meta1899344832.mat.meta1942141328.mat.meta1998554402.mat.meta2030778644.mat.meta2038172114.mat.meta2056516474.mat.meta2086589292.mat.meta2126790404.mat.meta2150757578.mat.meta2164612953.mat.meta2173349684.mat.meta2179085644.mat.meta2224894161.mat.meta2231992728.mat.meta2236099016.mat.meta2270965971.mat.meta2308993049.mat.meta2329426606.mat.meta2330919951.mat.meta2341708282.mat.meta2365482467.mat.meta2374156310.mat.meta2412091565.mat.meta2422519158.mat.meta242956612.mat.meta2663927093.mat.meta2671497964.mat.meta2712042832.mat.meta2717376397.mat.meta2748594355.mat.meta2768759778.mat.meta2773309832.mat.meta279519651.mat.meta2798732219.mat.meta2818854931.mat.meta282571981.mat.meta2827258663.mat.meta2872434622.mat.meta291057203.mat.meta2951302974.mat.meta2955110083.mat.meta2984523060.mat.meta3010969751.mat.meta3021603982.mat.meta3069336989.mat.meta3075384026.mat.meta312143936.mat.meta3212549395.mat.meta3226047052.mat.meta3262379475.mat.meta3273471000.mat.meta3295735809.mat.meta3336766882.mat.meta333862325.mat.meta3341047381.mat.meta3353932625.mat.meta3363614085.mat.meta3437553339.mat.meta344691116.mat.meta3523271540.mat.meta3570599973.mat.meta3572509830.mat.meta3610657690.mat.meta3639508904.mat.meta3644564855.mat.meta368522329.mat.meta3705907492.mat.meta3749952433.mat.meta3755923179.mat.meta3896304250.mat.meta3942533584.mat.meta3962488102.mat.meta4014519825.mat.meta40224011.mat.meta4032495685.mat.meta4059208281.mat.meta4065270110.mat.meta4118968099.mat.meta4127354831.mat.meta4136476578.mat.meta4147561564.mat.meta4203081856.mat.meta420772151.mat.meta4227421557.mat.meta423142768.mat.meta4237594988.mat.meta4259853465.mat.meta4272373903.mat.meta445651814.mat.meta508718230.mat.meta508911977.mat.meta514692701.mat.meta528925730.mat.meta539264358.mat.meta591534960.mat.meta632347983.mat.meta675833814.mat.meta690632569.mat.meta712937773.mat.meta728259273.mat.meta756241716.mat.meta766900231.mat.meta779439783.mat.meta80054534.mat.meta811395433.mat.meta831380125.mat.meta855384395.mat.meta880088689.mat.meta895650739.mat.meta914047818.mat.meta920657540.mat.meta948720418.mat.meta977943163.mat.meta
Model
Materials
Script
Project3D
BundleData
Tables3D
Res_newMS
ChangJing
kuafu
Sence
Moxing
Boss
BOSS_tiemuzhen
zhanhun
Moster
MS_baiwuchang
MS_haidao
MS_heiyiren
MS_jianshi
MS_qixuezhu
NPC
Player
jianxiu
shizhuang
liushan
shizhuang
jiuzhoumiaoyi
liehuoxianfeng
molong
xiaochou
xiarilianren
xueguohuanjing
yezhanshizhuang
yundongshizhuang
Wing
Wing_huihuang
xiaowujian
Sence_beifen
zhucheng
Particles
Meshes
TeXiao
Fbxs
Effect
zhaohuanshi_FBX
T4M
Editor
MeshBillb
UnusedAssets
Res_newMS
ChangJing
Particles
Meshes
TeXiao
ExcelTexts
ProjectSettings
119
Assets/Plugins/IngameDebugConsole/Scripts/CircularBuffer.cs
Normal file
119
Assets/Plugins/IngameDebugConsole/Scripts/CircularBuffer.cs
Normal file
@ -0,0 +1,119 @@
|
||||
// #define RESET_REMOVED_ELEMENTS
|
||||
|
||||
namespace IngameDebugConsole
|
||||
{
|
||||
public class CircularBuffer<T>
|
||||
{
|
||||
private T[] arr;
|
||||
private int startIndex;
|
||||
|
||||
public int Count { get; private set; }
|
||||
public T this[int index] { get { return arr[( startIndex + index ) % arr.Length]; } }
|
||||
|
||||
public CircularBuffer( int capacity )
|
||||
{
|
||||
arr = new T[capacity];
|
||||
}
|
||||
|
||||
// Old elements are overwritten when capacity is reached
|
||||
public void Add( T value )
|
||||
{
|
||||
if( Count < arr.Length )
|
||||
arr[Count++] = value;
|
||||
else
|
||||
{
|
||||
arr[startIndex] = value;
|
||||
if( ++startIndex >= arr.Length )
|
||||
startIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DynamicCircularBuffer<T>
|
||||
{
|
||||
private T[] arr;
|
||||
private int startIndex;
|
||||
|
||||
public int Count { get; private set; }
|
||||
public int Capacity { get { return arr.Length; } }
|
||||
|
||||
public T this[int index]
|
||||
{
|
||||
get { return arr[( startIndex + index ) % arr.Length]; }
|
||||
set { arr[( startIndex + index ) % arr.Length] = value; }
|
||||
}
|
||||
|
||||
public DynamicCircularBuffer( int initialCapacity = 2 )
|
||||
{
|
||||
arr = new T[initialCapacity];
|
||||
}
|
||||
|
||||
public void Add( T value )
|
||||
{
|
||||
if( Count >= arr.Length )
|
||||
{
|
||||
int prevSize = arr.Length;
|
||||
int newSize = prevSize > 0 ? prevSize * 2 : 2; // Size must be doubled (at least), or the shift operation below must consider IndexOutOfRange situations
|
||||
|
||||
System.Array.Resize( ref arr, newSize );
|
||||
|
||||
if( startIndex > 0 )
|
||||
{
|
||||
if( startIndex <= ( prevSize - 1 ) / 2 )
|
||||
{
|
||||
// Move elements [0,startIndex) to the end
|
||||
for( int i = 0; i < startIndex; i++ )
|
||||
{
|
||||
arr[i + prevSize] = arr[i];
|
||||
#if RESET_REMOVED_ELEMENTS
|
||||
arr[i] = default( T );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Move elements [startIndex,prevSize) to the end
|
||||
int delta = newSize - prevSize;
|
||||
for( int i = prevSize - 1; i >= startIndex; i-- )
|
||||
{
|
||||
arr[i + delta] = arr[i];
|
||||
#if RESET_REMOVED_ELEMENTS
|
||||
arr[i] = default( T );
|
||||
#endif
|
||||
}
|
||||
|
||||
startIndex += delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this[Count++] = value;
|
||||
}
|
||||
|
||||
public T RemoveFirst()
|
||||
{
|
||||
T element = arr[startIndex];
|
||||
#if RESET_REMOVED_ELEMENTS
|
||||
arr[startIndex] = default( T );
|
||||
#endif
|
||||
|
||||
if( ++startIndex >= arr.Length )
|
||||
startIndex = 0;
|
||||
|
||||
Count--;
|
||||
return element;
|
||||
}
|
||||
|
||||
public T RemoveLast()
|
||||
{
|
||||
int index = ( startIndex + Count - 1 ) % arr.Length;
|
||||
T element = arr[index];
|
||||
#if RESET_REMOVED_ELEMENTS
|
||||
arr[index] = default( T );
|
||||
#endif
|
||||
|
||||
Count--;
|
||||
return element;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6136cb3c00eac0149901b8e7f2fecef8
|
||||
timeCreated: 1550943949
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Assets/Plugins/IngameDebugConsole/Scripts/Commands.meta
Normal file
8
Assets/Plugins/IngameDebugConsole/Scripts/Commands.meta
Normal file
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb9b6e1ab379cec46bfae8f8abcc1f45
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,58 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace IngameDebugConsole.Commands
|
||||
{
|
||||
public class PlayerPrefsCommands
|
||||
{
|
||||
[ConsoleMethod( "prefs.int", "Returns the value of an Integer PlayerPrefs field" ), UnityEngine.Scripting.Preserve]
|
||||
public static string PlayerPrefsGetInt( string key )
|
||||
{
|
||||
if( !PlayerPrefs.HasKey( key ) ) return "Key Not Found";
|
||||
return PlayerPrefs.GetInt( key ).ToString();
|
||||
}
|
||||
|
||||
[ConsoleMethod( "prefs.int", "Sets the value of an Integer PlayerPrefs field" ), UnityEngine.Scripting.Preserve]
|
||||
public static void PlayerPrefsSetInt( string key, int value )
|
||||
{
|
||||
PlayerPrefs.SetInt( key, value );
|
||||
}
|
||||
|
||||
[ConsoleMethod( "prefs.float", "Returns the value of a Float PlayerPrefs field" ), UnityEngine.Scripting.Preserve]
|
||||
public static string PlayerPrefsGetFloat( string key )
|
||||
{
|
||||
if( !PlayerPrefs.HasKey( key ) ) return "Key Not Found";
|
||||
return PlayerPrefs.GetFloat( key ).ToString();
|
||||
}
|
||||
|
||||
[ConsoleMethod( "prefs.float", "Sets the value of a Float PlayerPrefs field" ), UnityEngine.Scripting.Preserve]
|
||||
public static void PlayerPrefsSetFloat( string key, float value )
|
||||
{
|
||||
PlayerPrefs.SetFloat( key, value );
|
||||
}
|
||||
|
||||
[ConsoleMethod( "prefs.string", "Returns the value of a String PlayerPrefs field" ), UnityEngine.Scripting.Preserve]
|
||||
public static string PlayerPrefsGetString( string key )
|
||||
{
|
||||
if( !PlayerPrefs.HasKey( key ) ) return "Key Not Found";
|
||||
return PlayerPrefs.GetString( key );
|
||||
}
|
||||
|
||||
[ConsoleMethod( "prefs.string", "Sets the value of a String PlayerPrefs field" ), UnityEngine.Scripting.Preserve]
|
||||
public static void PlayerPrefsSetString( string key, string value )
|
||||
{
|
||||
PlayerPrefs.SetString( key, value );
|
||||
}
|
||||
|
||||
[ConsoleMethod( "prefs.delete", "Deletes a PlayerPrefs field" ), UnityEngine.Scripting.Preserve]
|
||||
public static void PlayerPrefsDelete( string key )
|
||||
{
|
||||
PlayerPrefs.DeleteKey( key );
|
||||
}
|
||||
|
||||
[ConsoleMethod( "prefs.clear", "Deletes all PlayerPrefs fields" ), UnityEngine.Scripting.Preserve]
|
||||
public static void PlayerPrefsClear()
|
||||
{
|
||||
PlayerPrefs.DeleteAll();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33fb3ee25c8764f4c905fa3ac7c4eb89
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,58 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace IngameDebugConsole.Commands
|
||||
{
|
||||
public class SceneCommands
|
||||
{
|
||||
[ConsoleMethod( "scene.load", "Loads a scene" ), UnityEngine.Scripting.Preserve]
|
||||
public static void LoadScene( string sceneName )
|
||||
{
|
||||
LoadSceneInternal( sceneName, false, LoadSceneMode.Single );
|
||||
}
|
||||
|
||||
[ConsoleMethod( "scene.load", "Loads a scene" ), UnityEngine.Scripting.Preserve]
|
||||
public static void LoadScene( string sceneName, LoadSceneMode mode )
|
||||
{
|
||||
LoadSceneInternal( sceneName, false, mode );
|
||||
}
|
||||
|
||||
[ConsoleMethod( "scene.loadasync", "Loads a scene asynchronously" ), UnityEngine.Scripting.Preserve]
|
||||
public static void LoadSceneAsync( string sceneName )
|
||||
{
|
||||
LoadSceneInternal( sceneName, true, LoadSceneMode.Single );
|
||||
}
|
||||
|
||||
[ConsoleMethod( "scene.loadasync", "Loads a scene asynchronously" ), UnityEngine.Scripting.Preserve]
|
||||
public static void LoadSceneAsync( string sceneName, LoadSceneMode mode )
|
||||
{
|
||||
LoadSceneInternal( sceneName, true, mode );
|
||||
}
|
||||
|
||||
private static void LoadSceneInternal( string sceneName, bool isAsync, LoadSceneMode mode )
|
||||
{
|
||||
if( SceneManager.GetSceneByName( sceneName ).IsValid() )
|
||||
{
|
||||
Debug.Log( "Scene " + sceneName + " is already loaded" );
|
||||
return;
|
||||
}
|
||||
|
||||
if( isAsync )
|
||||
SceneManager.LoadSceneAsync( sceneName, mode );
|
||||
else
|
||||
SceneManager.LoadScene( sceneName, mode );
|
||||
}
|
||||
|
||||
[ConsoleMethod( "scene.unload", "Unloads a scene" ), UnityEngine.Scripting.Preserve]
|
||||
public static void UnloadScene( string sceneName )
|
||||
{
|
||||
SceneManager.UnloadSceneAsync( sceneName );
|
||||
}
|
||||
|
||||
[ConsoleMethod( "scene.restart", "Restarts the active scene" ), UnityEngine.Scripting.Preserve]
|
||||
public static void RestartScene()
|
||||
{
|
||||
SceneManager.LoadScene( SceneManager.GetActiveScene().name, LoadSceneMode.Single );
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 45984eacd62d9a3489fd62689265a23c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,19 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace IngameDebugConsole.Commands
|
||||
{
|
||||
public class TimeCommands
|
||||
{
|
||||
[ConsoleMethod( "time.scale", "Sets the Time.timeScale value" ), UnityEngine.Scripting.Preserve]
|
||||
public static void SetTimeScale( float value )
|
||||
{
|
||||
Time.timeScale = Mathf.Max( value, 0f );
|
||||
}
|
||||
|
||||
[ConsoleMethod( "time.scale", "Returns the current Time.timeScale value" ), UnityEngine.Scripting.Preserve]
|
||||
public static float GetTimeScale()
|
||||
{
|
||||
return Time.timeScale;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bb12a1f557fffa541909fcfe92d9c1bf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
|
||||
namespace IngameDebugConsole
|
||||
{
|
||||
[AttributeUsage( AttributeTargets.Method, Inherited = false, AllowMultiple = true )]
|
||||
public class ConsoleMethodAttribute : Attribute
|
||||
{
|
||||
private string m_command;
|
||||
private string m_description;
|
||||
private string[] m_parameterNames;
|
||||
|
||||
public string Command { get { return m_command; } }
|
||||
public string Description { get { return m_description; } }
|
||||
public string[] ParameterNames { get { return m_parameterNames; } }
|
||||
|
||||
public ConsoleMethodAttribute( string command, string description, params string[] parameterNames )
|
||||
{
|
||||
m_command = command;
|
||||
m_description = description;
|
||||
m_parameterNames = parameterNames;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 324bb39c0bff0f74fa42f83e91f07e3a
|
||||
timeCreated: 1520710946
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
1505
Assets/Plugins/IngameDebugConsole/Scripts/DebugLogConsole.cs
Normal file
1505
Assets/Plugins/IngameDebugConsole/Scripts/DebugLogConsole.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d15693a03d0d33b4892c6365a2a97e19
|
||||
timeCreated: 1472036503
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
170
Assets/Plugins/IngameDebugConsole/Scripts/DebugLogEntry.cs
Normal file
170
Assets/Plugins/IngameDebugConsole/Scripts/DebugLogEntry.cs
Normal file
@ -0,0 +1,170 @@
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
// Container for a simple debug entry
|
||||
namespace IngameDebugConsole
|
||||
{
|
||||
public class DebugLogEntry : System.IEquatable<DebugLogEntry>
|
||||
{
|
||||
private const int HASH_NOT_CALCULATED = -623218;
|
||||
|
||||
public string logString;
|
||||
public string stackTrace;
|
||||
|
||||
private string completeLog;
|
||||
|
||||
// Sprite to show with this entry
|
||||
public Sprite logTypeSpriteRepresentation;
|
||||
|
||||
// Collapsed count
|
||||
public int count;
|
||||
|
||||
private int hashValue;
|
||||
|
||||
public void Initialize( string logString, string stackTrace )
|
||||
{
|
||||
this.logString = logString;
|
||||
this.stackTrace = stackTrace;
|
||||
|
||||
completeLog = null;
|
||||
count = 1;
|
||||
hashValue = HASH_NOT_CALCULATED;
|
||||
}
|
||||
|
||||
// Check if two entries have the same origin
|
||||
public bool Equals( DebugLogEntry other )
|
||||
{
|
||||
return this.logString == other.logString && this.stackTrace == other.stackTrace;
|
||||
}
|
||||
|
||||
// Checks if logString or stackTrace contains the search term
|
||||
public bool MatchesSearchTerm( string searchTerm )
|
||||
{
|
||||
return ( logString != null && DebugLogConsole.caseInsensitiveComparer.IndexOf( logString, searchTerm, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace ) >= 0 ) ||
|
||||
( stackTrace != null && DebugLogConsole.caseInsensitiveComparer.IndexOf( stackTrace, searchTerm, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace ) >= 0 );
|
||||
}
|
||||
|
||||
// Return a string containing complete information about this debug entry
|
||||
public override string ToString()
|
||||
{
|
||||
if( completeLog == null )
|
||||
completeLog = string.Concat( logString, "\n", stackTrace );
|
||||
|
||||
return completeLog;
|
||||
}
|
||||
|
||||
// Credit: https://stackoverflow.com/a/19250516/2373034
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if( hashValue == HASH_NOT_CALCULATED )
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
hashValue = 17;
|
||||
hashValue = hashValue * 23 + ( logString == null ? 0 : logString.GetHashCode() );
|
||||
hashValue = hashValue * 23 + ( stackTrace == null ? 0 : stackTrace.GetHashCode() );
|
||||
}
|
||||
}
|
||||
|
||||
return hashValue;
|
||||
}
|
||||
}
|
||||
|
||||
public struct QueuedDebugLogEntry
|
||||
{
|
||||
public readonly string logString;
|
||||
public readonly string stackTrace;
|
||||
public readonly LogType logType;
|
||||
|
||||
public QueuedDebugLogEntry( string logString, string stackTrace, LogType logType )
|
||||
{
|
||||
this.logString = logString;
|
||||
this.stackTrace = stackTrace;
|
||||
this.logType = logType;
|
||||
}
|
||||
|
||||
// Checks if logString or stackTrace contains the search term
|
||||
public bool MatchesSearchTerm( string searchTerm )
|
||||
{
|
||||
return ( logString != null && DebugLogConsole.caseInsensitiveComparer.IndexOf( logString, searchTerm, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace ) >= 0 ) ||
|
||||
( stackTrace != null && DebugLogConsole.caseInsensitiveComparer.IndexOf( stackTrace, searchTerm, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace ) >= 0 );
|
||||
}
|
||||
}
|
||||
|
||||
public struct DebugLogEntryTimestamp
|
||||
{
|
||||
public readonly System.DateTime dateTime;
|
||||
#if !IDG_OMIT_ELAPSED_TIME
|
||||
public readonly float elapsedSeconds;
|
||||
#endif
|
||||
#if !IDG_OMIT_FRAMECOUNT
|
||||
public readonly int frameCount;
|
||||
#endif
|
||||
|
||||
#if !IDG_OMIT_ELAPSED_TIME && !IDG_OMIT_FRAMECOUNT
|
||||
public DebugLogEntryTimestamp( System.DateTime dateTime, float elapsedSeconds, int frameCount )
|
||||
#elif !IDG_OMIT_ELAPSED_TIME
|
||||
public DebugLogEntryTimestamp( System.DateTime dateTime, float elapsedSeconds )
|
||||
#elif !IDG_OMIT_FRAMECOUNT
|
||||
public DebugLogEntryTimestamp( System.DateTime dateTime, int frameCount )
|
||||
#else
|
||||
public DebugLogEntryTimestamp( System.DateTime dateTime )
|
||||
#endif
|
||||
{
|
||||
this.dateTime = dateTime;
|
||||
#if !IDG_OMIT_ELAPSED_TIME
|
||||
this.elapsedSeconds = elapsedSeconds;
|
||||
#endif
|
||||
#if !IDG_OMIT_FRAMECOUNT
|
||||
this.frameCount = frameCount;
|
||||
#endif
|
||||
}
|
||||
|
||||
public void AppendTime( StringBuilder sb )
|
||||
{
|
||||
// Add DateTime in format: [HH:mm:ss]
|
||||
sb.Append( "[" );
|
||||
|
||||
int hour = dateTime.Hour;
|
||||
if( hour >= 10 )
|
||||
sb.Append( hour );
|
||||
else
|
||||
sb.Append( "0" ).Append( hour );
|
||||
|
||||
sb.Append( ":" );
|
||||
|
||||
int minute = dateTime.Minute;
|
||||
if( minute >= 10 )
|
||||
sb.Append( minute );
|
||||
else
|
||||
sb.Append( "0" ).Append( minute );
|
||||
|
||||
sb.Append( ":" );
|
||||
|
||||
int second = dateTime.Second;
|
||||
if( second >= 10 )
|
||||
sb.Append( second );
|
||||
else
|
||||
sb.Append( "0" ).Append( second );
|
||||
|
||||
sb.Append( "]" );
|
||||
}
|
||||
|
||||
public void AppendFullTimestamp( StringBuilder sb )
|
||||
{
|
||||
AppendTime( sb );
|
||||
|
||||
#if !IDG_OMIT_ELAPSED_TIME && !IDG_OMIT_FRAMECOUNT
|
||||
// Append elapsed seconds and frame count in format: [1.0s at #Frame]
|
||||
sb.Append( "[" ).Append( elapsedSeconds.ToString( "F1" ) ).Append( "s at " ).Append( "#" ).Append( frameCount ).Append( "]" );
|
||||
#elif !IDG_OMIT_ELAPSED_TIME
|
||||
// Append elapsed seconds in format: [1.0s]
|
||||
sb.Append( "[" ).Append( elapsedSeconds.ToString( "F1" ) ).Append( "s]" );
|
||||
#elif !IDG_OMIT_FRAMECOUNT
|
||||
// Append frame count in format: [#Frame]
|
||||
sb.Append( "[#" ).Append( frameCount ).Append( "]" );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e7b1a420c564be040bf73b8a377fc2c2
|
||||
timeCreated: 1466375168
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,39 @@
|
||||
namespace IngameDebugConsole
|
||||
{
|
||||
public class DebugLogIndexList<T>
|
||||
{
|
||||
private T[] indices;
|
||||
private int size;
|
||||
|
||||
public int Count { get { return size; } }
|
||||
public T this[int index]
|
||||
{
|
||||
get { return indices[index]; }
|
||||
set { indices[index] = value; }
|
||||
}
|
||||
|
||||
public DebugLogIndexList()
|
||||
{
|
||||
indices = new T[64];
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public void Add( T value )
|
||||
{
|
||||
if( size == indices.Length )
|
||||
System.Array.Resize( ref indices, size * 2 );
|
||||
|
||||
indices[size++] = value;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
size = 0;
|
||||
}
|
||||
|
||||
public int IndexOf( T value )
|
||||
{
|
||||
return System.Array.IndexOf( indices, value );
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37c6c91e5bfac6f499698c03f593bcbb
|
||||
timeCreated: 1520627934
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
283
Assets/Plugins/IngameDebugConsole/Scripts/DebugLogItem.cs
Normal file
283
Assets/Plugins/IngameDebugConsole/Scripts/DebugLogItem.cs
Normal file
@ -0,0 +1,283 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
using System.Text;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using System.Text.RegularExpressions;
|
||||
#endif
|
||||
|
||||
// A UI element to show information about a debug entry
|
||||
namespace IngameDebugConsole
|
||||
{
|
||||
public class DebugLogItem : MonoBehaviour, IPointerClickHandler
|
||||
{
|
||||
#region Platform Specific Elements
|
||||
#if !UNITY_2018_1_OR_NEWER
|
||||
#if !UNITY_EDITOR && UNITY_ANDROID
|
||||
private static AndroidJavaClass m_ajc = null;
|
||||
private static AndroidJavaClass AJC
|
||||
{
|
||||
get
|
||||
{
|
||||
if( m_ajc == null )
|
||||
m_ajc = new AndroidJavaClass( "com.yasirkula.unity.DebugConsole" );
|
||||
|
||||
return m_ajc;
|
||||
}
|
||||
}
|
||||
|
||||
private static AndroidJavaObject m_context = null;
|
||||
private static AndroidJavaObject Context
|
||||
{
|
||||
get
|
||||
{
|
||||
if( m_context == null )
|
||||
{
|
||||
using( AndroidJavaObject unityClass = new AndroidJavaClass( "com.unity3d.player.UnityPlayer" ) )
|
||||
{
|
||||
m_context = unityClass.GetStatic<AndroidJavaObject>( "currentActivity" );
|
||||
}
|
||||
}
|
||||
|
||||
return m_context;
|
||||
}
|
||||
}
|
||||
#elif !UNITY_EDITOR && UNITY_IOS
|
||||
[System.Runtime.InteropServices.DllImport( "__Internal" )]
|
||||
private static extern void _DebugConsole_CopyText( string text );
|
||||
#endif
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
#pragma warning disable 0649
|
||||
// Cached components
|
||||
[SerializeField]
|
||||
private RectTransform transformComponent;
|
||||
public RectTransform Transform { get { return transformComponent; } }
|
||||
|
||||
[SerializeField]
|
||||
private Image imageComponent;
|
||||
public Image Image { get { return imageComponent; } }
|
||||
|
||||
[SerializeField]
|
||||
private CanvasGroup canvasGroupComponent;
|
||||
public CanvasGroup CanvasGroup { get { return canvasGroupComponent; } }
|
||||
|
||||
[SerializeField]
|
||||
private Text logText;
|
||||
[SerializeField]
|
||||
private Image logTypeImage;
|
||||
|
||||
// Objects related to the collapsed count of the debug entry
|
||||
[SerializeField]
|
||||
private GameObject logCountParent;
|
||||
[SerializeField]
|
||||
private Text logCountText;
|
||||
|
||||
[SerializeField]
|
||||
private RectTransform copyLogButton;
|
||||
#pragma warning restore 0649
|
||||
|
||||
// Debug entry to show with this log item
|
||||
private DebugLogEntry logEntry;
|
||||
public DebugLogEntry Entry { get { return logEntry; } }
|
||||
|
||||
private DebugLogEntryTimestamp? logEntryTimestamp;
|
||||
public DebugLogEntryTimestamp? Timestamp { get { return logEntryTimestamp; } }
|
||||
|
||||
// Index of the entry in the list of entries
|
||||
private int entryIndex;
|
||||
public int Index { get { return entryIndex; } }
|
||||
|
||||
private bool isExpanded;
|
||||
public bool Expanded { get { return isExpanded; } }
|
||||
|
||||
private Vector2 logTextOriginalPosition;
|
||||
private Vector2 logTextOriginalSize;
|
||||
private float copyLogButtonHeight;
|
||||
|
||||
private DebugLogRecycledListView listView;
|
||||
|
||||
public void Initialize( DebugLogRecycledListView listView )
|
||||
{
|
||||
this.listView = listView;
|
||||
|
||||
logTextOriginalPosition = logText.rectTransform.anchoredPosition;
|
||||
logTextOriginalSize = logText.rectTransform.sizeDelta;
|
||||
copyLogButtonHeight = copyLogButton.anchoredPosition.y + copyLogButton.sizeDelta.y + 2f; // 2f: space between text and button
|
||||
|
||||
#if !UNITY_EDITOR && UNITY_WEBGL
|
||||
copyLogButton.gameObject.AddComponent<DebugLogItemCopyWebGL>().Initialize( this );
|
||||
#endif
|
||||
}
|
||||
|
||||
public void SetContent( DebugLogEntry logEntry, DebugLogEntryTimestamp? logEntryTimestamp, int entryIndex, bool isExpanded )
|
||||
{
|
||||
this.logEntry = logEntry;
|
||||
this.logEntryTimestamp = logEntryTimestamp;
|
||||
this.entryIndex = entryIndex;
|
||||
this.isExpanded = isExpanded;
|
||||
|
||||
Vector2 size = transformComponent.sizeDelta;
|
||||
if( isExpanded )
|
||||
{
|
||||
logText.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||
size.y = listView.SelectedItemHeight;
|
||||
|
||||
if( !copyLogButton.gameObject.activeSelf )
|
||||
{
|
||||
copyLogButton.gameObject.SetActive( true );
|
||||
|
||||
logText.rectTransform.anchoredPosition = new Vector2( logTextOriginalPosition.x, logTextOriginalPosition.y + copyLogButtonHeight * 0.5f );
|
||||
logText.rectTransform.sizeDelta = logTextOriginalSize - new Vector2( 0f, copyLogButtonHeight );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logText.horizontalOverflow = HorizontalWrapMode.Overflow;
|
||||
size.y = listView.ItemHeight;
|
||||
|
||||
if( copyLogButton.gameObject.activeSelf )
|
||||
{
|
||||
copyLogButton.gameObject.SetActive( false );
|
||||
|
||||
logText.rectTransform.anchoredPosition = logTextOriginalPosition;
|
||||
logText.rectTransform.sizeDelta = logTextOriginalSize;
|
||||
}
|
||||
}
|
||||
|
||||
transformComponent.sizeDelta = size;
|
||||
|
||||
SetText( logEntry, logEntryTimestamp, isExpanded );
|
||||
logTypeImage.sprite = logEntry.logTypeSpriteRepresentation;
|
||||
}
|
||||
|
||||
// Show the collapsed count of the debug entry
|
||||
public void ShowCount()
|
||||
{
|
||||
logCountText.text = logEntry.count.ToString();
|
||||
|
||||
if( !logCountParent.activeSelf )
|
||||
logCountParent.SetActive( true );
|
||||
}
|
||||
|
||||
// Hide the collapsed count of the debug entry
|
||||
public void HideCount()
|
||||
{
|
||||
if( logCountParent.activeSelf )
|
||||
logCountParent.SetActive( false );
|
||||
}
|
||||
|
||||
// Update the debug entry's displayed timestamp
|
||||
public void UpdateTimestamp( DebugLogEntryTimestamp timestamp )
|
||||
{
|
||||
logEntryTimestamp = timestamp;
|
||||
|
||||
if( isExpanded || listView.manager.alwaysDisplayTimestamps )
|
||||
SetText( logEntry, timestamp, isExpanded );
|
||||
}
|
||||
|
||||
private void SetText( DebugLogEntry logEntry, DebugLogEntryTimestamp? logEntryTimestamp, bool isExpanded )
|
||||
{
|
||||
if( !logEntryTimestamp.HasValue || ( !isExpanded && !listView.manager.alwaysDisplayTimestamps ) )
|
||||
logText.text = isExpanded ? logEntry.ToString() : logEntry.logString;
|
||||
else
|
||||
{
|
||||
StringBuilder sb = listView.manager.sharedStringBuilder;
|
||||
sb.Length = 0;
|
||||
|
||||
if( isExpanded )
|
||||
{
|
||||
logEntryTimestamp.Value.AppendFullTimestamp( sb );
|
||||
sb.Append( ": " ).Append( logEntry.ToString() );
|
||||
}
|
||||
else
|
||||
{
|
||||
logEntryTimestamp.Value.AppendTime( sb );
|
||||
sb.Append( " " ).Append( logEntry.logString );
|
||||
}
|
||||
|
||||
logText.text = sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
// This log item is clicked, show the debug entry's stack trace
|
||||
public void OnPointerClick( PointerEventData eventData )
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if( eventData.button == PointerEventData.InputButton.Right )
|
||||
{
|
||||
Match regex = Regex.Match( logEntry.stackTrace, @"\(at .*\.cs:[0-9]+\)$", RegexOptions.Multiline );
|
||||
if( regex.Success )
|
||||
{
|
||||
string line = logEntry.stackTrace.Substring( regex.Index + 4, regex.Length - 5 );
|
||||
int lineSeparator = line.IndexOf( ':' );
|
||||
MonoScript script = AssetDatabase.LoadAssetAtPath<MonoScript>( line.Substring( 0, lineSeparator ) );
|
||||
if( script != null )
|
||||
AssetDatabase.OpenAsset( script, int.Parse( line.Substring( lineSeparator + 1 ) ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
listView.OnLogItemClicked( this );
|
||||
#else
|
||||
listView.OnLogItemClicked( this );
|
||||
#endif
|
||||
}
|
||||
|
||||
public void CopyLog()
|
||||
{
|
||||
#if UNITY_EDITOR || !UNITY_WEBGL
|
||||
string log = GetCopyContent();
|
||||
if( string.IsNullOrEmpty( log ) )
|
||||
return;
|
||||
|
||||
#if UNITY_EDITOR || UNITY_2018_1_OR_NEWER || ( !UNITY_ANDROID && !UNITY_IOS )
|
||||
GUIUtility.systemCopyBuffer = log;
|
||||
#elif UNITY_ANDROID
|
||||
AJC.CallStatic( "CopyText", Context, log );
|
||||
#elif UNITY_IOS
|
||||
_DebugConsole_CopyText( log );
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
internal string GetCopyContent()
|
||||
{
|
||||
if( !logEntryTimestamp.HasValue )
|
||||
return logEntry.ToString();
|
||||
else
|
||||
{
|
||||
StringBuilder sb = listView.manager.sharedStringBuilder;
|
||||
sb.Length = 0;
|
||||
|
||||
logEntryTimestamp.Value.AppendFullTimestamp( sb );
|
||||
sb.Append( ": " ).Append( logEntry.ToString() );
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public float CalculateExpandedHeight( DebugLogEntry logEntry, DebugLogEntryTimestamp? logEntryTimestamp )
|
||||
{
|
||||
string text = logText.text;
|
||||
HorizontalWrapMode wrapMode = logText.horizontalOverflow;
|
||||
|
||||
SetText( logEntry, logEntryTimestamp, true );
|
||||
logText.horizontalOverflow = HorizontalWrapMode.Wrap;
|
||||
|
||||
float result = logText.preferredHeight + copyLogButtonHeight;
|
||||
|
||||
logText.text = text;
|
||||
logText.horizontalOverflow = wrapMode;
|
||||
|
||||
return Mathf.Max( listView.ItemHeight, result );
|
||||
}
|
||||
|
||||
// Return a string containing complete information about the debug entry
|
||||
public override string ToString()
|
||||
{
|
||||
return logEntry.ToString();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2ea291be9de70a4abfec595203c96c1
|
||||
timeCreated: 1465919949
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,36 @@
|
||||
#if !UNITY_EDITOR && UNITY_WEBGL
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace IngameDebugConsole
|
||||
{
|
||||
public class DebugLogItemCopyWebGL : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
|
||||
{
|
||||
[DllImport( "__Internal" )]
|
||||
private static extern void IngameDebugConsoleStartCopy( string textToCopy );
|
||||
[DllImport( "__Internal" )]
|
||||
private static extern void IngameDebugConsoleCancelCopy();
|
||||
|
||||
private DebugLogItem logItem;
|
||||
|
||||
public void Initialize( DebugLogItem logItem )
|
||||
{
|
||||
this.logItem = logItem;
|
||||
}
|
||||
|
||||
public void OnPointerDown( PointerEventData eventData )
|
||||
{
|
||||
string log = logItem.GetCopyContent();
|
||||
if( !string.IsNullOrEmpty( log ) )
|
||||
IngameDebugConsoleStartCopy( log );
|
||||
}
|
||||
|
||||
public void OnPointerUp( PointerEventData eventData )
|
||||
{
|
||||
if( eventData.dragging )
|
||||
IngameDebugConsoleCancelCopy();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5a7d9d894141e704d8160fb4632121ac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
1758
Assets/Plugins/IngameDebugConsole/Scripts/DebugLogManager.cs
Normal file
1758
Assets/Plugins/IngameDebugConsole/Scripts/DebugLogManager.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6a4f16ed905adcd4ab0d7c8c11f0d72c
|
||||
timeCreated: 1522092746
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: -9869
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
277
Assets/Plugins/IngameDebugConsole/Scripts/DebugLogPopup.cs
Normal file
277
Assets/Plugins/IngameDebugConsole/Scripts/DebugLogPopup.cs
Normal file
@ -0,0 +1,277 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
using System.Collections;
|
||||
#if UNITY_EDITOR && UNITY_2021_1_OR_NEWER
|
||||
using Screen = UnityEngine.Device.Screen; // To support Device Simulator on Unity 2021.1+
|
||||
#endif
|
||||
|
||||
// Manager class for the debug popup
|
||||
namespace IngameDebugConsole
|
||||
{
|
||||
public class DebugLogPopup : MonoBehaviour, IPointerClickHandler, IBeginDragHandler, IDragHandler, IEndDragHandler
|
||||
{
|
||||
private RectTransform popupTransform;
|
||||
|
||||
// Dimensions of the popup divided by 2
|
||||
private Vector2 halfSize;
|
||||
|
||||
// Background image that will change color to indicate an alert
|
||||
private Image backgroundImage;
|
||||
|
||||
// Canvas group to modify visibility of the popup
|
||||
private CanvasGroup canvasGroup;
|
||||
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private DebugLogManager debugManager;
|
||||
|
||||
[SerializeField]
|
||||
private Text newInfoCountText;
|
||||
[SerializeField]
|
||||
private Text newWarningCountText;
|
||||
[SerializeField]
|
||||
private Text newErrorCountText;
|
||||
|
||||
[SerializeField]
|
||||
private Color alertColorInfo;
|
||||
[SerializeField]
|
||||
private Color alertColorWarning;
|
||||
[SerializeField]
|
||||
private Color alertColorError;
|
||||
#pragma warning restore 0649
|
||||
|
||||
// Number of new debug entries since the log window has been closed
|
||||
private int newInfoCount = 0, newWarningCount = 0, newErrorCount = 0;
|
||||
|
||||
private Color normalColor;
|
||||
|
||||
private bool isPopupBeingDragged = false;
|
||||
private Vector2 normalizedPosition;
|
||||
|
||||
// Coroutines for simple code-based animations
|
||||
private IEnumerator moveToPosCoroutine = null;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
popupTransform = (RectTransform) transform;
|
||||
backgroundImage = GetComponent<Image>();
|
||||
canvasGroup = GetComponent<CanvasGroup>();
|
||||
|
||||
normalColor = backgroundImage.color;
|
||||
|
||||
halfSize = popupTransform.sizeDelta * 0.5f;
|
||||
|
||||
Vector2 pos = popupTransform.anchoredPosition;
|
||||
if( pos.x != 0f || pos.y != 0f )
|
||||
normalizedPosition = pos.normalized; // Respect the initial popup position set in the prefab
|
||||
else
|
||||
normalizedPosition = new Vector2( 0.5f, 0f ); // Right edge by default
|
||||
}
|
||||
|
||||
public void NewLogsArrived( int newInfo, int newWarning, int newError )
|
||||
{
|
||||
if( newInfo > 0 )
|
||||
{
|
||||
newInfoCount += newInfo;
|
||||
newInfoCountText.text = newInfoCount.ToString();
|
||||
}
|
||||
|
||||
if( newWarning > 0 )
|
||||
{
|
||||
newWarningCount += newWarning;
|
||||
newWarningCountText.text = newWarningCount.ToString();
|
||||
}
|
||||
|
||||
if( newError > 0 )
|
||||
{
|
||||
newErrorCount += newError;
|
||||
newErrorCountText.text = newErrorCount.ToString();
|
||||
}
|
||||
|
||||
if( newErrorCount > 0 )
|
||||
backgroundImage.color = alertColorError;
|
||||
else if( newWarningCount > 0 )
|
||||
backgroundImage.color = alertColorWarning;
|
||||
else
|
||||
backgroundImage.color = alertColorInfo;
|
||||
}
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
newInfoCount = 0;
|
||||
newWarningCount = 0;
|
||||
newErrorCount = 0;
|
||||
|
||||
newInfoCountText.text = "0";
|
||||
newWarningCountText.text = "0";
|
||||
newErrorCountText.text = "0";
|
||||
|
||||
backgroundImage.color = normalColor;
|
||||
}
|
||||
|
||||
// A simple smooth movement animation
|
||||
private IEnumerator MoveToPosAnimation( Vector2 targetPos )
|
||||
{
|
||||
float modifier = 0f;
|
||||
Vector2 initialPos = popupTransform.anchoredPosition;
|
||||
|
||||
while( modifier < 1f )
|
||||
{
|
||||
modifier += 4f * Time.unscaledDeltaTime;
|
||||
popupTransform.anchoredPosition = Vector2.Lerp( initialPos, targetPos, modifier );
|
||||
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Popup is clicked
|
||||
public void OnPointerClick( PointerEventData data )
|
||||
{
|
||||
// Hide the popup and show the log window
|
||||
if( !isPopupBeingDragged )
|
||||
debugManager.ShowLogWindow();
|
||||
}
|
||||
|
||||
// Hides the log window and shows the popup
|
||||
public void Show()
|
||||
{
|
||||
canvasGroup.blocksRaycasts = true;
|
||||
canvasGroup.alpha = 1f;
|
||||
|
||||
// Reset the counters
|
||||
Reset();
|
||||
|
||||
// Update position in case resolution was changed while the popup was hidden
|
||||
UpdatePosition( true );
|
||||
}
|
||||
|
||||
// Hide the popup
|
||||
public void Hide()
|
||||
{
|
||||
canvasGroup.blocksRaycasts = false;
|
||||
canvasGroup.alpha = 0f;
|
||||
|
||||
isPopupBeingDragged = false;
|
||||
}
|
||||
|
||||
public void OnBeginDrag( PointerEventData data )
|
||||
{
|
||||
isPopupBeingDragged = true;
|
||||
|
||||
// If a smooth movement animation is in progress, cancel it
|
||||
if( moveToPosCoroutine != null )
|
||||
{
|
||||
StopCoroutine( moveToPosCoroutine );
|
||||
moveToPosCoroutine = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Reposition the popup
|
||||
public void OnDrag( PointerEventData data )
|
||||
{
|
||||
Vector2 localPoint;
|
||||
if( RectTransformUtility.ScreenPointToLocalPointInRectangle( debugManager.canvasTR, data.position, data.pressEventCamera, out localPoint ) )
|
||||
popupTransform.anchoredPosition = localPoint;
|
||||
}
|
||||
|
||||
// Smoothly translate the popup to the nearest edge
|
||||
public void OnEndDrag( PointerEventData data )
|
||||
{
|
||||
isPopupBeingDragged = false;
|
||||
UpdatePosition( false );
|
||||
}
|
||||
|
||||
// There are 2 different spaces used in these calculations:
|
||||
// RectTransform space: raw anchoredPosition of the popup that's in range [-canvasSize/2, canvasSize/2]
|
||||
// Safe area space: Screen.safeArea space that's in range [safeAreaBottomLeft, safeAreaTopRight] where these corner positions
|
||||
// are all positive (calculated from bottom left corner of the screen instead of the center of the screen)
|
||||
public void UpdatePosition( bool immediately )
|
||||
{
|
||||
Vector2 canvasRawSize = debugManager.canvasTR.rect.size;
|
||||
|
||||
// Calculate safe area bounds
|
||||
float canvasWidth = canvasRawSize.x;
|
||||
float canvasHeight = canvasRawSize.y;
|
||||
|
||||
float canvasBottomLeftX = 0f;
|
||||
float canvasBottomLeftY = 0f;
|
||||
|
||||
if( debugManager.popupAvoidsScreenCutout )
|
||||
{
|
||||
#if UNITY_2017_2_OR_NEWER && ( UNITY_EDITOR || UNITY_ANDROID || UNITY_IOS )
|
||||
Rect safeArea = Screen.safeArea;
|
||||
|
||||
int screenWidth = Screen.width;
|
||||
int screenHeight = Screen.height;
|
||||
|
||||
canvasWidth *= safeArea.width / screenWidth;
|
||||
canvasHeight *= safeArea.height / screenHeight;
|
||||
|
||||
canvasBottomLeftX = canvasRawSize.x * ( safeArea.x / screenWidth );
|
||||
canvasBottomLeftY = canvasRawSize.y * ( safeArea.y / screenHeight );
|
||||
#endif
|
||||
}
|
||||
|
||||
// Calculate safe area position of the popup
|
||||
// normalizedPosition allows us to glue the popup to a specific edge of the screen. It becomes useful when
|
||||
// the popup is at the right edge and we switch from portrait screen orientation to landscape screen orientation.
|
||||
// Without normalizedPosition, popup could jump to bottom or top edges instead of staying at the right edge
|
||||
Vector2 pos = canvasRawSize * 0.5f + ( immediately ? new Vector2( normalizedPosition.x * canvasWidth, normalizedPosition.y * canvasHeight ) : ( popupTransform.anchoredPosition - new Vector2( canvasBottomLeftX, canvasBottomLeftY ) ) );
|
||||
|
||||
// Find distances to all four edges of the safe area
|
||||
float distToLeft = pos.x;
|
||||
float distToRight = canvasWidth - distToLeft;
|
||||
|
||||
float distToBottom = pos.y;
|
||||
float distToTop = canvasHeight - distToBottom;
|
||||
|
||||
float horDistance = Mathf.Min( distToLeft, distToRight );
|
||||
float vertDistance = Mathf.Min( distToBottom, distToTop );
|
||||
|
||||
// Find the nearest edge's safe area coordinates
|
||||
if( horDistance < vertDistance )
|
||||
{
|
||||
if( distToLeft < distToRight )
|
||||
pos = new Vector2( halfSize.x, pos.y );
|
||||
else
|
||||
pos = new Vector2( canvasWidth - halfSize.x, pos.y );
|
||||
|
||||
pos.y = Mathf.Clamp( pos.y, halfSize.y, canvasHeight - halfSize.y );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( distToBottom < distToTop )
|
||||
pos = new Vector2( pos.x, halfSize.y );
|
||||
else
|
||||
pos = new Vector2( pos.x, canvasHeight - halfSize.y );
|
||||
|
||||
pos.x = Mathf.Clamp( pos.x, halfSize.x, canvasWidth - halfSize.x );
|
||||
}
|
||||
|
||||
pos -= canvasRawSize * 0.5f;
|
||||
|
||||
normalizedPosition.Set( pos.x / canvasWidth, pos.y / canvasHeight );
|
||||
|
||||
// Safe area's bottom left coordinates are added to pos only after normalizedPosition's value
|
||||
// is set because normalizedPosition is in range [-canvasWidth / 2, canvasWidth / 2]
|
||||
pos += new Vector2( canvasBottomLeftX, canvasBottomLeftY );
|
||||
|
||||
// If another smooth movement animation is in progress, cancel it
|
||||
if( moveToPosCoroutine != null )
|
||||
{
|
||||
StopCoroutine( moveToPosCoroutine );
|
||||
moveToPosCoroutine = null;
|
||||
}
|
||||
|
||||
if( immediately )
|
||||
popupTransform.anchoredPosition = pos;
|
||||
else
|
||||
{
|
||||
// Smoothly translate the popup to the specified position
|
||||
moveToPosCoroutine = MoveToPosAnimation( pos );
|
||||
StartCoroutine( moveToPosCoroutine );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05cc4b1999716644c9308528e38e7081
|
||||
timeCreated: 1466533184
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,392 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
// Handles the log items in an optimized way such that existing log items are
|
||||
// recycled within the list instead of creating a new log item at each chance
|
||||
namespace IngameDebugConsole
|
||||
{
|
||||
public class DebugLogRecycledListView : MonoBehaviour
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
// Cached components
|
||||
[SerializeField]
|
||||
private RectTransform transformComponent;
|
||||
[SerializeField]
|
||||
private RectTransform viewportTransform;
|
||||
|
||||
[SerializeField]
|
||||
private Color logItemNormalColor1;
|
||||
[SerializeField]
|
||||
private Color logItemNormalColor2;
|
||||
[SerializeField]
|
||||
private Color logItemSelectedColor;
|
||||
#pragma warning restore 0649
|
||||
|
||||
internal DebugLogManager manager;
|
||||
private ScrollRect scrollView;
|
||||
|
||||
private float logItemHeight, _1OverLogItemHeight;
|
||||
private float viewportHeight;
|
||||
|
||||
// Unique debug entries
|
||||
private List<DebugLogEntry> collapsedLogEntries = null;
|
||||
|
||||
// Indices of debug entries to show in collapsedLogEntries
|
||||
private DebugLogIndexList<int> indicesOfEntriesToShow = null;
|
||||
private DebugLogIndexList<DebugLogEntryTimestamp> timestampsOfEntriesToShow = null;
|
||||
|
||||
private int indexOfSelectedLogEntry = int.MaxValue;
|
||||
private float positionOfSelectedLogEntry = float.MaxValue;
|
||||
private float heightOfSelectedLogEntry;
|
||||
private float deltaHeightOfSelectedLogEntry;
|
||||
|
||||
// Log items used to visualize the debug entries at specified indices
|
||||
private readonly Dictionary<int, DebugLogItem> logItemsAtIndices = new Dictionary<int, DebugLogItem>( 256 );
|
||||
|
||||
private bool isCollapseOn = false;
|
||||
|
||||
// Current indices of debug entries shown on screen
|
||||
private int currentTopIndex = -1, currentBottomIndex = -1;
|
||||
|
||||
public float ItemHeight { get { return logItemHeight; } }
|
||||
public float SelectedItemHeight { get { return heightOfSelectedLogEntry; } }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
scrollView = viewportTransform.GetComponentInParent<ScrollRect>();
|
||||
scrollView.onValueChanged.AddListener( ( pos ) => UpdateItemsInTheList( false ) );
|
||||
|
||||
viewportHeight = viewportTransform.rect.height;
|
||||
}
|
||||
|
||||
public void Initialize( DebugLogManager manager, List<DebugLogEntry> collapsedLogEntries, DebugLogIndexList<int> indicesOfEntriesToShow, DebugLogIndexList<DebugLogEntryTimestamp> timestampsOfEntriesToShow, float logItemHeight )
|
||||
{
|
||||
this.manager = manager;
|
||||
this.collapsedLogEntries = collapsedLogEntries;
|
||||
this.indicesOfEntriesToShow = indicesOfEntriesToShow;
|
||||
this.timestampsOfEntriesToShow = timestampsOfEntriesToShow;
|
||||
this.logItemHeight = logItemHeight;
|
||||
_1OverLogItemHeight = 1f / logItemHeight;
|
||||
}
|
||||
|
||||
public void SetCollapseMode( bool collapse )
|
||||
{
|
||||
isCollapseOn = collapse;
|
||||
}
|
||||
|
||||
// A log item is clicked, highlight it
|
||||
public void OnLogItemClicked( DebugLogItem item )
|
||||
{
|
||||
OnLogItemClickedInternal( item.Index, item );
|
||||
}
|
||||
|
||||
// Force expand the log item at specified index
|
||||
public void SelectAndFocusOnLogItemAtIndex( int itemIndex )
|
||||
{
|
||||
if( indexOfSelectedLogEntry != itemIndex ) // Make sure that we aren't deselecting the target log item
|
||||
OnLogItemClickedInternal( itemIndex );
|
||||
|
||||
float transformComponentCenterYAtTop = viewportHeight * 0.5f;
|
||||
float transformComponentCenterYAtBottom = transformComponent.sizeDelta.y - viewportHeight * 0.5f;
|
||||
float transformComponentTargetCenterY = itemIndex * logItemHeight + viewportHeight * 0.5f;
|
||||
if( transformComponentCenterYAtTop == transformComponentCenterYAtBottom )
|
||||
scrollView.verticalNormalizedPosition = 0.5f;
|
||||
else
|
||||
scrollView.verticalNormalizedPosition = Mathf.Clamp01( Mathf.InverseLerp( transformComponentCenterYAtBottom, transformComponentCenterYAtTop, transformComponentTargetCenterY ) );
|
||||
|
||||
manager.SetSnapToBottom( false );
|
||||
}
|
||||
|
||||
private void OnLogItemClickedInternal( int itemIndex, DebugLogItem referenceItem = null )
|
||||
{
|
||||
if( indexOfSelectedLogEntry != itemIndex )
|
||||
{
|
||||
DeselectSelectedLogItem();
|
||||
|
||||
if( !referenceItem )
|
||||
{
|
||||
if( currentTopIndex == -1 )
|
||||
UpdateItemsInTheList( false ); // Try to generate some DebugLogItems, we need one DebugLogItem to calculate the text height
|
||||
|
||||
referenceItem = logItemsAtIndices[currentTopIndex];
|
||||
}
|
||||
|
||||
indexOfSelectedLogEntry = itemIndex;
|
||||
positionOfSelectedLogEntry = itemIndex * logItemHeight;
|
||||
heightOfSelectedLogEntry = referenceItem.CalculateExpandedHeight( collapsedLogEntries[indicesOfEntriesToShow[itemIndex]], ( timestampsOfEntriesToShow != null ) ? timestampsOfEntriesToShow[itemIndex] : (DebugLogEntryTimestamp?) null );
|
||||
deltaHeightOfSelectedLogEntry = heightOfSelectedLogEntry - logItemHeight;
|
||||
|
||||
manager.SetSnapToBottom( false );
|
||||
}
|
||||
else
|
||||
DeselectSelectedLogItem();
|
||||
|
||||
if( indexOfSelectedLogEntry >= currentTopIndex && indexOfSelectedLogEntry <= currentBottomIndex )
|
||||
ColorLogItem( logItemsAtIndices[indexOfSelectedLogEntry], indexOfSelectedLogEntry );
|
||||
|
||||
CalculateContentHeight();
|
||||
|
||||
HardResetItems();
|
||||
UpdateItemsInTheList( true );
|
||||
|
||||
manager.ValidateScrollPosition();
|
||||
}
|
||||
|
||||
// Deselect the currently selected log item
|
||||
public void DeselectSelectedLogItem()
|
||||
{
|
||||
int indexOfPreviouslySelectedLogEntry = indexOfSelectedLogEntry;
|
||||
indexOfSelectedLogEntry = int.MaxValue;
|
||||
|
||||
positionOfSelectedLogEntry = float.MaxValue;
|
||||
heightOfSelectedLogEntry = deltaHeightOfSelectedLogEntry = 0f;
|
||||
|
||||
if( indexOfPreviouslySelectedLogEntry >= currentTopIndex && indexOfPreviouslySelectedLogEntry <= currentBottomIndex )
|
||||
ColorLogItem( logItemsAtIndices[indexOfPreviouslySelectedLogEntry], indexOfPreviouslySelectedLogEntry );
|
||||
}
|
||||
|
||||
// Number of debug entries may be changed, update the list
|
||||
public void OnLogEntriesUpdated( bool updateAllVisibleItemContents )
|
||||
{
|
||||
CalculateContentHeight();
|
||||
viewportHeight = viewportTransform.rect.height;
|
||||
|
||||
if( updateAllVisibleItemContents )
|
||||
HardResetItems();
|
||||
|
||||
UpdateItemsInTheList( updateAllVisibleItemContents );
|
||||
}
|
||||
|
||||
// A single collapsed log entry at specified index is updated, refresh its item if visible
|
||||
public void OnCollapsedLogEntryAtIndexUpdated( int index )
|
||||
{
|
||||
DebugLogItem logItem;
|
||||
if( logItemsAtIndices.TryGetValue( index, out logItem ) )
|
||||
{
|
||||
logItem.ShowCount();
|
||||
|
||||
if( timestampsOfEntriesToShow != null )
|
||||
logItem.UpdateTimestamp( timestampsOfEntriesToShow[index] );
|
||||
}
|
||||
}
|
||||
|
||||
// Log window's width has changed, update the expanded (currently selected) log's height
|
||||
public void OnViewportWidthChanged()
|
||||
{
|
||||
if( indexOfSelectedLogEntry >= indicesOfEntriesToShow.Count )
|
||||
return;
|
||||
|
||||
if( currentTopIndex == -1 )
|
||||
{
|
||||
UpdateItemsInTheList( false ); // Try to generate some DebugLogItems, we need one DebugLogItem to calculate the text height
|
||||
if( currentTopIndex == -1 ) // No DebugLogItems are generated, weird
|
||||
return;
|
||||
}
|
||||
|
||||
DebugLogItem referenceItem = logItemsAtIndices[currentTopIndex];
|
||||
|
||||
heightOfSelectedLogEntry = referenceItem.CalculateExpandedHeight( collapsedLogEntries[indicesOfEntriesToShow[indexOfSelectedLogEntry]], ( timestampsOfEntriesToShow != null ) ? timestampsOfEntriesToShow[indexOfSelectedLogEntry] : (DebugLogEntryTimestamp?) null );
|
||||
deltaHeightOfSelectedLogEntry = heightOfSelectedLogEntry - logItemHeight;
|
||||
|
||||
CalculateContentHeight();
|
||||
|
||||
HardResetItems();
|
||||
UpdateItemsInTheList( true );
|
||||
|
||||
manager.ValidateScrollPosition();
|
||||
}
|
||||
|
||||
// Log window's height has changed, update the list
|
||||
public void OnViewportHeightChanged()
|
||||
{
|
||||
viewportHeight = viewportTransform.rect.height;
|
||||
UpdateItemsInTheList( false );
|
||||
}
|
||||
|
||||
private void HardResetItems()
|
||||
{
|
||||
if( currentTopIndex != -1 )
|
||||
{
|
||||
DestroyLogItemsBetweenIndices( currentTopIndex, currentBottomIndex );
|
||||
currentTopIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateContentHeight()
|
||||
{
|
||||
float newHeight = Mathf.Max( 1f, indicesOfEntriesToShow.Count * logItemHeight + deltaHeightOfSelectedLogEntry );
|
||||
transformComponent.sizeDelta = new Vector2( 0f, newHeight );
|
||||
}
|
||||
|
||||
// Calculate the indices of log entries to show
|
||||
// and handle log items accordingly
|
||||
public void UpdateItemsInTheList( bool updateAllVisibleItemContents )
|
||||
{
|
||||
// If there is at least one log entry to show
|
||||
if( indicesOfEntriesToShow.Count > 0 )
|
||||
{
|
||||
float contentPosTop = transformComponent.anchoredPosition.y - 1f;
|
||||
float contentPosBottom = contentPosTop + viewportHeight + 2f;
|
||||
|
||||
if( positionOfSelectedLogEntry <= contentPosBottom )
|
||||
{
|
||||
if( positionOfSelectedLogEntry <= contentPosTop )
|
||||
{
|
||||
contentPosTop -= deltaHeightOfSelectedLogEntry;
|
||||
contentPosBottom -= deltaHeightOfSelectedLogEntry;
|
||||
|
||||
if( contentPosTop < positionOfSelectedLogEntry - 1f )
|
||||
contentPosTop = positionOfSelectedLogEntry - 1f;
|
||||
|
||||
if( contentPosBottom < contentPosTop + 2f )
|
||||
contentPosBottom = contentPosTop + 2f;
|
||||
}
|
||||
else
|
||||
{
|
||||
contentPosBottom -= deltaHeightOfSelectedLogEntry;
|
||||
if( contentPosBottom < positionOfSelectedLogEntry + 1f )
|
||||
contentPosBottom = positionOfSelectedLogEntry + 1f;
|
||||
}
|
||||
}
|
||||
|
||||
int newTopIndex = (int) ( contentPosTop * _1OverLogItemHeight );
|
||||
int newBottomIndex = (int) ( contentPosBottom * _1OverLogItemHeight );
|
||||
|
||||
if( newTopIndex < 0 )
|
||||
newTopIndex = 0;
|
||||
|
||||
if( newBottomIndex > indicesOfEntriesToShow.Count - 1 )
|
||||
newBottomIndex = indicesOfEntriesToShow.Count - 1;
|
||||
|
||||
if( currentTopIndex == -1 )
|
||||
{
|
||||
// There are no log items visible on screen,
|
||||
// just create the new log items
|
||||
updateAllVisibleItemContents = true;
|
||||
|
||||
currentTopIndex = newTopIndex;
|
||||
currentBottomIndex = newBottomIndex;
|
||||
|
||||
CreateLogItemsBetweenIndices( newTopIndex, newBottomIndex );
|
||||
}
|
||||
else
|
||||
{
|
||||
// There are some log items visible on screen
|
||||
|
||||
if( newBottomIndex < currentTopIndex || newTopIndex > currentBottomIndex )
|
||||
{
|
||||
// If user scrolled a lot such that, none of the log items are now within
|
||||
// the bounds of the scroll view, pool all the previous log items and create
|
||||
// new log items for the new list of visible debug entries
|
||||
updateAllVisibleItemContents = true;
|
||||
|
||||
DestroyLogItemsBetweenIndices( currentTopIndex, currentBottomIndex );
|
||||
CreateLogItemsBetweenIndices( newTopIndex, newBottomIndex );
|
||||
}
|
||||
else
|
||||
{
|
||||
// User did not scroll a lot such that, there are still some log items within
|
||||
// the bounds of the scroll view. Don't destroy them but update their content,
|
||||
// if necessary
|
||||
if( newTopIndex > currentTopIndex )
|
||||
DestroyLogItemsBetweenIndices( currentTopIndex, newTopIndex - 1 );
|
||||
|
||||
if( newBottomIndex < currentBottomIndex )
|
||||
DestroyLogItemsBetweenIndices( newBottomIndex + 1, currentBottomIndex );
|
||||
|
||||
if( newTopIndex < currentTopIndex )
|
||||
{
|
||||
CreateLogItemsBetweenIndices( newTopIndex, currentTopIndex - 1 );
|
||||
|
||||
// If it is not necessary to update all the log items,
|
||||
// then just update the newly created log items. Otherwise,
|
||||
// wait for the major update
|
||||
if( !updateAllVisibleItemContents )
|
||||
UpdateLogItemContentsBetweenIndices( newTopIndex, currentTopIndex - 1 );
|
||||
}
|
||||
|
||||
if( newBottomIndex > currentBottomIndex )
|
||||
{
|
||||
CreateLogItemsBetweenIndices( currentBottomIndex + 1, newBottomIndex );
|
||||
|
||||
// If it is not necessary to update all the log items,
|
||||
// then just update the newly created log items. Otherwise,
|
||||
// wait for the major update
|
||||
if( !updateAllVisibleItemContents )
|
||||
UpdateLogItemContentsBetweenIndices( currentBottomIndex + 1, newBottomIndex );
|
||||
}
|
||||
}
|
||||
|
||||
currentTopIndex = newTopIndex;
|
||||
currentBottomIndex = newBottomIndex;
|
||||
}
|
||||
|
||||
if( updateAllVisibleItemContents )
|
||||
{
|
||||
// Update all the log items
|
||||
UpdateLogItemContentsBetweenIndices( currentTopIndex, currentBottomIndex );
|
||||
}
|
||||
}
|
||||
else
|
||||
HardResetItems();
|
||||
}
|
||||
|
||||
private void CreateLogItemsBetweenIndices( int topIndex, int bottomIndex )
|
||||
{
|
||||
for( int i = topIndex; i <= bottomIndex; i++ )
|
||||
CreateLogItemAtIndex( i );
|
||||
}
|
||||
|
||||
// Create (or unpool) a log item
|
||||
private void CreateLogItemAtIndex( int index )
|
||||
{
|
||||
DebugLogItem logItem = manager.PopLogItem();
|
||||
|
||||
// Reposition the log item
|
||||
Vector2 anchoredPosition = new Vector2( 1f, -index * logItemHeight );
|
||||
if( index > indexOfSelectedLogEntry )
|
||||
anchoredPosition.y -= deltaHeightOfSelectedLogEntry;
|
||||
|
||||
logItem.Transform.anchoredPosition = anchoredPosition;
|
||||
|
||||
// Color the log item
|
||||
ColorLogItem( logItem, index );
|
||||
|
||||
// To access this log item easily in the future, add it to the dictionary
|
||||
logItemsAtIndices[index] = logItem;
|
||||
}
|
||||
|
||||
private void DestroyLogItemsBetweenIndices( int topIndex, int bottomIndex )
|
||||
{
|
||||
for( int i = topIndex; i <= bottomIndex; i++ )
|
||||
manager.PoolLogItem( logItemsAtIndices[i] );
|
||||
}
|
||||
|
||||
private void UpdateLogItemContentsBetweenIndices( int topIndex, int bottomIndex )
|
||||
{
|
||||
DebugLogItem logItem;
|
||||
for( int i = topIndex; i <= bottomIndex; i++ )
|
||||
{
|
||||
logItem = logItemsAtIndices[i];
|
||||
logItem.SetContent( collapsedLogEntries[indicesOfEntriesToShow[i]], ( timestampsOfEntriesToShow != null ) ? timestampsOfEntriesToShow[i] : (DebugLogEntryTimestamp?) null, i, i == indexOfSelectedLogEntry );
|
||||
|
||||
if( isCollapseOn )
|
||||
logItem.ShowCount();
|
||||
else
|
||||
logItem.HideCount();
|
||||
}
|
||||
}
|
||||
|
||||
// Color a log item using its index
|
||||
private void ColorLogItem( DebugLogItem logItem, int index )
|
||||
{
|
||||
if( index == indexOfSelectedLogEntry )
|
||||
logItem.Image.color = logItemSelectedColor;
|
||||
else if( index % 2 == 0 )
|
||||
logItem.Image.color = logItemNormalColor1;
|
||||
else
|
||||
logItem.Image.color = logItemNormalColor2;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce231987d32488f43b6fb798f7df43f6
|
||||
timeCreated: 1466373025
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,24 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
// Listens to drag event on the DebugLogManager's resize button
|
||||
namespace IngameDebugConsole
|
||||
{
|
||||
public class DebugLogResizeListener : MonoBehaviour, IBeginDragHandler, IDragHandler
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private DebugLogManager debugManager;
|
||||
#pragma warning restore 0649
|
||||
|
||||
// This interface must be implemented in order to receive drag events
|
||||
void IBeginDragHandler.OnBeginDrag( PointerEventData eventData )
|
||||
{
|
||||
}
|
||||
|
||||
void IDragHandler.OnDrag( PointerEventData eventData )
|
||||
{
|
||||
debugManager.Resize( eventData );
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6565f2084f5aef44abe57c988745b9c3
|
||||
timeCreated: 1601221093
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,60 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
// Listens to scroll events on the scroll rect that debug items are stored
|
||||
// and decides whether snap to bottom should be true or not
|
||||
//
|
||||
// Procedure: if, after a user input (drag or scroll), scrollbar is at the bottom, then
|
||||
// snap to bottom shall be true, otherwise it shall be false
|
||||
namespace IngameDebugConsole
|
||||
{
|
||||
public class DebugsOnScrollListener : MonoBehaviour, IScrollHandler, IBeginDragHandler, IEndDragHandler
|
||||
{
|
||||
public ScrollRect debugsScrollRect;
|
||||
public DebugLogManager debugLogManager;
|
||||
|
||||
public void OnScroll( PointerEventData data )
|
||||
{
|
||||
if( IsScrollbarAtBottom() )
|
||||
debugLogManager.SetSnapToBottom( true );
|
||||
else
|
||||
debugLogManager.SetSnapToBottom( false );
|
||||
}
|
||||
|
||||
public void OnBeginDrag( PointerEventData data )
|
||||
{
|
||||
debugLogManager.SetSnapToBottom( false );
|
||||
}
|
||||
|
||||
public void OnEndDrag( PointerEventData data )
|
||||
{
|
||||
if( IsScrollbarAtBottom() )
|
||||
debugLogManager.SetSnapToBottom( true );
|
||||
else
|
||||
debugLogManager.SetSnapToBottom( false );
|
||||
}
|
||||
|
||||
public void OnScrollbarDragStart( BaseEventData data )
|
||||
{
|
||||
debugLogManager.SetSnapToBottom( false );
|
||||
}
|
||||
|
||||
public void OnScrollbarDragEnd( BaseEventData data )
|
||||
{
|
||||
if( IsScrollbarAtBottom() )
|
||||
debugLogManager.SetSnapToBottom( true );
|
||||
else
|
||||
debugLogManager.SetSnapToBottom( false );
|
||||
}
|
||||
|
||||
private bool IsScrollbarAtBottom()
|
||||
{
|
||||
float scrollbarYPos = debugsScrollRect.verticalNormalizedPosition;
|
||||
if( scrollbarYPos <= 1E-6f )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cb564dcb180e586429c57456166a76b5
|
||||
timeCreated: 1466004663
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -0,0 +1,60 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace IngameDebugConsole
|
||||
{
|
||||
// Avoid multiple EventSystems in the scene by activating the embedded EventSystem only if one doesn't already exist in the scene
|
||||
[DefaultExecutionOrder( 1000 )]
|
||||
public class EventSystemHandler : MonoBehaviour
|
||||
{
|
||||
#pragma warning disable 0649
|
||||
[SerializeField]
|
||||
private GameObject embeddedEventSystem;
|
||||
#pragma warning restore 0649
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
SceneManager.sceneLoaded += OnSceneLoaded;
|
||||
SceneManager.sceneUnloaded -= OnSceneUnloaded;
|
||||
SceneManager.sceneUnloaded += OnSceneUnloaded;
|
||||
|
||||
ActivateEventSystemIfNeeded();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
SceneManager.sceneLoaded -= OnSceneLoaded;
|
||||
SceneManager.sceneUnloaded -= OnSceneUnloaded;
|
||||
|
||||
DeactivateEventSystem();
|
||||
}
|
||||
|
||||
private void OnSceneLoaded( Scene scene, LoadSceneMode mode )
|
||||
{
|
||||
#if UNITY_2017_2_OR_NEWER
|
||||
DeactivateEventSystem();
|
||||
#endif
|
||||
ActivateEventSystemIfNeeded();
|
||||
}
|
||||
|
||||
private void OnSceneUnloaded( Scene current )
|
||||
{
|
||||
// Deactivate the embedded EventSystem before changing scenes because the new scene might have its own EventSystem
|
||||
DeactivateEventSystem();
|
||||
}
|
||||
|
||||
private void ActivateEventSystemIfNeeded()
|
||||
{
|
||||
if( embeddedEventSystem && !EventSystem.current )
|
||||
embeddedEventSystem.SetActive( true );
|
||||
}
|
||||
|
||||
private void DeactivateEventSystem()
|
||||
{
|
||||
if( embeddedEventSystem )
|
||||
embeddedEventSystem.SetActive( false );
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c3cc1b407f337e641ad32a2e91d5b478
|
||||
timeCreated: 1658741613
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user