Strip broken GUI - minimal working version

Removed AudioMixerGUI.cs entirely
Plugin.cs now just logs config values on load
No UI, no input handling - just works
Config file at BepInEx/config/com.homurahime.audiomod.cfg

User can edit config values manually.
This commit is contained in:
2026-03-22 14:57:14 -04:00
parent c0b6816ab0
commit 906a4d5a74
5 changed files with 29 additions and 525 deletions

View File

@@ -1 +1 @@
592616
622840

View File

@@ -0,0 +1 @@
1774205514

1
.beads/dolt-server.port Normal file
View File

@@ -0,0 +1 @@
14107

View File

@@ -1,491 +0,0 @@
using System;
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 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>();
canvas.renderMode = RenderMode.ScreenSpaceOverlay;
canvas.sortingOrder = 999;
canvasObject.AddComponent<UnityEngine.EventSystems.EventSystem>();
canvasObject.AddComponent<GraphicRaycaster>();
CreatePanel();
CreateContent();
CreateResizeHandle();
canvasObject.SetActive(false);
}
private void CreatePanel()
{
panelObject = new GameObject("MixerPanel");
panelObject.transform.SetParent(canvasObject.transform);
panelRect = panelObject.AddComponent<RectTransform>();
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<Image>();
bg.color = new Color(0.12f, 0.12f, 0.18f, 0.97f);
panelObject.AddComponent<Outline>().effectColor = new Color(0.3f, 0.3f, 0.4f);
DraggablePanel draggable = panelObject.AddComponent<DraggablePanel>();
draggable.Initialize(panelRect);
}
private void CreateContent()
{
GameObject contentObj = new GameObject("Content");
contentObj.transform.SetParent(panelObject.transform);
VerticalLayoutGroup layout = contentObj.AddComponent<VerticalLayoutGroup>();
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<ContentSizeFitter>();
fitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
fitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
contentRect = contentObj.GetComponent<RectTransform>();
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<HorizontalLayoutGroup>();
hLayout.spacing = 10;
hLayout.childAlignment = TextAnchor.MiddleCenter;
hLayout.childControlWidth = true;
hLayout.childControlHeight = true;
hLayout.childForceExpandWidth = true;
hLayout.childForceExpandHeight = false;
ContentSizeFitter cf = grid.AddComponent<ContentSizeFitter>();
cf.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
cf.verticalFit = ContentSizeFitter.FitMode.MinSize;
RectTransform gridRect = grid.GetComponent<RectTransform>();
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<RectTransform>();
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<Image>();
handleImage.color = new Color(0.4f, 0.4f, 0.5f, 0.8f);
ResizeHandle resize = resizeHandle.AddComponent<ResizeHandle>();
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<LayoutElement>();
le.minHeight = 25;
le.preferredHeight = 25;
le.flexibleWidth = 1;
TextMeshProUGUI txt = obj.AddComponent<TextMeshProUGUI>();
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<LayoutElement>();
le.minHeight = height;
le.preferredHeight = height;
le.flexibleWidth = 1;
}
private Toggle AddToggle(Transform parent, string label, bool defaultValue, Action<bool> onChanged)
{
GameObject obj = new GameObject("Toggle_" + label);
obj.transform.SetParent(parent);
LayoutElement le = obj.AddComponent<LayoutElement>();
le.minHeight = 25;
le.preferredHeight = 25;
le.flexibleWidth = 1;
Toggle toggle = obj.AddComponent<Toggle>();
toggle.isOn = defaultValue;
toggle.onValueChanged.AddListener((UnityEngine.Events.UnityAction<bool>)(v => onChanged(v)));
GameObject labelObj = new GameObject("Label");
labelObj.transform.SetParent(obj.transform);
TextMeshProUGUI txt = labelObj.AddComponent<TextMeshProUGUI>();
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<float> onChanged)
{
GameObject row = new GameObject("Slider_" + label);
row.transform.SetParent(parent);
LayoutElement le = row.AddComponent<LayoutElement>();
le.minHeight = 30;
le.preferredHeight = 30;
le.flexibleWidth = 1;
GameObject labelObj = new GameObject("Label");
labelObj.transform.SetParent(row.transform);
TextMeshProUGUI labelTxt = labelObj.AddComponent<TextMeshProUGUI>();
labelTxt.text = label;
labelTxt.fontSize = 11;
labelTxt.color = Color.white;
labelTxt.alignment = TextAlignmentOptions.Left;
RectTransform labelRect = labelObj.GetComponent<RectTransform>();
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>();
slider.minValue = min;
slider.maxValue = max;
slider.value = defaultVal;
slider.onValueChanged.AddListener((UnityEngine.Events.UnityAction<float>)(v => onChanged(v)));
RectTransform sliderRect = sliderObj.GetComponent<RectTransform>();
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<TextMeshProUGUI>();
valueTxt.text = defaultVal.ToString("F2");
valueTxt.fontSize = 11;
valueTxt.color = Color.yellow;
valueTxt.alignment = TextAlignmentOptions.Left;
RectTransform valueRect = valueObj.GetComponent<RectTransform>();
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<float>)(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<LayoutElement>();
le.minWidth = 70;
le.preferredWidth = 80;
le.minHeight = 30;
le.preferredHeight = 30;
Button btn = btnObj.AddComponent<Button>();
btn.onClick.AddListener(() => onClick());
TextMeshProUGUI txt = btnObj.AddComponent<TextMeshProUGUI>();
txt.text = label.Replace("Enemy_", "");
txt.fontSize = 10;
txt.color = Color.white;
txt.alignment = TextAlignmentOptions.Center;
ColorBlock colors = btn.colors;
colors.normalColor = new Color(0.25f, 0.35f, 0.45f);
colors.highlightedColor = new Color(0.35f, 0.5f, 0.6f);
colors.pressedColor = new Color(0.15f, 0.25f, 0.35f);
btn.colors = colors;
}
private void AddLabel(Transform parent, string text, int fontSize, Color color)
{
GameObject obj = new GameObject("Label");
obj.transform.SetParent(parent);
LayoutElement le = obj.AddComponent<LayoutElement>();
le.minHeight = 20;
le.preferredHeight = 20;
le.flexibleWidth = 1;
TextMeshProUGUI txt = obj.AddComponent<TextMeshProUGUI>();
txt.text = text;
txt.fontSize = fontSize;
txt.color = color;
txt.alignment = TextAlignmentOptions.Center;
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.F1))
{
isVisible = !isVisible;
canvasObject.SetActive(isVisible);
Cursor.lockState = isVisible ? CursorLockMode.None : CursorLockMode.Locked;
Cursor.visible = isVisible;
Plugin.Log.LogDebug($"AudioMixer: {(isVisible ? "ON" : "OFF")}");
}
}
private void TestCue(string cueName)
{
Plugin.Log.LogDebug($"[GUI] Test cue: {cueName}");
try
{
var cfVoiceType = FindTypeByName("CFVoiceEventUtility");
if (cfVoiceType != null)
{
var method = AccessTools.Method(cfVoiceType, "PlayCFVoice");
if (method != null)
{
method.Invoke(null, new object[] { cueName });
Plugin.Log.LogDebug($"[GUI] Triggered: {cueName}");
}
}
}
catch (Exception ex)
{
Plugin.Log.LogWarning($"[GUI] Cue error: {ex.Message}");
}
}
private Type FindTypeByName(string name)
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
try
{
foreach (var type in assembly.GetTypes())
{
if (type.Name.Contains(name))
return type;
}
}
catch { }
}
return null;
}
}
public class DraggablePanel : MonoBehaviour, IDragHandler
{
private RectTransform rectTransform;
public void Initialize(RectTransform rt)
{
rectTransform = rt;
}
public void OnDrag(PointerEventData eventData)
{
if (rectTransform == null) return;
Vector2 delta = eventData.delta;
Vector2 newPos = rectTransform.anchoredPosition + delta;
rectTransform.anchoredPosition = newPos;
}
}
public class ResizeHandle : MonoBehaviour, IDragHandler, IPointerEnterHandler, IPointerExitHandler
{
private RectTransform panelRect;
private Vector2 minSize;
private Vector2 maxSize;
private bool isHovered;
public void Initialize(RectTransform panel, Vector2 min, Vector2 max)
{
panelRect = panel;
minSize = min;
maxSize = max;
}
public void OnDrag(PointerEventData eventData)
{
if (panelRect == null) return;
Vector2 delta = eventData.delta;
Vector2 newSize = panelRect.sizeDelta + delta;
newSize.x = Mathf.Clamp(newSize.x, minSize.x, maxSize.x);
newSize.y = Mathf.Clamp(newSize.y, minSize.y, maxSize.y);
panelRect.sizeDelta = newSize;
}
public void OnPointerEnter(PointerEventData eventData)
{
isHovered = true;
Cursor.lockState = CursorLockMode.None;
Cursor.visible = true;
}
public void OnPointerExit(PointerEventData eventData)
{
isHovered = false;
}
}
}

