Fixed certain menu related graphics loading issues.

Partly implemented menu structure; getting bugs fixed took priority.
This commit is contained in:
Pieter Hulshoff 2018-04-01 21:42:31 +02:00
parent 65aa165404
commit da45a04ae8
22 changed files with 491 additions and 416 deletions

View File

@ -131,6 +131,7 @@ set(RETROFE_HEADERS
"${RETROFE_DIR}/Source/Graphics/FontCache.h" "${RETROFE_DIR}/Source/Graphics/FontCache.h"
"${RETROFE_DIR}/Source/Graphics/PageBuilder.h" "${RETROFE_DIR}/Source/Graphics/PageBuilder.h"
"${RETROFE_DIR}/Source/Graphics/Page.h" "${RETROFE_DIR}/Source/Graphics/Page.h"
"${RETROFE_DIR}/Source/Menu/Menu.h"
"${RETROFE_DIR}/Source/Sound/Sound.h" "${RETROFE_DIR}/Source/Sound/Sound.h"
"${RETROFE_DIR}/Source/Utility/Log.h" "${RETROFE_DIR}/Source/Utility/Log.h"
"${RETROFE_DIR}/Source/Utility/Utils.h" "${RETROFE_DIR}/Source/Utility/Utils.h"
@ -183,6 +184,7 @@ set(RETROFE_SOURCES
"${RETROFE_DIR}/Source/Graphics/Component/VideoBuilder.cpp" "${RETROFE_DIR}/Source/Graphics/Component/VideoBuilder.cpp"
"${RETROFE_DIR}/Source/Graphics/Component/VideoComponent.cpp" "${RETROFE_DIR}/Source/Graphics/Component/VideoComponent.cpp"
"${RETROFE_DIR}/Source/Graphics/Component/Video.cpp" "${RETROFE_DIR}/Source/Graphics/Component/Video.cpp"
"${RETROFE_DIR}/Source/Menu/Menu.cpp"
"${RETROFE_DIR}/Source/Sound/Sound.cpp" "${RETROFE_DIR}/Source/Sound/Sound.cpp"
"${RETROFE_DIR}/Source/Utility/Log.cpp" "${RETROFE_DIR}/Source/Utility/Log.cpp"
"${RETROFE_DIR}/Source/Utility/Utils.cpp" "${RETROFE_DIR}/Source/Utility/Utils.cpp"

View File

@ -34,12 +34,12 @@ public:
void addPlaylists(CollectionInfo *info); void addPlaylists(CollectionInfo *info);
void injectMetadata(CollectionInfo *info); void injectMetadata(CollectionInfo *info);
static bool createCollectionDirectory(std::string collectionName); static bool createCollectionDirectory(std::string collectionName);
bool ImportBasicList(CollectionInfo *info, std::string file, std::vector<Item *> &list);
private: private:
Configuration &conf_; Configuration &conf_;
MetadataDatabase &metaDB_; MetadataDatabase &metaDB_;
bool ImportBasicList(CollectionInfo *info, std::string file, std::map<std::string, Item *> &list); bool ImportBasicList(CollectionInfo *info, std::string file, std::map<std::string, Item *> &list);
bool ImportBasicList(CollectionInfo *info, std::string file, std::vector<Item *> &list);
bool ImportDirectory(CollectionInfo *info, std::string mergedCollectionName); bool ImportDirectory(CollectionInfo *info, std::string mergedCollectionName);
void ImportRomDirectory(std::string path, CollectionInfo *info, std::map<std::string, Item *> includeFilter, std::map<std::string, Item *> excludeFilter, bool romHierarchy); void ImportRomDirectory(std::string path, CollectionInfo *info, std::map<std::string, Item *> includeFilter, std::map<std::string, Item *> excludeFilter, bool romHierarchy);
}; };

View File

@ -63,6 +63,7 @@ bool UserInput::initialize()
MapKey("addPlaylist", KeyCodeAddPlaylist, false); MapKey("addPlaylist", KeyCodeAddPlaylist, false);
MapKey("removePlaylist", KeyCodeRemovePlaylist, false); MapKey("removePlaylist", KeyCodeRemovePlaylist, false);
MapKey("random", KeyCodeRandom, false); MapKey("random", KeyCodeRandom, false);
MapKey("menu", KeyCodeMenu, true);
bool retVal = true; bool retVal = true;
@ -88,6 +89,7 @@ bool UserInput::initialize()
retVal = MapKey("select", KeyCodeSelect) && retVal; retVal = MapKey("select", KeyCodeSelect) && retVal;
retVal = MapKey("back", KeyCodeBack) && retVal; retVal = MapKey("back", KeyCodeBack) && retVal;
retVal = MapKey("quit", KeyCodeQuit) && retVal; retVal = MapKey("quit", KeyCodeQuit) && retVal;
retVal = MapKey("menu", KeyCodeMenu) && retVal;
return retVal; return retVal;
} }

View File

@ -45,6 +45,7 @@ public:
KeyCodeNextPlaylist, KeyCodeNextPlaylist,
KeyCodePrevPlaylist, KeyCodePrevPlaylist,
KeyCodeRandom, KeyCodeRandom,
KeyCodeMenu,
KeyCodeAddPlaylist, KeyCodeAddPlaylist,
KeyCodeRemovePlaylist, KeyCodeRemovePlaylist,
KeyCodeAdminMode, KeyCodeAdminMode,

View File

@ -50,6 +50,7 @@ public:
std::string collectionName; std::string collectionName;
void setMenuScrollReload(bool menuScrollReload); void setMenuScrollReload(bool menuScrollReload);
bool getMenuScrollReload(); bool getMenuScrollReload();
virtual void setInput(std::string text) {};
protected: protected:
Page &page; Page &page;

View File

@ -28,12 +28,13 @@
#include <vector> #include <vector>
#include <iostream> #include <iostream>
ReloadableMedia::ReloadableMedia(Configuration &config, bool systemMode, bool layoutMode, bool commonMode, std::string type, Page &p, int displayOffset, bool isVideo, Font *font, float scaleX, float scaleY) ReloadableMedia::ReloadableMedia(Configuration &config, bool systemMode, bool layoutMode, bool commonMode, bool menuMode, std::string type, Page &p, int displayOffset, bool isVideo, Font *font, float scaleX, float scaleY)
: Component(p) : Component(p)
, config_(config) , config_(config)
, systemMode_(systemMode) , systemMode_(systemMode)
, layoutMode_(layoutMode) , layoutMode_(layoutMode)
, commonMode_(commonMode) , commonMode_(commonMode)
, menuMode_(menuMode)
, loadedComponent_(NULL) , loadedComponent_(NULL)
, videoInst_(NULL) , videoInst_(NULL)
, isVideo_(isVideo) , isVideo_(isVideo)

View File

