Add main menu scene with Rive UI, procedural background, and scene transitions
- Add Menu scene with Rive-driven login and navigation UI (RiveLoginController, RiveNavigationController) for entering a username and starting/navigating the client via Rive triggers - Add SceneTransitionController to fade out and load the Landscape gameplay scene when Play is selected - Add procedural low-poly triangle field background and animated wave panel (LowPolyTriangleField, TriangleWavePanel) with matching editor menus and materials - Add MenuLightAnimator for animated menu lighting and UI fade helpers (MenuFadeIn, DebugFadeToggle/Bridge) - Rename SampleScene to Landscape and wire ChatNetworkManager to hide the new Rive login canvas once gameplay starts - Bump Input System action codegen version and add Rive package references/project settings updates to support the new UI
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
using ProceduralEditor;
|
||||
using Rive;
|
||||
using Rive.Components;
|
||||
using System.Reflection.Metadata;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
/// Sends keyboard navigation commands to the Rive menu and
|
||||
/// activates the Play option when Enter is pressed
|
||||
public class RiveNavigationController : MonoBehaviour
|
||||
{
|
||||
[Header("Rive")]
|
||||
[Tooltip("RiveWidget that hosts the menu artboard.")]
|
||||
[SerializeField] private RiveWidget riveWidget;
|
||||
|
||||
[Header("Scene Transition")]
|
||||
[Tooltip("Object containing the SceneTransitionController component.")]
|
||||
[SerializeField] private SceneTransitionController sceneTransitionController;
|
||||
|
||||
[Header("Menu Selection")]
|
||||
[Tooltip("Total number of selectable Rive menu buttons.")]
|
||||
[Min(1)]
|
||||
[SerializeField] private int menuItemCount = 1;
|
||||
|
||||
|
||||
private const string NextTriggerName = "nextButtonClicked";
|
||||
private const string PreviousTriggerName = "previousButtonClicked";
|
||||
private const int PlayIndex = 0;
|
||||
|
||||
private ViewModelInstanceTriggerProperty nextTrigger;
|
||||
private ViewModelInstanceTriggerProperty previousTrigger;
|
||||
|
||||
private int selectedIndex;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (riveWidget == null)
|
||||
{
|
||||
Debug.LogError($"{nameof(RiveNavigationController)}: riveWidget is not assigned.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sceneTransitionController == null)
|
||||
{
|
||||
Debug.LogError($"{nameof(RiveNavigationController)}: SceneTransitionController is not assigned.");
|
||||
}
|
||||
|
||||
riveWidget.OnWidgetStatusChanged += HandleWidgetStatusChanged;
|
||||
// In case the widget already finished loading before we subscribed.
|
||||
HandleWidgetStatusChanged();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
if (riveWidget != null)
|
||||
riveWidget.OnWidgetStatusChanged -= HandleWidgetStatusChanged;
|
||||
}
|
||||
|
||||
private void HandleWidgetStatusChanged()
|
||||
{
|
||||
if (riveWidget.Status != WidgetStatus.Loaded)
|
||||
return;
|
||||
|
||||
ViewModelInstance viewModelInstance = riveWidget.StateMachine?.ViewModelInstance;
|
||||
if (viewModelInstance == null)
|
||||
{
|
||||
Debug.LogError($"{nameof(RiveNavigationController)}: ViewModelInstance is null. " +
|
||||
"Set Data Binding Mode to Auto Bind Default on the Rive Widget.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Cache both triggers once the artboard is ready so Update() doesn't do
|
||||
// string lookups every frame.
|
||||
nextTrigger = viewModelInstance.GetTriggerProperty(NextTriggerName);
|
||||
previousTrigger = viewModelInstance.GetTriggerProperty(PreviousTriggerName);
|
||||
|
||||
if (nextTrigger == null)
|
||||
Debug.LogError($"{nameof(RiveNavigationController)}: Trigger '{NextTriggerName}' not found on view model.");
|
||||
if (previousTrigger == null)
|
||||
Debug.LogError($"{nameof(RiveNavigationController)}: Trigger '{PreviousTriggerName}' not found on view model.");
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
Keyboard keyboard = Keyboard.current;
|
||||
|
||||
if (keyboard == null)
|
||||
return;
|
||||
|
||||
if (keyboard.rightArrowKey.wasPressedThisFrame)
|
||||
{
|
||||
MoveSelection(+1);
|
||||
nextTrigger?.Trigger();
|
||||
}
|
||||
|
||||
if (keyboard.leftArrowKey.wasPressedThisFrame)
|
||||
{
|
||||
MoveSelection(-1);
|
||||
previousTrigger?.Trigger();
|
||||
}
|
||||
|
||||
bool enterPressed = keyboard.enterKey.wasPressedThisFrame || keyboard.numpadEnterKey.wasPressedThisFrame;
|
||||
|
||||
if (enterPressed && selectedIndex == PlayIndex)
|
||||
{
|
||||
if (sceneTransitionController == null)
|
||||
{
|
||||
Debug.LogError($"{nameof(RiveNavigationController)}: SceneTransitionController is not assigned.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sceneTransitionController.LoadGameplayScene();
|
||||
}
|
||||
}
|
||||
|
||||
private void MoveSelection(int direction)
|
||||
{
|
||||
if (menuItemCount <= 0)
|
||||
return;
|
||||
|
||||
selectedIndex += direction;
|
||||
|
||||
if (selectedIndex >= menuItemCount)
|
||||
selectedIndex = 0;
|
||||
|
||||
if (selectedIndex < 0)
|
||||
selectedIndex = menuItemCount - 1;
|
||||
|
||||
Debug.Log($"Rive menu selection index: {selectedIndex}");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user