Work on controls menu

This commit is contained in:
James Lambert 2023-04-25 21:20:32 -06:00
parent e104577c41
commit bba255a357
11 changed files with 180 additions and 19 deletions

View file

@ -249,6 +249,8 @@ build/src/menu/landing_menu.o: build/assets/materials/ui.h
build/src/menu/options_menu.o: build/assets/materials/ui.h
build/src/menu/controls.o: build/assets/materials/ui.h
build/assets/models/player/chell.h: assets/materials/chell.skm.yaml
build/assets/models/props/combine_ball_catcher.h: assets/materials/ball_catcher.skm.yaml

View file

@ -158,4 +158,24 @@ struct Vector2 controllerDirectionGet(enum ControllerAction direction) {
int controllerActionGet(enum ControllerAction action) {
return (gActionState & (1 << action)) != 0;
}
int controllerSourcesForAction(enum ControllerAction action, struct ControllerSourceWithController* sources, int maxSources) {
int index = 0;
for (int controllerIndex = 0; controllerIndex < 2; ++controllerIndex) {
for (int sourceIndex = 0; sourceIndex < ControllerActionSourceCount; ++sourceIndex) {
if (gControllerSettings[controllerIndex][sourceIndex] == action) {
sources[index].button = sourceIndex;
sources[index].controller = controllerIndex;
++index;
if (index == maxSources) {
return index;
}
}
}
}
return index;
}

View file

@ -41,6 +41,13 @@ enum ControllerAction {
// direction actions
ControllerActionMove,
ControllerActionRotate,
ControllerActionCount = ControllerActionRotate,
};
struct ControllerSourceWithController {
char button;
char controller;
};
void controllerActionInit();
@ -50,4 +57,6 @@ void controllerActionRead();
struct Vector2 controllerDirectionGet(enum ControllerAction direction);
int controllerActionGet(enum ControllerAction action);
int controllerSourcesForAction(enum ControllerAction action, struct ControllerSourceWithController* sources, int maxSources);
#endif

View file

@ -200,7 +200,7 @@ static void gameProc(void* arg) {
contactSolverInit(&gContactSolver);
portalSurfaceCleanupQueueInit();
savefileNew();
levelLoadWithCallbacks(0);
levelLoadWithCallbacks(MAIN_MENU);
cutsceneRunnerReset();
controllersInit();
controllerActionInit();

View file

@ -1 +1,88 @@
#include "controls.h"
#include "controls.h"
#include "../font/dejavusans.h"
#include "../font/font.h"
#include "../build/assets/materials/ui.h"
#define CONTROL_ROW_HEIGHT 14
#define CONTROLS_Y 54
#define CONTROLS_WIDTH 252
#define CONTROLS_HEIGHT 100
#define CONTROLS_X ((SCREEN_WD - CONTROLS_WIDTH) / 2)
struct ControlActionDataRow {
char* name;
enum ControllerAction action;
char* header;
};
struct ControlActionDataRow gControllerDataRows[] = {
{"Move", ControllerActionMove, "Movement"},
{"Look", ControllerActionRotate, NULL},
{"Jump", ControllerActionJump, NULL},
{"Duck", ControllerActionDuck, NULL},
{"Fire blue portal", ControllerActionOpenPortal0, "Combat"},
{"Fire red portal", ControllerActionOpenPortal1, NULL},
{"Use item", ControllerActionUseItem, NULL},
{"Pause", ControllerActionPause, "Misc"},
{"Look forward", ControllerActionLookForward, "Misc Movement"},
{"Look backward", ControllerActionLookForward, NULL},
};
void controlsRerenderRow(struct ControlsMenuRow* row, struct ControlActionDataRow* data, int x, int y) {
fontRender(&gDejaVuSansFont, data->name, x, y, row->actionText);
}
void controlsInitRow(struct ControlsMenuRow* row, struct ControlActionDataRow* data) {
row->actionText = menuBuildText(&gDejaVuSansFont, data->name, 0, 0);
Gfx* dl = row->sourceIcons;
gSPEndDisplayList(dl++);
}
void controlsRerender(struct ControlsMenu* controlsMenu) {
int y = CONTROLS_Y;
for (int i = 0; i < ControllerActionCount; ++i) {
controlsRerenderRow(&controlsMenu->actionRows[i], &gControllerDataRows[i], CONTROLS_X, y);
y += CONTROL_ROW_HEIGHT;
}
}
void controlsMenuInit(struct ControlsMenu* controlsMenu) {
for (int i = 0; i < ControllerActionCount; ++i) {
controlsInitRow(&controlsMenu->actionRows[i], &gControllerDataRows[i]);
}
controlsRerender(controlsMenu);
controlsMenu->scrollOutline = menuBuildOutline(CONTROLS_X, CONTROLS_Y, CONTROLS_WIDTH, CONTROLS_HEIGHT, 1);
}
void controlsMenuRender(struct ControlsMenu* controlsMenu, struct RenderState* renderState, struct GraphicsTask* task) {
gSPDisplayList(renderState->dl++, ui_material_list[SOLID_TRANSPARENT_OVERLAY_INDEX]);
gDPFillRectangle(renderState->dl++, CONTROLS_X, CONTROLS_Y, CONTROLS_X + CONTROLS_WIDTH, CONTROLS_Y + CONTROLS_HEIGHT);
gSPDisplayList(renderState->dl++, ui_material_revert_list[SOLID_TRANSPARENT_OVERLAY_INDEX]);
gSPDisplayList(renderState->dl++, ui_material_list[SOLID_ENV_INDEX]);
gSPDisplayList(renderState->dl++, controlsMenu->scrollOutline);
gSPDisplayList(renderState->dl++, ui_material_revert_list[SOLID_ENV_INDEX]);
gDPSetScissor(renderState->dl++, G_SC_NON_INTERLACE, CONTROLS_X, CONTROLS_Y, CONTROLS_X + CONTROLS_WIDTH, CONTROLS_Y + CONTROLS_HEIGHT);
gSPDisplayList(renderState->dl++, ui_material_list[DEJAVU_SANS_INDEX]);
for (int i = 0; i < ControllerActionCount; ++i) {
gSPDisplayList(renderState->dl++, controlsMenu->actionRows[i].actionText);
}
gSPDisplayList(renderState->dl++, ui_material_revert_list[DEJAVU_SANS_INDEX]);
gDPSetScissor(renderState->dl++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WD, SCREEN_HT);
}

View file

@ -1,8 +1,24 @@
#ifndef __MENU_CONTROLS_H__
#define __MENU_CONTROLS_H__
struct ControlsMenu {
#include "./menu.h"
#include "../controls/controller_actions.h"
#include "../graphics/graphics.h"
#define MAX_SOURCES_PER_ACTION 4
struct ControlsMenuRow {
Gfx* actionText;
Gfx sourceIcons[MAX_SOURCES_PER_ACTION * GFX_ENTRIES_PER_IMAGE + GFX_ENTRIES_PER_END_DL];
};
struct ControlsMenu {
Gfx* scrollOutline;
struct ControlsMenuRow actionRows[ControllerActionCount];
};
void controlsMenuInit(struct ControlsMenu* controlsMenu);
void controlsMenuRender(struct ControlsMenu* controlsMenu, struct RenderState* renderState, struct GraphicsTask* task);
#endif

View file

@ -117,23 +117,36 @@ Gfx* menuBuildSolidBorder(int x, int y, int w, int h, int nx, int ny, int nw, in
return result;
}
Gfx* menuBuildOutline(int x, int y, int width, int height, int invert) {
Gfx* result = malloc(sizeof(Gfx) * 9);
Gfx* dl = result;
gDPPipeSync(dl++);
if (invert) {
gDPSetEnvColor(dl++, gBorderDark.r, gBorderDark.g, gBorderDark.b, gBorderDark.a);
} else {
gDPSetEnvColor(dl++, gBorderHighlight.r, gBorderHighlight.g, gBorderHighlight.b, gBorderHighlight.a);
}
gDPFillRectangle(dl++, x, y, x + width - 1, y + 1);
gDPFillRectangle(dl++, x, y, x + 1, y + height);
gDPPipeSync(dl++);
if (invert) {
gDPSetEnvColor(dl++, gBorderHighlight.r, gBorderHighlight.g, gBorderHighlight.b, gBorderHighlight.a);
} else {
gDPSetEnvColor(dl++, gBorderDark.r, gBorderDark.g, gBorderDark.b, gBorderDark.a);
}
gDPFillRectangle(dl++, x, y + height - 1, x + width, y + height);
gDPFillRectangle(dl++, x + width - 1, y, x + width, y + height - 1);
gSPEndDisplayList(dl++);
return result;
}
struct MenuButton menuBuildButton(struct Font* font, char* message, int x, int y, int width, int height) {
struct MenuButton result;
result.text = menuBuildText(font, message, x + 4, y + 2);
result.outline = malloc(sizeof(Gfx) * 9);
Gfx* dl = result.outline;
gDPPipeSync(dl++);
gDPSetEnvColor(dl++, gBorderHighlight.r, gBorderHighlight.g, gBorderHighlight.b, gBorderHighlight.a);
gDPFillRectangle(dl++, x, y, x + width - 1, y + 1);
gDPFillRectangle(dl++, x, y, x + 1, y + height);
gDPPipeSync(dl++);
gDPSetEnvColor(dl++, gBorderDark.r, gBorderDark.g, gBorderDark.b, gBorderDark.a);
gDPFillRectangle(dl++, x, y + height - 1, x + width, y + height);
gDPFillRectangle(dl++, x + width - 1, y, x + width, y + height - 1);
gSPEndDisplayList(dl++);
result.outline = menuBuildOutline(x, y, width, height, 0);
return result;
}

View file

@ -11,6 +11,8 @@ struct MenuButton {
Gfx* text;
};
#define GFX_ENTRIES_PER_IMAGE 3
#define GFX_ENTRIES_PER_END_DL 1
extern struct Coloru8 gSelectionOrange;
extern struct Coloru8 gSelectionGray;
@ -22,6 +24,7 @@ Gfx* menuBuildText(struct Font* font, char* message, int x, int y);
Gfx* menuBuildBorder(int x, int y, int width, int height);
Gfx* menuBuildHorizontalLine(int x, int y, int width);
Gfx* menuBuildSolidBorder(int x, int y, int w, int h, int nx, int ny, int nw, int nh);
Gfx* menuBuildOutline(int x, int y, int width, int height, int invert);
struct MenuButton menuBuildButton(struct Font* font, char* message, int x, int y, int width, int height);
void menuSetRenderColor(struct RenderState* renderState, int isSelected, struct Coloru8* selected, struct Coloru8* defaultColor);

View file

@ -33,8 +33,8 @@ struct Chapter gChapters[] = {
#define CHAPTER_IMAGE_SIZE (84 * 48 * 2)
void chapterMenuInit(struct ChapterMenu* chapterMenu, int x, int y) {
chapterMenu->chapterText = malloc(sizeof(Gfx) * 3 * 10 + 1);
chapterMenu->testChamberText = malloc(sizeof(Gfx) * 3 * 14 + 1);
chapterMenu->chapterText = malloc(sizeof(Gfx) * GFX_ENTRIES_PER_IMAGE * 10 + GFX_ENTRIES_PER_END_DL);
chapterMenu->testChamberText = malloc(sizeof(Gfx) * GFX_ENTRIES_PER_IMAGE * 14 + GFX_ENTRIES_PER_END_DL);
chapterMenu->border = menuBuildSolidBorder(
x, y + 27,
92, 58,

View file

@ -38,6 +38,8 @@ void optionsMenuInit(struct OptionsMenu* options) {
MENU_LEFT + OPTIONS_PADDING, MENU_TOP + OPTIONS_PADDING,
MENU_WIDTH - OPTIONS_PADDING * 2, MENU_HEIGHT - OPTIONS_PADDING * 2
);
controlsMenuInit(&options->controlsMenu);
}
enum MainMenuState optionsMenuUpdate(struct OptionsMenu* options) {
@ -66,4 +68,10 @@ void optionsMenuRender(struct OptionsMenu* options, struct RenderState* renderSt
gSPDisplayList(renderState->dl++, ui_material_list[DEJAVU_SANS_INDEX]);
renderState->dl = tabsRenderText(&options->tabs, renderState->dl);
gSPDisplayList(renderState->dl++, ui_material_revert_list[DEJAVU_SANS_INDEX]);
switch (options->tabs.selectedTab) {
case 0:
controlsMenuRender(&options->controlsMenu, renderState, task);
break;
}
}

View file

@ -5,12 +5,15 @@
#include "./menu.h"
#include "./menu_state.h"
#include "./tabs.h"
#include "./controls.h"
struct OptionsMenu {
Gfx* menuOutline;
Gfx* optionsText;
struct Tabs tabs;
struct ControlsMenu controlsMenu;
};
void optionsMenuInit(struct OptionsMenu* options);