2013-12-11 03:23:47 +00:00
# include "SystemView.h"
# include "../SystemData.h"
# include "../Renderer.h"
# include "../Log.h"
2013-12-24 17:50:26 +00:00
# include "../Window.h"
# include "ViewController.h"
2014-02-21 04:20:10 +00:00
# include "../animations/LambdaAnimation.h"
# include "../SystemData.h"
2013-12-11 03:23:47 +00:00
2014-02-21 04:20:10 +00:00
# define SELECTED_SCALE 1.2f
# define LOGO_PADDING (logoSize().x() * (SELECTED_SCALE - 1) / 2)
2013-12-11 03:23:47 +00:00
2014-02-21 04:20:10 +00:00
SystemView : : SystemView ( Window * window ) : IList < SystemViewData , SystemData * > ( window )
2013-12-11 03:23:47 +00:00
{
2014-02-21 04:20:10 +00:00
mCamOffset = 0 ;
2013-12-11 03:23:47 +00:00
2014-02-21 04:20:10 +00:00
setSize ( ( float ) Renderer : : getScreenWidth ( ) , ( float ) Renderer : : getScreenHeight ( ) ) ;
2013-12-11 03:23:47 +00:00
2014-02-21 04:20:10 +00:00
populate ( ) ;
2013-12-11 03:23:47 +00:00
}
2014-02-21 04:20:10 +00:00
void SystemView : : populate ( )
2013-12-11 03:23:47 +00:00
{
2014-02-21 04:20:10 +00:00
mEntries . clear ( ) ;
2013-12-30 23:23:34 +00:00
2014-02-21 04:20:10 +00:00
for ( auto it = SystemData : : sSystemVector . begin ( ) ; it ! = SystemData : : sSystemVector . end ( ) ; it + + )
{
2014-02-25 01:26:58 +00:00
const std : : shared_ptr < ThemeData > & theme = ( * it ) - > getTheme ( ) ;
2014-02-21 04:20:10 +00:00
Entry e ;
e . name = ( * it ) - > getName ( ) ;
e . object = * it ;
2014-01-07 22:57:30 +00:00
2014-02-25 01:26:58 +00:00
// make logo
if ( theme - > getElement ( " system " , " header " , " image " ) )
2014-02-21 04:20:10 +00:00
{
ImageComponent * logo = new ImageComponent ( mWindow ) ;
logo - > setMaxSize ( logoSize ( ) ) ;
logo - > applyTheme ( ( * it ) - > getTheme ( ) , " system " , " header " , ThemeFlags : : PATH ) ;
logo - > setPosition ( ( logoSize ( ) . x ( ) - logo - > getSize ( ) . x ( ) ) / 2 , 0 ) ;
e . data . logo = std : : shared_ptr < GuiComponent > ( logo ) ;
} else {
// no logo in theme; use text
TextComponent * text = new TextComponent ( mWindow ) ;
text - > setFont ( Font : : get ( FONT_SIZE_LARGE ) ) ;
text - > setText ( ( * it ) - > getName ( ) ) ;
text - > setSize ( logoSize ( ) ) ;
text - > setCentered ( true ) ;
e . data . logo = std : : shared_ptr < GuiComponent > ( text ) ;
}
2013-12-30 23:23:34 +00:00
2014-02-25 01:26:58 +00:00
// make title
e . data . title = std : : shared_ptr < TextComponent > ( new TextComponent ( mWindow ) ) ;
e . data . title - > setFont ( Font : : get ( FONT_SIZE_LARGE ) ) ;
e . data . title - > setSize ( mSize . x ( ) , ( float ) FONT_SIZE_LARGE ) ;
e . data . title - > setText ( ( * it ) - > getFullName ( ) ) ;
e . data . title - > setCentered ( true ) ;
2014-02-21 04:20:10 +00:00
2014-02-25 01:26:58 +00:00
// make background
if ( theme - > getElement ( " system " , " systemImage " , " image " ) )
{
e . data . background = std : : shared_ptr < ImageComponent > ( new ImageComponent ( mWindow ) ) ;
e . data . background - > applyTheme ( theme , " system " , " systemImage " , ThemeFlags : : PATH ) ;
e . data . background - > setOpacity ( ( unsigned char ) ( 255 * 0.75f ) ) ; // make it 75% opaque
e . data . background - > setPosition ( ( mSize . x ( ) - e . data . background - > getSize ( ) . x ( ) ) / 2 , ( mSize . y ( ) - e . data . background - > getSize ( ) . y ( ) ) / 2 ) ; // center it (it's drawn at (0, 0))
} else {
e . data . background = nullptr ;
}
2014-02-21 04:20:10 +00:00
this - > add ( e ) ;
2013-12-11 03:23:47 +00:00
}
2014-02-21 04:20:10 +00:00
}
2013-12-11 03:23:47 +00:00
2014-02-21 04:20:10 +00:00
void SystemView : : goToSystem ( SystemData * system )
{
setCursor ( system ) ;
2013-12-11 03:23:47 +00:00
}
2013-12-24 17:50:26 +00:00
bool SystemView : : input ( InputConfig * config , Input input )
{
if ( input . value ! = 0 )
{
if ( config - > isMappedTo ( " left " , input ) )
{
2014-02-21 04:20:10 +00:00
listInput ( - 1 ) ;
2013-12-24 17:50:26 +00:00
return true ;
}
if ( config - > isMappedTo ( " right " , input ) )
{
2014-02-21 04:20:10 +00:00
listInput ( 1 ) ;
2013-12-24 17:50:26 +00:00
return true ;
}
if ( config - > isMappedTo ( " a " , input ) )
{
2014-02-21 04:20:10 +00:00
stopScrolling ( ) ;
mWindow - > getViewController ( ) - > goToGameList ( getSelected ( ) ) ;
2013-12-24 17:50:26 +00:00
return true ;
}
2014-02-21 04:20:10 +00:00
} else {
if ( config - > isMappedTo ( " left " , input ) | | config - > isMappedTo ( " right " , input ) )
listInput ( 0 ) ;
2013-12-24 17:50:26 +00:00
}
return GuiComponent : : input ( config , input ) ;
}
2014-01-25 23:34:29 +00:00
2014-02-21 04:20:10 +00:00
void SystemView : : update ( int deltaTime )
{
listUpdate ( deltaTime ) ;
GuiComponent : : update ( deltaTime ) ;
}
void SystemView : : onCursorChanged ( const CursorState & state )
{
float startPos = mCamOffset ;
2014-02-25 01:26:58 +00:00
float posMax = ( float ) mEntries . size ( ) ;
float target = ( float ) mCursor ;
2014-02-21 04:20:10 +00:00
// what's the shortest way to get to our target?
// it's one of these...
float endPos = target ; // directly
float dist = abs ( endPos - startPos ) ;
if ( abs ( target + posMax - startPos ) < dist )
endPos = target + posMax ; // loop around the end (0 -> max)
if ( abs ( target - posMax - startPos ) < dist )
endPos = target - posMax ; // loop around the start (max - 1 -> -1)
Animation * anim = new LambdaAnimation (
[ startPos , endPos , posMax , this ] ( float t )
{
t - = 1 ;
float f = lerp < float > ( startPos , endPos , t * t * t + 1 ) ;
if ( f < 0 )
f + = posMax ;
if ( f > = posMax )
f - = posMax ;
this - > mCamOffset = f ;
2014-02-25 01:26:58 +00:00
} , 500 ) ;
2014-02-21 04:20:10 +00:00
setAnimation ( anim ) ;
}
void SystemView : : render ( const Eigen : : Affine3f & parentTrans )
{
if ( size ( ) = = 0 )
return ;
Eigen : : Affine3f trans = getTransform ( ) * parentTrans ;
2014-02-25 01:26:58 +00:00
// draw the list elements (titles, backgrounds, logos)
2014-02-21 04:20:10 +00:00
Eigen : : Affine3f logoTrans = trans ;
2014-02-25 01:26:58 +00:00
const float logoSizeX = logoSize ( ) . x ( ) + LOGO_PADDING ;
2014-02-21 04:20:10 +00:00
2014-02-25 01:26:58 +00:00
int logoCount = ( int ) ( mSize . x ( ) / logoSizeX ) + 2 ; // how many logos we need to draw
int center = ( int ) ( mCamOffset ) ;
2014-02-21 04:20:10 +00:00
2014-02-25 01:26:58 +00:00
// draw titles + background images (same transforms)
Eigen : : Affine3f titleTrans = trans ;
for ( int i = center - 1 ; i < center + 2 ; i + + )
2014-02-21 04:20:10 +00:00
{
2014-02-25 01:26:58 +00:00
int index = i ;
while ( index < 0 )
index + = mEntries . size ( ) ;
while ( index > = ( int ) mEntries . size ( ) )
index - = mEntries . size ( ) ;
titleTrans . translation ( ) = trans . translation ( ) + Eigen : : Vector3f ( ( i - mCamOffset ) * mSize . x ( ) , 0 , 0 ) ;
// background image (might not exist)
if ( mEntries . at ( index ) . data . background )
mEntries . at ( index ) . data . background - > render ( titleTrans ) ;
// title (always exists)
mEntries . at ( index ) . data . title - > render ( titleTrans ) ;
2014-02-21 04:20:10 +00:00
}
2014-02-25 01:26:58 +00:00
// draw logos
float xOff = ( mSize . x ( ) - logoSize ( ) . x ( ) ) / 2 - ( mCamOffset * logoSizeX ) ;
float yOff = ( mSize . y ( ) - logoSize ( ) . y ( ) ) / 2 ;
2014-02-21 04:20:10 +00:00
for ( int i = center - logoCount / 2 ; i < center + logoCount / 2 + logoCount % 2 ; i + + )
{
int index = i ;
while ( index < 0 )
index + = mEntries . size ( ) ;
while ( index > = ( int ) mEntries . size ( ) )
index - = mEntries . size ( ) ;
logoTrans . translation ( ) = trans . translation ( ) + Eigen : : Vector3f ( i * logoSizeX + xOff , yOff , 0 ) ;
std : : shared_ptr < GuiComponent > comp = mEntries . at ( index ) . data . logo ;
if ( comp )
{
2014-02-25 01:26:58 +00:00
if ( index = = mCursor ) //scale our selection up
2014-02-21 04:20:10 +00:00
{
// fix the centering because we go by left corner and not center (bleh)
logoTrans . translation ( ) - = Eigen : : Vector3f ( ( comp - > getSize ( ) . x ( ) / 2 ) * ( SELECTED_SCALE - 1 ) , ( comp - > getSize ( ) . y ( ) / 2 ) * ( SELECTED_SCALE - 1 ) , 0 ) ;
logoTrans . scale ( Eigen : : Vector3f ( SELECTED_SCALE , SELECTED_SCALE , 1.0f ) ) ;
mEntries . at ( index ) . data . logo - > render ( logoTrans ) ;
logoTrans . scale ( Eigen : : Vector3f ( 1 / SELECTED_SCALE , 1 / SELECTED_SCALE , 1.0f ) ) ;
} else {
mEntries . at ( index ) . data . logo - > render ( logoTrans ) ;
}
}
}
}
2014-01-25 23:34:29 +00:00
std : : vector < HelpPrompt > SystemView : : getHelpPrompts ( )
{
std : : vector < HelpPrompt > prompts ;
2014-02-21 04:20:10 +00:00
prompts . push_back ( HelpPrompt ( " left/right " , " choose " ) ) ;
2014-01-25 23:34:29 +00:00
prompts . push_back ( HelpPrompt ( " a " , " select " ) ) ;
return prompts ;
}