usbloadergx/source/libwiigui/gui_element.cpp
giantpune 9e79c9d99b * remove little unused code
* code cleanup
2010-09-18 23:16:05 +00:00

841 lines
19 KiB
C++
Raw Blame History

/****************************************************************************
* libwiigui
*
* Tantric 2009
*
* gui_element.cpp
*
* GUI class definitions
***************************************************************************/
#include "gui.h"
/**
* Constructor for the Object class.
*/
//mutex_t GuiElement::mutex = LWP_MUTEX_NULL;
mutex_t GuiElement::_lock_mutex = LWP_MUTEX_NULL;
GuiElement::GuiElement()
{
xoffset = 0;
yoffset = 0;
zoffset = 0;
xmin = 0;
xmax = 0;
ymin = 0;
ymax = 0;
width = 0;
height = 0;
alpha = 255;
scale = 1;
state = STATE_DEFAULT;
stateChan = -1;
trigger[0] = NULL;
trigger[1] = NULL;
trigger[2] = NULL;
trigger[3] = NULL;
trigger[4] = NULL;
trigger[5] = NULL;
parentElement = NULL;
rumble = true;
selectable = false;
clickable = false;
holdable = false;
visible = true;
focus = -1; // cannot be focused
updateCB = NULL;
yoffsetDyn = 0;
xoffsetDyn = 0;
yoffsetDynFloat = 0;
alphaDyn = -1;
scaleDyn = 1;
effects = 0;
effectAmount = 0;
effectTarget = 0;
effectsOver = 0;
effectAmountOver = 0;
effectTargetOver = 0;
frequency = 0.0f;
changervar = 0;
degree = -90.0f;
circleamount = 360.0f;
Radius = 150;
angleDyn = 0.0f;
anglespeed = 0.0f;
// default alignment - align to top left
alignmentVert = ALIGN_TOP;
alignmentHor = ALIGN_LEFT;
// if(mutex == LWP_MUTEX_NULL) LWP_MutexInit(&mutex, true);
if ( _lock_mutex == LWP_MUTEX_NULL ) LWP_MutexInit( &_lock_mutex, true );
_lock_thread = LWP_THREAD_NULL;
_lock_count = 0;
_lock_queue = LWP_TQUEUE_NULL;
}
/**
* Destructor for the GuiElement class.
*/
GuiElement::~GuiElement()
{
// LWP_MutexDestroy(mutex);
}
void GuiElement::SetParent( GuiElement * e )
{
LOCK( this );
parentElement = e;
}
GuiElement * GuiElement::GetParent()
{
return parentElement;
}
/**
* Get the left position of the GuiElement.
* @see SetLeft()
* @return Left position in pixel.
*/
int GuiElement::GetLeft()
{
int x = 0;
int pWidth = 0;
int pLeft = 0;
if ( parentElement )
{
pWidth = parentElement->GetWidth();
pLeft = parentElement->GetLeft();
}
if ( effects & ( EFFECT_SLIDE_IN | EFFECT_SLIDE_OUT | EFFECT_GOROUND | EFFECT_ROCK_VERTICLE ) )
pLeft += xoffsetDyn;
switch ( alignmentHor )
{
case ALIGN_LEFT:
x = pLeft;
break;
case ALIGN_CENTRE:
x = pLeft + ( pWidth / 2 ) - ( width / 2 );
break;
case ALIGN_RIGHT:
x = pLeft + pWidth - width;
break;
}
return x + xoffset;
}
/**
* Get the top position of the GuiElement.
* @see SetTop()
* @return Top position in pixel.
*/
int GuiElement::GetTop()
{
int y = 0;
int pHeight = 0;
int pTop = 0;
if ( parentElement )
{
pHeight = parentElement->GetHeight();
pTop = parentElement->GetTop();
}
if ( effects & ( EFFECT_SLIDE_IN | EFFECT_SLIDE_OUT | EFFECT_GOROUND | EFFECT_ROCK_VERTICLE ) )
pTop += yoffsetDyn;
switch ( alignmentVert )
{
case ALIGN_TOP:
y = pTop;
break;
case ALIGN_MIDDLE:
y = pTop + ( pHeight / 2 ) - ( height / 2 );
break;
case ALIGN_BOTTOM:
y = pTop + pHeight - height;
break;
}
return y + yoffset;
}
void GuiElement::SetMinX( int x )
{
LOCK( this );
xmin = x;
}
int GuiElement::GetMinX()
{
return xmin;
}
void GuiElement::SetMaxX( int x )
{
LOCK( this );
xmax = x;
}
int GuiElement::GetMaxX()
{
return xmax;
}
void GuiElement::SetMinY( int y )
{
LOCK( this );
ymin = y;
}
int GuiElement::GetMinY()
{
return ymin;
}
void GuiElement::SetMaxY( int y )
{
LOCK( this );
ymax = y;
}
int GuiElement::GetMaxY()
{
return ymax;
}
/**
* Get the width of the GuiElement.
* @see SetWidth()
* @return Width of the GuiElement.
*/
int GuiElement::GetWidth()
{
return width;
}
/**
* Get the height of the GuiElement.
* @see SetHeight()
* @return Height of the GuiElement.
*/
int GuiElement::GetHeight()
{
return height;
}
/**
* Set the width and height of the GuiElement.
* @param[in] Width Width in pixel.
* @param[in] Height Height in pixel.
* @see SetWidth()
* @see SetHeight()
*/
void GuiElement::SetSize( int w, int h )
{
LOCK( this );
width = w;
height = h;
}
/**
* Get visible.
* @see SetVisible()
* @return true if visible, false otherwise.
*/
bool GuiElement::IsVisible()
{
return visible;
}
/**
* Set visible.
* @param[in] Visible Set to true to show GuiElement.
* @see IsVisible()
*/
void GuiElement::SetVisible( bool v )
{
LOCK( this );
visible = v;
}
void GuiElement::SetAlpha( int a )
{
LOCK( this );
alpha = a;
}
int GuiElement::GetAlpha()
{
int a;
if ( alphaDyn >= 0 )
a = alphaDyn;
else
a = alpha;
if ( parentElement )
a *= parentElement->GetAlpha() / 255.0;
return a;
}
float GuiElement::GetAngleDyn()
{
float a = 0.0;
if ( angleDyn )
a = angleDyn;
if ( parentElement && !angleDyn )
a = parentElement->GetAngleDyn();
return a;
}
void GuiElement::SetScale( float s )
{
LOCK( this );
scale = s;
}
float GuiElement::GetScale()
{
float s = scale * scaleDyn;
if ( parentElement )
s *= parentElement->GetScale();
return s;
}
int GuiElement::GetState()
{
return state;
}
int GuiElement::GetStateChan()
{
return stateChan;
}
void GuiElement::SetState( int s, int c )
{
LOCK( this );
state = s;
stateChan = c;
}
void GuiElement::ResetState()
{
LOCK( this );
if ( state != STATE_DISABLED )
{
state = STATE_DEFAULT;
stateChan = -1;
}
}
void GuiElement::SetClickable( bool c )
{
LOCK( this );
clickable = c;
}
void GuiElement::SetSelectable( bool s )
{
LOCK( this );
selectable = s;
}
void GuiElement::SetHoldable( bool d )
{
LOCK( this );
holdable = d;
}
bool GuiElement::IsSelectable()
{
if ( state == STATE_DISABLED || state == STATE_CLICKED )
return false;
else
return selectable;
}
bool GuiElement::IsClickable()
{
if ( state == STATE_DISABLED ||
state == STATE_CLICKED ||
state == STATE_HELD )
return false;
else
return clickable;
}
bool GuiElement::IsHoldable()
{
if ( state == STATE_DISABLED )
return false;
else
return holdable;
}
void GuiElement::SetFocus( int f )
{
LOCK( this );
focus = f;
}
int GuiElement::IsFocused()
{
return focus;
}
void GuiElement::SetTrigger( GuiTrigger * t )
{
LOCK( this );
if ( !trigger[0] )
trigger[0] = t;
else if ( !trigger[1] )
trigger[1] = t;
else if ( !trigger[2] )
trigger[2] = t;
else if ( !trigger[3] )
trigger[3] = t;
else if ( !trigger[4] )
trigger[4] = t;
else if ( !trigger[5] )
trigger[5] = t;
else // both were assigned, so we'll just overwrite the first one
trigger[0] = t;
}
void GuiElement::SetTrigger( u8 i, GuiTrigger * t )
{
LOCK( this );
trigger[i] = t;
}
void GuiElement::RemoveTrigger( u8 i )
{
LOCK( this );
trigger[i] = NULL;
}
bool GuiElement::Rumble()
{
return rumble;
}
void GuiElement::SetRumble( bool r )
{
LOCK( this );
rumble = r;
}
int GuiElement::GetEffect()
{
LOCK( this );
return effects;
}
int GuiElement::GetEffectOnOver()
{
LOCK( this );
return effectsOver;
}
float GuiElement::GetFrequency()
{
LOCK( this );
return frequency;
}
void GuiElement::SetEffect( int eff, int speed, f32 circles, int r, f32 startdegree, f32 anglespeedset, int center_x, int center_y )
{
if ( eff & EFFECT_GOROUND )
{
xoffsetDyn = 0; //!position of circle in x
yoffsetDyn = 0; //!position of circle in y
Radius = r; //!radius of the circle
degree = startdegree; //!for example -90 (<28>) to start at top of circle
circleamount = circles; //!circleamoutn in degrees for example 360 for 1 circle
angleDyn = 0.0f; //!this is used by the code to calc the angle
anglespeed = anglespeedset; //!This is anglespeed depending on circle speed 1 is same speed and 0.5 half speed
temp_xoffset = center_x; //!position of center in x
temp_yoffset = center_y; //!position of center in y
}
effects |= eff;
effectAmount = speed; //!Circlespeed
}
void GuiElement::SetEffect( int eff, int amount, int target )
{
LOCK( this );
if ( eff & EFFECT_SLIDE_IN )
{
// these calculations overcompensate a little
if ( eff & EFFECT_SLIDE_TOP )
yoffsetDyn = -screenheight;
else if ( eff & EFFECT_SLIDE_LEFT )
xoffsetDyn = -screenwidth;
else if ( eff & EFFECT_SLIDE_BOTTOM )
yoffsetDyn = screenheight;
else if ( eff & EFFECT_SLIDE_RIGHT )
xoffsetDyn = screenwidth;
}
if ( eff & EFFECT_FADE && amount > 0 )
{
alphaDyn = 0;
}
else if ( eff & EFFECT_FADE && amount < 0 )
{
alphaDyn = alpha;
}
else if ( eff & EFFECT_ROCK_VERTICLE )
{
changervar = 0;
yoffsetDyn = 0;
yoffsetDynFloat = 0.0;
}
effects |= eff;
effectAmount = amount;
effectTarget = target;
}
void GuiElement::SetEffectOnOver( int eff, int amount, int target )
{
LOCK( this );
effectsOver |= eff;
effectAmountOver = amount;
effectTargetOver = target;
}
void GuiElement::SetEffectGrow()
{
SetEffectOnOver( EFFECT_SCALE, 4, 110 );
}
void GuiElement::StopEffect()
{
xoffsetDyn = 0;
yoffsetDyn = 0;
effects = 0;
effectsOver = 0;
effectAmount = 0;
effectAmountOver = 0;
effectTarget = 0;
effectTargetOver = 0;
scaleDyn = 1;
frequency = 0.0f;
changervar = 0;
//angleDyn = 0.0f;
anglespeed = 0.0f;
}
void GuiElement::UpdateEffects()
{
LOCK( this );
if ( effects & ( EFFECT_SLIDE_IN | EFFECT_SLIDE_OUT | EFFECT_GOROUND ) )
{
if ( effects & EFFECT_SLIDE_IN )
{
if ( effects & EFFECT_SLIDE_LEFT )
{
xoffsetDyn += effectAmount;
if ( xoffsetDyn >= 0 )
{
xoffsetDyn = 0;
effects = 0;
}
}
else if ( effects & EFFECT_SLIDE_RIGHT )
{
xoffsetDyn -= effectAmount;
if ( xoffsetDyn <= 0 )
{
xoffsetDyn = 0;
effects = 0;
}
}
else if ( effects & EFFECT_SLIDE_TOP )
{
yoffsetDyn += effectAmount;
if ( yoffsetDyn >= 0 )
{
yoffsetDyn = 0;
effects = 0;
}
}
else if ( effects & EFFECT_SLIDE_BOTTOM )
{
yoffsetDyn -= effectAmount;
if ( yoffsetDyn <= 0 )
{
yoffsetDyn = 0;
effects = 0;
}
}
}
else
{
if ( effects & EFFECT_SLIDE_LEFT )
{
xoffsetDyn -= effectAmount;
if ( xoffsetDyn <= -screenwidth )
effects = 0; // shut off effect
}
else if ( effects & EFFECT_SLIDE_RIGHT )
{
xoffsetDyn += effectAmount;
if ( xoffsetDyn >= screenwidth )
effects = 0; // shut off effect
}
else if ( effects & EFFECT_SLIDE_TOP )
{
yoffsetDyn -= effectAmount;
if ( yoffsetDyn <= -screenheight )
effects = 0; // shut off effect
}
else if ( effects & EFFECT_SLIDE_BOTTOM )
{
yoffsetDyn += effectAmount;
if ( yoffsetDyn >= screenheight )
effects = 0; // shut off effect
}
}
}
if ( effects & EFFECT_GOROUND )
{
//!< check out gui.h for info
xoffset = temp_xoffset;
yoffset = temp_yoffset;
if ( fabs( frequency ) < circleamount )
{
angleDyn = ( frequency + degree + 90.0f ) * anglespeed;
xoffsetDyn = ( int ) lround( ( ( f32 ) Radius ) * cos( ( frequency + degree ) * PI / 180.0f ) );
yoffsetDyn = ( int ) lround( ( ( f32 ) Radius ) * sin( ( frequency + degree ) * PI / 180.0f ) );
frequency += ( ( f32 ) effectAmount ) * 0.01f;
}
else
{
f32 temp_frequency = ( ( effectAmount < 0 ) ? -1.0f : 1.0f ) * circleamount;
angleDyn = ( temp_frequency + degree + 90.0f ) * anglespeed;
xoffsetDyn = ( int ) lround( ( ( f32 ) Radius ) * cos( ( temp_frequency + degree ) * PI / 180.0f ) );
yoffsetDyn = ( int ) lround( ( ( f32 ) Radius ) * sin( ( temp_frequency + degree ) * PI / 180.0f ) );
xoffset += xoffsetDyn;
yoffset += yoffsetDyn;
effects ^= EFFECT_GOROUND;
frequency = 0.0f;
}
}
if ( effects & EFFECT_ROCK_VERTICLE )
{
//move up to 10pixel above 0
if ( changervar == 0 && yoffsetDynFloat < 11.0 )
{
yoffsetDynFloat += ( effectAmount * 0.01 );
}
else if ( yoffsetDynFloat > 10.0 )
{
changervar = 1;
}
//move down till 10pixel under 0
if ( changervar == 1 && yoffsetDynFloat > -11.0 )
{
yoffsetDynFloat -= ( effectAmount * 0.01 );
}
else if ( yoffsetDynFloat < -10.0 )
{
changervar = 0;
}
yoffsetDyn = ( int )( yoffsetDynFloat );
}
if ( effects & EFFECT_FADE )
{
alphaDyn += effectAmount;
if ( effectAmount < 0 && alphaDyn <= 0 )
{
alphaDyn = 0;
effects = 0; // shut off effect
}
else if ( effectAmount > 0 && alphaDyn >= alpha )
{
alphaDyn = alpha;
effects = 0; // shut off effect
}
}
if ( effects & EFFECT_SCALE )
{
scaleDyn += effectAmount / 100.0;
if ( ( effectAmount < 0 && scaleDyn <= effectTarget / 100.0 )
|| ( effectAmount > 0 && scaleDyn >= effectTarget / 100.0 ) )
{
scaleDyn = effectTarget / 100.0;
effects = 0; // shut off effect
}
}
if ( effects & EFFECT_PULSE )
{
int percent = 10; //go down from target by this
if ( ( scaleDyn <= ( effectTarget*0.01 ) ) && ( !changervar ) )
{
scaleDyn += ( effectAmount * 0.001 );
}
else if ( scaleDyn > ( effectTarget*0.01 ) )
{
changervar = 1;
}
if ( ( scaleDyn >= ( ( effectTarget - percent )*0.01 ) ) && ( changervar ) )
{
scaleDyn -= ( effectAmount * 0.001 );
}
else if ( scaleDyn < ( ( effectTarget - percent )*0.01 ) )
{
changervar = 0;
}
}
}
void GuiElement::Update( GuiTrigger * t )
{
LOCK( this );
if ( updateCB )
updateCB( this );
}
void GuiElement::SetUpdateCallback( UpdateCallback u )
{
LOCK( this );
updateCB = u;
}
void GuiElement::SetPosition( int xoff, int yoff, int zoff )
{
LOCK( this );
xoffset = xoff;
yoffset = yoff;
zoffset = zoff;
}
void GuiElement::SetAlignment( int hor, int vert )
{
LOCK( this );
alignmentHor = hor;
alignmentVert = vert;
}
int GuiElement::GetSelected()
{
return -1;
}
/**
* Draw an element on screen.
*/
void GuiElement::Draw()
{
}
/**
* Draw Tooltips on screen.
*/
void GuiElement::DrawTooltip()
{
}
/**
* Check if a position is inside the GuiElement.
* @param[in] x X position in pixel.
* @param[in] y Y position in pixel.
*/
bool GuiElement::IsInside( int x, int y )
{
if ( x > this->GetLeft() && x < ( this->GetLeft() + width )
&& y > this->GetTop() && y < ( this->GetTop() + height ) )
return true;
return false;
}
void GuiElement::Lock()
{
// LWP_MutexLock(mutex);
for ( ;; ) // loop while element is locked by self
{
LWP_MutexLock( _lock_mutex );
if ( _lock_thread == LWP_THREAD_NULL ) // element is not locked
{
_lock_thread = LWP_GetSelf(); // mark as locked
_lock_count = 1; // set count of lock to 1
LWP_MutexUnlock( _lock_mutex );
return;
}
else if ( _lock_thread == LWP_GetSelf() ) // thread is locked by my self
{
_lock_count++; // inc count of locks;
LWP_MutexUnlock( _lock_mutex );
return;
}
else // otherwise the element is locked by an other thread
{
if ( _lock_queue == LWP_TQUEUE_NULL ) // no queue - meens it is the first access to the locked element
LWP_InitQueue( &_lock_queue ); // init queue
LWP_MutexUnlock( _lock_mutex );
LWP_ThreadSleep( _lock_queue ); // and sleep
// try lock again;
}
}
}
void GuiElement::Unlock()
{
// LWP_MutexUnlock(mutex);
LWP_MutexLock( _lock_mutex );
// only the thread was locked this element, can call unlock
if ( _lock_thread == LWP_GetSelf() ) // but we check it here <20> safe is safe
{
if ( --_lock_count == 0 ) // dec count of locks and check if it last lock;
{
_lock_thread = LWP_THREAD_NULL; // mark as unlocked
if ( _lock_queue != LWP_TQUEUE_NULL ) // has a queue
{
LWP_CloseQueue( _lock_queue ); // close the queue and wake all waited threads
_lock_queue = LWP_TQUEUE_NULL;
}
}
}
LWP_MutexUnlock( _lock_mutex );
}
SimpleLock::SimpleLock( GuiElement *e ) : element( e )
{
element->Lock();
}
SimpleLock::~SimpleLock()
{
element->Unlock();
}