namespace SRDebugger.UI.Tabs { using System; using System.Collections.Generic; using System.ComponentModel; using Controls; using Controls.Data; using Internal; using Other; using Services; using SRF; using UnityEngine; using UnityEngine.UI; public class OptionsTabController : SRMonoBehaviourEx { private class CategoryInstance { public CategoryGroup CategoryGroup { get; private set; } public readonly List Options = new List(); public CategoryInstance(CategoryGroup group) { CategoryGroup = group; } } private readonly List _controls = new List(); private readonly List _categories = new List(); private readonly Dictionary _options = new Dictionary(); private bool _queueRefresh; private bool _selectionModeEnabled; private Canvas _optionCanvas; [RequiredField] public ActionControl ActionControlPrefab; [RequiredField] public CategoryGroup CategoryGroupPrefab; [RequiredField] public RectTransform ContentContainer; [RequiredField] public GameObject NoOptionsNotice; [RequiredField] public Toggle PinButton; [RequiredField] public GameObject PinPromptSpacer; [RequiredField] public GameObject PinPromptText; protected override void Start() { base.Start(); PinButton.onValueChanged.AddListener(SetSelectionModeEnabled); PinPromptText.SetActive(false); //PinPromptSpacer.SetActive(false); Populate(); _optionCanvas = GetComponent(); Service.Options.OptionsUpdated += OnOptionsUpdated; Service.PinnedUI.OptionPinStateChanged += OnOptionPinnedStateChanged; } protected override void OnDestroy() { if (Service.Options != null) { Service.Options.OptionsUpdated -= OnOptionsUpdated; } if (Service.PinnedUI != null) { Service.PinnedUI.OptionPinStateChanged -= OnOptionPinnedStateChanged; } base.OnDestroy(); } private void OnOptionPinnedStateChanged(OptionDefinition optionDefinition, bool isPinned) { if (_options.ContainsKey(optionDefinition)) { _options[optionDefinition].IsSelected = isPinned; } } private void OnOptionsUpdated(object sender, EventArgs eventArgs) { Clear(); Populate(); } protected override void OnEnable() { base.OnEnable(); Service.Panel.VisibilityChanged += PanelOnVisibilityChanged; } protected override void OnDisable() { // Always end pinning mode when tabbing away SetSelectionModeEnabled(false); if (Service.Panel != null) { Service.Panel.VisibilityChanged -= PanelOnVisibilityChanged; } base.OnDisable(); } protected override void Update() { base.Update(); if (_queueRefresh) { _queueRefresh = false; Refresh(); } } private void PanelOnVisibilityChanged(IDebugPanelService debugPanelService, bool b) { // Always end pinning mode when panel is closed if (!b) { SetSelectionModeEnabled(false); // Refresh bindings for all pinned controls Refresh(); } else if (b && CachedGameObject.activeInHierarchy) { // If the panel is visible, and this tab is active (selected), refresh all the data bindings Refresh(); } if (_optionCanvas != null) { _optionCanvas.enabled = b; } } public void SetSelectionModeEnabled(bool isEnabled) { if (_selectionModeEnabled == isEnabled) { return; } _selectionModeEnabled = isEnabled; PinButton.isOn = isEnabled; PinPromptText.SetActive(isEnabled); //PinPromptSpacer.SetActive(isEnabled); foreach (var kv in _options) { kv.Value.SelectionModeEnabled = isEnabled; // Set IsSelected if entering selection mode. if (isEnabled) { kv.Value.IsSelected = Service.PinnedUI.HasPinned(kv.Key); } } foreach (var cat in _categories) { cat.CategoryGroup.SelectionModeEnabled = isEnabled; } RefreshCategorySelection(); // Return if entering selection mode if (isEnabled) { return; } } private void Refresh() { for (var i = 0; i < _options.Count; i++) { _controls[i].Refresh(); _controls[i].IsSelected = Service.PinnedUI.HasPinned(_controls[i].Option); } } private void CommitPinnedOptions() { foreach (var kv in _options) { var control = kv.Value; if (control.IsSelected && !Service.PinnedUI.HasPinned(kv.Key)) { Service.PinnedUI.Pin(kv.Key); } else if (!control.IsSelected && Service.PinnedUI.HasPinned(kv.Key)) { Service.PinnedUI.Unpin(kv.Key); } } } private bool _isTogglingCategory; private void RefreshCategorySelection() { _isTogglingCategory = true; foreach (var cat in _categories) { var allSelected = true; for (var i = 0; i < cat.Options.Count; i++) { if (!cat.Options[i].IsSelected) { allSelected = false; break; } } cat.CategoryGroup.IsSelected = allSelected; } _isTogglingCategory = false; } private void OnOptionSelectionToggle(bool selected) { if (!_isTogglingCategory) { RefreshCategorySelection(); CommitPinnedOptions(); } } /// /// When a category mode selection is changed. /// /// /// private void OnCategorySelectionToggle(CategoryInstance category, bool selected) { _isTogglingCategory = true; for (var i = 0; i < category.Options.Count; i++) { category.Options[i].IsSelected = selected; } _isTogglingCategory = false; CommitPinnedOptions(); } #region Initialisation protected void Populate() { var sortedOptions = new Dictionary>(); foreach (var option in Service.Options.Options) { // Find a properly list for that category, or create a new one List memberList; if (!sortedOptions.TryGetValue(option.Category, out memberList)) { memberList = new List(); sortedOptions.Add(option.Category, memberList); } memberList.Add(option); } var hasCreated = false; foreach (var kv in sortedOptions) { if (kv.Value.Count == 0) { continue; } hasCreated = true; CreateCategory(kv.Key, kv.Value); } if (hasCreated) { NoOptionsNotice.SetActive(false); } } protected void CreateCategory(string title, List options) { options.Sort((d1, d2) => d1.SortPriority.CompareTo(d2.SortPriority)); var groupInstance = SRInstantiate.Instantiate(CategoryGroupPrefab); var categoryInstance = new CategoryInstance(groupInstance); _categories.Add(categoryInstance); groupInstance.CachedTransform.SetParent(ContentContainer, false); groupInstance.Header.text = title; groupInstance.SelectionModeEnabled = false; categoryInstance.CategoryGroup.SelectionToggle.onValueChanged.AddListener( b => OnCategorySelectionToggle(categoryInstance, b)); foreach (var option in options) { var control = OptionControlFactory.CreateControl(option, title); if (control == null) { Debug.LogError("[SRDebugger.OptionsTab] Failed to create option control for {0}".Fmt(option.Name)); continue; } categoryInstance.Options.Add(control); control.CachedTransform.SetParent(groupInstance.Container, false); control.IsSelected = Service.PinnedUI.HasPinned(option); control.SelectionModeEnabled = false; control.SelectionModeToggle.onValueChanged.AddListener(OnOptionSelectionToggle); _options.Add(option, control); _controls.Add(control); } } void Clear() { foreach (var categoryInstance in _categories) { Destroy(categoryInstance.CategoryGroup.gameObject); } _categories.Clear(); _controls.Clear(); _options.Clear(); } #endregion } }