new GUI classes

This commit is contained in:
dborth 2009-04-07 02:57:49 +00:00
parent b2079db222
commit 390f90fec7
83 changed files with 3385 additions and 19324 deletions

Binary file not shown.

View File

@ -1,15 +1,35 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
/*!\mainpage libwiigui Documentation
*
* Tantric February 2009
* \section Introduction
* libwiigui is a GUI library for the Wii, created to help structure the
* design of a complicated GUI interface, and to enable an author to create
* a sophisticated, feature-rich GUI. It was originally conceived and written
* after I started to design a GUI for Snes9x GX, and found libwiisprite and
* GRRLIB inadequate for the purpose. It uses GX for drawing, and makes use
* of PNGU for displaying images and FreeTypeGX for text. It was designed to
* be flexible and is easy to modify - don't be afraid to change the way it
* works or expand it to suit your GUI's purposes! If you do, and you think
* your changes might benefit others, please share them so they might be
* added to the project!
*
* gui.h
*
* GUI class definitions
***************************************************************************/
* \section Quickstart
* Start from the supplied template example. For more advanced uses, see the
* source code for Snes9x GX, FCE Ultra GX, and Visual Boy Advance GX.
#ifndef GUI_H
#define GUI_H
* \section Contact
* If you have any suggestions for the library or documentation, or want to
* contribute, please visit the libwiigui website:
* http://code.google.com/p/libwiigui/
* \section Credits
* This library was wholly designed and written by Tantric. Thanks to the
* authors of PNGU and FreeTypeGX, of which this library makes use. Thanks
* also to the authors of GRRLIB and libwiisprite for laying the foundations.
*
*/
#ifndef LIBWIIGUI_H
#define LIBWIIGUI_H
#include <gccore.h>
#include <malloc.h>
@ -17,38 +37,26 @@
#include <string.h>
#include <vector>
#include <math.h>
#include <wiiuse/wpad.h>
#include <mp3player.h>
#include <asndlib.h>
#include "pngu/pngu.h"
#include "FreeTypeGX.h"
#include "vba.h"
#include "snes9xGX.h"
#include "video.h"
#include "input.h"
#include "filelist.h"
#include "fileop.h"
#include "menu.h"
#include "input.h"
#include "oggplayer.h"
#define PI 3.14159265f
#define PADCAL 50
#define SCROLL_INITIAL_DELAY 20
#define SCROLL_LOOP_DELAY 3
#define PAGESIZE 8
#define SAVELISTSIZE 6
#define MAX_SAVES 20
#define MAX_OPTIONS 30
typedef void (*UpdateCallback)(void * e);
typedef struct _paddata {
u16 btns_d;
u16 btns_u;
u16 btns_h;
s8 stickX;
s8 stickY;
s8 substickX;
s8 substickY;
u8 triggerL;
u8 triggerR;
} PADData;
enum
{
ALIGN_LEFT,
@ -69,9 +77,15 @@ enum
enum
{
TRIGGER_SIMPLE,
TRIGGER_BUTTON_ONLY,
TRIGGER_BUTTON_ONLY_IN_FOCUS
SOUND_PCM,
SOUND_OGG
};
enum
{
IMAGE_TEXTURE,
IMAGE_COLOR,
IMAGE_DATA
};
#define EFFECT_SLIDE_TOP 1
@ -84,146 +98,696 @@ enum
#define EFFECT_SCALE 128
#define EFFECT_COLOR_TRANSITION 256
enum
{
ON_CLICK,
ON_OVER
};
//!Sound conversion and playback. A wrapper for other sound libraries - ASND, libmad, ltremor, etc
class GuiSound
{
public:
GuiSound(const u8 * s, int l);
//!Constructor
//!\param s Pointer to the sound data
//!\param l Length of sound data
//!\param t Sound format type (SOUND_PCM or SOUND_OGG)
GuiSound(const u8 * s, int l, int t);
//!Destructor
~GuiSound();
//!Start sound playback
void Play();
//!Stop sound playback
void Stop();
//!Pause sound playback
void Pause();
//!Resume sound playback
void Resume();
//!Checks if the sound is currently playing
//!\return true if sound is playing, false otherwise
bool IsPlaying();
//!Set sound volume
//!\param v Sound volume (0-100)
void SetVolume(int v);
//!Set the sound to loop playback (only applies to OGG)
//!\param l Loop (true to loop)
void SetLoop(bool l);
protected:
const u8 * sound;
s32 length;
};
class GuiTrigger
{
public:
GuiTrigger();
~GuiTrigger();
void SetSimpleTrigger(s32 ch, u32 wiibtns, u16 gcbtns);
void SetButtonOnlyTrigger(s32 ch, u32 wiibtns, u16 gcbtns);
void SetButtonOnlyInFocusTrigger(s32 ch, u32 wiibtns, u16 gcbtns);
s8 WPAD_Stick(u8 right, int axis);
bool Left();
bool Right();
bool Up();
bool Down();
u8 type;
s32 chan;
WPADData wpad;
PADData pad;
const u8 * sound; //!< Pointer to the sound data
int type; //!< Sound format type (SOUND_PCM or SOUND_OGG)
s32 length; //!< Length of sound data
s32 voice; //!< Currently assigned ASND voice channel
s32 volume; //!< Sound volume (0-100)
bool loop; //!< Loop sound playback
};
//!Primary Gui class
class GuiElement
{
public:
//!Constructor
GuiElement();
//!Destructor
~GuiElement();
//!Set the element's parent
//!\param e Pointer to parent element
void SetParent(GuiElement * e);
//!Gets the current leftmost coordinate of the element
//!Considers horizontal alignment, x offset, width, and parent element's GetLeft() / GetWidth() values
//!\return left coordinate
int GetLeft();
//!Gets the current topmost coordinate of the element
//!Considers vertical alignment, y offset, height, and parent element's GetTop() / GetHeight() values
//!\return top coordinate
int GetTop();
//!Gets the current width of the element. Does not currently consider the scale
//!\return width
int GetWidth();
//!Gets the height of the element. Does not currently consider the scale
//!\return height
int GetHeight();
//!Sets the size (width/height) of the element
//!\param w Width of element
//!\param h Height of element
void SetSize(int w, int h);
//!Checks whether or not the element is visible
//!\return true if visible, false otherwise
bool IsVisible();
//!Checks whether or not the element is selectable
//!\return true if selectable, false otherwise
bool IsSelectable();
//!Checks whether or not the element is clickable
//!\return true if clickable, false otherwise
bool IsClickable();
//!Sets whether or not the element is selectable
//!\param s Selectable
void SetSelectable(bool s);
//!Sets whether or not the element is clickable
//!\param c Clickable
void SetClickable(bool c);
//!Gets the element's current state
//!\return state
int GetState();
void SetVisible(bool v);
//!Sets the element's alpha value
//!\param a alpha value
void SetAlpha(int a);
//!Gets the element's alpha value
//!Considers alpha, alphaDyn, and the parent element's GetAlpha() value
//!\return alpha
int GetAlpha();
//!Sets the element's scale
//!\param s scale (1 is 100%)
void SetScale(float s);
//!Gets the element's current scale
//!Considers scale, scaleDyn, and the parent element's GetScale() value
float GetScale();
//!Set a new GuiTrigger for the element
//!\param t Pointer to GuiTrigger
void SetTrigger(GuiTrigger * t);
//!\overload
//!\param i Index of trigger array to set
//!\param t Pointer to GuiTrigger
void SetTrigger(u8 i, GuiTrigger * t);
//!Checks whether rumble was requested by the element
//!\return true is rumble was requested, false otherwise
bool Rumble();
//!Sets whether or not the element is requesting a rumble event
//!\param r true if requesting rumble, false if not
void SetRumble(bool r);
//!Set an effect for the element
//!\param e Effect to enable
//!\param a Amount of the effect (usage varies on effect)
//!\param t Target amount of the effect (usage varies on effect)
void SetEffect(int e, int a, int t=0);
//!Sets an effect to be enabled on wiimote cursor over
//!\param e Effect to enable
//!\param a Amount of the effect (usage varies on effect)
//!\param t Target amount of the effect (usage varies on effect)
void SetEffectOnOver(int e, int a, int t=0);
//!Shortcut to SetEffectOnOver(EFFECT_SCALE, 4, 110)
void SetEffectGrow();
//!Gets the current element effects
//!\return element effects
int GetEffect();
//!Checks whether the specified coordinates are within the element's boundaries
//!\param x X coordinate
//!\param y Y coordinate
//!\return true if contained within, false otherwise
bool IsInside(int x, int y);
//!Sets the element's position
//!\param x X coordinate
//!\param y Y coordinate
void SetPosition(int x, int y);
//!Updates the element's effects (dynamic values)
//!Called by Draw(), used for animation purposes
void UpdateEffects();
//!Sets a function to called after after Update()
//!Callback function can be used to response to changes in the state of the element, and/or update the element's attributes
void SetUpdateCallback(UpdateCallback u);
//!Checks whether the element is in focus
//!\return true if element is in focus, false otherwise
int IsFocused();
//!Sets the element's visibility
//!\param v Visibility (true = visible)
virtual void SetVisible(bool v);
//!Sets the element's focus
//!\param v Focus (true = in focus)
virtual void SetFocus(int f);
//!Sets the element's state
//!\param v State (STATE_DEFAULT, STATE_SELECTED, STATE_CLICKED, STATE_DISABLED)
virtual void SetState(int s);
//!Resets the element's state to STATE_DEFAULT
virtual void ResetState();
//!Gets whether or not the element is in STATE_SELECTED
//!\return true if selected, false otherwise
virtual int GetSelected();
//!Sets the element's alignment respective to its parent element
//!\param hor Horizontal alignment (ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTRE)
//!\param vert Vertical alignment (ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE)
virtual void SetAlignment(int hor, int vert);
//!Called constantly to allow the element to respond to the current input data
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
virtual void Update(GuiTrigger * t);
//!Called constantly to redraw the element
virtual void Draw();
protected:
bool visible;
int focus; // -1 = cannot focus, 0 = not focused, 1 = focused
int width;
int height;
int xoffset;
int yoffset;
int xoffsetDyn;
int yoffsetDyn;
int alpha;
f32 scale;
int alphaDyn;
f32 scaleDyn;
int effects;
int effectAmount;
int effectTarget;
int effectsOver;
int effectAmountOver;
int effectTargetOver;
int alignmentHor; // LEFT, RIGHT, CENTRE
int alignmentVert; // TOP, BOTTOM, MIDDLE
int state; // DEFAULT, SELECTED, CLICKED, DISABLED
bool selectable; // is SELECTED a valid state?
bool clickable; // is CLICKED a valid state?
GuiTrigger * trigger[2];
GuiElement * parentElement;
UpdateCallback updateCB;
bool visible; //!< Visibility of the element. If false, Draw() is skipped
int focus; //!< Element focus (-1 = focus disabled, 0 = not focused, 1 = focused)
int width; //!< Element width
int height; //!< Element height
int xoffset; //!< Element X offset
int yoffset; //!< Element Y offset
int xoffsetDyn; //!< Element X offset, dynamic (added to xoffset value for animation effects)
int yoffsetDyn; //!< Element Y offset, dynamic (added to yoffset value for animation effects)
int alpha; //!< Element alpha value (0-255)
f32 scale; //!< Element scale (1 = 100%)
int alphaDyn; //!< Element alpha, dynamic (multiplied by alpha value for blending/fading effects)
f32 scaleDyn; //!< Element scale, dynamic (multiplied by alpha value for blending/fading effects)
bool rumble; //!< Wiimote rumble (on/off) - set to on when this element requests a rumble event
int effects; //!< Currently enabled effect(s). 0 when no effects are enabled
int effectAmount; //!< Effect amount. Used by different effects for different purposes
int effectTarget; //!< Effect target amount. Used by different effects for different purposes
int effectsOver; //!< Effects to enable when wiimote cursor is over this element. Copied to effects variable on over event
int effectAmountOver; //!< EffectAmount to set when wiimote cursor is over this element
int effectTargetOver; //!< EffectTarget to set when wiimote cursor is over this element
int alignmentHor; //!< Horizontal element alignment, respective to parent element (LEFT, RIGHT, CENTRE)
int alignmentVert; //!< Horizontal element alignment, respective to parent element (TOP, BOTTOM, MIDDLE)
int state; //!< Element state (DEFAULT, SELECTED, CLICKED, DISABLED)
bool selectable; //!< Whether or not this element selectable (can change to SELECTED state)
bool clickable; //!< Whether or not this element is clickable (can change to CLICKED state)
GuiTrigger * trigger[2]; //!< GuiTriggers (input actions) that this element responds to
GuiElement * parentElement; //!< Parent element
UpdateCallback updateCB; //!< Callback function to call when this element is updated
};
//!Allows GuiElements to be grouped together into a "window"
class GuiWindow : public GuiElement
{
public:
//!Constructor
GuiWindow();
//!\overload
//!\param w Width of window
//!\param h Height of window
GuiWindow(int w, int h);
//!Destructor
~GuiWindow();
//!Appends a GuiElement to the GuiWindow
//!\param e The GuiElement to append. If it is already in the GuiWindow, it is removed first
void Append(GuiElement* e);
//!Inserts a GuiElement into the GuiWindow at the specified index
//!\param e The GuiElement to insert. If it is already in the GuiWindow, it is removed first
//!\param i Index in which to insert the element
void Insert(GuiElement* e, u32 i);
//!Removes the specified GuiElement from the GuiWindow
//!\param e GuiElement to be removed
void Remove(GuiElement* e);
//!Removes all GuiElements
void RemoveAll();
//!Returns the GuiElement at the specified index
//!\param index The index of the element
//!\return A pointer to the element at the index, NULL on error (eg: out of bounds)
GuiElement* GetGuiElementAt(u32 index) const;
//!Returns the size of the list of elements
//!\return The size of the current element list
u32 GetSize();
//!Sets the visibility of the window
//!\param v visibility (true = visible)
void SetVisible(bool v);
//!Resets the window's state to STATE_DEFAULT
void ResetState();
//!Sets the window's state
//!\param s State
void SetState(int s);
//!Gets the index of the GuiElement inside the window that is currently selected
//!\return index of selected GuiElement
int GetSelected();
//!Sets the window focus
//!\param f Focus
void SetFocus(int f);
//!Change the focus to the specified element
//!This is intended for the primary GuiWindow only
//!\param e GuiElement that should have focus
void ChangeFocus(GuiElement * e);
//!Changes window focus to the next focusable window or element
//!If no element is in focus, changes focus to the first available element
//!If B or 1 button is pressed, changes focus to the next available element
//!This is intended for the primary GuiWindow only
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
void ToggleFocus(GuiTrigger * t);
//!Moves the selected element to the element to the left or right
//!\param d Direction to move (-1 = left, 1 = right)
void MoveSelectionHor(int d);
//!Moves the selected element to the element above or below
//!\param d Direction to move (-1 = up, 1 = down)
void MoveSelectionVert(int d);
//!Draws all the elements in this GuiWindow
void Draw();
//!Updates the window and all elements contains within
//!Allows the GuiWindow and all elements to respond to the input data specified
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
void Update(GuiTrigger * t);
protected:
std::vector<GuiElement*> _elements; //!< Contains all elements within the GuiWindow
};
//!Converts image data into GX-useable RGBA8
//!Currently designed for use only with PNG files
class GuiImageData
{
public:
//!Constructor
//!Converts the image data to RGBA8 - expects PNG format
//!\param i Image data
GuiImageData(const u8 * i);
//!Destructor
~GuiImageData();
//!Gets a pointer to the image data
//!\return pointer to image data
u8 * GetImage();
//!Gets the image width
//!\return image width
int GetWidth();
//!Gets the image height
//!\return image height
int GetHeight();
protected:
u8 * data;
int height;
int width;
u8 * data; //!< Image data
int height; //!< Height of image
int width; //!< Width of image
};
//!Display, manage, and manipulate images in the Gui
class GuiImage : public GuiElement
{
public:
//!Constructor
//!\param img Pointer to GuiImageData element
GuiImage(GuiImageData * img);
//!\overload
//!Sets up a new image from the image data specified
//!\param img
//!\param w Image width
//!\param h Image height
GuiImage(u8 * img, int w, int h);
//!\overload
//!Creates an image filled with the specified color
//!\param w Image width
//!\param h Image height
//!\param c Image color
GuiImage(int w, int h, GXColor c);
//!Destructor
~GuiImage();
//!Sets the image rotation angle for drawing
//!\param a Angle (in degrees)
void SetAngle(float a);
//!Sets the number of times to draw the image horizontally
//!\param t Number of times to draw the image
void SetTile(int t);
//!Constantly called to draw the image
void Draw();
//!Gets the image data
//!\return pointer to image data
u8 * GetImage();
//!Sets up a new image using the GuiImageData object specified
//!\param img Pointer to GuiImageData object
void SetImage(GuiImageData * img);
//!\overload
//!\param img Pointer to image data
//!\param w Width
//!\param h Height
void SetImage(u8 * img, int w, int h);
//!Gets the pixel color at the specified coordinates of the image
//!\param x X coordinate
//!\param y Y coordinate
GXColor GetPixel(int x, int y);
//!Sets the pixel color at the specified coordinates of the image
//!\param x X coordinate
//!\param y Y coordinate
//!\param color Pixel color
void SetPixel(int x, int y, GXColor color);
void Stripe(int s);
//!Directly modifies the image data to create a color-striped effect
//!Alters the RGB values by the specified amount
//!\param s Amount to increment/decrement the RGB values in the image
void ColorStripe(int s);
//!Sets a stripe effect on the image, overlaying alpha blended rectangles
//!Does not alter the image data
//!\param s Alpha amount to draw over the image
void SetStripe(int s);
protected:
u8 * image;
f32 imageangle;
int tile;
int imgType; //!< Type of image data (IMAGE_TEXTURE, IMAGE_COLOR, IMAGE_DATA)
u8 * image; //!< Poiner to image data. May be shared with GuiImageData data
f32 imageangle; //!< Angle to draw the image
int tile; //!< Number of times to draw (tile) the image horizontally
int stripe; //!< Alpha value (0-255) to apply a stripe effect to the texture
};
//!Display, manage, and manipulate text in the Gui
class GuiText : public GuiElement
{
public:
//!Constructor
//!\param t Text
//!\param s Font size
//!\param c Font color
GuiText(const char * t, int s, GXColor c);
//!\overload
//!\Assumes SetPresets() has been called to setup preferred text attributes
//!\param t Text
GuiText(const char * t);
//!Destructor
~GuiText();
//!Sets the text of the GuiText element
//!\param t Text
void SetText(const char * t);
//!Sets up preset values to be used by GuiText(t)
//!Useful when printing multiple text elements, all with the same attributes set
//!\param sz Font size
//!\param c Font color
//!\param w Maximum width of texture image (for text wrapping)
//!\param s Font size
//!\param h Text alignment (horizontal)
//!\param v Text alignment (vertical)
void SetPresets(int sz, GXColor c, int w, u16 s, int h, int v);
//!Sets the font size
//!\param s Font size
void SetFontSize(int s);
//!Sets the maximum width of the drawn texture image
//!If the text exceeds this, it is wrapped to the next line
//!\param w Maximum width
void SetMaxWidth(int w);
//!Sets the font color
//!\param c Font color
void SetColor(GXColor c);
//!Sets the FreeTypeGX style attributes
//!\param s Style attributes
void SetStyle(u16 s);
//!Sets the text alignment
//!\param hor Horizontal alignment (ALIGN_LEFT, ALIGN_RIGHT, ALIGN_CENTRE)
//!\param vert Vertical alignment (ALIGN_TOP, ALIGN_BOTTOM, ALIGN_MIDDLE)
void SetAlignment(int hor, int vert);
//!Constantly called to draw the text
void Draw();
protected:
wchar_t* text; //!< Unicode text value
int size; //!< Font size
int maxWidth; //!< Maximum width of the generated text object (for text wrapping)
u16 style; //!< FreeTypeGX style attributes
GXColor color; //!< Font color
};
//!Display, manage, and manipulate buttons in the Gui
//!Buttons can have images, icons, text, and sound set (all of which are optional)
class GuiButton : public GuiElement
{
public:
//!Constructor
//!\param w Width
//!\param h Height
GuiButton(int w, int h);
//!Destructor
~GuiButton();
//!Sets the button's image
//!\param i Pointer to GuiImage object
void SetImage(GuiImage* i);
//!Sets the button's image on over
//!\param i Pointer to GuiImage object
void SetImageOver(GuiImage* i);
//!Sets the button's icon
//!\param i Pointer to GuiImage object
void SetIcon(GuiImage* i);
//!Sets the button's icon on over
//!\param i Pointer to GuiImage object
void SetIconOver(GuiImage* i);
//!Sets the button's label
//!\param t Pointer to GuiText object
void SetLabel(GuiText* t);
//!\overload
//!\param t Pointer to GuiText object
//!\param n Index of label to set
void SetLabel(GuiText* t, int n);
//!Sets the button's label on over (eg: different colored text)
//!\param t Pointer to GuiText object
void SetLabelOver(GuiText* t);
//!\overload
//!\param t Pointer to GuiText object
//!\param n Index of label to set
void SetLabelOver(GuiText* t, int n);
//!Sets the sound to play on over
//!\param s Pointer to GuiSound object
void SetSoundOver(GuiSound * s);
//!Sets the sound to play on click
//!\param s Pointer to GuiSound object
void SetSoundClick(GuiSound * s);
//!Constantly called to draw the GuiButton
void Draw();
//!Constantly called to allow the GuiButton to respond to updated input data
//!\param t Pointer to a GuiTrigger, containing the current input data from PAD/WPAD
void Update(GuiTrigger * t);
protected:
GuiImage * image; //!< Button image
GuiImage * imageOver; //!< Button image on wiimote cursor over
GuiImage * icon; //!< Button icon (drawn after button image)
GuiImage * iconOver; //!< Button icon on wiimote cursor over
GuiText * label[3]; //!< Label(s) to display
GuiText * labelOver[3]; //!< Label(s) to display on wiimote cursor over
GuiSound * soundOver; //!< Sound to play on wiimote cursor over
GuiSound * soundClick; //!< Sound to play on click
};
//!Display a list of files
class GuiFileBrowser : public GuiElement
{
public:
GuiFileBrowser(int w, int h);
~GuiFileBrowser();
void ResetState();
void SetFocus(int f);
void Draw();
void TriggerUpdate();
void Update(GuiTrigger * t);
GuiButton * gameList[PAGESIZE];
protected:
int selectedItem;
bool listChanged;
GuiText * gameListText[PAGESIZE];
GuiImage * gameListBg[PAGESIZE];
GuiImage * gameListFolder[PAGESIZE];
GuiButton * arrowUpBtn;
GuiButton * arrowDownBtn;
GuiButton * scrollbarBoxBtn;
GuiImage * bgGameSelectionImg;
GuiImage * scrollbarImg;
GuiImage * arrowDownImg;
GuiImage * arrowDownOverImg;
GuiImage * arrowUpImg;
GuiImage * arrowUpOverImg;
GuiImage * scrollbarBoxImg;
GuiImage * scrollbarBoxOverImg;
GuiImageData * bgGameSelection;
GuiImageData * bgGameSelectionEntry;
GuiImageData * gameFolder;
GuiImageData * scrollbar;
GuiImageData * arrowDown;
GuiImageData * arrowDownOver;
GuiImageData * arrowUp;
GuiImageData * arrowUpOver;
GuiImageData * scrollbarBox;
GuiImageData * scrollbarBoxOver;
GuiSound * btnSoundOver;
GuiSound * btnSoundClick;
GuiTrigger * trigA;
};
typedef struct _optionlist {
int length;
char name[MAX_OPTIONS][150];
char value[MAX_OPTIONS][150];
} OptionList;
//!Display a list of menu options
class GuiOptionBrowser : public GuiElement
{
public:
GuiOptionBrowser(int w, int h, OptionList * l);
~GuiOptionBrowser();
void SetCol2Position(int x);
int FindMenuItem(int c, int d);
int GetClickedOption();
void ResetState();
void SetFocus(int f);
void Draw();
void Update(GuiTrigger * t);
GuiText * optionVal[PAGESIZE];
protected:
int selectedItem;
int listOffset;
OptionList * options;
int optionIndex[PAGESIZE];
GuiButton * optionBtn[PAGESIZE];
GuiText * optionTxt[PAGESIZE];
GuiImage * optionBg[PAGESIZE];
GuiButton * arrowUpBtn;
GuiButton * arrowDownBtn;
GuiButton * scrollbarBoxBtn;
GuiImage * bgOptionsImg;
GuiImage * scrollbarImg;
GuiImage * arrowDownImg;
GuiImage * arrowDownOverImg;
GuiImage * arrowUpImg;
GuiImage * arrowUpOverImg;
GuiImage * scrollbarBoxImg;
GuiImage * scrollbarBoxOverImg;
GuiImageData * bgOptions;
GuiImageData * bgOptionsEntry;
GuiImageData * scrollbar;
GuiImageData * arrowDown;
GuiImageData * arrowDownOver;
GuiImageData * arrowUp;
GuiImageData * arrowUpOver;
GuiImageData * scrollbarBox;
GuiImageData * scrollbarBoxOver;
GuiSound * btnSoundOver;
GuiSound * btnSoundClick;
GuiTrigger * trigA;
};
typedef struct _savelist {
int length;
char filename[MAX_SAVES][256];
GuiImageData * previewImg[MAX_SAVES];
char date[MAX_SAVES][20];
char time[MAX_SAVES][10];
int type[MAX_SAVES];
int files[2][100];
} SaveList;
//!Display a list of game save files, with screenshots and file information
class GuiSaveBrowser : public GuiElement
{
public:
GuiSaveBrowser(int w, int h, SaveList * l, int a);
~GuiSaveBrowser();
int GetClickedSave();
void ResetState();
void SetFocus(int f);
void Draw();
void Update(GuiTrigger * t);
protected:
int selectedItem;
int listOffset;
int action;
SaveList * saves;
GuiButton * saveBtn[SAVELISTSIZE];
GuiText * saveDate[SAVELISTSIZE];
GuiText * saveTime[SAVELISTSIZE];
GuiText * saveType[SAVELISTSIZE];
GuiImage * saveBgImg[SAVELISTSIZE];
GuiImage * saveBgOverImg[SAVELISTSIZE];
GuiImage * savePreviewImg[SAVELISTSIZE];
GuiButton * arrowUpBtn;
GuiButton * arrowDownBtn;
GuiButton * scrollbarBoxBtn;
GuiImage * scrollbarImg;
GuiImage * arrowDownImg;
GuiImage * arrowDownOverImg;
GuiImage * arrowUpImg;
GuiImage * arrowUpOverImg;
GuiImage * scrollbarBoxImg;
GuiImage * scrollbarBoxOverImg;
GuiImageData * gameSave;
GuiImageData * gameSaveOver;
GuiImageData * gameSaveBlank;
GuiImageData * scrollbar;
GuiImageData * arrowDown;
GuiImageData * arrowDownOver;
GuiImageData * arrowUp;
GuiImageData * arrowUpOver;
GuiImageData * scrollbarBox;
GuiImageData * scrollbarBoxOver;
GuiSound * btnSoundOver;
GuiSound * btnSoundClick;
GuiTrigger * trigA;
};
typedef struct _keytype {
char ch, chShift;
} Key;
//!On-screen keyboard
class GuiKeyboard : public GuiWindow
{
public:
GuiKeyboard(char * t, u32 m);
~GuiKeyboard();
void Update(GuiTrigger * t);
char kbtextstr[256];
protected:
u32 kbtextmaxlen;
Key keys[4][11];
int shift;
int caps;
GuiText * kbText;
GuiImage * keyTextboxImg;
GuiText * keyCapsText;
GuiImage * keyCapsImg;
GuiImage * keyCapsOverImg;
GuiButton * keyCaps;
GuiText * keyShiftText;
GuiImage * keyShiftImg;
GuiImage * keyShiftOverImg;
GuiButton * keyShift;
GuiText * keyBackText;
GuiImage * keyBackImg;
GuiImage * keyBackOverImg;
GuiButton * keyBack;
GuiImage * keySpaceImg;
GuiImage * keySpaceOverImg;
GuiButton * keySpace;
GuiButton * keyBtn[4][11];
GuiImage * keyImg[4][11];
GuiImage * keyImgOver[4][11];
GuiText * keyTxt[4][11];
GuiImageData * keyTextbox;
GuiImageData * key;
GuiImageData * keyOver;
GuiImageData * keyMedium;
GuiImageData * keyMediumOver;
GuiImageData * keyLarge;
GuiImageData * keyLargeOver;
GuiSound * keySoundOver;
GuiSound * keySoundClick;
GuiTrigger * trigA;
};
#endif

View File

@ -0,0 +1,231 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Tantric February 2009
*
* gui_button.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
/**
* Constructor for the GuiButton class.
*/
GuiButton::GuiButton(int w, int h)
{
width = w;
height = h;
image = NULL;
imageOver = NULL;
icon = NULL;
iconOver = NULL;
for(int i=0; i < 3; i++)
{
label[i] = NULL;
labelOver[i] = NULL;
}
soundOver = NULL;
soundClick = NULL;
selectable = true;
clickable = true;
}
/**
* Destructor for the GuiButton class.
*/
GuiButton::~GuiButton()
{
}
void GuiButton::SetImage(GuiImage* img)
{
image = img;
if(img)
img->SetParent(this);
}
void GuiButton::SetImageOver(GuiImage* img)
{
imageOver = img;
if(img)
img->SetParent(this);
}
void GuiButton::SetIcon(GuiImage* img)
{
icon = img;
if(img)
img->SetParent(this);
}
void GuiButton::SetIconOver(GuiImage* img)
{
iconOver = img;
if(img)
img->SetParent(this);
}
void GuiButton::SetLabel(GuiText* txt)
{
label[0] = txt;
if(txt)
txt->SetParent(this);
}
void GuiButton::SetLabelOver(GuiText* txt)
{
labelOver[0] = txt;
if(txt)
txt->SetParent(this);
}
void GuiButton::SetLabel(GuiText* txt, int n)
{
label[n] = txt;
if(txt)
txt->SetParent(this);
}
void GuiButton::SetLabelOver(GuiText* txt, int n)
{
labelOver[n] = txt;
if(txt)
txt->SetParent(this);
}
void GuiButton::SetSoundOver(GuiSound * snd)
{
soundOver = snd;
}
void GuiButton::SetSoundClick(GuiSound * snd)
{
soundClick = snd;
}
/**
* Draw the button on screen
*/
void GuiButton::Draw()
{
if(!this->IsVisible())
return;
// draw image
if(state == STATE_SELECTED && imageOver)
imageOver->Draw();
else if(image)
image->Draw();
// draw icon
if(state == STATE_SELECTED && iconOver)
iconOver->Draw();
else if(icon)
icon->Draw();
// draw text
for(int i=0; i<3; i++)
{
if(state == STATE_SELECTED && labelOver[i])
labelOver[i]->Draw();
else if(label[i])
label[i]->Draw();
}
this->UpdateEffects();
}
void GuiButton::Update(GuiTrigger * t)
{
if(state == STATE_CLICKED || state == STATE_DISABLED || !t)
return;
else if(parentElement && parentElement->GetState() == STATE_DISABLED)
return;
#ifdef HW_RVL
// cursor
if(t->wpad.ir.valid)
{
if(this->IsInside(t->wpad.ir.x, t->wpad.ir.y))
{
if(state == STATE_DEFAULT) // we weren't on the button before!
{
state = STATE_SELECTED;
if(this->Rumble())
rumbleRequest[t->chan] = 1;
if(soundOver)
soundOver->Play();
if(effectsOver && !effects)
{
// initiate effects
effects = effectsOver;
effectAmount = effectAmountOver;
effectTarget = effectTargetOver;
}
}
}
else
{
if(state == STATE_SELECTED)
state = STATE_DEFAULT;
if(effectTarget == effectTargetOver && effectAmount == effectAmountOver)
{
// initiate effects (in reverse)
effects = effectsOver;
effectAmount = -effectAmountOver;
effectTarget = 100;
}
}
}
#endif
// button triggers
if(this->IsClickable())
{
for(int i=0; i<2; i++)
{
if(trigger[i] && (trigger[i]->chan == -1 || trigger[i]->chan == t->chan))
{
// higher 16 bits only (wiimote)
s32 wm_btns = t->wpad.btns_d << 16;
s32 wm_btns_trig = trigger[i]->wpad.btns_d << 16;
// lower 16 bits only (classic controller)
s32 cc_btns = t->wpad.btns_d >> 16;
s32 cc_btns_trig = trigger[i]->wpad.btns_d >> 16;
if(
(t->wpad.btns_d > 0 &&
wm_btns == wm_btns_trig ||
(cc_btns == cc_btns_trig && t->wpad.exp.type == EXP_CLASSIC)) ||
(t->pad.btns_d == trigger[i]->pad.btns_d && t->pad.btns_d > 0))
{
if(state == STATE_SELECTED)
{
state = STATE_CLICKED;
if(soundClick)
soundClick->Play();
}
else if(trigger[i]->type == TRIGGER_BUTTON_ONLY)
{
state = STATE_CLICKED;
}
else if(trigger[i]->type == TRIGGER_BUTTON_ONLY_IN_FOCUS &&
parentElement->IsFocused())
{
state = STATE_CLICKED;
}
}
}
}
}
if(updateCB)
updateCB(this);
}

View File

@ -25,6 +25,7 @@ GuiElement::GuiElement()
trigger[0] = NULL;
trigger[1] = NULL;
parentElement = NULL;
rumble = true;
selectable = false;
clickable = false;
visible = true;
@ -283,6 +284,16 @@ void GuiElement::SetTrigger(u8 i, GuiTrigger * t)
trigger[i] = t;
}
bool GuiElement::Rumble()
{
return rumble;
}
void GuiElement::SetRumble(bool r)
{
rumble = r;
}
int GuiElement::GetEffect()
{
return effects;

View File

@ -0,0 +1,328 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Tantric February 2009
*
* gui_filebrowser.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
#include "filebrowser.h"
/**
* Constructor for the GuiFileBrowser class.
*/
GuiFileBrowser::GuiFileBrowser(int w, int h)
{
width = w;
height = h;
selectedItem = 0;
selectable = true;
listChanged = true; // trigger an initial list update
focus = 0; // allow focus
trigA = new GuiTrigger;
if(GCSettings.WiimoteOrientation)
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
else
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
btnSoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, SOUND_PCM);
btnSoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, SOUND_PCM);
bgGameSelection = new GuiImageData(bg_game_selection_png);
bgGameSelectionImg = new GuiImage(bgGameSelection);
bgGameSelectionImg->SetParent(this);
bgGameSelectionImg->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
bgGameSelectionEntry = new GuiImageData(bg_game_selection_entry_png);
gameFolder = new GuiImageData(folder_png);
scrollbar = new GuiImageData(scrollbar_png);
scrollbarImg = new GuiImage(scrollbar);
scrollbarImg->SetParent(this);
scrollbarImg->SetAlignment(ALIGN_RIGHT, ALIGN_TOP);
scrollbarImg->SetPosition(0, 30);
arrowDown = new GuiImageData(scrollbar_arrowdown_png);
arrowDownImg = new GuiImage(arrowDown);
arrowDownOver = new GuiImageData(scrollbar_arrowdown_over_png);
arrowDownOverImg = new GuiImage(arrowDownOver);
arrowUp = new GuiImageData(scrollbar_arrowup_png);
arrowUpImg = new GuiImage(arrowUp);
arrowUpOver = new GuiImageData(scrollbar_arrowup_over_png);
arrowUpOverImg = new GuiImage(arrowUpOver);
scrollbarBox = new GuiImageData(scrollbar_box_png);
scrollbarBoxImg = new GuiImage(scrollbarBox);
scrollbarBoxOver = new GuiImageData(scrollbar_box_over_png);
scrollbarBoxOverImg = new GuiImage(scrollbarBoxOver);
arrowUpBtn = new GuiButton(arrowUpImg->GetWidth(), arrowUpImg->GetHeight());
arrowUpBtn->SetParent(this);
arrowUpBtn->SetImage(arrowUpImg);
arrowUpBtn->SetImageOver(arrowUpOverImg);
arrowUpBtn->SetAlignment(ALIGN_RIGHT, ALIGN_TOP);
arrowUpBtn->SetSelectable(false);
arrowUpBtn->SetTrigger(trigA);
arrowUpBtn->SetSoundOver(btnSoundOver);
arrowUpBtn->SetSoundClick(btnSoundClick);
arrowDownBtn = new GuiButton(arrowDownImg->GetWidth(), arrowDownImg->GetHeight());
arrowDownBtn->SetParent(this);
arrowDownBtn->SetImage(arrowDownImg);
arrowDownBtn->SetImageOver(arrowDownOverImg);
arrowDownBtn->SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM);
arrowDownBtn->SetSelectable(false);
arrowDownBtn->SetTrigger(trigA);
arrowDownBtn->SetSoundOver(btnSoundOver);
arrowDownBtn->SetSoundClick(btnSoundClick);
scrollbarBoxBtn = new GuiButton(scrollbarBoxImg->GetWidth(), scrollbarBoxImg->GetHeight());
scrollbarBoxBtn->SetParent(this);
scrollbarBoxBtn->SetImage(scrollbarBoxImg);
scrollbarBoxBtn->SetImageOver(scrollbarBoxOverImg);
scrollbarBoxBtn->SetAlignment(ALIGN_RIGHT, ALIGN_TOP);
scrollbarBoxBtn->SetSelectable(false);
for(int i=0; i<PAGESIZE; i++)
{
gameListText[i] = new GuiText("Game",22, (GXColor){0, 0, 0, 0xff});
gameListText[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
gameListText[i]->SetPosition(5,0);
gameListBg[i] = new GuiImage(bgGameSelectionEntry);
gameListFolder[i] = new GuiImage(gameFolder);
gameList[i] = new GuiButton(380, 30);
gameList[i]->SetParent(this);
gameList[i]->SetLabel(gameListText[i]);
gameList[i]->SetImageOver(gameListBg[i]);
gameList[i]->SetPosition(2,30*i+3);
gameList[i]->SetTrigger(trigA);
gameList[i]->SetSoundClick(btnSoundClick);
}
}
/**
* Destructor for the GuiFileBrowser class.
*/
GuiFileBrowser::~GuiFileBrowser()
{
delete arrowUpBtn;
delete arrowDownBtn;
delete scrollbarBoxBtn;
delete bgGameSelectionImg;
delete scrollbarImg;
delete arrowDownImg;
delete arrowDownOverImg;
delete arrowUpImg;
delete arrowUpOverImg;
delete scrollbarBoxImg;
delete scrollbarBoxOverImg;
delete bgGameSelection;
delete bgGameSelectionEntry;
delete gameFolder;
delete scrollbar;
delete arrowDown;
delete arrowDownOver;
delete arrowUp;
delete arrowUpOver;
delete scrollbarBox;
delete scrollbarBoxOver;
delete btnSoundOver;
delete btnSoundClick;
delete trigA;
for(int i=0; i<PAGESIZE; i++)
{
delete gameListText[i];
delete gameList[i];
delete gameListBg[i];
delete gameListFolder[i];
}
}
void GuiFileBrowser::SetFocus(int f)
{
focus = f;
for(int i=0; i<PAGESIZE; i++)
gameList[i]->ResetState();
if(f == 1)
gameList[selectedItem]->SetState(STATE_SELECTED);
}
void GuiFileBrowser::ResetState()
{
state = STATE_DEFAULT;
selectedItem = 0;
for(int i=0; i<PAGESIZE; i++)
{
gameList[i]->ResetState();
}
}
void GuiFileBrowser::TriggerUpdate()
{
listChanged = true;
}
/**
* Draw the button on screen
*/
void GuiFileBrowser::Draw()
{
if(!this->IsVisible())
return;
bgGameSelectionImg->Draw();
for(int i=0; i<PAGESIZE; i++)
{
gameList[i]->Draw();
}
scrollbarImg->Draw();
arrowUpBtn->Draw();
arrowDownBtn->Draw();
scrollbarBoxBtn->Draw();
this->UpdateEffects();
}
void GuiFileBrowser::Update(GuiTrigger * t)
{
if(state == STATE_DISABLED || !t)
return;
// update the location of the scroll box based on the position in the file list
int position = 136*(browser.pageIndex + selectedItem) / browser.numEntries;
scrollbarBoxBtn->SetPosition(0,position+36);
arrowUpBtn->Update(t);
arrowDownBtn->Update(t);
scrollbarBoxBtn->Update(t);
// pad/joystick navigation
if(!focus)
{
goto endNavigation; // skip navigation
listChanged = false;
}
if(t->Right() || arrowDownBtn->GetState() == STATE_CLICKED)
{
if(browser.pageIndex < browser.numEntries && browser.numEntries > PAGESIZE)
{
browser.pageIndex += PAGESIZE;
if(browser.pageIndex+PAGESIZE >= browser.numEntries)
browser.pageIndex = browser.numEntries-PAGESIZE;
listChanged = true;
}
arrowDownBtn->ResetState();
}
else if(t->Left() || arrowUpBtn->GetState() == STATE_CLICKED)
{
if(browser.pageIndex > 0)
{
browser.pageIndex -= PAGESIZE;
if(browser.pageIndex < 0)
browser.pageIndex = 0;
listChanged = true;
}
arrowUpBtn->ResetState();
}
else if(t->Down())
{
if(browser.pageIndex + selectedItem + 1 < browser.numEntries)
{
if(selectedItem == PAGESIZE-1)
{
// move list down by 1
browser.pageIndex++;
listChanged = true;
}
else if(gameList[selectedItem+1]->IsVisible())
{
gameList[selectedItem]->ResetState();
gameList[++selectedItem]->SetState(STATE_SELECTED);
}
}
}
else if(t->Up())
{
if(selectedItem == 0 && browser.pageIndex + selectedItem > 0)
{
// move list up by 1
browser.pageIndex--;
listChanged = true;
}
else if(selectedItem > 0)
{
gameList[selectedItem]->ResetState();
gameList[--selectedItem]->SetState(STATE_SELECTED);
}
}
endNavigation:
for(int i=0; i<PAGESIZE; i++)
{
if(listChanged)
{
if(browser.pageIndex+i < browser.numEntries)
{
if(gameList[i]->GetState() == STATE_DISABLED)
gameList[i]->SetState(STATE_DEFAULT);
gameList[i]->SetVisible(true);
gameListText[i]->SetText(browserList[browser.pageIndex+i].displayname);
if(browserList[browser.pageIndex+i].isdir) // directory
{
gameList[i]->SetIcon(gameListFolder[i]);
gameListText[i]->SetPosition(30,0);
}
else
{
gameList[i]->SetIcon(NULL);
gameListText[i]->SetPosition(10,0);
}
}
else
{
gameList[i]->SetVisible(false);
gameList[i]->SetState(STATE_DISABLED);
}
}
if(focus)
{
if(i != selectedItem && gameList[i]->GetState() == STATE_SELECTED)
gameList[i]->ResetState();
else if(i == selectedItem && gameList[i]->GetState() == STATE_DEFAULT)
gameList[selectedItem]->SetState(STATE_SELECTED);
}
gameList[i]->Update(t);
if(gameList[i]->GetState() == STATE_SELECTED)
{
selectedItem = i;
browser.selIndex = browser.pageIndex + i;
}
}
listChanged = false;
if(updateCB)
updateCB(this);
}

View File

@ -0,0 +1,220 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Tantric February 2009
*
* gui_image.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
/**
* Constructor for the GuiImage class.
*/
GuiImage::GuiImage(GuiImageData * img)
{
image = img->GetImage();
width = img->GetWidth();
height = img->GetHeight();
imageangle = 0;
tile = -1;
stripe = 0;
imgType = IMAGE_DATA;
}
GuiImage::GuiImage(u8 * img, int w, int h)
{
image = img;
width = w;
height = h;
imageangle = 0;
tile = -1;
stripe = 0;
imgType = IMAGE_TEXTURE;
}
GuiImage::GuiImage(int w, int h, GXColor c)
{
image = (u8 *)memalign (32, w * h * 4);
width = w;
height = h;
imageangle = 0;
tile = -1;
stripe = 0;
imgType = IMAGE_COLOR;
if(!image)
return;
int x, y;
for(y=0; y < h; y++)
{
for(x=0; x < w; x++)
{
this->SetPixel(x, y, c);
}
}
int len = w*h*4;
if(len%32) len += (32-len%32);
DCFlushRange(image, len);
}
/**
* Destructor for the GuiImage class.
*/
GuiImage::~GuiImage()
{
if(imgType == IMAGE_COLOR && image)
free(image);
}
u8 * GuiImage::GetImage()
{
return image;
}
void GuiImage::SetImage(GuiImageData * img)
{
image = img->GetImage();
width = img->GetWidth();
height = img->GetHeight();
imgType = IMAGE_DATA;
}
void GuiImage::SetImage(u8 * img, int w, int h)
{
image = img;
width = w;
height = h;
imgType = IMAGE_TEXTURE;
}
void GuiImage::SetAngle(float a)
{
imageangle = a;
}
void GuiImage::SetTile(int t)
{
tile = t;
}
GXColor GuiImage::GetPixel(int x, int y)
{
if(!image || this->GetWidth() <= 0 || x < 0 || y < 0)
return (GXColor){0, 0, 0, 0};
u32 offset = (((y >> 2)<<4)*this->GetWidth()) + ((x >> 2)<<6) + (((y%4 << 2) + x%4 ) << 1);
GXColor color;
color.a = *(image+offset);
color.r = *(image+offset+1);
color.g = *(image+offset+32);
color.b = *(image+offset+33);
return color;
}
void GuiImage::SetPixel(int x, int y, GXColor color)
{
if(!image || this->GetWidth() <= 0 || x < 0 || y < 0)
return;
u32 offset = (((y >> 2)<<4)*this->GetWidth()) + ((x >> 2)<<6) + (((y%4 << 2) + x%4 ) << 1);
*(image+offset) = color.a;
*(image+offset+1) = color.r;
*(image+offset+32) = color.g;
*(image+offset+33) = color.b;
}
void GuiImage::SetStripe(int s)
{
stripe = s;
}
void GuiImage::ColorStripe(int shift)
{
int x, y;
GXColor color;
int alt = 0;
for(y=0; y < this->GetHeight(); y++)
{
if(y % 3 == 0)
alt ^= 1;
for(x=0; x < this->GetWidth(); x++)
{
color = GetPixel(x, y);
if(alt)
{
if(color.r < 255-shift)
color.r += shift;
else
color.r = 255;
if(color.g < 255-shift)
color.g += shift;
else
color.g = 255;
if(color.b < 255-shift)
color.b += shift;
else
color.b = 255;
color.a = 255;
}
else
{
if(color.r > shift)
color.r -= shift;
else
color.r = 0;
if(color.g > shift)
color.g -= shift;
else
color.g = 0;
if(color.b > shift)
color.b -= shift;
else
color.b = 0;
color.a = 255;
}
SetPixel(x, y, color);
}
}
}
/**
* Draw the button on screen
*/
void GuiImage::Draw()
{
if(!image || !this->IsVisible() || tile == 0)
return;
float currScale = this->GetScale();
int currLeft = this->GetLeft();
if(tile > 0)
{
for(int i=0; i<tile; i++)
Menu_DrawImg(currLeft+width*i, this->GetTop(), width, height, image, imageangle, currScale, currScale, this->GetAlpha());
}
else
{
// temporary (maybe), used to correct offset for scaled images
if(scale != 1)
currLeft = currLeft - width/2 + (width*scale)/2;
Menu_DrawImg(currLeft, this->GetTop(), width, height, image, imageangle, currScale, currScale, this->GetAlpha());
}
if(stripe > 0)
for(int y=0; y < this->GetHeight(); y+=6)
Menu_DrawRectangle(currLeft,this->GetTop()+y,this->GetWidth(),3,(GXColor){0, 0, 0, stripe},1);
this->UpdateEffects();
}

View File

@ -14,26 +14,45 @@
* Constructor for the GuiImageData class.
*/
GuiImageData::GuiImageData(const u8 * img)
{
if(img == NULL)
{
data = NULL;
width = 0;
height = 0;
if(img)
{
PNGUPROP imgProp;
IMGCTX ctx = PNGU_SelectImageFromBuffer(img);
if(!ctx)
return;
int res = PNGU_GetImageProperties(ctx, &imgProp);
if(res == PNGU_OK)
{
int len = imgProp.imgWidth * imgProp.imgHeight * 4;
if(len%32) len += (32-len%32);
data = (u8 *)memalign (32, len);
if(data)
{
res = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, data, 255);
if(res == PNGU_OK)
{
width = imgProp.imgWidth;
height = imgProp.imgHeight;
DCFlushRange(data, len);
}
else
{
PNGUPROP imgProp;
IMGCTX ctx;
ctx = PNGU_SelectImageFromBuffer(img);
PNGU_GetImageProperties (ctx, &imgProp);
width = imgProp.imgWidth;
height = imgProp.imgHeight;
data = (u8 *)memalign (32, imgProp.imgWidth * imgProp.imgHeight * 4);
PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, data, 255);
free(data);
data = NULL;
}
}
}
PNGU_ReleaseImageContext (ctx);
DCFlushRange (data, imgProp.imgWidth * imgProp.imgHeight * 4);
}
}

View File

@ -0,0 +1,330 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Tantric February 2009
*
* gui_keyboard.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
/**
* Constructor for the GuiKeyboard class.
*/
GuiKeyboard::GuiKeyboard(char * t, u32 max)
{
width = 540;
height = 400;
shift = 0;
caps = 0;
selectable = true;
focus = 0; // allow focus
alignmentHor = ALIGN_CENTRE;
alignmentVert = ALIGN_MIDDLE;
strncpy(kbtextstr, t, max);
kbtextstr[max] = 0;
kbtextmaxlen = max;
Key thekeys[4][11] = {
{
{'1','!'},
{'2','@'},
{'3','#'},
{'4','$'},
{'5','%'},
{'6','^'},
{'7','&'},
{'8','*'},
{'9','('},
{'0',')'},
{'\0','\0'}
},
{
{'q','Q'},
{'w','W'},
{'e','E'},
{'r','R'},
{'t','T'},
{'y','Y'},
{'u','U'},
{'i','I'},
{'o','O'},
{'p','P'},
{'-','_'}
},
{
{'a','A'},
{'s','S'},
{'d','D'},
{'f','F'},
{'g','G'},
{'h','H'},
{'j','J'},
{'k','K'},
{'l','L'},
{':',';'},
{'\'','"'}
},
{
{'z','Z'},
{'x','X'},
{'c','C'},
{'v','V'},
{'b','B'},
{'n','N'},
{'m','M'},
{',','<'},
{'.','>'},
{'/','?'},
{'\0','\0'}
}
};
memcpy(keys, thekeys, sizeof(thekeys));
keyTextbox = new GuiImageData(keyboard_textbox_png);
keyTextboxImg = new GuiImage(keyTextbox);
keyTextboxImg->SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
keyTextboxImg->SetPosition(0, 0);
this->Append(keyTextboxImg);
kbText = new GuiText(kbtextstr, 22, (GXColor){0, 0, 0, 0xff});
kbText->SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
kbText->SetPosition(0, 13);
this->Append(kbText);
key = new GuiImageData(keyboard_key_png);
keyOver = new GuiImageData(keyboard_key_over_png);
keyMedium = new GuiImageData(keyboard_mediumkey_png);
keyMediumOver = new GuiImageData(keyboard_mediumkey_over_png);
keyLarge = new GuiImageData(keyboard_largekey_png);
keyLargeOver = new GuiImageData(keyboard_largekey_over_png);
keySoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, SOUND_PCM);
keySoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, SOUND_PCM);
trigA = new GuiTrigger;
if(GCSettings.WiimoteOrientation)
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
else
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
keyBackImg = new GuiImage(keyMedium);
keyBackOverImg = new GuiImage(keyMediumOver);
keyBackText = new GuiText("Back", 22, (GXColor){0, 0, 0, 0xff});
keyBack = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight());
keyBack->SetImage(keyBackImg);
keyBack->SetImageOver(keyBackOverImg);
keyBack->SetLabel(keyBackText);
keyBack->SetSoundOver(keySoundOver);
keyBack->SetSoundClick(keySoundClick);
keyBack->SetTrigger(trigA);
keyBack->SetPosition(10*42+40, 0*42+80);
keyBack->SetEffectGrow();
this->Append(keyBack);
keyCapsImg = new GuiImage(keyMedium);
keyCapsOverImg = new GuiImage(keyMediumOver);
keyCapsText = new GuiText("Caps", 22, (GXColor){0, 0, 0, 0xff});
keyCaps = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight());
keyCaps->SetImage(keyCapsImg);
keyCaps->SetImageOver(keyCapsOverImg);
keyCaps->SetLabel(keyCapsText);
keyCaps->SetSoundOver(keySoundOver);
keyCaps->SetSoundClick(keySoundClick);
keyCaps->SetTrigger(trigA);
keyCaps->SetPosition(0, 2*42+80);
keyCaps->SetEffectGrow();
this->Append(keyCaps);
keyShiftImg = new GuiImage(keyMedium);
keyShiftOverImg = new GuiImage(keyMediumOver);
keyShiftText = new GuiText("Shift", 22, (GXColor){0, 0, 0, 0xff});
keyShift = new GuiButton(keyMedium->GetWidth(), keyMedium->GetHeight());
keyShift->SetImage(keyShiftImg);
keyShift->SetImageOver(keyShiftOverImg);
keyShift->SetLabel(keyShiftText);
keyShift->SetSoundOver(keySoundOver);
keyShift->SetSoundClick(keySoundClick);
keyShift->SetTrigger(trigA);
keyShift->SetPosition(21, 3*42+80);
keyShift->SetEffectGrow();
this->Append(keyShift);
keySpaceImg = new GuiImage(keyLarge);
keySpaceOverImg = new GuiImage(keyLargeOver);
keySpace = new GuiButton(keyLarge->GetWidth(), keyLarge->GetHeight());
keySpace->SetImage(keySpaceImg);
keySpace->SetImageOver(keySpaceOverImg);
keySpace->SetSoundOver(keySoundOver);
keySpace->SetSoundClick(keySoundClick);
keySpace->SetTrigger(trigA);
keySpace->SetPosition(0, 4*42+80);
keySpace->SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
keySpace->SetEffectGrow();
this->Append(keySpace);
for(int i=0; i<4; i++)
{
for(int j=0; j<11; j++)
{
if(keys[i][j].ch != '\0')
{
keyImg[i][j] = new GuiImage(key);
keyImgOver[i][j] = new GuiImage(keyOver);
keyTxt[i][j] = new GuiText(NULL, 22, (GXColor){0, 0, 0, 0xff});
keyTxt[i][j]->SetAlignment(ALIGN_CENTRE, ALIGN_BOTTOM);
keyTxt[i][j]->SetPosition(0, -10);
keyBtn[i][j] = new GuiButton(key->GetWidth(), key->GetHeight());
keyBtn[i][j]->SetImage(keyImg[i][j]);
keyBtn[i][j]->SetImageOver(keyImgOver[i][j]);
keyBtn[i][j]->SetSoundOver(keySoundOver);
keyBtn[i][j]->SetSoundClick(keySoundClick);
keyBtn[i][j]->SetTrigger(trigA);
keyBtn[i][j]->SetLabel(keyTxt[i][j]);
keyBtn[i][j]->SetPosition(j*42+21*i+40, i*42+80);
keyBtn[i][j]->SetEffectGrow();
this->Append(keyBtn[i][j]);
}
}
}
}
/**
* Destructor for the GuiKeyboard class.
*/
GuiKeyboard::~GuiKeyboard()
{
delete kbText;
delete keyTextbox;
delete keyTextboxImg;
delete keyCapsText;
delete keyCapsImg;
delete keyCapsOverImg;
delete keyCaps;
delete keyShiftText;
delete keyShiftImg;
delete keyShiftOverImg;
delete keyShift;
delete keyBackText;
delete keyBackImg;
delete keyBackOverImg;
delete keyBack;
delete keySpaceImg;
delete keySpaceOverImg;
delete keySpace;
delete key;
delete keyOver;
delete keyMedium;
delete keyMediumOver;
delete keyLarge;
delete keyLargeOver;
delete keySoundOver;
delete keySoundClick;
delete trigA;
for(int i=0; i<4; i++)
{
for(int j=0; j<11; j++)
{
if(keys[i][j].ch != '\0')
{
delete keyImg[i][j];
delete keyImgOver[i][j];
delete keyTxt[i][j];
delete keyBtn[i][j];
}
}
}
}
void GuiKeyboard::Update(GuiTrigger * t)
{
if(_elements.size() == 0 || (state == STATE_DISABLED && parentElement))
return;
for (u8 i = 0; i < _elements.size(); i++)
{
try { _elements.at(i)->Update(t); }
catch (exception& e) { }
}
if(keySpace->GetState() == STATE_CLICKED)
{
if(strlen(kbtextstr) < kbtextmaxlen)
{
kbtextstr[strlen(kbtextstr)] = ' ';
kbText->SetText(kbtextstr);
}
keySpace->SetState(STATE_SELECTED);
}
else if(keyBack->GetState() == STATE_CLICKED)
{
kbtextstr[strlen(kbtextstr)-1] = 0;
kbText->SetText(kbtextstr);
keyBack->SetState(STATE_SELECTED);
}
else if(keyShift->GetState() == STATE_CLICKED)
{
shift ^= 1;
keyShift->SetState(STATE_SELECTED);
}
else if(keyCaps->GetState() == STATE_CLICKED)
{
caps ^= 1;
keyCaps->SetState(STATE_SELECTED);
}
char txt[2] = { 0, 0 };
for(int i=0; i<4; i++)
{
for(int j=0; j<11; j++)
{
if(keys[i][j].ch != '\0')
{
if(shift || caps)
txt[0] = keys[i][j].chShift;
else
txt[0] = keys[i][j].ch;
keyTxt[i][j]->SetText(txt);
if(keyBtn[i][j]->GetState() == STATE_CLICKED)
{
if(strlen(kbtextstr) < kbtextmaxlen)
{
if(shift || caps)
{
kbtextstr[strlen(kbtextstr)] = keys[i][j].chShift;
if(shift) shift ^= 1;
}
else
{
kbtextstr[strlen(kbtextstr)] = keys[i][j].ch;
}
}
kbText->SetText(kbtextstr);
keyBtn[i][j]->SetState(STATE_SELECTED);
}
}
}
}
this->ToggleFocus(t);
if(focus) // only send actions to this window if it's in focus
{
// pad/joystick navigation
if(t->Right())
this->MoveSelectionHor(1);
else if(t->Left())
this->MoveSelectionHor(-1);
else if(t->Down())
this->MoveSelectionVert(1);
else if(t->Up())
this->MoveSelectionVert(-1);
}
}

View File

@ -0,0 +1,351 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Tantric February 2009
*
* gui_optionbrowser.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
#include "filebrowser.h"
/**
* Constructor for the GuiOptionBrowser class.
*/
GuiOptionBrowser::GuiOptionBrowser(int w, int h, OptionList * l)
{
width = w;
height = h;
options = l;
selectable = true;
listOffset = this->FindMenuItem(-1, 1);
selectedItem = 0;
focus = 0; // allow focus
trigA = new GuiTrigger;
if(GCSettings.WiimoteOrientation)
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
else
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
btnSoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, SOUND_PCM);
btnSoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, SOUND_PCM);
bgOptions = new GuiImageData(bg_options_png);
bgOptionsImg = new GuiImage(bgOptions);
bgOptionsImg->SetParent(this);
bgOptionsImg->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
bgOptionsEntry = new GuiImageData(bg_options_entry_png);
scrollbar = new GuiImageData(scrollbar_png);
scrollbarImg = new GuiImage(scrollbar);
scrollbarImg->SetParent(this);
scrollbarImg->SetAlignment(ALIGN_RIGHT, ALIGN_TOP);
scrollbarImg->SetPosition(0, 30);
arrowDown = new GuiImageData(scrollbar_arrowdown_png);
arrowDownImg = new GuiImage(arrowDown);
arrowDownOver = new GuiImageData(scrollbar_arrowdown_over_png);
arrowDownOverImg = new GuiImage(arrowDownOver);
arrowUp = new GuiImageData(scrollbar_arrowup_png);
arrowUpImg = new GuiImage(arrowUp);
arrowUpOver = new GuiImageData(scrollbar_arrowup_over_png);
arrowUpOverImg = new GuiImage(arrowUpOver);
scrollbarBox = new GuiImageData(scrollbar_box_png);
scrollbarBoxImg = new GuiImage(scrollbarBox);
scrollbarBoxOver = new GuiImageData(scrollbar_box_over_png);
scrollbarBoxOverImg = new GuiImage(scrollbarBoxOver);
arrowUpBtn = new GuiButton(arrowUpImg->GetWidth(), arrowUpImg->GetHeight());
arrowUpBtn->SetParent(this);
arrowUpBtn->SetImage(arrowUpImg);
arrowUpBtn->SetImageOver(arrowUpOverImg);
arrowUpBtn->SetAlignment(ALIGN_RIGHT, ALIGN_TOP);
arrowUpBtn->SetSelectable(false);
arrowUpBtn->SetTrigger(trigA);
arrowUpBtn->SetSoundOver(btnSoundOver);
arrowUpBtn->SetSoundClick(btnSoundClick);
arrowDownBtn = new GuiButton(arrowDownImg->GetWidth(), arrowDownImg->GetHeight());
arrowDownBtn->SetParent(this);
arrowDownBtn->SetImage(arrowDownImg);
arrowDownBtn->SetImageOver(arrowDownOverImg);
arrowDownBtn->SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM);
arrowDownBtn->SetSelectable(false);
arrowDownBtn->SetTrigger(trigA);
arrowDownBtn->SetSoundOver(btnSoundOver);
arrowDownBtn->SetSoundClick(btnSoundClick);
scrollbarBoxBtn = new GuiButton(scrollbarBoxImg->GetWidth(), scrollbarBoxImg->GetHeight());
scrollbarBoxBtn->SetParent(this);
scrollbarBoxBtn->SetImage(scrollbarBoxImg);
scrollbarBoxBtn->SetImageOver(scrollbarBoxOverImg);
scrollbarBoxBtn->SetAlignment(ALIGN_RIGHT, ALIGN_TOP);
scrollbarBoxBtn->SetSelectable(false);
for(int i=0; i<PAGESIZE; i++)
{
optionTxt[i] = new GuiText(options->name[i], 22, (GXColor){0, 0, 0, 0xff});
optionTxt[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
optionTxt[i]->SetPosition(8,0);
optionVal[i] = new GuiText(NULL, 22, (GXColor){0, 0, 0, 0xff});
optionVal[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
optionVal[i]->SetPosition(250,0);
optionBg[i] = new GuiImage(bgOptionsEntry);
optionBtn[i] = new GuiButton(512,30);
optionBtn[i]->SetParent(this);
optionBtn[i]->SetLabel(optionTxt[i], 0);
optionBtn[i]->SetLabel(optionVal[i], 1);
optionBtn[i]->SetImageOver(optionBg[i]);
optionBtn[i]->SetPosition(0,30*i+3);
optionBtn[i]->SetTrigger(trigA);
optionBtn[i]->SetSoundClick(btnSoundClick);
}
}
/**
* Destructor for the GuiOptionBrowser class.
*/
GuiOptionBrowser::~GuiOptionBrowser()
{
delete arrowUpBtn;
delete arrowDownBtn;
delete scrollbarBoxBtn;
delete bgOptionsImg;
delete scrollbarImg;
delete arrowDownImg;
delete arrowDownOverImg;
delete arrowUpImg;
delete arrowUpOverImg;
delete scrollbarBoxImg;
delete scrollbarBoxOverImg;
delete bgOptions;
delete bgOptionsEntry;
delete scrollbar;
delete arrowDown;
delete arrowDownOver;
delete arrowUp;
delete arrowUpOver;
delete scrollbarBox;
delete scrollbarBoxOver;
delete trigA;
delete btnSoundOver;
delete btnSoundClick;
for(int i=0; i<PAGESIZE; i++)
{
delete optionTxt[i];
delete optionVal[i];
delete optionBg[i];
delete optionBtn[i];
}
}
void GuiOptionBrowser::SetCol2Position(int x)
{
for(int i=0; i<PAGESIZE; i++)
optionVal[i]->SetPosition(x,0);
}
void GuiOptionBrowser::SetFocus(int f)
{
focus = f;
for(int i=0; i<PAGESIZE; i++)
optionBtn[i]->ResetState();
if(f == 1)
optionBtn[selectedItem]->SetState(STATE_SELECTED);
}
void GuiOptionBrowser::ResetState()
{
if(state != STATE_DISABLED)
state = STATE_DEFAULT;
for(int i=0; i<PAGESIZE; i++)
{
optionBtn[i]->ResetState();
}
}
int GuiOptionBrowser::GetClickedOption()
{
int found = -1;
for(int i=0; i<PAGESIZE; i++)
{
if(optionBtn[i]->GetState() == STATE_CLICKED)
{
optionBtn[i]->SetState(STATE_SELECTED);
found = optionIndex[i];
break;
}
}
return found;
}
/****************************************************************************
* FindMenuItem
*
* Help function to find the next visible menu item on the list
***************************************************************************/
int GuiOptionBrowser::FindMenuItem(int currentItem, int direction)
{
int nextItem = currentItem + direction;
if(nextItem < 0 || nextItem >= options->length)
return -1;
if(strlen(options->name[nextItem]) > 0)
return nextItem;
else
return FindMenuItem(nextItem, direction);
}
/**
* Draw the button on screen
*/
void GuiOptionBrowser::Draw()
{
if(!this->IsVisible())
return;
bgOptionsImg->Draw();
int next = listOffset;
for(int i=0; i<PAGESIZE; i++)
{
if(next >= 0)
{
optionBtn[i]->Draw();
next = this->FindMenuItem(next, 1);
}
else
break;
}
scrollbarImg->Draw();
arrowUpBtn->Draw();
arrowDownBtn->Draw();
scrollbarBoxBtn->Draw();
this->UpdateEffects();
}
void GuiOptionBrowser::Update(GuiTrigger * t)
{
if(state == STATE_DISABLED || !t)
return;
int next, prev;
// update the location of the scroll box based on the position in the option list
int position = 136*(listOffset+selectedItem)/options->length;
if(position > 130)
position = 136;
scrollbarBoxBtn->SetPosition(0,position+36);
arrowUpBtn->Update(t);
arrowDownBtn->Update(t);
scrollbarBoxBtn->Update(t);
next = listOffset;
for(int i=0; i<PAGESIZE; i++)
{
if(next >= 0)
{
if(optionBtn[i]->GetState() == STATE_DISABLED)
{
optionBtn[i]->SetVisible(true);
optionBtn[i]->SetState(STATE_DEFAULT);
}
optionTxt[i]->SetText(options->name[next]);
optionVal[i]->SetText(options->value[next]);
optionIndex[i] = next;
next = this->FindMenuItem(next, 1);
}
else
{
optionBtn[i]->SetVisible(false);
optionBtn[i]->SetState(STATE_DISABLED);
}
if(focus)
{
if(i != selectedItem && optionBtn[i]->GetState() == STATE_SELECTED)
optionBtn[i]->ResetState();
else if(i == selectedItem && optionBtn[i]->GetState() == STATE_DEFAULT)
optionBtn[selectedItem]->SetState(STATE_SELECTED);
}
optionBtn[i]->Update(t);
if(optionBtn[i]->GetState() == STATE_SELECTED)
{
selectedItem = i;
}
}
// pad/joystick navigation
if(!focus)
return; // skip navigation
if(t->Down() || arrowDownBtn->GetState() == STATE_CLICKED)
{
next = this->FindMenuItem(optionIndex[selectedItem], 1);
if(next >= 0)
{
if(selectedItem == PAGESIZE-1)
{
// move list down by 1
listOffset = this->FindMenuItem(listOffset, 1);
}
else if(optionBtn[selectedItem+1]->IsVisible())
{
optionBtn[selectedItem]->ResetState();
optionBtn[selectedItem+1]->SetState(STATE_SELECTED);
selectedItem++;
}
}
arrowDownBtn->ResetState();
}
else if(t->Up() || arrowUpBtn->GetState() == STATE_CLICKED)
{
prev = this->FindMenuItem(optionIndex[selectedItem], -1);
if(prev >= 0)
{
if(selectedItem == 0)
{
// move list up by 1
listOffset = prev;
}
else
{
optionBtn[selectedItem]->ResetState();
optionBtn[selectedItem-1]->SetState(STATE_SELECTED);
selectedItem--;
}
}
arrowUpBtn->ResetState();
}
if(updateCB)
updateCB(this);
}

View File

@ -0,0 +1,420 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Tantric February 2009
*
* gui_savebrowser.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
#include "filebrowser.h"
/**
* Constructor for the GuiSaveBrowser class.
*/
GuiSaveBrowser::GuiSaveBrowser(int w, int h, SaveList * s, int a)
{
width = w;
height = h;
saves = s;
action = a;
selectable = true;
if(action == 0) // save
listOffset = 0;
else
listOffset = -2;
selectedItem = 0;
focus = 0; // allow focus
trigA = new GuiTrigger;
if(GCSettings.WiimoteOrientation)
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_2 | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
else
trigA->SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
btnSoundOver = new GuiSound(button_over_pcm, button_over_pcm_size, SOUND_PCM);
btnSoundClick = new GuiSound(button_click_pcm, button_click_pcm_size, SOUND_PCM);
gameSave = new GuiImageData(button_gamesave_png);
gameSaveOver = new GuiImageData(button_gamesave_over_png);
gameSaveBlank = new GuiImageData(button_gamesave_blank_png);
scrollbar = new GuiImageData(scrollbar_png);
scrollbarImg = new GuiImage(scrollbar);
scrollbarImg->SetParent(this);
scrollbarImg->SetAlignment(ALIGN_RIGHT, ALIGN_TOP);
scrollbarImg->SetPosition(0, 30);
arrowDown = new GuiImageData(scrollbar_arrowdown_png);
arrowDownImg = new GuiImage(arrowDown);
arrowDownOver = new GuiImageData(scrollbar_arrowdown_over_png);
arrowDownOverImg = new GuiImage(arrowDownOver);
arrowUp = new GuiImageData(scrollbar_arrowup_png);
arrowUpImg = new GuiImage(arrowUp);
arrowUpOver = new GuiImageData(scrollbar_arrowup_over_png);
arrowUpOverImg = new GuiImage(arrowUpOver);
scrollbarBox = new GuiImageData(scrollbar_box_png);
scrollbarBoxImg = new GuiImage(scrollbarBox);
scrollbarBoxOver = new GuiImageData(scrollbar_box_over_png);
scrollbarBoxOverImg = new GuiImage(scrollbarBoxOver);
arrowUpBtn = new GuiButton(arrowUpImg->GetWidth(), arrowUpImg->GetHeight());
arrowUpBtn->SetParent(this);
arrowUpBtn->SetImage(arrowUpImg);
arrowUpBtn->SetImageOver(arrowUpOverImg);
arrowUpBtn->SetAlignment(ALIGN_RIGHT, ALIGN_TOP);
arrowUpBtn->SetSelectable(false);
arrowUpBtn->SetTrigger(trigA);
arrowUpBtn->SetSoundOver(btnSoundOver);
arrowUpBtn->SetSoundClick(btnSoundClick);
arrowDownBtn = new GuiButton(arrowDownImg->GetWidth(), arrowDownImg->GetHeight());
arrowDownBtn->SetParent(this);
arrowDownBtn->SetImage(arrowDownImg);
arrowDownBtn->SetImageOver(arrowDownOverImg);
arrowDownBtn->SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM);
arrowDownBtn->SetSelectable(false);
arrowDownBtn->SetTrigger(trigA);
arrowDownBtn->SetSoundOver(btnSoundOver);
arrowDownBtn->SetSoundClick(btnSoundClick);
scrollbarBoxBtn = new GuiButton(scrollbarBoxImg->GetWidth(), scrollbarBoxImg->GetHeight());
scrollbarBoxBtn->SetParent(this);
scrollbarBoxBtn->SetImage(scrollbarBoxImg);
scrollbarBoxBtn->SetImageOver(scrollbarBoxOverImg);
scrollbarBoxBtn->SetAlignment(ALIGN_RIGHT, ALIGN_TOP);
scrollbarBoxBtn->SetSelectable(false);
for(int i=0; i<SAVELISTSIZE; i++)
{
saveDate[i] = new GuiText(NULL, 22, (GXColor){0, 0, 0, 0xff});
saveDate[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
saveDate[i]->SetPosition(80,5);
saveTime[i] = new GuiText(NULL, 22, (GXColor){0, 0, 0, 0xff});
saveTime[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
saveTime[i]->SetPosition(80,27);
saveType[i] = new GuiText(NULL, 22, (GXColor){0, 0, 0, 0xff});
saveType[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
saveType[i]->SetPosition(80,50);
saveBgImg[i] = new GuiImage(gameSave);
saveBgOverImg[i] = new GuiImage(gameSaveOver);
savePreviewImg[i] = new GuiImage(gameSaveBlank);
savePreviewImg[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
savePreviewImg[i]->SetPosition(5,0);
saveBtn[i] = new GuiButton(saveBgImg[i]->GetWidth(),saveBgImg[i]->GetHeight());
saveBtn[i]->SetParent(this);
saveBtn[i]->SetLabel(saveDate[i], 0);
saveBtn[i]->SetLabel(saveTime[i], 1);
saveBtn[i]->SetLabel(saveType[i], 2);
saveBtn[i]->SetImage(saveBgImg[i]);
saveBtn[i]->SetImageOver(saveBgOverImg[i]);
saveBtn[i]->SetIcon(savePreviewImg[i]);
saveBtn[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP);
saveBtn[i]->SetPosition(257*(i % 2),87*(i/2));
saveBtn[i]->SetTrigger(trigA);
saveBtn[i]->SetState(STATE_DISABLED);
saveBtn[i]->SetEffectGrow();
saveBtn[i]->SetVisible(false);
saveBtn[i]->SetSoundOver(btnSoundOver);
saveBtn[i]->SetSoundClick(btnSoundClick);
}
}
/**
* Destructor for the GuiSaveBrowser class.
*/
GuiSaveBrowser::~GuiSaveBrowser()
{
delete arrowUpBtn;
delete arrowDownBtn;
delete scrollbarBoxBtn;
delete scrollbarImg;
delete arrowDownImg;
delete arrowDownOverImg;
delete arrowUpImg;
delete arrowUpOverImg;
delete scrollbarBoxImg;
delete scrollbarBoxOverImg;
delete gameSave;
delete gameSaveOver;
delete gameSaveBlank;
delete scrollbar;
delete arrowDown;
delete arrowDownOver;
delete arrowUp;
delete arrowUpOver;
delete scrollbarBox;
delete scrollbarBoxOver;
delete btnSoundOver;
delete btnSoundClick;
delete trigA;
for(int i=0; i<SAVELISTSIZE; i++)
{
delete saveBtn[i];
delete saveDate[i];
delete saveTime[i];
delete saveType[i];
delete saveBgImg[i];
delete saveBgOverImg[i];
delete savePreviewImg[i];
}
}
void GuiSaveBrowser::SetFocus(int f)
{
focus = f;
for(int i=0; i<SAVELISTSIZE; i++)
saveBtn[i]->ResetState();
if(f == 1)
saveBtn[selectedItem]->SetState(STATE_SELECTED);
}
void GuiSaveBrowser::ResetState()
{
if(state != STATE_DISABLED)
state = STATE_DEFAULT;
for(int i=0; i<SAVELISTSIZE; i++)
{
saveBtn[i]->ResetState();
}
}
int GuiSaveBrowser::GetClickedSave()
{
int found = -1;
for(int i=0; i<SAVELISTSIZE; i++)
{
if(saveBtn[i]->GetState() == STATE_CLICKED)
{
saveBtn[i]->SetState(STATE_SELECTED);
found = i;
break;
}
}
return found;
}
/**
* Draw the button on screen
*/
void GuiSaveBrowser::Draw()
{
if(!this->IsVisible())
return;
for(int i=0; i<SAVELISTSIZE; i++)
saveBtn[i]->Draw();
scrollbarImg->Draw();
arrowUpBtn->Draw();
arrowDownBtn->Draw();
scrollbarBoxBtn->Draw();
this->UpdateEffects();
}
void GuiSaveBrowser::Update(GuiTrigger * t)
{
if(state == STATE_DISABLED || !t)
return;
int i, len;
char savetext[50];
// update the location of the scroll box based on the position in the option list
int position;
if(action == 0)
position = 136*(listOffset+selectedItem)/saves->length;
else
position = 136*(listOffset+selectedItem+2)/saves->length;
if(position > 130)
position = 136;
scrollbarBoxBtn->SetPosition(0,position+36);
arrowUpBtn->Update(t);
arrowDownBtn->Update(t);
scrollbarBoxBtn->Update(t);
// pad/joystick navigation
if(!focus)
goto endNavigation; // skip navigation
if(t->Right())
{
if(selectedItem == SAVELISTSIZE-1)
{
if(listOffset + SAVELISTSIZE < saves->length)
{
// move list down by 1 row
listOffset += 2;
selectedItem -= 1;
}
}
else if(saveBtn[selectedItem+1]->IsVisible())
{
saveBtn[selectedItem]->ResetState();
saveBtn[selectedItem+1]->SetState(STATE_SELECTED);
selectedItem += 1;
}
}
else if(t->Left())
{
if(selectedItem == 0)
{
if((listOffset - 2 >= 0 && action == 0) ||
(listOffset - 2 >= -2 && action == 1))
{
// move list up by 1
listOffset -= 2;
selectedItem = SAVELISTSIZE-1;
}
}
else
{
selectedItem -= 1;
}
}
else if(t->Down() || arrowDownBtn->GetState() == STATE_CLICKED)
{
if(selectedItem >= SAVELISTSIZE-2)
{
if(listOffset + SAVELISTSIZE + 1 < saves->length)
{
listOffset += 2;
}
else if(listOffset + SAVELISTSIZE < saves->length)
{
listOffset += 2;
if(selectedItem == SAVELISTSIZE-1)
selectedItem -= 1;
}
}
else if(saveBtn[selectedItem+2]->IsVisible())
{
selectedItem += 2;
}
arrowDownBtn->ResetState();
}
else if(t->Up() || arrowUpBtn->GetState() == STATE_CLICKED)
{
if(selectedItem < 2)
{
if((listOffset - 2 >= 0 && action == 0) ||
(listOffset - 2 >= -2 && action == 1))
{
// move list up by 1
listOffset -= 2;
}
}
else
{
selectedItem -= 2;
}
arrowUpBtn->ResetState();
}
endNavigation:
for(i=0; i<SAVELISTSIZE; i++)
{
if(listOffset+i < 0 && action == 1)
{
saveDate[0]->SetText(NULL);
saveDate[1]->SetText(NULL);
saveTime[0]->SetText("New SRAM");
saveTime[1]->SetText("New Snapshot");
saveType[0]->SetText(NULL);
saveType[1]->SetText(NULL);
savePreviewImg[0]->SetImage(gameSaveBlank);
savePreviewImg[1]->SetImage(gameSaveBlank);
savePreviewImg[0]->SetScale(1);
savePreviewImg[1]->SetScale(1);
saveBtn[0]->SetVisible(true);
saveBtn[1]->SetVisible(true);
if(saveBtn[0]->GetState() == STATE_DISABLED)
saveBtn[0]->SetState(STATE_DEFAULT);
if(saveBtn[1]->GetState() == STATE_DISABLED)
saveBtn[1]->SetState(STATE_DEFAULT);
}
else if(listOffset+i < saves->length)
{
if(saveBtn[i]->GetState() == STATE_DISABLED)
{
saveBtn[i]->SetVisible(true);
saveBtn[i]->SetState(STATE_DEFAULT);
}
saveDate[i]->SetText(saves->date[listOffset+i]);
saveTime[i]->SetText(saves->time[listOffset+i]);
if(saves->type[listOffset+i] == FILE_SRAM)
sprintf(savetext, "SRAM");
else
sprintf(savetext, "Snapshot");
len = strlen(saves->filename[listOffset+i]);
if(len > 10 &&
((saves->filename[listOffset+i][len-8] == 'A' &&
saves->filename[listOffset+i][len-7] == 'u' &&
saves->filename[listOffset+i][len-6] == 't' &&
saves->filename[listOffset+i][len-5] == 'o') ||
saves->filename[listOffset+i][len-5] == '0')
)
{
strcat(savetext, " (Auto)");
}
saveType[i]->SetText(savetext);
if(saves->previewImg[listOffset+i] != NULL)
{
savePreviewImg[i]->SetImage(saves->previewImg[listOffset+i]);
savePreviewImg[i]->SetScale(0.1);
}
else
{
savePreviewImg[i]->SetImage(gameSaveBlank);
savePreviewImg[i]->SetScale(1);
}
}
else
{
saveBtn[i]->SetVisible(false);
saveBtn[i]->SetState(STATE_DISABLED);
}
if(focus)
{
if(i != selectedItem && saveBtn[i]->GetState() == STATE_SELECTED)
saveBtn[i]->ResetState();
else if(i == selectedItem && saveBtn[i]->GetState() == STATE_DEFAULT)
saveBtn[selectedItem]->SetState(STATE_SELECTED);
}
saveBtn[i]->Update(t);
if(saveBtn[i]->GetState() == STATE_SELECTED)
selectedItem = i;
}
if(updateCB)
updateCB(this);
}

View File

@ -0,0 +1,155 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Tantric February 2009
*
* gui_sound.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
/**
* Constructor for the GuiSound class.
*/
GuiSound::GuiSound(const u8 * snd, s32 len, int t)
{
sound = snd;
length = len;
type = t;
voice = -1;
volume = 100;
loop = false;
}
/**
* Destructor for the GuiSound class.
*/
GuiSound::~GuiSound()
{
#ifndef NO_SOUND
if(type == SOUND_OGG)
StopOgg();
#endif
}
void GuiSound::Play()
{
#ifndef NO_SOUND
int vol;
switch(type)
{
case SOUND_PCM:
vol = 255*(volume/100.0)*(GCSettings.SFXVolume/100.0);
voice = ASND_GetFirstUnusedVoice();
if(voice >= 0)
ASND_SetVoice(voice, VOICE_STEREO_16BIT, 48000, 0,
(u8 *)sound, length, vol, vol, NULL);
break;
case SOUND_OGG:
voice = 0;
if(loop)
PlayOgg(mem_open((char *)sound, length), 0, OGG_INFINITE_TIME);
else
PlayOgg(mem_open((char *)sound, length), 0, OGG_ONE_TIME);
SetVolumeOgg(255*(volume/100.0));
break;
}
#endif
}
void GuiSound::Stop()
{
#ifndef NO_SOUND
if(voice < 0)
return;
switch(type)
{
case SOUND_PCM:
ASND_StopVoice(voice);
break;
case SOUND_OGG:
StopOgg();
break;
}
#endif
}
void GuiSound::Pause()
{
#ifndef NO_SOUND
if(voice < 0)
return;
switch(type)
{
case SOUND_PCM:
ASND_PauseVoice(voice, 1);
break;
case SOUND_OGG:
PauseOgg(1);
break;
}
#endif
}
void GuiSound::Resume()
{
#ifndef NO_SOUND
if(voice < 0)
return;
switch(type)
{
case SOUND_PCM:
ASND_PauseVoice(voice, 0);
break;
case SOUND_OGG:
PauseOgg(0);
break;
}
#endif
}
bool GuiSound::IsPlaying()
{
if(ASND_StatusVoice(voice) == SND_WORKING || ASND_StatusVoice(voice) == SND_WAITING)
return true;
else
return false;
}
void GuiSound::SetVolume(int vol)
{
#ifndef NO_SOUND
volume = vol;
if(voice < 0)
return;
int newvol = 255*(volume/100.0)*(GCSettings.SFXVolume/100.0);
switch(type)
{
case SOUND_PCM:
ASND_ChangeVolumeVoice(voice, newvol, newvol);
break;
case SOUND_OGG:
SetVolumeOgg(255*(volume/100.0));
break;
}
#endif
}
void GuiSound::SetLoop(bool l)
{
loop = l;
}

234
source/ngc/gui/gui_text.cpp Normal file
View File

@ -0,0 +1,234 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Tantric February 2009
*
* gui_text.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
static int currentSize = 0;
static int presetSize = 0;
static int presetMaxWidth = 0;
static int presetAlignmentHor = 0;
static int presetAlignmentVert = 0;
static u16 presetStyle = 0;
static GXColor presetColor = (GXColor){255, 255, 255, 255};
/**
* Constructor for the GuiText class.
*/
GuiText::GuiText(const char * t, int s, GXColor c)
{
text = NULL;
size = s;
color = c;
alpha = c.a;
style = FTGX_JUSTIFY_CENTER | FTGX_ALIGN_MIDDLE;
maxWidth = 0;
alignmentHor = ALIGN_CENTRE;
alignmentVert = ALIGN_MIDDLE;
if(t)
text = fontSystem->charToWideChar((char *)t);
}
/**
* Constructor for the GuiText class, uses presets
*/
GuiText::GuiText(const char * t)
{
text = NULL;
size = presetSize;
color = presetColor;
alpha = presetColor.a;
style = presetStyle;
maxWidth = presetMaxWidth;
alignmentHor = presetAlignmentHor;
alignmentVert = presetAlignmentVert;
if(t)
text = fontSystem->charToWideChar((char *)t);
}
/**
* Destructor for the GuiText class.
*/
GuiText::~GuiText()
{
if(text)
{
delete text;
text = NULL;
}
}
void GuiText::SetText(const char * t)
{
if(text)
delete text;
text = NULL;
if(t)
text = fontSystem->charToWideChar((char *)t);
}
void GuiText::SetPresets(int sz, GXColor c, int w, u16 s, int h, int v)
{
presetSize = sz;
presetColor = c;
presetStyle = s;
presetMaxWidth = w;
presetAlignmentHor = h;
presetAlignmentVert = v;
}
void GuiText::SetFontSize(int s)
{
size = s;
}
void GuiText::SetMaxWidth(int w)
{
maxWidth = w;
}
void GuiText::SetColor(GXColor c)
{
color = c;
alpha = c.a;
}
void GuiText::SetStyle(u16 s)
{
style = s;
}
void GuiText::SetAlignment(int hor, int vert)
{
style = 0;
switch(hor)
{
case ALIGN_LEFT:
style |= FTGX_JUSTIFY_LEFT;
break;
case ALIGN_RIGHT:
style |= FTGX_JUSTIFY_RIGHT;
break;
default:
style |= FTGX_JUSTIFY_CENTER;
break;
}
switch(vert)
{
case ALIGN_TOP:
style |= FTGX_ALIGN_TOP;
break;
case ALIGN_BOTTOM:
style |= FTGX_ALIGN_BOTTOM;
break;
default:
style |= FTGX_ALIGN_MIDDLE;
break;
}
alignmentHor = hor;
alignmentVert = vert;
}
/**
* Draw the text on screen
*/
void GuiText::Draw()
{
if(!text)
return;
if(!this->IsVisible())
return;
GXColor c = color;
c.a = this->GetAlpha();
int newSize = size*this->GetScale();
if(newSize != currentSize)
{
fontSystem->changeSize(newSize);
currentSize = newSize;
}
int voffset = 0;
if(alignmentVert == ALIGN_MIDDLE)
voffset = -newSize/2 + 2;
if(maxWidth > 0) // text wrapping
{
int lineheight = newSize + 6;
int strlen = wcslen(text);
int i = 0;
int ch = 0;
int linenum = 0;
int lastSpace = -1;
int lastSpaceIndex = -1;
wchar_t * tmptext[20];
while(ch < strlen)
{
if(i == 0)
tmptext[linenum] = new wchar_t[strlen + 1];
tmptext[linenum][i] = text[ch];
tmptext[linenum][i+1] = 0;
if(text[ch] == ' ' || ch == strlen-1)
{
if(fontSystem->getWidth(tmptext[linenum]) >= maxWidth)
{
if(lastSpace >= 0)
{
tmptext[linenum][lastSpaceIndex] = 0; // discard space, and everything after
ch = lastSpace; // go backwards to the last space
lastSpace = -1; // we have used this space
lastSpaceIndex = -1;
}
linenum++;
i = -1;
}
else if(ch == strlen-1)
{
linenum++;
}
}
if(text[ch] == ' ' && i >= 0)
{
lastSpace = ch;
lastSpaceIndex = i;
}
ch++;
i++;
}
if(alignmentVert == ALIGN_MIDDLE)
voffset = voffset - (lineheight*linenum)/2 + lineheight/2;
for(i=0; i < linenum; i++)
{
fontSystem->drawText(this->GetLeft(), this->GetTop()+voffset+i*lineheight, tmptext[i], c, style);
delete tmptext[i];
}
}
else
{
fontSystem->drawText(this->GetLeft(), this->GetTop()+voffset, text, c, style);
}
this->UpdateEffects();
}

View File

@ -75,6 +75,8 @@ void GuiTrigger::SetButtonOnlyInFocusTrigger(s32 ch, u32 wiibtns, u16 gcbtns)
s8 GuiTrigger::WPAD_Stick(u8 right, int axis)
{
#ifdef HW_RVL
float mag = 0.0;
float ang = 0.0;
@ -117,6 +119,10 @@ s8 GuiTrigger::WPAD_Stick(u8 right, int axis)
val = mag * cos((PI * ang)/180.0f);
return (s8)(val * 128.0f);
#else
return 0;
#endif
}
bool GuiTrigger::Left()
@ -124,7 +130,7 @@ bool GuiTrigger::Left()
u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_UP : WPAD_BUTTON_LEFT;
if((wpad.btns_d | wpad.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_LEFT)
|| pad.btns_d & PAD_BUTTON_LEFT
|| (pad.btns_d | pad.btns_h) & PAD_BUTTON_LEFT
|| pad.stickX < -PADCAL
|| WPAD_Stick(0,0) < -PADCAL)
{
@ -152,7 +158,7 @@ bool GuiTrigger::Right()
u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_DOWN : WPAD_BUTTON_RIGHT;
if((wpad.btns_d | wpad.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_RIGHT)
|| pad.btns_d & PAD_BUTTON_RIGHT
|| (pad.btns_d | pad.btns_h) & PAD_BUTTON_RIGHT
|| pad.stickX > PADCAL
|| WPAD_Stick(0,0) > PADCAL)
{
@ -180,7 +186,7 @@ bool GuiTrigger::Up()
u32 wiibtn = GCSettings.WiimoteOrientation ? WPAD_BUTTON_RIGHT : WPAD_BUTTON_UP;
if((wpad.btns_d | wpad.btns_h) & (wiibtn | WPAD_CLASSIC_BUTTON_UP)
|| pad.btns_d & PAD_BUTTON_UP
|| (pad.btns_d | pad.btns_h) & PAD_BUTTON_UP
|| pad.stickY > PADCAL
|| WPAD_Stick(0,1) > PADCAL)
{

View File

@ -0,0 +1,404 @@
/****************************************************************************
* Snes9x 1.51 Nintendo Wii/Gamecube Port
*
* Tantric February 2009
*
* gui_window.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
GuiWindow::GuiWindow()
{
width = 0;
height = 0;
focus = 0; // allow focus
}
GuiWindow::GuiWindow(int w, int h)
{
width = w;
height = h;
focus = 0; // allow focus
}
GuiWindow::~GuiWindow()
{
}
void GuiWindow::Append(GuiElement* e)
{
if (e == NULL)
return;
Remove(e);
_elements.push_back(e);
e->SetParent(this);
}
void GuiWindow::Insert(GuiElement* e, u32 index)
{
if (e == NULL || index > (_elements.size() - 1))
return;
Remove(e);
_elements.insert(_elements.begin()+index, e);
e->SetParent(this);
}
void GuiWindow::Remove(GuiElement* e)
{
if (e == NULL)
return;
for (u8 i = 0; i < _elements.size(); i++)
{
if(e == _elements.at(i))
{
_elements.erase(_elements.begin()+i);
break;
}
}
}
void GuiWindow::RemoveAll()
{
_elements.clear();
}
GuiElement* GuiWindow::GetGuiElementAt(u32 index) const
{
if (index >= _elements.size())
return NULL;
return _elements.at(index);
}
u32 GuiWindow::GetSize()
{
return _elements.size();
}
void GuiWindow::Draw()
{
if(_elements.size() == 0 || !this->IsVisible())
return;
for (u8 i = 0; i < _elements.size(); i++)
{
try { _elements.at(i)->Draw(); }
catch (exception& e) { }
}
this->UpdateEffects();
if(parentElement && state == STATE_DISABLED)
Menu_DrawRectangle(0,0,screenwidth,screenheight,(GXColor){0xbe, 0xca, 0xd5, 0x70},1);
}
void GuiWindow::ResetState()
{
if(state != STATE_DISABLED)
state = STATE_DEFAULT;
for (u8 i = 0; i < _elements.size(); i++)
{
try { _elements.at(i)->ResetState(); }
catch (exception& e) { }
}
}
void GuiWindow::SetState(int s)
{
state = s;
for (u8 i = 0; i < _elements.size(); i++)
{
try { _elements.at(i)->SetState(s); }
catch (exception& e) { }
}
}
void GuiWindow::SetVisible(bool v)
{
visible = v;
for (u8 i = 0; i < _elements.size(); i++)
{
try { _elements.at(i)->SetVisible(v); }
catch (exception& e) { }
}
}
void GuiWindow::SetFocus(int f)
{
focus = f;
if(f == 1)
this->MoveSelectionVert(1);
else
this->ResetState();
}
void GuiWindow::ChangeFocus(GuiElement* e)
{
if(parentElement)
return; // this is only intended for the main window
for (u8 i = 0; i < _elements.size(); i++)
{
if(e == _elements.at(i))
_elements.at(i)->SetFocus(1);
else if(_elements.at(i)->IsFocused() == 1)
_elements.at(i)->SetFocus(0);
}
}
void GuiWindow::ToggleFocus(GuiTrigger * t)
{
if(parentElement)
return; // this is only intended for the main window
int found = -1;
int newfocus = -1;
u8 i;
// look for currently in focus element
for (i = 0; i < _elements.size(); i++)
{
try
{
if(_elements.at(i)->IsFocused() == 1)
{
found = i;
break;
}
}
catch (exception& e) { }
}
// element with focus not found, try to give focus
if(found == -1)
{
for (i = 0; i < _elements.size(); i++)
{
try
{
if(_elements.at(i)->IsFocused() == 0 && _elements.at(i)->GetState() != STATE_DISABLED) // focus is possible (but not set)
{
_elements.at(i)->SetFocus(1); // give this element focus
break;
}
}
catch (exception& e) { }
}
}
// change focus
else if(t->wpad.btns_d & (WPAD_BUTTON_1 | WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B)
|| t->pad.btns_d & PAD_BUTTON_B)
{
for (i = found; i < _elements.size(); i++)
{
try
{
if(_elements.at(i)->IsFocused() == 0 && _elements.at(i)->GetState() != STATE_DISABLED) // focus is possible (but not set)
{
newfocus = i;
_elements.at(i)->SetFocus(1); // give this element focus
_elements.at(found)->SetFocus(0); // disable focus on other element
break;
}
}
catch (exception& e) { }
}
if(newfocus == -1)
{
for (i = 0; i < found; i++)
{
try
{
if(_elements.at(i)->IsFocused() == 0 && _elements.at(i)->GetState() != STATE_DISABLED) // focus is possible (but not set)
{
_elements.at(i)->SetFocus(1); // give this element focus
_elements.at(found)->SetFocus(0); // disable focus on other element
break;
}
}
catch (exception& e) { }
}
}
}
}
int GuiWindow::GetSelected()
{
// find selected element
int found = -1;
for (u8 i = 0; i < _elements.size(); i++)
{
try
{
if(_elements.at(i)->GetState() == STATE_SELECTED)
{
found = i;
break;
}
}
catch (exception& e) { }
}
return found;
}
// set element to left/right as selected
// there's probably a more clever way to do this, but this way works
void GuiWindow::MoveSelectionHor(int dir)
{
int found = -1;
u16 left = 0;
u16 top = 0;
u8 i = 0;
int selected = this->GetSelected();
if(selected >= 0)
{
left = _elements.at(selected)->GetLeft();
top = _elements.at(selected)->GetTop();
}
// look for a button on the same row, to the left/right
for (i = 0; i < _elements.size(); i++)
{
try
{
if(_elements.at(i)->IsSelectable())
{
if(_elements.at(i)->GetLeft()*dir > left*dir && _elements.at(i)->GetTop() == top)
{
if(found == -1)
found = i;
else if(_elements.at(i)->GetLeft()*dir < _elements.at(found)->GetLeft()*dir)
found = i; // this is a better match
}
}
}
catch (exception& e) { }
}
if(found >= 0)
goto matchfound;
// match still not found, let's try the first button in the next row
for (i = 0; i < _elements.size(); i++)
{
try
{
if(_elements.at(i)->IsSelectable())
{
if(_elements.at(i)->GetTop()*dir > top*dir)
{
if(found == -1)
found = i;
else if(_elements.at(i)->GetTop()*dir < _elements.at(found)->GetTop()*dir)
found = i; // this is a better match
else if(_elements.at(i)->GetTop()*dir == _elements.at(found)->GetTop()*dir
&&
_elements.at(i)->GetLeft()*dir < _elements.at(found)->GetLeft()*dir)
found = i; // this is a better match
}
}
}
catch (exception& e) { }
}
// match found
matchfound:
if(found >= 0)
{
_elements.at(found)->SetState(STATE_SELECTED);
if(selected >= 0)
_elements.at(selected)->ResetState();
}
}
void GuiWindow::MoveSelectionVert(int dir)
{
int found = -1;
u16 left = 0;
u16 top = 0;
u8 i = 0;
int selected = this->GetSelected();
if(selected >= 0)
{
left = _elements.at(selected)->GetLeft();
top = _elements.at(selected)->GetTop();
}
// look for a button above/below, with the least horizontal difference
for (i = 0; i < _elements.size(); i++)
{
try
{
if(_elements.at(i)->IsSelectable())
{
if(_elements.at(i)->GetTop()*dir > top*dir)
{
if(found == -1)
found = i;
else if(_elements.at(i)->GetTop()*dir < _elements.at(found)->GetTop()*dir)
found = i; // this is a better match
else if(_elements.at(i)->GetTop()*dir == _elements.at(found)->GetTop()*dir
&&
abs(_elements.at(i)->GetLeft() - left) <
abs(_elements.at(found)->GetLeft() - left))
found = i;
}
}
}
catch (exception& e) { }
}
if(found >= 0)
goto matchfound;
// match found
matchfound:
if(found >= 0)
{
_elements.at(found)->SetState(STATE_SELECTED);
if(selected >= 0)
_elements.at(selected)->ResetState();
}
}
void GuiWindow::Update(GuiTrigger * t)
{
if(_elements.size() == 0 || (state == STATE_DISABLED && parentElement))
return;
for (u8 i = 0; i < _elements.size(); i++)
{
try { _elements.at(i)->Update(t); }
catch (exception& e) { }
}
this->ToggleFocus(t);
if(focus) // only send actions to this window if it's in focus
{
// pad/joystick navigation
if(t->Right())
this->MoveSelectionHor(1);
else if(t->Left())
this->MoveSelectionHor(-1);
else if(t->Down())
this->MoveSelectionVert(1);
else if(t->Up())
this->MoveSelectionVert(-1);
}
if(updateCB)
updateCB(this);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 750 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 792 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 764 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 842 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 776 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 775 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 546 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 599 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 777 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 700 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 739 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
source/ngc/sounds/enter.ogg Normal file

Binary file not shown.

BIN
source/ngc/sounds/exit.ogg Normal file

Binary file not shown.