232 lines
6.3 KiB
C
232 lines
6.3 KiB
C
#include <sparrow3d.h>
|
|
#include <string.h>
|
|
#include "button.h"
|
|
#include "menu.h"
|
|
|
|
// ============================================================================
|
|
// INIT
|
|
// ============================================================================
|
|
// init a menu with the given title text.
|
|
void
|
|
initMenu
|
|
( struct eMenu* menu, char title[512],
|
|
spFontPointer* titleFont, spFontPointer* elementFont,
|
|
int menuBackgroundColor, int selectBackgroundColor )
|
|
{
|
|
strcpy(menu->title, title);
|
|
|
|
menu->width = 0;
|
|
menu->height = 0;
|
|
menu->surface = NULL;
|
|
|
|
menu->font = titleFont;
|
|
menu->elementFont = elementFont;
|
|
menu->titleCentered = 1;
|
|
menu->textCentered = 1;
|
|
|
|
menu->selection = 0;
|
|
menu->elementCount = 0;
|
|
|
|
menu->inputDelayStep = 100;
|
|
menu->inputCutoffStep = -1;
|
|
menu->inputImmediate = 1;
|
|
menu->inputDisable = 0;
|
|
menu->inputReset = 1;
|
|
|
|
menu->menuBgColor = menuBackgroundColor;
|
|
menu->selectBgColor = selectBackgroundColor;
|
|
|
|
menu->moveSound = NULL;
|
|
menu->selectSound = NULL;
|
|
menu->soundChannel = 0;
|
|
}
|
|
|
|
// init the given eMenuElement with the given text in an eMenu.
|
|
void
|
|
initMenuElement
|
|
( struct eMenu* menu, struct eMenuElement* element, char text[512] )
|
|
{
|
|
int count = menu->elementCount;
|
|
|
|
strcpy(element->text, text);
|
|
element->parentMenu = menu;
|
|
element->index = count;
|
|
menu->elements[count] = element;
|
|
menu->elementCount = menu->elementCount + 1;
|
|
}
|
|
|
|
// create a new eMenuElement with given text, and append to eMenu.
|
|
void
|
|
addMenuElement
|
|
( struct eMenu* menu, char text[512] )
|
|
{
|
|
struct eMenuElement* element = malloc(sizeof(struct eMenuElement));
|
|
initMenuElement( menu, element, text );
|
|
}
|
|
|
|
// -------------------------------------------------------------------
|
|
// resize a menu (executed by resize loop)
|
|
void
|
|
resizeMenu ( struct eMenu* menu )
|
|
{
|
|
if ( menu->height == 0 )
|
|
menu->height = idealMenuHeight(menu);
|
|
if ( menu->width == 0 )
|
|
menu->width = idealMenuWidth(menu);
|
|
|
|
menu->scaleFactor = spFixedToInt(spGetSizeFactor());
|
|
int height = menu->height * menu->scaleFactor;
|
|
int width = menu->width * menu->scaleFactor;
|
|
|
|
|
|
if ( menu->surface != NULL )
|
|
spDeleteSurface( menu->surface );
|
|
|
|
menu->surface = spCreateSurface(width, height);
|
|
}
|
|
|
|
|
|
// ============================================================================
|
|
// DRAW
|
|
// ============================================================================
|
|
// draw an eMenu on it's surface.
|
|
void
|
|
drawMenu ( struct eMenu* menu )
|
|
{
|
|
SDL_Surface* old_surface = spGetRenderTarget( );
|
|
spSelectRenderTarget( menu->surface );
|
|
|
|
spClearTarget( menu->menuBgColor );
|
|
if ( menu->textCentered == 0 )
|
|
spFontDrawMiddle( menu->width / 2 * menu->scaleFactor,0,0,
|
|
menu->title, *(menu->font) );
|
|
else
|
|
spFontDraw( 0,0,0, menu->title, *(menu->font) );
|
|
|
|
for ( int i=0; i < menu->elementCount; i++ ) {
|
|
drawMenuElement( menu->elements[i]);
|
|
}
|
|
|
|
spSelectRenderTarget( old_surface );
|
|
}
|
|
|
|
// draw an eMenuElement on current target surface
|
|
void
|
|
drawMenuElement ( struct eMenuElement* element )
|
|
{
|
|
struct eMenu* parent = element->parentMenu;
|
|
int index = element->index;
|
|
int selection = parent->selection;
|
|
|
|
spFontPointer font = *(parent->elementFont);
|
|
int fontHeight = font->maxheight;
|
|
|
|
if ( index == selection ) {
|
|
index++;
|
|
spRectangle( 0,(index * fontHeight) + (fontHeight * .6),0,
|
|
parent->width * parent->scaleFactor * 2,
|
|
fontHeight,
|
|
parent->selectBgColor );
|
|
}
|
|
else index++;
|
|
|
|
if ( parent->textCentered == 0 )
|
|
spFontDrawMiddle( parent->width / 2 * parent->scaleFactor,
|
|
index * fontHeight,0,
|
|
element->text, *(parent->elementFont));
|
|
else
|
|
spFontDraw( 20,index * fontHeight,0,
|
|
element->text, *(parent->elementFont));
|
|
}
|
|
|
|
|
|
// ============================================================================
|
|
// INPUT
|
|
// ============================================================================
|
|
// calc the input for the given menu.
|
|
// returns -1 if no menu-related buttons were pressed,
|
|
// 0 if not buttons were pressed,
|
|
// otherwise return the item selected + 1.
|
|
int
|
|
calcMenu ( struct eMenu* menu, int sp_select_button, Uint32 steps )
|
|
{
|
|
if ( getButton( sp_select_button, steps ) )
|
|
return menuSelect( menu, steps );
|
|
else if ( getButtonLim( SP_BUTTON_UP, steps,
|
|
menu->inputDelayStep,menu->inputCutoffStep, menu->inputImmediate,
|
|
menu->inputDisable, menu->inputReset ) )
|
|
menuSelectUp( menu, steps );
|
|
else if ( getButtonLim( SP_BUTTON_DOWN, steps,
|
|
menu->inputDelayStep,menu->inputCutoffStep, menu->inputImmediate,
|
|
menu->inputDisable, menu->inputReset ) )
|
|
menuSelectDown( menu, steps );
|
|
else
|
|
return CALCMENU_NOINPUT;
|
|
return CALCMENU_MOVED;
|
|
}
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// returns selected menu item, and plays proper sound
|
|
int
|
|
menuSelect ( struct eMenu* menu, Uint32 steps )
|
|
{
|
|
if ( menu->moveSound != NULL )
|
|
spSoundPlay( menu->selectSound, menu->soundChannel,0,0,-1 );
|
|
return menu->selection + 1;
|
|
}
|
|
|
|
// move an eMenu's selected element up by one (if possible)
|
|
void
|
|
menuSelectUp ( struct eMenu* menu, Uint32 steps )
|
|
{
|
|
if ( 0 < menu->selection ) {
|
|
menu->selection -= 1;
|
|
if ( menu->moveSound != NULL )
|
|
spSoundPlay(menu->moveSound, menu->soundChannel,0,0,-1);
|
|
}
|
|
}
|
|
|
|
// move an eMenu's selected element down by one (if possible)
|
|
void
|
|
menuSelectDown ( struct eMenu* menu, Uint32 steps )
|
|
{
|
|
if ( (menu->elementCount - 1) > menu->selection ) {
|
|
menu->selection += 1;
|
|
if ( menu->moveSound != NULL )
|
|
spSoundPlay(menu->moveSound, menu->soundChannel,0,0,-1);
|
|
}
|
|
}
|
|
|
|
|
|
// ============================================================================
|
|
// UTIL
|
|
// ============================================================================
|
|
// return menu's ideal (smallest while displaying everything) calculated height
|
|
int
|
|
idealMenuHeight ( struct eMenu* menu )
|
|
{
|
|
spFontPointer font = *(menu->font);
|
|
spFontPointer elementFont = *(menu->elementFont);
|
|
int titleHeight = font->maxheight;
|
|
int elementHeight = elementFont->maxheight + 2;
|
|
|
|
return titleHeight + (elementHeight * menu->elementCount);
|
|
}
|
|
|
|
// return menu's ideal (smallest while displaying everything) calculated width
|
|
int
|
|
idealMenuWidth ( struct eMenu* menu )
|
|
{
|
|
struct eMenuElement* element;
|
|
int top_len = spFontWidth( menu->title, *(menu->font) );
|
|
|
|
for ( int i = 0; i < menu->elementCount; i++ ) {
|
|
element = menu->elements[i];
|
|
int len = spFontWidth( element->text, *(menu->elementFont));
|
|
if ( len > top_len )
|
|
top_len = len;
|
|
}
|
|
return top_len;
|
|
}
|