@ -27,7 +27,7 @@ class Image;
class ReloadableMedia : public Component class ReloadableMedia : public Component
{ {
public: public:
ReloadableMedia(Configuration &config, bool systemMode, bool layoutMode, bool commonMode, std::string type, Page &page, int displayOffset, bool isVideo, Font *font, float scaleX, float scaleY); ReloadableMedia(Configuration &config, bool systemMode, bool layoutMode, bool commonMode, bool menuMode, std::string type, Page &page, int displayOffset, bool isVideo, Font *font, float scaleX, float scaleY);
virtual ~ReloadableMedia(); virtual ~ReloadableMedia();
void update(float dt); void update(float dt);
void draw(); void draw();
@ -43,6 +43,7 @@ private:
bool systemMode_; bool systemMode_;
bool layoutMode_; bool layoutMode_;
bool commonMode_; bool commonMode_;
bool menuMode_;
Component *loadedComponent_; Component *loadedComponent_;
IVideo *videoInst_; IVideo *videoInst_;
bool isVideo_; bool isVideo_;

View File

@ -28,11 +28,12 @@
#include <algorithm> #include <algorithm>
ReloadableScrollingText::ReloadableScrollingText(Configuration &config, bool systemMode, bool layoutMode, std::string type, std::string textFormat, std::string singlePrefix, std::string singlePostfix, std::string pluralPrefix, std::string pluralPostfix, std::string alignment, Page &p, int displayOffset, Font *font, float scaleX, float scaleY, std::string direction, float scrollingSpeed, float startPosition, float startTime, float endTime ) ReloadableScrollingText::ReloadableScrollingText(Configuration &config, bool systemMode, bool layoutMode, bool menuMode, std::string type, std::string textFormat, std::string singlePrefix, std::string singlePostfix, std::string pluralPrefix, std::string pluralPostfix, std::string alignment, Page &p, int displayOffset, Font *font, float scaleX, float scaleY, std::string direction, float scrollingSpeed, float startPosition, float startTime, float endTime )
: Component(p) : Component(p)
, config_(config) , config_(config)
, systemMode_(systemMode) , systemMode_(systemMode)
, layoutMode_(layoutMode) , layoutMode_(layoutMode)
, menuMode_(menuMode)
, fontInst_(font) , fontInst_(font)
, type_(type) , type_(type)
, textFormat_(textFormat) , textFormat_(textFormat)

View File

@ -24,7 +24,7 @@
class ReloadableScrollingText : public Component class ReloadableScrollingText : public Component
{ {
public: public:
ReloadableScrollingText(Configuration &config, bool systemMode, bool layoutMode, std::string type, std::string textFormat, std::string singlePrefix, std::string singlePostfix, std::string pluralPrefix, std::string pluralPostfix, std::string alignment, Page &page, int displayOffset, Font *font, float scaleX, float scaleY, std::string direction, float scrollingSpeed, float startPosition, float startTime, float endTime ); ReloadableScrollingText(Configuration &config, bool systemMode, bool layoutMode, bool menuMode, std::string type, std::string textFormat, std::string singlePrefix, std::string singlePostfix, std::string pluralPrefix, std::string pluralPostfix, std::string alignment, Page &page, int displayOffset, Font *font, float scaleX, float scaleY, std::string direction, float scrollingSpeed, float startPosition, float startTime, float endTime );
virtual ~ReloadableScrollingText( ); virtual ~ReloadableScrollingText( );
void update(float dt); void update(float dt);
void draw( ); void draw( );
@ -39,6 +39,7 @@ private:
Configuration &config_; Configuration &config_;
bool systemMode_; bool systemMode_;
bool layoutMode_; bool layoutMode_;
bool menuMode_;
Font *fontInst_; Font *fontInst_;
std::string type_; std::string type_;
std::string textFormat_; std::string textFormat_;

View File

@ -43,50 +43,53 @@
ScrollingList::ScrollingList( Configuration &c, ScrollingList::ScrollingList( Configuration &c,
Page &p, Page &p,
bool layoutMode, bool layoutMode,
bool commonMode,
float scaleX, float scaleX,
float scaleY, float scaleY,
Font *font, Font *font,
std::string layoutKey, std::string layoutKey,
std::string imageType ) std::string imageType )
: Component(p ) : Component( p )
, horizontalScroll(false ) , horizontalScroll( false )
, layoutMode_(layoutMode ) , layoutMode_( layoutMode )
, spriteList_(NULL ) , commonMode_( commonMode )
, scrollPoints_(NULL ) , spriteList_( NULL )
, tweenPoints_(NULL ) , scrollPoints_( NULL )
, itemIndex_(0 ) , tweenPoints_( NULL )
, selectedOffsetIndex_(0 ) , itemIndex_( 0 )
, scrollAcceleration_(0 ) , selectedOffsetIndex_( 0 )
, startScrollTime_(0.500 ) , scrollAcceleration_( 0 )
, scrollPeriod_(0 ) , startScrollTime_( 0.500 )
, config_(c ) , scrollPeriod_( 0 )
, scaleX_(scaleX ) , config_( c )
, scaleY_(scaleY ) , scaleX_( scaleX )
, fontInst_(font ) , scaleY_( scaleY )
, layoutKey_(layoutKey ) , fontInst_( font )
, imageType_(imageType ) , layoutKey_( layoutKey )
, items_(NULL ) , imageType_( imageType )
, items_( NULL )
{ {
} }
ScrollingList::ScrollingList( const ScrollingList &copy ) ScrollingList::ScrollingList( const ScrollingList &copy )
: Component(copy ) : Component( copy )
, horizontalScroll(copy.horizontalScroll ) , horizontalScroll( copy.horizontalScroll )
, layoutMode_(copy.layoutMode_ ) , layoutMode_( copy.layoutMode_ )
, spriteList_(NULL ) , commonMode_( copy.commonMode_ )
, itemIndex_(0 ) , spriteList_( NULL )
, selectedOffsetIndex_(copy.selectedOffsetIndex_ ) , itemIndex_( 0 )
, scrollAcceleration_(copy.scrollAcceleration_ ) , selectedOffsetIndex_( copy.selectedOffsetIndex_ )
, startScrollTime_(copy.startScrollTime_ ) , scrollAcceleration_( copy.scrollAcceleration_ )
, scrollPeriod_(copy.startScrollTime_ ) , startScrollTime_( copy.startScrollTime_ )
, config_(copy.config_ ) , scrollPeriod_( copy.startScrollTime_ )
, scaleX_(copy.scaleX_ ) , config_( copy.config_ )
, scaleY_(copy.scaleY_ ) , scaleX_( copy.scaleX_ )
, fontInst_(copy.fontInst_ ) , scaleY_( copy.scaleY_ )
, layoutKey_(copy.layoutKey_ ) , fontInst_( copy.fontInst_ )
, imageType_(copy.imageType_ ) , layoutKey_( copy.layoutKey_ )
, items_(NULL ) , imageType_( copy.imageType_ )
, items_( NULL )
{ {
scrollPoints_ = NULL; scrollPoints_ = NULL;
tweenPoints_ = NULL; tweenPoints_ = NULL;
@ -530,20 +533,70 @@ bool ScrollingList::allocateTexture( unsigned int index, Item *item )
std::string layoutName; std::string layoutName;
config_.getProperty( "layout", layoutName ); config_.getProperty( "layout", layoutName );
// check collection path for art based on gamename std::string typeLC = Utils::toLower( imageType_ );
std::vector<std::string> names;
names.push_back( item->name );
names.push_back( item->fullTitle );
if ( item->cloneof != "" )
names.push_back( item->cloneof );
if ( typeLC == "numberbuttons" )
names.push_back( item->numberButtons );
if ( typeLC == "numberplayers" )
names.push_back( item->numberPlayers );
if ( typeLC == "year" )
names.push_back( item->year );
if ( typeLC == "title" )
names.push_back( item->title );
if ( typeLC == "developer" )
{
if ( item->developer == "" )
{
names.push_back( item->manufacturer );
}
else
{
names.push_back( item->developer );
}
}
if ( typeLC == "manufacturer" )
names.push_back( item->manufacturer );
if ( typeLC == "genre" )
names.push_back( item->genre );
if ( typeLC == "ctrltype" )
names.push_back( item->ctrlType );
if ( typeLC == "joyways" )
names.push_back( item->joyWays );
if ( typeLC == "rating" )
names.push_back( item->rating );
if ( typeLC == "score" )
names.push_back( item->score );
names.push_back("default");
for ( unsigned int n = 0; n < names.size() && !t; ++n )
{
// check collection path for art
if ( layoutMode_ ) if ( layoutMode_ )
{ {
if ( commonMode_ )
imagePath = Utils::combinePath(Configuration::absolutePath, "layouts", layoutName, "collections", "_common");
else
imagePath = Utils::combinePath( Configuration::absolutePath, "layouts", layoutName, "collections", collectionName ); imagePath = Utils::combinePath( Configuration::absolutePath, "layouts", layoutName, "collections", collectionName );
imagePath = Utils::combinePath( imagePath, "medium_artwork", imageType_ ); imagePath = Utils::combinePath( imagePath, "medium_artwork", imageType_ );
} }
else else
{ {
if ( commonMode_ )
{
imagePath = Utils::combinePath(Configuration::absolutePath, "collections", "_common" );
imagePath = Utils::combinePath( imagePath, "medium_artwork", imageType_ );
}
else
config_.getMediaPropertyAbsolutePath( collectionName, imageType_, false, imagePath ); config_.getMediaPropertyAbsolutePath( collectionName, imageType_, false, imagePath );
} }
t = imageBuild.CreateImage( imagePath, page, item->name, scaleX_, scaleY_ ); t = imageBuild.CreateImage( imagePath, page, names[n], scaleX_, scaleY_ );
// check sub-collection path for art
// check sub-collection path for art based on gamename if ( !t && !commonMode_ )
if ( !t )
{ {
if ( layoutMode_ ) if ( layoutMode_ )
{ {
@ -554,67 +607,8 @@ bool ScrollingList::allocateTexture( unsigned int index, Item *item )
{ {
config_.getMediaPropertyAbsolutePath( item->collectionInfo->name, imageType_, false, imagePath ); config_.getMediaPropertyAbsolutePath( item->collectionInfo->name, imageType_, false, imagePath );
} }
t = imageBuild.CreateImage( imagePath, page, item->name, scaleX_, scaleY_ ); t = imageBuild.CreateImage( imagePath, page, names[n], scaleX_, scaleY_ );
} }
// check collection path for art based on game name (full title )
if ( !t && item->title != item->fullTitle )
{
if ( layoutMode_ )
{
imagePath = Utils::combinePath( Configuration::absolutePath, "layouts", layoutName, "collections", collectionName );
imagePath = Utils::combinePath( imagePath, "medium_artwork", imageType_ );
}
else
{
config_.getMediaPropertyAbsolutePath( collectionName, imageType_, false, imagePath );
}
t = imageBuild.CreateImage( imagePath, page, item->fullTitle, scaleX_, scaleY_ );
}
// check sub-collection path for art based on game name (full title )
if ( !t && item->title != item->fullTitle )
{
if ( layoutMode_ )
{
imagePath = Utils::combinePath( Configuration::absolutePath, "layouts", layoutName, "collections", item->collectionInfo->name );
imagePath = Utils::combinePath( imagePath, "medium_artwork", imageType_ );
}
else
{
config_.getMediaPropertyAbsolutePath( item->collectionInfo->name, imageType_, false, imagePath );
}
t = imageBuild.CreateImage( imagePath, page, item->fullTitle, scaleX_, scaleY_ );
}
// check collection path for art based on parent game name
if ( !t && item->cloneof != "" )
{
if ( layoutMode_ )
{
imagePath = Utils::combinePath( Configuration::absolutePath, "layouts", layoutName, "collections", collectionName );
imagePath = Utils::combinePath( imagePath, "medium_artwork", imageType_ );
}
else
{
config_.getMediaPropertyAbsolutePath( collectionName, imageType_, false, imagePath );
}
t = imageBuild.CreateImage( imagePath, page, item->cloneof, scaleX_, scaleY_ );
}
// check sub-collection path for art based on parent game name
if ( !t && item->cloneof != "" )
{
if ( layoutMode_ )
{
imagePath = Utils::combinePath( Configuration::absolutePath, "layouts", layoutName, "collections", item->collectionInfo->name );
imagePath = Utils::combinePath( imagePath, "medium_artwork", imageType_ );
}
else
{
config_.getMediaPropertyAbsolutePath( item->collectionInfo->name, imageType_, false, imagePath );
}
t = imageBuild.CreateImage( imagePath, page, item->cloneof, scaleX_, scaleY_ );
} }
// check collection path for art based on system name // check collection path for art based on system name
@ -622,11 +616,20 @@ bool ScrollingList::allocateTexture( unsigned int index, Item *item )
{ {
if ( layoutMode_ ) if ( layoutMode_ )
{ {
if ( commonMode_ )
imagePath = Utils::combinePath(Configuration::absolutePath, "layouts", layoutName, "collections", "_common");
else
imagePath = Utils::combinePath( Configuration::absolutePath, "layouts", layoutName, "collections", item->name ); imagePath = Utils::combinePath( Configuration::absolutePath, "layouts", layoutName, "collections", item->name );
imagePath = Utils::combinePath( imagePath, "system_artwork" ); imagePath = Utils::combinePath( imagePath, "system_artwork" );
} }
else else
{ {
if ( commonMode_ )
{
imagePath = Utils::combinePath(Configuration::absolutePath, "collections", "_common" );
imagePath = Utils::combinePath( imagePath, "system_artwork" );
}
else
config_.getMediaPropertyAbsolutePath( item->name, imageType_, true, imagePath ); config_.getMediaPropertyAbsolutePath( item->name, imageType_, true, imagePath );
} }
t = imageBuild.CreateImage( imagePath, page, imageType_, scaleX_, scaleY_ ); t = imageBuild.CreateImage( imagePath, page, imageType_, scaleX_, scaleY_ );

View File

@ -36,6 +36,7 @@ public:
ScrollingList( Configuration &c, ScrollingList( Configuration &c,
Page &p, Page &p,
bool layoutMode, bool layoutMode,
bool commonMode,
float scaleX, float scaleX,
float scaleY, float scaleY,
Font *font, Font *font,
@ -94,6 +95,7 @@ private:
unsigned int loopDecrement( unsigned int offset, unsigned int i, unsigned int size ); unsigned int loopDecrement( unsigned int offset, unsigned int i, unsigned int size );
bool layoutMode_; bool layoutMode_;
bool commonMode_;
std::vector<Component *> *spriteList_; std::vector<Component *> *spriteList_;
std::vector<ViewInfo *> *scrollPoints_; std::vector<ViewInfo *> *scrollPoints_;
std::vector<AnimationEvents *> *tweenPoints_; std::vector<AnimationEvents *> *tweenPoints_;

View File

@ -14,64 +14,72 @@
* along with RetroFE. If not, see <http://www.gnu.org/licenses/>. * along with RetroFE. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "Text.h" #include "Text.h"
#include "../../Utility/Log.h" #include "../../Utility/Log.h"
#include "../../SDL.h" #include "../../SDL.h"
#include "../Font.h" #include "../Font.h"
#include <sstream> #include <sstream>
Text::Text(std::string text, Page &p, Font *font, float scaleX, float scaleY)
Text::Text( std::string text, Page &p, Font *font, float scaleX, float scaleY, bool input )
: Component(p) : Component(p)
, textData_(text) , textData_(text)
, fontInst_(font) , fontInst_(font)
, scaleX_(scaleX) , scaleX_(scaleX)
, scaleY_(scaleY) , scaleY_(scaleY)
, input_(input)
{ {
allocateGraphicsMemory(); allocateGraphicsMemory( );
} }
Text::~Text() Text::~Text( )
{ {
freeGraphicsMemory(); freeGraphicsMemory( );
} }
void Text::freeGraphicsMemory() void Text::freeGraphicsMemory( )
{ {
Component::freeGraphicsMemory(); Component::freeGraphicsMemory( );
} }
void Text::allocateGraphicsMemory() void Text::allocateGraphicsMemory( )
{ {
//todo: make the font blend color a parameter that is passed in Component::allocateGraphicsMemory( );
Component::allocateGraphicsMemory();
} }
void Text::deInitializeFonts() void Text::deInitializeFonts( )
{ {
fontInst_->deInitialize(); fontInst_->deInitialize( );
} }
void Text::initializeFonts() void Text::initializeFonts( )
{ {
fontInst_->initialize(); fontInst_->initialize( );
} }
void Text::setText(std::string text) void Text::setText( std::string text )
{ {
textData_ = text; textData_ = text;
} }
void Text::draw() void Text::setInput( std::string text )
{ {
Component::draw(); if ( input_ )
textData_ = text;
}
void Text::draw( )
{
Component::draw( );
Font *font; Font *font;
if (baseViewInfo.font) // Use font of this specific item if available if ( baseViewInfo.font ) // Use font of this specific item if available
font = baseViewInfo.font; font = baseViewInfo.font;
else // If not, use the general font settings else // If not, use the general font settings
font = fontInst_; font = fontInst_;
SDL_Texture *t = font->getTexture(); SDL_Texture *t = font->getTexture( );
float imageHeight = 0; float imageHeight = 0;
float imageWidth = 0; float imageWidth = 0;
@ -85,23 +93,23 @@ void Text::draw()
imageMaxWidth = baseViewInfo.MaxWidth; imageMaxWidth = baseViewInfo.MaxWidth;
} }
imageHeight = (float)font->getHeight(); imageHeight = (float)font->getHeight( );
float scale = (float)baseViewInfo.FontSize / (float)imageHeight; float scale = (float)baseViewInfo.FontSize / (float)imageHeight;
unsigned int textIndexMax = 0; unsigned int textIndexMax = 0;
// determine image width // determine image width
for(unsigned int i = 0; i < textData_.size(); ++i) for ( unsigned int i = 0; i < textData_.size( ); ++i )
{ {
Font::GlyphInfo glyph; Font::GlyphInfo glyph;
if(font->getRect(textData_[i], glyph)) if ( font->getRect( textData_[i], glyph ) )
{ {
if(glyph.minX < 0) if ( glyph.minX < 0 )
{ {
imageWidth += glyph.minX; imageWidth += glyph.minX;
} }
if ((imageWidth + glyph.advance)*scale > imageMaxWidth ) if ( (imageWidth + glyph.advance)*scale > imageMaxWidth )
{ {
break; break;
} }
@ -122,8 +130,8 @@ void Text::draw()
baseViewInfo.ImageWidth = imageWidth; baseViewInfo.ImageWidth = imageWidth;
baseViewInfo.ImageHeight = imageHeight; baseViewInfo.ImageHeight = imageHeight;
float xOrigin = baseViewInfo.XRelativeToOrigin(); float xOrigin = baseViewInfo.XRelativeToOrigin( );
float yOrigin = baseViewInfo.YRelativeToOrigin(); float yOrigin = baseViewInfo.YRelativeToOrigin( );
baseViewInfo.Width = oldWidth; baseViewInfo.Width = oldWidth;
baseViewInfo.Height = oldHeight; baseViewInfo.Height = oldHeight;
@ -132,36 +140,35 @@ void Text::draw()
SDL_Rect rect; SDL_Rect rect;
rect.x = static_cast<int>(xOrigin); rect.x = static_cast<int>( xOrigin );
for(unsigned int i = 0; i <= textIndexMax; ++i) for ( unsigned int i = 0; i <= textIndexMax; ++i )
{ {
Font::GlyphInfo glyph; Font::GlyphInfo glyph;
if(font->getRect(textData_[i], glyph) && glyph.rect.h > 0) if ( font->getRect(textData_[i], glyph) && glyph.rect.h > 0 )
{ {
SDL_Rect charRect = glyph.rect; SDL_Rect charRect = glyph.rect;
float h = static_cast<float>(charRect.h * scale); float h = static_cast<float>( charRect.h * scale );
float w = static_cast<float>(charRect.w * scale); float w = static_cast<float>( charRect.w * scale );
rect.h = static_cast<int>(h); rect.h = static_cast<int>( h );
rect.w = static_cast<int>(w); rect.w = static_cast<int>( w );
rect.y = static_cast<int>(yOrigin); rect.y = static_cast<int>( yOrigin );
if(glyph.minX < 0) if(glyph.minX < 0)
{ {
rect.x += static_cast<int>((float)(glyph.minX) * scale); rect.x += static_cast<int>( (float)(glyph.minX) * scale );
} }
if(font->getAscent() < glyph.maxY) if ( font->getAscent( ) < glyph.maxY )
{ {
rect.y += static_cast<int>((font->getAscent() - glyph.maxY)*scale); rect.y += static_cast<int>( (font->getAscent( ) - glyph.maxY)*scale );
} }
SDL::renderCopy(t, baseViewInfo.Alpha, &charRect, &rect, baseViewInfo); SDL::renderCopy( t, baseViewInfo.Alpha, &charRect, &rect, baseViewInfo );
rect.x += static_cast<int>(glyph.advance * scale); rect.x += static_cast<int>( glyph.advance * scale );
} }
} }
} }

View File

@ -15,29 +15,34 @@
*/ */
#pragma once #pragma once
#include "Component.h" #include "Component.h"
#include "../Page.h" #include "../Page.h"
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <vector> #include <vector>
class Font; class Font;
class Text : public Component class Text : public Component
{ {
public: public:
//todo: should have a Font flass that references fontcache, pass that in as an argument Text( std::string text, Page &p, Font *font, float scaleX, float scaleY, bool input = false );
Text(std::string text, Page &p, Font *font, float scaleX, float scaleY); virtual ~Text( );
virtual ~Text(); void setText( std::string text );
void setText(std::string text); void setInput( std::string text );
void allocateGraphicsMemory(); void allocateGraphicsMemory( );
void freeGraphicsMemory(); void freeGraphicsMemory( );
void deInitializeFonts(); void deInitializeFonts( );
void initializeFonts(); void initializeFonts( );
void draw(); void draw( );
private: private:
std::string textData_; std::string textData_;
Font *fontInst_; Font *fontInst_;
float scaleX_; float scaleX_;
float scaleY_; float scaleY_;
bool input_;
}; };

View File

@ -483,6 +483,24 @@ void Page::highlightExit()
} }
void Page::menuAction( std::string action )
{
for(std::vector<Component *>::iterator it = LayerComponents.begin(); it != LayerComponents.end(); ++it)
{
(*it)->triggerEvent( action );
}
}
void Page::menuInput( std::string text )
{
for(std::vector<Component *>::iterator it = LayerComponents.begin(); it != LayerComponents.end(); ++it)
{
(*it)->setInput( text );
}
}
void Page::setScrolling(ScrollDirection direction) void Page::setScrolling(ScrollDirection direction)
{ {
switch(direction) switch(direction)
@ -1041,6 +1059,8 @@ void Page::allocateGraphicsMemory()
Logger::write(Logger::ZONE_DEBUG, "Page", "Allocating graphics memory"); Logger::write(Logger::ZONE_DEBUG, "Page", "Allocating graphics memory");
for(MenuVector_T::iterator it = menus_.begin(); it != menus_.end(); it++) for(MenuVector_T::iterator it = menus_.begin(); it != menus_.end(); it++)
{
if ( std::distance(menus_.begin(), it) < menuDepth_ )
{ {
for(std::vector<ScrollingList *>::iterator it2 = menus_[std::distance(menus_.begin(), it)].begin(); it2 != menus_[std::distance(menus_.begin(), it)].end(); it2++) for(std::vector<ScrollingList *>::iterator it2 = menus_[std::distance(menus_.begin(), it)].begin(); it2 != menus_[std::distance(menus_.begin(), it)].end(); it2++)
{ {
@ -1048,6 +1068,7 @@ void Page::allocateGraphicsMemory()
menu->allocateGraphicsMemory(); menu->allocateGraphicsMemory();
} }
} }
}
if(loadSoundChunk_) loadSoundChunk_->allocate(); if(loadSoundChunk_) loadSoundChunk_->allocate();
if(unloadSoundChunk_) unloadSoundChunk_->allocate(); if(unloadSoundChunk_) unloadSoundChunk_->allocate();

View File

@ -98,6 +98,8 @@ public:
void menuScroll(); void menuScroll();
void highlightEnter(); void highlightEnter();
void highlightExit(); void highlightExit();
void menuAction( std::string action );
void menuInput( std::string text );
void addPlaylist(); void addPlaylist();
void removePlaylist(); void removePlaylist();
void reallocateMenuSpritePoints(); void reallocateMenuSpritePoints();

View File

@ -49,7 +49,7 @@ static const int MENU_END = -2; // last item transitions here after it scroll
static const int MENU_CENTER = -4; static const int MENU_CENTER = -4;
//todo: this file is starting to become a god class of building. Consider splitting into sub-builders //todo: this file is starting to become a god class of building. Consider splitting into sub-builders
PageBuilder::PageBuilder(std::string layoutKey, std::string layoutPage, Configuration &c, FontCache *fc) PageBuilder::PageBuilder(std::string layoutKey, std::string layoutPage, Configuration &c, FontCache *fc, bool isMenu)
: layoutKey(layoutKey) : layoutKey(layoutKey)
, layoutPage(layoutPage) , layoutPage(layoutPage)
, config_(c) , config_(c)
@ -59,6 +59,7 @@ PageBuilder::PageBuilder(std::string layoutKey, std::string layoutPage, Configur
, screenWidth_(0) , screenWidth_(0)
, fontSize_(24) , fontSize_(24)
, fontCache_(fc) , fontCache_(fc)
, isMenu_(isMenu)
{ {
screenWidth_ = SDL::getWindowWidth(); screenWidth_ = SDL::getWindowWidth();
screenHeight_ = SDL::getWindowHeight(); screenHeight_ = SDL::getWindowHeight();
@ -80,7 +81,11 @@ Page *PageBuilder::buildPage( std::string collectionName )
std::string layoutFileAspect; std::string layoutFileAspect;
std::string layoutName = layoutKey; std::string layoutName = layoutKey;
if ( collectionName == "" ) if ( isMenu_ )
{
layoutPath = Utils::combinePath(Configuration::absolutePath, "menu");
}
else if ( collectionName == "" )
{ {
layoutPath = Utils::combinePath(Configuration::absolutePath, "layouts", layoutName); layoutPath = Utils::combinePath(Configuration::absolutePath, "layouts", layoutName);
} }
@ -523,6 +528,7 @@ void PageBuilder::loadReloadableImages(xml_node<> *layout, std::string tagName,
bool systemMode = false; bool systemMode = false;
bool layoutMode = false; bool layoutMode = false;
bool commonMode = false; bool commonMode = false;
bool menuMode = false;
int selectedOffset = 0; int selectedOffset = 0;
if(tagName == "reloadableVideo") if(tagName == "reloadableVideo")
{ {
@ -569,6 +575,10 @@ void PageBuilder::loadReloadableImages(xml_node<> *layout, std::string tagName,
systemMode = true; systemMode = true;
layoutMode = true; layoutMode = true;
} }
if(sysMode == "menu")
{
menuMode = true;
}
} }
if(selectedOffsetXml) if(selectedOffsetXml)
@ -686,7 +696,7 @@ void PageBuilder::loadReloadableImages(xml_node<> *layout, std::string tagName,
{ {
pluralPostfix = pluralPostfixXml->value(); pluralPostfix = pluralPostfixXml->value();
} }
c = new ReloadableScrollingText(config_, systemMode, layoutMode, type->value(), singlePrefix, singlePostfix, pluralPrefix, pluralPostfix, textFormat, alignment, *page, selectedOffset, font, scaleX_, scaleY_, direction, scrollingSpeed, startPosition, startTime, endTime); c = new ReloadableScrollingText(config_, systemMode, layoutMode, menuMode, type->value(), singlePrefix, singlePostfix, pluralPrefix, pluralPostfix, textFormat, alignment, *page, selectedOffset, font, scaleX_, scaleY_, direction, scrollingSpeed, startPosition, startTime, endTime);
xml_attribute<> *menuScrollReload = componentXml->first_attribute("menuScrollReload"); xml_attribute<> *menuScrollReload = componentXml->first_attribute("menuScrollReload");
if (menuScrollReload && if (menuScrollReload &&
(Utils::toLower(menuScrollReload->value()) == "true" || (Utils::toLower(menuScrollReload->value()) == "true" ||
@ -699,7 +709,7 @@ void PageBuilder::loadReloadableImages(xml_node<> *layout, std::string tagName,
else else
{ {
Font *font = addFont(componentXml, NULL); Font *font = addFont(componentXml, NULL);
c = new ReloadableMedia(config_, systemMode, layoutMode, commonMode, type->value(), *page, selectedOffset, (tagName == "reloadableVideo"), font, scaleX_, scaleY_); c = new ReloadableMedia(config_, systemMode, layoutMode, commonMode, menuMode, type->value(), *page, selectedOffset, (tagName == "reloadableVideo"), font, scaleX_, scaleY_);
xml_attribute<> *menuScrollReload = componentXml->first_attribute("menuScrollReload"); xml_attribute<> *menuScrollReload = componentXml->first_attribute("menuScrollReload");
if (menuScrollReload && if (menuScrollReload &&
(Utils::toLower(menuScrollReload->value()) == "true" || (Utils::toLower(menuScrollReload->value()) == "true" ||
@ -812,6 +822,11 @@ AnimationEvents *PageBuilder::createTweenInstance(xml_node<> *componentXml)
buildTweenSet(tweens, componentXml, "onGameEnter", "gameEnter"); buildTweenSet(tweens, componentXml, "onGameEnter", "gameEnter");
buildTweenSet(tweens, componentXml, "onGameExit", "gameExit"); buildTweenSet(tweens, componentXml, "onGameExit", "gameExit");
buildTweenSet(tweens, componentXml, "onMenuActionInputEnter", "menuActionInputEnter");
buildTweenSet(tweens, componentXml, "onMenuActionInputExit", "menuActionInputExit");
buildTweenSet(tweens, componentXml, "onMenuActionSelectEnter", "menuActionSelectEnter");
buildTweenSet(tweens, componentXml, "onMenuActionSelectExit", "menuActionSelectExit");
return tweens; return tweens;
} }
@ -921,6 +936,7 @@ ScrollingList * PageBuilder::buildMenu(xml_node<> *menuXml, Page &page)
} }
bool layoutMode = false; bool layoutMode = false;
bool commonMode = false;
if(modeXml) if(modeXml)
{ {
std::string sysMode = modeXml->value(); std::string sysMode = modeXml->value();
@ -928,12 +944,21 @@ ScrollingList * PageBuilder::buildMenu(xml_node<> *menuXml, Page &page)
{ {
layoutMode = true; layoutMode = true;
} }
if(sysMode == "common")
{
commonMode = true;
}
if(sysMode == "commonlayout")
{
layoutMode = true;
commonMode = true;
}
} }
// on default, text will be rendered to the menu. Preload it into cache. // on default, text will be rendered to the menu. Preload it into cache.
Font *font = addFont(itemDefaults, NULL); Font *font = addFont(itemDefaults, NULL);
menu = new ScrollingList(config_, page, layoutMode, scaleX_, scaleY_, font, layoutKey, imageType); menu = new ScrollingList(config_, page, layoutMode, commonMode, scaleX_, scaleY_, font, layoutKey, imageType);
if(scrollTimeXml) if(scrollTimeXml)
{ {

View File

@ -33,7 +33,7 @@ class Font;
class PageBuilder class PageBuilder
{ {
public: public:
PageBuilder(std::string layoutKey, std::string layoutPage, Configuration &c, FontCache *fc); PageBuilder(std::string layoutKey, std::string layoutPage, Configuration &c, FontCache *fc, bool isMenu = false);
virtual ~PageBuilder(); virtual ~PageBuilder();
Page *buildPage( std::string collectionName = "" ); Page *buildPage( std::string collectionName = "" );
@ -50,6 +50,7 @@ private:
std::string fontName_; std::string fontName_;
int fontSize_; int fontSize_;
FontCache *fontCache_; FontCache *fontCache_;
bool isMenu_;
Font *addFont(rapidxml::xml_node<> *component, rapidxml::xml_node<> *defaults); Font *addFont(rapidxml::xml_node<> *component, rapidxml::xml_node<> *defaults);
void loadReloadableImages(rapidxml::xml_node<> *layout, std::string tagName, Page *page); void loadReloadableImages(rapidxml::xml_node<> *layout, std::string tagName, Page *page);

View File

@ -0,0 +1,46 @@
/* This file is part of RetroFE.
*
* RetroFE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RetroFE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RetroFE. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Menu.h"
#include "../Collection/Item.h"
#include <iostream>
Menu::Menu( Configuration &c )
: config_( c )
{
page_ = nullptr;
}
void Menu::handleEntry( Item *item )
{
std::cout << "Handling " + item->ctrlType + "." << std::endl;
return;
}
void Menu::setPage( Page *page )
{
page_ = page;
}
void Menu::clearPage( )
{
page_ = nullptr;
}

View File

@ -0,0 +1,37 @@
/* This file is part of RetroFE.
*
* RetroFE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RetroFE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RetroFE. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
class Configuration;
class Item;
class Page;
class Menu
{
public:
Menu( Configuration &c );
void handleEntry( Item *item );
void setPage( Page *page );
void clearPage( );
private:
Configuration &config_;
Page *page_;
};

View File

@ -21,6 +21,7 @@
#include "Database/Configuration.h" #include "Database/Configuration.h"
#include "Collection/Item.h" #include "Collection/Item.h"
#include "Execute/Launcher.h" #include "Execute/Launcher.h"
#include "Menu/Menu.h"
#include "Utility/Log.h" #include "Utility/Log.h"
#include "Utility/Utils.h" #include "Utility/Utils.h"
#include "Collection/MenuParser.h" #include "Collection/MenuParser.h"
@ -35,6 +36,7 @@
#include <dirent.h> #include <dirent.h>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <string>
#include <tuple> #include <tuple>
#include <vector> #include <vector>
#include <SDL2/SDL_ttf.h> #include <SDL2/SDL_ttf.h>
@ -68,6 +70,7 @@ RetroFE::RetroFE( Configuration &c )
, keyLastTime_(0) , keyLastTime_(0)
, keyDelayTime_(.3f) , keyDelayTime_(.3f)
{ {
menuMode_ = false;
} }
@ -273,24 +276,11 @@ void RetroFE::run( )
// Define control configuration // Define control configuration
std::string controlsConfPath = Utils::combinePath( Configuration::absolutePath, "controls.conf" ); std::string controlsConfPath = Utils::combinePath( Configuration::absolutePath, "controls.conf" );
if ( !config_.import( "controls", controlsConfPath ) ) if ( !config_.import( "controls", controlsConfPath ) )
{
// Let the user input new controls
get_controls_config( );
// Re-initialize SDL to reset the controller situation
SDL::deInitialize( );
if(! SDL::initialize( config_ ) ) return;
// Retry reading the control configuration
if ( !config_.import( "controls", controlsConfPath ) )
{ {
Logger::write( Logger::ZONE_ERROR, "RetroFE", "Could not import \"" + controlsConfPath + "\"" ); Logger::write( Logger::ZONE_ERROR, "RetroFE", "Could not import \"" + controlsConfPath + "\"" );
return; return;
} }
}
float preloadTime = 0; float preloadTime = 0;
// Initialize video // Initialize video
@ -330,6 +320,7 @@ void RetroFE::run( )
bool exitSplashMode = false; bool exitSplashMode = false;
Launcher l( config_ ); Launcher l( config_ );
Menu m( config_ );
preloadTime = static_cast<float>( SDL_GetTicks( ) ) / 1000; preloadTime = static_cast<float>( SDL_GetTicks( ) ) / 1000;
while ( running ) while ( running )
@ -472,6 +463,7 @@ void RetroFE::run( )
case RETROFE_PLAYLIST_LOAD_ART: case RETROFE_PLAYLIST_LOAD_ART:
if (currentPage_->isIdle( )) if (currentPage_->isIdle( ))
{ {
currentPage_->onNewItemSelected( );
currentPage_->reallocateMenuSpritePoints( ); currentPage_->reallocateMenuSpritePoints( );
currentPage_->highlightEnter( ); currentPage_->highlightEnter( );
state = RETROFE_PLAYLIST_ENTER; state = RETROFE_PLAYLIST_ENTER;
@ -555,22 +547,29 @@ void RetroFE::run( )
{ {
lastMenuOffsets_[currentPage_->getCollectionName( )] = currentPage_->getScrollOffsetIndex( ); lastMenuOffsets_[currentPage_->getCollectionName( )] = currentPage_->getScrollOffsetIndex( );
lastMenuPlaylists_[currentPage_->getCollectionName( )] = currentPage_->getPlaylistName( ); lastMenuPlaylists_[currentPage_->getCollectionName( )] = currentPage_->getPlaylistName( );
std::string nextPageName = nextPageItem_->name;
if ( !menuMode_ )
{
// Load new layout if available // Load new layout if available
std::string layoutName; std::string layoutName;
config_.getProperty( "layout", layoutName ); config_.getProperty( "layout", layoutName );
PageBuilder pb(layoutName, "layout", config_, &fontcache_); PageBuilder pb( layoutName, "layout", config_, &fontcache_ );
Page *page = pb.buildPage( nextPageItem_->name); Page *page = pb.buildPage( nextPageItem_->name );
std::string nextPageName = nextPageItem_->name;
if ( page ) if ( page )
{ {
currentPage_->freeGraphicsMemory( ); currentPage_->freeGraphicsMemory( );
pages_.push( currentPage_ ); pages_.push( currentPage_ );
currentPage_ = page; currentPage_ = page;
} }
}
config_.setProperty( "currentCollection", nextPageName ); config_.setProperty( "currentCollection", nextPageName );
CollectionInfo *info = getCollection( nextPageName ); CollectionInfo *info;
if ( menuMode_ )
info = getMenuCollection( nextPageName );
else
info = getCollection( nextPageName );
currentPage_->pushCollection(info); currentPage_->pushCollection(info);
@ -635,6 +634,24 @@ void RetroFE::run( )
} }
break; break;
// Launching a menu entry
case RETROFE_HANDLE_MENUENTRY:
// Empty event queue
SDL_Event e;
while ( SDL_PollEvent( &e ) );
input_.resetStates( );
// Handle menu entry
m.handleEntry( currentPage_->getSelectedItem( ) );
// Empty event queue
while ( SDL_PollEvent( &e ) );
input_.resetStates( );
state = RETROFE_IDLE;
break;
// Launching game; start onGameEnter animation // Launching game; start onGameEnter animation
case RETROFE_LAUNCH_ENTER: case RETROFE_LAUNCH_ENTER:
currentPage_->enterGame( ); // Start onGameEnter animation currentPage_->enterGame( ); // Start onGameEnter animation
@ -668,6 +685,8 @@ void RetroFE::run( )
if (currentPage_->getMenuDepth( ) == 1 ) if (currentPage_->getMenuDepth( ) == 1 )
{ {
currentPage_->stop( ); currentPage_->stop( );
m.clearPage( );
menuMode_ = false;
} }
else else
{ {
@ -749,6 +768,48 @@ void RetroFE::run( )
} }
break; break;
// Start menu mode
case RETROFE_MENUMODE_START_REQUEST:
if ( currentPage_->isIdle( ) )
{
lastMenuOffsets_[currentPage_->getCollectionName( )] = currentPage_->getScrollOffsetIndex( );
lastMenuPlaylists_[currentPage_->getCollectionName( )] = currentPage_->getPlaylistName( );
std::string layoutName;
config_.getProperty( "layout", layoutName );
PageBuilder pb( layoutName, "layout", config_, &fontcache_, true );
Page *page = pb.buildPage( );
if ( page )
{
currentPage_->freeGraphicsMemory( );
pages_.push( currentPage_ );
currentPage_ = page;
menuMode_ = true;
m.setPage( page );
}
config_.setProperty( "currentCollection", "menu" );
CollectionInfo *info = getMenuCollection( "menu" );
currentPage_->pushCollection(info);
currentPage_->onNewItemSelected( );
currentPage_->reallocateMenuSpritePoints( );
state = RETROFE_MENUMODE_START_LOAD_ART;
}
break;
case RETROFE_MENUMODE_START_LOAD_ART:
currentPage_->start();
state = RETROFE_MENUMODE_START_ENTER;
break;
case RETROFE_MENUMODE_START_ENTER:
if ( currentPage_->isIdle( ) )
{
SDL_Event e;
while ( SDL_PollEvent( &e ) );
input_.resetStates( );
state = RETROFE_IDLE;
}
break;
// Wait for splash mode animation to finish // Wait for splash mode animation to finish
case RETROFE_NEW: case RETROFE_NEW:
if ( currentPage_->isIdle( ) ) if ( currentPage_->isIdle( ) )
@ -796,6 +857,10 @@ void RetroFE::run( )
{ {
attract_.update( deltaTime, *currentPage_ ); attract_.update( deltaTime, *currentPage_ );
} }
if ( menuMode_ )
{
attract_.reset( );
}
currentPage_->update( deltaTime ); currentPage_->update( deltaTime );
} }
@ -883,7 +948,13 @@ RetroFE::RETROFE_STATE RetroFE::processUserInput( Page *page )
if ( page->isMenuIdle( ) ) if ( page->isMenuIdle( ) )
{ {
if (!input_.keystate(UserInput::KeyCodePageUp) && if ( input_.keystate(UserInput::KeyCodeMenu) && !menuMode_)
{
state = RETROFE_MENUMODE_START_REQUEST;
}
if ( menuMode_ || (
!input_.keystate(UserInput::KeyCodePageUp) &&
!input_.keystate(UserInput::KeyCodePageDown) && !input_.keystate(UserInput::KeyCodePageDown) &&
!input_.keystate(UserInput::KeyCodeLetterUp) && !input_.keystate(UserInput::KeyCodeLetterUp) &&
!input_.keystate(UserInput::KeyCodeLetterDown) && !input_.keystate(UserInput::KeyCodeLetterDown) &&
@ -892,7 +963,8 @@ RetroFE::RETROFE_STATE RetroFE::processUserInput( Page *page )
!input_.keystate(UserInput::KeyCodePrevPlaylist) && !input_.keystate(UserInput::KeyCodePrevPlaylist) &&
!input_.keystate(UserInput::KeyCodeAddPlaylist) && !input_.keystate(UserInput::KeyCodeAddPlaylist) &&
!input_.keystate(UserInput::KeyCodeRemovePlaylist) && !input_.keystate(UserInput::KeyCodeRemovePlaylist) &&
!input_.keystate(UserInput::KeyCodeRandom)) !input_.keystate(UserInput::KeyCodeRandom) &&
!input_.keystate(UserInput::KeyCodeMenu)) )
{ {
keyLastTime_ = 0; keyLastTime_ = 0;
keyDelayTime_= 0.3f; keyDelayTime_= 0.3f;
@ -908,6 +980,7 @@ RetroFE::RETROFE_STATE RetroFE::processUserInput( Page *page )
{ {
attract_.reset( ); attract_.reset( );
page->pageScroll(Page::ScrollDirectionBack); page->pageScroll(Page::ScrollDirectionBack);
page->onNewItemSelected( );
page->reallocateMenuSpritePoints( ); page->reallocateMenuSpritePoints( );
state = RETROFE_MENUJUMP_REQUEST; state = RETROFE_MENUJUMP_REQUEST;
} }
@ -915,6 +988,7 @@ RetroFE::RETROFE_STATE RetroFE::processUserInput( Page *page )
{ {
attract_.reset( ); attract_.reset( );
page->pageScroll(Page::ScrollDirectionForward); page->pageScroll(Page::ScrollDirectionForward);
page->onNewItemSelected( );
page->reallocateMenuSpritePoints( ); page->reallocateMenuSpritePoints( );
state = RETROFE_MENUJUMP_REQUEST; state = RETROFE_MENUJUMP_REQUEST;
} }
@ -922,6 +996,7 @@ RetroFE::RETROFE_STATE RetroFE::processUserInput( Page *page )
{ {
attract_.reset( ); attract_.reset( );
page->letterScroll(Page::ScrollDirectionBack); page->letterScroll(Page::ScrollDirectionBack);
page->onNewItemSelected( );
page->reallocateMenuSpritePoints( ); page->reallocateMenuSpritePoints( );
state = RETROFE_MENUJUMP_REQUEST; state = RETROFE_MENUJUMP_REQUEST;
} }
@ -929,6 +1004,7 @@ RetroFE::RETROFE_STATE RetroFE::processUserInput( Page *page )
{ {
attract_.reset( ); attract_.reset( );
page->letterScroll(Page::ScrollDirectionForward); page->letterScroll(Page::ScrollDirectionForward);
page->onNewItemSelected( );
page->reallocateMenuSpritePoints( ); page->reallocateMenuSpritePoints( );
state = RETROFE_MENUJUMP_REQUEST; state = RETROFE_MENUJUMP_REQUEST;
} }
@ -966,6 +1042,7 @@ RetroFE::RETROFE_STATE RetroFE::processUserInput( Page *page )
{ {
attract_.reset( ); attract_.reset( );
page->selectRandom( ); page->selectRandom( );
page->onNewItemSelected( );
page->reallocateMenuSpritePoints( ); page->reallocateMenuSpritePoints( );
state = RETROFE_HIGHLIGHT_REQUEST; state = RETROFE_HIGHLIGHT_REQUEST;
} }
@ -984,9 +1061,16 @@ RetroFE::RETROFE_STATE RetroFE::processUserInput( Page *page )
if ( nextPageItem_ ) if ( nextPageItem_ )
{ {
if ( nextPageItem_->leaf ) if ( nextPageItem_->leaf )
{
if ( menuMode_ )
{
state = RETROFE_HANDLE_MENUENTRY;
}
else
{ {
state = RETROFE_LAUNCH_ENTER; state = RETROFE_LAUNCH_ENTER;
} }
}
else else
{ {
state = RETROFE_NEXT_PAGE_REQUEST; state = RETROFE_NEXT_PAGE_REQUEST;
@ -1040,7 +1124,7 @@ Page *RetroFE::loadPage( )
config_.getProperty( "layout", layoutName ); config_.getProperty( "layout", layoutName );
PageBuilder pb(layoutName, "layout", config_, &fontcache_); PageBuilder pb( layoutName, "layout", config_, &fontcache_ );
Page *page = pb.buildPage( ); Page *page = pb.buildPage( );
if ( !page ) if ( !page )
@ -1058,7 +1142,7 @@ Page *RetroFE::loadSplashPage( )
std::string layoutName; std::string layoutName;
config_.getProperty( "layout", layoutName ); config_.getProperty( "layout", layoutName );
PageBuilder pb(layoutName, "splash", config_, &fontcache_); PageBuilder pb( layoutName, "splash", config_, &fontcache_ );
Page * page = pb.buildPage( ); Page * page = pb.buildPage( );
page->start( ); page->start( );
@ -1178,199 +1262,30 @@ CollectionInfo *RetroFE::getCollection(std::string collectionName)
} }
std::string RetroFE::get_key( ) // Load a menu
CollectionInfo *RetroFE::getMenuCollection( std::string collectionName )
{ {
std::string menuPath = Utils::combinePath( Configuration::absolutePath, "menu" );
SDL_Event event; std::string menuFile = Utils::combinePath( menuPath, collectionName + ".txt" );
std::string return_value; std::vector<Item *> menuVector;
CollectionInfoBuilder cib( config_, *metadb_ );
while ( SDL_PollEvent( &event ) ) CollectionInfo *collection = new CollectionInfo( collectionName, menuPath, "", "", "" );
cib.ImportBasicList( collection, menuFile, menuVector );
for ( std::vector<Item *>::iterator it = menuVector.begin( ); it != menuVector.end( ); ++it)
{ {
switch (event.type) (*it)->leaf = false;
size_t position = (*it)->name.find( "=" );
if ( position != std::string::npos )
{ {
case SDL_JOYDEVICEADDED: (*it)->ctrlType = Utils::trimEnds( (*it)->name.substr( position+1, (*it)->name.size( )-1 ) );
if ( !SDL_JoystickOpen( event.jdevice.which ) ) (*it)->name = Utils::trimEnds( (*it)->name.substr( 0, position ) );
Logger::write( Logger::ZONE_INFO, "RetroFE", "Unable to open SDL joystick." ); (*it)->title = (*it)->name;
else (*it)->fullTitle = (*it)->name;
Logger::write( Logger::ZONE_INFO, "RetroFE", "SDL joystick opened." ); (*it)->leaf = true;
break;
case SDL_KEYDOWN:
if ( return_value.empty( ) )
return_value = SDL_GetKeyName( event.key.keysym.sym);
break;
case SDL_JOYBUTTONDOWN:
if ( return_value.empty( ) )
return_value = "joyButton" + std::to_string( int( event.jbutton.button ) );
break;
case SDL_JOYAXISMOTION:
if ((event.jaxis.value > 30000 || event.jaxis.value < -30000) && event.jaxis.axis <= 3)
{
if ( event.jaxis.value > 0 )
{
if ( return_value.empty( ) )
return_value = "joyAxis" + std::to_string( int( event.jaxis.axis ) ) + "+";
} }
else (*it)->collectionInfo = collection;
{ collection->items.push_back( *it );
if ( return_value.empty( ) )
return_value = "joyAxis" + std::to_string( int( event.jaxis.axis ) ) + "-";
} }
} collection->playlists["all"] = &collection->items;
break; return collection;
case SDL_JOYHATMOTION:
switch( event.jhat.value )
{
case SDL_HAT_UP:
if ( return_value.empty( ) )
return_value = "joyHat" + std::to_string( int( event.jhat.hat ) ) + "Up";
break;
case SDL_HAT_DOWN:
if ( return_value.empty( ) )
return_value = "joyHat" + std::to_string( int( event.jhat.hat ) ) + "Down";
break;
case SDL_HAT_LEFT:
if ( return_value.empty( ) )
return_value = "joyHat" + std::to_string( int( event.jhat.hat ) ) + "Left";
break;
case SDL_HAT_RIGHT:
if ( return_value.empty( ) )
return_value = "joyHat" + std::to_string( int( event.jhat.hat ) ) + "Right";
break;
}
break;
default:
break;
}
}
return return_value;
}
void RetroFE::print_string( std::string message, TTF_Font *font )
{
SDL_Surface *surfaceMessage;
SDL_Texture *messageTexture;
SDL_Rect messageRect;
SDL_Color color = {255, 255, 255, 0};
surfaceMessage = TTF_RenderText_Solid( font, message.c_str( ), color );
if ( !surfaceMessage )
Logger::write( Logger::ZONE_INFO, "RetroFE", "Could not render print_string text." );
messageTexture = SDL_CreateTextureFromSurface( SDL::getRenderer( ), surfaceMessage );
if ( !messageTexture )
Logger::write( Logger::ZONE_INFO, "RetroFE", "Could not create print_string texture." );
messageRect.w = SDL::getWindowWidth( ) * 8 / 10;
messageRect.h = SDL::getWindowWidth( ) * 8 * surfaceMessage->h / (10 * surfaceMessage->w);
messageRect.x = SDL::getWindowWidth( )/2 - messageRect.w/2;
messageRect.y = SDL::getWindowHeight( )/2 - messageRect.h/2;
SDL_LockMutex( SDL::getMutex( ) );
SDL_SetRenderDrawColor( SDL::getRenderer( ), 0, 0, 0, 0xFF );
SDL_RenderClear( SDL::getRenderer( ) );
SDL_RenderCopy( SDL::getRenderer( ), messageTexture, NULL, &messageRect);
SDL_RenderPresent( SDL::getRenderer( ) );
SDL_UnlockMutex( SDL::getMutex( ) );
SDL_FreeSurface( surfaceMessage);
SDL_DestroyTexture( messageTexture );
}
void RetroFE::get_controls_config( )
{
Logger::write( Logger::ZONE_INFO, "RetroFE", std::to_string( SDL_NumJoysticks( ) ) + " joysticks were found." );
TTF_Font *font = TTF_OpenFont( Utils::combinePath( "core", "OpenSans.ttf" ).c_str( ), 48 );
if ( !font )
{
Logger::write( Logger::ZONE_INFO, "RetroFE", "SDL could not open font OpenSans.ttf" );
return;
}
std::ofstream controls_file;
controls_file.open( "controls.conf" );
std::vector<std::tuple<std::string, std::string, bool>> controls;
controls.push_back( std::make_tuple( "up", "go up in the games/collection menu", true ) );
controls.push_back( std::make_tuple( "down", "go down in the games/collection menu", true ) );
controls.push_back( std::make_tuple( "left", "go left in the games/collection menu", true ) );
controls.push_back( std::make_tuple( "right", "go right in the games/collection menu", true ) );
controls.push_back( std::make_tuple( "pageUp", "go to the next page in your games/collection menu", false ) );
controls.push_back( std::make_tuple( "pageDown", "go to the previous page in your games/collection menu", false ) );
controls.push_back( std::make_tuple( "letterUp", "go to the next letter in your games/collection menu", false ) );
controls.push_back( std::make_tuple( "letterDown", "go to the previous letter in your games/collection menu", false ) );
controls.push_back( std::make_tuple( "favPlaylist", "switch to your Favorites playlist", false ) );
controls.push_back( std::make_tuple( "nextPlaylist", "switch to the next playlist", false ) );
controls.push_back( std::make_tuple( "prevPlaylist", "switch to the previous playlist", false ) );
controls.push_back( std::make_tuple( "addPlaylist", "add the selected game/collection to your Favorites playlist", false ) );
controls.push_back( std::make_tuple( "removePlaylist", "remove the selected game/collection from your Favorites playlist", false ) );
controls.push_back( std::make_tuple( "random", "select a random game/collection from the menu", false ) );
controls.push_back( std::make_tuple( "select", "enter the collection/start the game", true ) );
controls.push_back( std::make_tuple( "back", "go back to the previous menu", true ) );
controls.push_back( std::make_tuple( "quit", "quit RetroFE", true ) );
std::string key;
std::vector<std::string> keys;
// Clear input queue before we start, but do attach joysticks
get_key( );
for ( unsigned int c = 0; c < controls.size( ); c++ )
{
keys.clear( );
int time_out = 0;
while ( true )
{
key = "";
while ( key.empty( ) )
{
if ( !keys.size( ) )
{
if ( std::get<2>( controls[c] ) )
print_string( "Please enter your control to " + std::get<1>( controls[c] ) + ". This key is mandatory for proper RetroFE usage.", font );
else
print_string( "Please enter your control to " + std::get<1>( controls[c] ) + " or wait " + std::to_string( 10 - time_out / 10 ) + " second(s) to not make a selection for this control.", font );
}
else
{
print_string( "Please enter another control to " + std::get<1>( controls[c] ) + " or wait " + std::to_string( 10 - time_out / 10 ) + " second(s) to continue with the next control.", font );
}
SDL_Delay( 100 );
key = get_key( );
time_out++;
if ( (!std::get<2>( controls[c] ) || keys.size( )) && time_out > 100 )
break;
}
if ( key.empty( ) || (keys.size( ) && std::find( keys.begin( ), keys.end( ), key ) != keys.end( )) )
break;
keys.push_back( key );
time_out = 0;
}
if ( keys.size( ) )
{
controls_file << std::get<0>( controls[c] ) + " = ";
for ( unsigned int i = 0; i < keys.size( ); i++ )
if ( i == 0 )
controls_file << keys[i];
else
controls_file << ", " << keys[i];
controls_file << std::endl;
}
}
controls_file.close( );
TTF_CloseFont( font );
} }

View File

@ -76,6 +76,7 @@ private:
RETROFE_NEXT_PAGE_MENU_EXIT, RETROFE_NEXT_PAGE_MENU_EXIT,
RETROFE_NEXT_PAGE_MENU_LOAD_ART, RETROFE_NEXT_PAGE_MENU_LOAD_ART,
RETROFE_NEXT_PAGE_MENU_ENTER, RETROFE_NEXT_PAGE_MENU_ENTER,
RETROFE_HANDLE_MENUENTRY,
RETROFE_LAUNCH_ENTER, RETROFE_LAUNCH_ENTER,
RETROFE_LAUNCH_REQUEST, RETROFE_LAUNCH_REQUEST,
RETROFE_LAUNCH_EXIT, RETROFE_LAUNCH_EXIT,
@ -83,6 +84,9 @@ private:
RETROFE_BACK_MENU_EXIT, RETROFE_BACK_MENU_EXIT,
RETROFE_BACK_MENU_LOAD_ART, RETROFE_BACK_MENU_LOAD_ART,
RETROFE_BACK_MENU_ENTER, RETROFE_BACK_MENU_ENTER,
RETROFE_MENUMODE_START_REQUEST,
RETROFE_MENUMODE_START_LOAD_ART,
RETROFE_MENUMODE_START_ENTER,
RETROFE_NEW, RETROFE_NEW,
RETROFE_QUIT_REQUEST, RETROFE_QUIT_REQUEST,
RETROFE_QUIT, RETROFE_QUIT,
@ -96,6 +100,7 @@ private:
RETROFE_STATE processUserInput( Page *page ); RETROFE_STATE processUserInput( Page *page );
void update( float dt, bool scrollActive ); void update( float dt, bool scrollActive );
CollectionInfo *getCollection( std::string collectionName ); CollectionInfo *getCollection( std::string collectionName );
CollectionInfo *getMenuCollection( std::string collectionName );
Configuration &config_; Configuration &config_;
DB *db_; DB *db_;
@ -111,12 +116,8 @@ private:
Item *nextPageItem_; Item *nextPageItem_;
FontCache fontcache_; FontCache fontcache_;
AttractMode attract_; AttractMode attract_;
bool menuMode_;
std::map<std::string, unsigned int> lastMenuOffsets_; std::map<std::string, unsigned int> lastMenuOffsets_;
std::map<std::string, std::string> lastMenuPlaylists_; std::map<std::string, std::string> lastMenuPlaylists_;
std::string get_key( );
void print_string( std::string message, TTF_Font *font );
void get_controls_config( );
}; };

View File

@ -21,7 +21,7 @@
std::string retrofe_version_major = "0"; std::string retrofe_version_major = "0";
std::string retrofe_version_minor = "8"; std::string retrofe_version_minor = "8";
std::string retrofe_version_build = "15b1"; std::string retrofe_version_build = "15b2";
std::string Version::getString( ) std::string Version::getString( )