MVP of the plane throwing game (#77)
Co-authored-by: Michal Pikulski <michal@foolhardyhorizons.com> Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com> Reviewed-on: #77
This commit is contained in:
297
Assets/Scripts/Minigames/Airplane/UI/AirplaneSelectionUI.cs
Normal file
297
Assets/Scripts/Minigames/Airplane/UI/AirplaneSelectionUI.cs
Normal file
@@ -0,0 +1,297 @@
|
||||
using System;
|
||||
using Core;
|
||||
using Minigames.Airplane.Data;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Minigames.Airplane.UI
|
||||
{
|
||||
/// <summary>
|
||||
/// UI for selecting airplane type before game starts.
|
||||
/// Displays buttons for each available airplane type.
|
||||
/// </summary>
|
||||
public class AirplaneSelectionUI : MonoBehaviour
|
||||
{
|
||||
#region Inspector References
|
||||
|
||||
[Header("UI References")]
|
||||
[SerializeField] private Button jetPlaneButton;
|
||||
[SerializeField] private Button bobbingPlaneButton;
|
||||
[SerializeField] private Button dropPlaneButton;
|
||||
[SerializeField] private Button confirmButton;
|
||||
|
||||
[Header("Debug")]
|
||||
[SerializeField] private bool showDebugLogs;
|
||||
|
||||
#endregion
|
||||
|
||||
#region State
|
||||
|
||||
private AirplaneAbilityType selectedType;
|
||||
private AirplaneSelectionButton selectedButtonComponent;
|
||||
private bool hasConfirmed;
|
||||
|
||||
public bool HasSelectedType => hasConfirmed;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
public event Action<AirplaneAbilityType> OnTypeSelected;
|
||||
public event Action<AirplaneAbilityType> OnConfirmed;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lifecycle
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
// Setup button listeners
|
||||
if (jetPlaneButton != null)
|
||||
jetPlaneButton.onClick.AddListener(() => SelectType(AirplaneAbilityType.Jet, jetPlaneButton));
|
||||
|
||||
if (bobbingPlaneButton != null)
|
||||
bobbingPlaneButton.onClick.AddListener(() => SelectType(AirplaneAbilityType.Bobbing, bobbingPlaneButton));
|
||||
|
||||
if (dropPlaneButton != null)
|
||||
dropPlaneButton.onClick.AddListener(() => SelectType(AirplaneAbilityType.Drop, dropPlaneButton));
|
||||
|
||||
if (confirmButton != null)
|
||||
{
|
||||
confirmButton.onClick.AddListener(ConfirmSelection);
|
||||
confirmButton.interactable = false; // Disabled until selection made
|
||||
}
|
||||
|
||||
// Hide by default (deactivate container child, not root)
|
||||
if (transform.childCount > 0)
|
||||
{
|
||||
Transform container = transform.GetChild(0);
|
||||
container.gameObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public API
|
||||
|
||||
/// <summary>
|
||||
/// Show the selection UI.
|
||||
/// Activates the immediate child container.
|
||||
/// Script should be on Root, with UI elements under a Container child.
|
||||
/// </summary>
|
||||
public void Show()
|
||||
{
|
||||
selectedType = AirplaneAbilityType.None;
|
||||
selectedButtonComponent = null;
|
||||
hasConfirmed = false;
|
||||
|
||||
if (confirmButton != null)
|
||||
confirmButton.interactable = false;
|
||||
|
||||
// Reset all button highlights
|
||||
ResetButtonHighlights();
|
||||
|
||||
// Populate icons from settings
|
||||
PopulateButtonIcons();
|
||||
|
||||
// Activate the container (immediate child)
|
||||
if (transform.childCount > 0)
|
||||
{
|
||||
Transform container = transform.GetChild(0);
|
||||
container.gameObject.SetActive(true);
|
||||
|
||||
if (showDebugLogs)
|
||||
{
|
||||
Logging.Debug($"[AirplaneSelectionUI] Shown. Activated container: {container.name}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Error("[AirplaneSelectionUI] No child container found! Expected structure: Root(script)->Container->UI Elements");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hide the selection UI.
|
||||
/// Deactivates the immediate child container.
|
||||
/// </summary>
|
||||
public void Hide()
|
||||
{
|
||||
// Deactivate the container (immediate child)
|
||||
if (transform.childCount > 0)
|
||||
{
|
||||
Transform container = transform.GetChild(0);
|
||||
container.gameObject.SetActive(false);
|
||||
|
||||
if (showDebugLogs)
|
||||
{
|
||||
Logging.Debug($"[AirplaneSelectionUI] Hidden. Deactivated container: {container.name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the selected airplane type.
|
||||
/// </summary>
|
||||
public AirplaneAbilityType GetSelectedType()
|
||||
{
|
||||
return selectedType;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void SelectType(AirplaneAbilityType type, Button button)
|
||||
{
|
||||
if (type == AirplaneAbilityType.None)
|
||||
{
|
||||
Logging.Warning("[AirplaneSelectionUI] Attempted to select None type!");
|
||||
return;
|
||||
}
|
||||
|
||||
selectedType = type;
|
||||
|
||||
// Get the AirplaneSelectionButton component (on same GameObject as Button)
|
||||
var buttonComponent = button.GetComponent<AirplaneSelectionButton>();
|
||||
if (buttonComponent == null)
|
||||
{
|
||||
Logging.Warning($"[AirplaneSelectionUI] Button {button.name} is missing AirplaneSelectionButton component!");
|
||||
return;
|
||||
}
|
||||
|
||||
selectedButtonComponent = buttonComponent;
|
||||
|
||||
// Update visual feedback
|
||||
ResetButtonHighlights();
|
||||
HighlightButton(buttonComponent);
|
||||
|
||||
// Enable confirm button
|
||||
if (confirmButton != null)
|
||||
confirmButton.interactable = true;
|
||||
|
||||
// Fire event
|
||||
OnTypeSelected?.Invoke(type);
|
||||
|
||||
if (showDebugLogs)
|
||||
{
|
||||
Logging.Debug($"[AirplaneSelectionUI] Selected type: {type}");
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfirmSelection()
|
||||
{
|
||||
if (selectedType == AirplaneAbilityType.None)
|
||||
{
|
||||
Logging.Warning("[AirplaneSelectionUI] Cannot confirm - no type selected!");
|
||||
return;
|
||||
}
|
||||
|
||||
hasConfirmed = true;
|
||||
|
||||
// Fire event
|
||||
OnConfirmed?.Invoke(selectedType);
|
||||
|
||||
// Hide UI
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void ResetButtonHighlights()
|
||||
{
|
||||
// End highlight on all buttons
|
||||
if (jetPlaneButton != null)
|
||||
{
|
||||
var component = jetPlaneButton.GetComponent<AirplaneSelectionButton>();
|
||||
if (component != null) component.HighlightEnd();
|
||||
}
|
||||
|
||||
if (bobbingPlaneButton != null)
|
||||
{
|
||||
var component = bobbingPlaneButton.GetComponent<AirplaneSelectionButton>();
|
||||
if (component != null) component.HighlightEnd();
|
||||
}
|
||||
|
||||
if (dropPlaneButton != null)
|
||||
{
|
||||
var component = dropPlaneButton.GetComponent<AirplaneSelectionButton>();
|
||||
if (component != null) component.HighlightEnd();
|
||||
}
|
||||
}
|
||||
|
||||
private void HighlightButton(AirplaneSelectionButton buttonComponent)
|
||||
{
|
||||
if (buttonComponent != null)
|
||||
{
|
||||
buttonComponent.HighlightStart();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populate button icons from airplane settings.
|
||||
/// Assumes Image component is on the same GameObject as the Button.
|
||||
/// </summary>
|
||||
private void PopulateButtonIcons()
|
||||
{
|
||||
// Get airplane settings
|
||||
var settings = GameManager.GetSettingsObject<AppleHills.Core.Settings.IAirplaneSettings>();
|
||||
if (settings == null)
|
||||
{
|
||||
if (showDebugLogs)
|
||||
{
|
||||
Logging.Warning("[AirplaneSelectionUI] Could not load airplane settings for icons");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Populate Jet button icon
|
||||
if (jetPlaneButton != null)
|
||||
{
|
||||
var jetConfig = settings.GetAirplaneConfig(AirplaneAbilityType.Jet);
|
||||
if (jetConfig != null && jetConfig.previewSprite != null)
|
||||
{
|
||||
var image = jetPlaneButton.GetComponent<Image>();
|
||||
if (image != null)
|
||||
{
|
||||
image.sprite = jetConfig.previewSprite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Populate Bobbing button icon
|
||||
if (bobbingPlaneButton != null)
|
||||
{
|
||||
var bobbingConfig = settings.GetAirplaneConfig(AirplaneAbilityType.Bobbing);
|
||||
if (bobbingConfig != null && bobbingConfig.previewSprite != null)
|
||||
{
|
||||
var image = bobbingPlaneButton.GetComponent<Image>();
|
||||
if (image != null)
|
||||
{
|
||||
image.sprite = bobbingConfig.previewSprite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Populate Drop button icon
|
||||
if (dropPlaneButton != null)
|
||||
{
|
||||
var dropConfig = settings.GetAirplaneConfig(AirplaneAbilityType.Drop);
|
||||
if (dropConfig != null && dropConfig.previewSprite != null)
|
||||
{
|
||||
var image = dropPlaneButton.GetComponent<Image>();
|
||||
if (image != null)
|
||||
{
|
||||
image.sprite = dropConfig.previewSprite;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showDebugLogs)
|
||||
{
|
||||
Logging.Debug("[AirplaneSelectionUI] Populated airplane icons from settings");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user