Changes

Jump to navigation Jump to search
25,209 bytes added ,  20:58, 13 January 2011
m
Corrected small typo
 
== Foreward ==
LibwiiGui is written in C++ and uses classes. Classes are a collection of functions and variables related to a single thing. You work with classes by creating instances of them, called ''objects''. When using these classesobjects, their collected public functions and variables (if they are declared public) can be accessed by a dot (.) in some cases, and an arrow (->) in other cases. This will become more understandable later on in the tutorial, but for now, know that when the class instance object is created with an asterisk (*) before it, you will be using the arrow (->). When , and when the class object is created without the asterisk, you will use the dot (.).
This tutorial uses the same design as the demo included with libwiigui. Every menu is created inside a function. The GUI updating routine is created as a function, and is in a thread. When wanting to change to a knew new menu, you set the menu variable to a value that denotes the menu you wish to change to. Again, this will become more apparent later on.
Lastly, before attempting to read this tutorial (or try to use libwiigui for that matter) you should already have at least a basic understanding of C++, if not more. You can easily find some online tutorials ([http://www.cprogramming.com cprogramming.com], [http://www.cplusplus.com cplusplus.com]) or a book from your local library.
 
== Setting Up ==
You first must have devkitProdevkitPPC. DevkitPro devkitPPC is what allows programmer's to compile their programs for other systems, such as the Wii, PSP, and DS. This should be pretty straight-foreward forward for Windows users. Just [http://www.devkitpro.org/downloads/ download] the latest Windows installer, and go through the installer. When asked what to install, you must install devkitPPC. That allows you to compile for the PowerPC architecture, which the Wii uses. You also will need libOGClibogc, which is the library that lets you program for the Wii. Windows users may skip to the horizontal line below. Linux and Mac users will need to [should follow the instructions at http://sourceforgewiki.devkitpro.netorg/project/showfilesindex.php?group_id=114505 download] devkitPPC and libOGC. Select the appropriate version to download, and put them both in a directory (I would suggest making a devkitpro directory in your home folder and putting both in this folder). In Linux, you will want to edit your bash configuration file to define the DEVKITPRO and DEVKITPPC variables. The following code should do the trick for most linux users: <source lang = "text">sudo gedit /usr/bash.bashrc<Getting_Started/source> Then input your password, and add the following to the top of the file: <source lang = "text">export DEVKITPPC="<path to devkitpro directory>"eport DEVKITPPC="<path to devkitPPC directory>"</source> You also may want to [http://sourceforge.net/project/showfiles.php?group_id=114505 download] the examples from devkitpro. Put these in your devkitpro directory in a folder named examples.
----
If you haven't already done so, [http://code.google.com/p/libwiigui/downloads/list download] libwiigui. You can extract this anywhere, as this is where your source will be for your entire project. You also will need to [http://code.google.com/p/libwiigui/downloads/list download] the required devkitpro libraries. Extract these to your libogc folder (should be devkitPro/libogc) overwriting any existing files.
== Object Creation ==
== Class Creation ==There are two ways an object (an instance of a class) can be created. We will use both methods when working with LibwiiGui. When you want an object to be able to be accessed outside of the function where it was made, you will want to create it with an asterisk, which declares a pointer to your object. You will want to use this approach for your main GuiWindow, which should contain the background and every other window (these other windows will be your menus). You also will want to initially set it to NULL for safety's sake:
There are two ways a class instance can be created. LibwiiGui uses both methods. When you want a class to be able to be accessed by any other function, you will want to create it with an asterisk, which declares a pointer to your class. You will want to use this for your main GuiWindow, which should contain the background, and every other window (these other windows will be your menus). You also will want to initially set it to NULL for safety's sake. <source lang = "c++cpp" >
GuiWindow * mainWindow = NULL;
</source>
These declarations should be at the top of the file, underneath the includes. Then, when using itcalling the object's functions, you will use ->:
<source lang = "c++cpp">mainWindow->Append(image&someElement);
</source>
If you have a class that is only relavent to In the function you above code, we are in (e.g. a menu) you will want adding an object called someElement to declare the instance inside the mainWindow, using mainWindow's Append function:.
If you want an object that is only relevant to the function you are in (e.g. a menu), you will want to declare the instance inside the function: <source lang = "c++cpp">
int menu_function(){
GuiWindow menuwindow;
</source>
and then Then use the dot:(.) to operate on the object
<source lang = "c++cpp">
int menu_function(){
GuiWindow menuwindow;
}
</source>
 
== The GuiElement ==
 
Every LibwiiGui object you create (except for GuiSound, GuiTrigger, and GuiImageData) will inherit from the GuiElement class. This means that you can use any GuiElement function in any GuiElement you use, allowing you to move, get the width of, and get the state of images, buttons, keyboards, option browsers, etc. The GuiElement (from libwiigui/gui.h) class defines the following public functions which you can use with any GuiElement:
 
<source lang = "cpp">
//!Constructor
GuiElement();
 
//!Destructor
~GuiElement();
 
//!Set the element's parent
//!\param e Pointer to parent element
void SetParent(GuiElement * e);
 
//!Gets the element's parent
//!\return Pointer to parent element
GuiElement * GetParent();
 
//!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();
 
//!Sets the minimum y offset of the element
//!\param y Y offset
void SetMinY(int y);
 
//!Gets the minimum y offset of the element
//!\return Minimum Y offset
int GetMinY();
 
//!Sets the maximum y offset of the element
//!\param y Y offset
void SetMaxY(int y);
 
//!Gets the maximum y offset of the element
//!\return Maximum Y offset
int GetMaxY();
 
//!Sets the minimum x offset of the element
//!\param x X offset
void SetMinX(int x);
 
//!Gets the minimum x offset of the element
//!\return Minimum X offset
int GetMinX();
 
//!Sets the maximum x offset of the element
//!\param x X offset
void SetMaxX(int x);
 
//!Gets the maximum x offset of the element
//!\return Maximum X offset
int GetMaxX();
 
//!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();
 
//!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 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);
 
//!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 f Focus (true = in focus)
 
virtual void SetFocus(int f);
 
//!Sets the element's state
 
//!\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
 
//!\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();
</source>
 
Most functions are pretty self-explanatory. Some you will not use often, while others you will be using all the time (such as SetPosition). Remember, you will want to use these functions with the upper-most class you can. For example, if you set GuiImageData to a GuiImage, and then set the GuiImage to a GuiButton, you will want to set the position of the GuiButton, not the GuiImage.
== Your First Image ==
 
Images are created using the GuiImage class. Images can either be loaded from the sd card, or from a buffer. There are quite a few things you will have to do, though, before you can display your image. Open demo.cpp from the libwiigui template.
 
First, we must initialize the video hardware, by using the function from video.cpp. This must be done in any wii application you make, even if you are not going to be displaying any images:
<source lang = "cpp">
InitVideo();
</source>
If you are going to want sound, initilaize the sound hardware also:
<source lang = "cpp">
InitAudio();
</source>
If you are going to be loading images from the sd card (or using the sd card for any other reason), you will need to initialize it:
<source lang="cpp">
fatInitDefault();
</source>
Next, you will need to start the Gui updating thread:
<source lang = "cpp">
InitGUIThreads();
</source>
This is what writes any changes you made to the screen. Last, you would call the function that starts your main menu. In the demo, it is:
<source lang="cpp">
MainMenu(MENU_SETTINGS);
</source>
but it can be whatever you named your menu function.
 
Now, open menu.cpp. Find the MainMenu function. For anything you do in libwiigui, you will want to use "menus" to display anything, except for adding things to the background of your entire GUI, which you will do in the MainMenu function. A menu is simply a function, which should return an int. At the top, declare int menu = MENU_NONE, so if this changes, it will stop your loop later on. At the end of your function, return menu, which will let MainMenu() know which menu to load next.
 
<source lang = "cpp">
int menu_function(){
int menu = MENU_NONE;
//everything else
return menu;
}
</source>
 
To load an image, you declare an instance of the GuiImage class. Unless you are in the MainMenu function, you will want to declare it this way:
<source lang="cpp">
GuiImage image(&ImageData);
</source>
What is the ImageData inside the initializer function? Well before actually creating the image, you must load your image. This can be done by creating an instance of the GuiImageData class:
<source lang="cpp">
GuiImageData imagedata(image_source);
</source>
The image source is your image buffer, where the contents of the image are kept. The image must be in the png format, and have dimensions that are a multiple of 4. To load an image from an sd card to an image buffer, do the following (this is a little more complicated, and is slower anyway, so only use it if necessary) '''Somebody verify this please''':
<source lang="cpp">
const u8 *image_name_png; //define the variables to hold your image file
const u32 image_name_png_size;
size_t amount_read;
FILE *fp = fopen("Path to image on sd card","r"); //open the png file
if(!fp) return; //make sure the file exists
 
fseek (fp , 0 , SEEK_END);
image_name_png_size = ftell(fp); //find the file size
rewind(fp);
 
image_name_png = new u8 [image_name_png_size]; //allocate memory for your image buffer
if(!image_name_png) return; //make sure memory allocated
 
amount_read = fread(image_name_png,1,image_name_png_size,fp); //read file to buffer
if(amount_read != image_size_png_size) return; //make sure it read everything
 
fclose(fp); //close file
</source>
You may be wondering how an image gets loaded into a buffer without the sd card. Whenever you want to add a new image, you must copy the image to the source/images folder, and add it to filelist.h:
<source lang = "cpp">
extern const u8 image_name_png[];
 
extern const u32 image_name_png_size;
</source>
Then your image will be put into the image_name_png buffer when it is compiled. Just place your image in the images folder, and the compiler will take care of the rest for you.
 
Then, you must append your new image to the GuiWindow you are dealing with. Before doing do, you need to suspend the gui thread, so that you are not making changes to variables while the thread is reading them, and resume the thread after appending:
<source lang = "cpp">
HaltGui();
mainWindow->Append(&image);
ResumeGui();
</source>
Unless the image is created as a pointer, you must have the & before it to pass the address of your GuiImage to the Append function.
 
Now, unless you want your menu to display for only a frame or two, you are going to want to keep the menu going somehow. Do this by adding a loop in it, usually a while loop that checks to see if your menu variable has changed:
 
<source lang = "cpp">
while(menu == MENU_NONE){
VIDEO_WaitVSync();
//Other code (you will use this mostly with GuiButtons)
}
</source>
 
Last, you ''must'' remove any GuiElements you have Append()ed in your menu (unless it was declared globally, but you should still remove it) before returning to the MainMenu function, or else the GUI will keep trying to display an image that doesn't exist any more. Use the Remove() function, which takes in a GuiElement:
 
<source lang = "cpp">
mainWindow->Remove(&image);
</source>
 
So that's all it takes to load an image. Easy, right? Here's an example of the complete proccess:
 
''main.cpp:''
<source lang="cpp">
#include <gccore.h>
#include <stdio.h>
#include <stdlib.h>
#include <ogcsys.h>
#include <unistd.h>
#include "FreeTypeGX.h"
#include "video.h"
#include "audio.h"
#include "menu.h"
#include "input.h"
#include "filelist.h"
#include "demo.h"
 
int ExitRequested = 0;
 
void initall(){
InitVideo(); // Initialise video
InitAudio();
InitGUIThreads();
fatInitDefault();
}
 
void ExitApp()
{
ShutoffRumble();
StopGX();
exit(0);
}
 
//---------------------------------------------------------------------------------
 
int main(int argc, char **argv) {
initall();
MainMenu(MAIN_SCREEN);
}
 
 
</source>
 
''menu.cpp:''
<source lang="cpp">
#include <gccore.h>
#include <ogcsys.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <wiiuse/wpad.h>
 
#include "libwiigui/gui.h"
#include "menu.h"
#include "demo.h"
#include "input.h"
#include "filelist.h"
 
static GuiImageData * pointer[4];
static GuiImage * bgImg = NULL;
static GuiSound * bgMusic = NULL;
static GuiWindow * mainWindow = NULL;
static lwp_t guithread = LWP_THREAD_NULL;
static bool guiHalt = true;
 
 
 
static void
ResumeGui()
{
guiHalt = false;
LWP_ResumeThread (guithread);
}
 
 
 
 
static void
HaltGui()
{
guiHalt = true;
 
// wait for thread to finish
while(!LWP_ThreadIsSuspended(guithread))
usleep(50);
}
 
 
 
static void *
UpdateGUI (void *arg)
{
while(1)
{
if(guiHalt)
{
LWP_SuspendThread(guithread);
}
else
{
mainWindow->Draw();
 
#ifdef HW_RVL
for(int i=3; i >= 0; i--) // so that player 1's cursor appears on top!
{
if(userInput[i].wpad.ir.valid)
Menu_DrawImg(userInput[i].wpad.ir.x-48, userInput[i].wpad.ir.y-48,
96, 96, pointer[i]->GetImage(), userInput[i].wpad.ir.angle, 1, 1, 255);
DoRumble(i);
}
#endif
 
Menu_Render();
 
for(int i=0; i < 4; i++)
mainWindow->Update(&userInput[i]);
 
if(ExitRequested)
{
for(int a = 0; a < 255; a += 15)
{
mainWindow->Draw();
Menu_DrawRectangle(0,0,screenwidth,screenheight,(GXColor){0, 0, 0, a},1);
Menu_Render();
}
ExitApp();
}
}
}
return NULL;
}
 
 
 
 
void
InitGUIThreads()
{
LWP_CreateThread (&guithread, UpdateGUI, NULL, NULL, 0, 70);
}
 
 
 
 
 
int MenuDefault(){
 
int menu=MENU_DEFAULT;
GuiImageData image_data(image_png);
GuiImage image(&image_data);
HaltGui();
mainWindow->Append(&image);
ResumeGui();
while(menu==MENU_DEFAULT){
VIDEO_WaitVSync();
}
 
mainWindow->Remove(&image);
return menu;
}
 
MainMenu(){
void MainMenu(int menu)
{
int currentMenu = menu;
 
#ifdef HW_RVL
pointer[0] = new GuiImageData(player1_point_png);
pointer[1] = new GuiImageData(player2_point_png);
pointer[2] = new GuiImageData(player3_point_png);
pointer[3] = new GuiImageData(player4_point_png);
#endif
 
mainWindow = new GuiWindow(screenwidth, screenheight);
 
bgImg = new GuiImage(screenwidth, screenheight, (GXColor){50, 50, 50, 255});
bgImg->ColorStripe(30);
mainWindow->Append(bgImg);
 
GuiTrigger trigA;
trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
 
ResumeGui();
 
bgMusic = new GuiSound(bg_music_ogg, bg_music_ogg_size, SOUND_OGG);
bgMusic->SetVolume(50);
bgMusic->Play(); // startup music
 
while(currentMenu != MENU_EXIT)
{
switch (currentMenu)
{
case MENU_DEFAULT:
currentMenu = MenuDefault();
break;
default: // unrecognized menu
currentMenu = MenuDefault();
break;
}
}
 
ResumeGui();
ExitRequested = 1;
while(1) usleep(50);
 
HaltGui();
 
bgMusic->Stop();
delete bgMusic;
delete bgImg;
delete mainWindow;
 
delete pointer[0];
delete pointer[1];
delete pointer[2];
delete pointer[3];
 
mainWindow = NULL;
}
}
</source>
 
If you want any other menu names (MENU_DEFAULT), you can define them in menu.h:
 
''menu.h''
<source lang="cpp">
#ifndef _MENU_H_
#define _MENU_H_
 
#include <ogcsys.h>
 
void InitGUIThreads();
void MainMenu (int menuitem);
 
enum
{
MENU_EXIT = -1,
MENU_NONE,
MENU_SETTINGS,
MENU_SETTINGS_FILE,
MENU_DEFAULT
};
 
#endif
</source>
 
== Buttons ==
 
Buttons are very useful, as they allow an image (or any other GuiElement) to be "clicked." GuiButtons add the following functions to your initial GuiElement functions:
<source lang = "cpp">
//!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 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
 
//!\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
 
//!\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 (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);
 
//!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);
</source>
Once again, it's pretty self-explanatory. Buttons are simple to create, just remember, you must Append() the ''GuiButton'' to your GuiWindow, not the ''GuiImage''. To create a button, declare an instance of the GuiButton class, giving the address your GuiImage (or another GuiElement) as the argument:
 
<source lang = "cpp">
GuiImage image;
GuiButton button(&image);
</source>
 
Then you can use the button as if it were an image, except you can use SetTrigger, which sets when the button will be considered "clicked." To do this, you must first define a GuiTrigger. A GuiTrigger can be made by declaring an instance, the first argument being the Wiimote channel (use -1 for all), the second being the Wiimote buttons, and the third being the Gamecube buttons. For the buttons, you can do a bitwise-or ( | ) to "add" the buttons together, allowing the trigger to use more than one button.
 
<source lang = "cpp">
GuiTrigger trigA;
trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
</source>
 
Here I am setting a GuiTrigger to trigger when the wiimote button A, classic controller button A, or gamecube button A is clicked.
 
Then, you must set your button's trigger using SetTrigger, giving the address of your GuiTrigger as the only argument:
 
<source lang = "cpp">
button.SetTrigger(&trigA);
</source>
 
Now, if your button is clicked, the GetState function will return STATE_CLICKED:
 
<source lang = "cpp">
if(button.GetState() == STATE_CLICKED){
//Do something because button was clicked
}
</source>
 
 
 
== Program Flow ==
Now that you know a little more about buttons and images, you need to understand how a libwiigui project should be set up. One thing that is confusing for people trying to use libwiigui (or at least it was for me) is that there seem to be two different libraries. This is not true. The bare library is only what is in your libwiigui folder. Everything else (menu.cpp, video.h) is not part of the libwiigui library. They simply lay down the recommended way to effectively use the library. You will not need to worry much about any files except for ''menu.cpp'', ''menu.h'', and ''demo.cpp''.
 
''demo.cpp'' is your main cpp file, where your program starts in. If you want, you can rename this to ''main.cpp'' or something you see fitting. This file will just call a couple functions to initialize things, maybe set a few variables for you, and then calls your MainMenu() function, which takes care of everything else for you (unless you stop the gui for something else).
 
''menu.h'' is what declares a couple of functions, and "enum's" the variables that will "describe" your menus (not exactly, but close enough for us). So both of those files are simple, just a few function calls, and a few declarations.
 
''menu.cpp'' is what contains your entire gui. This is the only file (other than ''filebrowser.cpp'') that actually uses libwiigui. All of this sort of "wraps" libwiigui into a usable form. ''menu.cpp'' will contain your UpdateGui() function. This is what Draw()s any changes you've made, draws the cursor(s) on the screen, and checks if you want to exit (so that it can fade out). UpdateGui() is used by creating a thread that runs UpdateGui(). Threads are what allow two different functions to execute simultaneously (not really, but it gives the illusion of it), so regardless of what you are doing elsewhere, your gui will still be displayed as long as the thread is running. However, threads can cause quite a few problems, one being when a variable is being written to and read from at the same time. To avoid this, you must call HaltGui() before Append()ing anything to the mainWindow. After your done Appending, call ResumeGui() to start the gui back up.
 
Everything that is displayed ''should'' be a part of a "menu" (with a few exceptions, such as snes9gx, which stops the gui when emulating, and starts it when you return to the main menu). A "menu" is not actually defined by libwiigui, rather it is the concept of having images, buttons, and any other GuiElement used grouped together to be displayed at once. These are typically going to be grouped into one GuiWindow that is appended to the mainWindow. A "menu" should follow the following basic outline:
 
<source lang = "cpp">
static int stdmenu(){
int menu = MENU_NONE;
 
///All of the GuiElements here are optional, as you will be doing whatever pertains to your usage
GuiText titleTxt("Menu Title", 28, (GXColor){255, 255, 255, 255});
titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP);
titleTxt.SetPosition(50,50);
 
GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM);
GuiImageData btnOutline(button_png);
GuiImageData btnOutlineOver(button_over_png);
 
GuiTrigger trigA;
trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A);
 
GuiText backBtnTxt("Go Back", 22, (GXColor){0, 0, 0, 255});
GuiImage backBtnImg(&btnOutline);
GuiImage backBtnImgOver(&btnOutlineOver);
GuiButton backBtn(btnOutline.GetWidth(), btnOutline.GetHeight());
backBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
backBtn.SetPosition(100, -35);
backBtn.SetLabel(&backBtnTxt);
backBtn.SetImage(&backBtnImg);
backBtn.SetImageOver(&backBtnImgOver);
backBtn.SetSoundOver(&btnSoundOver);
backBtn.SetTrigger(&trigA);
backBtn.SetEffectGrow();
GuiText okayBtnTxt("Okay", 22, (GXColor){0, 0, 0, 255});
GuiImage okayBtnImg(&btnOutline);
GuiImage okayBtnImgOver(&btnOutlineOver);
GuiButton okayBtn(btnOutline.GetWidth(), btnOutline.GetHeight());
okayBtn.SetAlignment(ALIGN_LEFT, ALIGN_BOTTOM);
okayBtn.SetPosition(300, -35);
okayBtn.SetLabel(&okayBtnTxt);
okayBtn.SetImage(&okayBtnImg);
okayBtn.SetImageOver(&okayBtnImgOver);
okayBtn.SetSoundOver(&btnSoundOver);
okayBtn.SetTrigger(&trigA);
okayBtn.SetEffectGrow();
 
///Here is where you Halt the Gui, and append things. Notice that everything is appended to the GuiWindow w. w is then appended to the mainWindow.
 
HaltGui();
GuiWindow w(screenwidth, screenheight);
w.Append(&backBtn);
w.Append(&okayBtn);
w.Append(&titleTxt);
mainWindow->Append(&w);
ResumeGui();
///This is the loop that keeps the menu running until told to stop
 
 
while(menu == MENU_NONE) //The loop will run until menu is changed
{
VIDEO_WaitVSync (); //Waits for the vertical sync, to reduce flickering
 
if(backBtn.GetState() == STATE_CLICKED) //Checks if you clicked back
{
menu = MENU_EXIT; //stops the loop, and returns MENU_EXIT, which will exit the app
}
if(okayBtn.GetState() == STATE_CLICKED) //Checks if you clicked okay
{
menu = MENU_MAIN; //stops the loop, and returns MENU_MAIN, which will start the main menu
}
}
HaltGui(); //stop the gui
mainWindow->Remove(&w); //remove your window to free memory
return menu; //return the new menu to load
}
</source>
19

edits

Navigation menu