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 { private readonly List _controlList = new List(); private readonly Dictionary _pinnedObjects = new Dictionary(); private bool _queueRefresh; private PinnedUIRoot _uiRoot; public DockConsoleController DockConsoleController { get { if (_uiRoot == null) { Load(); } return _uiRoot.DockConsoleController; } } public event Action OptionPinStateChanged; public event Action 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(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()); } } 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(); } } } }