Start migrating audio options to use a menu builder
This commit is contained in:
parent
12a236de5c
commit
9ec21b9c1a
2
Makefile
2
Makefile
|
@ -232,7 +232,7 @@ build/assets/materials/hud.h build/assets/materials/hud_mat.c: assets/materials/
|
|||
|
||||
src/levels/level_def_gen.h: build/assets/materials/static.h
|
||||
|
||||
build/src/scene/hud.o: build/assets/materials/hud.h
|
||||
build/src/scene/hud.o: build/assets/materials/hud.h build/src/audio/subtitles.h
|
||||
|
||||
build/src/scene/elevator.o: build/assets/models/props/round_elevator_collision.h \
|
||||
build/assets/models/props/round_elevator.h \
|
||||
|
|
|
@ -84,8 +84,6 @@ void audioOptionsHandleSlider(short selectedItem, unsigned short* settingValue,
|
|||
}
|
||||
|
||||
void audioOptionsRenderText(struct AudioOptions* audioOptions) {
|
||||
audioOptions->gameVolumeText = menuBuildPrerenderedText(&gDejaVuSansFont, translationsGet(GAMEUI_SOUNDEFFECTVOLUME), GAMEPLAY_X + 8, GAMEPLAY_Y + 8);
|
||||
audioOptions->musicVolumeText = menuBuildPrerenderedText(&gDejaVuSansFont, translationsGet(GAMEUI_MUSICVOLUME), GAMEPLAY_X + 8, GAMEPLAY_Y + 28);
|
||||
audioOptions->subtitlesEnabled.prerenderedText = menuBuildPrerenderedText(
|
||||
&gDejaVuSansFont,
|
||||
translationsGet(GAMEUI_SUBTITLESANDSOUNDEFFECTS),
|
||||
|
@ -104,16 +102,85 @@ void audioOptionsRenderText(struct AudioOptions* audioOptions) {
|
|||
audioOptions->audioLanguageDynamicText = menuBuildPrerenderedText(&gDejaVuSansFont, AudioLanguages[gSaveData.audio.audioLanguage], GAMEPLAY_X + 125, GAMEPLAY_Y + 124);
|
||||
}
|
||||
|
||||
struct MenuElementParams gAudioMenuParams[] = {
|
||||
{
|
||||
.type = MenuElementTypeText,
|
||||
.x = GAMEPLAY_X + 8,
|
||||
.y = GAMEPLAY_Y + 8,
|
||||
.params = {
|
||||
.text = {
|
||||
.font = &gDejaVuSansFont,
|
||||
.messageId = GAMEUI_SOUNDEFFECTVOLUME,
|
||||
},
|
||||
},
|
||||
.selectionIndex = AudioOptionGameVolume,
|
||||
},
|
||||
{
|
||||
.type = MenuElementTypeSlider,
|
||||
.x = GAMEPLAY_X + 120,
|
||||
.y = GAMEPLAY_Y + 8,
|
||||
.params = {
|
||||
.slider = {
|
||||
.width = 120,
|
||||
.numberOfTicks = 9,
|
||||
.discrete = 0,
|
||||
},
|
||||
},
|
||||
.selectionIndex = AudioOptionGameVolume,
|
||||
},
|
||||
{
|
||||
.type = MenuElementTypeText,
|
||||
.x = GAMEPLAY_X + 8,
|
||||
.y = GAMEPLAY_Y + 28,
|
||||
.params = {
|
||||
.text = {
|
||||
.font = &gDejaVuSansFont,
|
||||
.messageId = GAMEUI_MUSICVOLUME,
|
||||
},
|
||||
},
|
||||
.selectionIndex = AudioOptionMusicVolume,
|
||||
},
|
||||
{
|
||||
.type = MenuElementTypeSlider,
|
||||
.x = GAMEPLAY_X + 120,
|
||||
.y = GAMEPLAY_Y + 28,
|
||||
.params = {
|
||||
.slider = {
|
||||
.width = 120,
|
||||
.numberOfTicks = 9,
|
||||
.discrete = 0,
|
||||
},
|
||||
},
|
||||
.selectionIndex = AudioOptionMusicVolume,
|
||||
},
|
||||
};
|
||||
|
||||
void audioOptionsActoin(void* data, int selection, struct MenuAction* action) {
|
||||
switch (selection) {
|
||||
case AudioOptionGameVolume:
|
||||
gSaveData.audio.soundVolume = (int)(0xFFFF * action->state.fSlider.value);
|
||||
soundPlayerGameVolumeUpdate();
|
||||
break;
|
||||
case AudioOptionMusicVolume:
|
||||
gSaveData.audio.musicVolume = (int)(0xFFFF * action->state.fSlider.value);
|
||||
soundPlayerGameVolumeUpdate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void audioOptionsInit(struct AudioOptions* audioOptions) {
|
||||
menuBuilderInit(
|
||||
&audioOptions->menuBuilder,
|
||||
gAudioMenuParams,
|
||||
sizeof(gAudioMenuParams) / sizeof(*gAudioMenuParams),
|
||||
AudioOptionCount,
|
||||
audioOptionsActoin,
|
||||
audioOptions
|
||||
);
|
||||
|
||||
audioOptions->selectedItem = AudioOptionGameVolume;
|
||||
int temp;
|
||||
|
||||
audioOptions->gameVolume = menuBuildSlider(GAMEPLAY_X + 120, GAMEPLAY_Y + 8, 120, SCROLL_TICKS_VOLUME);
|
||||
audioOptions->gameVolume.value = (float)gSaveData.audio.soundVolume/0xFFFF;
|
||||
|
||||
audioOptions->musicVolume = menuBuildSlider(GAMEPLAY_X + 120, GAMEPLAY_Y + 28, 120, SCROLL_TICKS_VOLUME);
|
||||
audioOptions->musicVolume.value = (float)gSaveData.audio.musicVolume/0xFFFF;
|
||||
|
||||
audioOptions->subtitlesEnabled = menuBuildCheckbox(&gDejaVuSansFont, translationsGet(GAMEUI_SUBTITLESANDSOUNDEFFECTS), GAMEPLAY_X + 8, GAMEPLAY_Y + 48, 1);
|
||||
audioOptions->subtitlesEnabled.checked = (gSaveData.controls.flags & ControlSaveSubtitlesEnabled) != 0;
|
||||
|
||||
|
@ -139,8 +206,6 @@ void audioOptionsInit(struct AudioOptions* audioOptions) {
|
|||
}
|
||||
|
||||
void audioOptionsRebuildtext(struct AudioOptions* audioOptions) {
|
||||
prerenderedTextFree(audioOptions->gameVolumeText);
|
||||
prerenderedTextFree(audioOptions->musicVolumeText);
|
||||
prerenderedTextFree(audioOptions->subtitlesEnabled.prerenderedText);
|
||||
prerenderedTextFree(audioOptions->allSubtitlesEnabled.prerenderedText);
|
||||
prerenderedTextFree(audioOptions->subtitlesLanguageText);
|
||||
|
@ -149,6 +214,8 @@ void audioOptionsRebuildtext(struct AudioOptions* audioOptions) {
|
|||
prerenderedTextFree(audioOptions->audioLanguageDynamicText);
|
||||
|
||||
audioOptionsRenderText(audioOptions);
|
||||
|
||||
menuBuilderRebuildText(&audioOptions->menuBuilder);
|
||||
}
|
||||
|
||||
enum MenuDirection audioOptionsUpdate(struct AudioOptions* audioOptions) {
|
||||
|
@ -177,14 +244,6 @@ enum MenuDirection audioOptionsUpdate(struct AudioOptions* audioOptions) {
|
|||
}
|
||||
|
||||
switch (audioOptions->selectedItem) {
|
||||
case AudioOptionGameVolume:
|
||||
audioOptionsHandleSlider(audioOptions->selectedItem, &gSaveData.audio.soundVolume, &audioOptions->gameVolume.value);
|
||||
soundPlayerGameVolumeUpdate();
|
||||
break;
|
||||
case AudioOptionMusicVolume:
|
||||
audioOptionsHandleSlider(audioOptions->selectedItem, &gSaveData.audio.musicVolume, &audioOptions->musicVolume.value);
|
||||
soundPlayerGameVolumeUpdate();
|
||||
break;
|
||||
case AudioOptionSubtitlesEnabled:
|
||||
if (controllerGetButtonDown(0, A_BUTTON)) {
|
||||
audioOptions->subtitlesEnabled.checked = !audioOptions->subtitlesEnabled.checked;
|
||||
|
@ -258,12 +317,6 @@ enum MenuDirection audioOptionsUpdate(struct AudioOptions* audioOptions) {
|
|||
void audioOptionsRender(struct AudioOptions* audioOptions, struct RenderState* renderState, struct GraphicsTask* task) {
|
||||
gSPDisplayList(renderState->dl++, ui_material_list[SOLID_ENV_INDEX]);
|
||||
|
||||
gSPDisplayList(renderState->dl++, audioOptions->gameVolume.back);
|
||||
renderState->dl = menuSliderRender(&audioOptions->gameVolume, renderState->dl);
|
||||
|
||||
gSPDisplayList(renderState->dl++, audioOptions->musicVolume.back);
|
||||
renderState->dl = menuSliderRender(&audioOptions->musicVolume, renderState->dl);
|
||||
|
||||
gSPDisplayList(renderState->dl++, audioOptions->subtitlesEnabled.outline);
|
||||
renderState->dl = menuCheckboxRender(&audioOptions->subtitlesEnabled, renderState->dl);
|
||||
|
||||
|
@ -280,8 +333,6 @@ void audioOptionsRender(struct AudioOptions* audioOptions, struct RenderState* r
|
|||
|
||||
struct PrerenderedTextBatch* batch = prerenderedBatchStart();
|
||||
|
||||
prerenderedBatchAdd(batch, audioOptions->gameVolumeText, audioOptions->selectedItem == AudioOptionGameVolume ? &gSelectionGray : &gColorWhite);
|
||||
prerenderedBatchAdd(batch, audioOptions->musicVolumeText, audioOptions->selectedItem == AudioOptionMusicVolume ? &gSelectionGray : &gColorWhite);
|
||||
prerenderedBatchAdd(batch, audioOptions->subtitlesEnabled.prerenderedText, audioOptions->selectedItem == AudioOptionSubtitlesEnabled ? &gSelectionGray : &gColorWhite);
|
||||
prerenderedBatchAdd(batch, audioOptions->allSubtitlesEnabled.prerenderedText, audioOptions->selectedItem == AudioOptionAllSubtitlesEnabled ? &gSelectionGray : &gColorWhite);
|
||||
prerenderedBatchAdd(batch, audioOptions->subtitlesLanguageText, audioOptions->selectedItem == AudioOptionSubtitlesLanguage ? &gSelectionGray : &gColorWhite);
|
||||
|
@ -292,4 +343,6 @@ void audioOptionsRender(struct AudioOptions* audioOptions, struct RenderState* r
|
|||
renderState->dl = prerenderedBatchFinish(batch, gDejaVuSansImages, renderState->dl);
|
||||
|
||||
gSPDisplayList(renderState->dl++, ui_material_revert_list[DEJAVU_SANS_0_INDEX]);
|
||||
|
||||
menuBuilderRender(&audioOptions->menuBuilder, renderState);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "./menu.h"
|
||||
#include "../graphics/graphics.h"
|
||||
#include "menu_builder.h"
|
||||
|
||||
enum AudioOption {
|
||||
AudioOptionGameVolume,
|
||||
|
@ -15,13 +16,11 @@ enum AudioOption {
|
|||
};
|
||||
|
||||
struct AudioOptions {
|
||||
struct MenuSlider gameVolume;
|
||||
struct MenuSlider musicVolume;
|
||||
struct MenuBuilder menuBuilder;
|
||||
|
||||
struct MenuCheckbox subtitlesEnabled;
|
||||
struct MenuCheckbox allSubtitlesEnabled;
|
||||
struct MenuSlider subtitlesLanguage;
|
||||
struct PrerenderedText* gameVolumeText;
|
||||
struct PrerenderedText* musicVolumeText;
|
||||
struct PrerenderedText* subtitlesLanguageText;
|
||||
struct PrerenderedText* subtitlesLanguageDynamicText;
|
||||
unsigned short subtitles_language_temp;
|
||||
|
|
263
src/menu/menu_builder.c
Normal file
263
src/menu/menu_builder.c
Normal file
|
@ -0,0 +1,263 @@
|
|||
#include "menu_builder.h"
|
||||
|
||||
#include "../util/memory.h"
|
||||
#include "../controls/controller.h"
|
||||
#include "./translations.h"
|
||||
#include "../audio/soundplayer.h"
|
||||
#include "../util/time.h"
|
||||
#include "../math/mathf.h"
|
||||
|
||||
#include "../font/dejavusans.h"
|
||||
#include "../build/assets/materials/ui.h"
|
||||
#include "../build/src/audio/clips.h"
|
||||
|
||||
void textMenuItemInit(struct MenuBuilderElement* element) {
|
||||
element->data = menuBuildPrerenderedText(
|
||||
element->params->params.text.font,
|
||||
translationsGet(element->params->params.text.messageId),
|
||||
element->params->x,
|
||||
element->params->y
|
||||
);
|
||||
}
|
||||
|
||||
void textMenuItemRebuildText(struct MenuBuilderElement* element) {
|
||||
prerenderedTextFree(element->data);
|
||||
textMenuItemInit(element);
|
||||
}
|
||||
|
||||
void textMenuItemRender(struct MenuBuilderElement* element, int selection, int materialIndex, struct PrerenderedTextBatch* textBatch, struct RenderState* renderState) {
|
||||
if (textBatch) {
|
||||
prerenderedBatchAdd(textBatch, element->data, selection == element->selectionIndex ? &gSelectionGray : &gColorWhite);
|
||||
}
|
||||
}
|
||||
|
||||
void checkboxMenuItemInit(struct MenuBuilderElement* element) {
|
||||
struct MenuCheckbox* checkbox = malloc(sizeof(struct MenuCheckbox));
|
||||
*checkbox = menuBuildCheckbox(
|
||||
element->params->params.checkbox.font,
|
||||
translationsGet(element->params->params.checkbox.messageId),
|
||||
element->params->x,
|
||||
element->params->y,
|
||||
1
|
||||
);
|
||||
element->data = checkbox;
|
||||
}
|
||||
|
||||
enum MenuDirection checkboxMenuItemUpdate(struct MenuBuilderElement* element, MenuActionCalback actionCallback, void* data) {
|
||||
if (controllerGetButtonDown(0, A_BUTTON)) {
|
||||
struct MenuCheckbox* checkbox = (struct MenuCheckbox*)element->data;
|
||||
|
||||
checkbox->checked = !checkbox->checked;
|
||||
|
||||
struct MenuAction action;
|
||||
action.type = MenuElementTypeCheckbox;
|
||||
action.state.checkbox.isChecked = checkbox->checked;
|
||||
actionCallback(data, element->selectionIndex, &action);
|
||||
}
|
||||
|
||||
return MenuDirectionStay;
|
||||
}
|
||||
|
||||
void checkboxMenuItemRebuildText(struct MenuBuilderElement* element) {
|
||||
struct MenuCheckbox* checkbox = (struct MenuCheckbox*)element->data;
|
||||
|
||||
prerenderedTextFree(checkbox->prerenderedText);
|
||||
checkbox->prerenderedText = menuBuildPrerenderedText(
|
||||
element->params->params.checkbox.font,
|
||||
translationsGet(element->params->params.checkbox.messageId),
|
||||
element->params->x + CHECKBOX_SIZE + 6,
|
||||
element->params->y
|
||||
);
|
||||
}
|
||||
|
||||
void checkboxMenuItemRender(struct MenuBuilderElement* element, int selection, int materialIndex, struct PrerenderedTextBatch* textBatch, struct RenderState* renderState) {
|
||||
struct MenuCheckbox* checkbox = (struct MenuCheckbox*)element->data;
|
||||
|
||||
if (materialIndex == SOLID_ENV_INDEX) {
|
||||
gSPDisplayList(renderState->dl++, checkbox->outline);
|
||||
renderState->dl = menuCheckboxRender(checkbox, renderState->dl);
|
||||
} else if (textBatch) {
|
||||
prerenderedBatchAdd(textBatch, checkbox->prerenderedText, selection == element->selectionIndex ? &gSelectionGray : &gColorWhite);
|
||||
}
|
||||
}
|
||||
|
||||
void sliderMenuItemInit(struct MenuBuilderElement* element) {
|
||||
struct MenuSlider* slider = malloc(sizeof(struct MenuSlider));
|
||||
|
||||
short steps = element->params->params.slider.numberOfTicks;
|
||||
|
||||
if (steps == 0) {
|
||||
steps = 9;
|
||||
}
|
||||
|
||||
*slider = menuBuildSlider(
|
||||
element->params->x,
|
||||
element->params->y,
|
||||
element->params->params.slider.width,
|
||||
steps
|
||||
);
|
||||
element->data = slider;
|
||||
}
|
||||
|
||||
#define FULL_SCROLL_TIME 2.0f
|
||||
#define SCROLL_MULTIPLIER (1.0f * FIXED_DELTA_TIME / (80 * FULL_SCROLL_TIME))
|
||||
|
||||
enum MenuDirection sliderMenuItemUpdate(struct MenuBuilderElement* element, MenuActionCalback actionCallback, void* data) {
|
||||
struct MenuSlider* slider = (struct MenuSlider*)element->data;
|
||||
|
||||
if (element->params->params.slider.discrete) {
|
||||
int controllerDir = controllerGetDirectionDown(0);
|
||||
|
||||
int numTicks = element->params->params.slider.numberOfTicks;
|
||||
int currentValue = (int)floorf(slider->value * numTicks);
|
||||
int newValue = currentValue;
|
||||
|
||||
if (controllerDir & ControllerDirectionRight) {
|
||||
++numTicks;
|
||||
} else if (controllerDir & ControllerDirectionLeft) {
|
||||
--numTicks;
|
||||
}
|
||||
|
||||
if (newValue < 0) {
|
||||
newValue = 0;
|
||||
} else if (newValue >= numTicks) {
|
||||
newValue = numTicks - 1;
|
||||
}
|
||||
|
||||
if (newValue != currentValue) {
|
||||
struct MenuAction action;
|
||||
action.type = MenuElementTypeSlider;
|
||||
action.state.iSlider.value = newValue;
|
||||
actionCallback(data, element->selectionIndex, &action);
|
||||
slider->value = newValue;
|
||||
}
|
||||
|
||||
slider->value = (float)newValue / (float)numTicks;
|
||||
} else {
|
||||
OSContPad* pad = controllersGetControllerData(0);
|
||||
float newValue = slider->value + pad->stick_x * SCROLL_MULTIPLIER;
|
||||
|
||||
if (newValue > 1.0f) {
|
||||
newValue = 1.0f;
|
||||
} else if (newValue < 0.0f) {
|
||||
newValue = 0.0f;
|
||||
}
|
||||
|
||||
if (newValue != slider->value) {
|
||||
struct MenuAction action;
|
||||
action.type = MenuElementTypeSlider;
|
||||
action.state.fSlider.value = newValue;
|
||||
actionCallback(data, element->selectionIndex, &action);
|
||||
slider->value = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
return MenuDirectionStay;
|
||||
}
|
||||
|
||||
void sliderMenuItemRender(struct MenuBuilderElement* element, int selection, int materialIndex, struct PrerenderedTextBatch* textBatch, struct RenderState* renderState) {
|
||||
struct MenuSlider* slider = (struct MenuSlider*)element->data;
|
||||
gSPDisplayList(renderState->dl++, slider->back);
|
||||
renderState->dl = menuSliderRender(slider, renderState->dl);
|
||||
}
|
||||
|
||||
struct MenuBuilderCallbacks gMenuTypeCallbacks[] = {
|
||||
{textMenuItemInit, NULL, textMenuItemRebuildText, textMenuItemRender},
|
||||
{checkboxMenuItemInit, checkboxMenuItemUpdate, checkboxMenuItemRebuildText, checkboxMenuItemRender},
|
||||
{sliderMenuItemInit, sliderMenuItemUpdate, NULL, sliderMenuItemRender},
|
||||
};
|
||||
|
||||
void menuBuilderInit(
|
||||
struct MenuBuilder* menuBuilder,
|
||||
struct MenuElementParams* params,
|
||||
int elementCount,
|
||||
int maxSelection,
|
||||
MenuActionCalback actionCallback,
|
||||
void* data
|
||||
) {
|
||||
menuBuilder->elements = malloc(sizeof(struct MenuBuilderElement) * elementCount);
|
||||
menuBuilder->elementCount = elementCount;
|
||||
menuBuilder->selection = 0;
|
||||
menuBuilder->maxSelection = maxSelection;
|
||||
menuBuilder->actionCallback = actionCallback;
|
||||
menuBuilder->data = data;
|
||||
|
||||
for (int i = 0; i < elementCount; ++i) {
|
||||
menuBuilder->elements[i].data = NULL;
|
||||
menuBuilder->elements[i].selectionIndex = params[i].selectionIndex;
|
||||
menuBuilder->elements[i].callbacks = &gMenuTypeCallbacks[params[i].type];
|
||||
menuBuilder->elements[i].params = ¶ms[i];
|
||||
menuBuilder->elements[i].callbacks->init(&menuBuilder->elements[i]);
|
||||
}
|
||||
}
|
||||
|
||||
enum MenuDirection menuBuilderUpdate(struct MenuBuilder* menuBuilder) {
|
||||
if (controllerGetButtonDown(0, B_BUTTON)) {
|
||||
return MenuDirectionUp;
|
||||
}
|
||||
|
||||
int controllerDir = controllerGetDirectionDown(0);
|
||||
|
||||
if (controllerDir & ControllerDirectionDown) {
|
||||
++menuBuilder->selection;
|
||||
|
||||
if (menuBuilder->selection == menuBuilder->maxSelection) {
|
||||
menuBuilder->selection = 0;
|
||||
}
|
||||
soundPlayerPlay(SOUNDS_BUTTONROLLOVER, 1.0f, 0.5f, NULL, NULL, SoundTypeAll);
|
||||
}
|
||||
|
||||
if (controllerDir & ControllerDirectionUp) {
|
||||
if (menuBuilder->selection == 0) {
|
||||
menuBuilder->selection = menuBuilder->maxSelection - 1;
|
||||
} else {
|
||||
--menuBuilder->selection;
|
||||
}
|
||||
soundPlayerPlay(SOUNDS_BUTTONROLLOVER, 1.0f, 0.5f, NULL, NULL, SoundTypeAll);
|
||||
}
|
||||
|
||||
for (int i = 0; i < menuBuilder->elementCount; ++i) {
|
||||
struct MenuBuilderElement* element = &menuBuilder->elements[i];
|
||||
|
||||
if (element->callbacks->update && element->selectionIndex == menuBuilder->selection) {
|
||||
enum MenuDirection direction = element->callbacks->update(element, menuBuilder->actionCallback, menuBuilder->data);
|
||||
|
||||
if (direction != MenuDirectionStay) {
|
||||
return direction;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (controllerGetButtonDown(0, L_TRIG) || controllerGetButtonDown(0, Z_TRIG)) {
|
||||
return MenuDirectionLeft;
|
||||
}
|
||||
if (controllerGetButtonDown(0, R_TRIG)) {
|
||||
return MenuDirectionRight;
|
||||
}
|
||||
|
||||
return MenuDirectionStay;
|
||||
}
|
||||
|
||||
void menuBuilderRebuildText(struct MenuBuilder* menuBuilder) {
|
||||
for (int i = 0; i < menuBuilder->elementCount; ++i) {
|
||||
if (menuBuilder->elements[i].callbacks->rebuildText) {
|
||||
menuBuilder->elements[i].callbacks->rebuildText(&menuBuilder->elements[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void menuBuilderRender(struct MenuBuilder* menuBuilder, struct RenderState* renderState) {
|
||||
gSPDisplayList(renderState->dl++, ui_material_list[SOLID_ENV_INDEX]);
|
||||
for (int i = 0; i < menuBuilder->elementCount; ++i) {
|
||||
menuBuilder->elements[i].callbacks->render(&menuBuilder->elements[i], menuBuilder->selection, SOLID_ENV_INDEX, NULL, renderState);
|
||||
}
|
||||
gSPDisplayList(renderState->dl++, ui_material_revert_list[SOLID_ENV_INDEX]);
|
||||
|
||||
|
||||
struct PrerenderedTextBatch* batch = prerenderedBatchStart();
|
||||
for (int i = 0; i < menuBuilder->elementCount; ++i) {
|
||||
menuBuilder->elements[i].callbacks->render(&menuBuilder->elements[i], menuBuilder->selection, -1, batch, renderState);
|
||||
}
|
||||
renderState->dl = prerenderedBatchFinish(batch, gDejaVuSansImages, renderState->dl);
|
||||
gSPDisplayList(renderState->dl++, ui_material_revert_list[DEJAVU_SANS_0_INDEX]);
|
||||
}
|
102
src/menu/menu_builder.h
Normal file
102
src/menu/menu_builder.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
#ifndef __MENU_MENU_BUILDER_H__
|
||||
#define __MENU_MENU_BUILDER_H__
|
||||
|
||||
#include "../font/font.h"
|
||||
#include "./menu.h"
|
||||
#include "../graphics/renderstate.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
struct MenuBuilderElement;
|
||||
struct MenuElementParams;
|
||||
|
||||
enum MenuElementType {
|
||||
MenuElementTypeText,
|
||||
MenuElementTypeCheckbox,
|
||||
MenuElementTypeSlider,
|
||||
};
|
||||
|
||||
struct MenuAction {
|
||||
enum MenuElementType type;
|
||||
union
|
||||
{
|
||||
struct {
|
||||
unsigned char isChecked;
|
||||
} checkbox;
|
||||
struct {
|
||||
float value;
|
||||
} fSlider;
|
||||
struct {
|
||||
short value;
|
||||
} iSlider;
|
||||
} state;
|
||||
};
|
||||
|
||||
typedef void (*MenuActionCalback)(void* data, int selection, struct MenuAction* action);
|
||||
|
||||
typedef void (*MenuItemInit)(struct MenuBuilderElement* element);
|
||||
typedef enum MenuDirection (*MenuItemUpdate)(struct MenuBuilderElement* element, MenuActionCalback actionCallback, void* data);
|
||||
typedef void (*MenuItemRebuildText)(struct MenuBuilderElement* element);
|
||||
typedef void (*MenuItemRender)(struct MenuBuilderElement* element, int selection, int materialIndex, struct PrerenderedTextBatch* textBatch, struct RenderState* renderState);
|
||||
|
||||
struct MenuBuilderCallbacks {
|
||||
MenuItemInit init;
|
||||
MenuItemUpdate update;
|
||||
MenuItemRebuildText rebuildText;
|
||||
MenuItemRender render;
|
||||
};
|
||||
|
||||
struct MenuElementParams {
|
||||
enum MenuElementType type;
|
||||
short x;
|
||||
short y;
|
||||
union
|
||||
{
|
||||
struct {
|
||||
struct Font* font;
|
||||
short messageId;
|
||||
} text;
|
||||
struct {
|
||||
struct Font* font;
|
||||
short messageId;
|
||||
} checkbox;
|
||||
struct {
|
||||
struct Font* font;
|
||||
short messageId;
|
||||
short width;
|
||||
short numberOfTicks;
|
||||
short discrete;
|
||||
} slider;
|
||||
} params;
|
||||
short selectionIndex;
|
||||
};
|
||||
|
||||
struct MenuBuilderElement {
|
||||
void* data;
|
||||
struct MenuBuilderCallbacks* callbacks;
|
||||
struct MenuElementParams* params;
|
||||
short selectionIndex;
|
||||
};
|
||||
|
||||
struct MenuBuilder {
|
||||
struct MenuBuilderElement* elements;
|
||||
MenuActionCalback actionCallback;
|
||||
void* data;
|
||||
short elementCount;
|
||||
short selection;
|
||||
short maxSelection;
|
||||
};
|
||||
|
||||
void menuBuilderInit(
|
||||
struct MenuBuilder* menuBuilder,
|
||||
struct MenuElementParams* params,
|
||||
int elementCount,
|
||||
int maxSelection,
|
||||
MenuActionCalback actionCallback,
|
||||
void* data
|
||||
);
|
||||
enum MenuDirection menuBuilderUpdate(struct MenuBuilder* menuBuilder);
|
||||
void menuBuilderRebuildText(struct MenuBuilder* menuBuilder);
|
||||
void menuBuilderRender(struct MenuBuilder* menuBuilder, struct RenderState* renderState);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue