提交Unity 联机Pro

This commit is contained in:
PC-20230316NUNE\Administrator
2024-08-17 14:27:18 +08:00
parent f00193b000
commit 894100ae37
7448 changed files with 854473 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
namespace SRDebugger.Services.Implementation
{
using System;
using Internal;
using SRF.Service;
using UnityEngine;
[Service(typeof (IBugReportService))]
class BugReportApiService : IBugReportService
{
private IBugReporterHandler _handler = new InternalBugReporterHandler();
public bool IsUsable
{
get
{
return _handler != null && _handler.IsUsable;
}
}
public void SetHandler(IBugReporterHandler handler)
{
Debug.LogFormat("[SRDebugger] Bug Report handler set to {0}", handler);
_handler = handler;
}
public void SendBugReport(BugReport report, BugReportCompleteCallback completeHandler,
IProgress<float> progress = null)
{
if (_handler == null)
{
throw new InvalidOperationException("No bug report handler has been configured.");
}
if (!_handler.IsUsable)
{
throw new InvalidOperationException("Bug report handler is not usable.");
}
if (report == null)
{
throw new ArgumentNullException("report");
}
if (completeHandler == null)
{
throw new ArgumentNullException("completeHandler");
}
if (Application.internetReachability == NetworkReachability.NotReachable)
{
completeHandler(false, "No Internet Connection");
return;
}
_handler.Submit(report, result => completeHandler(result.IsSuccessful, result.ErrorMessage), progress);
}
}
}

View File

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

View File

@@ -0,0 +1,167 @@
namespace SRDebugger.Services.Implementation
{
using System;
using System.Collections;
using Internal;
using SRF;
using SRF.Service;
using UI.Other;
using UnityEngine;
[Service(typeof (BugReportPopoverService))]
public class BugReportPopoverService : SRServiceBase<BugReportPopoverService>
{
private BugReportCompleteCallback _callback;
private bool _isVisible;
private BugReportPopoverRoot _popover;
private BugReportSheetController _sheet;
public bool IsShowingPopover
{
get { return _isVisible; }
}
public void ShowBugReporter(BugReportCompleteCallback callback, bool takeScreenshotFirst = true,
string descriptionText = null)
{
if (_isVisible)
{
throw new InvalidOperationException("Bug report popover is already visible.");
}
if (_popover == null)
{
Load();
}
if (_popover == null)
{
Debug.LogWarning("[SRDebugger] Bug report popover failed loading, executing callback with fail result");
callback(false, "Resource load failed");
return;
}
_callback = callback;
_isVisible = true;
SRDebuggerUtil.EnsureEventSystemExists();
StartCoroutine(OpenCo(takeScreenshotFirst, descriptionText));
}
private IEnumerator OpenCo(bool takeScreenshot, string descriptionText)
{
if (takeScreenshot)
{
// Wait for screenshot to be captured
yield return StartCoroutine(BugReportScreenshotUtil.ScreenshotCaptureCo());
}
_popover.CachedGameObject.SetActive(true);
yield return new WaitForEndOfFrame();
if (!string.IsNullOrEmpty(descriptionText))
{
_sheet.DescriptionField.text = descriptionText;
}
}
private void SubmitComplete(bool didSucceed, string errorMessage)
{
OnComplete(didSucceed, errorMessage, false);
}
private void CancelPressed()
{
OnComplete(false, "User Cancelled", true);
}
private void OnComplete(bool success, string errorMessage, bool close)
{
if (!_isVisible)
{
Debug.LogWarning("[SRDebugger] Received callback at unexpected time. ???");
return;
}
if (!success && !close)
{
return;
}
_isVisible = false;
// Destroy it all so it doesn't linger in the scene using memory
_popover.gameObject.SetActive(false);
Destroy(_popover.gameObject);
_popover = null;
_sheet = null;
BugReportScreenshotUtil.ScreenshotData = null;
_callback(success, errorMessage);
}
private void TakingScreenshot()
{
if (!IsShowingPopover)
{
Debug.LogWarning("[SRDebugger] Received callback at unexpected time. ???");
return;
}
_popover.CanvasGroup.alpha = 0f;
}
private void ScreenshotComplete()
{
if (!IsShowingPopover)
{
Debug.LogWarning("[SRDebugger] Received callback at unexpected time. ???");
return;
}
_popover.CanvasGroup.alpha = 1f;
}
protected override void Awake()
{
base.Awake();
CachedTransform.SetParent(Hierarchy.Get("SRDebugger"));
}
private void Load()
{
var popoverPrefab = Resources.Load<BugReportPopoverRoot>(SRDebugPaths.BugReportPopoverPath);
var sheetPrefab = Resources.Load<BugReportSheetController>(SRDebugPaths.BugReportSheetPath);
if (popoverPrefab == null)
{
Debug.LogError("[SRDebugger] Unable to load bug report popover prefab");
return;
}
if (sheetPrefab == null)
{
Debug.LogError("[SRDebugger] Unable to load bug report sheet prefab");
return;
}
_popover = SRInstantiate.Instantiate(popoverPrefab);
_popover.CachedTransform.SetParent(CachedTransform, false);
_sheet = SRInstantiate.Instantiate(sheetPrefab);
_sheet.CachedTransform.SetParent(_popover.Container, false);
_sheet.SubmitComplete = SubmitComplete;
_sheet.CancelPressed = CancelPressed;
_sheet.TakingScreenshot = TakingScreenshot;
_sheet.ScreenshotComplete = ScreenshotComplete;
_popover.CachedGameObject.SetActive(false);
}
}
}

View File

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

View File

@@ -0,0 +1,57 @@
using System;
using SRDebugger.Services;
using SRF.Service;
using UnityEngine;
namespace Assets.StompyRobot.SRDebugger.Scripts.Services.Implementation
{
[Service(typeof(IConsoleFilterState))]
public sealed class ConsoleFilterStateService : IConsoleFilterState
{
public event ConsoleStateChangedEventHandler FilterStateChange;
private readonly bool[] _states;
public ConsoleFilterStateService()
{
_states = new bool[Enum.GetValues(typeof(LogType)).Length];
for (var i = 0; i < _states.Length; i++)
{
_states[i] = true;
}
}
public void SetConsoleFilterState(LogType type, bool newState)
{
type = GetType(type);
if (_states[(int)type] == newState)
{
return;
}
//Debug.Log($"FilterState changed {type} {!newState} -> {newState}");
_states[(int)type] = newState;
FilterStateChange?.Invoke(type, newState);
}
public bool GetConsoleFilterState(LogType type)
{
type = GetType(type);
return _states[(int)type];
}
private static LogType GetType(LogType type)
{
switch (type)
{
case LogType.Error:
case LogType.Assert:
case LogType.Exception:
return LogType.Error;
default:
return type;
}
}
}
}

View File

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

View File

@@ -0,0 +1,32 @@
namespace SRDebugger.Services.Implementation
{
using SRF;
using SRF.Service;
using UnityEngine;
[Service(typeof (IDebugCameraService))]
public class DebugCameraServiceImpl : IDebugCameraService
{
private Camera _debugCamera;
public DebugCameraServiceImpl()
{
if (Settings.Instance.UseDebugCamera)
{
_debugCamera = new GameObject("SRDebugCamera").AddComponent<Camera>();
_debugCamera.cullingMask = 1 << Settings.Instance.DebugLayer;
_debugCamera.depth = Settings.Instance.DebugCameraDepth;
_debugCamera.clearFlags = CameraClearFlags.Depth;
_debugCamera.transform.SetParent(Hierarchy.Get("SRDebugger"));
}
}
public Camera Camera
{
get { return _debugCamera; }
}
}
}

View File

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

View File

@@ -0,0 +1,171 @@
namespace SRDebugger.Services.Implementation
{
using System;
using Internal;
using SRF;
using SRF.Service;
using UI;
using UnityEngine;
[Service(typeof (IDebugPanelService))]
public class DebugPanelServiceImpl : ScriptableObject, IDebugPanelService, IDisposable
{
private DebugPanelRoot _debugPanelRootObject;
public event Action<IDebugPanelService, bool> VisibilityChanged;
private bool _isVisible;
private bool? _cursorWasVisible;
private CursorLockMode? _cursorLockMode;
public DebugPanelRoot RootObject
{
get { return _debugPanelRootObject; }
}
public bool IsLoaded
{
get { return _debugPanelRootObject != null; }
}
public bool IsVisible
{
get { return IsLoaded && _isVisible; }
set
{
if (_isVisible == value)
{
return;
}
if (value)
{
if (!IsLoaded)
{
Load();
}
SRDebuggerUtil.EnsureEventSystemExists();
_debugPanelRootObject.CanvasGroup.alpha = 1.0f;
_debugPanelRootObject.CanvasGroup.interactable = true;
_debugPanelRootObject.CanvasGroup.blocksRaycasts = true;
_cursorWasVisible = Cursor.visible;
_cursorLockMode = Cursor.lockState;
foreach (var c in _debugPanelRootObject.GetComponentsInChildren<Canvas>())
{
c.enabled = true;
}
if (Settings.Instance.AutomaticallyShowCursor)
{
Cursor.visible = true;
Cursor.lockState = CursorLockMode.None;
}
}
else
{
if (IsLoaded)
{
_debugPanelRootObject.CanvasGroup.alpha = 0.0f;
_debugPanelRootObject.CanvasGroup.interactable = false;
_debugPanelRootObject.CanvasGroup.blocksRaycasts = false;
foreach (var c in _debugPanelRootObject.GetComponentsInChildren<Canvas>())
{
c.enabled = false;
}
}
if (_cursorWasVisible.HasValue)
{
Cursor.visible = _cursorWasVisible.Value;
_cursorWasVisible = null;
}
if (_cursorLockMode.HasValue)
{
Cursor.lockState = _cursorLockMode.Value;
_cursorLockMode = null;
}
}
_isVisible = value;
if (VisibilityChanged != null)
{
VisibilityChanged(this, _isVisible);
}
}
}
public DefaultTabs? ActiveTab
{
get
{
if (_debugPanelRootObject == null)
{
return null;
}
return _debugPanelRootObject.TabController.ActiveTab;
}
}
public void OpenTab(DefaultTabs tab)
{
if (!IsVisible)
{
IsVisible = true;
}
_debugPanelRootObject.TabController.OpenTab(tab);
}
public void Unload()
{
if (_debugPanelRootObject == null)
{
return;
}
IsVisible = false;
_debugPanelRootObject.CachedGameObject.SetActive(false);
Destroy(_debugPanelRootObject.CachedGameObject);
_debugPanelRootObject = null;
}
private void Load()
{
var prefab = Resources.Load<DebugPanelRoot>(SRDebugPaths.DebugPanelPrefabPath);
if (prefab == null)
{
Debug.LogError("[SRDebugger] Error loading debug panel prefab");
return;
}
_debugPanelRootObject = SRInstantiate.Instantiate(prefab);
_debugPanelRootObject.name = "Panel";
DontDestroyOnLoad(_debugPanelRootObject);
_debugPanelRootObject.CachedTransform.SetParent(Hierarchy.Get("SRDebugger"), true);
SRDebuggerUtil.EnsureEventSystemExists();
}
public void Dispose()
{
if (_debugPanelRootObject != null)
{
DestroyImmediate(_debugPanelRootObject.gameObject);
}
}
}
}

View File

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

View File

@@ -0,0 +1,225 @@
namespace SRDebugger.Services.Implementation
{
using System;
using Internal;
using SRF;
using SRF.Service;
using UI.Other;
using UnityEngine;
[Service(typeof (IDebugTriggerService))]
public class DebugTriggerImpl : SRServiceBase<IDebugTriggerService>, IDebugTriggerService
{
private PinAlignment _position;
private TriggerRoot _trigger;
private IConsoleService _consoleService;
private bool _showErrorNotification;
public bool IsEnabled
{
get { return _trigger != null && _trigger.CachedGameObject.activeSelf; }
set
{
// Create trigger if it does not yet exist
if (value && _trigger == null)
{
CreateTrigger();
}
if (_trigger != null)
{
_trigger.CachedGameObject.SetActive(value);
}
}
}
public bool ShowErrorNotification
{
get
{
return _showErrorNotification;
}
set
{
if (_showErrorNotification == value) return;
_showErrorNotification = value;
if (_trigger == null) return;
if(_showErrorNotification)
{
_consoleService = SRServiceManager.GetService<IConsoleService>();
_consoleService.Error += OnError;
}
else
{
_consoleService.Error -= OnError;
_consoleService = null;
}
}
}
public PinAlignment Position
{
get { return _position; }
set
{
if (_trigger != null)
{
SetTriggerPosition(_trigger.TriggerTransform, value);
}
_position = value;
}
}
protected override void Awake()
{
base.Awake();
DontDestroyOnLoad(CachedGameObject);
CachedTransform.SetParent(Hierarchy.Get("SRDebugger"), true);
ShowErrorNotification = Settings.Instance.ErrorNotification;
name = "Trigger";
}
private void OnError(IConsoleService console)
{
if (_trigger != null)
{
_trigger.ErrorNotifier.ShowErrorWarning();
}
}
private void CreateTrigger()
{
var prefab = Resources.Load<TriggerRoot>(SRDebugPaths.TriggerPrefabPath);
if (prefab == null)
{
Debug.LogError("[SRDebugger] Error loading trigger prefab");
return;
}
_trigger = SRInstantiate.Instantiate(prefab);
_trigger.CachedTransform.SetParent(CachedTransform, true);
SetTriggerPosition(_trigger.TriggerTransform, _position);
switch (Settings.Instance.TriggerBehaviour)
{
case Settings.TriggerBehaviours.TripleTap:
{
_trigger.TripleTapButton.onClick.AddListener(OnTriggerButtonClick);
_trigger.TapHoldButton.gameObject.SetActive(false);
break;
}
case Settings.TriggerBehaviours.TapAndHold:
{
_trigger.TapHoldButton.onLongPress.AddListener(OnTriggerButtonClick);
_trigger.TripleTapButton.gameObject.SetActive(false);
break;
}
case Settings.TriggerBehaviours.DoubleTap:
{
_trigger.TripleTapButton.RequiredTapCount = 2;
_trigger.TripleTapButton.onClick.AddListener(OnTriggerButtonClick);
_trigger.TapHoldButton.gameObject.SetActive(false);
break;
}
default:
throw new Exception("Unhandled TriggerBehaviour");
}
SRDebuggerUtil.EnsureEventSystemExists();
UnityEngine.SceneManagement.SceneManager.activeSceneChanged += OnActiveSceneChanged;
if (_showErrorNotification)
{
_consoleService = SRServiceManager.GetService<IConsoleService>();
_consoleService.Error += OnError;
}
}
protected override void OnDestroy()
{
UnityEngine.SceneManagement.SceneManager.activeSceneChanged -= OnActiveSceneChanged;
if (_consoleService != null)
{
_consoleService.Error -= OnError;
}
base.OnDestroy();
}
private static void OnActiveSceneChanged(UnityEngine.SceneManagement.Scene s1, UnityEngine.SceneManagement.Scene s2)
{
SRDebuggerUtil.EnsureEventSystemExists();
}
private void OnTriggerButtonClick()
{
if (_trigger.ErrorNotifier.IsVisible)
{
// Open into console if there is an error.
SRDebug.Instance.ShowDebugPanel(DefaultTabs.Console);
}
else
{
SRDebug.Instance.ShowDebugPanel();
}
}
private static void SetTriggerPosition(RectTransform t, PinAlignment position)
{
var pivotX = 0f;
var pivotY = 0f;
var posX = 0f;
var posY = 0f;
if (position == PinAlignment.TopLeft || position == PinAlignment.TopRight || position == PinAlignment.TopCenter)
{
pivotY = 1f;
posY = 1f;
}
else if (position == PinAlignment.BottomLeft || position == PinAlignment.BottomRight || position == PinAlignment.BottomCenter)
{
pivotY = 0f;
posY = 0f;
} else if (position == PinAlignment.CenterLeft || position == PinAlignment.CenterRight)
{
pivotY = 0.5f;
posY = 0.5f;
}
if (position == PinAlignment.TopLeft || position == PinAlignment.BottomLeft || position == PinAlignment.CenterLeft)
{
pivotX = 0f;
posX = 0f;
}
else if (position == PinAlignment.TopRight || position == PinAlignment.BottomRight || position == PinAlignment.CenterRight)
{
pivotX = 1f;
posX = 1f;
} else if (position == PinAlignment.TopCenter || position == PinAlignment.BottomCenter)
{
pivotX = 0.5f;
posX = 0.5f;
}
t.pivot = new Vector2(pivotX, pivotY);
t.anchorMax = t.anchorMin = new Vector2(posX, posY);
}
}
}

View File

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

View File

@@ -0,0 +1,148 @@
namespace SRDebugger.Services.Implementation
{
using Internal;
using SRF.Service;
using UI.Other;
using UnityEngine;
[Service(typeof (IDockConsoleService))]
public class DockConsoleServiceImpl : IDockConsoleService
{
private ConsoleAlignment _alignment;
private DockConsoleController _consoleRoot;
private bool _didSuspendTrigger;
private bool _isExpanded = true;
private bool _isVisible;
public DockConsoleServiceImpl()
{
_alignment = Settings.Instance.ConsoleAlignment;
}
public bool IsVisible
{
get { return _isVisible; }
set
{
if (value == _isVisible)
{
return;
}
_isVisible = value;
if (_consoleRoot == null && value)
{
Load();
}
else
{
_consoleRoot.CachedGameObject.SetActive(value);
}
CheckTrigger();
}
}
public bool IsExpanded
{
get { return _isExpanded; }
set
{
if (value == _isExpanded)
{
return;
}
_isExpanded = value;
if (_consoleRoot == null && value)
{
Load();
}
else
{
_consoleRoot.SetDropdownVisibility(value);
}
CheckTrigger();
}
}
public ConsoleAlignment Alignment
{
get { return _alignment; }
set
{
_alignment = value;
if (_consoleRoot != null)
{
_consoleRoot.SetAlignmentMode(value);
}
CheckTrigger();
}
}
private void Load()
{
var dockService = SRServiceManager.GetService<IPinnedUIService>();
if (dockService == null)
{
Debug.LogError("[DockConsoleService] PinnedUIService not found");
return;
}
var pinService = dockService as PinnedUIServiceImpl;
if (pinService == null)
{
Debug.LogError("[DockConsoleService] Expected IPinnedUIService to be PinnedUIServiceImpl");
return;
}
_consoleRoot = pinService.DockConsoleController;
_consoleRoot.SetDropdownVisibility(_isExpanded);
_consoleRoot.IsVisible = _isVisible;
_consoleRoot.SetAlignmentMode(_alignment);
CheckTrigger();
}
private void CheckTrigger()
{
ConsoleAlignment? triggerAlignment = null;
var pinAlignment = Service.Trigger.Position;
if (pinAlignment == PinAlignment.TopLeft ||
pinAlignment == PinAlignment.TopRight || pinAlignment == PinAlignment.TopCenter)
{
triggerAlignment = ConsoleAlignment.Top;
} else if (pinAlignment == PinAlignment.BottomLeft ||
pinAlignment == PinAlignment.BottomRight ||
pinAlignment == PinAlignment.BottomCenter)
{
triggerAlignment = ConsoleAlignment.Bottom;
}
var shouldHide = triggerAlignment.HasValue && IsVisible && Alignment == triggerAlignment.Value;
// Show trigger if we have hidden it, and we no longer need to hide it.
if (_didSuspendTrigger && !shouldHide)
{
Service.Trigger.IsEnabled = true;
_didSuspendTrigger = false;
}
else if (Service.Trigger.IsEnabled && shouldHide)
{
Service.Trigger.IsEnabled = false;
_didSuspendTrigger = true;
}
}
}
}

View File

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

View File

@@ -0,0 +1,265 @@

namespace SRDebugger.Services.Implementation
{
using System.Collections.Generic;
using Internal;
using SRF;
using SRF.Service;
using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
#endif
[Service(typeof (KeyboardShortcutListenerService))]
public class KeyboardShortcutListenerService : SRServiceBase<KeyboardShortcutListenerService>
{
private List<Settings.KeyboardShortcut> _shortcuts;
protected override void Awake()
{
base.Awake();
CachedTransform.SetParent(Hierarchy.Get("SRDebugger"));
_shortcuts = new List<Settings.KeyboardShortcut>(Settings.Instance.KeyboardShortcuts);
#if ENABLE_INPUT_SYSTEM
foreach (var s in _shortcuts)
{
// Cache the actual keycode so we don't have to use strings each time we want to use it.
string keyName = s.Key.ToString();
KeyControl keyControl = Keyboard.current[keyName] as KeyControl;
if (keyControl == null)
{
Debug.LogErrorFormat(
"[SRDebugger] Input System: Unable to find shortcut key: {0}. Shortcut ({1}) will not be functional.",
keyName, s.Action);
s.Cached_KeyCode = Key.None;
}
// Find the index for this key control
for (var index = 0; index < Keyboard.current.allKeys.Count; index++)
{
if (Keyboard.current.allKeys[index] == keyControl)
{
s.Cached_KeyCode = (Key) (index + 1);
break;
}
}
}
#endif
}
private void ToggleTab(DefaultTabs t)
{
var activeTab = Service.Panel.ActiveTab;
if (Service.Panel.IsVisible && activeTab.HasValue && activeTab.Value == t)
{
SRDebug.Instance.HideDebugPanel();
}
else
{
SRDebug.Instance.ShowDebugPanel(t);
}
}
private void ExecuteShortcut(Settings.KeyboardShortcut shortcut)
{
switch (shortcut.Action)
{
case Settings.ShortcutActions.OpenSystemInfoTab:
ToggleTab(DefaultTabs.SystemInformation);
break;
case Settings.ShortcutActions.OpenConsoleTab:
ToggleTab(DefaultTabs.Console);
break;
case Settings.ShortcutActions.OpenOptionsTab:
ToggleTab(DefaultTabs.Options);
break;
case Settings.ShortcutActions.OpenProfilerTab:
ToggleTab(DefaultTabs.Profiler);
break;
case Settings.ShortcutActions.OpenBugReporterTab:
ToggleTab(DefaultTabs.BugReporter);
break;
case Settings.ShortcutActions.ClosePanel:
SRDebug.Instance.HideDebugPanel();
break;
case Settings.ShortcutActions.OpenPanel:
SRDebug.Instance.ShowDebugPanel();
break;
case Settings.ShortcutActions.TogglePanel:
if (SRDebug.Instance.IsDebugPanelVisible)
{
SRDebug.Instance.HideDebugPanel();
}
else
{
SRDebug.Instance.ShowDebugPanel();
}
break;
case Settings.ShortcutActions.ShowBugReportPopover:
SRDebug.Instance.ShowBugReportSheet();
break;
case Settings.ShortcutActions.ToggleDockedConsole:
SRDebug.Instance.DockConsole.IsVisible = !SRDebug.Instance.DockConsole.IsVisible;
break;
case Settings.ShortcutActions.ToggleDockedProfiler:
SRDebug.Instance.IsProfilerDocked = !SRDebug.Instance.IsProfilerDocked;
break;
default:
Debug.LogWarning("[SRDebugger] Unhandled keyboard shortcut: " + shortcut.Action);
break;
}
}
protected override void Update()
{
base.Update();
#if ENABLE_INPUT_SYSTEM && ENABLE_LEGACY_INPUT_MANAGER
switch (Settings.Instance.UIInputMode)
{
case Settings.UIModes.NewInputSystem:
UpdateInputSystem();
break;
case Settings.UIModes.LegacyInputSystem:
UpdateLegacyInputSystem();
break;
}
#elif ENABLE_INPUT_SYSTEM
UpdateInputSystem();
#elif ENABLE_LEGACY_INPUT_MANAGER || (!ENABLE_INPUT_SYSTEM && !UNITY_2019_3_OR_NEWER)
UpdateLegacyInputSystem();
#endif
}
#if ENABLE_INPUT_SYSTEM
private void UpdateInputSystem()
{
var keyboard = Keyboard.current;
if (Settings.Instance.KeyboardEscapeClose && keyboard.escapeKey.isPressed && Service.Panel.IsVisible)
{
SRDebug.Instance.HideDebugPanel();
}
var ctrl = keyboard.leftCtrlKey.isPressed || keyboard.rightCtrlKey.isPressed;
var alt = keyboard.leftAltKey.isPressed || keyboard.rightAltKey.isPressed;
var shift = keyboard.leftShiftKey.isPressed || keyboard.rightShiftKey.isPressed;
for (var i = 0; i < _shortcuts.Count; i++)
{
var s = _shortcuts[i];
if (s.Control && !ctrl)
{
continue;
}
if (s.Shift && !shift)
{
continue;
}
if (s.Alt && !alt)
{
continue;
}
if (!s.Cached_KeyCode.HasValue)
{
continue; // We can't use this shortcut since we didn't find the keycode.
}
if (keyboard[s.Cached_KeyCode.Value].wasPressedThisFrame)
{
ExecuteShortcut(s);
break;
}
}
}
#endif
#if ENABLE_LEGACY_INPUT_MANAGER || (!ENABLE_INPUT_SYSTEM && !UNITY_2019_3_OR_NEWER)
private void UpdateLegacyInputSystem()
{
if (Settings.Instance.KeyboardEscapeClose && Input.GetKeyDown(KeyCode.Escape) && Service.Panel.IsVisible)
{
SRDebug.Instance.HideDebugPanel();
}
var ctrl = Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl);
var alt = Input.GetKey(KeyCode.LeftAlt) || Input.GetKey(KeyCode.RightAlt);
var shift = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
for (var i = 0; i < _shortcuts.Count; i++)
{
var s = _shortcuts[i];
if (s.Control && !ctrl)
{
continue;
}
if (s.Shift && !shift)
{
continue;
}
if (s.Alt && !alt)
{
continue;
}
if (Input.GetKeyDown(s.Key))
{
ExecuteShortcut(s);
break;
}
}
}
#endif
}
}

View File

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

View File

@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using SRDebugger.Internal;
namespace SRDebugger.Services.Implementation
{
public sealed partial class OptionsServiceImpl
{
/// <summary>
/// Options container that is implemented via reflection.
/// This is the normal behaviour used when options container is added as an `object`.
/// </summary>
private class ReflectionOptionContainer : IOptionContainer
{
// Options don't change, so just leave stubs that do nothing.
public event Action<OptionDefinition> OptionAdded
{
add { }
remove { }
}
public event Action<OptionDefinition> OptionRemoved
{
add { }
remove { }
}
public bool IsDynamic
{
get { return false; }
}
private List<OptionDefinition> Options
{
get
{
if (_options == null) _options = SRDebuggerUtil.ScanForOptions(_target);
return _options;
}
}
private List<OptionDefinition> _options;
public IEnumerable<OptionDefinition> GetOptions()
{
return Options;
}
private readonly object _target;
public ReflectionOptionContainer(object target)
{
_target = target;
}
protected bool Equals(ReflectionOptionContainer other)
{
return Equals(other._target, this._target);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((ReflectionOptionContainer) obj);
}
public override int GetHashCode()
{
return _target.GetHashCode();
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3343cb41b53a47568cb627f032f95dd7
timeCreated: 1609341203

View File

@@ -0,0 +1,185 @@
namespace SRDebugger.Services.Implementation
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Internal;
using SRF.Service;
using SRF.Helpers;
using UnityEngine;
[Service(typeof (IOptionsService))]
public partial class OptionsServiceImpl : IOptionsService
{
public event EventHandler OptionsUpdated;
public ICollection<OptionDefinition> Options
{
get { return _optionsReadonly; }
}
private void OptionsContainerOnOptionAdded(IOptionContainer container, OptionDefinition optionDefinition)
{
List<OptionDefinition> options;
if(!_optionContainerLookup.TryGetValue(container, out options))
{
Debug.LogWarning("[SRDebugger] Received event from unknown option container.");
return;
}
if (options.Contains(optionDefinition))
{
Debug.LogWarning("[SRDebugger] Received option added event from option container, but option has already been added.");
return;
}
options.Add(optionDefinition);
_options.Add(optionDefinition);
OnOptionsUpdated();
}
private void OptionsContainerOnOptionRemoved(IOptionContainer container, OptionDefinition optionDefinition)
{
List<OptionDefinition> options;
if (!_optionContainerLookup.TryGetValue(container, out options))
{
Debug.LogWarning("[SRDebugger] Received event from unknown option container.");
return;
}
if (options.Remove(optionDefinition))
{
_options.Remove(optionDefinition);
OnOptionsUpdated();
}
else
{
Debug.LogWarning("[SRDebugger] Received option removed event from option container, but option does not exist.");
}
}
private readonly Dictionary<IOptionContainer, List<OptionDefinition>> _optionContainerLookup = new Dictionary<IOptionContainer, List<OptionDefinition>>();
private readonly Dictionary<IOptionContainer, OptionContainerEventHandler> _optionContainerEventHandlerLookup = new Dictionary<IOptionContainer, OptionContainerEventHandler>();
private readonly List<OptionDefinition> _options = new List<OptionDefinition>();
private readonly IList<OptionDefinition> _optionsReadonly;
public OptionsServiceImpl()
{
_optionsReadonly = new ReadOnlyCollection<OptionDefinition>(_options);
}
public void Scan(object obj)
{
AddContainer(obj);
}
public void AddContainer(object obj)
{
var container = obj as IOptionContainer ?? new ReflectionOptionContainer(obj);
AddContainer(container);
}
public void AddContainer(IOptionContainer optionContainer)
{
if (_optionContainerLookup.ContainsKey(optionContainer))
{
throw new Exception("An options container should only be added once.");
}
List<OptionDefinition> options = new List<OptionDefinition>();
options.AddRange(optionContainer.GetOptions());
_optionContainerLookup.Add(optionContainer, options);
if (optionContainer.IsDynamic)
{
var handler = new OptionContainerEventHandler(this, optionContainer);
_optionContainerEventHandlerLookup.Add(optionContainer, handler);
}
if (options.Count > 0)
{
_options.AddRange(options);
OnOptionsUpdated();
}
}
public void RemoveContainer(object obj)
{
var container = obj as IOptionContainer ?? new ReflectionOptionContainer(obj);
RemoveContainer(container);
}
public void RemoveContainer(IOptionContainer optionContainer)
{
if (!_optionContainerLookup.ContainsKey(optionContainer))
{
return;
}
bool isDirty = false;
var list = _optionContainerLookup[optionContainer];
_optionContainerLookup.Remove(optionContainer);
foreach (var op in list)
{
_options.Remove(op);
isDirty = true;
}
OptionContainerEventHandler handler;
if (_optionContainerEventHandlerLookup.TryGetValue(optionContainer,
out handler))
{
handler.Dispose();
_optionContainerEventHandlerLookup.Remove(optionContainer);
}
if (isDirty)
{
OnOptionsUpdated();
}
}
private void OnOptionsUpdated()
{
if (OptionsUpdated != null)
{
OptionsUpdated(this, EventArgs.Empty);
}
}
class OptionContainerEventHandler : IDisposable
{
private readonly OptionsServiceImpl _service;
private readonly IOptionContainer _container;
public OptionContainerEventHandler(OptionsServiceImpl service, IOptionContainer container)
{
_container = container;
_service = service;
container.OptionAdded += ContainerOnOptionAdded;
container.OptionRemoved += ContainerOnOptionRemoved;
}
private void ContainerOnOptionAdded(OptionDefinition obj)
{
_service.OptionsContainerOnOptionAdded(_container, obj);
}
private void ContainerOnOptionRemoved(OptionDefinition obj)
{
_service.OptionsContainerOnOptionRemoved(_container, obj);
}
public void Dispose()
{
_container.OptionAdded -= ContainerOnOptionAdded;
_container.OptionRemoved -= ContainerOnOptionRemoved;
}
}
}
}

View File

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

View File

@@ -0,0 +1,129 @@
namespace SRDebugger.Services.Implementation
{
using System;
using System.Collections.Generic;
using System.Linq;
using Internal;
using SRF;
using SRF.Service;
using UI.Controls;
using UnityEngine;
[Service(typeof (IPinEntryService))]
public class PinEntryServiceImpl : SRServiceBase<IPinEntryService>, IPinEntryService
{
private PinEntryCompleteCallback _callback;
private bool _isVisible;
private PinEntryControl _pinControl;
private readonly List<int> _requiredPin = new List<int>(4);
public bool IsShowingKeypad
{
get { return _isVisible; }
}
public void ShowPinEntry(IReadOnlyList<int> requiredPin, string message, PinEntryCompleteCallback callback,
bool allowCancel = true)
{
if (_isVisible)
{
throw new InvalidOperationException("Pin entry is already in progress");
}
VerifyPin(requiredPin);
if (_pinControl == null)
{
Load();
}
if (_pinControl == null)
{
Debug.LogWarning("[PinEntry] Pin entry failed loading, executing callback with fail result");
callback(false);
return;
}
_pinControl.Clear();
_pinControl.PromptText.text = message;
_pinControl.CanCancel = allowCancel;
_callback = callback;
_requiredPin.Clear();
_requiredPin.AddRange(requiredPin);
_pinControl.Show();
_isVisible = true;
SRDebuggerUtil.EnsureEventSystemExists();
}
protected override void Awake()
{
base.Awake();
CachedTransform.SetParent(Hierarchy.Get("SRDebugger"));
}
private void Load()
{
var prefab = Resources.Load<PinEntryControl>(SRDebugPaths.PinEntryPrefabPath);
if (prefab == null)
{
Debug.LogError("[PinEntry] Unable to load pin entry prefab");
return;
}
_pinControl = SRInstantiate.Instantiate(prefab);
_pinControl.CachedTransform.SetParent(CachedTransform, false);
_pinControl.Hide();
_pinControl.Complete += PinControlOnComplete;
}
private void PinControlOnComplete(IList<int> result, bool didCancel)
{
var isValid = _requiredPin.SequenceEqual(result);
if (!didCancel && !isValid)
{
_pinControl.Clear();
_pinControl.PlayInvalidCodeAnimation();
return;
}
_isVisible = false;
_pinControl.Hide();
if (didCancel)
{
_callback(false);
return;
}
_callback(isValid);
}
private void VerifyPin(IReadOnlyList<int> pin)
{
if (pin.Count != 4)
{
throw new ArgumentException("Pin list must have 4 elements");
}
for (var i = 0; i < pin.Count; i++)
{
if (pin[i] < 0 || pin[i] > 9)
{
throw new ArgumentException("Pin numbers must be >= 0 && <= 9");
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,271 @@
namespace SRDebugger.Services.Implementation
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using Internal;
using SRF;
using SRF.Service;
using UI.Controls;
using UI.Other;
using UnityEngine;
[Service(typeof (IPinnedUIService))]
public class PinnedUIServiceImpl : SRServiceBase<IPinnedUIService>, IPinnedUIService
{
private readonly List<OptionsControlBase> _controlList = new List<OptionsControlBase>();
private readonly Dictionary<OptionDefinition, OptionsControlBase> _pinnedObjects =
new Dictionary<OptionDefinition, OptionsControlBase>();
private bool _queueRefresh;
private PinnedUIRoot _uiRoot;
public DockConsoleController DockConsoleController
{
get
{
if (_uiRoot == null)
{
Load();
}
return _uiRoot.DockConsoleController;
}
}
public event Action<OptionDefinition, bool> OptionPinStateChanged;
public event Action<RectTransform> OptionsCanvasCreated;
public bool IsProfilerPinned
{
get
{
if (_uiRoot == null)
{
return false;
}
return _uiRoot.Profiler.activeSelf;
}
set
{
if (_uiRoot == null)
{
Load();
}
_uiRoot.Profiler.SetActive(value);
}
}
public void Pin(OptionDefinition obj, int order = -1)
{
if (_uiRoot == null)
{
Load();
}
if (_pinnedObjects.ContainsKey(obj))
{
return;
}
var control = OptionControlFactory.CreateControl(obj);
control.CachedTransform.SetParent(_uiRoot.Container, false);
if (order >= 0)
{
control.CachedTransform.SetSiblingIndex(order);
}
_pinnedObjects.Add(obj, control);
_controlList.Add(control);
OnPinnedStateChanged(obj, true);
}
public void Unpin(OptionDefinition obj)
{
if (!_pinnedObjects.ContainsKey(obj))
{
return;
}
var control = _pinnedObjects[obj];
_pinnedObjects.Remove(obj);
_controlList.Remove(control);
Destroy(control.CachedGameObject);
OnPinnedStateChanged(obj, false);
}
private void OnPinnedStateChanged(OptionDefinition option, bool isPinned)
{
if (OptionPinStateChanged != null)
{
OptionPinStateChanged(option, isPinned);
}
}
public void UnpinAll()
{
foreach (var op in _pinnedObjects)
{
Destroy(op.Value.CachedGameObject);
}
_pinnedObjects.Clear();
_controlList.Clear();
}
public bool HasPinned(OptionDefinition option)
{
return _pinnedObjects.ContainsKey(option);
}
protected override void Awake()
{
base.Awake();
CachedTransform.SetParent(Hierarchy.Get("SRDebugger"));
}
private void Load()
{
var prefab = Resources.Load<PinnedUIRoot>(SRDebugPaths.PinnedUIPrefabPath);
if (prefab == null)
{
Debug.LogError("[SRDebugger.PinnedUI] Error loading ui prefab");
return;
}
var instance = SRInstantiate.Instantiate(prefab);
instance.CachedTransform.SetParent(CachedTransform, false);
_uiRoot = instance;
UpdateAnchors();
SRDebug.Instance.PanelVisibilityChanged += OnDebugPanelVisibilityChanged;
Service.Options.OptionsUpdated += OnOptionsUpdated;
if (OptionsCanvasCreated != null)
{
OptionsCanvasCreated(_uiRoot.Canvas.GetComponent<RectTransform>());
}
}
private void UpdateAnchors()
{
// Setup alignment of Profiler/Options splitter
switch (Settings.Instance.ProfilerAlignment)
{
case PinAlignment.BottomLeft:
case PinAlignment.TopLeft:
case PinAlignment.CenterLeft:
_uiRoot.Profiler.transform.SetSiblingIndex(0);
break;
case PinAlignment.BottomRight:
case PinAlignment.TopRight:
case PinAlignment.CenterRight:
_uiRoot.Profiler.transform.SetSiblingIndex(1);
break;
}
// Setup alignment of Profiler vertical layout group
switch (Settings.Instance.ProfilerAlignment)
{
case PinAlignment.TopRight:
case PinAlignment.TopLeft:
_uiRoot.ProfilerVerticalLayoutGroup.childAlignment = TextAnchor.UpperCenter;
break;
case PinAlignment.BottomRight:
case PinAlignment.BottomLeft:
_uiRoot.ProfilerVerticalLayoutGroup.childAlignment = TextAnchor.LowerCenter;
break;
case PinAlignment.CenterLeft:
case PinAlignment.CenterRight:
_uiRoot.ProfilerVerticalLayoutGroup.childAlignment = TextAnchor.MiddleCenter;
break;
}
_uiRoot.ProfilerHandleManager.SetAlignment(Settings.Instance.ProfilerAlignment);
// Setup alignment of options flow layout group
switch (Settings.Instance.OptionsAlignment)
{
case PinAlignment.BottomLeft: // OptionsBottomLeft
_uiRoot.OptionsLayoutGroup.childAlignment = TextAnchor.LowerLeft;
break;
case PinAlignment.TopLeft:
_uiRoot.OptionsLayoutGroup.childAlignment = TextAnchor.UpperLeft;
break;
case PinAlignment.BottomRight:
_uiRoot.OptionsLayoutGroup.childAlignment = TextAnchor.LowerRight;
break;
case PinAlignment.TopRight:
_uiRoot.OptionsLayoutGroup.childAlignment = TextAnchor.UpperRight;
break;
case PinAlignment.BottomCenter:
_uiRoot.OptionsLayoutGroup.childAlignment = TextAnchor.LowerCenter;
break;
case PinAlignment.TopCenter:
_uiRoot.OptionsLayoutGroup.childAlignment = TextAnchor.UpperCenter;
break;
case PinAlignment.CenterLeft:
_uiRoot.OptionsLayoutGroup.childAlignment = TextAnchor.MiddleLeft;
break;
case PinAlignment.CenterRight:
_uiRoot.OptionsLayoutGroup.childAlignment = TextAnchor.MiddleRight;
break;
}
}
protected override void Update()
{
base.Update();
if (_queueRefresh)
{
_queueRefresh = false;
Refresh();
}
}
private void OnOptionsUpdated(object sender, EventArgs eventArgs)
{
// Check for removed options.
var pinned = _pinnedObjects.Keys.ToList();
foreach (var op in pinned)
{
if (!Service.Options.Options.Contains(op))
{
Unpin(op);
}
}
}
private void OnDebugPanelVisibilityChanged(bool isVisible)
{
// Refresh bindings when debug panel is no longer visible
if (!isVisible)
{
_queueRefresh = true;
}
}
private void Refresh()
{
for (var i = 0; i < _controlList.Count; i++)
{
_controlList[i].Refresh();
}
}
}
}

View File

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

View File

@@ -0,0 +1,382 @@
namespace SRDebugger.Services.Implementation
{
using System;
using Internal;
using SRF;
using SRF.Service;
using UnityEngine;
using Object = UnityEngine.Object;
using SRF.UI;
using UnityEngine.UI;
[Service(typeof (IDebugService))]
public class SRDebugService : IDebugService
{
public IDockConsoleService DockConsole
{
get { return Service.DockConsole; }
}
public IConsoleFilterState ConsoleFilter
{
get
{
if (_consoleFilterState == null)
{
_consoleFilterState = SRServiceManager.GetService<IConsoleFilterState>();
}
return _consoleFilterState;
}
}
public event VisibilityChangedDelegate PanelVisibilityChanged;
public event PinnedUiCanvasCreated PinnedUiCanvasCreated;
private readonly IDebugPanelService _debugPanelService;
private readonly IDebugTriggerService _debugTrigger;
private readonly ISystemInformationService _informationService;
private readonly IOptionsService _optionsService;
private readonly IPinnedUIService _pinnedUiService;
private IConsoleFilterState _consoleFilterState;
private EntryCode? _entryCode;
private bool _hasAuthorised;
private DefaultTabs? _queuedTab;
private RectTransform _worldSpaceTransform;
private DynamicOptionContainer _looseOptionContainer;
public SRDebugService()
{
SRServiceManager.RegisterService<IDebugService>(this);
// Load profiler
SRServiceManager.GetService<IProfilerService>();
// Setup trigger service
_debugTrigger = SRServiceManager.GetService<IDebugTriggerService>();
_informationService = SRServiceManager.GetService<ISystemInformationService>();
_pinnedUiService = SRServiceManager.GetService<IPinnedUIService>();
_pinnedUiService.OptionsCanvasCreated += transform =>
{
if (PinnedUiCanvasCreated == null) return;
try
{
PinnedUiCanvasCreated(transform);
}
catch(Exception e)
{
Debug.LogException(e);
}
};
_optionsService = SRServiceManager.GetService<IOptionsService>();
// Create debug panel service (this does not actually load any UI resources until opened)
_debugPanelService = SRServiceManager.GetService<IDebugPanelService>();
// Subscribe to visibility changes to provide API-facing event for panel open/close
_debugPanelService.VisibilityChanged += DebugPanelServiceOnVisibilityChanged;
_debugTrigger.IsEnabled = Settings.EnableTrigger == Settings.TriggerEnableModes.Enabled ||
Settings.EnableTrigger == Settings.TriggerEnableModes.MobileOnly && Application.isMobilePlatform ||
Settings.EnableTrigger == Settings.TriggerEnableModes.DevelopmentBuildsOnly && Debug.isDebugBuild;
_debugTrigger.Position = Settings.TriggerPosition;
if (Settings.EnableKeyboardShortcuts)
{
SRServiceManager.GetService<KeyboardShortcutListenerService>();
}
if (Settings.Instance.RequireCode)
{
if (Settings.Instance.EntryCode.Count != 4)
{
Debug.LogError("[SRDebugger] RequireCode is enabled, but pin is not 4 digits");
}
else
{
_entryCode = new EntryCode(Settings.Instance.EntryCode[0], Settings.Instance.EntryCode[1],
Settings.Instance.EntryCode[2], Settings.Instance.EntryCode[3]);
}
}
// Ensure that root object cannot be destroyed on scene loads
var srDebuggerParent = Hierarchy.Get("SRDebugger");
Object.DontDestroyOnLoad(srDebuggerParent.gameObject);
// Add any options containers that were created on init
var internalRegistry = SRServiceManager.GetService<InternalOptionsRegistry>();
internalRegistry.SetHandler(_optionsService.AddContainer);
}
public Settings Settings
{
get { return Settings.Instance; }
}
public bool IsDebugPanelVisible
{
get { return _debugPanelService.IsVisible; }
}
public bool IsTriggerEnabled
{
get { return _debugTrigger.IsEnabled; }
set { _debugTrigger.IsEnabled = value; }
}
public bool IsTriggerErrorNotificationEnabled
{
get { return _debugTrigger.ShowErrorNotification; }
set { _debugTrigger.ShowErrorNotification = value; }
}
public bool IsProfilerDocked
{
get { return Service.PinnedUI.IsProfilerPinned; }
set { Service.PinnedUI.IsProfilerPinned = value; }
}
public void AddSystemInfo(InfoEntry entry, string category = "Default")
{
_informationService.Add(entry, category);
}
public void ShowDebugPanel(bool requireEntryCode = true)
{
if (requireEntryCode && _entryCode.HasValue && !_hasAuthorised)
{
PromptEntryCode();
return;
}
_debugPanelService.IsVisible = true;
}
public void ShowDebugPanel(DefaultTabs tab, bool requireEntryCode = true)
{
if (requireEntryCode && _entryCode.HasValue && !_hasAuthorised)
{
_queuedTab = tab;
PromptEntryCode();
return;
}
_debugPanelService.IsVisible = true;
_debugPanelService.OpenTab(tab);
}
public void HideDebugPanel()
{
_debugPanelService.IsVisible = false;
}
public void SetEntryCode(EntryCode newCode)
{
_hasAuthorised = false;
_entryCode = newCode;
}
public void DisableEntryCode()
{
_entryCode = null;
}
public void DestroyDebugPanel()
{
_debugPanelService.IsVisible = false;
_debugPanelService.Unload();
}
#region Options
public void AddOptionContainer(object container)
{
_optionsService.AddContainer(container);
}
public void RemoveOptionContainer(object container)
{
_optionsService.RemoveContainer(container);
}
public void AddOption(OptionDefinition option)
{
if(_looseOptionContainer == null)
{
_looseOptionContainer = new DynamicOptionContainer();
_optionsService.AddContainer(_looseOptionContainer);
}
_looseOptionContainer.AddOption(option);
}
public bool RemoveOption(OptionDefinition option)
{
if (_looseOptionContainer != null)
{
return _looseOptionContainer.RemoveOption(option);
}
return false;
}
public void PinAllOptions(string category)
{
foreach (var op in _optionsService.Options)
{
if (op.Category == category)
{
_pinnedUiService.Pin(op);
}
}
}
public void UnpinAllOptions(string category)
{
foreach (var op in _optionsService.Options)
{
if (op.Category == category)
{
_pinnedUiService.Unpin(op);
}
}
}
public void PinOption(string name)
{
foreach (var op in _optionsService.Options)
{
if (op.Name == name)
{
_pinnedUiService.Pin(op);
}
}
}
public void UnpinOption(string name)
{
foreach (var op in _optionsService.Options)
{
if (op.Name == name)
{
_pinnedUiService.Unpin(op);
}
}
}
public void ClearPinnedOptions()
{
_pinnedUiService.UnpinAll();
}
#endregion
#region Bug Reporter
public void ShowBugReportSheet(ActionCompleteCallback onComplete = null, bool takeScreenshot = true,
string descriptionContent = null)
{
var popoverService = SRServiceManager.GetService<BugReportPopoverService>();
if (popoverService.IsShowingPopover)
{
return;
}
popoverService.ShowBugReporter((succeed, message) =>
{
if (onComplete != null)
{
onComplete(succeed);
}
}, takeScreenshot, descriptionContent);
}
#endregion
private void DebugPanelServiceOnVisibilityChanged(IDebugPanelService debugPanelService, bool b)
{
if (PanelVisibilityChanged == null)
{
return;
}
try
{
PanelVisibilityChanged(b);
}
catch (Exception e)
{
Debug.LogError("[SRDebugger] Event target threw exception (IDebugService.PanelVisiblityChanged)");
Debug.LogException(e);
}
}
private void PromptEntryCode()
{
SRServiceManager.GetService<IPinEntryService>()
.ShowPinEntry(_entryCode.Value, SRDebugStrings.Current.PinEntryPrompt,
entered =>
{
if (entered)
{
if (!Settings.Instance.RequireEntryCodeEveryTime)
{
_hasAuthorised = true;
}
if (_queuedTab.HasValue)
{
var t = _queuedTab.Value;
_queuedTab = null;
ShowDebugPanel(t, false);
}
else
{
ShowDebugPanel(false);
}
}
_queuedTab = null;
});
}
public RectTransform EnableWorldSpaceMode()
{
if (_worldSpaceTransform != null)
{
return _worldSpaceTransform;
}
if (Settings.Instance.UseDebugCamera)
{
throw new InvalidOperationException("UseDebugCamera cannot be enabled at the same time as EnableWorldSpaceMode.");
}
_debugPanelService.IsVisible = true;
var root = ((DebugPanelServiceImpl) _debugPanelService).RootObject;
root.Canvas.gameObject.RemoveComponentIfExists<SRRetinaScaler>();
root.Canvas.gameObject.RemoveComponentIfExists<CanvasScaler>();
root.Canvas.renderMode = RenderMode.WorldSpace;
var rectTransform = root.Canvas.GetComponent<RectTransform>();
rectTransform.sizeDelta = new Vector2(1024, 768);
rectTransform.position = Vector3.zero;
return _worldSpaceTransform = rectTransform;
}
public void SetBugReporterHandler(IBugReporterHandler bugReporterHandler)
{
SRServiceManager.GetService<IBugReportService>().SetHandler(bugReporterHandler);
}
}
}

View File

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

View File

@@ -0,0 +1,210 @@
using System;
using System.Collections.Generic;
namespace SRDebugger.Services.Implementation
{
using SRF.Service;
using UnityEngine;
[Service(typeof (IConsoleService))]
public class StandardConsoleService : IConsoleService, IDisposable
{
private readonly bool _collapseEnabled;
private bool _hasCleared;
private readonly CircularBuffer<ConsoleEntry> _allConsoleEntries;
private CircularBuffer<ConsoleEntry> _consoleEntries;
private readonly object _threadLock = new object();
private ILogHandler _expectedLogHandler;
public StandardConsoleService()
{
Application.logMessageReceivedThreaded += UnityLogCallback;
_expectedLogHandler = Debug.unityLogger.logHandler;
SRServiceManager.RegisterService<IConsoleService>(this);
_collapseEnabled = Settings.Instance.CollapseDuplicateLogEntries;
_allConsoleEntries = new CircularBuffer<ConsoleEntry>(Settings.Instance.MaximumConsoleEntries);
}
public void Dispose()
{
Application.logMessageReceivedThreaded -= UnityLogCallback;
if (_consoleEntries != null)
{
_consoleEntries.Clear();
}
_allConsoleEntries.Clear();
}
public int ErrorCount { get; private set; }
public int WarningCount { get; private set; }
public int InfoCount { get; private set; }
public event ConsoleUpdatedEventHandler Updated;
public event ConsoleUpdatedEventHandler Error;
public bool LoggingEnabled
{
get { return Debug.unityLogger.logEnabled; }
set { Debug.unityLogger.logEnabled = value; }
}
public bool LogHandlerIsOverriden
{
get
{
return Debug.unityLogger.logHandler != _expectedLogHandler;
}
}
public IReadOnlyList<ConsoleEntry> Entries
{
get
{
if (!_hasCleared)
{
return _allConsoleEntries;
}
return _consoleEntries;
}
}
public IReadOnlyList<ConsoleEntry> AllEntries
{
get { return _allConsoleEntries; }
}
public void Clear()
{
lock (_threadLock)
{
_hasCleared = true;
if (_consoleEntries == null)
{
_consoleEntries = new CircularBuffer<ConsoleEntry>(Settings.Instance.MaximumConsoleEntries);
}
else
{
_consoleEntries.Clear();
}
ErrorCount = WarningCount = InfoCount = 0;
}
OnUpdated();
}
protected void OnEntryAdded(ConsoleEntry entry)
{
if (_hasCleared)
{
// Decrement counters if adding this entry will push another
// entry from the buffer.
if (_consoleEntries.IsFull)
{
AdjustCounter(_consoleEntries.Front().LogType, -1);
_consoleEntries.PopFront();
}
_consoleEntries.PushBack(entry);
}
else
{
if (_allConsoleEntries.IsFull)
{
AdjustCounter(_allConsoleEntries.Front().LogType, -1);
_allConsoleEntries.PopFront();
}
}
_allConsoleEntries.PushBack(entry);
OnUpdated();
}
protected void OnEntryDuplicated(ConsoleEntry entry)
{
entry.Count++;
OnUpdated();
// If has cleared, add this entry again for the current list
if (_hasCleared && _consoleEntries.Count == 0)
{
OnEntryAdded(new ConsoleEntry(entry) {Count = 1});
}
}
private void OnUpdated()
{
if (Updated != null)
{
try
{
Updated(this);
}
catch {}
}
}
private void UnityLogCallback(string condition, string stackTrace, LogType type)
{
//if (condition.StartsWith("[SRConsole]"))
// return;
lock (_threadLock)
{
var prevMessage = _collapseEnabled && _allConsoleEntries.Count > 0
? _allConsoleEntries[_allConsoleEntries.Count - 1]
: null;
AdjustCounter(type, 1);
if (prevMessage != null && prevMessage.LogType == type && prevMessage.Message == condition &&
prevMessage.StackTrace == stackTrace)
{
OnEntryDuplicated(prevMessage);
}
else
{
var newEntry = new ConsoleEntry
{
LogType = type,
StackTrace = stackTrace,
Message = condition
};
OnEntryAdded(newEntry);
}
}
}
private void AdjustCounter(LogType type, int amount)
{
switch (type)
{
case LogType.Assert:
case LogType.Error:
case LogType.Exception:
ErrorCount += amount;
if (Error != null)
{
Error.Invoke(this);
}
break;
case LogType.Warning:
WarningCount += amount;
break;
case LogType.Log:
InfoCount += amount;
break;
}
}
}
}

View File

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

View File

@@ -0,0 +1,270 @@
namespace SRDebugger.Services.Implementation
{
using System;
using System.Collections.Generic;
using System.Linq;
using SRF;
using SRF.Service;
using UnityEngine;
/// <summary>
/// Reports system specifications and environment information. Information that can
/// be used to identify a user is marked as private, and won't be included in any generated
/// reports.
/// </summary>
[Service(typeof(ISystemInformationService))]
public class StandardSystemInformationService : ISystemInformationService
{
private readonly Dictionary<string, IList<InfoEntry>> _info = new Dictionary<string, IList<InfoEntry>>();
public StandardSystemInformationService()
{
CreateDefaultSet();
}
public IEnumerable<string> GetCategories()
{
return _info.Keys;
}
public IList<InfoEntry> GetInfo(string category)
{
IList<InfoEntry> list;
if (!_info.TryGetValue(category, out list))
{
Debug.LogError("[SystemInformationService] Category not found: {0}".Fmt(category));
return new InfoEntry[0];
}
return list;
}
public void Add(InfoEntry info, string category = "Default")
{
IList<InfoEntry> list;
if (!_info.TryGetValue(category, out list))
{
list = new List<InfoEntry>();
_info.Add(category, list);
}
if (list.Any(p => p.Title == info.Title))
{
throw new ArgumentException("An InfoEntry object with the same title already exists in that category.", "info");
}
list.Add(info);
}
public Dictionary<string, Dictionary<string, object>> CreateReport(bool includePrivate = false)
{
var dict = new Dictionary<string, Dictionary<string, object>>(_info.Count);
foreach (var keyValuePair in _info)
{
var category = new Dictionary<string, object>(keyValuePair.Value.Count);
foreach (var systemInfo in keyValuePair.Value)
{
if (systemInfo.IsPrivate && !includePrivate)
{
continue;
}
category.Add(systemInfo.Title, systemInfo.Value);
}
dict.Add(keyValuePair.Key, category);
}
return dict;
}
private void CreateDefaultSet()
{
_info.Add("System", new[]
{
InfoEntry.Create("Operating System", UnityEngine.SystemInfo.operatingSystem),
InfoEntry.Create("Device Name", UnityEngine.SystemInfo.deviceName, true),
InfoEntry.Create("Device Type", UnityEngine.SystemInfo.deviceType),
InfoEntry.Create("Device Model", UnityEngine.SystemInfo.deviceModel),
InfoEntry.Create("CPU Type", UnityEngine.SystemInfo.processorType),
InfoEntry.Create("CPU Count", UnityEngine.SystemInfo.processorCount),
InfoEntry.Create("System Memory", SRFileUtil.GetBytesReadable(((long) UnityEngine.SystemInfo.systemMemorySize)*1024*1024))
//Info.Create("Process Name", () => Process.GetCurrentProcess().ProcessName)
});
if (SystemInfo.batteryStatus != BatteryStatus.Unknown)
{
_info.Add("Battery", new[]
{
InfoEntry.Create("Status", UnityEngine.SystemInfo.batteryStatus),
InfoEntry.Create("Battery Level", UnityEngine.SystemInfo.batteryLevel)
});
}
#if ENABLE_IL2CPP
const string IL2CPP = "Yes";
#else
const string IL2CPP = "No";
#endif
_info.Add("Unity", new[]
{
InfoEntry.Create("Version", Application.unityVersion),
InfoEntry.Create("Debug", Debug.isDebugBuild),
InfoEntry.Create("Unity Pro", Application.HasProLicense()),
InfoEntry.Create("Genuine",
"{0} ({1})".Fmt(Application.genuine ? "Yes" : "No",
Application.genuineCheckAvailable ? "Trusted" : "Untrusted")),
InfoEntry.Create("System Language", Application.systemLanguage),
InfoEntry.Create("Platform", Application.platform),
InfoEntry.Create("Install Mode", Application.installMode),
InfoEntry.Create("Sandbox", Application.sandboxType),
InfoEntry.Create("IL2CPP", IL2CPP),
InfoEntry.Create("Application Version", Application.version),
InfoEntry.Create("Application Id", Application.identifier),
InfoEntry.Create("SRDebugger Version", SRDebug.Version),
});
_info.Add("Display", new[]
{
InfoEntry.Create("Resolution", () => Screen.width + "x" + Screen.height),
InfoEntry.Create("DPI", () => Screen.dpi),
InfoEntry.Create("Fullscreen", () => Screen.fullScreen),
InfoEntry.Create("Fullscreen Mode", () => Screen.fullScreenMode),
InfoEntry.Create("Orientation", () => Screen.orientation),
});
_info.Add("Runtime", new[]
{
InfoEntry.Create("Play Time", () => Time.unscaledTime),
InfoEntry.Create("Level Play Time", () => Time.timeSinceLevelLoad),
#if UNITY_4_6 || UNITY_4_7 || UNITY_5_0 || UNITY_5_1 || UNITY_5_2
InfoEntry.Create("Current Level", () => Application.loadedLevelName),
#else
InfoEntry.Create("Current Level", () =>
{
var activeScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene();
return "{0} (Index: {1})".Fmt(activeScene.name, activeScene.buildIndex);
}),
#endif
InfoEntry.Create("Quality Level",
() =>
QualitySettings.names[QualitySettings.GetQualityLevel()] + " (" +
QualitySettings.GetQualityLevel() + ")")
});
// Check for cloud build manifest
var cloudBuildManifest = (TextAsset)Resources.Load("UnityCloudBuildManifest.json");
var manifestDict = cloudBuildManifest != null
? Json.Deserialize(cloudBuildManifest.text) as Dictionary<string, object>
: null;
if (manifestDict != null)
{
var manifestList = new List<InfoEntry>(manifestDict.Count);
foreach (var kvp in manifestDict)
{
if (kvp.Value == null)
{
continue;
}
var value = kvp.Value.ToString();
manifestList.Add(InfoEntry.Create(GetCloudManifestPrettyName(kvp.Key), value));
}
_info.Add("Build", manifestList);
}
_info.Add("Features", new[]
{
InfoEntry.Create("Location", UnityEngine.SystemInfo.supportsLocationService),
InfoEntry.Create("Accelerometer", UnityEngine.SystemInfo.supportsAccelerometer),
InfoEntry.Create("Gyroscope", UnityEngine.SystemInfo.supportsGyroscope),
InfoEntry.Create("Vibration", UnityEngine.SystemInfo.supportsVibration),
InfoEntry.Create("Audio", UnityEngine.SystemInfo.supportsAudio)
});
#if UNITY_IOS
_info.Add("iOS", new[] {
#if UNITY_5 || UNITY_5_3_OR_NEWER
InfoEntry.Create("Generation", UnityEngine.iOS.Device.generation),
InfoEntry.Create("Ad Tracking", UnityEngine.iOS.Device.advertisingTrackingEnabled),
#else
InfoEntry.Create("Generation", iPhone.generation),
InfoEntry.Create("Ad Tracking", iPhone.advertisingTrackingEnabled),
#endif
});
#endif
#pragma warning disable 618
_info.Add("Graphics - Device", new[]
{
InfoEntry.Create("Device Name", UnityEngine.SystemInfo.graphicsDeviceName),
InfoEntry.Create("Device Vendor", UnityEngine.SystemInfo.graphicsDeviceVendor),
InfoEntry.Create("Device Version", UnityEngine.SystemInfo.graphicsDeviceVersion),
InfoEntry.Create("Graphics Memory", SRFileUtil.GetBytesReadable(((long) UnityEngine.SystemInfo.graphicsMemorySize)*1024*1024)),
InfoEntry.Create("Max Tex Size", UnityEngine.SystemInfo.maxTextureSize),
});
_info.Add("Graphics - Features", new[]
{
InfoEntry.Create("UV Starts at top", UnityEngine.SystemInfo.graphicsUVStartsAtTop),
InfoEntry.Create("Shader Level", UnityEngine.SystemInfo.graphicsShaderLevel),
InfoEntry.Create("Multi Threaded", UnityEngine.SystemInfo.graphicsMultiThreaded),
InfoEntry.Create("Hidden Service Removal (GPU)", UnityEngine.SystemInfo.hasHiddenSurfaceRemovalOnGPU),
InfoEntry.Create("Uniform Array Indexing (Fragment Shaders)", UnityEngine.SystemInfo.hasDynamicUniformArrayIndexingInFragmentShaders),
InfoEntry.Create("Shadows", UnityEngine.SystemInfo.supportsShadows),
InfoEntry.Create("Raw Depth Sampling (Shadows)", UnityEngine.SystemInfo.supportsRawShadowDepthSampling),
InfoEntry.Create("Motion Vectors", UnityEngine.SystemInfo.supportsMotionVectors),
InfoEntry.Create("Cubemaps", UnityEngine.SystemInfo.supportsRenderToCubemap),
InfoEntry.Create("Image Effects", UnityEngine.SystemInfo.supportsImageEffects),
InfoEntry.Create("3D Textures", UnityEngine.SystemInfo.supports3DTextures),
InfoEntry.Create("2D Array Textures", UnityEngine.SystemInfo.supports2DArrayTextures),
InfoEntry.Create("3D Render Textures", UnityEngine.SystemInfo.supports3DRenderTextures),
InfoEntry.Create("Cubemap Array Textures", UnityEngine.SystemInfo.supportsCubemapArrayTextures),
InfoEntry.Create("Copy Texture Support", UnityEngine.SystemInfo.copyTextureSupport),
InfoEntry.Create("Compute Shaders", UnityEngine.SystemInfo.supportsComputeShaders),
InfoEntry.Create("Instancing", UnityEngine.SystemInfo.supportsInstancing),
InfoEntry.Create("Hardware Quad Topology", UnityEngine.SystemInfo.supportsHardwareQuadTopology),
InfoEntry.Create("32-bit index buffer", UnityEngine.SystemInfo.supports32bitsIndexBuffer),
InfoEntry.Create("Sparse Textures", UnityEngine.SystemInfo.supportsSparseTextures),
InfoEntry.Create("Render Target Count", UnityEngine.SystemInfo.supportedRenderTargetCount),
InfoEntry.Create("Separated Render Targets Blend", UnityEngine.SystemInfo.supportsSeparatedRenderTargetsBlend),
InfoEntry.Create("Multisampled Textures", UnityEngine.SystemInfo.supportsMultisampledTextures),
InfoEntry.Create("Texture Wrap Mirror Once", UnityEngine.SystemInfo.supportsTextureWrapMirrorOnce),
InfoEntry.Create("Reversed Z Buffer", UnityEngine.SystemInfo.usesReversedZBuffer)
});
#pragma warning restore 618
}
private static string GetCloudManifestPrettyName(string name)
{
switch (name)
{
case "scmCommitId":
return "Commit";
case "scmBranch":
return "Branch";
case "cloudBuildTargetName":
return "Build Target";
case "buildStartTime":
return "Build Date";
}
// Return name with first letter capitalised
return name.Substring(0, 1).ToUpper() + name.Substring(1);
}
}
}

View File

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