diff --git a/.beads/dolt-server.activity b/.beads/dolt-server.activity deleted file mode 100644 index 295985b..0000000 --- a/.beads/dolt-server.activity +++ /dev/null @@ -1 +0,0 @@ -1774203036 \ No newline at end of file diff --git a/.beads/dolt-server.port b/.beads/dolt-server.port deleted file mode 100644 index f4c3ffd..0000000 --- a/.beads/dolt-server.port +++ /dev/null @@ -1 +0,0 @@ -14107 \ No newline at end of file diff --git a/src/HomuraHimeAudioMod/GUI/AudioMixerGUI.cs b/src/HomuraHimeAudioMod/GUI/AudioMixerGUI.cs index 902b5aa..a5464b9 100644 --- a/src/HomuraHimeAudioMod/GUI/AudioMixerGUI.cs +++ b/src/HomuraHimeAudioMod/GUI/AudioMixerGUI.cs @@ -1,228 +1,491 @@ using System; -using System.Collections.Generic; using UnityEngine; +using UnityEngine.UI; +using UnityEngine.EventSystems; +using TMPro; using HarmonyLib; namespace HomuraHimeAudioMod.GUI { public class AudioMixerGUI : MonoBehaviour { + private GameObject canvasObject; + private GameObject panelObject; + private RectTransform panelRect; + private RectTransform contentRect; + private GameObject resizeHandle; private bool isVisible = false; - private Vector2 scrollPosition; - private float margin = 10f; - private float labelWidth = 140f; - private float sliderWidth = 200f; - private float buttonHeight = 25f; - private float lineHeight = 30f; - private float windowWidth = 380f; - private float windowHeight = 450f; - private Rect windowRect = new Rect(10, 10, 380, 450); + private Vector2 minSize = new Vector2(350, 400); + private Vector2 maxSize = new Vector2(800, 900); + private Vector2 currentSize = new Vector2(420, 650); + + private Toggle voiceLimitToggle; + private Slider maxVoicesSlider; + private Toggle duckingToggle; + private Slider duckFadeSlider; + private Slider duckVolumeSlider; + private Toggle enemyAudioToggle; + private Slider indicatorBoostSlider; + private Slider alertBoostSlider; + private Slider attackBoostSlider; + + private void Start() + { + CreateGUI(); + Plugin.Log.LogInfo("AudioMixerGUI Canvas created - Press F1"); + } + + private void CreateGUI() + { + canvasObject = new GameObject("AudioMixerCanvas"); + Canvas canvas = canvasObject.AddComponent(); + canvas.renderMode = RenderMode.ScreenSpaceOverlay; + canvas.sortingOrder = 999; + canvasObject.AddComponent(); + canvasObject.AddComponent(); + + CreatePanel(); + CreateContent(); + CreateResizeHandle(); + + canvasObject.SetActive(false); + } + + private void CreatePanel() + { + panelObject = new GameObject("MixerPanel"); + panelObject.transform.SetParent(canvasObject.transform); + + panelRect = panelObject.AddComponent(); + panelRect.anchorMin = Vector2.zero; + panelRect.anchorMax = Vector2.zero; + panelRect.pivot = Vector2.zero; + panelRect.anchoredPosition = new Vector2(30, 30); + panelRect.sizeDelta = currentSize; + + Image bg = panelObject.AddComponent(); + bg.color = new Color(0.12f, 0.12f, 0.18f, 0.97f); + + panelObject.AddComponent().effectColor = new Color(0.3f, 0.3f, 0.4f); + + DraggablePanel draggable = panelObject.AddComponent(); + draggable.Initialize(panelRect); + } + + private void CreateContent() + { + GameObject contentObj = new GameObject("Content"); + contentObj.transform.SetParent(panelObject.transform); + + VerticalLayoutGroup layout = contentObj.AddComponent(); + layout.spacing = 8; + layout.padding = new RectOffset(15, 15, 15, 15); + layout.childAlignment = TextAnchor.UpperCenter; + layout.childControlWidth = true; + layout.childControlHeight = true; + layout.childForceExpandWidth = true; + layout.childForceExpandHeight = false; + + ContentSizeFitter fitter = contentObj.AddComponent(); + fitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize; + fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize; + + contentRect = contentObj.GetComponent(); + contentRect.anchorMin = Vector2.zero; + contentRect.anchorMax = Vector2.one; + contentRect.sizeDelta = new Vector2(-30, -50); + + CreateHeader(contentObj.transform); + CreateVoiceSection(contentObj.transform); + CreateDuckingSection(contentObj.transform); + CreateEnemySection(contentObj.transform); + CreateCueSection(contentObj.transform); + CreateFooter(contentObj.transform); + } + + private void CreateHeader(Transform parent) + { + AddSectionTitle(parent, "AUDIO MIXER", 18, new Color(1f, 0.8f, 0.2f)); + AddSpacer(parent, 5); + } + + private void CreateVoiceSection(Transform parent) + { + AddSectionTitle(parent, "VOICE MANAGER", 14, new Color(0.7f, 0.9f, 1f)); + + voiceLimitToggle = AddToggle(parent, "Voice Limit Fix", ModConfig.EnableVoiceLimitFix.Value, + (v) => ModConfig.EnableVoiceLimitFix.Value = v); + + CreateSliderRow(parent, "Max Voices:", 32, 256, ModConfig.MaxVoiceCount.Value, + out maxVoicesSlider, (v) => ModConfig.MaxVoiceCount.Value = (int)v); + + AddSpacer(parent, 10); + } + + private void CreateDuckingSection(Transform parent) + { + AddSectionTitle(parent, "AUDIO DUCKING", 14, new Color(0.7f, 0.9f, 1f)); + + duckingToggle = AddToggle(parent, "Ducking Fix", ModConfig.EnableDuckingFix.Value, + (v) => ModConfig.EnableDuckingFix.Value = v); + + CreateSliderRow(parent, "Duck Fade:", 0.01f, 0.3f, ModConfig.DuckFadeTime.Value, + out duckFadeSlider, (v) => ModConfig.DuckFadeTime.Value = v); + + CreateSliderRow(parent, "Duck Volume:", 0.1f, 0.8f, ModConfig.DuckVolume.Value, + out duckVolumeSlider, (v) => ModConfig.DuckVolume.Value = v); + + AddSpacer(parent, 10); + } + + private void CreateEnemySection(Transform parent) + { + AddSectionTitle(parent, "ENEMY AUDIO", 14, new Color(1f, 0.6f, 0.6f)); + + enemyAudioToggle = AddToggle(parent, "Enemy Audio Boost", ModConfig.EnableEnemyAudioBoost.Value, + (v) => ModConfig.EnableEnemyAudioBoost.Value = v); + + CreateSliderRow(parent, "Indicator:", 0.5f, 2.0f, ModConfig.EnemyIndicatorBoost.Value, + out indicatorBoostSlider, (v) => ModConfig.EnemyIndicatorBoost.Value = v); + + CreateSliderRow(parent, "Alert:", 0.5f, 2.0f, ModConfig.AlertSoundBoost.Value, + out alertBoostSlider, (v) => ModConfig.AlertSoundBoost.Value = v); + + CreateSliderRow(parent, "Attack:", 0.5f, 2.0f, ModConfig.AttackSoundBoost.Value, + out attackBoostSlider, (v) => ModConfig.AttackSoundBoost.Value = v); + + AddSpacer(parent, 10); + } + + private void CreateCueSection(Transform parent) + { + AddSectionTitle(parent, "TEST CUES", 14, new Color(0.6f, 1f, 0.6f)); + + GameObject grid = new GameObject("CueGrid"); + grid.transform.SetParent(parent.transform); + + HorizontalLayoutGroup hLayout = grid.AddComponent(); + hLayout.spacing = 10; + hLayout.childAlignment = TextAnchor.MiddleCenter; + hLayout.childControlWidth = true; + hLayout.childControlHeight = true; + hLayout.childForceExpandWidth = true; + hLayout.childForceExpandHeight = false; + + ContentSizeFitter cf = grid.AddComponent(); + cf.horizontalFit = ContentSizeFitter.FitMode.PreferredSize; + cf.verticalFit = ContentSizeFitter.FitMode.MinSize; + + RectTransform gridRect = grid.GetComponent(); + gridRect.sizeDelta = new Vector2(0, 40); + + AddCueButton(grid.transform, "Enemy_Idle", () => TestCue("Enemy_Idle")); + AddCueButton(grid.transform, "Enemy_Alert", () => TestCue("Enemy_Alert")); + AddCueButton(grid.transform, "Enemy_Attack", () => TestCue("Enemy_Attack")); + AddCueButton(grid.transform, "Enemy_Chase", () => TestCue("Enemy_Chase")); + AddCueButton(grid.transform, "Enemy_Death", () => TestCue("Enemy_Death")); + + AddSpacer(parent, 10); + } + + private void CreateFooter(Transform parent) + { + AddLabel(parent, "F1: Toggle | Drag: Move | Corner: Resize", 11, Color.gray); + } + + private void CreateResizeHandle() + { + resizeHandle = new GameObject("ResizeHandle"); + resizeHandle.transform.SetParent(panelObject.transform); + + RectTransform handleRect = resizeHandle.AddComponent(); + handleRect.anchorMin = new Vector2(1, 0); + handleRect.anchorMax = new Vector2(1, 0); + handleRect.pivot = new Vector2(1, 0); + handleRect.anchoredPosition = new Vector2(0, 0); + handleRect.sizeDelta = new Vector2(20, 20); + + Image handleImage = resizeHandle.AddComponent(); + handleImage.color = new Color(0.4f, 0.4f, 0.5f, 0.8f); + + ResizeHandle resize = resizeHandle.AddComponent(); + resize.Initialize(panelRect, minSize, maxSize); + } + + private void AddSectionTitle(Transform parent, string text, int fontSize, Color color) + { + GameObject obj = new GameObject("Title"); + obj.transform.SetParent(parent); + + LayoutElement le = obj.AddComponent(); + le.minHeight = 25; + le.preferredHeight = 25; + le.flexibleWidth = 1; + + TextMeshProUGUI txt = obj.AddComponent(); + txt.text = text; + txt.fontSize = fontSize; + txt.fontStyle = FontStyles.Bold; + txt.color = color; + txt.alignment = TextAlignmentOptions.Center; + } + + private void AddSpacer(Transform parent, float height) + { + GameObject spacer = new GameObject("Spacer"); + spacer.transform.SetParent(parent); + + LayoutElement le = spacer.AddComponent(); + le.minHeight = height; + le.preferredHeight = height; + le.flexibleWidth = 1; + } + + private Toggle AddToggle(Transform parent, string label, bool defaultValue, Action onChanged) + { + GameObject obj = new GameObject("Toggle_" + label); + obj.transform.SetParent(parent); + + LayoutElement le = obj.AddComponent(); + le.minHeight = 25; + le.preferredHeight = 25; + le.flexibleWidth = 1; + + Toggle toggle = obj.AddComponent(); + toggle.isOn = defaultValue; + toggle.onValueChanged.AddListener((UnityEngine.Events.UnityAction)(v => onChanged(v))); + + GameObject labelObj = new GameObject("Label"); + labelObj.transform.SetParent(obj.transform); + + TextMeshProUGUI txt = labelObj.AddComponent(); + txt.text = label; + txt.fontSize = 12; + txt.color = Color.white; + txt.alignment = TextAlignmentOptions.Left; + + return toggle; + } + + private void CreateSliderRow(Transform parent, string label, float min, float max, float defaultVal, + out Slider slider, Action onChanged) + { + GameObject row = new GameObject("Slider_" + label); + row.transform.SetParent(parent); + + LayoutElement le = row.AddComponent(); + le.minHeight = 30; + le.preferredHeight = 30; + le.flexibleWidth = 1; + + GameObject labelObj = new GameObject("Label"); + labelObj.transform.SetParent(row.transform); + + TextMeshProUGUI labelTxt = labelObj.AddComponent(); + labelTxt.text = label; + labelTxt.fontSize = 11; + labelTxt.color = Color.white; + labelTxt.alignment = TextAlignmentOptions.Left; + + RectTransform labelRect = labelObj.GetComponent(); + labelRect.anchorMin = new Vector2(0, 0); + labelRect.anchorMax = new Vector2(0.35f, 1); + labelRect.pivot = new Vector2(0, 0.5f); + labelRect.offsetMin = new Vector2(0, 0); + labelRect.offsetMax = new Vector2(0, 0); + labelRect.sizeDelta = new Vector2(0, 0); + + GameObject sliderObj = new GameObject("Slider"); + sliderObj.transform.SetParent(row.transform); + + slider = sliderObj.AddComponent(); + slider.minValue = min; + slider.maxValue = max; + slider.value = defaultVal; + slider.onValueChanged.AddListener((UnityEngine.Events.UnityAction)(v => onChanged(v))); + + RectTransform sliderRect = sliderObj.GetComponent(); + sliderRect.anchorMin = new Vector2(0.35f, 0); + sliderRect.anchorMax = new Vector2(0.75f, 1); + sliderRect.pivot = new Vector2(0.5f, 0.5f); + sliderRect.offsetMin = new Vector2(5, 3); + sliderRect.offsetMax = new Vector2(-5, -3); + + GameObject valueObj = new GameObject("Value"); + valueObj.transform.SetParent(row.transform); + + TextMeshProUGUI valueTxt = valueObj.AddComponent(); + valueTxt.text = defaultVal.ToString("F2"); + valueTxt.fontSize = 11; + valueTxt.color = Color.yellow; + valueTxt.alignment = TextAlignmentOptions.Left; + + RectTransform valueRect = valueObj.GetComponent(); + valueRect.anchorMin = new Vector2(0.75f, 0); + valueRect.anchorMax = new Vector2(1, 1); + valueRect.pivot = new Vector2(0, 0.5f); + valueRect.offsetMin = new Vector2(5, 0); + valueRect.offsetMax = new Vector2(0, 0); + valueRect.sizeDelta = new Vector2(0, 0); + + slider.onValueChanged.AddListener((UnityEngine.Events.UnityAction)(v => valueTxt.text = v.ToString("F2"))); + } + + private void AddCueButton(Transform parent, string label, Action onClick) + { + GameObject btnObj = new GameObject("CueBtn_" + label); + btnObj.transform.SetParent(parent); + + LayoutElement le = btnObj.AddComponent(); + le.minWidth = 70; + le.preferredWidth = 80; + le.minHeight = 30; + le.preferredHeight = 30; + + Button btn = btnObj.AddComponent