From 20480f6eaf5316c671bdec5fe7bcf333ab0e37b2 Mon Sep 17 00:00:00 2001 From: Christen Date: Tue, 3 Mar 2026 00:51:12 -0500 Subject: [PATCH] Added speaker and power modules --- Assets/ControlPanel.cs | 334 +- Assets/IK/InverseKinematicsController.cs | 2 +- Assets/LiveViewModulePanel.cs | 16 +- Assets/Module/PowerModule.prefab | 223 + Assets/Module/PowerModule.prefab.meta | 7 + Assets/Module/SpeakerModule.prefab | 194 + Assets/Module/SpeakerModule.prefab.meta | 7 + Assets/Module/TopologyBuilder.cs | 1 + Assets/Module/battery_module_mf_unity.prefab | 19 +- Assets/Module/power_module_rounded.fbx | Bin 0 -> 112128 bytes Assets/Module/power_module_rounded.fbx.meta | 110 + Assets/ModuleSpawner.cs | 3 + .../BatteryModule.cs => PowerModule.cs} | 4 +- Assets/PowerModule.cs.meta | 2 + Assets/Resources/mockDataSimple.json | 2 +- Assets/Scenes/SampleScene.unity | 123 +- Assets/SpeakerModule.cs | 69 + Assets/SpeakerModule.cs.meta | 2 + Assets/StandaloneFileBrowser.meta | 8 + .../IStandaloneFileBrowser.cs | 13 + .../IStandaloneFileBrowser.cs.meta | 12 + Assets/StandaloneFileBrowser/Plugins.meta | 8 + .../StandaloneFileBrowser/Plugins/Linux.meta | 10 + .../Plugins/Linux/x86_64.meta | 10 + .../Linux/x86_64/libStandaloneFileBrowser.so | Bin 0 -> 26984 bytes .../x86_64/libStandaloneFileBrowser.so.meta | 126 + .../Plugins/Ookii.Dialogs.dll | Bin 0 -> 133632 bytes .../Plugins/Ookii.Dialogs.dll.meta | 145 + .../Plugins/StandaloneFileBrowser.bundle.meta | 40 + .../Contents.meta | 8 + .../Contents/Info.plist | 46 + .../Contents/MacOS.meta | 8 + .../Contents/MacOS/StandaloneFileBrowser | Bin 0 -> 28672 bytes .../Plugins/StandaloneFileBrowser.jslib | 90 + .../Plugins/StandaloneFileBrowser.jslib.meta | 96 + .../Plugins/System.Windows.Forms.dll | Bin 0 -> 3053568 bytes .../Plugins/System.Windows.Forms.dll.meta | 145 + Assets/StandaloneFileBrowser/Sample.meta | 8 + .../Sample/BasicSample.cs | 119 + .../Sample/BasicSample.cs.meta | 12 + .../Sample/BasicSampleScene.unity | 248 + .../Sample/BasicSampleScene.unity.meta | 8 + .../Sample/CanvasSampleOpenFileImage.cs | 53 + .../Sample/CanvasSampleOpenFileImage.cs.meta | 12 + .../Sample/CanvasSampleOpenFileText.cs | 53 + .../Sample/CanvasSampleOpenFileText.cs.meta | 12 + .../CanvasSampleOpenFileTextMultiple.cs | 62 + .../CanvasSampleOpenFileTextMultiple.cs.meta} | 2 +- .../Sample/CanvasSampleSaveFileImage.cs | 65 + .../Sample/CanvasSampleSaveFileImage.cs.meta | 12 + .../Sample/CanvasSampleSaveFileText.cs | 52 + .../Sample/CanvasSampleSaveFileText.cs.meta | 12 + .../Sample/CanvasSampleScene.unity | 1520 +++ .../Sample/CanvasSampleScene.unity.meta | 8 + .../StandaloneFileBrowser.cs | 153 + .../StandaloneFileBrowser.cs.meta | 12 + .../StandaloneFileBrowserEditor.cs | 56 + .../StandaloneFileBrowserEditor.cs.meta | 12 + .../StandaloneFileBrowserLinux.cs | 115 + .../StandaloneFileBrowserLinux.cs.meta | 3 + .../StandaloneFileBrowserMac.cs | 119 + .../StandaloneFileBrowserMac.cs.meta | 12 + .../StandaloneFileBrowserWindows.cs | 137 + .../StandaloneFileBrowserWindows.cs.meta | 12 + .../Fonts & Materials/Roboto-Bold SDF.asset | 10734 +++++++++++++++- 65 files changed, 14788 insertions(+), 718 deletions(-) create mode 100644 Assets/Module/PowerModule.prefab create mode 100644 Assets/Module/PowerModule.prefab.meta create mode 100644 Assets/Module/SpeakerModule.prefab create mode 100644 Assets/Module/SpeakerModule.prefab.meta create mode 100644 Assets/Module/power_module_rounded.fbx create mode 100644 Assets/Module/power_module_rounded.fbx.meta rename Assets/{Module/BatteryModule.cs => PowerModule.cs} (66%) create mode 100644 Assets/PowerModule.cs.meta create mode 100644 Assets/SpeakerModule.cs create mode 100644 Assets/SpeakerModule.cs.meta create mode 100644 Assets/StandaloneFileBrowser.meta create mode 100644 Assets/StandaloneFileBrowser/IStandaloneFileBrowser.cs create mode 100644 Assets/StandaloneFileBrowser/IStandaloneFileBrowser.cs.meta create mode 100644 Assets/StandaloneFileBrowser/Plugins.meta create mode 100644 Assets/StandaloneFileBrowser/Plugins/Linux.meta create mode 100644 Assets/StandaloneFileBrowser/Plugins/Linux/x86_64.meta create mode 100644 Assets/StandaloneFileBrowser/Plugins/Linux/x86_64/libStandaloneFileBrowser.so create mode 100644 Assets/StandaloneFileBrowser/Plugins/Linux/x86_64/libStandaloneFileBrowser.so.meta create mode 100644 Assets/StandaloneFileBrowser/Plugins/Ookii.Dialogs.dll create mode 100644 Assets/StandaloneFileBrowser/Plugins/Ookii.Dialogs.dll.meta create mode 100644 Assets/StandaloneFileBrowser/Plugins/StandaloneFileBrowser.bundle.meta create mode 100644 Assets/StandaloneFileBrowser/Plugins/StandaloneFileBrowser.bundle/Contents.meta create mode 100644 Assets/StandaloneFileBrowser/Plugins/StandaloneFileBrowser.bundle/Contents/Info.plist create mode 100644 Assets/StandaloneFileBrowser/Plugins/StandaloneFileBrowser.bundle/Contents/MacOS.meta create mode 100644 Assets/StandaloneFileBrowser/Plugins/StandaloneFileBrowser.bundle/Contents/MacOS/StandaloneFileBrowser create mode 100644 Assets/StandaloneFileBrowser/Plugins/StandaloneFileBrowser.jslib create mode 100644 Assets/StandaloneFileBrowser/Plugins/StandaloneFileBrowser.jslib.meta create mode 100644 Assets/StandaloneFileBrowser/Plugins/System.Windows.Forms.dll create mode 100644 Assets/StandaloneFileBrowser/Plugins/System.Windows.Forms.dll.meta create mode 100644 Assets/StandaloneFileBrowser/Sample.meta create mode 100644 Assets/StandaloneFileBrowser/Sample/BasicSample.cs create mode 100644 Assets/StandaloneFileBrowser/Sample/BasicSample.cs.meta create mode 100644 Assets/StandaloneFileBrowser/Sample/BasicSampleScene.unity create mode 100644 Assets/StandaloneFileBrowser/Sample/BasicSampleScene.unity.meta create mode 100644 Assets/StandaloneFileBrowser/Sample/CanvasSampleOpenFileImage.cs create mode 100644 Assets/StandaloneFileBrowser/Sample/CanvasSampleOpenFileImage.cs.meta create mode 100644 Assets/StandaloneFileBrowser/Sample/CanvasSampleOpenFileText.cs create mode 100644 Assets/StandaloneFileBrowser/Sample/CanvasSampleOpenFileText.cs.meta create mode 100644 Assets/StandaloneFileBrowser/Sample/CanvasSampleOpenFileTextMultiple.cs rename Assets/{Module/BatteryModule.cs.meta => StandaloneFileBrowser/Sample/CanvasSampleOpenFileTextMultiple.cs.meta} (83%) create mode 100644 Assets/StandaloneFileBrowser/Sample/CanvasSampleSaveFileImage.cs create mode 100644 Assets/StandaloneFileBrowser/Sample/CanvasSampleSaveFileImage.cs.meta create mode 100644 Assets/StandaloneFileBrowser/Sample/CanvasSampleSaveFileText.cs create mode 100644 Assets/StandaloneFileBrowser/Sample/CanvasSampleSaveFileText.cs.meta create mode 100644 Assets/StandaloneFileBrowser/Sample/CanvasSampleScene.unity create mode 100644 Assets/StandaloneFileBrowser/Sample/CanvasSampleScene.unity.meta create mode 100644 Assets/StandaloneFileBrowser/StandaloneFileBrowser.cs create mode 100644 Assets/StandaloneFileBrowser/StandaloneFileBrowser.cs.meta create mode 100644 Assets/StandaloneFileBrowser/StandaloneFileBrowserEditor.cs create mode 100644 Assets/StandaloneFileBrowser/StandaloneFileBrowserEditor.cs.meta create mode 100644 Assets/StandaloneFileBrowser/StandaloneFileBrowserLinux.cs create mode 100644 Assets/StandaloneFileBrowser/StandaloneFileBrowserLinux.cs.meta create mode 100644 Assets/StandaloneFileBrowser/StandaloneFileBrowserMac.cs create mode 100644 Assets/StandaloneFileBrowser/StandaloneFileBrowserMac.cs.meta create mode 100644 Assets/StandaloneFileBrowser/StandaloneFileBrowserWindows.cs create mode 100644 Assets/StandaloneFileBrowser/StandaloneFileBrowserWindows.cs.meta diff --git a/Assets/ControlPanel.cs b/Assets/ControlPanel.cs index 8c6a7ec..fc528db 100644 --- a/Assets/ControlPanel.cs +++ b/Assets/ControlPanel.cs @@ -5,38 +5,47 @@ using UnityEngine.UI; public class ControlPanel : MonoBehaviour { [Header("Core UI (assign in Inspector)")] - public TMP_InputField inputField; // was DegreesInputField - public TMP_Dropdown directionDropdown; // was DirectionDropdown - public Button button; // was RotateButton + public TMP_InputField inputField; + public TMP_Dropdown directionDropdown; + public Button button; // existing Send/Rotate button in hierarchy - private enum Mode { None, DC, Display } + private enum Mode { None, DC, Display, Speaker } private Mode _mode = Mode.None; private DCMotorModule _dc; private DisplayModule _display; + private SpeakerModule _speaker; - // Keep separate inputs so they don't interfere private string _savedDCInput = ""; private int _savedDirectionIndex = 0; private string _savedDisplayInput = ""; - // Found automatically (no new UI objects) - private TextMeshProUGUI _caption; // DegreesCaption text - private TextMeshProUGUI _buttonText; // RotateButton/Text (TMP) - private GameObject _directionCaptionGO; // DirectionCaption - private GameObject _directionDropdownGO; // DirectionDropdown GameObject + // Found automatically (no hierarchy edits) + private TextMeshProUGUI _caption; // child "DegreesCaption" + private TextMeshProUGUI _buttonText; // child "RotateButton/Text (TMP)" + private GameObject _directionCaptionGO; + private GameObject _directionDropdownGO; + + // Created in code (Speaker mode only) + private Button _uploadButton; + private TextMeshProUGUI _uploadButtonText; + private Button _playButton; + private TextMeshProUGUI _playButtonText; private void Awake() { CacheUIFromHierarchy(); + // Create these once; hide unless Speaker mode + CreateUploadButtonIfNeeded(); + CreatePlayButtonIfNeeded(); + if (button != null) { button.onClick.RemoveAllListeners(); - button.onClick.AddListener(OnButtonClicked); + button.onClick.AddListener(OnMainButtonClicked); } - // Cache typed values so switching modules restores what you typed if (inputField != null) { inputField.onValueChanged.AddListener(_ => CacheCurrentInput()); @@ -52,29 +61,17 @@ public class ControlPanel : MonoBehaviour } } - /// - /// Call this whenever a DC or Display module is selected. - /// public void Initialize(ModuleBase module) { CacheCurrentInput(); _dc = module as DCMotorModule; _display = module as DisplayModule; + _speaker = module as SpeakerModule; - if (_dc != null) - { - SwitchMode(Mode.DC); - gameObject.SetActive(true); - return; - } - - if (_display != null) - { - SwitchMode(Mode.Display); - gameObject.SetActive(true); - return; - } + if (_dc != null) { SwitchMode(Mode.DC); gameObject.SetActive(true); return; } + if (_display != null) { SwitchMode(Mode.Display); gameObject.SetActive(true); return; } + if (_speaker != null) { SwitchMode(Mode.Speaker); gameObject.SetActive(true); return; } HidePanel(); } @@ -86,11 +83,13 @@ public class ControlPanel : MonoBehaviour _mode = Mode.None; _dc = null; _display = null; + _speaker = null; + SetUploadVisible(false); + SetPlayVisible(false); } private void CacheUIFromHierarchy() { - // Assumes this script is on the parent that contains these children var captionT = transform.Find("DegreesCaption"); if (captionT != null) _caption = captionT.GetComponent(); @@ -111,30 +110,64 @@ public class ControlPanel : MonoBehaviour if (_mode == Mode.DC) { - if (_caption != null) _caption.text = "Degrees"; - if (_buttonText != null) _buttonText.text = "Rotate"; + SetCaption("Degrees"); + SetCaptionVisible(true); + SetMainButtonText("Rotate"); SetDirectionVisible(true); + SetInputVisible(true); + SetUploadVisible(false); + SetPlayVisible(false); if (inputField != null) + { + inputField.readOnly = false; inputField.SetTextWithoutNotify(_savedDCInput); + } if (directionDropdown != null) directionDropdown.SetValueWithoutNotify(_savedDirectionIndex); } else if (_mode == Mode.Display) { - if (_caption != null) _caption.text = "Text"; - if (_buttonText != null) _buttonText.text = "Send"; + SetCaption("Text"); + SetCaptionVisible(true); + SetMainButtonText("Send"); SetDirectionVisible(false); - - // Prefer module's current displayText; fallback to last typed text - string toShow = _savedDisplayInput; - if (_display != null && !string.IsNullOrEmpty(_display.displayText)) - toShow = _display.displayText; + SetInputVisible(true); + SetUploadVisible(false); + SetPlayVisible(false); if (inputField != null) + { + inputField.readOnly = false; + string toShow = _savedDisplayInput; + if (_display != null && !string.IsNullOrEmpty(_display.displayText)) + toShow = _display.displayText; inputField.SetTextWithoutNotify(toShow); + } } + else if (_mode == Mode.Speaker) + { + // Speaker UI: no input field (removes the white box behind buttons) + SetMainButtonText("Send Audio"); + SetCaptionVisible(false); + SetDirectionVisible(false); + SetInputVisible(false); + + // Show speaker buttons + SetUploadVisible(true); + SetPlayVisible(true); + } + } + + private void SetCaption(string text) + { + if (_caption != null) _caption.text = text; + } + + private void SetMainButtonText(string text) + { + if (_buttonText != null) _buttonText.text = text; } private void SetDirectionVisible(bool visible) @@ -143,6 +176,12 @@ public class ControlPanel : MonoBehaviour if (_directionDropdownGO != null) _directionDropdownGO.SetActive(visible); } + private void SetInputVisible(bool visible) + { + if (inputField != null && inputField.gameObject.activeSelf != visible) + inputField.gameObject.SetActive(visible); + } + private void CacheCurrentInput() { if (inputField == null) return; @@ -150,8 +189,7 @@ public class ControlPanel : MonoBehaviour if (_mode == Mode.DC) { _savedDCInput = inputField.text; - if (directionDropdown != null) - _savedDirectionIndex = directionDropdown.value; + if (directionDropdown != null) _savedDirectionIndex = directionDropdown.value; } else if (_mode == Mode.Display) { @@ -159,15 +197,11 @@ public class ControlPanel : MonoBehaviour } } - private void OnButtonClicked() + private void OnMainButtonClicked() { if (_mode == Mode.DC) { - if (_dc == null) - { - Debug.LogWarning("ControlPanel: No DC module selected."); - return; - } + if (_dc == null) return; if (!float.TryParse(inputField.text, out float degrees)) { @@ -180,14 +214,206 @@ public class ControlPanel : MonoBehaviour } else if (_mode == Mode.Display) { - if (_display == null) - { - Debug.LogWarning("ControlPanel: No Display module selected."); - return; - } - - string text = inputField != null ? inputField.text : ""; - _display.SetDisplayText(text); // <- THIS is where Display module gets the text + if (_display == null) return; + _display.SetDisplayText(inputField != null ? inputField.text : ""); + } + else if (_mode == Mode.Speaker) + { + if (_speaker == null) return; + _speaker.SendAudioToHardware(); // Send Audio = upload to hardware (your implementation) } } + + // ------------------------- + // Styling helpers (copy Send button look) + // ------------------------- + + private void CopyButtonStyle(Button source, Button target) + { + if (source == null || target == null) return; + + // Button settings + target.transition = source.transition; + target.colors = source.colors; + target.spriteState = source.spriteState; + target.navigation = source.navigation; + target.interactable = source.interactable; + + // Image settings + var srcImg = source.GetComponent(); + var dstImg = target.GetComponent(); + if (srcImg != null && dstImg != null) + { + dstImg.sprite = srcImg.sprite; + dstImg.type = srcImg.type; + dstImg.pixelsPerUnitMultiplier = srcImg.pixelsPerUnitMultiplier; + dstImg.material = srcImg.material; + dstImg.color = srcImg.color; + dstImg.raycastTarget = srcImg.raycastTarget; + } + } + + private void CopyTMPStyle(TextMeshProUGUI source, TextMeshProUGUI target) + { + if (source == null || target == null) return; + + target.font = source.font; + target.fontSharedMaterial = source.fontSharedMaterial; + target.fontStyle = source.fontStyle; + target.fontSize = source.fontSize; + target.enableAutoSizing = source.enableAutoSizing; + target.color = source.color; + target.enableVertexGradient = source.enableVertexGradient; + target.alignment = source.alignment; + target.enableWordWrapping = source.enableWordWrapping; + target.richText = source.richText; + } + + // ------------------------- + // Upload button (code-created) + // ------------------------- + + private void CreateUploadButtonIfNeeded() + { + if (_uploadButton != null) return; + + var go = new GameObject("UploadButton"); + go.transform.SetParent(transform, false); + + var img = go.AddComponent(); + img.raycastTarget = true; + + _uploadButton = go.AddComponent