mirror of
https://github.com/mwpenny/portal64-still-alive.git
synced 2024-10-20 22:47:37 -04:00
Work on configurable controls
This commit is contained in:
parent
b7d1404868
commit
e104577c41
161
src/controls/controller_actions.c
Normal file
161
src/controls/controller_actions.c
Normal file
|
@ -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;
|
||||
}
|
53
src/controls/controller_actions.h
Normal file
53
src/controls/controller_actions.h
Normal file
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -2,6 +2,7 @@
|
|||
#define __FONT_FONT_H__
|
||||
|
||||
#include <ultra64.h>
|
||||
#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
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
1
src/menu/controls.c
Normal file
1
src/menu/controls.c
Normal file
|
@ -0,0 +1 @@
|
|||
#include "controls.h"
|
8
src/menu/controls.h
Normal file
8
src/menu/controls.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef __MENU_CONTROLS_H__
|
||||
#define __MENU_CONTROLS_H__
|
||||
|
||||
struct ControlsMenu {
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -24,7 +24,7 @@ void mainMenuInit(struct MainMenu* mainMenu) {
|
|||
newGameInit(&mainMenu->newGameMenu);
|
||||
optionsMenuInit(&mainMenu->optionsMenu);
|
||||
|
||||
mainMenu->state = MainMenuStateLanding;
|
||||
mainMenu->state = MainMenuStateOptions;
|
||||
|
||||
mainMenuReadCamera(mainMenu);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
}
|
|
@ -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);
|
||||
|
|
105
src/menu/tabs.c
Normal file
105
src/menu/tabs.c
Normal file
|
@ -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;
|
||||
}
|
34
src/menu/tabs.h
Normal file
34
src/menu/tabs.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
#ifndef __MENU_TABS_H__
|
||||
#define __MENU_TABS_H__
|
||||
|
||||
#include <ultra64.h>
|
||||
#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
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue