Files
DTrierFlood_New/Assets/Scripts/Networking/Client/SweConnectionButtonController.cs

281 lines
8.8 KiB
C#

using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace FloodSWE.Networking
{
/// <summary>
/// Drives a Connect/Disconnect button from SweQuestControlClient state.
/// </summary>
public sealed class SweConnectionButtonController : MonoBehaviour
{
[Header("References")]
[SerializeField] private SweQuestControlClient controlClient;
[SerializeField] private Button button;
[SerializeField] private TMP_Text label;
[SerializeField] private TMP_InputField serverIpInput;
[Header("Labels")]
[SerializeField] private string connectLabel = "Connect";
[SerializeField] private string loadingLabel = "Loading...";
[SerializeField] private string disconnectLabel = "Disconnect";
[Header("Behavior")]
[SerializeField] private bool disableButtonWhileLoading = true;
[SerializeField] private bool allowCancelWhileLoading = false;
private void OnEnable()
{
if (button == null)
{
button = GetComponent<Button>();
}
if (label == null && button != null)
{
label = button.GetComponentInChildren<TMP_Text>();
}
if (controlClient == null)
{
controlClient = FindFirstObjectByType<SweQuestControlClient>();
}
EnsureServerIpInput();
if (serverIpInput != null)
{
serverIpInput.onValueChanged.AddListener(OnServerIpChanged);
string serverHost = controlClient != null ? controlClient.serverHost : string.Empty;
serverIpInput.SetTextWithoutNotify(serverHost ?? string.Empty);
}
if (button != null)
{
button.onClick.AddListener(OnButtonPressed);
}
RefreshVisual();
}
private void OnDisable()
{
if (serverIpInput != null)
{
serverIpInput.onValueChanged.RemoveListener(OnServerIpChanged);
}
if (button != null)
{
button.onClick.RemoveListener(OnButtonPressed);
}
}
private void Update()
{
RefreshVisual();
}
public void OnButtonPressed()
{
if (controlClient == null)
{
return;
}
if (controlClient.IsConnectionAlive)
{
controlClient.Disconnect();
return;
}
if (controlClient.IsWaitingForAck)
{
if (allowCancelWhileLoading)
{
controlClient.Disconnect();
}
return;
}
controlClient.Connect();
}
private void RefreshVisual()
{
if (controlClient == null)
{
SetLabel(connectLabel);
SetButtonInteractable(false);
return;
}
if (controlClient.IsConnectionAlive)
{
SetLabel(disconnectLabel);
SetButtonInteractable(true);
return;
}
if (controlClient.IsWaitingForAck)
{
SetLabel(loadingLabel);
bool interactable = !disableButtonWhileLoading || allowCancelWhileLoading;
SetButtonInteractable(interactable);
return;
}
SetLabel(connectLabel);
SetButtonInteractable(true);
}
private void SetLabel(string textValue)
{
if (label == null || label.text == textValue)
{
return;
}
label.text = textValue;
}
private void SetButtonInteractable(bool interactable)
{
if (button == null || button.interactable == interactable)
{
return;
}
button.interactable = interactable;
}
private void OnServerIpChanged(string serverIp)
{
if (controlClient == null)
{
return;
}
controlClient.serverHost = serverIp ?? string.Empty;
}
private void EnsureServerIpInput()
{
if (serverIpInput != null)
{
return;
}
RectTransform panelRect = transform.parent as RectTransform;
if (panelRect == null)
{
return;
}
TMP_InputField existingInput = panelRect.GetComponentInChildren<TMP_InputField>(true);
if (existingInput != null)
{
serverIpInput = existingInput;
return;
}
serverIpInput = CreateServerIpInput(panelRect);
}
private TMP_InputField CreateServerIpInput(RectTransform panelRect)
{
RectTransform buttonRect = button != null ? button.transform as RectTransform : null;
if (buttonRect != null)
{
buttonRect.anchoredPosition = new Vector2(buttonRect.anchoredPosition.x, -95.0f);
}
panelRect.sizeDelta = new Vector2(panelRect.sizeDelta.x, Mathf.Max(125.0f, panelRect.sizeDelta.y));
GameObject inputRoot = new GameObject(
"Server IP Input",
typeof(RectTransform),
typeof(CanvasRenderer),
typeof(Image),
typeof(TMP_InputField));
RectTransform inputRect = inputRoot.GetComponent<RectTransform>();
inputRect.SetParent(panelRect, false);
inputRect.anchorMin = new Vector2(0.0f, 1.0f);
inputRect.anchorMax = new Vector2(0.0f, 1.0f);
inputRect.pivot = new Vector2(0.0f, 1.0f);
inputRect.anchoredPosition = new Vector2(25.0f, -60.0f);
inputRect.sizeDelta = new Vector2(200.0f, 30.0f);
Image background = inputRoot.GetComponent<Image>();
background.color = new Color(1.0f, 1.0f, 1.0f, 0.95f);
GameObject textAreaObject = new GameObject("Text Area", typeof(RectTransform), typeof(RectMask2D));
RectTransform textAreaRect = textAreaObject.GetComponent<RectTransform>();
textAreaRect.SetParent(inputRect, false);
textAreaRect.anchorMin = Vector2.zero;
textAreaRect.anchorMax = Vector2.one;
textAreaRect.offsetMin = new Vector2(10.0f, 6.0f);
textAreaRect.offsetMax = new Vector2(-10.0f, -7.0f);
TMP_FontAsset fontAsset = label != null ? label.font : TMP_Settings.defaultFontAsset;
TextMeshProUGUI placeholder = CreateInputText(
"Placeholder",
textAreaRect,
fontAsset,
"Server IP",
new Color(0.45f, 0.45f, 0.45f, 0.9f));
placeholder.fontStyle = FontStyles.Italic;
TextMeshProUGUI inputText = CreateInputText(
"Text",
textAreaRect,
fontAsset,
string.Empty,
Color.black);
TMP_InputField inputField = inputRoot.GetComponent<TMP_InputField>();
inputField.targetGraphic = background;
inputField.textViewport = textAreaRect;
inputField.textComponent = inputText;
inputField.placeholder = placeholder;
inputField.lineType = TMP_InputField.LineType.SingleLine;
return inputField;
}
private static TextMeshProUGUI CreateInputText(
string objectName,
RectTransform parent,
TMP_FontAsset fontAsset,
string textValue,
Color textColor)
{
GameObject textObject = new GameObject(objectName, typeof(RectTransform), typeof(CanvasRenderer), typeof(TextMeshProUGUI));
RectTransform textRect = textObject.GetComponent<RectTransform>();
textRect.SetParent(parent, false);
textRect.anchorMin = Vector2.zero;
textRect.anchorMax = Vector2.one;
textRect.offsetMin = Vector2.zero;
textRect.offsetMax = Vector2.zero;
TextMeshProUGUI text = textObject.GetComponent<TextMeshProUGUI>();
text.font = fontAsset;
if (fontAsset != null)
{
text.fontSharedMaterial = fontAsset.material;
}
text.text = textValue;
text.color = textColor;
text.fontSize = 20.0f;
text.enableAutoSizing = true;
text.fontSizeMin = 14.0f;
text.fontSizeMax = 24.0f;
text.alignment = TextAlignmentOptions.Left;
text.enableWordWrapping = false;
text.raycastTarget = false;
return text;
}
}
}