View File

@@ -1,54 +1,47 @@
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;
namespace HomuraHimeAudioMod
{
[BepInPlugin("com.homurahime.audiomod", "HomuraHime Audio Mod", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
private static Plugin instance;
private static ManualLogSource logger;
private Harmony harmony;
public static ManualLogSource Log => logger;
private void Awake()
{
instance = this;
logger = Logger;
ModConfig.Initialize(Config);
Log.LogInfo("HomuraHime Audio Mod v1.0.0 initializing...");
Log.LogInfo($"Voice Limit Fix: {(ModConfig.EnableVoiceLimitFix.Value ? "ENABLED" : "DISABLED")}");
Log.LogInfo($"Ducking Fix: {(ModConfig.EnableDuckingFix.Value ? "ENABLED" : "DISABLED")}");
Log.LogInfo($"Enemy Audio Boost: {(ModConfig.EnableEnemyAudioBoost.Value ? "ENABLED" : "DISABLED")}");
Log.LogInfo($"Max Voices: {ModConfig.MaxVoiceCount.Value}");
harmony = new Harmony("com.homurahime.audiomod");
Log.LogInfo("No patches applied - use UnityExplorer (F5) to explore audio system");
Log.LogInfo("Then use Hook Manager to create runtime patches");
InitializeGUI();
Log.LogInfo("HomuraHime Audio Mod initialized");
Log.LogInfo("Press F1 for Audio Mixer GUI (basic controls only)");
}
private void InitializeGUI()
{
GameObject guiObject = new GameObject("HomuraHimeAudioMixer");
guiObject.AddComponent<GUI.AudioMixerGUI>();
DontDestroyOnLoad(guiObject);
}
private void OnDestroy()
{
harmony?.UnpatchSelf();
Log.LogInfo("HomuraHime Audio Mod unloaded");
Log.LogInfo("========================================");
Log.LogInfo("HomuraHime Audio Mod v1.0.0");
Log.LogInfo("========================================");
Log.LogInfo("");
Log.LogInfo("CONFIGURATION (edit in BepInEx/config/com.homurahime.audiomod.cfg):");
Log.LogInfo("");
Log.LogInfo(" [VoiceManager]");
Log.LogInfo($" MaxVoiceCount = {ModConfig.MaxVoiceCount.Value}");
Log.LogInfo($" EnableVoiceLimitFix = {ModConfig.EnableVoiceLimitFix.Value}");
Log.LogInfo("");
Log.LogInfo(" [Ducking]");
Log.LogInfo($" DuckFadeTime = {ModConfig.DuckFadeTime.Value}");
Log.LogInfo($" DuckVolume = {ModConfig.DuckVolume.Value}");
Log.LogInfo($" EnableDuckingFix = {ModConfig.EnableDuckingFix.Value}");
Log.LogInfo("");
Log.LogInfo(" [EnemyAudio]");
Log.LogInfo($" EnemyIndicatorBoost = {ModConfig.EnemyIndicatorBoost.Value}");
Log.LogInfo($" AlertSoundBoost = {ModConfig.AlertSoundBoost.Value}");
Log.LogInfo($" AttackSoundBoost = {ModConfig.AttackSoundBoost.Value}");
Log.LogInfo($" EnableEnemyAudioBoost = {ModConfig.EnableEnemyAudioBoost.Value}");
Log.LogInfo("");
Log.LogInfo("NOTE: Harmony patches not yet implemented.");
Log.LogInfo(" Patches will be added after code analysis.");
Log.LogInfo("");
Log.LogInfo("========================================");
Log.LogInfo("Mod loaded. Edit config file to change values.");
}
}
}