mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-18 09:19:17 +01:00
a66a30a771
*added support to control screen pointer with gc pad or classic controller. you are always able to control as long as the corresponding wii control does not point to the screen (e.g. wiimote 1 not pointing to screen -> gcpad/classic controller 1 can control pointer 1). a speed factor is added to the gui option. need feedback about a proper default value, currently 15% (only tested gc pad on dolphin-emu) *fix reinit of cheatcount on download of new file *moved installation window to be on top of main window *added game installation cancel *added nand extract cancel *added back extract of save feature for a real nand channels *added auto position of progress window messages in vertical direction depending of how many are used at the same time
538 lines
11 KiB
C++
538 lines
11 KiB
C++
/****************************************************************************
|
|
* libwiigui
|
|
*
|
|
* Tantric 2009
|
|
*
|
|
* gui_button.cpp
|
|
*
|
|
* GUI class definitions
|
|
***************************************************************************/
|
|
|
|
#include "gui.h"
|
|
|
|
static int scrollison = 0;
|
|
|
|
/**
|
|
* Constructor for the GuiButton class.
|
|
*/
|
|
|
|
GuiButton::GuiButton(int w, int h)
|
|
{
|
|
width = w;
|
|
height = h;
|
|
image = NULL;
|
|
imageOver = NULL;
|
|
imageHold = NULL;
|
|
imageClick = NULL;
|
|
icon = NULL;
|
|
iconOver = NULL;
|
|
iconHold = NULL;
|
|
iconClick = NULL;
|
|
toolTip = 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;
|
|
|
|
time1 = time2 = 0;
|
|
}
|
|
|
|
GuiButton::GuiButton(GuiImage* img, GuiImage* imgOver, int hor, int vert, int x, int y, GuiTrigger* trig,
|
|
GuiSound* sndOver, GuiSound* sndClick, u8 grow)
|
|
{
|
|
width = img ? img->GetWidth() : 0;
|
|
height = img ? img->GetHeight() : 0;
|
|
image = img;
|
|
if(image) image->SetParent(this);
|
|
imageOver = imgOver;
|
|
if (imageOver) imageOver->SetParent(this);
|
|
imageHold = NULL;
|
|
imageClick = NULL;
|
|
icon = NULL;
|
|
iconOver = NULL;
|
|
iconHold = NULL;
|
|
iconClick = NULL;
|
|
toolTip = NULL;
|
|
alignmentHor = hor;
|
|
alignmentVert = vert;
|
|
xoffset = x;
|
|
yoffset = y;
|
|
trigger[0] = trig;
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
label[i] = NULL;
|
|
labelOver[i] = NULL;
|
|
labelHold[i] = NULL;
|
|
labelClick[i] = NULL;
|
|
}
|
|
|
|
soundOver = sndOver;
|
|
soundHold = NULL;
|
|
soundClick = sndClick;
|
|
selectable = true;
|
|
holdable = false;
|
|
clickable = true;
|
|
|
|
if (grow == 1)
|
|
{
|
|
effectsOver |= EFFECT_SCALE;
|
|
effectAmountOver = 4;
|
|
effectTargetOver = 110;
|
|
}
|
|
time1 = time2 = 0;
|
|
}
|
|
|
|
GuiButton::GuiButton(GuiImage* img, GuiImage* imgOver, int hor, int vert, int x, int y, GuiTrigger* trig,
|
|
GuiSound* sndOver, GuiSound* sndClick, u8 grow, GuiTooltip* tt, int ttx, int tty, int h_align, int v_align)
|
|
{
|
|
width = img ? img->GetWidth() : 0;
|
|
height = img ? img->GetHeight() : 0;
|
|
image = img;
|
|
if(image) image->SetParent(this);
|
|
imageOver = imgOver;
|
|
if (imageOver) imageOver->SetParent(this);
|
|
imageHold = NULL;
|
|
imageClick = NULL;
|
|
icon = NULL;
|
|
iconOver = NULL;
|
|
iconHold = NULL;
|
|
iconClick = NULL;
|
|
toolTip = NULL;
|
|
alignmentHor = hor;
|
|
alignmentVert = vert;
|
|
xoffset = x;
|
|
yoffset = y;
|
|
trigger[0] = trig;
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
label[i] = NULL;
|
|
labelOver[i] = NULL;
|
|
labelHold[i] = NULL;
|
|
labelClick[i] = NULL;
|
|
}
|
|
|
|
soundOver = sndOver;
|
|
soundHold = NULL;
|
|
soundClick = sndClick;
|
|
selectable = true;
|
|
holdable = false;
|
|
clickable = true;
|
|
|
|
if (grow == 1)
|
|
{
|
|
effectsOver |= EFFECT_SCALE;
|
|
effectAmountOver = 4;
|
|
effectTargetOver = 110;
|
|
}
|
|
|
|
toolTip = tt;
|
|
if(toolTip)
|
|
{
|
|
toolTip->SetParent(this);
|
|
toolTip->SetAlignment(h_align, v_align);
|
|
toolTip->SetPosition(ttx, tty);
|
|
}
|
|
|
|
time1 = time2 = 0;
|
|
}
|
|
|
|
/**
|
|
* Destructor for the GuiButton class.
|
|
*/
|
|
GuiButton::~GuiButton()
|
|
{
|
|
}
|
|
|
|
void GuiButton::SetImage(GuiImage* img)
|
|
{
|
|
LOCK( this );
|
|
image = img;
|
|
if (img) img->SetParent(this);
|
|
}
|
|
void GuiButton::SetImageOver(GuiImage* img)
|
|
{
|
|
LOCK( this );
|
|
imageOver = img;
|
|
if (img) img->SetParent(this);
|
|
}
|
|
void GuiButton::SetImageHold(GuiImage* img)
|
|
{
|
|
LOCK( this );
|
|
imageHold = img;
|
|
if (img) img->SetParent(this);
|
|
}
|
|
void GuiButton::SetImageClick(GuiImage* img)
|
|
{
|
|
LOCK( this );
|
|
imageClick = img;
|
|
if (img) img->SetParent(this);
|
|
}
|
|
void GuiButton::SetIcon(GuiImage* img)
|
|
{
|
|
LOCK( this );
|
|
icon = img;
|
|
if (img) img->SetParent(this);
|
|
}
|
|
void GuiButton::SetIconOver(GuiImage* img)
|
|
{
|
|
LOCK( this );
|
|
iconOver = img;
|
|
if (img) img->SetParent(this);
|
|
}
|
|
void GuiButton::SetIconHold(GuiImage* img)
|
|
{
|
|
LOCK( this );
|
|
iconHold = img;
|
|
if (img) img->SetParent(this);
|
|
}
|
|
void GuiButton::SetIconClick(GuiImage* img)
|
|
{
|
|
LOCK( this );
|
|
iconClick = img;
|
|
if (img) img->SetParent(this);
|
|
}
|
|
void GuiButton::SetLabel(GuiText* txt, int n)
|
|
{
|
|
LOCK( this );
|
|
label[n] = txt;
|
|
if (txt) txt->SetParent(this);
|
|
}
|
|
void GuiButton::SetLabelOver(GuiText* txt, int n)
|
|
{
|
|
LOCK( this );
|
|
labelOver[n] = txt;
|
|
if (txt) txt->SetParent(this);
|
|
}
|
|
void GuiButton::SetLabelHold(GuiText* txt, int n)
|
|
{
|
|
LOCK( this );
|
|
labelHold[n] = txt;
|
|
if (txt) txt->SetParent(this);
|
|
}
|
|
void GuiButton::SetLabelClick(GuiText* txt, int n)
|
|
{
|
|
LOCK( this );
|
|
labelClick[n] = txt;
|
|
if (txt) txt->SetParent(this);
|
|
}
|
|
void GuiButton::SetSoundOver(GuiSound * snd)
|
|
{
|
|
LOCK( this );
|
|
soundOver = snd;
|
|
}
|
|
void GuiButton::SetSoundHold(GuiSound * snd)
|
|
{
|
|
LOCK( this );
|
|
soundHold = snd;
|
|
}
|
|
void GuiButton::SetSoundClick(GuiSound * snd)
|
|
{
|
|
LOCK( this );
|
|
soundClick = snd;
|
|
}
|
|
|
|
void GuiButton::SetToolTip(GuiTooltip* tt, int x, int y, int h_align, int v_align)
|
|
{
|
|
LOCK( this );
|
|
if (tt)
|
|
{
|
|
toolTip = tt;
|
|
toolTip->SetParent(this);
|
|
toolTip->SetAlignment(h_align, v_align);
|
|
toolTip->SetPosition(x, y);
|
|
|
|
}
|
|
}
|
|
|
|
void GuiButton::RemoveToolTip()
|
|
{
|
|
LOCK( this );
|
|
toolTip = NULL;
|
|
}
|
|
|
|
void GuiButton::RemoveSoundOver()
|
|
{
|
|
LOCK( this );
|
|
soundOver = NULL;
|
|
}
|
|
void GuiButton::RemoveSoundClick()
|
|
{
|
|
LOCK( this );
|
|
soundClick = NULL;
|
|
}
|
|
void GuiButton::SetSkew(int XX1, int YY1, int XX2, int YY2, int XX3, int YY3, int XX4, int YY4)
|
|
{
|
|
if (image)
|
|
{
|
|
image->xx1 = XX1;
|
|
image->yy1 = YY1;
|
|
image->xx2 = XX2;
|
|
image->yy2 = YY2;
|
|
image->xx3 = XX3;
|
|
image->yy3 = YY3;
|
|
image->xx4 = XX4;
|
|
image->yy4 = YY4;
|
|
}
|
|
}
|
|
|
|
void GuiButton::SetSkew(int *skew)
|
|
{
|
|
if (image) image->SetSkew(skew);
|
|
}
|
|
|
|
void GuiButton::SetState(int s, int c)
|
|
{
|
|
GuiElement::SetState(s, c);
|
|
|
|
if(c < 0 || c > 3)
|
|
return;
|
|
|
|
if (s == STATE_CLICKED)
|
|
{
|
|
POINT p = {0, 0};
|
|
|
|
if (userInput[c].wpad.ir.valid)
|
|
{
|
|
p.x = userInput[c].wpad.ir.x;
|
|
p.y = userInput[c].wpad.ir.y;
|
|
}
|
|
Clicked(this, c, p);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Draw the button on screen
|
|
*/
|
|
void GuiButton::Draw()
|
|
{
|
|
LOCK( this );
|
|
if (!this->IsVisible()) return;
|
|
|
|
// draw image
|
|
if ((state == STATE_SELECTED || state == STATE_HELD) && imageOver)
|
|
imageOver->Draw();
|
|
else if (image) image->Draw();
|
|
// draw icon
|
|
if ((state == STATE_SELECTED || state == STATE_HELD) && iconOver)
|
|
iconOver->Draw();
|
|
else if (icon) icon->Draw();
|
|
// draw text
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
if ((state == STATE_SELECTED || state == STATE_HELD) && labelOver[i])
|
|
labelOver[i]->Draw();
|
|
else if (label[i]) label[i]->Draw();
|
|
}
|
|
|
|
this->UpdateEffects();
|
|
}
|
|
void GuiButton::DrawTooltip()
|
|
{
|
|
LOCK( this );
|
|
if (this->IsVisible() && state == STATE_SELECTED && toolTip)
|
|
{
|
|
if (time2 == 0)
|
|
{
|
|
time(&time1);
|
|
time2 = time1;
|
|
}
|
|
if (time1 != 0) // timer läuft
|
|
time(&time1);
|
|
|
|
if (time1 == 0 || difftime(time1, time2) >= 2)
|
|
{
|
|
if (time1 != 0) // timer gerade abgelaufen
|
|
toolTip->SetEffect(EFFECT_FADE, 20);
|
|
time1 = 0;
|
|
toolTip->Draw();
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (time2 != 0 && time1 == 0) // timer abgelaufen, gerade DESELECT
|
|
if (toolTip) toolTip->SetEffect(EFFECT_FADE, -20);
|
|
time2 = 0;
|
|
}
|
|
if (toolTip && toolTip->GetEffect()) toolTip->Draw();
|
|
}
|
|
void GuiButton::ScrollIsOn(int f)
|
|
{
|
|
scrollison = f;
|
|
}
|
|
|
|
void GuiButton::Update(GuiTrigger * t)
|
|
{
|
|
LOCK( this );
|
|
if (!this->IsVisible() || 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!
|
|
|
|
{
|
|
if ( scrollison == 0 )
|
|
{
|
|
this->SetState( STATE_SELECTED, t->chan );
|
|
}
|
|
|
|
if ( this->Rumble() && scrollison == 0 )
|
|
rumbleRequest[t->chan] = 1;
|
|
|
|
if ( soundOver && scrollison == 0 )
|
|
soundOver->Play();
|
|
|
|
if ( effectsOver && !effects && scrollison == 0 )
|
|
{
|
|
// initiate effects
|
|
effects = effectsOver;
|
|
effectAmount = effectAmountOver;
|
|
effectTarget = effectTargetOver;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( state == STATE_SELECTED && ( stateChan == t->chan || stateChan == -1 ) )
|
|
this->ResetState();
|
|
|
|
if ( effectTarget == effectTargetOver && effectAmount == effectAmountOver )
|
|
{
|
|
// initiate effects (in reverse)
|
|
effects = effectsOver;
|
|
effectAmount = -effectAmountOver;
|
|
effectTarget = 100;
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
|
|
if (state == STATE_SELECTED && (stateChan == t->chan || stateChan == -1)) this->ResetState();
|
|
|
|
if (effectTarget == effectTargetOver && effectAmount == effectAmountOver)
|
|
{
|
|
// initiate effects (in reverse)
|
|
effects = effectsOver;
|
|
effectAmount = -effectAmountOver;
|
|
effectTarget = 100;
|
|
}
|
|
|
|
#endif
|
|
|
|
// button triggers
|
|
if (this->IsClickable() && scrollison == 0)
|
|
{
|
|
s32 wm_btns, wm_btns_trig, cc_btns, cc_btns_trig;
|
|
for (int i = 0; i < 6; i++)
|
|
{
|
|
if (trigger[i] && (trigger[i]->chan == -1 || trigger[i]->chan == t->chan))
|
|
{
|
|
// higher 16 bits only (wiimote)
|
|
wm_btns = t->wpad.btns_d << 16;
|
|
wm_btns_trig = trigger[i]->wpad.btns_d << 16;
|
|
|
|
// lower 16 bits only (classic controller)
|
|
cc_btns = t->wpad.btns_d >> 16;
|
|
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 (t->chan == stateChan || stateChan == -1)
|
|
{
|
|
if (state == STATE_SELECTED)
|
|
{
|
|
this->SetState(STATE_CLICKED, t->chan);
|
|
|
|
if (soundClick) soundClick->Play();
|
|
}
|
|
else if (trigger[i]->type == TRIGGER_BUTTON_ONLY)
|
|
{
|
|
this->SetState(STATE_CLICKED, t->chan);
|
|
if (soundClick) soundClick->Play();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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 < 6; i++)
|
|
{
|
|
if (trigger[i] && (trigger[i]->chan == -1 || trigger[i]->chan == t->chan))
|
|
{
|
|
// higher 16 bits only (wiimote)
|
|
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)
|
|
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_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) held = true;
|
|
}
|
|
|
|
if (!held && state == STATE_HELD && stateChan == t->chan)
|
|
{
|
|
this->ResetState();
|
|
}
|
|
else if (held && state == STATE_CLICKED && stateChan == t->chan)
|
|
{
|
|
this->SetState(STATE_HELD, t->chan);
|
|
}
|
|
else if (held && state == STATE_HELD && Held.connected())
|
|
{
|
|
POINT p = {0, 0};
|
|
|
|
if (userInput[t->chan].wpad.ir.valid)
|
|
{
|
|
p.x = userInput[t->chan].wpad.ir.x;
|
|
p.y = userInput[t->chan].wpad.ir.y;
|
|
}
|
|
Held(this, t->chan, p);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (updateCB) updateCB(this);
|
|
}
|
|
|