#include "gui.h"
#include <SDL2/SDL.h>
#include <stdio.h>
#include "datatypes.h"
#include "stage.h"
#include "delays.h"
#include "util.h"
/*
Copyright (c) 2013-2021 Devine Lu Linvega
2018 web port by rezmason
2021 C89 port by rezmason
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
*/
#define PATH_LENGTH 64
#define NODE_RENDER_PATH "graphics/node_render/%s.%i"
#define CURSOR_BORDER 32
#define NUDGE_MULT 0.025
#define loadCursor(cursor, path) success &= Loader_LoadCursor(&cursor, "graphics/cursor/" path)
#define loadImage(asset, path) success &= Loader_LoadImage(Loader_CreateImage(&asset, LOADTYPE_MANUAL, "graphics/interface/" path))
#define lazyLoadImage(asset, path) Loader_CreateImage(&asset, LOADTYPE_LAZY, "graphics/interface/" path)
#define lazierLoadImage(asset, path) Loader_CreateImage(&asset, LOADTYPE_LAZIER, "graphics/interface/" path)
#define loadLogo(asset, path) Loader_CreateImage(&asset, LOADTYPE_LAZIER, "graphics/logos/" path)
static const char *modifierNames[] = {
"",
".filled",
".empty",
".on",
".open",
".secret",
".seal.1",
".seal.2",
".unlocked",
".seal.1",
".seal.2",
".seal.both",
".exit"};
static SDL_Cursor *cursorsByType[NumberOfCursorTypes][2];
static CursorType currentCursorType = CURSORTYPE_FORWARD;
static int cursorPressed = 0;
static CursorType actionCursorType = CURSORTYPE_FORWARD;
static int actionTriggerActive;
static SDL_Color red = {0xFF, 0x0, 0x0, 0xFF};
static SDL_Color cyan = {0x72, 0xDE, 0xC2, 0xFF};
static Image *iconsByType[NumberOfIconTypes];
static Image *clocksByType[NumberOfClockTypes];
static Image *mazeIconsByAxisAndInstruction[NumberOfMazeAxes][NumberOfMazeInstructions];
static Image *progressPanesByChapter[NumberOfChapters];
static Image *sealsByZone[NumberOfZones];
static Image *ententeProgressPane;
static Image *menuControls;
static Image *menuLogo;
static Image *vignette;
static Image *black;
static Image *hundredRabbitsLogo;
static Image *xxiivvLogo;
static Image *rezmasonLogo;
static int nodeImageIndex = 0;
static Image *nodeImages[2];
static char nodeImagePaths[2][PATH_LENGTH];
static int splash1Delay;
static int splash2Delay;
static int splash3Delay;
static int splash4Delay;
int
GUI_PreloadAssets()
{
int success = 1;
/* Cursors get loaded immediately */
loadCursor(cursorsByType[CURSORTYPE_FUSE][0], "fuse.png");
loadCursor(cursorsByType[CURSORTYPE_FUSE][1], "fuse.png");
loadCursor(cursorsByType[CURSORTYPE_FORWARD][0], "pointer.up.png");
loadCursor(cursorsByType[CURSORTYPE_FORWARD][1], "pointer.up.pressed.png");
loadCursor(cursorsByType[CURSORTYPE_LEFT][0], "pointer.left.png");
loadCursor(cursorsByType[CURSORTYPE_LEFT][1], "pointer.left.pressed.png");
loadCursor(cursorsByType[CURSORTYPE_RIGHT][0], "pointer.right.png");
loadCursor(cursorsByType[CURSORTYPE_RIGHT][1], "pointer.right.pressed.png");
cursorsByType[CURSORTYPE_SYSTEM][0] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
cursorsByType[CURSORTYPE_SYSTEM][1] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);
/* HUD images get loaded immediately */
loadImage(iconsByType[ICONTYPE_ALERT], "alert.svg");
loadImage(iconsByType[ICONTYPE_CLOCK_0], "clock.0.svg");
loadImage(iconsByType[ICONTYPE_CLOCK_1], "clock.1.svg");
loadImage(iconsByType[ICONTYPE_CLOCK_2], "clock.2.svg");
loadImage(iconsByType[ICONTYPE_FOOTSTEP], "footstep.svg");
loadImage(iconsByType[ICONTYPE_FUSE_0], "fuse.0.svg");
loadImage(iconsByType[ICONTYPE_FUSE_1], "fuse.1.svg");
loadImage(iconsByType[ICONTYPE_FUSE_2], "fuse.2.svg");
loadImage(iconsByType[ICONTYPE_FUSE_3], "fuse.3.svg");
loadImage(iconsByType[ICONTYPE_MUSIC_OFF], "music.off.svg");
loadImage(iconsByType[ICONTYPE_MUSIC_ON], "music.on.svg");
loadImage(iconsByType[ICONTYPE_SAVE], "save.svg");
loadImage(sealsByZone[ZONE_ANTECHANNEL], "seal.antechannel.svg");
loadImage(sealsByZone[ZONE_CAPSULE], "seal.capsule.svg");
loadImage(sealsByZone[ZONE_CIRCULAR], "seal.circular.svg");
loadImage(sealsByZone[ZONE_ENTENTE], "seal.entente.svg");
loadImage(sealsByZone[ZONE_FOREST], "seal.forest.svg");
loadImage(sealsByZone[ZONE_METAMONDST], "seal.metamondst.svg");
loadImage(sealsByZone[ZONE_NATANIEV], "seal.nataniev.svg");
loadImage(sealsByZone[ZONE_NETHER], "seal.nether.svg");
loadImage(sealsByZone[ZONE_NONE], "seal.none.svg");
loadImage(sealsByZone[ZONE_RAINRE], "seal.rainre.svg");
loadImage(sealsByZone[ZONE_STONES], "seal.stones.svg");
loadImage(sealsByZone[ZONE_STUDIO], "seal.studio.svg");
loadImage(sealsByZone[ZONE_TERMINAL], "seal.terminal.svg");
/* Clock, maze and progress images can be loaded once they're needed */
lazyLoadImage(clocksByType[CLOCKTYPE_SHADOW], "dimclock.shadow.svg");
lazyLoadImage(clocksByType[CLOCKTYPE_STATE_0], "dimclock.state0.svg");
lazyLoadImage(clocksByType[CLOCKTYPE_STATE_1], "dimclock.state1.svg");
lazyLoadImage(clocksByType[CLOCKTYPE_STATE_2], "dimclock.state2.svg");
lazyLoadImage(mazeIconsByAxisAndInstruction[MAZEAXIS_X][MAZEINSTRUCTION_LEFT], "entente.x.left.svg");
lazyLoadImage(mazeIconsByAxisAndInstruction[MAZEAXIS_X][MAZEINSTRUCTION_RIGHT], "entente.x.right.svg");
lazyLoadImage(mazeIconsByAxisAndInstruction[MAZEAXIS_X][MAZEINSTRUCTION_STRAIGHT], "entente.x.straight.svg");
lazyLoadImage(mazeIconsByAxisAndInstruction[MAZEAXIS_Y][MAZEINSTRUCTION_LEFT], "entente.y.left.svg");
lazyLoadImage(mazeIconsByAxisAndInstruction[MAZEAXIS_Y][MAZEINSTRUCTION_RIGHT], "entente.y.right.svg");
lazyLoadImage(mazeIconsByAxisAndInstruction[MAZEAXIS_Y][MAZEINSTRUCTION_STRAIGHT], "entente.y.straight.svg");
lazyLoadImage(progressPanesByChapter[CHAPTER_ACT1], "progress.act1.svg");
lazyLoadImage(progressPanesByChapter[CHAPTER_ACT2], "progress.act2.svg");
lazyLoadImage(progressPanesByChapter[CHAPTER_ACT3], "progress.act3.svg");
lazyLoadImage(progressPanesByChapter[CHAPTER_ACT4], "progress.act4.svg");
lazyLoadImage(progressPanesByChapter[CHAPTER_ACT5], "progress.act5.svg");
lazyLoadImage(ententeProgressPane, "progress.entente.svg");
/* The full-screen menus are huge and rarely needed */
lazierLoadImage(menuControls, "menu.controls.svg");
lazierLoadImage(menuLogo, "menu.logo.svg");
/* The splash screen images only show up once */
loadLogo(hundredRabbitsLogo, "100R.svg");
loadLogo(xxiivvLogo, "xxiivv.svg");
loadLogo(rezmasonLogo, "rm.svg");
/*
This one's interesting: the vignette is a full-screen
radial gradient that flashes almost every time the player
performs an action. So it's loaded when the game initializes,
but it's a very small SVG that's rendered very large.
*/
loadImage(vignette, "vignette.svg");
loadImage(black, "black.svg");
return success;
}
void
GUI_Init()
{
Stage_SetAlpha(BILLBOARD_HUD_STEP_RIGHT, 0);
Stage_SetAlpha(BILLBOARD_HUD_STEP_FORWARD, 0);
Stage_SetAlpha(BILLBOARD_HUD_STEP_LEFT, 0);
Stage_SetAlpha(BILLBOARD_HUD_CLOCK_ALERT, 0);
Stage_SetAlpha(BILLBOARD_HUD_SEAL_ALERT, 0);
Stage_SetAlpha(BILLBOARD_HUD_FUSE_ALERT, 0);
Stage_SetAlpha(BILLBOARD_HUD_SAVE, 0);
Stage_SetAlpha(BILLBOARD_CLOCK_SHADOW, 0);
Stage_SetAlpha(BILLBOARD_VIGNETTE, 0);
Stage_SetAlpha(BILLBOARD_MENU_LOGO, 0);
Stage_SetAlpha(BILLBOARD_MENU_CONTROLS, 0);
Stage_SetAlpha(BILLBOARD_SPLASH, 0);
/* Most HUD elements occupy a Stage region for the whole game */
nodeImageIndex = 0;
Stage_SetImage(BILLBOARD_NODE, nodeImages[0]);
Stage_SetImage(BILLBOARD_LAST_NODE_FADE, nodeImages[1]);
Stage_SetImage(BILLBOARD_HUD_STEP_RIGHT, iconsByType[ICONTYPE_FOOTSTEP]);
Stage_SetImage(BILLBOARD_HUD_STEP_FORWARD, iconsByType[ICONTYPE_FOOTSTEP]);
Stage_SetImage(BILLBOARD_HUD_STEP_LEFT, iconsByType[ICONTYPE_FOOTSTEP]);
Stage_SetImage(BILLBOARD_HUD_CLOCK_ALERT, iconsByType[ICONTYPE_ALERT]);
Stage_SetImage(BILLBOARD_HUD_SEAL_ALERT, iconsByType[ICONTYPE_ALERT]);
Stage_SetImage(BILLBOARD_HUD_FUSE_ALERT, iconsByType[ICONTYPE_ALERT]);
Stage_SetImage(BILLBOARD_HUD_SAVE, iconsByType[ICONTYPE_SAVE]);
Stage_SetImage(BILLBOARD_CLOCK_SHADOW, clocksByType[CLOCKTYPE_SHADOW]);
Stage_SetImage(BILLBOARD_VIGNETTE, vignette);
Stage_SetImage(BILLBOARD_MENU_BLACK, black);
Stage_SetImage(BILLBOARD_MENU_LOGO, menuLogo);
Stage_SetImage(BILLBOARD_MENU_CONTROLS, menuControls);
SDL_SetCursor(cursorsByType[currentCursorType][cursorPressed]);
Loader_CreateImage(&nodeImages[0], LOADTYPE_LAZIER, nodeImagePaths[0]);
Loader_CreateImage(&nodeImages[1], LOADTYPE_LAZIER, nodeImagePaths[1]);
}
void
GUI_Quit()
{
int i, j;
for(i = 0; i < NumberOfCursorTypes; i++) {
SDL_FreeCursor(cursorsByType[i][0]);
SDL_FreeCursor(cursorsByType[i][1]);
cursorsByType[i][0] = NULL;
cursorsByType[i][1] = NULL;
}
for(i = 0; i < NumberOfIconTypes; i++) {
Loader_DestroyImage(iconsByType[i]);
iconsByType[i] = NULL;
}
for(i = 0; i < NumberOfClockTypes; i++) {
Loader_DestroyImage(clocksByType[i]);
clocksByType[i] = NULL;
}
for(i = 0; i < NumberOfMazeAxes; i++) {
for(j = 0; j < NumberOfMazeInstructions; j++) {
Loader_DestroyImage(mazeIconsByAxisAndInstruction[i][j]);
mazeIconsByAxisAndInstruction[i][j] = NULL;
}
}
for(i = 0; i < NumberOfChapters; i++) {
Loader_DestroyImage(progressPanesByChapter[i]);
progressPanesByChapter[i] = NULL;
}
for(i = 0; i < NumberOfZones; i++) {
Loader_DestroyImage(sealsByZone[i]);
sealsByZone[i] = NULL;
}
Loader_DestroyImage(ententeProgressPane);
ententeProgressPane = NULL;
Loader_DestroyImage(menuControls);
menuControls = NULL;
Loader_DestroyImage(menuLogo);
menuLogo = NULL;
Loader_DestroyImage(vignette);
vignette = NULL;
Loader_DestroyImage(black);
black = NULL;
Loader_DestroyImage(hundredRabbitsLogo);
hundredRabbitsLogo = NULL;
Loader_DestroyImage(rezmasonLogo);
rezmasonLogo = NULL;
Loader_DestroyImage(xxiivvLogo);
xxiivvLogo = NULL;
Loader_DestroyImage(nodeImages[0]);
Loader_DestroyImage(nodeImages[1]);
}
void
GUI_SetActionTrigger(int active)
{
actionTriggerActive = active;
}
void
GUI_HideCursor()
{
SDL_ShowCursor(0);
}
void
GUI_UpdateCursor(int mouseX, int mouseY, int pressed)
{
CursorType type;
RegionName regionUnderMouse = GUI_GetRegionNameAt(mouseX, mouseY);
if(Stage_PointNearBorder(mouseX, mouseY, CURSOR_BORDER)) {
/*
The system cursor is shown near the edge of the window,
so that the game's cursors don't obstruct the player's
view of their cursor while they resize or move the window.
*/
type = CURSORTYPE_SYSTEM;
} else {
switch(regionUnderMouse) {
case TRIGGER_ACTION:
type = actionCursorType;
break;
case TRIGGER_MOVE_FORWARD:
type = CURSORTYPE_FORWARD;
break;
case TRIGGER_MOVE_LEFT:
type = CURSORTYPE_LEFT;
break;
case TRIGGER_MOVE_RIGHT:
type = CURSORTYPE_RIGHT;
break;
default:
type = CURSORTYPE_FORWARD;
break;
}
}
SDL_ShowCursor(1);
if(currentCursorType != type || cursorPressed != pressed) {
currentCursorType = type;
cursorPressed = pressed;
SDL_SetCursor(cursorsByType[currentCursorType][cursorPressed]);
}
}
void
GUI_EnableFuseCursor(int enable)
{
int currentCursorIsActionCursor = currentCursorType == actionCursorType;
actionCursorType = enable ? CURSORTYPE_FUSE : CURSORTYPE_FORWARD;
if(currentCursorIsActionCursor) {
currentCursorType = actionCursorType;
SDL_SetCursor(cursorsByType[currentCursorType][cursorPressed]);
}
}
RegionName
GUI_GetRegionNameAt(int mouseX, int mouseY)
{
int i = actionTriggerActive ? TRIGGER_ACTION : TRIGGER_MOVE_FORWARD;
for(; i <= TRIGGER_MOVE_RIGHT; i++) {
if(Stage_HitTest(i, mouseX, mouseY)) {
return i;
}
}
return TRIGGER_MOVE_FORWARD;
}
void
GUI_Reset()
{
GUI_HideMenu();
Stage_SetAlpha(BILLBOARD_LAST_NODE_FADE, 0);
Stage_SetAlpha(BILLBOARD_CLOCK, 0);
Stage_SetAlpha(BILLBOARD_CLOCK_SHADOW, 0);
Stage_SetAlpha(BILLBOARD_PROGRESS_PANE, 0);
Stage_SetAlpha(BILLBOARD_ENTENTE_SCREEN, 0);
}
void
GUI_ShowClockFace(int state, int refresh)
{
Stage_SetImage(BILLBOARD_CLOCK, clocksByType[CLOCKTYPE_STATE_0 + state]);
if(!refresh) {
Stage_Fade(BILLBOARD_CLOCK_SHADOW, 0, 0.23, 1.5, 0.5);
Stage_Fade(BILLBOARD_CLOCK, 0, 1, 0.5, 0.5);
} else {
Stage_SetAlpha(BILLBOARD_CLOCK_SHADOW, 0.23);
Stage_SetAlpha(BILLBOARD_CLOCK, 1);
}
}
void
GUI_ShowClock(int state)
{
Stage_SetImage(BILLBOARD_HUD_CLOCK, iconsByType[ICONTYPE_CLOCK_0 + state]);
Stage_Fade(BILLBOARD_HUD_CLOCK, 1, 0, 0.5, 3);
}
void
GUI_ShowClockAlert()
{
Stage_Fade(BILLBOARD_HUD_CLOCK_ALERT, 1, 0, 0.5, 0.5);
}
void
GUI_ShowSeals(Zone zoneP, Zone zoneQ)
{
/*
For aesthetic reasons, seals are always presented
in a particular order.
*/
Zone zone1, zone2;
if((zoneP > ZONE_NONE && zoneP < zoneQ) || zoneQ == ZONE_NONE) {
zone1 = zoneP;
zone2 = zoneQ;
} else {
zone1 = zoneQ;
zone2 = zoneP;
}
Stage_SetImage(BILLBOARD_HUD_SEAL_1, sealsByZone[zone1]);
Stage_SetImage(BILLBOARD_HUD_SEAL_2, sealsByZone[zone2]);
Stage_Fade(BILLBOARD_HUD_SEAL_1, 1, 0, 0.5, 3);
Stage_Fade(BILLBOARD_HUD_SEAL_2, 1, 0, 0.5, 3);
}
void
GUI_ShowSealAlert()
{
Stage_Fade(BILLBOARD_HUD_SEAL_ALERT, 1, 0, 0.5, 0.5);
}
void
GUI_ShowEnergy(int level)
{
Stage_SetImage(BILLBOARD_HUD_FUSE, iconsByType[ICONTYPE_FUSE_0 + level]);
Stage_Fade(BILLBOARD_HUD_FUSE, 1, 0, 0.5, 3);
}
void
GUI_ShowEnergyAlert()
{
Stage_Fade(BILLBOARD_HUD_FUSE_ALERT, 1, 0, 1.5, 0.5);
}
void
GUI_ShowAudio(int enabled)
{
Stage_SetImage(BILLBOARD_HUD_AUDIO, iconsByType[ICONTYPE_MUSIC_OFF + enabled]);
Stage_Fade(BILLBOARD_HUD_AUDIO, 1, 0, 0.5, 3);
}
void
GUI_HideMenu()
{
Stage_SetAlpha(BILLBOARD_MENU_BLACK, 0.);
Stage_SetAlpha(BILLBOARD_MENU_CREDIT1, 0.);
Stage_SetAlpha(BILLBOARD_MENU_CREDIT2, 0.);
Stage_SetAlpha(BILLBOARD_MENU_CREDIT3, 0.);
Stage_SetAlpha(BILLBOARD_MENU_CREDIT4, 0.);
Stage_SetAlpha(BILLBOARD_MENU_LOGO, 0.);
Stage_SetAlpha(BILLBOARD_MENU_CONTROLS, 0.);
Stage_SetAlpha(BILLBOARD_SPLASH, 0.);
}
void
GUI_ShowHomeMenu()
{
Stage_SetAlpha(BILLBOARD_HUD_SEAL_1, 0);
Stage_SetAlpha(BILLBOARD_HUD_SEAL_2, 0);
Stage_SetAlpha(BILLBOARD_HUD_FUSE, 0);
Stage_SetAlpha(BILLBOARD_HUD_SAVE, 0);
Stage_SetAlpha(BILLBOARD_NODE, 1);
Stage_Fade(BILLBOARD_MENU_BLACK, 1, 0, 2, 0);
Stage_Fade(BILLBOARD_MENU_LOGO, 1, 0, 2, 3);
Stage_Fade(BILLBOARD_MENU_CONTROLS, 1, 0, 1, 8);
}
void
GUI_ShowMovement(int nudgeX, int nudgeY)
{
Stage_Nudge(nudgeX * NUDGE_MULT, nudgeY * NUDGE_MULT, 0.2);
Stage_Fade(BILLBOARD_NODE, 0.5, 1, 0.2, 0);
Stage_SetAlpha(BILLBOARD_LAST_NODE_FADE, 0);
}
void
GUI_ShowNode(char *nodeName, Orientation orientation, NodeModifier modifier, double fadeDuration, double fadeDelay)
{
/*
The main visual information in Hiversaires comes
from the images loaded here.
The previous node image often cross-fades into the current one.
To accomplish this effect, Hiversaires takes the old image,
swaps its region with LAST_NODE_FADE, and fades out
on top of the new image. The last and current images are
reused in alternating roles, similar to a double buffering game.
*/
char path[PATH_LENGTH];
int nextIndex = !nodeImageIndex;
snprintf(path, PATH_LENGTH, NODE_RENDER_PATH "%s.jpg", nodeName, orientation, modifierNames[modifier]);
if(strcmp(nodeImagePaths[nodeImageIndex], path) == 0) {
return;
}
nodeImageIndex = nextIndex;
strcpy(nodeImagePaths[nextIndex], path);
Stage_SwapImages(BILLBOARD_LAST_NODE_FADE, BILLBOARD_NODE);
Stage_SetImage(BILLBOARD_NODE, nodeImages[nodeImageIndex]);
Stage_SetAlpha(BILLBOARD_NODE, 1);
Stage_Fade(BILLBOARD_LAST_NODE_FADE, 1, 0, fadeDuration, fadeDelay);
}
static void
splashNext(void *data)
{
Image *image = data;
Stage_SetImage(BILLBOARD_SPLASH, image);
Stage_Fade(BILLBOARD_SPLASH, 1, 0, 0.125, 0.875);
}
static void
splashEnd(void *data)
{
FuncWrapper *wrapper = data;
Stage_SetAlpha(BILLBOARD_SPLASH, 0);
wrapper->f();
free(wrapper);
}
void
GUI_RunSplash(void (*onComplete)())
{
Stage_SetAlpha(BILLBOARD_MENU_BLACK, 1);
Stage_SetAlpha(BILLBOARD_SPLASH, 1);
splash1Delay = Delays_Add(0.5, splashNext, hundredRabbitsLogo);
splash2Delay = Delays_Add(1.5, splashNext, xxiivvLogo);
splash3Delay = Delays_Add(2.5, splashNext, rezmasonLogo);
splash4Delay = Delays_Add(3.5, splashEnd, wrapFunction(onComplete));
}
void
GUI_SkipSplash()
{
Stage_SetAlpha(BILLBOARD_MENU_BLACK, 1);
Stage_SetAlpha(BILLBOARD_SPLASH, 0);
Delays_Cancel(splash1Delay, 0);
Delays_Cancel(splash2Delay, 0);
Delays_Cancel(splash3Delay, 0);
Delays_Cancel(splash4Delay, 1);
}
void
GUI_ShowCreditsMenu(int showSecret)
{
Stage_Fade(BILLBOARD_MENU_BLACK, 0, 1, 1, 1);
Stage_Fade(BILLBOARD_MENU_CREDIT1, 0, 1, 1, 6);
Stage_Fade(BILLBOARD_MENU_CREDIT2, 0, 1, 1, 10);
Stage_Fade(BILLBOARD_MENU_CREDIT3, 0, 1, 1, 16);
if(showSecret) {
Stage_Fade(BILLBOARD_MENU_CREDIT4, 0, 1, 1, 24);
}
}
void
GUI_FlashVignette()
{
Stage_Fade(BILLBOARD_VIGNETTE, 1., 0., 1., 0.);
}
void
GUI_ShowSave()
{
Stage_Fade(BILLBOARD_HUD_SAVE, 1, 0, 0.5, 3);
}
void
GUI_ShowProgressScreen(Chapter chapter)
{
Stage_SetImage(BILLBOARD_PROGRESS_PANE, progressPanesByChapter[chapter]);
Stage_Fade(BILLBOARD_PROGRESS_PANE, 0, 1, 0.5, 0.3);
}
void
GUI_ShowEntenteScreen()
{
Stage_SetImage(BILLBOARD_ENTENTE_SCREEN, ententeProgressPane);
Stage_Fade(BILLBOARD_PROGRESS_PANE, 0, 1, 0.5, 0.3);
}
void
GUI_ShowMazeInstruction(MazeAxis axis, MazeInstruction instruction)
{
Stage_SetImage(BILLBOARD_ENTENTE_SCREEN, mazeIconsByAxisAndInstruction[axis][instruction]);
Stage_Fade(BILLBOARD_ENTENTE_SCREEN, 0, 1, 1, 0);
}
void
GUI_ShowFootstep(Footstep step)
{
RegionName name;
switch(step) {
case FOOTSTEP_LEFT:
name = BILLBOARD_HUD_STEP_LEFT;
break;
case FOOTSTEP_RIGHT:
name = BILLBOARD_HUD_STEP_RIGHT;
break;
default:
name = BILLBOARD_HUD_STEP_FORWARD;
break;
}
Stage_Fade(name, 1, 0, 0.5, 0);
}
void
GUI_TintRed()
{
Stage_Tint(red, 2.1, -0.1);
}
void
GUI_TintCyan()
{
Stage_Tint(cyan, 2.1, -0.1);
}
void
GUI_StopTint()
{
Stage_StopTint();
}