Merge pull request #2 from Fretuks/claude/game-styling-animations-4mv9n8
Add smooth transitions and animations throughout UI
This commit is contained in:
@@ -46,6 +46,37 @@
|
|||||||
background-color: var(--kp-bg);
|
background-color: var(--kp-bg);
|
||||||
color: var(--kp-text);
|
color: var(--kp-text);
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
opacity: 1;
|
||||||
|
transition-property: opacity;
|
||||||
|
transition-duration: 220ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.combat-root.scene-fade-hidden {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.combat-root.reduced-motion {
|
||||||
|
transition-duration: 0ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scene-fade-curtain {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgb(0, 0, 0);
|
||||||
|
opacity: 0;
|
||||||
|
transition-property: opacity;
|
||||||
|
transition-duration: 200ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scene-fade-curtain.scene-fade-visible {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reduced-motion .scene-fade-curtain {
|
||||||
|
transition-duration: 0ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
.combat-status-bar {
|
.combat-status-bar {
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
using KernelPanic.UI;
|
||||||
using UnityEngine.SceneManagement;
|
using UnityEngine.SceneManagement;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
namespace KernelPanic.Core
|
namespace KernelPanic.Core
|
||||||
{
|
{
|
||||||
@@ -10,14 +12,38 @@ namespace KernelPanic.Core
|
|||||||
public const string MainMenuSceneName = "MainMenuScene";
|
public const string MainMenuSceneName = "MainMenuScene";
|
||||||
public const string GameSceneName = "GameScene";
|
public const string GameSceneName = "GameScene";
|
||||||
|
|
||||||
public static void LoadMainMenu()
|
private const string CurtainClassName = "scene-fade-curtain";
|
||||||
|
private const string CurtainVisibleClassName = "scene-fade-visible";
|
||||||
|
private const int FadeOutMs = 200;
|
||||||
|
|
||||||
|
public static void LoadMainMenu(VisualElement fadeRoot)
|
||||||
{
|
{
|
||||||
LoadScene(MainMenuSceneName);
|
FadeThenLoad(fadeRoot, MainMenuSceneName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void LoadGame()
|
public static void LoadGame(VisualElement fadeRoot)
|
||||||
{
|
{
|
||||||
LoadScene(GameSceneName);
|
FadeThenLoad(fadeRoot, GameSceneName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FadeThenLoad(VisualElement fadeRoot, string sceneName)
|
||||||
|
{
|
||||||
|
if (fadeRoot == null)
|
||||||
|
{
|
||||||
|
LoadScene(sceneName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VisualElement curtain = new() { pickingMode = PickingMode.Ignore };
|
||||||
|
curtain.AddToClassList(CurtainClassName);
|
||||||
|
fadeRoot.Add(curtain);
|
||||||
|
|
||||||
|
// Two scheduled steps: add the class one tick late so the initial opacity:0 is
|
||||||
|
// actually rendered first and the transition has something to animate from.
|
||||||
|
curtain.schedule.Execute(() => curtain.AddToClassList(CurtainVisibleClassName)).StartingIn(0);
|
||||||
|
|
||||||
|
int delay = UIPreferences.ReducedMotion ? 0 : FadeOutMs;
|
||||||
|
curtain.schedule.Execute(() => LoadScene(sceneName)).StartingIn(delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static for now because menu navigation has no instance state; a loading-screen service can replace this hook later.
|
// Static for now because menu navigation has no instance state; a loading-screen service can replace this hook later.
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ namespace KernelPanic.UI
|
|||||||
LoadStyles();
|
LoadStyles();
|
||||||
ApplyTerminalFont();
|
ApplyTerminalFont();
|
||||||
BuildLayout();
|
BuildLayout();
|
||||||
|
|
||||||
|
root.AddToClassList("scene-fade-hidden");
|
||||||
|
root.schedule.Execute(() => root.RemoveFromClassList("scene-fade-hidden")).StartingIn(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ApplyTerminalFont()
|
private void ApplyTerminalFont()
|
||||||
@@ -515,7 +518,7 @@ namespace KernelPanic.UI
|
|||||||
overlay.Add(OverlayLine($"waves cleared: {runManager.WavesCleared}"));
|
overlay.Add(OverlayLine($"waves cleared: {runManager.WavesCleared}"));
|
||||||
overlay.Add(OverlayLine($"+{runManager.AccruedBandwidth} bandwidth"));
|
overlay.Add(OverlayLine($"+{runManager.AccruedBandwidth} bandwidth"));
|
||||||
overlay.Add(OverlayLine($"+{runManager.AccruedEntropy} entropy"));
|
overlay.Add(OverlayLine($"+{runManager.AccruedEntropy} entropy"));
|
||||||
Button returnButton = new(SceneLoader.LoadMainMenu) { text = "> return to menu" };
|
Button returnButton = new(() => SceneLoader.LoadMainMenu(root)) { text = "> return to menu" };
|
||||||
returnButton.AddToClassList("primary-action");
|
returnButton.AddToClassList("primary-action");
|
||||||
overlay.Add(returnButton);
|
overlay.Add(returnButton);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ namespace KernelPanic.UI
|
|||||||
private bool _hasOpened;
|
private bool _hasOpened;
|
||||||
private string _resultBannerId;
|
private string _resultBannerId;
|
||||||
private string _resultText;
|
private string _resultText;
|
||||||
|
private readonly List<string> _resultRewardLines = new();
|
||||||
|
private readonly List<int> _resultRewardStars = new();
|
||||||
|
private bool _resultRevealed;
|
||||||
|
|
||||||
public void Bind(VisualElement root, DistroDatabase database, FontAsset artFont, GachaService service, PlayerCollection collection, EntropyWallet entropyWallet, Func<IReadOnlyList<DistroDefinition>, PullResolutionResult> pullResolver, Action changedCallback, Action rootCreditExchangeCallback)
|
public void Bind(VisualElement root, DistroDatabase database, FontAsset artFont, GachaService service, PlayerCollection collection, EntropyWallet entropyWallet, Func<IReadOnlyList<DistroDefinition>, PullResolutionResult> pullResolver, Action changedCallback, Action rootCreditExchangeCallback)
|
||||||
{
|
{
|
||||||
@@ -194,11 +197,10 @@ namespace KernelPanic.UI
|
|||||||
_bannerDetail.Add(BuildEntropyPrompt());
|
_bannerDetail.Add(BuildEntropyPrompt());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_resultBannerId == GachaService.BeginnerBannerId && !string.IsNullOrWhiteSpace(_resultText))
|
if (_resultBannerId == GachaService.BeginnerBannerId &&
|
||||||
|
(_resultRewardLines.Count > 0 || !string.IsNullOrWhiteSpace(_resultText)))
|
||||||
{
|
{
|
||||||
Label result = new(_resultText);
|
_bannerDetail.Add(BuildPullResultReveal());
|
||||||
result.AddToClassList("gacha-result");
|
|
||||||
_bannerDetail.Add(result);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,6 +236,8 @@ namespace KernelPanic.UI
|
|||||||
{
|
{
|
||||||
_resultBannerId = bannerId;
|
_resultBannerId = bannerId;
|
||||||
_resultText = $"git pull origin {bannerId}: remote not implemented yet";
|
_resultText = $"git pull origin {bannerId}: remote not implemented yet";
|
||||||
|
_resultRewardLines.Clear();
|
||||||
|
_resultRewardStars.Clear();
|
||||||
RenderSelectedBanner();
|
RenderSelectedBanner();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -243,15 +247,17 @@ namespace KernelPanic.UI
|
|||||||
{
|
{
|
||||||
_resultBannerId = bannerId;
|
_resultBannerId = bannerId;
|
||||||
_resultText = $"git pull failed: {result.FailureReason}";
|
_resultText = $"git pull failed: {result.FailureReason}";
|
||||||
|
_resultRewardLines.Clear();
|
||||||
|
_resultRewardStars.Clear();
|
||||||
RenderSelectedBanner();
|
RenderSelectedBanner();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<string> lines = new();
|
List<string> header = new();
|
||||||
lines.Add($"git pull complete: spent {result.CurrencySpent} {GachaService.FormatCurrencyName(result.CurrencyType)}");
|
header.Add($"git pull complete: spent {result.CurrencySpent} {GachaService.FormatCurrencyName(result.CurrencyType)}");
|
||||||
if (result.EntropySpent > 0)
|
if (result.EntropySpent > 0)
|
||||||
{
|
{
|
||||||
lines.Add($"entropy fallback: spent {result.EntropySpent} entropy");
|
header.Add($"entropy fallback: spent {result.EntropySpent} entropy");
|
||||||
}
|
}
|
||||||
|
|
||||||
List<DistroDefinition> distroRewards = new();
|
List<DistroDefinition> distroRewards = new();
|
||||||
@@ -265,6 +271,8 @@ namespace KernelPanic.UI
|
|||||||
|
|
||||||
PullResolutionResult resolution = _resolvePulledDistros?.Invoke(distroRewards);
|
PullResolutionResult resolution = _resolvePulledDistros?.Invoke(distroRewards);
|
||||||
int distroOutcomeIndex = 0;
|
int distroOutcomeIndex = 0;
|
||||||
|
_resultRewardLines.Clear();
|
||||||
|
_resultRewardStars.Clear();
|
||||||
for (int i = 0; i < result.Rewards.Count; i++)
|
for (int i = 0; i < result.Rewards.Count; i++)
|
||||||
{
|
{
|
||||||
GachaReward reward = result.Rewards[i];
|
GachaReward reward = result.Rewards[i];
|
||||||
@@ -277,15 +285,89 @@ namespace KernelPanic.UI
|
|||||||
|
|
||||||
string suffix = reward.Guaranteed ? " guaranteed" : reward.PityTriggered ? " pity" : string.Empty;
|
string suffix = reward.Guaranteed ? " guaranteed" : reward.PityTriggered ? " pity" : string.Empty;
|
||||||
string outcomeText = FormatPullOutcome(outcome);
|
string outcomeText = FormatPullOutcome(outcome);
|
||||||
lines.Add($"{i + 1:00}: {reward.StarRating}-star {reward.DisplayName}{suffix}{outcomeText}");
|
_resultRewardLines.Add($"{i + 1:00}: {reward.StarRating}-star {reward.DisplayName}{suffix}{outcomeText}");
|
||||||
|
_resultRewardStars.Add(reward.StarRating);
|
||||||
}
|
}
|
||||||
|
|
||||||
_resultBannerId = bannerId;
|
_resultBannerId = bannerId;
|
||||||
_resultText = string.Join("\n", lines);
|
_resultText = string.Join("\n", header);
|
||||||
|
_resultRevealed = false;
|
||||||
_onChanged?.Invoke();
|
_onChanged?.Invoke();
|
||||||
Refresh();
|
Refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private VisualElement BuildPullResultReveal()
|
||||||
|
{
|
||||||
|
VisualElement container = new();
|
||||||
|
container.AddToClassList("gacha-result-block");
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(_resultText))
|
||||||
|
{
|
||||||
|
Label header = new(_resultText);
|
||||||
|
header.AddToClassList("gacha-result");
|
||||||
|
container.Add(header);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_resultRewardLines.Count == 0)
|
||||||
|
{
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
VisualElement list = new();
|
||||||
|
list.AddToClassList("gacha-result-list");
|
||||||
|
container.Add(list);
|
||||||
|
|
||||||
|
bool animate = !_resultRevealed && !UIPreferences.ReducedMotion;
|
||||||
|
for (int i = 0; i < _resultRewardLines.Count; i++)
|
||||||
|
{
|
||||||
|
int stars = _resultRewardStars[i];
|
||||||
|
VisualElement card = new();
|
||||||
|
card.AddToClassList("gacha-result-card");
|
||||||
|
card.AddToClassList(RarityClassForStars(stars));
|
||||||
|
card.Add(new Label(_resultRewardLines[i]));
|
||||||
|
|
||||||
|
if (!animate)
|
||||||
|
{
|
||||||
|
card.AddToClassList("gacha-result-card-shown");
|
||||||
|
if (stars >= 5)
|
||||||
|
{
|
||||||
|
card.AddToClassList("gacha-result-card-flash");
|
||||||
|
}
|
||||||
|
|
||||||
|
list.Add(card);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
card.AddToClassList("gacha-result-card-hidden");
|
||||||
|
list.Add(card);
|
||||||
|
// Scheduled off _bannerDetail (already attached to the panel) rather than the
|
||||||
|
// freshly created card, which has no panel to tick a scheduler on until this
|
||||||
|
// whole tree is attached by the caller.
|
||||||
|
_bannerDetail.schedule.Execute(() =>
|
||||||
|
{
|
||||||
|
card.RemoveFromClassList("gacha-result-card-hidden");
|
||||||
|
card.AddToClassList("gacha-result-card-shown");
|
||||||
|
if (stars >= 5)
|
||||||
|
{
|
||||||
|
card.AddToClassList("gacha-result-card-flash");
|
||||||
|
}
|
||||||
|
}).StartingIn(90 * i + 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
_resultRevealed = true;
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string RarityClassForStars(int stars)
|
||||||
|
{
|
||||||
|
return stars switch
|
||||||
|
{
|
||||||
|
>= 5 => "gacha-result-card-legendary",
|
||||||
|
4 => "gacha-result-card-rare",
|
||||||
|
_ => "gacha-result-card-common"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private static string FormatPullOutcome(PullResolutionOutcome? outcome)
|
private static string FormatPullOutcome(PullResolutionOutcome? outcome)
|
||||||
{
|
{
|
||||||
if (!outcome.HasValue)
|
if (!outcome.HasValue)
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ namespace KernelPanic.UI
|
|||||||
private const string HiddenClassName = "hidden";
|
private const string HiddenClassName = "hidden";
|
||||||
private const string SelectedClassName = "selected";
|
private const string SelectedClassName = "selected";
|
||||||
private const string CursorOnClassName = "cursor-on";
|
private const string CursorOnClassName = "cursor-on";
|
||||||
|
private const string ModalOpenClassName = "modal-open";
|
||||||
|
private const int ModalTransitionMs = 160;
|
||||||
private const string SharedScrollbarStyleResourcePath = "TerminalScrollbars";
|
private const string SharedScrollbarStyleResourcePath = "TerminalScrollbars";
|
||||||
private const float BootIntroSeconds = 1.5f;
|
private const float BootIntroSeconds = 1.5f;
|
||||||
private static bool _bootIntroPlayed;
|
private static bool _bootIntroPlayed;
|
||||||
@@ -157,6 +159,8 @@ namespace KernelPanic.UI
|
|||||||
private bool _suppressNextClick;
|
private bool _suppressNextClick;
|
||||||
private bool _warnedUnresolvedSaveId;
|
private bool _warnedUnresolvedSaveId;
|
||||||
private bool _rootCreditExchangeOpen;
|
private bool _rootCreditExchangeOpen;
|
||||||
|
private IVisualElementScheduledItem _rootCreditExchangeOpenSchedule;
|
||||||
|
private IVisualElementScheduledItem _rootCreditExchangeHideSchedule;
|
||||||
private string _bootIntroCopy;
|
private string _bootIntroCopy;
|
||||||
private Action _rootCreditExchangeMinusHundredClicked;
|
private Action _rootCreditExchangeMinusHundredClicked;
|
||||||
private Action _rootCreditExchangeMinusOneClicked;
|
private Action _rootCreditExchangeMinusOneClicked;
|
||||||
@@ -199,6 +203,7 @@ namespace KernelPanic.UI
|
|||||||
{
|
{
|
||||||
RegisterCallbacks();
|
RegisterCallbacks();
|
||||||
_root.Focus();
|
_root.Focus();
|
||||||
|
_root.EnableInClassList("reduced-motion", UIPreferences.ReducedMotion);
|
||||||
_shellRoot.EnableInClassList("reduced-motion", UIPreferences.ReducedMotion);
|
_shellRoot.EnableInClassList("reduced-motion", UIPreferences.ReducedMotion);
|
||||||
RefreshStaticText();
|
RefreshStaticText();
|
||||||
RefreshCurrencyReadouts();
|
RefreshCurrencyReadouts();
|
||||||
@@ -473,7 +478,11 @@ namespace KernelPanic.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
_rootCreditExchangeOpen = true;
|
_rootCreditExchangeOpen = true;
|
||||||
|
_rootCreditExchangeHideSchedule?.Pause();
|
||||||
_rootCreditExchangeModal.RemoveFromClassList(HiddenClassName);
|
_rootCreditExchangeModal.RemoveFromClassList(HiddenClassName);
|
||||||
|
_rootCreditExchangeOpenSchedule?.Pause();
|
||||||
|
_rootCreditExchangeOpenSchedule = _rootCreditExchangeModal.schedule
|
||||||
|
.Execute(() => _rootCreditExchangeModal.AddToClassList(ModalOpenClassName)).StartingIn(0);
|
||||||
_rootCreditExchangeMessageLabel?.AddToClassList(HiddenClassName);
|
_rootCreditExchangeMessageLabel?.AddToClassList(HiddenClassName);
|
||||||
SetRootCreditExchangeAmount(Math.Min(100, _gachaService.RootCredits));
|
SetRootCreditExchangeAmount(Math.Min(100, _gachaService.RootCredits));
|
||||||
RefreshRootCreditExchange();
|
RefreshRootCreditExchange();
|
||||||
@@ -483,7 +492,12 @@ namespace KernelPanic.UI
|
|||||||
private void CloseRootCreditExchange()
|
private void CloseRootCreditExchange()
|
||||||
{
|
{
|
||||||
_rootCreditExchangeOpen = false;
|
_rootCreditExchangeOpen = false;
|
||||||
_rootCreditExchangeModal?.AddToClassList(HiddenClassName);
|
_rootCreditExchangeOpenSchedule?.Pause();
|
||||||
|
_rootCreditExchangeModal?.RemoveFromClassList(ModalOpenClassName);
|
||||||
|
int delay = UIPreferences.ReducedMotion ? 0 : ModalTransitionMs;
|
||||||
|
_rootCreditExchangeHideSchedule?.Pause();
|
||||||
|
_rootCreditExchangeHideSchedule = _rootCreditExchangeModal?.schedule
|
||||||
|
.Execute(() => _rootCreditExchangeModal.AddToClassList(HiddenClassName)).StartingIn(delay);
|
||||||
_root.Focus();
|
_root.Focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -878,6 +892,10 @@ namespace KernelPanic.UI
|
|||||||
|
|
||||||
private void PlayBootIntroIfNeeded()
|
private void PlayBootIntroIfNeeded()
|
||||||
{
|
{
|
||||||
|
// Always start the shell hidden so returning to the menu (starter chosen, boot intro
|
||||||
|
// already played this session) still gets a fade-in instead of popping in instantly.
|
||||||
|
_shellRoot.AddToClassList("boot-hidden");
|
||||||
|
|
||||||
if (_bootIntroPlayed || UIPreferences.ReducedMotion)
|
if (_bootIntroPlayed || UIPreferences.ReducedMotion)
|
||||||
{
|
{
|
||||||
CompleteBootIntro();
|
CompleteBootIntro();
|
||||||
@@ -889,7 +907,6 @@ namespace KernelPanic.UI
|
|||||||
_bootIntroCharacterCount = 0;
|
_bootIntroCharacterCount = 0;
|
||||||
_bootIntroLogLabel.text = string.Empty;
|
_bootIntroLogLabel.text = string.Empty;
|
||||||
_bootIntroPanel.RemoveFromClassList(HiddenClassName);
|
_bootIntroPanel.RemoveFromClassList(HiddenClassName);
|
||||||
_shellRoot.AddToClassList("boot-hidden");
|
|
||||||
|
|
||||||
_bootIntroSchedule = _root.schedule.Execute(UpdateBootIntro).Every(16);
|
_bootIntroSchedule = _root.schedule.Execute(UpdateBootIntro).Every(16);
|
||||||
}
|
}
|
||||||
@@ -1580,7 +1597,7 @@ namespace KernelPanic.UI
|
|||||||
|
|
||||||
SaveLastRunLoadout(unit, equippedCardIds);
|
SaveLastRunLoadout(unit, equippedCardIds);
|
||||||
RunContext.Set(unit, BuildEquippedCardDefinitions(unit, equippedCardIds), _selectedRunLanguages[0], _selectedRunLanguages[1], _playerCollection.GetVersion(unit.Id));
|
RunContext.Set(unit, BuildEquippedCardDefinitions(unit, equippedCardIds), _selectedRunLanguages[0], _selectedRunLanguages[1], _playerCollection.GetVersion(unit.Id));
|
||||||
SceneLoader.LoadGame();
|
SceneLoader.LoadGame(_root);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IReadOnlyList<CardDefinition> BuildEquippedCardDefinitions(DistroDefinition unit, IReadOnlyList<string> equippedCardIds)
|
private IReadOnlyList<CardDefinition> BuildEquippedCardDefinitions(DistroDefinition unit, IReadOnlyList<string> equippedCardIds)
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ namespace KernelPanic.UI
|
|||||||
public sealed class StarterSelectionController
|
public sealed class StarterSelectionController
|
||||||
{
|
{
|
||||||
private const int StarterCount = 3;
|
private const int StarterCount = 3;
|
||||||
|
private const string ModalOpenClassName = "modal-open";
|
||||||
|
private const int ModalTransitionMs = 160;
|
||||||
|
|
||||||
private readonly List<VisualElement> _cards = new();
|
private readonly List<VisualElement> _cards = new();
|
||||||
private readonly List<Label> _names = new();
|
private readonly List<Label> _names = new();
|
||||||
@@ -35,6 +37,8 @@ namespace KernelPanic.UI
|
|||||||
private bool _showingError;
|
private bool _showingError;
|
||||||
private bool _confirming;
|
private bool _confirming;
|
||||||
private IVisualElementScheduledItem _closeSchedule;
|
private IVisualElementScheduledItem _closeSchedule;
|
||||||
|
private IVisualElementScheduledItem _modalOpenSchedule;
|
||||||
|
private IVisualElementScheduledItem _modalHideSchedule;
|
||||||
|
|
||||||
public bool IsActive => _active;
|
public bool IsActive => _active;
|
||||||
|
|
||||||
@@ -90,7 +94,7 @@ namespace KernelPanic.UI
|
|||||||
_errorLabel.AddToClassList("hidden");
|
_errorLabel.AddToClassList("hidden");
|
||||||
_options.RemoveFromClassList("hidden");
|
_options.RemoveFromClassList("hidden");
|
||||||
_confirmLabel.AddToClassList("hidden");
|
_confirmLabel.AddToClassList("hidden");
|
||||||
_modal.RemoveFromClassList("hidden");
|
OpenModal();
|
||||||
|
|
||||||
for (int i = 0; i < _cards.Count; i++)
|
for (int i = 0; i < _cards.Count; i++)
|
||||||
{
|
{
|
||||||
@@ -165,6 +169,8 @@ namespace KernelPanic.UI
|
|||||||
public void PauseSchedules()
|
public void PauseSchedules()
|
||||||
{
|
{
|
||||||
_closeSchedule?.Pause();
|
_closeSchedule?.Pause();
|
||||||
|
_modalOpenSchedule?.Pause();
|
||||||
|
_modalHideSchedule?.Pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryGetStarters(out IReadOnlyList<DistroDefinition> starters, out string error)
|
private bool TryGetStarters(out IReadOnlyList<DistroDefinition> starters, out string error)
|
||||||
@@ -204,10 +210,18 @@ namespace KernelPanic.UI
|
|||||||
_confirmLabel.AddToClassList("hidden");
|
_confirmLabel.AddToClassList("hidden");
|
||||||
_errorLabel.text = $"starter selection unavailable: {error}. press enter to continue.";
|
_errorLabel.text = $"starter selection unavailable: {error}. press enter to continue.";
|
||||||
_errorLabel.RemoveFromClassList("hidden");
|
_errorLabel.RemoveFromClassList("hidden");
|
||||||
_modal.RemoveFromClassList("hidden");
|
OpenModal();
|
||||||
_root.Focus();
|
_root.Focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OpenModal()
|
||||||
|
{
|
||||||
|
_modalHideSchedule?.Pause();
|
||||||
|
_modal.RemoveFromClassList("hidden");
|
||||||
|
_modalOpenSchedule?.Pause();
|
||||||
|
_modalOpenSchedule = _modal.schedule.Execute(() => _modal.AddToClassList(ModalOpenClassName)).StartingIn(0);
|
||||||
|
}
|
||||||
|
|
||||||
private void Select(int index)
|
private void Select(int index)
|
||||||
{
|
{
|
||||||
if (_activeStarters.Count == 0)
|
if (_activeStarters.Count == 0)
|
||||||
@@ -292,7 +306,11 @@ namespace KernelPanic.UI
|
|||||||
_active = false;
|
_active = false;
|
||||||
_confirming = false;
|
_confirming = false;
|
||||||
_showingError = false;
|
_showingError = false;
|
||||||
_modal.AddToClassList("hidden");
|
_modalOpenSchedule?.Pause();
|
||||||
|
_modal.RemoveFromClassList(ModalOpenClassName);
|
||||||
|
int delay = UIPreferences.ReducedMotion ? 0 : ModalTransitionMs;
|
||||||
|
_modalHideSchedule?.Pause();
|
||||||
|
_modalHideSchedule = _modal.schedule.Execute(() => _modal.AddToClassList("hidden")).StartingIn(delay);
|
||||||
_root.Focus();
|
_root.Focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,6 +144,8 @@ Button {
|
|||||||
border-bottom-color: var(--kp-amber);
|
border-bottom-color: var(--kp-amber);
|
||||||
background-color: var(--kp-bg-solid);
|
background-color: var(--kp-bg-solid);
|
||||||
color: var(--kp-amber);
|
color: var(--kp-amber);
|
||||||
|
transition-property: background-color, color;
|
||||||
|
transition-duration: 120ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
.currency-plus-button:hover {
|
.currency-plus-button:hover {
|
||||||
@@ -205,6 +207,8 @@ Button {
|
|||||||
margin-bottom: 3px;
|
margin-bottom: 3px;
|
||||||
border-left-width: 2px;
|
border-left-width: 2px;
|
||||||
border-left-color: transparent;
|
border-left-color: transparent;
|
||||||
|
transition-property: background-color, border-left-color;
|
||||||
|
transition-duration: 120ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
.command-row:hover,
|
.command-row:hover,
|
||||||
@@ -592,6 +596,8 @@ Button {
|
|||||||
margin-bottom: 3px;
|
margin-bottom: 3px;
|
||||||
border-left-width: 2px;
|
border-left-width: 2px;
|
||||||
border-left-color: transparent;
|
border-left-color: transparent;
|
||||||
|
transition-property: background-color, border-left-color;
|
||||||
|
transition-duration: 120ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
.gacha-banner-row:hover,
|
.gacha-banner-row:hover,
|
||||||
@@ -743,6 +749,8 @@ Button {
|
|||||||
border-bottom-color: transparent;
|
border-bottom-color: transparent;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: var(--kp-muted);
|
color: var(--kp-muted);
|
||||||
|
transition-property: color, border-bottom-color;
|
||||||
|
transition-duration: 120ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
.collection-tab.selected {
|
.collection-tab.selected {
|
||||||
@@ -873,6 +881,8 @@ Button {
|
|||||||
border-left-width: 2px;
|
border-left-width: 2px;
|
||||||
border-left-color: var(--kp-primary);
|
border-left-color: var(--kp-primary);
|
||||||
background-color: var(--kp-hover);
|
background-color: var(--kp-hover);
|
||||||
|
transition-property: background-color;
|
||||||
|
transition-duration: 120ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
.version-upgrade-command:hover {
|
.version-upgrade-command:hover {
|
||||||
@@ -940,6 +950,8 @@ Button {
|
|||||||
padding: 8px 10px;
|
padding: 8px 10px;
|
||||||
border-left-width: 2px;
|
border-left-width: 2px;
|
||||||
border-left-color: transparent;
|
border-left-color: transparent;
|
||||||
|
transition-property: background-color, border-left-color;
|
||||||
|
transition-duration: 120ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
.collection-row.selected {
|
.collection-row.selected {
|
||||||
@@ -1039,6 +1051,8 @@ Button {
|
|||||||
margin-top: 4px;
|
margin-top: 4px;
|
||||||
border-left-width: 2px;
|
border-left-width: 2px;
|
||||||
border-left-color: transparent;
|
border-left-color: transparent;
|
||||||
|
transition-property: background-color, border-left-color;
|
||||||
|
transition-duration: 120ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
.package-row.selected,
|
.package-row.selected,
|
||||||
@@ -1178,6 +1192,25 @@ Button {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background-color: rgba(5, 8, 7, 0.88);
|
background-color: rgba(5, 8, 7, 0.88);
|
||||||
|
opacity: 0;
|
||||||
|
transition-property: opacity;
|
||||||
|
transition-duration: 160ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-overlay.modal-open {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-overlay > .starter-dialog,
|
||||||
|
.modal-overlay > .root-credit-dialog {
|
||||||
|
scale: 0.94 0.94;
|
||||||
|
transition-property: scale;
|
||||||
|
transition-duration: 160ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-overlay.modal-open > .starter-dialog,
|
||||||
|
.modal-overlay.modal-open > .root-credit-dialog {
|
||||||
|
scale: 1 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.starter-dialog {
|
.starter-dialog {
|
||||||
@@ -1230,6 +1263,8 @@ Button {
|
|||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: var(--kp-amber);
|
color: var(--kp-amber);
|
||||||
-unity-text-align: middle-center;
|
-unity-text-align: middle-center;
|
||||||
|
transition-property: color, border-left-color, border-right-color, border-top-color, border-bottom-color;
|
||||||
|
transition-duration: 120ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-close-button:hover {
|
.modal-close-button:hover {
|
||||||
@@ -1317,6 +1352,12 @@ Button {
|
|||||||
border-top-color: var(--kp-border);
|
border-top-color: var(--kp-border);
|
||||||
border-bottom-color: var(--kp-border);
|
border-bottom-color: var(--kp-border);
|
||||||
background-color: var(--kp-panel);
|
background-color: var(--kp-panel);
|
||||||
|
transition-property: background-color, border-left-color, border-right-color, border-top-color, border-bottom-color, scale;
|
||||||
|
transition-duration: 140ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.starter-card:hover {
|
||||||
|
scale: 1.015 1.015;
|
||||||
}
|
}
|
||||||
|
|
||||||
.starter-card.selected {
|
.starter-card.selected {
|
||||||
@@ -1364,6 +1405,8 @@ Button {
|
|||||||
background-color: var(--kp-panel);
|
background-color: var(--kp-panel);
|
||||||
color: var(--kp-primary);
|
color: var(--kp-primary);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
transition-property: background-color, color;
|
||||||
|
transition-duration: 120ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
.terminal-button:hover {
|
.terminal-button:hover {
|
||||||
@@ -1397,3 +1440,92 @@ Button {
|
|||||||
.prompt-text {
|
.prompt-text {
|
||||||
color: var(--kp-primary);
|
color: var(--kp-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scene-fade-curtain {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: rgb(0, 0, 0);
|
||||||
|
opacity: 0;
|
||||||
|
transition-property: opacity;
|
||||||
|
transition-duration: 200ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scene-fade-curtain.scene-fade-visible {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gacha-result-block {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gacha-result-list {
|
||||||
|
flex-direction: column;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gacha-result-card {
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 26px;
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 8px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
border-left-width: 2px;
|
||||||
|
border-left-color: var(--kp-primary-dim);
|
||||||
|
background-color: var(--kp-hover);
|
||||||
|
color: var(--kp-primary);
|
||||||
|
opacity: 1;
|
||||||
|
translate: 0 0;
|
||||||
|
scale: 1 1;
|
||||||
|
transition-property: opacity, translate, scale, border-left-color, background-color;
|
||||||
|
transition-duration: 220ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gacha-result-card-hidden {
|
||||||
|
opacity: 0;
|
||||||
|
translate: -12px 0;
|
||||||
|
scale: 0.96 0.96;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gacha-result-card-shown {
|
||||||
|
opacity: 1;
|
||||||
|
translate: 0 0;
|
||||||
|
scale: 1 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gacha-result-card-rare {
|
||||||
|
border-left-color: var(--kp-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.gacha-result-card-legendary {
|
||||||
|
border-left-color: var(--kp-amber);
|
||||||
|
color: var(--kp-amber);
|
||||||
|
}
|
||||||
|
|
||||||
|
.gacha-result-card-flash {
|
||||||
|
background-color: var(--kp-amber);
|
||||||
|
color: var(--kp-bg);
|
||||||
|
transition-property: background-color, color;
|
||||||
|
transition-duration: 90ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reduced-motion .scene-fade-curtain,
|
||||||
|
.reduced-motion .modal-overlay,
|
||||||
|
.reduced-motion .modal-overlay > .starter-dialog,
|
||||||
|
.reduced-motion .modal-overlay > .root-credit-dialog,
|
||||||
|
.reduced-motion .command-row,
|
||||||
|
.reduced-motion .gacha-banner-row,
|
||||||
|
.reduced-motion .collection-tab,
|
||||||
|
.reduced-motion .collection-row,
|
||||||
|
.reduced-motion .package-row,
|
||||||
|
.reduced-motion .starter-card,
|
||||||
|
.reduced-motion .terminal-button,
|
||||||
|
.reduced-motion .currency-plus-button,
|
||||||
|
.reduced-motion .modal-close-button,
|
||||||
|
.reduced-motion .version-upgrade-command,
|
||||||
|
.reduced-motion .gacha-result-card {
|
||||||
|
transition-duration: 0ms;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user