Added rest of the modules

This commit is contained in:
Christen
2026-03-03 19:47:55 -05:00
parent 81990827c0
commit faf9b62c30
9 changed files with 8313 additions and 206 deletions

View File

@@ -5,40 +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, Gripper }
private enum Mode { None, DC, Display, Speaker }
private Mode _mode = Mode.None;
private DCMotorModule _dc;
private DisplayModule _display;
private GripperModule _gripper;
private SpeakerModule _speaker;
// Keep separate inputs so they don't interfere
private string _savedDCInput = "";
private int _savedDirectionIndex = 0;
private string _savedDisplayInput = "";
private string _savedGripperInput = "";
// 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());
@@ -54,37 +61,17 @@ public class ControlPanel : MonoBehaviour
}
}
/// <summary>
/// Call this whenever a DC or Display module is selected.
/// </summary>
public void Initialize(ModuleBase module)
{
CacheCurrentInput();
_dc = module as DCMotorModule;
_display = module as DisplayModule;
_gripper = module as GripperModule;
_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 (_gripper != null)
{
SwitchMode(Mode.Gripper);
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();
}
@@ -96,12 +83,13 @@ public class ControlPanel : MonoBehaviour
_mode = Mode.None;
_dc = null;
_display = null;
_gripper = 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<TextMeshProUGUI>();
@@ -122,47 +110,78 @@ 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.Gripper)
else if (_mode == Mode.Speaker)
{
if (_caption != null) _caption.text = "Degrees";
if (_buttonText != null) _buttonText.text = "Apply";
// Speaker UI: no input field (removes the white box behind buttons)
SetMainButtonText("Send Audio");
SetCaptionVisible(false);
SetDirectionVisible(false);
SetInputVisible(false);
if (inputField != null)
inputField.SetTextWithoutNotify(_gripper != null ? _gripper.currentAngle.ToString("F0") : _savedGripperInput);
// 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)
{
if (_directionCaptionGO != null) _directionCaptionGO.SetActive(visible);
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;
@@ -170,28 +189,19 @@ 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)
{
_savedDisplayInput = inputField.text;
}
else if (_mode == Mode.Gripper)
{
_savedGripperInput = inputField.text;
}
}
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))
{
@@ -204,30 +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.Gripper)
else if (_mode == Mode.Speaker)
{
if (_gripper == null)
{
Debug.LogWarning("ControlPanel: No Gripper module selected.");
return;
}
if (!float.TryParse(inputField.text, out float degrees))
{
Debug.LogWarning("ControlPanel: Invalid degree input for Gripper.");
return;
}
_gripper.SetAngleAndSendControlLibrary(Mathf.Clamp(degrees, 0f, 180f));
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<Image>();
var dstImg = target.GetComponent<Image>();
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<Image>();
img.raycastTarget = true;
_uploadButton = go.AddComponent<Button>();
_uploadButton.onClick.AddListener(OnUploadClicked);
// Copy Send button look
CopyButtonStyle(button, _uploadButton);
var textGo = new GameObject("Text (TMP)");
textGo.transform.SetParent(go.transform, false);
_uploadButtonText = textGo.AddComponent<TextMeshProUGUI>();
_uploadButtonText.text = "Upload Audio";
// Copy Send text look
CopyTMPStyle(_buttonText, _uploadButtonText);
_uploadButtonText.alignment = TextAlignmentOptions.Center;
// Layout: above Play
var rt = go.GetComponent<RectTransform>();
rt.anchorMin = new Vector2(0.5f, 0f);
rt.anchorMax = new Vector2(0.5f, 0f);
rt.pivot = new Vector2(0.5f, 0f);
rt.sizeDelta = button != null ? button.GetComponent<RectTransform>().sizeDelta : new Vector2(180f, 40f);
rt.anchoredPosition = new Vector2(0f, 110f);
var trt = textGo.GetComponent<RectTransform>();
trt.anchorMin = Vector2.zero;
trt.anchorMax = Vector2.one;
trt.offsetMin = Vector2.zero;
trt.offsetMax = Vector2.zero;
go.SetActive(false);
}
private void SetUploadVisible(bool visible)
{
if (_uploadButton != null && _uploadButton.gameObject.activeSelf != visible)
_uploadButton.gameObject.SetActive(visible);
}
private void OnUploadClicked()
{
if (_speaker == null) return;
string path = OpenAudioFilePicker();
if (string.IsNullOrEmpty(path)) return;
_speaker.SetAudioFile(path);
// If you want to display filename somewhere without the input field,
// we can put it in the caption temporarily or add a TMP label in code.
}
// -------------------------
// Play button (code-created)
// -------------------------
private void CreatePlayButtonIfNeeded()
{
if (_playButton != null) return;
var go = new GameObject("PlayButton");
go.transform.SetParent(transform, false);
var img = go.AddComponent<Image>();
img.raycastTarget = true;
_playButton = go.AddComponent<Button>();
_playButton.onClick.AddListener(OnPlayClicked);
// Copy Send button look
CopyButtonStyle(button, _playButton);
var textGo = new GameObject("Text (TMP)");
textGo.transform.SetParent(go.transform, false);
_playButtonText = textGo.AddComponent<TextMeshProUGUI>();
_playButtonText.text = "Play Audio";
// Copy Send text look
CopyTMPStyle(_buttonText, _playButtonText);
_playButtonText.alignment = TextAlignmentOptions.Center;
// Layout: between Upload and Send
var rt = go.GetComponent<RectTransform>();
rt.anchorMin = new Vector2(0.5f, 0f);
rt.anchorMax = new Vector2(0.5f, 0f);
rt.pivot = new Vector2(0.5f, 0f);
rt.sizeDelta = button != null ? button.GetComponent<RectTransform>().sizeDelta : new Vector2(180f, 40f);
rt.anchoredPosition = new Vector2(0f, 60f);
var trt = textGo.GetComponent<RectTransform>();
trt.anchorMin = Vector2.zero;
trt.anchorMax = Vector2.one;
trt.offsetMin = Vector2.zero;
trt.offsetMax = Vector2.zero;
go.SetActive(false);
}
private void SetPlayVisible(bool visible)
{
if (_playButton != null && _playButton.gameObject.activeSelf != visible)
_playButton.gameObject.SetActive(visible);
}
private void OnPlayClicked()
{
if (_speaker == null) return;
_speaker.PlayAudioOnHardware();
}
// -------------------------
// File Picker (Editor + builds via SFB)
// -------------------------
private string OpenAudioFilePicker()
{
#if UNITY_EDITOR
return UnityEditor.EditorUtility.OpenFilePanel("Select audio file", "", "wav,mp3,ogg");
#else
var extensions = new[]
{
new SFB.ExtensionFilter("Audio Files", "wav", "mp3", "ogg"),
new SFB.ExtensionFilter("All Files", "*")
};
string[] paths = SFB.StandaloneFileBrowser.OpenFilePanel("Select audio file", "", extensions, false);
return (paths != null && paths.Length > 0) ? paths[0] : "";
#endif
}
private void SetCaptionVisible(bool visible)
{
if (_caption != null && _caption.gameObject.activeSelf != visible)
_caption.gameObject.SetActive(visible);
}
}