Splash screen support. Changed to use Lato font. Fixed issues where lists are empty.

This commit is contained in:
emb 2015-01-11 11:43:35 -06:00
parent 4914a01cee
commit 3ee6663350
13 changed files with 375 additions and 148 deletions

View File

@ -1,14 +1,77 @@
<!-- todo: add collection name text tag, metadata tags -->
<!-- todo: collection name text tag will load image, or text if image does not exist -->
<layout width="1920" height="1080" font="Age.otf" fontColor="ecf0f1">
<layout width="1920" height="1080" font="Lato-Black.ttf" fontColor="ecf0f1">
<sound type="load" src="load.wav" />
<sound type="unload" src="unload.wav" />
<sound type="highlight" src="highlight.wav" />
<sound type="select" src="select.wav" />
<!-- border for game name (in menu) -->
<container backgroundColor="222222" backgroundAlpha="99" x="0" y="bottom" yOrigin="center" yOffset="-175" height="150" width="stretch" layer="1" alpha="0.3" />
<!-- background -->
<container backgroundColor="000000" backgroundAlpha="FF" x="0" y="0" height="stretch" width="stretch" layer="0" alpha="0.3" />
<!-- border for menu -->
<container backgroundColor="c0392b" backgroundAlpha="99" x="center" y="0" height="stretch" width="center" layer="1" alpha="0.3" />
<menu orientation="horizontal" algorithm="easeincircular" xOffset="500" y="0" width="center" height="stretch" speed="0.05" acceleration="0.05" layer="3">
<itemDefaults spacing="10" x="center" height="30" font-size="30" alpha="0.5" xOffset="20" yOrigin="center" />
<item index="start" height="0" spacing="0" alpha="0"/>
<item index="2" spacing="0" height="50" fontSize="50" alpha="1" selected="true"/>
<item index="end" height="0" spacing="0" alpha="0"/>
</menu>
<!-- logo -->
<image x="30" y="20" height="80" src="logo.png" layer="1" alpha="0.3">
<onEnter>
<set duration=".5">
<animate type="y" from="top" to="20" algorithm="easeinquadratic"/>
<animate type="yOrigin" from="bottom" to="top" algorithm="easeincircular"/>
</set>
</onEnter>
<onExit>
<set duration=".25">
<animate type="y" from="20" to="top" algorithm="easeinquadratic"/>
<animate type="yOrigin" from="top" to="bottom" algorithm="easeincircular"/>
</set>
</onExit>
</image>
<!-- video (or snapshot if video doesn't exist)-->
<reloadableVideo imageType="snap" x="480" y="170" xOrigin="center" height="480" width="640" layer="5">
<onHighlightEnter>
<set duration=".4">
<animate type="alpha" from="0" to="1" algorithm="easeinquadratic"/>
</set>
</onHighlightEnter>
<onHighlightExit>
<set duration=".2">
<animate type="alpha" from="1" to="0" algorithm="easeinquadratic"/>
</set>
</onHighlightExit>
</reloadableVideo>
<!-- boxart -->
<!--
<reloadableImage type="box" x="480" y="750" xOrigin="center" height="240" layer="4">
<onHighlightEnter>
<set duration=".4">
<animate type="alpha" from="0" to="1" algorithm="easeinquadratic"/>
</set>
</onHighlightEnter>
<onHighlightExit>
<set duration=".2">
<animate type="alpha" from="1" to="0" algorithm="easeinquadratic"/>
</set>
</onHighlightExit>
</reloadableImage>
-->
<!--
<reloadableText type="title" x="0" y="bottom" xOffset="20" yOrigin="center" yOffset="-175" height="150" width="stretch" layer="1" fontSize="50">
<onHighlightEnter>
<set duration=".2">
@ -23,7 +86,7 @@
</set>
</onHighlightExit>
</reloadableText>
<!--
<reloadableText type="manufacturer" x="left" y="bottom" xOrigin="left" yOrigin="bottom" xOffset="10" yOffset="-10" fontSize="20" layer="0">
</reloadableText>
@ -35,44 +98,7 @@
<reloadableText type="numberButtons" x="left" y="bottom" xOrigin="left" yOrigin="bottom" xOffset="10" yOffset="-90" fontSize="20" layer="0">
</reloadableText>
-->
<menu orientation="horizontal" imageType="title" algorithm="easeincircular" x="100" y="100" height="700" speed="0.05" acceleration="0.05">
<itemDefaults height="50" spacing="10" alpha="0.5" xOffset="20" yOrigin="center" />
<item index="start" height="0" spacing="0" alpha="0"/>
<item index="2" spacing="0" height="100" fontSize="100" alpha="1" selected="true"/>
<item index="end" height="0" spacing="0" alpha="0"/>
</menu>
<image x="30" y="20" height="80" src="logo.png" layer="1" alpha="0.3">
<onEnter>
<set duration=".5">
<animate type="y" from="top" to="20" algorithm="easeinquadratic"/>
<animate type="yOrigin" from="bottom" to="top" algorithm="easeincircular"/>
</set>
</onEnter>
<onExit>
<set duration=".25">
<animate type="y" from="20" to="top" algorithm="easeinquadratic"/>
<animate type="yOrigin" from="top" to="bottom" algorithm="easeincircular"/>
</set>
</onExit>
</image>
<reloadableVideo imageType="snap" x="0" y="0" width="stretch" height="stretch" fontSize="20" layer="0">
<onHighlightEnter>
<set duration=".4">
<animate type="alpha" from="0" to="1" algorithm="easeinquadratic"/>
</set>
</onHighlightEnter>
<onHighlightExit>
<set duration=".2">
<animate type="alpha" from="1" to="0" algorithm="easeinquadratic"/>
</set>
</onHighlightExit>
</reloadableVideo>
</layout>
</layout>

View File

@ -0,0 +1,31 @@
<layout width="1920" height="1080" font="Age.otf" fontColor="ecf0f1">
<!-- border for menu -->
<container backgroundColor="c0392b" backgroundAlpha="99" x="0" y="0" height="stretch" width="stretch" layer="0" alpha="0.3" />
<!-- logo -->
<image x="center" y="center" height="150" xOrigin="center" yOrigin="center" src="logo.png" layer="1" alpha="1">
<onEnter>
<set duration=".5">
<animate type="alpha" from="0" to="1" algorithm="easeinquadratic"/>
</set>
</onEnter>
<onIdle>
<set duration=".5">
<animate type="alpha" from="1" to=".5" algorithm="easeinquadratic"/>
</set>
<set duration=".5">
<animate type="alpha" from=".5" to="1" algorithm="easeinquadratic"/>
</set>
</onIdle>
<onExit>
<set duration=".5">
<animate type="alpha" from="1" to="0" algorithm="easeinquadratic"/>
</set>
</onExit>
</image>
</layout>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 B

View File

@ -0,0 +1,31 @@
<layout width="1920" height="1080" font="Age.otf" fontColor="ecf0f1">
<!-- border for menu -->
<container backgroundColor="c0392b" backgroundAlpha="99" x="0" y="0" height="stretch" width="stretch" layer="0" alpha="0.3" />
<!-- logo -->
<image x="center" y="center" height="150" xOrigin="center" yOrigin="center" src="logo.png" layer="1" alpha="1">
<onEnter>
<set duration=".5">
<animate type="alpha" from="0" to="1" algorithm="easeinquadratic"/>
</set>
</onEnter>
<onIdle>
<set duration=".5">
<animate type="alpha" from="1" to=".5" algorithm="easeinquadratic"/>
</set>
<set duration=".5">
<animate type="alpha" from=".5" to="1" algorithm="easeinquadratic"/>
</set>
</onIdle>
<onExit>
<set duration=".5">
<animate type="alpha" from="1" to="0" algorithm="easeinquadratic"/>
</set>
</onExit>
</image>
</layout>

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@ -97,7 +97,11 @@ void Page::SetMenu(ScrollingList *s)
{
// todo: delete the old menu
Menu = s;
Menu->AddComponentForNotifications(this);
if(Menu)
{
Menu->AddComponentForNotifications(this);
}
}
bool Page::AddComponent(Component *c)
@ -127,7 +131,7 @@ bool Page::IsIdle()
{
bool idle = true;
if(!Menu->IsIdle())
if(Menu && !Menu->IsIdle())
{
idle = false;
}
@ -146,7 +150,7 @@ bool Page::IsIdle()
bool Page::IsHidden()
{
bool hidden = Menu->IsHidden();
bool hidden = (!Menu || Menu->IsHidden());
for(unsigned int i = 0; hidden && i < NUM_LAYERS; ++i)
{
@ -161,7 +165,10 @@ bool Page::IsHidden()
void Page::Start()
{
Menu->TriggerEnterEvent();
if(Menu)
{
Menu->TriggerEnterEvent();
}
if(LoadSoundChunk)
{
@ -179,8 +186,10 @@ void Page::Start()
void Page::Stop()
{
Menu->TriggerExitEvent();
if(Menu)
{
Menu->TriggerExitEvent();
}
if(UnloadSoundChunk)
{
UnloadSoundChunk->Play();
@ -204,7 +213,10 @@ Item *Page::GetSelectedItem()
void Page::RemoveSelectedItem()
{
//todo: change method to RemoveItem() and pass in SelectedItem
Menu->RemoveSelectedItem();
if(Menu)
{
Menu->RemoveSelectedItem();
}
SelectedItem = NULL;
}
@ -216,8 +228,11 @@ void Page::Highlight()
if(item)
{
Menu->TriggerHighlightEvent(item);
Menu->SetScrollActive(ScrollActive);
if(Menu)
{
Menu->TriggerHighlightEvent(item);
Menu->SetScrollActive(ScrollActive);
}
for(unsigned int i = 0; i < NUM_LAYERS; ++i)
{
@ -252,18 +267,24 @@ void Page::SetScrolling(ScrollDirection direction)
break;
}
Menu->SetScrollDirection(menuDirection);
if(Menu)
{
Menu->SetScrollDirection(menuDirection);
}
}
void Page::PageScroll(ScrollDirection direction)
{
if(direction == ScrollDirectionForward)
if(Menu)
{
Menu->PageDown();
}
if(direction == ScrollDirectionBack)
{
Menu->PageUp();
if(direction == ScrollDirectionForward)
{
Menu->PageDown();
}
if(direction == ScrollDirectionBack)
{
Menu->PageUp();
}
}
}
@ -271,16 +292,20 @@ void Page::PageScroll(ScrollDirection direction)
void Page::SetItems(std::vector<Item *> *items)
{
std::vector<ComponentItemBinding *> *sprites = ComponentItemBindingBuilder::BuildCollectionItems(items);
Menu->SetItems(sprites);
if(Menu)
{
Menu->SetItems(sprites);
}
}
void Page::Update(float dt)
{
Menu->Update(dt);
if(Menu)
{
Menu->Update(dt);
}
if(SelectedItemChanged && !HasSoundedWhenActive && HighlightSoundChunk)
{
// skip the first sound being played (as it is part of the on-enter)
@ -317,7 +342,10 @@ void Page::Draw()
(*it)->Draw();
}
Menu->Draw(i);
if(Menu)
{
Menu->Draw(i);
}
}
}
@ -329,7 +357,10 @@ const std::string& Page::GetCollectionName() const
void Page::FreeGraphicsMemory()
{
Logger::Write(Logger::ZONE_DEBUG, "Page", "Free");
Menu->FreeGraphicsMemory();
if(Menu)
{
Menu->FreeGraphicsMemory();
}
if(LoadSoundChunk) LoadSoundChunk->Free();
if(UnloadSoundChunk) UnloadSoundChunk->Free();
@ -349,7 +380,10 @@ void Page::AllocateGraphicsMemory()
{
FirstSoundPlayed = false;
Logger::Write(Logger::ZONE_DEBUG, "Page", "Allocating graphics memory");
Menu->AllocateGraphicsMemory();
if(Menu)
{
Menu->AllocateGraphicsMemory();
}
if(LoadSoundChunk) LoadSoundChunk->Allocate();
if(UnloadSoundChunk) UnloadSoundChunk->Allocate();
@ -368,7 +402,10 @@ void Page::AllocateGraphicsMemory()
void Page::LaunchEnter()
{
Menu->LaunchEnter();
if(Menu)
{
Menu->LaunchEnter();
}
for(unsigned int i = 0; i < NUM_LAYERS; ++i)
{
@ -381,7 +418,10 @@ void Page::LaunchEnter()
void Page::LaunchExit()
{
Menu->LaunchExit();
if(Menu)
{
Menu->LaunchExit();
}
for(unsigned int i = 0; i < NUM_LAYERS; ++i)
{

View File

@ -229,6 +229,8 @@ Page *PageBuilder::BuildPage()
Logger::Write(Logger::ZONE_DEBUG, "Layout", "Created page");
}
Logger::Write(Logger::ZONE_INFO, "Layout", "Initialized");
return page;
}
@ -307,14 +309,12 @@ bool PageBuilder::BuildComponents(xml_node<> *layout, Page *page)
{
xml_node<> *menuXml = layout->first_node("menu");
if(!menuXml)
if(menuXml)
{
Logger::Write(Logger::ZONE_ERROR, "Layout", "Missing menu tag");
return false;
ScrollingList *scrollingList = BuildMenu(menuXml);
page->SetMenu(scrollingList);
}
ScrollingList *scrollingList = BuildMenu(menuXml);
page->SetMenu(scrollingList);
for(xml_node<> *componentXml = layout->first_node("container"); componentXml; componentXml = componentXml->next_sibling("container"))
{

View File

@ -18,7 +18,6 @@
#include "Database/CollectionDatabase.h"
#include "Collection/CollectionInfoBuilder.h"
#include "Collection/CollectionInfo.h"
#include "Database/DB.h"
#include "Database/MamelistMetadata.h"
#include "Execute/Launcher.h"
#include "Utility/Log.h"
@ -49,26 +48,9 @@ int main(int argc, char *argv[])
return -1;
}
DB db(Configuration::GetAbsolutePath() + "/cache.db");
RetroFE p(config);
if(!db.Initialize())
{
return -1;
}
CollectionDatabase *cdb = InitializeCollectionDatabase(db, config);
if(!cdb)
{
return -1;
}
RetroFE p(*cdb, config);
if(p.Initialize())
{
p.Run();
}
p.Run();
p.DeInitialize();
@ -184,24 +166,3 @@ bool StartLogging()
return true;
}
CollectionDatabase *InitializeCollectionDatabase(DB &db, Configuration &config)
{
CollectionDatabase *cdb = NULL;
std::string dbFile = (Configuration::GetAbsolutePath() + "/cache.db");
std::ifstream infile(dbFile.c_str());
cdb = new CollectionDatabase(db, config);
if(!cdb->Initialize())
{
delete cdb;
cdb = NULL;
}
else if(!cdb->Import())
{
delete cdb;
cdb = NULL;
}
return cdb;
}

View File

@ -33,11 +33,15 @@
#ifdef WIN32
#include <Windows.h>
#include <SDL2/SDL_syswm.h>
#include <SDL2/SDL_thread.h>
#endif
RetroFE::RetroFE(CollectionDatabase &db, Configuration &c)
: Config(c)
, CollectionDB(db)
RetroFE::RetroFE(Configuration &c)
: Initialized(false)
, InitializeThread(NULL)
, Config(c)
, Db(NULL)
, CollectionDB(NULL)
, Input(Config)
, KeyInputDisable(0)
, CurrentTime(0)
@ -49,41 +53,88 @@ RetroFE::~RetroFE()
DeInitialize();
}
CollectionDatabase *RetroFE::InitializeCollectionDatabase(DB &db, Configuration &config)
{
CollectionDatabase *cdb = NULL;
std::string dbFile = (Configuration::GetAbsolutePath() + "/cache.db");
std::ifstream infile(dbFile.c_str());
cdb = new CollectionDatabase(db, config);
if(!cdb->Initialize())
{
delete cdb;
cdb = NULL;
}
else if(!cdb->Import())
{
delete cdb;
cdb = NULL;
}
return cdb;
}
void RetroFE::Render()
{
SDL_LockMutex(SDL::GetMutex());
SDL_SetRenderDrawColor(SDL::GetRenderer(), 0x0, 0x0, 0x00, 0xFF);
SDL_RenderClear(SDL::GetRenderer());
Page *page = PageChain.back();
if(page)
if(PageChain.size() > 0)
{
page->Draw();
}
Page *page = PageChain.back();
if(page)
{
page->Draw();
}
}
SDL_RenderPresent(SDL::GetRenderer());
SDL_UnlockMutex(SDL::GetMutex());
}
bool RetroFE::Initialize()
int RetroFE::Initialize(void *context)
{
int retVal = 0;
RetroFE *instance = static_cast<RetroFE *>(context);
Logger::Write(Logger::ZONE_INFO, "RetroFE", "Initializing");
if(!Input.Initialize()) return false;
if(!SDL::Initialize(Config)) return false;
FC.Initialize();
bool videoEnable = true;
int videoLoop = 0;
Config.GetProperty("videoEnable", videoEnable);
Config.GetProperty("videoLoop", videoLoop);
if(!instance->Input.Initialize()) return -1;
instance->Db = new DB(Configuration::GetAbsolutePath() + "/cache.db");
if(!instance->Db->Initialize())
{
Logger::Write(Logger::ZONE_ERROR, "RetroFE", "Could not initialize database");
return -1;
}
instance->CollectionDB = instance->InitializeCollectionDatabase(*instance->Db, instance->Config);
if(!instance->CollectionDB)
{
Logger::Write(Logger::ZONE_ERROR, "RetroFE", "Could not initialize CollectionDB!");
delete instance->Db;
return -1;
}
instance->FC.Initialize();
instance->Config.GetProperty("videoEnable", videoEnable);
instance->Config.GetProperty("videoLoop", videoLoop);
VideoFactory::SetEnabled(videoEnable);
VideoFactory::SetNumLoops(videoLoop);
return true;
instance->Initialized = true;
return 0;
}
void RetroFE::LaunchEnter()
@ -149,32 +200,59 @@ bool RetroFE::DeInitialize()
delete page;
PageChain.pop_back();
}
if(Db)
{
delete Db;
Db = NULL;
}
if(CollectionDB)
{
delete CollectionDB;
Db = NULL;
}
Initialized = false;
//todo: handle video deallocation
return retVal;
}
void RetroFE::Run()
{
if(!SDL::Initialize(Config)) return;
InitializeThread = SDL_CreateThread(Initialize, "RetroFEInit", (void *)this);
if(!InitializeThread)
{
Logger::Write(Logger::ZONE_INFO, "RetroFE", "Could not initialize RetroFE");
return;
}
int attractModeTime = 0;
std::string firstCollection = "Main";
bool running = true;
Item *nextPageItem = NULL;
bool adminMode = false;
RETROFE_STATE state = RETROFE_IDLE;
RETROFE_STATE state = RETROFE_NEW;
Config.GetProperty("attractModeTime", attractModeTime);
Config.GetProperty("firstCollection", firstCollection);
Attract.SetIdleTime(static_cast<float>(attractModeTime));
LoadPage(firstCollection);
int initializeStatus = 0;
// load the initial splash screen, unload it once it is complete
Page * page = LoadSplashPage();
bool splashMode = true;
Launcher l(*this, Config);
while (running)
{
float lastTime = 0;
float deltaTime = 0;
Page *page = PageChain.back();
Launcher l(*this, Config);
page = PageChain.back();
if(!page)
{
@ -182,12 +260,22 @@ void RetroFE::Run()
running = false;
break;
}
// todo: This could be transformed to use the state design pattern.
switch(state)
{
case RETROFE_IDLE:
state = ProcessUserInput(page);
if(page && !splashMode)
{
state = ProcessUserInput(page);
}
if(Initialized && splashMode)
{
SDL_WaitThread(InitializeThread, &initializeStatus);
state = RETROFE_BACK_WAIT;
page->Stop();
}
break;
case RETROFE_NEXT_PAGE_REQUEST:
@ -219,7 +307,8 @@ void RetroFE::Run()
PageChain.pop_back();
delete page;
page = PageChain.back();
page = (splashMode) ? LoadPage(firstCollection) : PageChain.back();
splashMode = false;
CurrentTime = (float)SDL_GetTicks() / 1000;
page->AllocateGraphicsMemory();
@ -267,12 +356,16 @@ void RetroFE::Run()
SDL_Delay(static_cast<unsigned int>(sleepTime));
}
Attract.Update(deltaTime, *page);
if(page)
{
Attract.Update(deltaTime, *page);
page->Update(deltaTime);
}
page->Update(deltaTime);
Render();
}
}
}
@ -372,6 +465,30 @@ RetroFE::RETROFE_STATE RetroFE::ProcessUserInput(Page *page)
}
void RetroFE::WaitToInitialize()
{
Logger::Write(Logger::ZONE_INFO, "RetroFE", "Loading splash screen");
PageBuilder pb("splash", "", Config, &FC);
Page * page = pb.BuildPage();
while(!Initialized)
{
SDL_SetRenderDrawColor(SDL::GetRenderer(), 0x0, 0x0, 0x00, 0xFF);
SDL_RenderClear(SDL::GetRenderer());
// image->Draw();
//todo: decouple page from a collection
page->Draw();
SDL_RenderPresent(SDL::GetRenderer());
SDL_Delay(2000);
}
int status = 0;
delete page;
SDL_WaitThread(InitializeThread, &status);
}
Page *RetroFE::LoadPage(std::string collectionName)
{
@ -405,14 +522,27 @@ Page *RetroFE::LoadPage(std::string collectionName)
return page;
}
Page *RetroFE::LoadSplashPage()
{
PageBuilder pb("splash", "", Config, &FC);
std::vector<Item *> *coll = new std::vector<Item *>();
Page * page = pb.BuildPage();
page->SetItems(coll);
page->Start();
PageChain.push_back(page);
return page;
}
std::vector<Item *> *RetroFE::GetCollection(std::string collectionName)
{
std::vector<Item *> *collection = new std::vector<Item *>(); // the page will deallocate this once its done
// the page will deallocate this once its done
std::vector<Item *> *collection = new std::vector<Item *>();
MenuParser mp;
mp.GetMenuItems(&CollectionDB, collectionName, *collection);
CollectionDB.GetCollection(collectionName, *collection);
mp.GetMenuItems(CollectionDB, collectionName, *collection);
CollectionDB->GetCollection(collectionName, *collection);
if(collection->size() == 0)
{

View File

@ -5,6 +5,7 @@
#include "Collection/Item.h"
#include "Control/UserInput.h"
#include "Database/DB.h"
#include "Execute/AttractMode.h"
#include "Graphics/FontCache.h"
#include "Video/IVideo.h"
@ -19,9 +20,8 @@ class Page;
class RetroFE
{
public:
RetroFE(CollectionDatabase &db, Configuration &c);
RetroFE(Configuration &c);
virtual ~RetroFE();
bool Initialize();
bool DeInitialize();
void Run();
void FreeGraphicsMemory();
@ -29,6 +29,10 @@ public:
void LaunchEnter();
void LaunchExit();
private:
bool Initialized;
SDL_Thread *InitializeThread;
static int Initialize(void *context);
enum RETROFE_STATE
{
RETROFE_IDLE,
@ -43,15 +47,19 @@ private:
};
void Render();
CollectionDatabase *InitializeCollectionDatabase(DB &db, Configuration &config);
bool Back(bool &exit);
void Quit();
void WaitToInitialize();
Page *LoadPage(std::string collectionName);
Page *LoadSplashPage();
RETROFE_STATE ProcessUserInput(Page *page);
void Update(float dt, bool scrollActive);
std::string GetLayout(std::string collectionName);
std::vector<Item *> *GetCollection(std::string collectionName);
Configuration &Config;
CollectionDatabase &CollectionDB;
DB *Db;
CollectionDatabase *CollectionDB;
UserInput Input;
std::list<Page *> PageChain;
float KeyInputDisable;