riversong code showcase

This commit is contained in:
Daniele Marotta
2026-05-21 15:52:18 +02:00
commit 4c9eea1c02
462 changed files with 23406 additions and 0 deletions

View File

@@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using UnityEngine;
namespace DanieleMarotta.RiversongCodeShowcase
{
public class OnboardingPanelUIController : UIControllerSystem<OnboardingPanelUIView>, IDisposable, IUpdatable
{
[InjectService]
private ISignalBus _signalBus;
[InjectService]
private GameConfig _config;
[InjectService]
private ISoundPlayer _soundPlayer;
private readonly Queue<OnboardingEvents> _completedEvents = new();
private bool _isWaitingToShowMessage;
private float _currentMessageTime;
public OnboardingPanelUIController(IServiceLocator serviceLocator) : base(serviceLocator)
{
}
protected override OnboardingPanelUIView View => UIRoot.GetView<OnboardingPanelUIView>();
public override async UniTask InitializeAsync()
{
await base.InitializeAsync();
_signalBus.Subscribe<OnboardingEventCompleted>(OnOnboardingEventCompleted);
}
public void Dispose()
{
_signalBus.Unsubscribe<OnboardingEventCompleted>(OnOnboardingEventCompleted);
}
public void Update()
{
if (View.IsShowingAnyMessage())
{
_currentMessageTime += Time.unscaledDeltaTime;
if (_currentMessageTime > _config.Onboarding.MessageDuration) View.CloseCurrentMessage();
return;
}
_currentMessageTime = 0;
if (_isWaitingToShowMessage || !_completedEvents.TryDequeue(out var completedEvent)) return;
_ = ShowMessageAsync(completedEvent);
}
private async UniTask ShowMessageAsync(OnboardingEvents completedEvent)
{
_isWaitingToShowMessage = true;
await UniTask.WaitForSeconds(1, true);
View.ShowMessage(GetMessage(completedEvent));
_soundPlayer.Play(SystemSoundId.OnboardingMessage);
_isWaitingToShowMessage = false;
}
private string GetMessage(OnboardingEvents completedEvent)
{
foreach (var entry in _config.Onboarding.Messages.Entries)
{
if (entry.Event != completedEvent) continue;
return entry.Text ?? $"Unknown Event {completedEvent}";
}
return $"Unknown Event {completedEvent}";
}
private void OnOnboardingEventCompleted(OnboardingEventCompleted signal)
{
_completedEvents.Enqueue(signal.Event);
}
}
}

View File

@@ -0,0 +1,92 @@
using System.Text;
using Cysharp.Threading.Tasks;
using PrimeTween;
using UnityEngine.UIElements;
namespace DanieleMarotta.RiversongCodeShowcase
{
[UIView("onboarding-panel")]
public class OnboardingPanelUIView : UIView
{
private VisualElement _messages;
public override UniTask InitializeAsync(UIService uiService, VisualElement rootElement)
{
base.InitializeAsync(uiService, rootElement);
_messages = rootElement.Q<VisualElement>(className: "onboarding-panel__messages");
return UniTask.CompletedTask;
}
public bool IsShowingAnyMessage()
{
return _messages.childCount > 0;
}
public void ShowMessage(string message)
{
var element = UIService.TemplateLibrary.OnboardingPanel.Message.CloneTree();
element.Q<Button>().RegisterCallbackOnce<ClickEvent>(_ => CloseCurrentMessage());
_messages.Add(element);
ShowMessageAsync(element, message).Forget();
}
private async UniTask ShowMessageAsync(VisualElement element, string message)
{
UIVisibilityAnimation.PlayShowTween(element).ToUniTask().Forget();
await AnimateTextAsync(element, message);
PlayReminderAnimationAsync(element).Forget();
}
private async UniTask AnimateTextAsync(VisualElement element, string message)
{
var label = element.Q<Label>(className: "onboarding-message__body");
label.text = string.Empty;
var visibleText = new StringBuilder(message.Length);
for (var i = 0; i < message.Length; i++)
{
if (message[i] == '<')
{
var tagEnd = message.IndexOf('>', i + 1);
if (tagEnd >= 0)
{
visibleText.Append(message, i, tagEnd - i + 1);
label.text = visibleText.ToString();
i = tagEnd;
continue;
}
}
visibleText.Append(message[i]);
label.text = visibleText.ToString();
await UniTask.WaitForSeconds(0.03f, true);
}
}
private async UniTask PlayReminderAnimationAsync(VisualElement message)
{
while (message.panel != null)
{
await UniTask.WaitForSeconds(5, true);
await Sequence.Create(useUnscaledTime: true)
.Chain(Tween.Custom(0, 3, 0.1f, value => message.style.translate = new Translate(value, 0), Ease.OutQuad))
.Chain(Tween.Custom(3, -2.5f, 0.14f, value => message.style.translate = new Translate(value, 0), Ease.InOutQuad))
.Chain(Tween.Custom(-2.5f, 1.5f, 0.12f, value => message.style.translate = new Translate(value, 0), Ease.InOutQuad))
.Chain(Tween.Custom(1.5f, 0, 0.1f, value => message.style.translate = new Translate(value, 0), Ease.OutQuad));
}
}
public void CloseCurrentMessage()
{
if (_messages.childCount == 0) return;
_messages[0].RemoveFromHierarchy();
}
}
}