diff --git a/source/ngc/gui/gui.h b/source/ngc/gui/gui.h index f0d14e6..441ca97 100644 --- a/source/ngc/gui/gui.h +++ b/source/ngc/gui/gui.h @@ -36,17 +36,21 @@ #include #include #include +#include #include #include +#include #include "pngu/pngu.h" #include "FreeTypeGX.h" #include "vba.h" #include "video.h" -#include "input.h" #include "filelist.h" #include "fileop.h" +#include "input.h" #include "oggplayer.h" +extern FreeTypeGX *fontSystem; + #define SCROLL_INITIAL_DELAY 20 #define SCROLL_LOOP_DELAY 3 #define PAGESIZE 8 @@ -88,6 +92,26 @@ enum IMAGE_DATA }; +enum +{ + TRIGGER_SIMPLE, + TRIGGER_HELD, + TRIGGER_BUTTON_ONLY, + TRIGGER_BUTTON_ONLY_IN_FOCUS +}; + +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; + #define EFFECT_SLIDE_TOP 1 #define EFFECT_SLIDE_BOTTOM 2 #define EFFECT_SLIDE_RIGHT 4 @@ -135,7 +159,61 @@ class GuiSound bool loop; //!< Loop sound playback }; -//!Primary Gui class +//!Menu input trigger management. Determine if action is neccessary based on input data by comparing controller input data to a specific trigger element. +class GuiTrigger +{ + public: + //!Constructor + GuiTrigger(); + //!Destructor + ~GuiTrigger(); + //!Sets a simple trigger. Requires: element is selected, and trigger button is pressed + //!\param ch Controller channel number + //!\param wiibtns Wii controller trigger button(s) - classic controller buttons are considered separately + //!\param gcbtns GameCube controller trigger button(s) + void SetSimpleTrigger(s32 ch, u32 wiibtns, u16 gcbtns); + //!Sets a held trigger. Requires: element is selected, and trigger button is pressed + //!\param ch Controller channel number + //!\param wiibtns Wii controller trigger button(s) - classic controller buttons are considered separately + //!\param gcbtns GameCube controller trigger button(s) + void SetHeldTrigger(s32 ch, u32 wiibtns, u16 gcbtns); + //!Sets a button-only trigger. Requires: Trigger button is pressed + //!\param ch Controller channel number + //!\param wiibtns Wii controller trigger button(s) - classic controller buttons are considered separately + //!\param gcbtns GameCube controller trigger button(s) + void SetButtonOnlyTrigger(s32 ch, u32 wiibtns, u16 gcbtns); + //!Sets a button-only trigger. Requires: trigger button is pressed and parent window of element is in focus + //!\param ch Controller channel number + //!\param wiibtns Wii controller trigger button(s) - classic controller buttons are considered separately + //!\param gcbtns GameCube controller trigger button(s) + void SetButtonOnlyInFocusTrigger(s32 ch, u32 wiibtns, u16 gcbtns); + //!Get X/Y value from Wii Joystick (classic, nunchuk) input + //!\param right Controller stick (left = 0, right = 1) + //!\param axis Controller stick axis (x-axis = 0, y-axis = 1) + //!\return Stick value + s8 WPAD_Stick(u8 right, int axis); + //!Move menu selection left (via pad/joystick). Allows scroll delay and button overriding + //!\return true if selection should be moved left, false otherwise + bool Left(); + //!Move menu selection right (via pad/joystick). Allows scroll delay and button overriding + //!\return true if selection should be moved right, false otherwise + bool Right(); + //!Move menu selection up (via pad/joystick). Allows scroll delay and button overriding + //!\return true if selection should be moved up, false otherwise + bool Up(); + //!Move menu selection down (via pad/joystick). Allows scroll delay and button overriding + //!\return true if selection should be moved down, false otherwise + bool Down(); + + u8 type; //!< trigger type (TRIGGER_SIMPLE, TRIGGER_HELD, TRIGGER_BUTTON_ONLY, TRIGGER_BUTTON_ONLY_IN_FOCUS) + s32 chan; //!< Trigger controller channel (0-3, -1 for all) + WPADData wpad; //!< Wii controller trigger data + PADData pad; //!< GameCube controller trigger data +}; + +extern GuiTrigger userInput[4]; + +//!Primary GUI class. Most other classes inherit from this class. class GuiElement { public: @@ -197,21 +275,24 @@ class GuiElement //!Checks whether or not the element is clickable //!\return true if clickable, false otherwise bool IsClickable(); - //!Checks whether or not the element is draggable - //!\return true if draggable, false otherwise - bool IsDraggable(); + //!Checks whether or not the element is holdable + //!\return true if holdable, false otherwise + bool IsHoldable(); //!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); - //!Sets whether or not the element is draggable - //!\param c Draggable - void SetDraggable(bool d); + //!Sets whether or not the element is holdable + //!\param c Holdable + void SetHoldable(bool d); //!Gets the element's current state //!\return state int GetState(); + //!Gets the controller channel that last changed the element's state + //!\return Channel number (0-3, -1 = no channel) + int GetStateChan(); //!Sets the element's alpha value //!\param a alpha value void SetAlpha(int a); @@ -275,11 +356,12 @@ class GuiElement //!\param v Visibility (true = visible) virtual void SetVisible(bool v); //!Sets the element's focus - //!\param v Focus (true = in focus) + //!\param f 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); + //!\param s State (STATE_DEFAULT, STATE_SELECTED, STATE_CLICKED, STATE_DISABLED) + //!\param c Controller channel (0-3, -1 = none) + virtual void SetState(int s, int c = -1); //!Resets the element's state to STATE_DEFAULT virtual void ResetState(); //!Gets whether or not the element is in STATE_SELECTED @@ -324,7 +406,7 @@ class GuiElement int stateChan; //!< Which controller channel is responsible for the last change in state 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) - bool draggable; //!< Whether or not this element is draggable (can change to HELD state) + bool holdable; //!< Whether or not this element is holdable (can change to HELD 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 @@ -401,8 +483,7 @@ class GuiWindow : public GuiElement std::vector _elements; //!< Contains all elements within the GuiWindow }; -//!Converts image data into GX-useable RGBA8 -//!Currently designed for use only with PNG files +//!Converts image data into GX-useable RGBA8. Currently designed for use only with PNG files class GuiImageData { public: @@ -427,11 +508,13 @@ class GuiImageData int width; //!< Width of image }; -//!Display, manage, and manipulate images in the Gui +//!Display, manage, and manipulate images in the GUI class GuiImage : public GuiElement { public: //!Constructor + GuiImage(); + //!\overload //!\param img Pointer to GuiImageData element GuiImage(GuiImageData * img); //!\overload @@ -492,7 +575,7 @@ class GuiImage : public GuiElement int stripe; //!< Alpha value (0-255) to apply a stripe effect to the texture }; -//!Display, manage, and manipulate text in the Gui +//!Display, manage, and manipulate text in the GUI class GuiText : public GuiElement { public: @@ -546,8 +629,7 @@ class GuiText : public GuiElement 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) +//!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: @@ -563,29 +645,46 @@ class GuiButton : public GuiElement //!Sets the button's image on over //!\param i Pointer to GuiImage object void SetImageOver(GuiImage* i); + //!Sets the button's image on hold + //!\param i Pointer to GuiImage object + void SetImageHold(GuiImage* i); + //!Sets the button's image on click + //!\param i Pointer to GuiImage object + void SetImageClick(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 icon on hold + //!\param i Pointer to GuiImage object + void SetIconHold(GuiImage* i); + //!Sets the button's icon on click + //!\param i Pointer to GuiImage object + void SetIconClick(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); + //!\param n Index of label to set (optional, default is 0) + void SetLabel(GuiText* t, int n = 0); //!Sets the button's label on over (eg: different colored text) //!\param t Pointer to GuiText object - void SetLabelOver(GuiText* t); - //!\overload + //!\param n Index of label to set (optional, default is 0) + void SetLabelOver(GuiText* t, int n = 0); + //!Sets the button's label on hold //!\param t Pointer to GuiText object - //!\param n Index of label to set - void SetLabelOver(GuiText* t, int n); + //!\param n Index of label to set (optional, default is 0) + void SetLabelHold(GuiText* t, int n = 0); + //!Sets the button's label on click + //!\param t Pointer to GuiText object + //!\param n Index of label to set (optional, default is 0) + void SetLabelClick(GuiText* t, int n = 0); //!Sets the sound to play on over //!\param s Pointer to GuiSound object void SetSoundOver(GuiSound * s); + //!Sets the sound to play on hold + //!\param s Pointer to GuiSound object + void SetSoundHold(GuiSound * s); //!Sets the sound to play on click //!\param s Pointer to GuiSound object void SetSoundClick(GuiSound * s); @@ -595,64 +694,71 @@ class GuiButton : public GuiElement //!\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 * image; //!< Button image (default) + GuiImage * imageOver; //!< Button image for STATE_SELECTED + GuiImage * imageHold; //!< Button image for STATE_HELD + GuiImage * imageClick; //!< Button image for STATE_CLICKED 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 + GuiImage * iconOver; //!< Button icon for STATE_SELECTED + GuiImage * iconHold; //!< Button icon for STATE_HELD + GuiImage * iconClick; //!< Button icon for STATE_CLICKED + GuiText * label[3]; //!< Label(s) to display (default) + GuiText * labelOver[3]; //!< Label(s) to display for STATE_SELECTED + GuiText * labelHold[3]; //!< Label(s) to display for STATE_HELD + GuiText * labelClick[3]; //!< Label(s) to display for STATE_CLICKED + GuiSound * soundOver; //!< Sound to play for STATE_SELECTED + GuiSound * soundHold; //!< Sound to play for STATE_HELD + GuiSound * soundClick; //!< Sound to play for STATE_CLICKED }; -//!Display a list of files -class GuiFileBrowser : public GuiElement +typedef struct _keytype { + char ch, chShift; +} Key; + +//!On-screen keyboard +class GuiKeyboard : public GuiWindow { public: - GuiFileBrowser(int w, int h); - ~GuiFileBrowser(); - void ResetState(); - void SetFocus(int f); - void Draw(); - void TriggerUpdate(); + GuiKeyboard(char * t, u32 m); + ~GuiKeyboard(); void Update(GuiTrigger * t); - GuiButton * gameList[PAGESIZE]; + char kbtextstr[256]; 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; + 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; - GuiTrigger * trigHeldA; }; typedef struct _optionlist { @@ -777,54 +883,55 @@ class GuiSaveBrowser : public GuiElement GuiTrigger * trigA; }; -typedef struct _keytype { - char ch, chShift; -} Key; - -//!On-screen keyboard -class GuiKeyboard : public GuiWindow +//!Display a list of files +class GuiFileBrowser : public GuiElement { public: - GuiKeyboard(char * t, u32 m); - ~GuiKeyboard(); + GuiFileBrowser(int w, int h); + ~GuiFileBrowser(); + void ResetState(); + void SetFocus(int f); + void Draw(); + void TriggerUpdate(); void Update(GuiTrigger * t); - char kbtextstr[256]; + GuiButton * gameList[PAGESIZE]; 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; + 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; + GuiTrigger * trigHeldA; }; #endif + diff --git a/source/ngc/gui/gui_button.cpp b/source/ngc/gui/gui_button.cpp index 51b3fed..16299b4 100644 --- a/source/ngc/gui/gui_button.cpp +++ b/source/ngc/gui/gui_button.cpp @@ -19,18 +19,26 @@ GuiButton::GuiButton(int w, int h) height = h; image = NULL; imageOver = NULL; + imageHold = NULL; + imageClick = NULL; icon = NULL; iconOver = NULL; + iconHold = NULL; + iconClick = NULL; for(int i=0; i < 3; i++) { label[i] = NULL; labelOver[i] = NULL; + labelHold[i] = NULL; + labelClick[i] = NULL; } soundOver = NULL; + soundHold = NULL; soundClick = NULL; selectable = true; + holdable = false; clickable = true; } @@ -44,63 +52,71 @@ GuiButton::~GuiButton() void GuiButton::SetImage(GuiImage* img) { image = img; - - if(img) - img->SetParent(this); + if(img) img->SetParent(this); } void GuiButton::SetImageOver(GuiImage* img) { imageOver = img; - - if(img) - img->SetParent(this); + if(img) img->SetParent(this); +} +void GuiButton::SetImageHold(GuiImage* img) +{ + imageHold = img; + if(img) img->SetParent(this); +} +void GuiButton::SetImageClick(GuiImage* img) +{ + imageClick = img; + if(img) img->SetParent(this); } void GuiButton::SetIcon(GuiImage* img) { icon = img; - - if(img) - img->SetParent(this); + if(img) img->SetParent(this); } void GuiButton::SetIconOver(GuiImage* img) { iconOver = img; - - if(img) - img->SetParent(this); + if(img) img->SetParent(this); } -void GuiButton::SetLabel(GuiText* txt) +void GuiButton::SetIconHold(GuiImage* img) { - label[0] = txt; - - if(txt) - txt->SetParent(this); + iconHold = img; + if(img) img->SetParent(this); } -void GuiButton::SetLabelOver(GuiText* txt) +void GuiButton::SetIconClick(GuiImage* img) { - labelOver[0] = txt; - - if(txt) - txt->SetParent(this); + iconClick = img; + if(img) img->SetParent(this); } void GuiButton::SetLabel(GuiText* txt, int n) { label[n] = txt; - - if(txt) - txt->SetParent(this); + if(txt) txt->SetParent(this); } void GuiButton::SetLabelOver(GuiText* txt, int n) { labelOver[n] = txt; - - if(txt) - txt->SetParent(this); + if(txt) txt->SetParent(this); +} +void GuiButton::SetLabelHold(GuiText* txt, int n) +{ + labelHold[n] = txt; + if(txt) txt->SetParent(this); +} +void GuiButton::SetLabelClick(GuiText* txt, int n) +{ + labelClick[n] = txt; + if(txt) txt->SetParent(this); } void GuiButton::SetSoundOver(GuiSound * snd) { soundOver = snd; } +void GuiButton::SetSoundHold(GuiSound * snd) +{ + soundHold = snd; +} void GuiButton::SetSoundClick(GuiSound * snd) { soundClick = snd; @@ -151,7 +167,7 @@ void GuiButton::Update(GuiTrigger * t) { if(state == STATE_DEFAULT) // we weren't on the button before! { - state = STATE_SELECTED; + this->SetState(STATE_SELECTED, t->chan); if(this->Rumble()) rumbleRequest[t->chan] = 1; @@ -170,8 +186,8 @@ void GuiButton::Update(GuiTrigger * t) } else { - if(state == STATE_SELECTED) - state = STATE_DEFAULT; + if(state == STATE_SELECTED && (stateChan == t->chan || stateChan == -1)) + this->ResetState(); if(effectTarget == effectTargetOver && effectAmount == effectAmountOver) { @@ -187,17 +203,18 @@ void GuiButton::Update(GuiTrigger * t) // button triggers if(this->IsClickable()) { + s32 wm_btns, wm_btns_trig, cc_btns, cc_btns_trig; 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; + wm_btns = t->wpad.btns_d << 16; + 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; + cc_btns = t->wpad.btns_d >> 16; + cc_btns_trig = trigger[i]->wpad.btns_d >> 16; if( (t->wpad.btns_d > 0 && @@ -205,47 +222,64 @@ void GuiButton::Update(GuiTrigger * t) (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) + if(t->chan == stateChan || stateChan == -1) { - state = STATE_CLICKED; + if(state == STATE_SELECTED) + { + this->SetState(STATE_CLICKED, t->chan); - 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(soundClick) + soundClick->Play(); + } + else if(trigger[i]->type == TRIGGER_BUTTON_ONLY) + { + this->SetState(STATE_CLICKED, t->chan); + } + else if(trigger[i]->type == TRIGGER_BUTTON_ONLY_IN_FOCUS && + parentElement->IsFocused()) + { + this->SetState(STATE_CLICKED, t->chan); + } } } } } } - if(this->IsDraggable()) + if(this->IsHoldable()) { bool held = false; + s32 wm_btns, wm_btns_h, wm_btns_trig, cc_btns, cc_btns_h, cc_btns_trig; 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_h << 16; - s32 wm_btns_trig = trigger[i]->wpad.btns_h << 16; + wm_btns = t->wpad.btns_d << 16; + wm_btns_h = t->wpad.btns_h << 16; + wm_btns_trig = trigger[i]->wpad.btns_h << 16; // lower 16 bits only (classic controller) - s32 cc_btns = t->wpad.btns_h >> 16; - s32 cc_btns_trig = trigger[i]->wpad.btns_h >> 16; + cc_btns = t->wpad.btns_d >> 16; + cc_btns_h = t->wpad.btns_h >> 16; + cc_btns_trig = trigger[i]->wpad.btns_h >> 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_h && t->pad.btns_d > 0)) + { + if(trigger[i]->type == TRIGGER_HELD && state == STATE_SELECTED && + (t->chan == stateChan || stateChan == -1)) + this->SetState(STATE_CLICKED, t->chan); + } if( (t->wpad.btns_h > 0 && - wm_btns == wm_btns_trig || - (cc_btns == cc_btns_trig && t->wpad.exp.type == EXP_CLASSIC)) || + wm_btns_h == wm_btns_trig || + (cc_btns_h == cc_btns_trig && t->wpad.exp.type == EXP_CLASSIC)) || (t->pad.btns_h == trigger[i]->pad.btns_h && t->pad.btns_h > 0)) { if(trigger[i]->type == TRIGGER_HELD) @@ -254,12 +288,11 @@ void GuiButton::Update(GuiTrigger * t) if(!held && state == STATE_HELD && stateChan == t->chan) { - state = STATE_DEFAULT; + this->ResetState(); } - else if(held && state == STATE_SELECTED) + else if(held && state == STATE_CLICKED && stateChan == t->chan) { - state = STATE_HELD; - stateChan = t->chan; // record which controller is holding the button + this->SetState(STATE_HELD, t->chan); } } } diff --git a/source/ngc/gui/gui_element.cpp b/source/ngc/gui/gui_element.cpp index 87d030e..d6575d7 100644 --- a/source/ngc/gui/gui_element.cpp +++ b/source/ngc/gui/gui_element.cpp @@ -33,7 +33,7 @@ GuiElement::GuiElement() rumble = true; selectable = false; clickable = false; - draggable = false; + holdable = false; visible = true; focus = -1; // cannot be focused updateCB = NULL; @@ -268,15 +268,24 @@ int GuiElement::GetState() return state; } -void GuiElement::SetState(int s) +int GuiElement::GetStateChan() +{ + return stateChan; +} + +void GuiElement::SetState(int s, int c) { state = s; + stateChan = c; } void GuiElement::ResetState() { if(state != STATE_DISABLED) + { state = STATE_DEFAULT; + stateChan = -1; + } } void GuiElement::SetClickable(bool c) @@ -289,9 +298,9 @@ void GuiElement::SetSelectable(bool s) selectable = s; } -void GuiElement::SetDraggable(bool d) +void GuiElement::SetHoldable(bool d) { - draggable = d; + holdable = d; } bool GuiElement::IsSelectable() @@ -312,12 +321,12 @@ bool GuiElement::IsClickable() return clickable; } -bool GuiElement::IsDraggable() +bool GuiElement::IsHoldable() { if(state == STATE_DISABLED) return false; else - return draggable; + return holdable; } void GuiElement::SetFocus(int f) diff --git a/source/ngc/gui/gui_filebrowser.cpp b/source/ngc/gui/gui_filebrowser.cpp index 2f6a588..d46a7a8 100644 --- a/source/ngc/gui/gui_filebrowser.cpp +++ b/source/ngc/gui/gui_filebrowser.cpp @@ -71,7 +71,9 @@ GuiFileBrowser::GuiFileBrowser(int w, int h) arrowUpBtn->SetImageOver(arrowUpOverImg); arrowUpBtn->SetAlignment(ALIGN_RIGHT, ALIGN_TOP); arrowUpBtn->SetSelectable(false); - arrowUpBtn->SetTrigger(trigA); + arrowUpBtn->SetClickable(false); + arrowUpBtn->SetHoldable(true); + arrowUpBtn->SetTrigger(trigHeldA); arrowUpBtn->SetSoundOver(btnSoundOver); arrowUpBtn->SetSoundClick(btnSoundClick); @@ -81,7 +83,9 @@ GuiFileBrowser::GuiFileBrowser(int w, int h) arrowDownBtn->SetImageOver(arrowDownOverImg); arrowDownBtn->SetAlignment(ALIGN_RIGHT, ALIGN_BOTTOM); arrowDownBtn->SetSelectable(false); - arrowDownBtn->SetTrigger(trigA); + arrowDownBtn->SetClickable(false); + arrowDownBtn->SetHoldable(true); + arrowDownBtn->SetTrigger(trigHeldA); arrowDownBtn->SetSoundOver(btnSoundOver); arrowDownBtn->SetSoundClick(btnSoundClick); @@ -94,7 +98,7 @@ GuiFileBrowser::GuiFileBrowser(int w, int h) scrollbarBoxBtn->SetMaxY(304); scrollbarBoxBtn->SetSelectable(false); scrollbarBoxBtn->SetClickable(false); - scrollbarBoxBtn->SetDraggable(true); + scrollbarBoxBtn->SetHoldable(true); scrollbarBoxBtn->SetTrigger(trigHeldA); for(int i=0; iSetPosition(0,position+36); - arrowUpBtn->Update(t); arrowDownBtn->Update(t); scrollbarBoxBtn->Update(t); - if(scrollbarBoxBtn->GetState() == STATE_HELD) + // move the file listing to respond to wiimote cursor movement + if(scrollbarBoxBtn->GetState() == STATE_HELD && + scrollbarBoxBtn->GetStateChan() == t->chan && + t->wpad.ir.valid && + browser.numEntries > PAGESIZE + ) { - // move the file listing to respond to wiimote cursor movement - if(t->wpad.ir.valid) + scrollbarBoxBtn->SetPosition(0,0); + position = t->wpad.ir.y - 60 - scrollbarBoxBtn->GetTop(); + + if(position < scrollbarBoxBtn->GetMinY()) + position = scrollbarBoxBtn->GetMinY(); + else if(position > scrollbarBoxBtn->GetMaxY()) + position = scrollbarBoxBtn->GetMaxY(); + + browser.pageIndex = (position * browser.numEntries)/136.0 - selectedItem; + + if(browser.pageIndex <= 0) { - scrollbarBoxBtn->SetPosition(0,0); - position = t->wpad.ir.y - 60 - scrollbarBoxBtn->GetTop(); - - if(position > scrollbarBoxBtn->GetMinY() && - position < scrollbarBoxBtn->GetMaxY()) - { - scrollbarBoxBtn->SetPosition(0, position); - browser.pageIndex = (position * browser.numEntries)/136.0 - selectedItem; - - if(browser.pageIndex <= 0) - { - browser.pageIndex = 0; - selectedItem = 0; - } - else if(browser.pageIndex+PAGESIZE >= browser.numEntries) - { - browser.pageIndex = browser.numEntries-PAGESIZE; - selectedItem = PAGESIZE-1; - } - listChanged = true; - } + browser.pageIndex = 0; + selectedItem = 0; } + else if(browser.pageIndex+PAGESIZE >= browser.numEntries) + { + browser.pageIndex = browser.numEntries-PAGESIZE; + selectedItem = PAGESIZE-1; + } + listChanged = true; } // pad/joystick navigation @@ -259,7 +261,16 @@ void GuiFileBrowser::Update(GuiTrigger * t) listChanged = false; } - if(t->Right() || arrowDownBtn->GetState() == STATE_CLICKED) + if(arrowDownBtn->GetState() == STATE_CLICKED && arrowDownBtn->GetStateChan() == t->chan) + t->wpad.btns_d |= WPAD_BUTTON_DOWN; + else if(arrowUpBtn->GetState() == STATE_CLICKED && arrowUpBtn->GetStateChan() == t->chan) + t->wpad.btns_d |= WPAD_BUTTON_UP; + else if(arrowDownBtn->GetState() == STATE_HELD && arrowDownBtn->GetStateChan() == t->chan) + t->wpad.btns_h |= WPAD_BUTTON_DOWN; + else if(arrowUpBtn->GetState() == STATE_HELD && arrowUpBtn->GetStateChan() == t->chan) + t->wpad.btns_h |= WPAD_BUTTON_UP; + + if(t->Right()) { if(browser.pageIndex < browser.numEntries && browser.numEntries > PAGESIZE) { @@ -268,9 +279,8 @@ void GuiFileBrowser::Update(GuiTrigger * t) browser.pageIndex = browser.numEntries-PAGESIZE; listChanged = true; } - arrowDownBtn->ResetState(); } - else if(t->Left() || arrowUpBtn->GetState() == STATE_CLICKED) + else if(t->Left()) { if(browser.pageIndex > 0) { @@ -279,7 +289,6 @@ void GuiFileBrowser::Update(GuiTrigger * t) browser.pageIndex = 0; listChanged = true; } - arrowUpBtn->ResetState(); } else if(t->Down()) { @@ -294,7 +303,7 @@ void GuiFileBrowser::Update(GuiTrigger * t) else if(gameList[selectedItem+1]->IsVisible()) { gameList[selectedItem]->ResetState(); - gameList[++selectedItem]->SetState(STATE_SELECTED); + gameList[++selectedItem]->SetState(STATE_SELECTED, t->chan); } } } @@ -309,7 +318,7 @@ void GuiFileBrowser::Update(GuiTrigger * t) else if(selectedItem > 0) { gameList[selectedItem]->ResetState(); - gameList[--selectedItem]->SetState(STATE_SELECTED); + gameList[--selectedItem]->SetState(STATE_SELECTED, t->chan); } } @@ -351,7 +360,7 @@ void GuiFileBrowser::Update(GuiTrigger * t) 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[selectedItem]->SetState(STATE_SELECTED, t->chan); } gameList[i]->Update(t); @@ -363,6 +372,13 @@ void GuiFileBrowser::Update(GuiTrigger * t) } } + // update the location of the scroll box based on the position in the file list + if(listChanged) + { + position = 136*(browser.pageIndex + selectedItem) / browser.numEntries; + scrollbarBoxBtn->SetPosition(0,position+36); + } + listChanged = false; if(updateCB) diff --git a/source/ngc/gui/gui_image.cpp b/source/ngc/gui/gui_image.cpp index d976f27..426eb97 100644 --- a/source/ngc/gui/gui_image.cpp +++ b/source/ngc/gui/gui_image.cpp @@ -12,6 +12,16 @@ /** * Constructor for the GuiImage class. */ +GuiImage::GuiImage() +{ + image = NULL; + width = 0; + height = 0; + imageangle = 0; + tile = -1; + stripe = 0; + imgType = IMAGE_DATA; +} GuiImage::GuiImage(GuiImageData * img) { diff --git a/source/ngc/gui/gui_keyboard.cpp b/source/ngc/gui/gui_keyboard.cpp index b792e99..6f74158 100644 --- a/source/ngc/gui/gui_keyboard.cpp +++ b/source/ngc/gui/gui_keyboard.cpp @@ -248,7 +248,7 @@ void GuiKeyboard::Update(GuiTrigger * t) for (u8 i = 0; i < _elements.size(); i++) { try { _elements.at(i)->Update(t); } - catch (exception& e) { } + catch (const std::exception& e) { } } if(keySpace->GetState() == STATE_CLICKED) @@ -258,23 +258,23 @@ void GuiKeyboard::Update(GuiTrigger * t) kbtextstr[strlen(kbtextstr)] = ' '; kbText->SetText(kbtextstr); } - keySpace->SetState(STATE_SELECTED); + keySpace->SetState(STATE_SELECTED, t->chan); } else if(keyBack->GetState() == STATE_CLICKED) { kbtextstr[strlen(kbtextstr)-1] = 0; kbText->SetText(kbtextstr); - keyBack->SetState(STATE_SELECTED); + keyBack->SetState(STATE_SELECTED, t->chan); } else if(keyShift->GetState() == STATE_CLICKED) { shift ^= 1; - keyShift->SetState(STATE_SELECTED); + keyShift->SetState(STATE_SELECTED, t->chan); } else if(keyCaps->GetState() == STATE_CLICKED) { caps ^= 1; - keyCaps->SetState(STATE_SELECTED); + keyCaps->SetState(STATE_SELECTED, t->chan); } char txt[2] = { 0, 0 }; @@ -307,7 +307,7 @@ void GuiKeyboard::Update(GuiTrigger * t) } } kbText->SetText(kbtextstr); - keyBtn[i][j]->SetState(STATE_SELECTED); + keyBtn[i][j]->SetState(STATE_SELECTED, t->chan); } } } diff --git a/source/ngc/gui/gui_optionbrowser.cpp b/source/ngc/gui/gui_optionbrowser.cpp index 1c220a0..8499175 100644 --- a/source/ngc/gui/gui_optionbrowser.cpp +++ b/source/ngc/gui/gui_optionbrowser.cpp @@ -170,7 +170,10 @@ void GuiOptionBrowser::SetFocus(int f) void GuiOptionBrowser::ResetState() { if(state != STATE_DISABLED) + { state = STATE_DEFAULT; + stateChan = -1; + } for(int i=0; iGetState() == STATE_SELECTED) optionBtn[i]->ResetState(); else if(i == selectedItem && optionBtn[i]->GetState() == STATE_DEFAULT) - optionBtn[selectedItem]->SetState(STATE_SELECTED); + optionBtn[selectedItem]->SetState(STATE_SELECTED, t->chan); } optionBtn[i]->Update(t); @@ -319,7 +322,7 @@ void GuiOptionBrowser::Update(GuiTrigger * t) else if(optionBtn[selectedItem+1]->IsVisible()) { optionBtn[selectedItem]->ResetState(); - optionBtn[selectedItem+1]->SetState(STATE_SELECTED); + optionBtn[selectedItem+1]->SetState(STATE_SELECTED, t->chan); selectedItem++; } } @@ -339,7 +342,7 @@ void GuiOptionBrowser::Update(GuiTrigger * t) else { optionBtn[selectedItem]->ResetState(); - optionBtn[selectedItem-1]->SetState(STATE_SELECTED); + optionBtn[selectedItem-1]->SetState(STATE_SELECTED, t->chan); selectedItem--; } } diff --git a/source/ngc/gui/gui_savebrowser.cpp b/source/ngc/gui/gui_savebrowser.cpp index d3a8dc7..bdf8693 100644 --- a/source/ngc/gui/gui_savebrowser.cpp +++ b/source/ngc/gui/gui_savebrowser.cpp @@ -186,7 +186,10 @@ void GuiSaveBrowser::SetFocus(int f) void GuiSaveBrowser::ResetState() { if(state != STATE_DISABLED) + { state = STATE_DEFAULT; + stateChan = -1; + } for(int i=0; iIsVisible()) { saveBtn[selectedItem]->ResetState(); - saveBtn[selectedItem+1]->SetState(STATE_SELECTED); + saveBtn[selectedItem+1]->SetState(STATE_SELECTED, t->chan); selectedItem += 1; } } @@ -406,7 +409,7 @@ void GuiSaveBrowser::Update(GuiTrigger * t) 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[selectedItem]->SetState(STATE_SELECTED, t->chan); } saveBtn[i]->Update(t); diff --git a/source/ngc/gui/gui_trigger.cpp b/source/ngc/gui/gui_trigger.cpp index 1a14c97..e0a2020 100644 --- a/source/ngc/gui/gui_trigger.cpp +++ b/source/ngc/gui/gui_trigger.cpp @@ -160,7 +160,8 @@ bool GuiTrigger::Left() } else { - scrollDelay--; + if(scrollDelay > 0) + scrollDelay--; } } return false; @@ -188,7 +189,8 @@ bool GuiTrigger::Right() } else { - scrollDelay--; + if(scrollDelay > 0) + scrollDelay--; } } return false; @@ -216,7 +218,8 @@ bool GuiTrigger::Up() } else { - scrollDelay--; + if(scrollDelay > 0) + scrollDelay--; } } return false; @@ -244,7 +247,8 @@ bool GuiTrigger::Down() } else { - scrollDelay--; + if(scrollDelay > 0) + scrollDelay--; } } return false; diff --git a/source/ngc/gui/gui_window.cpp b/source/ngc/gui/gui_window.cpp index 6de39ad..6da58fd 100644 --- a/source/ngc/gui/gui_window.cpp +++ b/source/ngc/gui/gui_window.cpp @@ -88,7 +88,7 @@ void GuiWindow::Draw() for (u8 i = 0; i < _elements.size(); i++) { try { _elements.at(i)->Draw(); } - catch (exception& e) { } + catch (const std::exception& e) { } } this->UpdateEffects(); @@ -105,7 +105,7 @@ void GuiWindow::ResetState() for (u8 i = 0; i < _elements.size(); i++) { try { _elements.at(i)->ResetState(); } - catch (exception& e) { } + catch (const std::exception& e) { } } } @@ -116,7 +116,7 @@ void GuiWindow::SetState(int s) for (u8 i = 0; i < _elements.size(); i++) { try { _elements.at(i)->SetState(s); } - catch (exception& e) { } + catch (const std::exception& e) { } } } @@ -127,7 +127,7 @@ void GuiWindow::SetVisible(bool v) for (u8 i = 0; i < _elements.size(); i++) { try { _elements.at(i)->SetVisible(v); } - catch (exception& e) { } + catch (const std::exception& e) { } } } @@ -175,7 +175,7 @@ void GuiWindow::ToggleFocus(GuiTrigger * t) break; } } - catch (exception& e) { } + catch (const std::exception& e) { } } // element with focus not found, try to give focus @@ -191,7 +191,7 @@ void GuiWindow::ToggleFocus(GuiTrigger * t) break; } } - catch (exception& e) { } + catch (const std::exception& e) { } } } // change focus @@ -210,7 +210,7 @@ void GuiWindow::ToggleFocus(GuiTrigger * t) break; } } - catch (exception& e) { } + catch (const std::exception& e) { } } if(newfocus == -1) @@ -226,7 +226,7 @@ void GuiWindow::ToggleFocus(GuiTrigger * t) break; } } - catch (exception& e) { } + catch (const std::exception& e) { } } } } @@ -246,7 +246,7 @@ int GuiWindow::GetSelected() break; } } - catch (exception& e) { } + catch (const std::exception& e) { } } return found; } @@ -284,7 +284,7 @@ void GuiWindow::MoveSelectionHor(int dir) } } } - catch (exception& e) { } + catch (const std::exception& e) { } } if(found >= 0) goto matchfound; @@ -309,7 +309,7 @@ void GuiWindow::MoveSelectionHor(int dir) } } } - catch (exception& e) { } + catch (const std::exception& e) { } } // match found @@ -358,7 +358,7 @@ void GuiWindow::MoveSelectionVert(int dir) } } } - catch (exception& e) { } + catch (const std::exception& e) { } } if(found >= 0) goto matchfound; @@ -381,7 +381,7 @@ void GuiWindow::Update(GuiTrigger * t) for (u8 i = 0; i < _elements.size(); i++) { try { _elements.at(i)->Update(t); } - catch (exception& e) { } + catch (const std::exception& e) { } } this->ToggleFocus(t); diff --git a/source/ngc/input.cpp b/source/ngc/input.cpp index 6e5df6f..f65d8c0 100644 --- a/source/ngc/input.cpp +++ b/source/ngc/input.cpp @@ -1,7 +1,7 @@ /**************************************************************************** * Visual Boy Advance GX * - * Tantric September 2008 + * Tantric 2008-2009 * * input.cpp * diff --git a/source/ngc/input.h b/source/ngc/input.h index f43a5ad..e83ba28 100644 --- a/source/ngc/input.h +++ b/source/ngc/input.h @@ -1,7 +1,7 @@ /**************************************************************************** * Visual Boy Advance GX * - * Tantric September 2008 + * Tantric 2008-2009 * * input.h * @@ -14,9 +14,9 @@ #include #include -#define PI 3.14159265f -#define PADCAL 50 -#define MAXJP 10 // # of mappable controller buttons +#define PI 3.14159265f +#define PADCAL 50 +#define MAXJP 10 // # of mappable controller buttons #define VBA_BUTTON_A 1 #define VBA_BUTTON_B 2 @@ -31,48 +31,6 @@ #define VBA_SPEED 1024 #define VBA_CAPTURE 2048 -enum -{ - TRIGGER_SIMPLE, - TRIGGER_HELD, - TRIGGER_BUTTON_ONLY, - TRIGGER_BUTTON_ONLY_IN_FOCUS -}; - -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; - -class GuiTrigger -{ - public: - GuiTrigger(); - ~GuiTrigger(); - void SetSimpleTrigger(s32 ch, u32 wiibtns, u16 gcbtns); - void SetHeldTrigger(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; -}; - -extern GuiTrigger userInput[4]; extern int rumbleRequest[4]; extern u32 btnmap[5][10]; diff --git a/source/ngc/menu.cpp b/source/ngc/menu.cpp index 4aff6ed..2527b1d 100644 --- a/source/ngc/menu.cpp +++ b/source/ngc/menu.cpp @@ -263,7 +263,7 @@ UpdateGUI (void *arg) Menu_Render(); - for(int i=0; i < 4; i++) + for(int i=3; i >= 0; i--) mainWindow->Update(&userInput[i]); #ifdef HW_RVL @@ -1236,7 +1236,8 @@ static int MenuGame() if(WPAD_Probe(i, NULL) == WPAD_ERR_NONE) // controller connected { level = (userInput[i].wpad.battery_level / 100.0) * 4; - batteryBarImg[i]->SetTile(level); + if(level > 4) level = 4; + batteryBarImg[i]->SetTile(level); if(level == 0) batteryImg[i]->SetImage(&batteryRed);