riversong code showcase
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user