287 lines
19 KiB
C#
287 lines
19 KiB
C#
using System;
|
|
using BlockOutReplica.Gameplay;
|
|
using UnityEngine;
|
|
|
|
namespace BlockOutReplica.Presentation
|
|
{
|
|
public sealed partial class BlockOutHud
|
|
{
|
|
private void DrawInteractionOverlay(float left, float scale)
|
|
{
|
|
if (game.Modal == GameModal.None) return;
|
|
Color previous = GUI.color;
|
|
GUI.color = new Color(0,0,0,game.Modal==GameModal.Quit?.89411765f:.72f);
|
|
GUI.DrawTexture(new Rect(0,0,Screen.width,Screen.height), Texture2D.whiteTexture);
|
|
GUI.color = previous;
|
|
// These layouts come from the original popup prefabs. Do not
|
|
// force them into the generic purchase/confirmation dialog layout.
|
|
if (game.Modal == GameModal.PreLevel) { DrawEntrancePopup(left, scale); return; }
|
|
if (game.Modal == GameModal.Pause) { DrawPausePopup(left, scale); return; }
|
|
if (game.Modal == GameModal.Quit) { DrawQuitPopup(left, scale); return; }
|
|
if (game.Modal == GameModal.Failed) { DrawFailedPopup(left, scale); return; }
|
|
if (game.Modal == GameModal.OutOfTime) { DrawOutOfTimePopup(left, scale); return; }
|
|
DrawNineSlice(Load("Popup_BG_Default_0"), D(left, scale, 55.3f, 181.3f, 429.3f, 557.2f), scale * .46875f);
|
|
GUIStyle text = CreateTextStyle(Mathf.RoundToInt(20 * scale));
|
|
GUIStyle small = CreateTextStyle(Mathf.RoundToInt(15 * scale));
|
|
string heading = game.Modal == GameModal.Pause ? "Pause" : game.Modal == GameModal.Restart ? "Restart?" :
|
|
game.Modal == GameModal.Quit ? "Quit level?" : game.Modal == GameModal.OutOfTime ? "Out of Time" :
|
|
game.Modal == GameModal.GiveUp ? "Give up?" : game.Modal == GameModal.Failed ? "Failed" :
|
|
game.Modal == GameModal.PreLevel ? "Level " + game.LevelNumber : game.Modal == GameModal.Settings ? "Settings" :
|
|
game.Modal == GameModal.Lives ? "Lives" : game.Modal == GameModal.BoosterPurchase ? "Get " + game.PurchaseBooster : "Information";
|
|
DrawOriginalPopupTitle(D(left, scale, 85, 160, 370, 73), heading, scale);
|
|
DrawPopupClose(left, scale, false);
|
|
Rect primary = D(left, scale, 135, 551, 270, 68);
|
|
Rect secondary = D(left, scale, 135, 637, 270, 58);
|
|
switch (game.Modal)
|
|
{
|
|
case GameModal.Settings:
|
|
DrawSettingRow(left, scale, 320, "Sounds", game.Player.Sounds, game.ToggleSounds);
|
|
DrawSettingRow(left, scale, 384, "Music", game.Player.Music, game.ToggleMusic);
|
|
DrawSettingRow(left, scale, 448, "Haptics", game.Player.Haptics, game.ToggleHaptics);
|
|
if (ActionButton(primary, "Done", scale)) game.CloseModal();
|
|
break;
|
|
case GameModal.Restart:
|
|
case GameModal.Quit:
|
|
DrawText(game.HasStarted ? "You will lose 1 life!" : "This level has not started.", D(left, scale, 80, 350, 380, 65), text);
|
|
DrawSprite(Load("MoreLives_Icon_Heart"), D(left, scale, 225, 414, 90, 80));
|
|
if (ActionButton(primary, game.Modal == GameModal.Restart ? "Restart" : "Quit", scale, true))
|
|
{ if (game.Modal == GameModal.Restart) game.ConfirmRestart(); else game.ConfirmQuit(); }
|
|
if (ActionButton(secondary, "Cancel", scale)) game.CloseModal();
|
|
break;
|
|
case GameModal.GiveUp:
|
|
DrawSprite(clockIcon, D(left, scale, 220, 318, 100, 100));
|
|
DrawText("You will lose 1 life!", D(left, scale, 75, 433, 390, 60), text);
|
|
if (ActionButton(primary, "Play On " + game.ContinueCost, scale)) game.ContinueWithCoins();
|
|
if (ActionButton(secondary, "Give up", scale, true)) game.GiveUpRun();
|
|
break;
|
|
case GameModal.BoosterPurchase:
|
|
int index = (int)game.PurchaseBooster - 1;
|
|
DrawSprite(boosterIcons[Mathf.Clamp(index,0,2)], D(left, scale, 220, 326, 100, 100));
|
|
DrawText("Buy 1 booster with coins", D(left, scale, 90, 447, 360, 55), text);
|
|
if (ActionButton(primary, "Buy 1 " + game.BoosterCost, scale)) game.BuySelectedBooster();
|
|
if (ActionButton(secondary, "Cancel", scale, true)) game.CloseModal();
|
|
break;
|
|
case GameModal.Lives:
|
|
DrawSprite(Load("MoreLives_Icon_Heart"), D(left, scale, 215, 315, 110, 105));
|
|
DrawText($"{game.Player.Lives} / {game.Player.MaxLives}", D(left, scale, 170, 422, 200, 50), text);
|
|
double seconds = game.Player.SecondsUntilLife;
|
|
DrawText(game.Player.Lives >= game.Player.MaxLives ? "Lives are full" : $"Next life {(int)seconds / 60:00}:{(int)seconds % 60:00}",
|
|
D(left, scale, 90, 482, 360, 42), small);
|
|
bool enabled = GUI.enabled; GUI.enabled = game.Player.Lives < game.Player.MaxLives;
|
|
if (ActionButton(primary, "Refill " + game.LifeRefillCost, scale)) game.BuyLifeRefill();
|
|
GUI.enabled = enabled;
|
|
if (ActionButton(secondary, "Back", scale)) game.CloseModal();
|
|
break;
|
|
case GameModal.Info:
|
|
DrawText(game.Notice, D(left, scale, 90, 340, 360, 170), text);
|
|
if (ActionButton(primary, "OK", scale)) game.CloseModal();
|
|
break;
|
|
}
|
|
if (!string.IsNullOrEmpty(game.Notice) && game.Modal != GameModal.Info)
|
|
DrawText(game.Notice, D(left, scale, 90, 710, 360, 42), small);
|
|
}
|
|
|
|
private void DrawEntrancePopup(float left, float scale)
|
|
{
|
|
// Original L10 runtime collapses the unused supply-box section.
|
|
// These dimensions come from the observed 882x1644 screen (game
|
|
// viewport y=76..1644), not the prefab's expanded initial size.
|
|
DrawNineSlice(Load("Popup_BG_Default_0"), D(left, scale, 65, 296, 413, 418), scale * .46875f);
|
|
DrawOriginalPopupTitle(D(left, scale, 70, 239, 400, 106), "Level " + game.LevelNumber, scale, 60);
|
|
DrawPopupClose(left, scale, true);
|
|
DrawMirroredSlicedPanel(Load("Prelevel_Booster_Area_Default"),
|
|
D(left, scale, 107, 376, 326, 145), scale * .46875f);
|
|
DrawText("Select Boosters:", D(left, scale, 170, 389, 200, 28), PopupTextStyle(21, scale, false));
|
|
DrawLockedPreBooster(left, scale, 214.12f, 462.8f);
|
|
DrawLockedPreBooster(left, scale, 327.75f, 463.64f);
|
|
if (PopupActionButton(D(left, scale, 152.35f, 566.06f, 235.3f, 97.97f), "Play", scale,
|
|
"Prelevel_Btn_Play", "Prelevel_Btn_Play_Bg_Default", 52)) game.EnterPreparedLevel();
|
|
DrawPopupNotice(left, scale);
|
|
}
|
|
|
|
private void DrawLockedPreBooster(float left, float scale, float cx, float cy)
|
|
{
|
|
DrawMirroredButton(Load("Prelevel_Booster_Btn_Bg_Default"), D(left, scale, cx - 45.47f, cy - 45.7f, 90.94f, 91.4f));
|
|
DrawMirroredButton(Load("Prelevel_Booster_Btn_Blue"), D(left, scale, cx - 39.375f, cy - 39.375f, 78.75f, 78.75f));
|
|
DrawSprite(Load("PrelevelPopup_Lock_Icon"), D(left, scale, cx - 22.27f, cy - 27.19f, 44.53f, 54.38f));
|
|
// There is no verified unlock threshold or purchase action for these
|
|
// pre-boosters. Never route them to the in-level booster inventory.
|
|
}
|
|
|
|
private void DrawPausePopup(float left, float scale)
|
|
{
|
|
DrawNineSlice(Load("Popup_BG_Default_0"), D(left, scale, 55.3f, 181.3f, 429.3f, 557.2f), scale * .46875f);
|
|
DrawOriginalPopupTitle(D(left, scale, 85, 160.05f, 370, 73), "Pause", scale);
|
|
DrawPopupClose(left, scale, false);
|
|
DrawOriginalSettingRow(left, scale, 297.06f, "Sounds:", "Pause_Icon_Sounds", game.Player.Sounds, game.ToggleSounds);
|
|
DrawOriginalSettingRow(left, scale, 385.05f, "Musics:", "Pause_Icon_Musics", game.Player.Music, game.ToggleMusic);
|
|
DrawSprite(Load("Pause_Horizontal_Seperator"),D(left,scale,119,437,302,9));
|
|
if (PopupActionButton(D(left, scale, 163.83f, 478.13f, 212.34f, 88.13f), "Resume", scale,
|
|
"Pause_Btn_Resume", "Pause_Btn_BG", 35)) game.CloseModal();
|
|
if (PopupActionButton(D(left, scale, 163.83f, 586.88f, 212.34f, 88.13f), "Quit", scale,
|
|
"Pause_Btn_Quit", "Pause_Btn_BG", 35)) game.RequestQuit();
|
|
DrawPopupNotice(left, scale);
|
|
}
|
|
|
|
private void DrawOriginalSettingRow(float left, float scale, float cy, string label, string icon, bool value, Action toggle)
|
|
{
|
|
DrawSprite(Load(icon), D(left, scale, 129.8f, cy - 18, 33, 36));
|
|
DrawOriginalText(label,D(left,scale,175.4f,cy-26,110,52),Mathf.RoundToInt(26*scale),OriginalTextRole.PopupLabel);
|
|
Rect track = D(left, scale, 287.56f, cy - 26.74f, 134.79f, 53.47f);
|
|
DrawNineSlice(Load("Pause_Toggle_BG"), track, scale * .46875f);
|
|
Rect off = D(left, scale, 291.71f, cy - 24.14f, 64.22f, 48.28f);
|
|
Rect on = D(left, scale, 354.05f, cy - 24.14f, 64.22f, 48.28f);
|
|
DrawSprite(Load(value ? "Pause_Toggle_Btn_On" : "Pause_Toggle_Btn_Off"), value ? on : off);
|
|
var offStyle=PopupTextStyle(23,scale,false);offStyle.normal.textColor=new Color(.22f,.16f,.62f);
|
|
var onStyle=PopupTextStyle(23,scale,false);onStyle.normal.textColor=value?new Color(.16f,.29f,.08f):new Color(.22f,.16f,.62f);
|
|
DrawText("Off", off, offStyle);DrawText("On", on, onStyle);
|
|
if (GUI.Button(track, GUIContent.none, GUIStyle.none)) { game.PlayUiSound(); toggle(); }
|
|
}
|
|
|
|
private void DrawFailedPopup(float left, float scale)
|
|
{
|
|
DrawNineSlice(Load("Popup_BG_Default_0"), D(left, scale, 54.94f, 182.30f, 430.13f, 556.21f), scale * .46875f);
|
|
Sprite titleArt = Load("Fail_Popup_Title_Default");
|
|
if (titleArt != null) DrawSprite(titleArt, D(left, scale, 151.17f, 151.05f, 237.66f, 139.22f));
|
|
else DrawOriginalPopupTitle(D(left, scale, 85, 160, 370, 73), "Failed", scale);
|
|
DrawPopupClose(left, scale, false);
|
|
DrawOriginalTitle("Level "+game.LevelNumber,D(left,scale,100,306,340,66),Mathf.RoundToInt(40*scale));
|
|
DrawSprite(Load("Fail_Popup_Coins"),D(left,scale,162,395,207,115));
|
|
DrawSlicedSprite(Load("Fail_Popup_Coins_Counter_Default"),D(left,scale,211,488,122,53));
|
|
DrawOriginalText(game.LevelRewardPreview.ToString(),D(left,scale,230,489,64,48),Mathf.RoundToInt(41*scale),
|
|
OriginalTextRole.Counter,TextAnchor.MiddleCenter,new Color(1,.76f,.25f));
|
|
DrawSlicedSprite(Load("Fail_Popup_X_Icon"),D(left,scale,303,476,65,65),OriginalSpriteLayout.MirroredHalf);
|
|
if (PopupActionButton(D(left, scale, 152.35f, 588.5f, 235.3f, 98), "Try Again", scale,
|
|
"Fail_Popup_Btn", "Fail_Popup_Btn_Stroke", 39)) game.RetryFailedLevel();
|
|
// Preserve the replica's Failed CloseModal -> GoHome callback; no
|
|
// extra red Home button is added below the native Try Again button.
|
|
DrawPopupNotice(left, scale);
|
|
}
|
|
|
|
private void DrawQuitPopup(float left,float scale)
|
|
{
|
|
// Observed L10 runtime: this banner extends to both viewport edges.
|
|
// Its narrow left strip provides the native horizontal rails; the
|
|
// rounded right cap from the prefab is outside the visible viewport.
|
|
DrawSprite(Load("Endgame_Popup_Left_Default"),new Rect(0,229*scale,Screen.width,471.4f*scale));
|
|
DrawSprite(Load("Endgame_Popup_Inside_Default"),new Rect(0,302*scale,Screen.width,203*scale));
|
|
DrawOriginalText("Are You Sure?",D(left,scale,90,252,360,51),Mathf.RoundToInt(39*scale),OriginalTextRole.PopupLabel);
|
|
DrawSprite(Load("broken_heart"),D(left,scale,189.8f,343.5f,159.2f,120.6f));
|
|
DrawOriginalText("You will lose 1 life!",D(left,scale,105,516,330,35),Mathf.RoundToInt(26*scale),OriginalTextRole.PopupLabel);
|
|
Rect coins=D(left,scale,71.6f,175.1f,115.1f,40.4f);
|
|
DrawSlicedSprite(Load("Endgame_Coin_BG_Defaut"),D(left,scale,91.6f,175.1f,95.1f,40.4f));
|
|
DrawSprite(Load("Endgame_Coin_Icon"),D(left,scale,71.6f,175.1f,40,40));
|
|
DrawOriginalText(game.Player.Coins.ToString(),D(left,scale,116,177,64,35),Mathf.RoundToInt(28*scale),OriginalTextRole.Counter);
|
|
Rect close=D(left,scale,421.8f,218,52,50.8f);
|
|
DrawSprite(Load("Settings_Exit_Btn_0"),close);
|
|
DrawSprite(Load("Settings_Exit_Icon_1"),D(left,scale,434.5f,229.5f,26.3f,27.2f));
|
|
if(GUI.Button(close,GUIContent.none,GUIStyle.none)){game.PlayUiSound();game.CloseModal();}
|
|
if(PopupActionButton(D(left,scale,150.6f,562,240.6f,100.4f),"Quit",scale,
|
|
"Endgame_Btn_Quit","Endgame_Btn_Stroke_Quit",43))game.ConfirmQuit();
|
|
}
|
|
|
|
private void DrawOutOfTimePopup(float left, float scale)
|
|
{
|
|
// StuckPopup has a full-screen dark backdrop, not Popup_BG_Default.
|
|
// Only its coin continuation branch is currently implemented. The
|
|
// prefab also contains free/ad variants; their availability is not
|
|
// established, so no non-functional ad button is drawn here.
|
|
DrawOriginalPopupTitle(D(left, scale, 85, 180.8f, 370, 73), "Out of Time", scale);
|
|
DrawSprite(Load("icon_notime") ?? clockIcon, D(left, scale, 132.98f, 297.11f, 272.34f, 281.72f));
|
|
DrawText("+30 seconds", D(left, scale, 110, 582.05f, 320, 72), PopupTextStyle(32, scale, true));
|
|
Rect button = D(left, scale, 115, 713.6f, 310, 98);
|
|
Rect frame = new Rect(button.x - 7 * scale, button.y - 7 * scale, button.width + 14 * scale, button.height + 14 * scale);
|
|
DrawMirroredButton(Load("Home_Button_Bg"), frame);
|
|
DrawMirroredButton(Load("Home_Button_Green_0") ?? Load("Home_Button_Green"), button);
|
|
DrawText("Play On", D(left, scale, 135, 723.3f, 166, 68), PopupTextStyle(29, scale, true));
|
|
DrawSprite(Load("icon_coin_bttn"), D(left, scale, 291, 735.6f, 35, 36));
|
|
DrawText(game.ContinueCost.ToString(), D(left, scale, 330, 723.3f, 80, 68), PopupTextStyle(27, scale, true));
|
|
if (GUI.Button(frame, GUIContent.none, GUIStyle.none)) { game.PlayUiSound(); game.ContinueWithCoins(); }
|
|
Rect close = D(left, scale, 423.55f, 57.13f, 48.75f, 48.75f);
|
|
DrawSprite(Load("Settings_Exit_Btn"), close);
|
|
DrawSprite(Load("Settings_Exit_Icon_1") ?? Load("Settings_Exit_Icon"), D(left, scale, 434.8f, 67.9f, 26.25f, 27.19f));
|
|
if (GUI.Button(close, GUIContent.none, GUIStyle.none)) { game.PlayUiSound(); game.CloseModal(); }
|
|
if (!string.IsNullOrEmpty(game.Notice))
|
|
DrawText(game.Notice, D(left, scale, 90, 839, 360, 48), PopupTextStyle(17, scale, true));
|
|
}
|
|
|
|
private void DrawPopupClose(float left, float scale, bool entrance)
|
|
{
|
|
float cy = entrance ? 341f : 236.11f;
|
|
Rect body = D(left, scale, 425.2f, cy - 26.72f, 53.44f, 53.44f);
|
|
DrawSprite(Load(entrance ? "Settings_Exit_Btn_1" : "Settings_Exit_Btn_0") ?? Load("Settings_Exit_Btn"), body);
|
|
DrawSprite(Load("Settings_Exit_Icon_1") ?? Load("Settings_Exit_Icon"), D(left, scale, 438.79f, cy - 13.59f, 26.25f, 27.19f));
|
|
if (GUI.Button(body, GUIContent.none, GUIStyle.none)) { game.PlayUiSound(); game.CloseModal(); }
|
|
}
|
|
|
|
private void DrawOriginalPopupTitle(Rect rect, string label, float scale, int fontSize = 60)
|
|
{
|
|
DrawOriginalTitle(label,rect,Mathf.RoundToInt(fontSize*scale));
|
|
}
|
|
|
|
private GUIStyle PopupTextStyle(int size, float scale, bool white)
|
|
{
|
|
GUIStyle style = CreateOriginalTextStyle(Mathf.RoundToInt(size*scale),white?OriginalTextRole.ButtonGreen:OriginalTextRole.Body);
|
|
style.normal.textColor = white ? Color.white : new Color(.22745f, .16863f, .63137f, 1);
|
|
return style;
|
|
}
|
|
|
|
private bool PopupActionButton(Rect rect, string label, float scale, string face, string frame, int fontSize)
|
|
{
|
|
Rect background = new Rect(rect.x - 6 * scale, rect.y - 5 * scale, rect.width + 12 * scale, rect.height + 12 * scale);
|
|
DrawMirroredButton(Load(frame), background);
|
|
DrawMirroredButton(Load(face), rect);
|
|
Rect textRect = rect; textRect.y -= 2 * scale;
|
|
DrawOriginalText(label,textRect,Mathf.RoundToInt(fontSize*scale),
|
|
face.IndexOf("Quit",StringComparison.Ordinal)>=0?OriginalTextRole.ButtonRed:OriginalTextRole.ButtonGreen);
|
|
if (!GUI.Button(background, GUIContent.none, GUIStyle.none)) return false;
|
|
game.PlayUiSound(); return true;
|
|
}
|
|
|
|
private void DrawPopupNotice(float left, float scale)
|
|
{
|
|
if (!string.IsNullOrEmpty(game.Notice))
|
|
DrawText(game.Notice, D(left, scale, 90, 699, 360, 42), PopupTextStyle(15, scale, false));
|
|
}
|
|
|
|
private static void DrawMirroredSlicedPanel(Sprite sprite, Rect target, float scale)
|
|
{
|
|
DrawSlicedSprite(sprite, target, OriginalSpriteLayout.MirroredHalf, scale);
|
|
}
|
|
|
|
private void DrawSettingRow(float left, float scale, float y, string label, bool value, Action toggle)
|
|
{
|
|
var style = CreateTextStyle(Mathf.RoundToInt(21 * scale));
|
|
DrawText(label, D(left, scale, 98, y, 180, 45), style);
|
|
Rect button = D(left, scale, 303, y, 113, 45);
|
|
DrawSprite(Load("Pause_Toggle_BG"), button);
|
|
DrawSprite(Load(value ? "Pause_Toggle_Btn_On" : "Pause_Toggle_Btn_Off"), button);
|
|
DrawText(value ? "On" : "Off", button, style);
|
|
if (GUI.Button(button, GUIContent.none, GUIStyle.none)) toggle();
|
|
}
|
|
|
|
private bool ActionButton(Rect rect, string label, float scale, bool red = false)
|
|
{
|
|
DrawMirroredButton(Load(red ? "Home_Button_Red" : "Home_Button_Green"), rect);
|
|
DrawText(label, rect, CreateTextStyle(Mathf.RoundToInt(23 * scale)));
|
|
if (!GUI.Button(rect, GUIContent.none, GUIStyle.none)) return false;
|
|
game.PlayUiSound(); return true;
|
|
}
|
|
|
|
private static void DrawNineSlice(Sprite sprite, Rect target, float scale)
|
|
{
|
|
if (sprite == null || sprite.texture == null)
|
|
{
|
|
Color previous = GUI.color; GUI.color = new Color(.23f,.15f,.58f,.98f);
|
|
GUI.DrawTexture(target, Texture2D.whiteTexture); GUI.color = previous; return;
|
|
}
|
|
DrawSlicedSprite(sprite, target, OriginalSpriteLayout.NineSlice, scale);
|
|
}
|
|
|
|
private static void DrawMirroredButton(Sprite sprite, Rect target)
|
|
{
|
|
DrawSlicedSprite(sprite, target, OriginalSpriteLayout.MirroredHalf);
|
|
}
|
|
}
|
|
}
|