From e104577c41dbf9db0ca313cb2446ee3b786305e2 Mon Sep 17 00:00:00 2001 From: James Lambert Date: Tue, 25 Apr 2023 08:51:55 -0600 Subject: [PATCH] Work on configurable controls --- src/controls/controller_actions.c | 161 ++++++++++++++++++++++++++++++ src/controls/controller_actions.h | 53 ++++++++++ src/font/font.c | 36 +++++++ src/font/font.h | 2 + src/graphics/graphics.c | 7 -- src/main.c | 5 +- src/menu/controls.c | 1 + src/menu/controls.h | 8 ++ src/menu/main_menu.c | 2 +- src/menu/menu.c | 12 ++- src/menu/menu.h | 3 + src/menu/options_menu.c | 38 ++++++- src/menu/options_menu.h | 3 + src/menu/tabs.c | 105 +++++++++++++++++++ src/menu/tabs.h | 34 +++++++ src/player/player.c | 58 +++-------- src/scene/portal.c | 5 - src/scene/scene.c | 30 +++--- 18 files changed, 480 insertions(+), 83 deletions(-) create mode 100644 src/controls/controller_actions.c create mode 100644 src/controls/controller_actions.h create mode 100644 src/menu/controls.c create mode 100644 src/menu/controls.h create mode 100644 src/menu/tabs.c create mode 100644 src/menu/tabs.h diff --git a/src/controls/controller_actions.c b/src/controls/controller_actions.c new file mode 100644 index 0000000..3dd61dd --- /dev/null +++ b/src/controls/controller_actions.c @@ -0,0 +1,161 @@ +#include "controller_actions.h" + +#include "../util/memory.h" +#include "./controller.h" +#include "../math/mathf.h" + +enum ControllerAction gDefaultControllerSettings[ControllerActionSourceCount] = { + [ControllerActionSourceAButton] = ControllerActionJump, + [ControllerActionSourceBButton] = ControllerActionUseItem, + [ControllerActionSourceCUpButton] = ControllerActionMove, + [ControllerActionSourceCRightButton] = ControllerActionMove, + [ControllerActionSourceCDownButton] = ControllerActionMove, + [ControllerActionSourceCLeftButton] = ControllerActionMove, + [ControllerActionSourceDUpButton] = ControllerActionMove, + [ControllerActionSourceDRightButton] = ControllerActionMove, + [ControllerActionSourceDDownButton] = ControllerActionMove, + [ControllerActionSourceDLeftButton] = ControllerActionMove, + [ControllerActionSourceStartButton] = ControllerActionPause, + [ControllerActionSourceLTrig] = ControllerActionOpenPortal1, + [ControllerActionSourceRTrig] = ControllerActionOpenPortal1, + [ControllerActionSourceZTrig] = ControllerActionOpenPortal0, + [ControllerActionSourceJoystick] = ControllerActionRotate, +}; + +unsigned short gActionSourceButtonMask[ControllerActionSourceCount] = { + [ControllerActionSourceAButton] = A_BUTTON, + [ControllerActionSourceBButton] = B_BUTTON, + [ControllerActionSourceCUpButton] = U_CBUTTONS, + [ControllerActionSourceCRightButton] = R_CBUTTONS, + [ControllerActionSourceCDownButton] = D_CBUTTONS, + [ControllerActionSourceCLeftButton] = L_CBUTTONS, + [ControllerActionSourceDUpButton] = U_JPAD, + [ControllerActionSourceDRightButton] = R_JPAD, + [ControllerActionSourceDDownButton] = D_JPAD, + [ControllerActionSourceDLeftButton] = L_JPAD, + [ControllerActionSourceStartButton] = START_BUTTON, + [ControllerActionSourceLTrig] = L_TRIG, + [ControllerActionSourceRTrig] = R_TRIG, + [ControllerActionSourceZTrig] = Z_TRIG, + [ControllerActionSourceJoystick] = 0, +}; + +#define IS_DIRECTION_ACTION(action) ((action) >= ControllerActionMove && (action) <= ControllerActionRotate) + +enum ControllerAction gControllerSettings[2][ControllerActionSourceCount]; + +int gActionState = 0; +struct Vector2 gDirections[2]; + +void controllerActionInit() { + memCopy(gControllerSettings[0], gDefaultControllerSettings, sizeof(gDefaultControllerSettings)); + zeroMemory(gControllerSettings[1], sizeof(gDefaultControllerSettings)); +} + +void controllerActionApply(enum ControllerAction action) { + gActionState |= (1 << action); +} + +#define DEADZONE_SIZE 5 +#define MAX_JOYSTICK_RANGE 80 + +float controllerCleanupStickInput(s8 input) { + if (input > -DEADZONE_SIZE && input < DEADZONE_SIZE) { + return 0.0f; + } + + if (input >= MAX_JOYSTICK_RANGE) { + return 1.0f; + } + + if (input <= -MAX_JOYSTICK_RANGE) { + return -1.0f; + } + + return ((float)input + (input > 0 ? -DEADZONE_SIZE : DEADZONE_SIZE)) * (1.0f / (MAX_JOYSTICK_RANGE - DEADZONE_SIZE)); +} + +void controllerActionReadDirection(enum ControllerActionSource source, int controllerIndex, int directionIndex) { + struct Vector2 result = gDirections[directionIndex]; + + switch (source) { + case ControllerActionSourceCUpButton: + if (controllerGetButton(controllerIndex, U_CBUTTONS)) { + result.y += 1.0f; + } + if (controllerGetButton(controllerIndex, D_CBUTTONS)) { + result.y -= 1.0f; + } + if (controllerGetButton(controllerIndex, R_CBUTTONS)) { + result.x += 1.0f; + } + if (controllerGetButton(controllerIndex, L_CBUTTONS)) { + result.x -= 1.0f; + } + break; + case ControllerActionSourceDUpButton: + if (controllerGetButton(controllerIndex, U_JPAD)) { + result.y += 1.0f; + } + if (controllerGetButton(controllerIndex, D_JPAD)) { + result.y -= 1.0f; + } + if (controllerGetButton(controllerIndex, R_JPAD)) { + result.x += 1.0f; + } + if (controllerGetButton(controllerIndex, L_JPAD)) { + result.x -= 1.0f; + } + break; + case ControllerActionSourceJoystick: + { + OSContPad* pad = controllersGetControllerData(controllerIndex); + result.x = controllerCleanupStickInput(pad->stick_x); + result.y = controllerCleanupStickInput(pad->stick_y); + break; + } + default: + break; + } + + gDirections[directionIndex] = result; +} + +void controllerActionRead() { + gActionState = 0; + gDirections[0] = gZeroVec2; + gDirections[1] = gZeroVec2; + + for (int controllerIndex = 0; controllerIndex < 2; ++controllerIndex) { + for (int sourceIndex = 0; sourceIndex < ControllerActionSourceCount; ++sourceIndex) { + enum ControllerAction action = gControllerSettings[controllerIndex][sourceIndex]; + + if (IS_DIRECTION_ACTION(action)) { + controllerActionReadDirection(sourceIndex, controllerIndex, action - ControllerActionMove); + + if (sourceIndex == ControllerActionSourceCUpButton || sourceIndex == ControllerActionSourceDUpButton) { + sourceIndex += 3; + } + } else if (controllerGetButtonDown(controllerIndex, gActionSourceButtonMask[sourceIndex])) { + controllerActionApply(action); + } + } + } + + for (int i = 0; i < 2; ++i) { + gDirections[i].x = clampf(gDirections[i].x, -1.0f, 1.0f); + gDirections[i].y = clampf(gDirections[i].y, -1.0f, 1.0f); + } +} + +struct Vector2 controllerDirectionGet(enum ControllerAction direction) { + if (!IS_DIRECTION_ACTION(direction)) { + return gZeroVec2; + } + + return gDirections[direction - ControllerActionMove]; +} + +int controllerActionGet(enum ControllerAction action) { + return (gActionState & (1 << action)) != 0; +} \ No newline at end of file diff --git a/src/controls/controller_actions.h b/src/controls/controller_actions.h new file mode 100644 index 0000000..5ae5c1f --- /dev/null +++ b/src/controls/controller_actions.h @@ -0,0 +1,53 @@ +#ifndef __CONTROLS_CONTROLLER_ACTIONS_H__ +#define __CONTROLS_CONTROLLER_ACTIONS_H__ + +#include "../math/vector2.h" + +enum ControllerActionSource { + // face buttons + ControllerActionSourceAButton, + ControllerActionSourceBButton, + ControllerActionSourceStartButton, + // c buttons + ControllerActionSourceCUpButton, + ControllerActionSourceCRightButton, + ControllerActionSourceCDownButton, + ControllerActionSourceCLeftButton, + // d pad + ControllerActionSourceDUpButton, + ControllerActionSourceDRightButton, + ControllerActionSourceDDownButton, + ControllerActionSourceDLeftButton, + // triggers + ControllerActionSourceLTrig, + ControllerActionSourceRTrig, + ControllerActionSourceZTrig, + // joystick + ControllerActionSourceJoystick, + + ControllerActionSourceCount, +}; + +enum ControllerAction { + ControllerActionOpenNone, + ControllerActionOpenPortal0, + ControllerActionOpenPortal1, + ControllerActionJump, + ControllerActionUseItem, + ControllerActionDuck, + ControllerActionLookForward, + ControllerActionLookBackward, + ControllerActionPause, + // direction actions + ControllerActionMove, + ControllerActionRotate, +}; + +void controllerActionInit(); + +void controllerActionRead(); + +struct Vector2 controllerDirectionGet(enum ControllerAction direction); +int controllerActionGet(enum ControllerAction action); + +#endif \ No newline at end of file diff --git a/src/font/font.c b/src/font/font.c index a4107cc..6ccd7fe 100644 --- a/src/font/font.c +++ b/src/font/font.c @@ -79,5 +79,41 @@ int fontCountGfx(struct Font* font, char* message) { result += 3; } + return result; +} + +struct Vector2s16 fontMeasure(struct Font* font, char* message) { + int startX = 0; + char prev = 0; + int x = 0; + int y = 0; + + struct Vector2s16 result; + + result.x = 0; + + for (; *message; prev = *message, ++message) { + char curr = *message; + + if (curr == '\n') { + y += font->charHeight; + x = startX; + continue; + } + + if ((unsigned char)curr >= font->symbolCount) { + continue; + } + + struct FontSymbol* symbol = &font->symbols[(int)curr]; + + x += fontDetermineKerning(font, prev, curr); + x += symbol->xadvance; + + result.x = MAX(result.x, x); + } + + result.y = y + font->charHeight; + return result; } \ No newline at end of file diff --git a/src/font/font.h b/src/font/font.h index f16b8ca..ba43178 100644 --- a/src/font/font.h +++ b/src/font/font.h @@ -2,6 +2,7 @@ #define __FONT_FONT_H__ #include +#include "../math/vector2s16.h" struct FontKerning { char amount; @@ -31,5 +32,6 @@ struct Font { int fontDetermineKerning(struct Font* font, char first, char second); Gfx* fontRender(struct Font* font, char* message, int x, int y, Gfx* dl); int fontCountGfx(struct Font* font, char* message); +struct Vector2s16 fontMeasure(struct Font* font, char* message); #endif \ No newline at end of file diff --git a/src/graphics/graphics.c b/src/graphics/graphics.c index f50d8f5..fca1f76 100644 --- a/src/graphics/graphics.c +++ b/src/graphics/graphics.c @@ -2,8 +2,6 @@ #include "initgfx.h" #include "util/memory.h" -#include "../controls/controller.h" - struct GraphicsTask gGraphicsTasks[2]; extern OSMesgQueue gfxFrameMsgQ; @@ -75,11 +73,6 @@ void graphicsCreateTask(struct GraphicsTask* targetTask, GraphicsCallback callba gDPPipeSync(renderState->dl++); gDPSetColorImage(renderState->dl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_WD, osVirtualToPhysical(targetTask->framebuffer)); - if (controllerGetButton(1, A_BUTTON)) { - gDPSetFillColor(renderState->dl++, 0); - gDPFillRectangle(renderState->dl++, 0, 0, SCREEN_WD-1, SCREEN_HT-1); - } - gDPPipeSync(renderState->dl++); gDPSetCycleType(renderState->dl++, G_CYC_1CYCLE); diff --git a/src/main.c b/src/main.c index 9c7c41b..afc289f 100644 --- a/src/main.c +++ b/src/main.c @@ -11,6 +11,7 @@ #include "util/memory.h" #include "string.h" #include "controls/controller.h" +#include "controls/controller_actions.h" #include "scene/dynamic_scene.h" #include "audio/soundplayer.h" #include "audio/audio.h" @@ -199,9 +200,10 @@ static void gameProc(void* arg) { contactSolverInit(&gContactSolver); portalSurfaceCleanupQueueInit(); savefileNew(); - levelLoadWithCallbacks(MAIN_MENU); + levelLoadWithCallbacks(0); cutsceneRunnerReset(); controllersInit(); + controllerActionInit(); initAudio(fps); soundPlayerInit(); skSetSegmentLocation(CHARACTER_ANIMATION_SEGMENT, (unsigned)_animation_segmentSegmentRomStart); @@ -245,6 +247,7 @@ static void gameProc(void* arg) { controllersTriggerRead(); controllerHandlePlayback(); + controllerActionRead(); skAnimatorSync(); if (inputIgnore) { diff --git a/src/menu/controls.c b/src/menu/controls.c new file mode 100644 index 0000000..7825dc2 --- /dev/null +++ b/src/menu/controls.c @@ -0,0 +1 @@ +#include "controls.h" \ No newline at end of file diff --git a/src/menu/controls.h b/src/menu/controls.h new file mode 100644 index 0000000..789d275 --- /dev/null +++ b/src/menu/controls.h @@ -0,0 +1,8 @@ +#ifndef __MENU_CONTROLS_H__ +#define __MENU_CONTROLS_H__ + +struct ControlsMenu { + +}; + +#endif \ No newline at end of file diff --git a/src/menu/main_menu.c b/src/menu/main_menu.c index a0ee1a3..ab872e4 100644 --- a/src/menu/main_menu.c +++ b/src/menu/main_menu.c @@ -24,7 +24,7 @@ void mainMenuInit(struct MainMenu* mainMenu) { newGameInit(&mainMenu->newGameMenu); optionsMenuInit(&mainMenu->optionsMenu); - mainMenu->state = MainMenuStateLanding; + mainMenu->state = MainMenuStateOptions; mainMenuReadCamera(mainMenu); diff --git a/src/menu/menu.c b/src/menu/menu.c index a06f6ac..9f2902e 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -2,6 +2,11 @@ #include "../util/memory.h" +struct Coloru8 gSelectionOrange = {255, 156, 0, 255}; +struct Coloru8 gSelectionGray = {201, 201, 201, 255}; +struct Coloru8 gBorderHighlight = {193, 193, 193, 255}; +struct Coloru8 gBorderDark = {86, 86, 86, 255}; + Gfx* menuBuildText(struct Font* font, char* message, int x, int y) { Gfx* result = malloc(sizeof(Gfx) * (fontCountGfx(font, message) + 1)); Gfx* dl = result; @@ -121,11 +126,11 @@ struct MenuButton menuBuildButton(struct Font* font, char* message, int x, int y Gfx* dl = result.outline; gDPPipeSync(dl++); - gDPSetEnvColor(dl++, 188, 188, 188, 255); + 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++, 76, 76, 76, 255); + 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++); @@ -133,9 +138,6 @@ struct MenuButton menuBuildButton(struct Font* font, char* message, int x, int y return result; } -struct Coloru8 gSelectionOrange = {255, 156, 0, 255}; -struct Coloru8 gSelectionGray = {201, 201, 201, 255}; - void menuSetRenderColor(struct RenderState* renderState, int isSelected, struct Coloru8* selected, struct Coloru8* defaultColor) { if (isSelected) { gDPSetEnvColor(renderState->dl++, selected->r, selected->g, selected->b, selected->a); diff --git a/src/menu/menu.h b/src/menu/menu.h index c0deb94..8b52c04 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -15,6 +15,9 @@ struct MenuButton { extern struct Coloru8 gSelectionOrange; extern struct Coloru8 gSelectionGray; +extern struct Coloru8 gBorderHighlight; +extern struct Coloru8 gBorderDark; + 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); diff --git a/src/menu/options_menu.c b/src/menu/options_menu.c index 36aa3ea..ac42c37 100644 --- a/src/menu/options_menu.c +++ b/src/menu/options_menu.c @@ -7,13 +7,37 @@ #include "../controls/controller.h" -#define OPTIONS_LEFT 40 -#define OPTIONS_TOP 45 + +struct Tab gOptionTabs[] = { + { + .message = "Controls", + }, + { + .message = "Audio", + }, +}; + +#define MENU_WIDTH 280 +#define MENU_HEIGHT 200 + +#define MENU_LEFT ((SCREEN_WD - MENU_WIDTH) / 2) +#define MENU_TOP ((SCREEN_HT - MENU_HEIGHT) / 2) + +#define OPTIONS_PADDING 8 void optionsMenuInit(struct OptionsMenu* options) { - options->menuOutline = menuBuildBorder(OPTIONS_LEFT, OPTIONS_TOP, SCREEN_WD - OPTIONS_LEFT * 2, SCREEN_HT - OPTIONS_TOP * 2); + options->menuOutline = menuBuildBorder(MENU_LEFT, MENU_TOP, MENU_WIDTH, MENU_HEIGHT); options->optionsText = menuBuildText(&gDejaVuSansFont, "OPTIONS", 48, 48); + + tabsInit( + &options->tabs, + gOptionTabs, + sizeof(gOptionTabs) / sizeof(*gOptionTabs), + &gDejaVuSansFont, + MENU_LEFT + OPTIONS_PADDING, MENU_TOP + OPTIONS_PADDING, + MENU_WIDTH - OPTIONS_PADDING * 2, MENU_HEIGHT - OPTIONS_PADDING * 2 + ); } enum MainMenuState optionsMenuUpdate(struct OptionsMenu* options) { @@ -34,4 +58,12 @@ void optionsMenuRender(struct OptionsMenu* options, struct RenderState* renderSt gSPDisplayList(renderState->dl++, ui_material_list[ROUNDED_CORNERS_INDEX]); gSPDisplayList(renderState->dl++, options->menuOutline); gSPDisplayList(renderState->dl++, ui_material_revert_list[ROUNDED_CORNERS_INDEX]); + + gSPDisplayList(renderState->dl++, ui_material_list[SOLID_ENV_INDEX]); + gSPDisplayList(renderState->dl++, options->tabs.tabOutline); + gSPDisplayList(renderState->dl++, ui_material_revert_list[SOLID_ENV_INDEX]); + + 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]); } \ No newline at end of file diff --git a/src/menu/options_menu.h b/src/menu/options_menu.h index 31c7681..46916b3 100644 --- a/src/menu/options_menu.h +++ b/src/menu/options_menu.h @@ -4,10 +4,13 @@ #include "../graphics/graphics.h" #include "./menu.h" #include "./menu_state.h" +#include "./tabs.h" struct OptionsMenu { Gfx* menuOutline; Gfx* optionsText; + + struct Tabs tabs; }; void optionsMenuInit(struct OptionsMenu* options); diff --git a/src/menu/tabs.c b/src/menu/tabs.c new file mode 100644 index 0000000..27cbf24 --- /dev/null +++ b/src/menu/tabs.c @@ -0,0 +1,105 @@ +#include "tabs.h" + +#include "../util/memory.h" +#include "./menu.h" + +#define LEFT_TEXT_PADDING 4 +#define RIGHT_TEXT_PADDING 16 +#define TOP_TEXT_PADDING 3 + +#define TAB_HEIGHT 18 + +void tabsSetSelectedTab(struct Tabs* tabs, int index) { + if (index < 0 || index >= tabs->tabCount) { + return; + } + + tabs->selectedTab = 0; + + Gfx* dl = tabs->tabOutline; + + gDPPipeSync(dl++); + gDPSetEnvColor(dl++, gBorderDark.r, gBorderDark.g, gBorderDark.b, gBorderDark.a); + gDPFillRectangle(dl++, tabs->x, tabs->y + tabs->height - 1, tabs->x + tabs->width, tabs->y + tabs->height); + gDPFillRectangle(dl++, tabs->x + tabs->width - 1, tabs->y + TAB_HEIGHT, tabs->x + tabs->width, tabs->y + tabs->height); + + for (int i = 0; i < tabs->tabCount; ++i) { + struct TabRenderData* tab = &tabs->tabRenderData[i]; + int tabTop = (i == tabs->selectedTab) ? tabs->y : (tabs->y + 1); + + gDPFillRectangle(dl++, tab->x + tab->width - 2, tabTop, tab->x + tab->width - 1, tabs->y + TAB_HEIGHT); + + fontRender(tabs->font, tabs->tabs[i].message, tab->x + LEFT_TEXT_PADDING, tabTop + TOP_TEXT_PADDING, tab->text); + } + + gDPPipeSync(dl++); + gDPSetEnvColor(dl++, gBorderHighlight.r, gBorderHighlight.g, gBorderHighlight.b, gBorderHighlight.a); + gDPFillRectangle(dl++, tabs->x, tabs->y + TAB_HEIGHT, tabs->x + 1, tabs->y + tabs->height); + + for (int i = 0; i < tabs->tabCount; ++i) { + struct TabRenderData* tab = &tabs->tabRenderData[i]; + int tabTop = (i == tabs->selectedTab) ? tabs->y : (tabs->y + 1); + + gDPFillRectangle(dl++, tab->x, tabTop, tab->x + 1, tabs->y + TAB_HEIGHT); + gDPFillRectangle(dl++, tab->x, tabTop, tab->x + tab->width - 2, tabTop + 1); + } + + struct TabRenderData* selectedTab = tabs->selectedTab < tabs->tabCount ? &tabs->tabRenderData[tabs->selectedTab] : NULL; + + if (selectedTab) { + gDPFillRectangle(dl++, tabs->x, tabs->y + TAB_HEIGHT, selectedTab->x, tabs->y + TAB_HEIGHT + 1); + gDPFillRectangle(dl++, tabs->x + selectedTab->width, tabs->y + TAB_HEIGHT, tabs->x + tabs->width, tabs->y + TAB_HEIGHT + 1); + } + + gSPEndDisplayList(dl++); +} + +void tabsInit(struct Tabs* tabs, struct Tab* tabList, int tabCount, struct Font* font, int x, int y, int width, int height) { + tabs->tabs = tabList; + tabs->tabCount = tabCount; + tabs->font = font; + tabs->width = width; + tabs->height = height; + tabs->x = x; + tabs->y = y; + tabs->tabOutline = malloc(sizeof(Gfx) * (10 + 3 * tabCount)); + + tabs->tabRenderData = malloc(sizeof(struct TabRenderData) * tabCount); + + int currentX = x; + + for (int i = 0; i < tabCount; ++i) { + struct Vector2s16 textSize = fontMeasure(font, tabList[i].message); + tabs->tabRenderData[i].text = menuBuildText(font, tabList[i].message, currentX + LEFT_TEXT_PADDING, y + TOP_TEXT_PADDING); + tabs->tabRenderData[i].width = textSize.x + LEFT_TEXT_PADDING + RIGHT_TEXT_PADDING; + tabs->tabRenderData[i].x = currentX; + + currentX += tabs->tabRenderData[i].width; + } + + tabs->selectedTab = -1; + tabsSetSelectedTab(tabs, 0); +} + +Gfx* tabsRenderText(struct Tabs* tabs, Gfx* dl) { + gDPPipeSync(dl++); + gDPSetEnvColor(dl++, gSelectionGray.r, gSelectionGray.g, gSelectionGray.b, gSelectionGray.a); + + for (int i = 0; i < tabs->tabCount; ++i) { + if (i == tabs->selectedTab) { + gDPSetEnvColor(dl++, gColorWhite.r, gColorWhite.g, gColorWhite.b, gColorWhite.a); + } + + gSPDisplayList(dl++, tabs->tabRenderData[i].text); + + if (i == tabs->selectedTab) { + gDPPipeSync(dl++); + gDPSetEnvColor(dl++, gSelectionGray.r, gSelectionGray.g, gSelectionGray.b, gSelectionGray.a); + } + } + + gDPPipeSync(dl++); + gDPSetEnvColor(dl++, gColorWhite.r, gColorWhite.g, gColorWhite.b, gColorWhite.a); + + return dl; +} \ No newline at end of file diff --git a/src/menu/tabs.h b/src/menu/tabs.h new file mode 100644 index 0000000..39189d8 --- /dev/null +++ b/src/menu/tabs.h @@ -0,0 +1,34 @@ +#ifndef __MENU_TABS_H__ +#define __MENU_TABS_H__ + +#include +#include "../font/font.h" + +struct Tab { + char* message; +}; + +struct TabRenderData { + Gfx* text; + short width; + short x; +}; + +struct Tabs { + struct Tab* tabs; + struct Font* font; + short tabCount; + short width; + short height; + short selectedTab; + short x; + short y; + Gfx* tabOutline; + struct TabRenderData* tabRenderData; +}; + +void tabsInit(struct Tabs* tabs, struct Tab* tabList, int tabCount, struct Font* font, int x, int y, int width, int height); +void tabsSetSelectedTab(struct Tabs* tabs, int index); +Gfx* tabsRenderText(struct Tabs* tabs, Gfx* dl); + +#endif \ No newline at end of file diff --git a/src/player/player.c b/src/player/player.c index d9dc9fb..385dfd9 100644 --- a/src/player/player.c +++ b/src/player/player.c @@ -3,7 +3,7 @@ #include "player.h" #include "../audio/clips.h" #include "../audio/soundplayer.h" -#include "../controls/controller.h" +#include "../controls/controller_actions.h" #include "../defs.h" #include "../levels/levels.h" #include "../math/mathf.h" @@ -317,14 +317,8 @@ void playerUpdateGrabbedObject(struct Player* player) { return; } - if (controllerGetButtonDown(0, B_BUTTON) || controllerGetButtonDown(1, U_JPAD)) { + if (controllerActionGet(ControllerActionUseItem)) { if (player->grabConstraint.object) { - if (controllerGetButtonDown(1, U_JPAD)) { - struct Vector3 forward; - quatMultVector(&player->lookTransform.rotation, &gForward, &forward); - vector3AddScaled(&player->grabConstraint.object->body->velocity, &forward, -50.0f, &player->grabConstraint.object->body->velocity); - } - playerSetGrabbing(player, NULL); } else { struct RaycastHit hit; @@ -440,25 +434,6 @@ void playerUpdateGunObject(struct Player* player) { } -#define DEADZONE_SIZE 5 -#define MAX_JOYSTICK_RANGE 80 - -float playerCleanupStickInput(s8 input) { - if (input > -DEADZONE_SIZE && input < DEADZONE_SIZE) { - return 0.0f; - } - - if (input >= MAX_JOYSTICK_RANGE) { - return 1.0f; - } - - if (input <= -MAX_JOYSTICK_RANGE) { - return -1.0f; - } - - return ((float)input + (input > 0 ? -DEADZONE_SIZE : DEADZONE_SIZE)) * (1.0f / (MAX_JOYSTICK_RANGE - DEADZONE_SIZE)); -} - void playerGetMoveBasis(struct Transform* transform, struct Vector3* forward, struct Vector3* right) { quatMultVector(&transform->rotation, &gForward, forward); quatMultVector(&transform->rotation, &gRight, right); @@ -559,7 +534,7 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) { int isDead = playerIsDead(player); - if (!isDead && (player->flags & PlayerFlagsGrounded) && controllerGetButtonDown(0, A_BUTTON)) { + if (!isDead && (player->flags & PlayerFlagsGrounded) && controllerActionGet(ControllerActionJump)) { player->body.velocity.y = JUMP_IMPULSE; player->flags |= PlayerJustJumped; } @@ -575,20 +550,13 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) { } if (!isDead) { - if (controllerGetButton(0, L_JPAD)) { - vector3AddScaled(&targetVelocity, &right, -PLAYER_SPEED, &targetVelocity); - } else if (controllerGetButton(0, R_JPAD)) { - vector3AddScaled(&targetVelocity, &right, PLAYER_SPEED, &targetVelocity); - } + struct Vector2 moveInput = controllerDirectionGet(ControllerActionMove); - if (controllerGetButton(0, U_JPAD)) { - vector3AddScaled(&targetVelocity, &forward, -PLAYER_SPEED, &targetVelocity); - } else if (controllerGetButton(0, D_JPAD)) { - vector3AddScaled(&targetVelocity, &forward, PLAYER_SPEED, &targetVelocity); - } + vector3AddScaled(&targetVelocity, &right, PLAYER_SPEED * moveInput.x, &targetVelocity); + vector3AddScaled(&targetVelocity, &forward, -PLAYER_SPEED * moveInput.y, &targetVelocity); // if player isnt crouched, crouch - if (!(player->flags & PlayerCrouched) && (controllerGetButtonDown(0, R_CBUTTONS))){ + if (!(player->flags & PlayerCrouched) && (controllerActionGet(ControllerActionDuck))){ player->flags |= PlayerCrouched; camera_y_modifier = -0.25; collisionSceneRemoveDynamicObject(&player->collisionObject); @@ -597,7 +565,7 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) { collisionObjectUpdateBB(&player->collisionObject); } //if player crouched, uncrouch - else if ((player->flags & PlayerCrouched) && (controllerGetButtonDown(0, R_CBUTTONS))){ + else if ((player->flags & PlayerCrouched) && (controllerActionGet(ControllerActionDuck))){ player->flags &= ~PlayerCrouched; camera_y_modifier = 0.0; collisionSceneRemoveDynamicObject(&player->collisionObject); @@ -607,7 +575,7 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) { } //look straight forward - if (controllerGetButtonDown(0, U_CBUTTONS)){ + if (controllerActionGet(ControllerActionLookForward)){ struct Vector3 lookingForward; vector3Negate(&gForward, &lookingForward); quatMultVector(&player->lookTransform.rotation, &lookingForward, &lookingForward); @@ -617,7 +585,7 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) { } } //look behind - if (controllerGetButtonDown(0, D_CBUTTONS)){ + if (controllerActionGet(ControllerActionLookBackward)){ struct Vector3 lookingForward; vector3Negate(&gForward, &lookingForward); quatMultVector(&player->lookTransform.rotation, &lookingForward, &lookingForward); @@ -751,9 +719,9 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) { soundPlayerPlay(soundsPortalExit[2 - didPassThroughPortal], 0.75f, 1.0f, NULL, NULL); } - OSContPad* controllerInput = controllersGetControllerData(0); - float targetYaw = -playerCleanupStickInput(controllerInput->stick_x) * ROTATE_RATE; - float targetPitch = playerCleanupStickInput(controllerInput->stick_y) * ROTATE_RATE; + struct Vector2 lookInput = controllerDirectionGet(ControllerActionRotate); + float targetYaw = -lookInput.x * ROTATE_RATE; + float targetPitch = lookInput.y * ROTATE_RATE; player->yawVelocity = mathfMoveTowards( player->yawVelocity, diff --git a/src/scene/portal.c b/src/scene/portal.c index a5d17f8..8c8183e 100644 --- a/src/scene/portal.c +++ b/src/scene/portal.c @@ -11,7 +11,6 @@ #include "../util/time.h" #include "../levels/levels.h" #include "./portal_surface_generator.h" -#include "../controls/controller.h" #include "../build/assets/models/portal/portal_blue.h" #include "../build/assets/models/portal/portal_blue_filled.h" @@ -62,10 +61,6 @@ void portalUpdate(struct Portal* portal, int isOpen) { portal->opacity = 1.0f; } - if (controllerGetButton(1, B_BUTTON)) { - portal->opacity = 0.5f; - } - if (portal->scale < 1.0f) { portal->scale += FIXED_DELTA_TIME * (1.0f / PORTAL_GROW_TIME); diff --git a/src/scene/scene.c b/src/scene/scene.c index 046b7c5..769d144 100644 --- a/src/scene/scene.c +++ b/src/scene/scene.c @@ -10,11 +10,11 @@ #include "materials/point_light_rendered.h" #include "util/time.h" #include "sk64/skelatool_defs.h" -#include "controls/controller.h" #include "shadow_map.h" #include "../physics/point_constraint.h" #include "../physics/debug_renderer.h" #include "../controls/controller.h" +#include "../controls/controller_actions.h" #include "../physics/collision_scene.h" #include "../levels/static_render.h" #include "../levels/levels.h" @@ -255,32 +255,30 @@ void sceneCheckPortals(struct Scene* scene) { quatMultVector(&scene->player.lookTransform.rotation, &raycastRay.dir, &raycastRay.dir); quatMultVector(&scene->player.lookTransform.rotation, &gUp, &playerUp); - int bluePortalFlags; - if (scene->player.flags & PlayerHasSecondPortalGun){ - bluePortalFlags = (L_TRIG); - }else{ - bluePortalFlags = (L_TRIG | Z_TRIG | R_TRIG); - } + int fireBlue = controllerActionGet(ControllerActionOpenPortal0); + int fireOrange = controllerActionGet(ControllerActionOpenPortal1); - if (controllerGetButtonDown(0, Z_TRIG | R_TRIG) && (scene->player.flags & PlayerHasSecondPortalGun) && !playerIsGrabbing(&scene->player)) { + int hasBlue = (scene->player.flags & PlayerHasFirstPortalGun) != 0; + int hasOrange = (scene->player.flags & PlayerHasSecondPortalGun) != 0; + + if (fireOrange && hasOrange && !playerIsGrabbing(&scene->player)) { sceneFirePortal(scene, &raycastRay, &playerUp, 0, scene->player.body.currentRoom, 1, 0); scene->player.flags |= PlayerJustShotPortalGun; scene->last_portal_indx_shot=0; soundPlayerPlay(soundsPortalgunShoot[0], 1.0f, 1.0f, NULL, NULL); } - if (controllerGetButtonDown(0, bluePortalFlags) && (scene->player.flags & PlayerHasFirstPortalGun) && !playerIsGrabbing(&scene->player)) { + if ((fireBlue || (!hasOrange && fireOrange)) && hasBlue && !playerIsGrabbing(&scene->player)) { sceneFirePortal(scene, &raycastRay, &playerUp, 1, scene->player.body.currentRoom, 1, 0); scene->player.flags |= PlayerJustShotPortalGun; scene->last_portal_indx_shot=1; soundPlayerPlay(soundsPortalgunShoot[1], 1.0f, 1.0f, NULL, NULL); } - if (controllerGetButtonDown(0, R_TRIG | L_TRIG | Z_TRIG) && playerIsGrabbing(&scene->player)){ + if ((fireOrange || fireBlue) && playerIsGrabbing(&scene->player)){ playerSetGrabbing(&scene->player, NULL); } - scene->looked_wall_portalable_0 = 0; scene->looked_wall_portalable_1 = 0; @@ -444,7 +442,7 @@ void sceneUpdate(struct Scene* scene) { sceneUpdateListeners(scene); sceneCheckPortals(scene); - if ((playerIsDead(&scene->player) && controllerGetButtonDown(0, START_BUTTON | A_BUTTON)) || + if ((playerIsDead(&scene->player) && (controllerActionGet(ControllerActionPause) || controllerActionGet(ControllerActionJump))) || scene->player.lookTransform.position.y < KILL_PLANE_Y) { levelLoadLastCheckpoint(); } @@ -553,7 +551,7 @@ void sceneUpdate(struct Scene* scene) { scene->cpuTime = osGetTime() - frameStart; scene->lastFrameStart = frameStart; - OSContPad* freecam = controllersGetControllerData(1); + OSContPad* freecam = controllersGetControllerData(2); struct Vector3 lookDir; @@ -562,7 +560,7 @@ void sceneUpdate(struct Scene* scene) { playerGetMoveBasis(&scene->camera.transform, &lookDir, &rightDir); if (freecam->stick_y) { - if (controllerGetButton(1, Z_TRIG)) { + if (controllerGetButton(2, Z_TRIG)) { vector3AddScaled( &scene->freeCameraOffset, &lookDir, @@ -583,13 +581,13 @@ void sceneUpdate(struct Scene* scene) { ); } - if (controllerGetButtonDown(1, START_BUTTON)) { + if (controllerGetButtonDown(2, START_BUTTON)) { scene->freeCameraOffset = gZeroVec; } vector3Add(&scene->camera.transform.position, &scene->freeCameraOffset, &scene->camera.transform.position); - if (controllerGetButtonDown(1, L_TRIG)) { + if (controllerGetButtonDown(2, L_TRIG)) { struct Transform identityTransform; transformInitIdentity(&identityTransform); identityTransform.position.y = 1.0f;