Merge with multiple menus

This commit is contained in:
emb 2015-01-30 12:54:22 -06:00
commit da7766f79e
21 changed files with 976 additions and 559 deletions

View File

@ -86,6 +86,7 @@ set(RETROFE_HEADERS
"${RETROFE_DIR}/Source/Execute/Launcher.h" "${RETROFE_DIR}/Source/Execute/Launcher.h"
"${RETROFE_DIR}/Source/Graphics/Animate/Tween.h" "${RETROFE_DIR}/Source/Graphics/Animate/Tween.h"
"${RETROFE_DIR}/Source/Graphics/Animate/TweenTypes.h" "${RETROFE_DIR}/Source/Graphics/Animate/TweenTypes.h"
"${RETROFE_DIR}/Source/Graphics/Animate/TweenSet.h"
"${RETROFE_DIR}/Source/Graphics/ComponentItemBinding.h" "${RETROFE_DIR}/Source/Graphics/ComponentItemBinding.h"
"${RETROFE_DIR}/Source/Graphics/Component/Container.h" "${RETROFE_DIR}/Source/Graphics/Component/Container.h"
"${RETROFE_DIR}/Source/Graphics/Component/Component.h" "${RETROFE_DIR}/Source/Graphics/Component/Component.h"
@ -126,12 +127,13 @@ set(RETROFE_SOURCES
"${RETROFE_DIR}/Source/Database/MetadataDatabase.cpp" "${RETROFE_DIR}/Source/Database/MetadataDatabase.cpp"
"${RETROFE_DIR}/Source/Execute/AttractMode.cpp" "${RETROFE_DIR}/Source/Execute/AttractMode.cpp"
"${RETROFE_DIR}/Source/Execute/Launcher.cpp" "${RETROFE_DIR}/Source/Execute/Launcher.cpp"
"${RETROFE_DIR}/Source/Graphics/Animate/Tween.cpp"
"${RETROFE_DIR}/Source/Graphics/Font.cpp" "${RETROFE_DIR}/Source/Graphics/Font.cpp"
"${RETROFE_DIR}/Source/Graphics/FontCache.cpp" "${RETROFE_DIR}/Source/Graphics/FontCache.cpp"
"${RETROFE_DIR}/Source/Graphics/PageBuilder.cpp" "${RETROFE_DIR}/Source/Graphics/PageBuilder.cpp"
"${RETROFE_DIR}/Source/Graphics/Page.cpp" "${RETROFE_DIR}/Source/Graphics/Page.cpp"
"${RETROFE_DIR}/Source/Graphics/ViewInfo.cpp" "${RETROFE_DIR}/Source/Graphics/ViewInfo.cpp"
"${RETROFE_DIR}/Source/Graphics/Animate/Tween.cpp"
"${RETROFE_DIR}/Source/Graphics/Animate/TweenSet.cpp"
"${RETROFE_DIR}/Source/Graphics/ComponentItemBindingBuilder.cpp" "${RETROFE_DIR}/Source/Graphics/ComponentItemBindingBuilder.cpp"
"${RETROFE_DIR}/Source/Graphics/ComponentItemBinding.cpp" "${RETROFE_DIR}/Source/Graphics/ComponentItemBinding.cpp"
"${RETROFE_DIR}/Source/Graphics/Component/Container.cpp" "${RETROFE_DIR}/Source/Graphics/Component/Container.cpp"

View File

@ -56,7 +56,6 @@ bool MenuParser::GetMenuItems(CollectionInfo *collection)
// gracefully exit if there is no menu file for the pa // gracefully exit if there is no menu file for the pa
if(file.good()) if(file.good())
{ {
Logger::Write(Logger::ZONE_INFO, "Menu", "Found menu");
std::vector<char> buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); std::vector<char> buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
buffer.push_back('\0'); buffer.push_back('\0');

View File

@ -41,6 +41,8 @@ Configuration::~Configuration()
void Configuration::Initialize() void Configuration::Initialize()
{ {
Configuration::SetAbsolutePath("D:/RetroFE");
#if 0
const char *environment = std::getenv("RETROFE_PATH"); const char *environment = std::getenv("RETROFE_PATH");
std::string environmentStr; std::string environmentStr;
if (environment != NULL) if (environment != NULL)
@ -68,6 +70,7 @@ void Configuration::Initialize()
Configuration::SetAbsolutePath(sPath); Configuration::SetAbsolutePath(sPath);
} }
#endif
} }
void Configuration::SetCurrentCollection(std::string collection) void Configuration::SetCurrentCollection(std::string collection)

View File

@ -1,5 +1,17 @@
/* This file is subject to the terms and conditions defined in /* This file is part of RetroFE.
* file 'LICENSE.txt', which is part of this source code package. *
* 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 #pragma once

View File

@ -0,0 +1,74 @@
/* 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
#include "Tween.h"
#include <string>
#include <vector>
class TweenSet
{
public:
typedef std::vector<std::vector<Tween *> *> TweenSets;
//todo: delete the tweens in a destructor
TweenSets *GetOnEnterTweens()
{
return &OnEnterTweens;
}
TweenSets *GetOnExitTweens()
{
return &OnExitTweens;
}
TweenSets *GetOnIdleTweens()
{
return &OnIdleTweens;
}
TweenSets *GetOnHighlightEnterTweens()
{
return &OnHighlightEnterTweens;
}
TweenSets *GetOnHighlightExitTweens()
{
return &OnHighlightExitTweens;
}
TweenSets *GetOnMenuEnterTweens()
{
return &OnMenuEnterTweens;
}
TweenSets *GetOnMenuScrollTweens()
{
return &OnMenuScrollTweens;
}
TweenSets *GetOnMenuExitTweens()
{
return &OnMenuExitTweens;
}
private:
TweenSets OnEnterTweens;
TweenSets OnExitTweens;
TweenSets OnIdleTweens;
TweenSets OnHighlightEnterTweens;
TweenSets OnHighlightExitTweens;
TweenSets OnMenuEnterTweens;
TweenSets OnMenuScrollTweens;
TweenSets OnMenuExitTweens;
};

View File

@ -21,15 +21,12 @@
Component::Component() Component::Component()
{ {
OnEnterTweens = NULL; Tweens = NULL;
OnExitTweens = NULL;
OnIdleTweens = NULL;
OnHighlightEnterTweens = NULL;
OnHighlightExitTweens = NULL;
SelectedItem = NULL; SelectedItem = NULL;
NewItemSelectedSinceEnter = false; NewItemSelectedSinceEnter = false;
BackgroundTexture = NULL; BackgroundTexture = NULL;
FreeGraphicsMemory(); FreeGraphicsMemory();
} }
Component::~Component() Component::~Component()
@ -42,6 +39,10 @@ void Component::FreeGraphicsMemory()
CurrentAnimationState = HIDDEN; CurrentAnimationState = HIDDEN;
EnterRequested = false; EnterRequested = false;
ExitRequested = false; ExitRequested = false;
MenuEnterRequested = false;
MenuScrollRequested = false;
MenuExitRequested = false;
NewItemSelected = false; NewItemSelected = false;
HighlightExitComplete = false; HighlightExitComplete = false;
CurrentTweens = NULL; CurrentTweens = NULL;
@ -87,6 +88,23 @@ void Component::TriggerExitEvent()
ExitRequested = true; ExitRequested = true;
} }
void Component::TriggerMenuEnterEvent()
{
MenuEnterRequested = true;
}
void Component::TriggerMenuScrollEvent()
{
MenuScrollRequested = true;
}
void Component::TriggerMenuExitEvent()
{
MenuExitRequested = true;
}
void Component::TriggerHighlightEvent(Item *selectedItem) void Component::TriggerHighlightEvent(Item *selectedItem)
{ {
NewItemSelected = true; NewItemSelected = true;
@ -108,6 +126,22 @@ bool Component::IsWaiting()
return (CurrentAnimationState == HIGHLIGHT_WAIT); return (CurrentAnimationState == HIGHLIGHT_WAIT);
} }
bool Component::IsMenuScrolling()
{
return (CurrentAnimationState == MENU_ENTER || CurrentAnimationState == MENU_SCROLL || CurrentAnimationState == MENU_EXIT || MenuScrollRequested);
}
std::string Component::GetCollectionName()
{
return CollectionName;
}
void Component::SetCollectionName(std::string collectionName)
{
CollectionName = collectionName;
}
void Component::Update(float dt) void Component::Update(float dt)
{ {
ElapsedTweenTime += dt; ElapsedTweenTime += dt;
@ -122,21 +156,38 @@ void Component::Update(float dt)
CurrentTweens = NULL; CurrentTweens = NULL;
// There was no request to override our state path. Continue on as normal. // There was no request to override our state path. Continue on as normal.
std::stringstream ss;
switch(CurrentAnimationState) switch(CurrentAnimationState)
{ {
case MENU_ENTER:
CurrentTweens = NULL;
CurrentAnimationState = IDLE;
break;
case MENU_SCROLL:
CurrentTweens = NULL;
CurrentAnimationState = IDLE;
break;
case MENU_EXIT:
CurrentTweens = NULL;
CurrentAnimationState = IDLE;
Logger::Write(Logger::ZONE_ERROR, "Component", "completed menu exit tween (hidden)");
break;
case ENTER: case ENTER:
CurrentTweens = OnHighlightEnterTweens; CurrentTweens = Tweens->GetOnHighlightEnterTweens();
CurrentAnimationState = HIGHLIGHT_ENTER; CurrentAnimationState = HIGHLIGHT_ENTER;
break; break;
case EXIT: case EXIT:
CurrentTweens = NULL; CurrentTweens = NULL;
CurrentAnimationState = HIDDEN; CurrentAnimationState = HIDDEN;
break; break;
case HIGHLIGHT_ENTER: case HIGHLIGHT_ENTER:
CurrentTweens = OnIdleTweens; CurrentTweens = Tweens->GetOnIdleTweens();
CurrentAnimationState = IDLE; CurrentAnimationState = IDLE;
break; break;
@ -144,17 +195,35 @@ void Component::Update(float dt)
// prevent us from automatically jumping to the exit tween upon enter // prevent us from automatically jumping to the exit tween upon enter
if(EnterRequested) if(EnterRequested)
{ {
EnterRequested = false; EnterRequested = false;
NewItemSelected = false; NewItemSelected = false;
}
else if(MenuEnterRequested)
{
MenuEnterRequested = false;
CurrentTweens = Tweens->GetOnMenuEnterTweens();
CurrentAnimationState = MENU_ENTER;
}
else if(MenuScrollRequested)
{
MenuScrollRequested = false;
CurrentTweens = Tweens->GetOnMenuScrollTweens();
CurrentAnimationState = MENU_SCROLL;
}
else if(MenuExitRequested)
{
MenuExitRequested = false;
CurrentTweens = Tweens->GetOnMenuExitTweens();
CurrentAnimationState = MENU_EXIT;
} }
else if(IsScrollActive() || NewItemSelected || ExitRequested) else if(IsScrollActive() || NewItemSelected || ExitRequested)
{ {
CurrentTweens = OnHighlightExitTweens; CurrentTweens = Tweens->GetOnHighlightExitTweens();
CurrentAnimationState = HIGHLIGHT_EXIT; CurrentAnimationState = HIGHLIGHT_EXIT;
} }
else else
{ {
CurrentTweens = OnIdleTweens; CurrentTweens = Tweens->GetOnIdleTweens();
CurrentAnimationState = IDLE; CurrentAnimationState = IDLE;
} }
break; break;
@ -166,14 +235,14 @@ void Component::Update(float dt)
if(ExitRequested && (CurrentAnimationState == HIGHLIGHT_WAIT)) if(ExitRequested && (CurrentAnimationState == HIGHLIGHT_WAIT))
{ {
CurrentTweens = OnHighlightExitTweens; CurrentTweens = Tweens->GetOnHighlightExitTweens();
CurrentAnimationState = HIGHLIGHT_EXIT; CurrentAnimationState = HIGHLIGHT_EXIT;
} }
else if(ExitRequested && (CurrentAnimationState == HIGHLIGHT_EXIT)) else if(ExitRequested && (CurrentAnimationState == HIGHLIGHT_EXIT))
{ {
CurrentTweens = OnExitTweens; CurrentTweens = Tweens->GetOnExitTweens();
CurrentAnimationState = EXIT; CurrentAnimationState = EXIT;
ExitRequested = false; ExitRequested = false;
} }
@ -184,7 +253,7 @@ void Component::Update(float dt)
} }
else if(NewItemSelected) else if(NewItemSelected)
{ {
CurrentTweens = OnHighlightEnterTweens; CurrentTweens = Tweens->GetOnHighlightEnterTweens();
CurrentAnimationState = HIGHLIGHT_ENTER; CurrentAnimationState = HIGHLIGHT_ENTER;
HighlightExitComplete = true; HighlightExitComplete = true;
NewItemSelected = false; NewItemSelected = false;
@ -199,9 +268,28 @@ void Component::Update(float dt)
case HIDDEN: case HIDDEN:
if(EnterRequested || ExitRequested) if(EnterRequested || ExitRequested)
{ {
CurrentTweens = OnEnterTweens; CurrentTweens = Tweens->GetOnEnterTweens();
CurrentAnimationState = ENTER; CurrentAnimationState = ENTER;
} }
else if(MenuExitRequested)
{
CurrentTweens = Tweens->GetOnMenuExitTweens();
CurrentAnimationState = MENU_EXIT;
MenuExitRequested = false;
}
else if(MenuEnterRequested)
{
CurrentTweens = Tweens->GetOnMenuEnterTweens();
CurrentAnimationState = MENU_ENTER;
MenuEnterRequested = false;
}
else if(MenuScrollRequested)
{
MenuScrollRequested = false;
CurrentTweens = Tweens->GetOnMenuScrollTweens();
CurrentAnimationState = MENU_SCROLL;
}
else else
{ {
CurrentTweens = NULL; CurrentTweens = NULL;

View File

@ -1,5 +1,17 @@
/* This file is subject to the terms and conditions defined in /* This file is part of RetroFE.
* file 'LICENSE.txt', which is part of this source code package. *
* 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 #pragma once
@ -9,6 +21,7 @@
#include "../MenuNotifierInterface.h" #include "../MenuNotifierInterface.h"
#include "../ViewInfo.h" #include "../ViewInfo.h"
#include "../Animate/Tween.h" #include "../Animate/Tween.h"
#include "../Animate/TweenSet.h"
#include "../../Collection/Item.h" #include "../../Collection/Item.h"
class Component class Component
@ -22,36 +35,29 @@ public:
virtual void LaunchExit() {} virtual void LaunchExit() {}
void TriggerEnterEvent(); void TriggerEnterEvent();
void TriggerExitEvent(); void TriggerExitEvent();
void TriggerMenuEnterEvent();
void TriggerMenuExitEvent();
void TriggerMenuScrollEvent();
void TriggerHighlightEvent(Item *selectedItem); void TriggerHighlightEvent(Item *selectedItem);
bool IsIdle(); bool IsIdle();
bool IsHidden(); bool IsHidden();
bool IsWaiting(); bool IsWaiting();
bool IsMenuScrolling();
std::string GetCollectionName();
void SetCollectionName(std::string collectionName);
typedef std::vector<std::vector<Tween *> *> TweenSets; typedef std::vector<std::vector<Tween *> *> TweenSets;
void SetOnEnterTweens(TweenSets *tweens) TweenSet *GetTweens() { return Tweens; }
void SetTweens(TweenSet *set)
{ {
this->OnEnterTweens = tweens; Tweens = set;
CurrentAnimationState = IDLE;
CurrentTweenIndex = 0;
CurrentTweenComplete = false;
ElapsedTweenTime = 0;
} }
void SetOnExitTweens(TweenSets *tweens)
{
this->OnExitTweens = tweens;
}
void SetOnIdleTweens(TweenSets *tweens)
{
this->OnIdleTweens = tweens;
}
void SetOnHighlightEnterTweens(TweenSets *tweens)
{
this->OnHighlightEnterTweens = tweens;
}
void SetOnHighlightExitTweens(TweenSets *tweens)
{
this->OnHighlightExitTweens = tweens;
}
virtual void Update(float dt); virtual void Update(float dt);
virtual void Draw(); virtual void Draw();
@ -78,6 +84,7 @@ public:
protected: protected:
std::string CollectionName;
Item *GetSelectedItem() Item *GetSelectedItem()
{ {
return SelectedItem; return SelectedItem;
@ -90,12 +97,18 @@ protected:
HIGHLIGHT_WAIT, HIGHLIGHT_WAIT,
HIGHLIGHT_ENTER, HIGHLIGHT_ENTER,
EXIT, EXIT,
MENU_ENTER,
MENU_SCROLL,
MENU_EXIT,
HIDDEN HIDDEN
}; };
AnimationState CurrentAnimationState; AnimationState CurrentAnimationState;
bool EnterRequested; bool EnterRequested;
bool ExitRequested; bool ExitRequested;
bool MenuEnterRequested;
bool MenuScrollRequested;
bool MenuExitRequested;
bool NewItemSelected; bool NewItemSelected;
bool HighlightExitComplete; bool HighlightExitComplete;
bool NewItemSelectedSinceEnter; bool NewItemSelectedSinceEnter;
@ -103,13 +116,7 @@ private:
bool Animate(bool loop); bool Animate(bool loop);
bool IsTweenSequencingComplete(); bool IsTweenSequencingComplete();
void ResetTweenSequence(std::vector<ViewInfo *> *tweens); void ResetTweenSequence(std::vector<ViewInfo *> *tweens);
TweenSet *Tweens;
TweenSets *OnEnterTweens;
TweenSets *OnExitTweens;
TweenSets *OnIdleTweens;
TweenSets *OnHighlightEnterTweens;
TweenSets *OnHighlightExitTweens;
TweenSets *CurrentTweens; TweenSets *CurrentTweens;
unsigned int CurrentTweenIndex; unsigned int CurrentTweenIndex;

View File

@ -27,12 +27,12 @@
#include <vector> #include <vector>
#include <iostream> #include <iostream>
ReloadableMedia::ReloadableMedia(std::string imagePath, std::string videoPath, bool isVideo, float scaleX, float scaleY) ReloadableMedia::ReloadableMedia(Configuration &config, std::string type, bool isVideo, float scaleX, float scaleY)
: LoadedComponent(NULL) : Config(config)
, ImagePath(imagePath) , LoadedComponent(NULL)
, VideoPath(videoPath)
, ReloadRequested(false) , ReloadRequested(false)
, FirstLoad(true) , FirstLoad(true)
, Type(type)
, IsVideo(isVideo) , IsVideo(isVideo)
, ScaleX(scaleX) , ScaleX(scaleX)
, ScaleY(scaleY) , ScaleY(scaleY)
@ -134,19 +134,14 @@ void ReloadableMedia::ReloadTexture()
{ {
names.push_back(selectedItem->GetCloneOf()); names.push_back(selectedItem->GetCloneOf());
} }
std::string videoPath;
Config.GetMediaPropertyAbsolutePath(GetCollectionName(), "video", videoPath);
for(unsigned int n = 0; n < names.size() && !found; ++n) for(unsigned int n = 0; n < names.size() && !found; ++n)
{ {
std::string filePrefix;
filePrefix.append(VideoPath);
filePrefix.append("/");
filePrefix.append(names[n]);
std::string file;
VideoBuilder videoBuild; VideoBuilder videoBuild;
LoadedComponent = videoBuild.CreateVideo(VideoPath, names[n], ScaleX, ScaleY); LoadedComponent = videoBuild.CreateVideo(videoPath, names[n], ScaleX, ScaleY);
if(LoadedComponent) if(LoadedComponent)
{ {
@ -158,8 +153,10 @@ void ReloadableMedia::ReloadTexture()
if(!LoadedComponent) if(!LoadedComponent)
{ {
std::string imagePath;
Config.GetMediaPropertyAbsolutePath(GetCollectionName(), Type, imagePath);
ImageBuilder imageBuild; ImageBuilder imageBuild;
LoadedComponent = imageBuild.CreateImage(ImagePath, selectedItem->GetFullTitle(), ScaleX, ScaleY); LoadedComponent = imageBuild.CreateImage(imagePath, selectedItem->GetFullTitle(), ScaleX, ScaleY);
if (LoadedComponent != NULL) if (LoadedComponent != NULL)
{ {

View File

@ -14,7 +14,7 @@ class Image;
class ReloadableMedia : public Component class ReloadableMedia : public Component
{ {
public: public:
ReloadableMedia(std::string imagePath, std::string videoPath, bool isVideo, float scaleX, float scaleY); ReloadableMedia(Configuration &config, std::string type, bool isVideo, float scaleX, float scaleY);
virtual ~ReloadableMedia(); virtual ~ReloadableMedia();
void Update(float dt); void Update(float dt);
void Draw(); void Draw();
@ -25,14 +25,14 @@ public:
private: private:
void ReloadTexture(); void ReloadTexture();
Configuration &Config;
Component *LoadedComponent; Component *LoadedComponent;
std::string ImagePath;
std::string VideoPath;
bool ReloadRequested; bool ReloadRequested;
bool FirstLoad; bool FirstLoad;
IVideo *VideoInst; IVideo *VideoInst;
bool IsVideo; bool IsVideo;
std::string Type;
float ScaleX; float ScaleX;
float ScaleY; float ScaleY;
}; };

View File

@ -23,10 +23,9 @@
#include <vector> #include <vector>
#include <iostream> #include <iostream>
ReloadableText::ReloadableText(std::string type, Font *font, SDL_Color color, std::string layoutKey, std::string collection, float scaleX, float scaleY) ReloadableText::ReloadableText(std::string type, Font *font, SDL_Color color, std::string layoutKey, float scaleX, float scaleY)
: ImageInst(NULL) : ImageInst(NULL)
, LayoutKey(layoutKey) , LayoutKey(layoutKey)
, Collection(collection)
, ReloadRequested(false) , ReloadRequested(false)
, FirstLoad(true) , FirstLoad(true)
, FontInst(font) , FontInst(font)

View File

@ -12,7 +12,7 @@
class ReloadableText : public Component class ReloadableText : public Component
{ {
public: public:
ReloadableText(std::string type, Font *font, SDL_Color color, std::string layoutKey, std::string collectionName, float scaleX, float scaleY); ReloadableText(std::string type, Font *font, SDL_Color color, std::string layoutKey, float scaleX, float scaleY);
virtual ~ReloadableText(); virtual ~ReloadableText();
void Update(float dt); void Update(float dt);
void Draw(); void Draw();
@ -37,7 +37,6 @@ private:
Text *ImageInst; Text *ImageInst;
TextType Type; TextType Type;
std::string LayoutKey; std::string LayoutKey;
std::string Collection;
bool ReloadRequested; bool ReloadRequested;
bool FirstLoad; bool FirstLoad;
Font *FontInst; Font *FontInst;

View File

@ -41,37 +41,98 @@ ScrollingList::ScrollingList(Configuration &c,
Font *font, Font *font,
SDL_Color fontColor, SDL_Color fontColor,
std::string layoutKey, std::string layoutKey,
std::string collectionName,
std::string imageType) std::string imageType)
: IsScrollChangedStarted(true) : SpriteList(NULL)
, IsScrollChangedSignalled(false)
, IsScrollChangedComplete(false)
, SpriteList(NULL)
, ScrollPoints(NULL) , ScrollPoints(NULL)
, TweenEnterTime(0) , TweenEnterTime(0)
, FirstSpriteIndex(0) , FirstSpriteIndex(0)
, SelectedSpriteListIndex(0) , SelectedSpriteListIndex(0)
, CurrentAnimateTime(0) // in seconds , ScrollStopRequested(true)
, ScrollTime(0) // in seconds
, CurrentScrollDirection(ScrollDirectionIdle) , CurrentScrollDirection(ScrollDirectionIdle)
, RequestedScrollDirection(ScrollDirectionIdle) , RequestedScrollDirection(ScrollDirectionIdle)
, CurrentScrollState(ScrollStateIdle) , CurrentScrollState(ScrollStateIdle)
, ScrollAcceleration(6) // todo: make configurable , ScrollAcceleration(6) // todo: make configurable
, ScrollVelocity(0) , ScrollPeriod(0)
, Config(c) , Config(c)
, ScaleX(scaleX) , ScaleX(scaleX)
, ScaleY(scaleY) , ScaleY(scaleY)
, FontInst(font) , FontInst(font)
, FontColor(fontColor) , FontColor(fontColor)
, LayoutKey(layoutKey) , LayoutKey(layoutKey)
, CollectionName(collectionName)
, ImageType(imageType) , ImageType(imageType)
, MaxLayer(0) , MaxLayer(0)
, Focus(false)
{ {
} }
ScrollingList::~ScrollingList() ScrollingList::~ScrollingList()
{ {
DestroyItems();
}
void ScrollingList::SetItems(std::vector<ComponentItemBinding *> *spriteList)
{
SpriteList = spriteList;
FirstSpriteIndex = 0;
if(!SpriteList) { return ; }
unsigned int originalSize = SpriteList->size();
// loop the scroll points if there are not enough, the +2 represents the head and tail nodes (for when the item is allocated)
while(ScrollPoints && ScrollPoints->size()+2 > SpriteList->size() && SpriteList->size() > 0)
{
for(unsigned int i = 0; i < originalSize; ++i)
{
Item *newItem = new Item();
Item *originalItem = SpriteList->at(i)->GetCollectionItem();
*newItem = *originalItem;
ComponentItemBinding *newSprite = new ComponentItemBinding(newItem);
SpriteList->push_back(newSprite);
}
}
for(unsigned int i = 0; ScrollPoints && i < SelectedSpriteListIndex; ++i)
{
CircularDecrement(FirstSpriteIndex, SpriteList);
}
AllocateSpritePoints();
}
void ScrollingList::DeallocateSpritePoints()
{
unsigned int spriteIndex = FirstSpriteIndex;
for(unsigned int i = 0; i < ScrollPoints->size(); ++i)
{
DeallocateTexture(SpriteList->at(spriteIndex));
CircularIncrement(spriteIndex, SpriteList);
}
}
void ScrollingList::AllocateSpritePoints()
{
unsigned int spriteIndex = FirstSpriteIndex;
for(unsigned int i = 0; i < ScrollPoints->size(); ++i)
{
AllocateTexture(SpriteList->at(spriteIndex));
Component *c = SpriteList->at(spriteIndex)->GetComponent();
ViewInfo *currentViewInfo = ScrollPoints->at(i);
unsigned int nextI = GetNextTween(i, ScrollPoints);
ViewInfo *nextViewInfo = ScrollPoints->at(nextI);
ResetTweens(c, TweenPoints->at(i), currentViewInfo, nextViewInfo, 0);
CircularIncrement(spriteIndex, SpriteList);
}
}
void ScrollingList::DestroyItems()
{
if(SpriteList) if(SpriteList)
{ {
std::vector<ComponentItemBinding *>::iterator it = SpriteList->begin(); std::vector<ComponentItemBinding *>::iterator it = SpriteList->begin();
@ -81,6 +142,7 @@ ScrollingList::~ScrollingList()
if(*it != NULL) if(*it != NULL)
{ {
DeallocateTexture(*it); DeallocateTexture(*it);
if((*it)->GetCollectionItem()) if((*it)->GetCollectionItem())
{ {
delete (*it)->GetCollectionItem(); delete (*it)->GetCollectionItem();
@ -89,6 +151,7 @@ ScrollingList::~ScrollingList()
delete *it; delete *it;
} }
SpriteList->erase(it); SpriteList->erase(it);
it = SpriteList->begin(); it = SpriteList->begin();
@ -97,43 +160,14 @@ ScrollingList::~ScrollingList()
delete SpriteList; delete SpriteList;
SpriteList = NULL; SpriteList = NULL;
} }
} }
void ScrollingList::SetItems(std::vector<ComponentItemBinding *> *spriteList)
{
SpriteList = spriteList;
FirstSpriteIndex = 0;
// loop the scroll points if there are not enough void ScrollingList::SetPoints(std::vector<ViewInfo *> *scrollPoints, std::vector<TweenSet *> *tweenPoints)
if(SpriteList)
{
unsigned int originalSize = SpriteList->size();
while(ScrollPoints && ScrollPoints->size()+4 > SpriteList->size() && SpriteList->size() > 0)
{
for(unsigned int i = 0; i < originalSize; ++i)
{
Item *newItem = new Item();
Item *originalItem = SpriteList->at(i)->GetCollectionItem();
*newItem = *originalItem;
ComponentItemBinding *newSprite = new ComponentItemBinding(newItem);
SpriteList->push_back(newSprite);
}
}
for(unsigned int i = 0; ScrollPoints && i < SelectedSpriteListIndex; ++i)
{
CircularDecrement(FirstSpriteIndex, SpriteList);
}
IsScrollChangedComplete = true;
}
}
void ScrollingList::SetPoints(std::vector<ViewInfo *> *scrollPoints)
{ {
ScrollPoints = scrollPoints; ScrollPoints = scrollPoints;
TweenPoints = tweenPoints;
for(unsigned int i = 0; i != scrollPoints->size(); ++i) for(unsigned int i = 0; i != scrollPoints->size(); ++i)
{ {
ViewInfo *info = scrollPoints->at(i); ViewInfo *info = scrollPoints->at(i);
@ -150,21 +184,47 @@ void ScrollingList::SetSelectedIndex(int selectedIndex)
{ {
CircularDecrement(FirstSpriteIndex, SpriteList); CircularDecrement(FirstSpriteIndex, SpriteList);
} }
} }
void ScrollingList::Click() void ScrollingList::Click(double nextScrollTime)
{ {
if(!SpriteList) { return; }
if(SpriteList->size() == 0) { return; }
unsigned int listSize = ScrollPoints->size();
unsigned int end = CircularIncrement(FirstSpriteIndex, listSize - 1, SpriteList);
unsigned int allocSpriteIndex = 0;
unsigned int deallocSpriteIndex = 0;
unsigned int allocPoint = 0;
if(CurrentScrollDirection == ScrollDirectionBack) if(CurrentScrollDirection == ScrollDirectionBack)
{ {
deallocSpriteIndex = end;
CircularDecrement(FirstSpriteIndex, SpriteList); CircularDecrement(FirstSpriteIndex, SpriteList);
IsScrollChangedComplete = true; allocSpriteIndex = FirstSpriteIndex;
allocPoint = 0;
} }
if(CurrentScrollDirection == ScrollDirectionForward) else if(CurrentScrollDirection == ScrollDirectionForward)
{ {
deallocSpriteIndex = FirstSpriteIndex;
CircularIncrement(FirstSpriteIndex, SpriteList); CircularIncrement(FirstSpriteIndex, SpriteList);
IsScrollChangedComplete = true; allocSpriteIndex = CircularIncrement(FirstSpriteIndex, listSize - 1, SpriteList);
allocPoint = listSize - 1;
} }
else
{
return;
}
DeallocateTexture(SpriteList->at(deallocSpriteIndex));
AllocateTexture(SpriteList->at(allocSpriteIndex));
Component *c = SpriteList->at(allocSpriteIndex)->GetComponent();
ViewInfo *currentViewInfo = ScrollPoints->at(allocPoint);
unsigned int nextI = GetNextTween(allocPoint, ScrollPoints);
ViewInfo *nextViewInfo = ScrollPoints->at(nextI);
ResetTweens(c, TweenPoints->at(allocPoint), currentViewInfo, nextViewInfo, nextScrollTime);
} }
unsigned int ScrollingList::GetNextTween(unsigned int currentIndex, std::vector<ViewInfo *> *list) unsigned int ScrollingList::GetNextTween(unsigned int currentIndex, std::vector<ViewInfo *> *list)
@ -183,10 +243,12 @@ unsigned int ScrollingList::GetNextTween(unsigned int currentIndex, std::vector<
void ScrollingList::PageUp() void ScrollingList::PageUp()
{ {
if(ScrollPoints && ScrollPoints->size() > 4) DeallocateSpritePoints();
if(SpriteList && ScrollPoints && ScrollPoints->size() > 2)
{ {
ScrollVelocity = 0; ScrollPeriod = 0;
unsigned int counts = ScrollPoints->size() - 4; unsigned int counts = ScrollPoints->size() - 2;
for(unsigned int i = 0; i < counts; i++) for(unsigned int i = 0; i < counts; i++)
{ {
@ -194,44 +256,42 @@ void ScrollingList::PageUp()
} }
} }
CurrentScrollState = ScrollStatePageChange; AllocateSpritePoints();
IsScrollChangedStarted = true;
IsScrollChangedSignalled = false; // CurrentScrollState = ScrollStatePageChange;
IsScrollChangedComplete = false;
} }
void ScrollingList::PageDown() void ScrollingList::PageDown()
{ {
if(ScrollPoints && ScrollPoints->size() > 4) DeallocateSpritePoints();
{
unsigned int counts = ScrollPoints->size() - 4;
ScrollVelocity = 0; if(SpriteList && ScrollPoints && ScrollPoints->size() > 2)
{
unsigned int counts = ScrollPoints->size() - 2;
ScrollPeriod = 0;
for(unsigned int i = 0; i < counts; i++) for(unsigned int i = 0; i < counts; i++)
{ {
CircularIncrement(FirstSpriteIndex, SpriteList); CircularIncrement(FirstSpriteIndex, SpriteList);
} }
} }
CurrentScrollState = ScrollStatePageChange; AllocateSpritePoints();
IsScrollChangedStarted = true; //todo: may want to handle this properly
IsScrollChangedSignalled = false; // CurrentScrollState = ScrollStatePageChange;
IsScrollChangedComplete = false;
} }
void ScrollingList::FreeGraphicsMemory() void ScrollingList::FreeGraphicsMemory()
{ {
Component::FreeGraphicsMemory(); Component::FreeGraphicsMemory();
TweenEnterTime = 0; TweenEnterTime = 0;
CurrentAnimateTime = 0;
ScrollTime = 0;
CurrentScrollDirection = ScrollDirectionIdle; CurrentScrollDirection = ScrollDirectionIdle;
RequestedScrollDirection = ScrollDirectionIdle; RequestedScrollDirection = ScrollDirectionIdle;
CurrentScrollState = ScrollStateIdle; CurrentScrollState = ScrollStateIdle;
ScrollAcceleration = 6; // todo: make configurable ScrollAcceleration = 6; // todo: make configurable
ScrollVelocity = 0; ScrollPeriod = 0;
for(unsigned int i = 0; i < SpriteList->size(); i++) for(unsigned int i = 0; SpriteList && i < SpriteList->size(); i++)
{ {
ComponentItemBinding *s = SpriteList->at(i); ComponentItemBinding *s = SpriteList->at(i);
@ -239,156 +299,151 @@ void ScrollingList::FreeGraphicsMemory()
} }
} }
void ScrollingList::TriggerMenuEnterEvent()
{
Focus = true;
if(!ScrollPoints) { return; }
if(!SpriteList) { return; }
if(SpriteList->size() == 0 ) { return; }
if(FirstSpriteIndex >= SpriteList->size()) { return; }
unsigned int spriteIndex = FirstSpriteIndex;
for(unsigned int i = 0; i < ScrollPoints->size(); ++i)
{
ComponentItemBinding *s = SpriteList->at(spriteIndex);
Component *c = s->GetComponent();
if(c)
{
c->TriggerMenuEnterEvent();
}
CircularIncrement(spriteIndex, SpriteList);
}
}
void ScrollingList::TriggerMenuExitEvent()
{
Focus = false;
if(!ScrollPoints) { return; }
if(!SpriteList) { return; }
if(SpriteList->size() == 0 ) { return; }
if(FirstSpriteIndex >= SpriteList->size()) { return; }
unsigned int spriteIndex = FirstSpriteIndex;
for(unsigned int i = 0; i < ScrollPoints->size(); ++i)
{
ComponentItemBinding *s = SpriteList->at(spriteIndex);
Component *c = s->GetComponent();
if(c)
{
c->TriggerMenuExitEvent();
}
CircularIncrement(spriteIndex, SpriteList);
}
}
void ScrollingList::Update(float dt) void ScrollingList::Update(float dt)
{ {
float scrollPeriod = 0; float scrollPeriod = 0;
bool initializePoints = false;
Component::Update(dt); Component::Update(dt);
if(!ScrollPoints) if(!ScrollPoints) { return; }
if(!SpriteList) { return; }
if(SpriteList->size() == 0) { return; }
bool readyToScroll = true;
bool scrollChanged = false;
bool scrollRequested = false;
bool scrollStopped = false;
// validate all scroll points are done tweening to the next position
for(unsigned int i = 0; i < SpriteList->size(); i++)
{ {
return; ComponentItemBinding *s = SpriteList->at(i);
Component *c = s->GetComponent();
if(c && c->IsMenuScrolling())
{
readyToScroll = false;
break;
}
} }
switch(CurrentScrollState) // check if it was requested to change directions
if(CurrentScrollState == ScrollStateActive && RequestedScrollDirection != CurrentScrollDirection)
{ {
case ScrollStateActive: CurrentScrollState = ScrollStateStopping;
if(RequestedScrollDirection != CurrentScrollDirection) }
{ else if(CurrentScrollState == ScrollStateIdle && readyToScroll)
CurrentScrollState = ScrollStateStopping; {
ScrollPeriod = 0.500;
} // check to see if requested to scroll
break;
case ScrollStateIdle:
ScrollTime = 0;
CurrentAnimateTime = 0;
ScrollVelocity = 0;
if(RequestedScrollDirection != ScrollDirectionIdle) if(RequestedScrollDirection != ScrollDirectionIdle)
{ {
initializePoints = true;
CurrentScrollState = ScrollStateActive; CurrentScrollState = ScrollStateActive;
CurrentScrollDirection = RequestedScrollDirection; CurrentScrollDirection = RequestedScrollDirection;
scrollRequested = true;
} }
break; }
default:
break;
}; // if currently scrolling, process it
if(!scrollRequested && readyToScroll)
if(CurrentScrollState != ScrollStatePageChange && CurrentScrollState != ScrollStateIdle)
{ {
IsScrollChangedStarted = true; if(CurrentScrollState == ScrollStateStopping)
ScrollTime += dt;
CurrentAnimateTime += dt;
ScrollVelocity = ScrollTime * ScrollAcceleration;
// clip at 5 items scrolled per second
if(ScrollVelocity > 30)
{ {
ScrollVelocity = 30; Click(0);
}
if(ScrollVelocity > 0)
{
scrollPeriod = 1 / ScrollVelocity;
}
// have we exceeded the time of when to stop on the next item in the list?
if(CurrentScrollState == ScrollStateStopping && CurrentAnimateTime >= scrollPeriod)
{
Click();
CurrentAnimateTime = 0;
ScrollVelocity = 0;
CurrentScrollState = ScrollStateIdle; CurrentScrollState = ScrollStateIdle;
} scrollStopped = true;
}
// update the tweens now that we are done
unsigned int spriteIndex = FirstSpriteIndex;
while(CurrentScrollState != ScrollStatePageChange && ScrollVelocity > 0 && CurrentAnimateTime >= scrollPeriod) for(unsigned int i = 0; i < TweenPoints->size(); ++i)
{
Click();
CurrentAnimateTime -= scrollPeriod;
}
if(ScrollPoints && SpriteList->size() > 0 && FirstSpriteIndex < SpriteList->size())
{
unsigned int spriteIndex = FirstSpriteIndex;
unsigned int numIterations = (ScrollPoints->size() > SpriteList->size()) ? SpriteList->size() : ScrollPoints->size();
unsigned int start = (ScrollPoints->size() > SpriteList->size()) ? SelectedSpriteListIndex : 0;
for(unsigned int i = start; i < start+numIterations && spriteIndex < SpriteList->size(); i++)
{
ComponentItemBinding *s = SpriteList->at(spriteIndex);
unsigned int nextI = GetNextTween(i, ScrollPoints);
ViewInfo *currentViewInfo = ScrollPoints->at(i);
ViewInfo *nextViewInfo = ScrollPoints->at(nextI);
AllocateTexture(s);
Component *c = s->GetComponent();
if(c)
{ {
currentViewInfo->SetImageHeight(c->GetBaseViewInfo()->GetImageHeight()); ComponentItemBinding *s = SpriteList->at(spriteIndex);
currentViewInfo->SetImageWidth(c->GetBaseViewInfo()->GetImageWidth());
nextViewInfo->SetImageHeight(c->GetBaseViewInfo()->GetImageHeight());
nextViewInfo->SetImageWidth(c->GetBaseViewInfo()->GetImageWidth());
nextViewInfo->SetBackgroundAlpha(c->GetBaseViewInfo()->GetBackgroundAlpha());
//todo: 30 is a magic number Component *c = s->GetComponent();
ViewInfo *spriteViewInfo = c->GetBaseViewInfo(); if(c)
{
c->SetTweens(TweenPoints->at(i));
}
spriteViewInfo->SetX(Tween::AnimateSingle(LINEAR, currentViewInfo->GetX(), nextViewInfo->GetX(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetY(Tween::AnimateSingle(LINEAR, currentViewInfo->GetY(), nextViewInfo->GetY(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetXOrigin(Tween::AnimateSingle(LINEAR, currentViewInfo->GetXOrigin(), nextViewInfo->GetXOrigin(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetYOrigin(Tween::AnimateSingle(LINEAR, currentViewInfo->GetYOrigin(), nextViewInfo->GetYOrigin(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetXOffset(Tween::AnimateSingle(LINEAR, currentViewInfo->GetXOffset(), nextViewInfo->GetXOffset(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetYOffset(Tween::AnimateSingle(LINEAR, currentViewInfo->GetYOffset(), nextViewInfo->GetYOffset(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetHeight(Tween::AnimateSingle(LINEAR, currentViewInfo->GetHeight(), nextViewInfo->GetHeight(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetWidth(Tween::AnimateSingle(LINEAR, currentViewInfo->GetWidth(), nextViewInfo->GetWidth(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetAlpha(Tween::AnimateSingle(LINEAR, currentViewInfo->GetAlpha(), nextViewInfo->GetAlpha(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetAngle(Tween::AnimateSingle(LINEAR, currentViewInfo->GetAngle(), nextViewInfo->GetAngle(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetFontSize(Tween::AnimateSingle(LINEAR, currentViewInfo->GetFontSize(), nextViewInfo->GetFontSize(), scrollPeriod, CurrentAnimateTime));
spriteViewInfo->SetBackgroundAlpha(Tween::AnimateSingle(LINEAR, currentViewInfo->GetBackgroundAlpha(), nextViewInfo->GetBackgroundAlpha(), scrollPeriod, CurrentAnimateTime));
c->Update(dt);
}
CircularIncrement(spriteIndex, SpriteList);
}
// start freeing up memory if the list is too large
if(SpriteList->size() + 4 > ScrollPoints->size())
{
spriteIndex = FirstSpriteIndex;
CircularDecrement(spriteIndex, SpriteList);
DeallocateTexture(SpriteList->at(spriteIndex));
CircularDecrement(spriteIndex, SpriteList);
DeallocateTexture(SpriteList->at(spriteIndex));
// point to the end of the list to start deallocating..
// It's not fast, but it's easy to read
spriteIndex = FirstSpriteIndex;
for(unsigned int i = 0; i < ScrollPoints->size(); i++)
{
CircularIncrement(spriteIndex, SpriteList); CircularIncrement(spriteIndex, SpriteList);
} }
CircularIncrement(spriteIndex, SpriteList); }
DeallocateTexture(SpriteList->at(spriteIndex));
CircularIncrement(spriteIndex, SpriteList); else if(CurrentScrollState == ScrollStateActive)
DeallocateTexture(SpriteList->at(spriteIndex)); {
ScrollPeriod -= 0.050f;
if(ScrollPeriod < 0.050)
{
ScrollPeriod = 0.050f;
}
Click(ScrollPeriod);
scrollChanged = true;
} }
} }
if(IsScrollChangedStarted && !IsScrollChangedSignalled)
unsigned int spriteIndex = FirstSpriteIndex;
for(unsigned int i = 0; i < ScrollPoints->size(); i++)
{
UpdateSprite(spriteIndex, i, (scrollRequested || scrollChanged), dt, ScrollPeriod);
CircularIncrement(spriteIndex, SpriteList);
}
if(scrollStopped || scrollChanged)
{ {
IsScrollChangedSignalled = true;
ComponentItemBinding *sprite = GetPendingCollectionItemSprite(); ComponentItemBinding *sprite = GetPendingCollectionItemSprite();
Item *item = NULL; Item *item = NULL;
@ -410,65 +465,122 @@ void ScrollingList::Update(float dt)
if(CurrentScrollState == ScrollStatePageChange) if(CurrentScrollState == ScrollStatePageChange)
{ {
IsScrollChangedComplete = true;
CurrentScrollState = ScrollStateIdle; CurrentScrollState = ScrollStateIdle;
} }
} }
if(IsScrollChangedStarted && IsScrollChangedSignalled && IsScrollChangedComplete)
{
IsScrollChangedStarted = false;
IsScrollChangedComplete = false;
IsScrollChangedSignalled = false;
}
} }
void ScrollingList::AllocateTexture(ComponentItemBinding *s) void ScrollingList::UpdateSprite(unsigned int spriteIndex, unsigned int pointIndex, bool newScroll, float dt, double nextScrollTime)
{ {
//todo: move this outside of the Draw routine ComponentItemBinding *s = SpriteList->at(spriteIndex);
if(s && s->GetComponent() == NULL)
Component *c = s->GetComponent();
//todo: remove me
if(c && newScroll)
{ {
const Item *item = s->GetCollectionItem(); ViewInfo *currentViewInfo = ScrollPoints->at(pointIndex);
//todo: will create a runtime fault if not of the right type unsigned int nextI = GetNextTween(pointIndex, ScrollPoints);
//todo: remove coupling from knowing the collection name ViewInfo *nextViewInfo = ScrollPoints->at(nextI);
std::string videoKey ="collections." + CollectionName + ".media.video"; ResetTweens(c, TweenPoints->at(pointIndex), currentViewInfo, nextViewInfo, nextScrollTime);
std::string imagePath; c->TriggerMenuScrollEvent();
std::string videoPath; }
if(c)
Component *t = NULL; {
c->Update(dt);
/*
// todo: to be supported at a later date
if(c->GetProperty(videoKey, videoPath))
{
t = new VideoComponent(videoPath, item->GetFullTitle(), ScaleX, ScaleY);
}
*/
if(!t)
{
ImageBuilder imageBuild;
Config.GetMediaPropertyAbsolutePath(CollectionName, ImageType, imagePath);
t = imageBuild.CreateImage(imagePath, item->GetName(), ScaleX, ScaleY);
if(!t && item->GetTitle() != item->GetFullTitle())
{
t = imageBuild.CreateImage(imagePath, item->GetFullTitle(), ScaleX, ScaleY);
}
}
if (!t)
{
t = new Text(item->GetTitle(), FontInst, FontColor, ScaleX, ScaleY);
}
if(t)
{
s->SetComponent(t);
}
} }
CircularIncrement(spriteIndex, SpriteList);
}
void ScrollingList::ResetTweens(Component *c, TweenSet *sets, ViewInfo *currentViewInfo, ViewInfo *nextViewInfo, double scrollTime)
{
if(!c) { return; }
if(!sets) { return; }
if(!currentViewInfo) { return; }
if(!nextViewInfo) { return; }
currentViewInfo->SetImageHeight(c->GetBaseViewInfo()->GetImageHeight());
currentViewInfo->SetImageWidth(c->GetBaseViewInfo()->GetImageWidth());
nextViewInfo->SetImageHeight(c->GetBaseViewInfo()->GetImageHeight());
nextViewInfo->SetImageWidth(c->GetBaseViewInfo()->GetImageWidth());
nextViewInfo->SetBackgroundAlpha(c->GetBaseViewInfo()->GetBackgroundAlpha());
//todo: delete properly, memory leak (big), proof of concept
c->SetTweens(sets);
TweenSets *scrollTween = sets->GetOnMenuScrollTweens();
TweenSets::iterator it = scrollTween->begin();
while(it != scrollTween->end())
{
std::vector<Tween *>::iterator it2 = (*it)->begin();
while(it2 != (*it)->end())
{
delete *it2;
(*it)->erase(it2);
it2 = (*it)->begin();
}
delete *it;
scrollTween->erase(it);
it = scrollTween->begin();
}
scrollTween->clear();
c->UpdateBaseViewInfo(*currentViewInfo);
std::vector<Tween *> *set = new std::vector<Tween *>();
set->push_back(new Tween(TWEEN_PROPERTY_HEIGHT, LINEAR, currentViewInfo->GetHeight(), nextViewInfo->GetHeight(), scrollTime));
set->push_back(new Tween(TWEEN_PROPERTY_WIDTH, LINEAR, currentViewInfo->GetWidth(), nextViewInfo->GetWidth(), scrollTime));
set->push_back(new Tween(TWEEN_PROPERTY_ANGLE, LINEAR, currentViewInfo->GetAngle(), nextViewInfo->GetAngle(), scrollTime));
set->push_back(new Tween(TWEEN_PROPERTY_ALPHA, LINEAR, currentViewInfo->GetAlpha(), nextViewInfo->GetAlpha(), scrollTime));
set->push_back(new Tween(TWEEN_PROPERTY_X, LINEAR, currentViewInfo->GetX(), nextViewInfo->GetX(), scrollTime));
set->push_back(new Tween(TWEEN_PROPERTY_Y, LINEAR, currentViewInfo->GetY(), nextViewInfo->GetY(), scrollTime));
set->push_back(new Tween(TWEEN_PROPERTY_X_ORIGIN, LINEAR, currentViewInfo->GetXOrigin(), nextViewInfo->GetXOrigin(), scrollTime));
set->push_back(new Tween(TWEEN_PROPERTY_Y_ORIGIN, LINEAR, currentViewInfo->GetYOrigin(), nextViewInfo->GetYOrigin(), scrollTime));
set->push_back(new Tween(TWEEN_PROPERTY_X_OFFSET, LINEAR, currentViewInfo->GetXOffset(), nextViewInfo->GetXOffset(), scrollTime));
set->push_back(new Tween(TWEEN_PROPERTY_Y_OFFSET, LINEAR, currentViewInfo->GetYOffset(), nextViewInfo->GetYOffset(), scrollTime));
set->push_back(new Tween(TWEEN_PROPERTY_FONT_SIZE, LINEAR, currentViewInfo->GetFontSize(), nextViewInfo->GetFontSize(), scrollTime));
set->push_back(new Tween(TWEEN_PROPERTY_BACKGROUND_ALPHA, LINEAR, currentViewInfo->GetBackgroundAlpha(), nextViewInfo->GetBackgroundAlpha(), scrollTime));
scrollTween->push_back(set);
}
bool ScrollingList::AllocateTexture(ComponentItemBinding *s)
{
if(!s || s->GetComponent() != NULL) { return false; }
const Item *item = s->GetCollectionItem();
//todo: will create a runtime fault if not of the right type
//todo: remove coupling from knowing the collection name
std::string videoKey ="collections." + GetCollectionName() + ".media.video";
std::string imagePath;
std::string videoPath;
Component *t = NULL;
ImageBuilder imageBuild;
Config.GetMediaPropertyAbsolutePath(GetCollectionName(), ImageType, imagePath);
t = imageBuild.CreateImage(imagePath, item->GetName(), ScaleX, ScaleY);
if(!t && item->GetTitle() != item->GetFullTitle())
{
t = imageBuild.CreateImage(imagePath, item->GetFullTitle(), ScaleX, ScaleY);
}
if (!t)
{
t = new Text(item->GetTitle(), FontInst, FontColor, ScaleX, ScaleY);
}
if(t)
{
s->SetComponent(t);
}
return true;
} }
void ScrollingList::DeallocateTexture(ComponentItemBinding *s) void ScrollingList::DeallocateTexture(ComponentItemBinding *s)
@ -476,6 +588,7 @@ void ScrollingList::DeallocateTexture(ComponentItemBinding *s)
if(s && s->GetComponent() != NULL) if(s && s->GetComponent() != NULL)
{ {
delete s->GetComponent(); delete s->GetComponent();
//todo: memory leak here, need to destroy allocated tween points here and in page (cannot be destroyed by component)
} }
s->SetComponent(NULL); s->SetComponent(NULL);
} }
@ -486,25 +599,25 @@ void ScrollingList::Draw()
// caller should instead call ScrollingList::Draw(unsigned int layer) // caller should instead call ScrollingList::Draw(unsigned int layer)
} }
//todo: this is kind of a hack. Aggregation needs to happen differently
void ScrollingList::Draw(unsigned int layer) void ScrollingList::Draw(unsigned int layer)
{ {
if(ScrollPoints && SpriteList && SpriteList->size() > 0 && FirstSpriteIndex < SpriteList->size()) if(!ScrollPoints) { return; }
if(!SpriteList) { return; }
if(SpriteList->size() == 0) { return; }
unsigned int spriteIndex = FirstSpriteIndex;
for(unsigned int i = 0; i < ScrollPoints->size(); i++)
{ {
unsigned int spriteIndex = FirstSpriteIndex; ComponentItemBinding *s = SpriteList->at(spriteIndex);
Component *c = s->GetComponent();
ViewInfo *currentViewInfo = ScrollPoints->at(i);
for(unsigned int i = 0; i < ScrollPoints->size(); i++) if(c && currentViewInfo && currentViewInfo->GetLayer() == layer)
{ {
std::vector<ComponentItemBinding *>::iterator it = SpriteList->begin() + spriteIndex; c->Draw();
Component *c = (*it)->GetComponent();
ViewInfo *currentViewInfo = ScrollPoints->at(i);
if(currentViewInfo && currentViewInfo->GetLayer() == layer)
{
c->Draw();
}
CircularIncrement(spriteIndex, SpriteList);
} }
CircularIncrement(spriteIndex, SpriteList);
} }
} }
@ -512,12 +625,14 @@ void ScrollingList::Draw(unsigned int layer)
void ScrollingList::SetScrollDirection(ScrollDirection direction) void ScrollingList::SetScrollDirection(ScrollDirection direction)
{ {
RequestedScrollDirection = direction; RequestedScrollDirection = direction;
ScrollStopRequested = (direction == ScrollDirection::ScrollDirectionIdle);
} }
void ScrollingList::RemoveSelectedItem() void ScrollingList::RemoveSelectedItem()
{ {
ComponentItemBinding *sprite = GetSelectedCollectionItemSprite(); ComponentItemBinding *sprite = GetSelectedCollectionItemSprite();
if(sprite) if(sprite && SpriteList)
{ {
Item *item = sprite->GetCollectionItem(); Item *item = sprite->GetCollectionItem();
DeallocateTexture(sprite); DeallocateTexture(sprite);
@ -542,7 +657,6 @@ void ScrollingList::RemoveSelectedItem()
FirstSpriteIndex = 0; FirstSpriteIndex = 0;
} }
} }
IsScrollChangedComplete = true;
} }
@ -569,17 +683,6 @@ ComponentItemBinding* ScrollingList::GetPendingCollectionItemSprite()
{ {
ComponentItemBinding *item = NULL; ComponentItemBinding *item = NULL;
unsigned int index = FirstSpriteIndex; unsigned int index = FirstSpriteIndex;
if(CurrentScrollState != ScrollStatePageChange)
{
if(CurrentScrollDirection == ScrollDirectionBack)
{
CircularDecrement(index, SpriteList);
}
if(CurrentScrollDirection == ScrollDirectionForward)
{
CircularIncrement(index, SpriteList);
}
}
if(SpriteList && SpriteList->size() > 0) if(SpriteList && SpriteList->size() > 0)
{ {
index = (index + SelectedSpriteListIndex) % SpriteList->size(); index = (index + SelectedSpriteListIndex) % SpriteList->size();
@ -613,22 +716,25 @@ ComponentItemBinding* ScrollingList::GetPendingSelectedCollectionItemSprite()
{ {
ComponentItemBinding *item = NULL; ComponentItemBinding *item = NULL;
unsigned int index = SelectedSpriteListIndex; if(SpriteList)
if(CurrentScrollDirection == ScrollDirectionBack)
{ {
CircularDecrement(index, SpriteList); unsigned int index = SelectedSpriteListIndex;
}
if(CurrentScrollDirection == ScrollDirectionForward)
{
CircularIncrement(index, SpriteList);
}
if(SpriteList && SpriteList->size() > 0) if(CurrentScrollDirection == ScrollDirectionBack)
{ {
index = (index + SelectedSpriteListIndex) % SpriteList->size(); CircularDecrement(index, SpriteList);
}
if(CurrentScrollDirection == ScrollDirectionForward)
{
CircularIncrement(index, SpriteList);
}
item = SpriteList->at(index); if(SpriteList && SpriteList->size() > 0)
{
index = (index + SelectedSpriteListIndex) % SpriteList->size();
item = SpriteList->at(index);
}
} }
return item; return item;
@ -668,6 +774,18 @@ void ScrollingList::CircularDecrement(unsigned int &index, std::vector<ViewInfo*
} }
} }
int ScrollingList::CircularIncrement(unsigned int index, unsigned int offset, std::vector<ComponentItemBinding *> *list)
{
unsigned int end = index + offset;
while(end >= list->size() && list->size() > 0)
{
end -= list->size();
}
return end;
}
void ScrollingList::CircularIncrement(unsigned int &index, std::vector<ComponentItemBinding*> *list) void ScrollingList::CircularIncrement(unsigned int &index, std::vector<ComponentItemBinding*> *list)
{ {
@ -678,6 +796,7 @@ void ScrollingList::CircularIncrement(unsigned int &index, std::vector<Component
index = 0; index = 0;
} }
} }
void ScrollingList::CircularDecrement(unsigned int &index, std::vector<ComponentItemBinding*> *list) void ScrollingList::CircularDecrement(unsigned int &index, std::vector<ComponentItemBinding*> *list)
{ {
if(index > 0) if(index > 0)

View File

@ -31,12 +31,22 @@ public:
}; };
ScrollingList(Configuration &c, float scaleX, float scaleY, Font *font, SDL_Color fontColor, std::string layoutKey, std::string CollectionName, std::string imageType); ScrollingList(Configuration &c,
float scaleX,
float scaleY,
Font *font,
SDL_Color fontColor,
std::string layoutKey,
std::string imageType);
virtual ~ScrollingList(); virtual ~ScrollingList();
void AllocateTexture(ComponentItemBinding *s); void TriggerMenuEnterEvent();
void TriggerMenuExitEvent();
bool AllocateTexture(ComponentItemBinding *s);
void DeallocateTexture(ComponentItemBinding *s); void DeallocateTexture(ComponentItemBinding *s);
void SetItems(std::vector<ComponentItemBinding *> *spriteList); void SetItems(std::vector<ComponentItemBinding *> *spriteList);
void SetPoints(std::vector<ViewInfo *> *scrollPoints); void DestroyItems();
void SetPoints(std::vector<ViewInfo *> *scrollPoints, std::vector<TweenSet *> *tweenPoints);
void SetScrollDirection(ScrollDirection direction); void SetScrollDirection(ScrollDirection direction);
void PageUp(); void PageUp();
void PageDown(); void PageDown();
@ -55,11 +65,12 @@ public:
void Draw(unsigned int layer); void Draw(unsigned int layer);
private: private:
void Click(); void Click(double nextScrollTime);
void DeallocateSpritePoints();
void AllocateSpritePoints();
void UpdateSprite(unsigned int spriteIndex, unsigned int pointIndex, bool newScroll, float dt, double nextScrollTime);
unsigned int GetNextTween(unsigned int currentIndex, std::vector<ViewInfo *> *list); unsigned int GetNextTween(unsigned int currentIndex, std::vector<ViewInfo *> *list);
bool IsScrollChangedStarted; void ResetTweens(Component *c, TweenSet *sets, ViewInfo *currentViewInfo, ViewInfo *nextViewInfo, double scrollTime);
bool IsScrollChangedSignalled;
bool IsScrollChangedComplete;
enum ScrollState enum ScrollState
{ {
@ -71,20 +82,22 @@ private:
std::vector<ComponentItemBinding *> *SpriteList; std::vector<ComponentItemBinding *> *SpriteList;
std::vector<ViewInfo *> *ScrollPoints; std::vector<ViewInfo *> *ScrollPoints;
std::vector<TweenSet *> *TweenPoints;
std::vector<MenuNotifierInterface *> NotificationComponents; std::vector<MenuNotifierInterface *> NotificationComponents;
float TweenEnterTime; float TweenEnterTime;
bool Focus;
unsigned int FirstSpriteIndex; unsigned int FirstSpriteIndex;
unsigned int SelectedSpriteListIndex; unsigned int SelectedSpriteListIndex;
float CurrentAnimateTime; bool ScrollStopRequested;
float ScrollTime;
ScrollDirection CurrentScrollDirection; ScrollDirection CurrentScrollDirection;
ScrollDirection RequestedScrollDirection; ScrollDirection RequestedScrollDirection;
ScrollState CurrentScrollState; ScrollState CurrentScrollState;
float ScrollAcceleration; float ScrollAcceleration;
float ScrollVelocity; float ScrollPeriod;
int CircularIncrement(unsigned int index, unsigned int offset, std::vector<ComponentItemBinding *> *list);
void CircularIncrement(unsigned &index, std::vector<ComponentItemBinding *> *list); void CircularIncrement(unsigned &index, std::vector<ComponentItemBinding *> *list);
void CircularDecrement(unsigned &index, std::vector<ComponentItemBinding *> *list); void CircularDecrement(unsigned &index, std::vector<ComponentItemBinding *> *list);
void CircularIncrement(unsigned &index, std::vector<ViewInfo *> *list); void CircularIncrement(unsigned &index, std::vector<ViewInfo *> *list);
@ -98,7 +111,6 @@ private:
Font *FontInst; Font *FontInst;
SDL_Color FontColor; SDL_Color FontColor;
std::string LayoutKey; std::string LayoutKey;
std::string CollectionName;
std::string ImageType; std::string ImageType;
unsigned int MaxLayer; unsigned int MaxLayer;
}; };

View File

@ -1,5 +1,17 @@
/* This file is subject to the terms and conditions defined in /* This file is part of RetroFE.
* file 'LICENSE.txt', which is part of this source code package. *
* 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 #pragma once
@ -17,6 +29,7 @@ public:
void SetComponent(Component *c); void SetComponent(Component *c);
Component* GetComponent() const; Component* GetComponent() const;
private: private:
Component *CollectionComponent; Component *CollectionComponent;
Item *CollectionItem; Item *CollectionItem;

View File

@ -25,10 +25,10 @@
#include "ComponentItemBindingBuilder.h" #include "ComponentItemBindingBuilder.h"
#include <sstream> #include <sstream>
Page::Page(std::string collectionName, Configuration &config) Page::Page(Configuration &config)
: CollectionName(collectionName) : Config(config)
, Config(config) , ActiveMenu(NULL)
, Menu(NULL) , MenuDepth(0)
, Items(NULL) , Items(NULL)
, ScrollActive(false) , ScrollActive(false)
, SelectedItem(NULL) , SelectedItem(NULL)
@ -45,9 +45,14 @@ Page::Page(std::string collectionName, Configuration &config)
Page::~Page() Page::~Page()
{ {
if(Menu) MenuVector_T::iterator it = Menus.begin();
while(it != Menus.end())
{ {
Menu->RemoveComponentForNotifications(this); ScrollingList *menu = *it;
menu->RemoveComponentForNotifications(this);
Menus.erase(it);
delete menu;
it = Menus.begin();
} }
for(unsigned int i = 0; i < sizeof(LayerComponents)/sizeof(LayerComponents[0]); ++i) for(unsigned int i = 0; i < sizeof(LayerComponents)/sizeof(LayerComponents[0]); ++i)
@ -60,10 +65,6 @@ Page::~Page()
LayerComponents[i].clear(); LayerComponents[i].clear();
} }
if(Menu)
{
delete Menu;
}
if(LoadSoundChunk) if(LoadSoundChunk)
{ {
@ -97,14 +98,13 @@ void Page::OnNewItemSelected(Item *item)
SelectedItemChanged = true; SelectedItemChanged = true;
} }
void Page::SetMenu(ScrollingList *s) void Page::PushMenu(ScrollingList *s)
{ {
// todo: delete the old menu Menus.push_back(s);
Menu = s;
if(s)
if(Menu)
{ {
Menu->AddComponentForNotifications(this); s->AddComponentForNotifications(this);
} }
} }
@ -141,9 +141,15 @@ bool Page::IsIdle()
{ {
bool idle = true; bool idle = true;
if(Menu && !Menu->IsIdle()) for(MenuVector_T::iterator it = Menus.begin(); it != Menus.end(); it++)
{ {
idle = false; ScrollingList *menu = *it;
if(!menu->IsIdle())
{
idle = false;
break;
}
} }
for(unsigned int i = 0; i < NUM_LAYERS && idle; ++i) for(unsigned int i = 0; i < NUM_LAYERS && idle; ++i)
@ -160,7 +166,19 @@ bool Page::IsIdle()
bool Page::IsHidden() bool Page::IsHidden()
{ {
bool hidden = (!Menu || Menu->IsHidden()); bool hidden = true;
for(MenuVector_T::iterator it = Menus.begin(); it != Menus.end(); it++)
{
ScrollingList *menu = *it;
if(!menu->IsHidden())
{
hidden = false;
break;
}
}
for(unsigned int i = 0; hidden && i < NUM_LAYERS; ++i) for(unsigned int i = 0; hidden && i < NUM_LAYERS; ++i)
{ {
@ -175,9 +193,10 @@ bool Page::IsHidden()
void Page::Start() void Page::Start()
{ {
if(Menu) for(MenuVector_T::iterator it = Menus.begin(); it != Menus.end(); it++)
{ {
Menu->TriggerEnterEvent(); ScrollingList *menu = *it;
menu->TriggerEnterEvent();
} }
if(LoadSoundChunk) if(LoadSoundChunk)
@ -185,6 +204,12 @@ void Page::Start()
LoadSoundChunk->Play(); LoadSoundChunk->Play();
} }
StartComponents();
}
void Page::StartComponents()
{
for(unsigned int i = 0; i < NUM_LAYERS; ++i) for(unsigned int i = 0; i < NUM_LAYERS; ++i)
{ {
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it) for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it)
@ -196,10 +221,12 @@ void Page::Start()
void Page::Stop() void Page::Stop()
{ {
if(Menu) for(MenuVector_T::iterator it = Menus.begin(); it != Menus.end(); it++)
{ {
Menu->TriggerExitEvent(); ScrollingList *menu = *it;
menu->TriggerExitEvent();
} }
if(UnloadSoundChunk) if(UnloadSoundChunk)
{ {
UnloadSoundChunk->Play(); UnloadSoundChunk->Play();
@ -222,11 +249,13 @@ Item *Page::GetSelectedItem()
void Page::RemoveSelectedItem() void Page::RemoveSelectedItem()
{ {
/*
//todo: change method to RemoveItem() and pass in SelectedItem //todo: change method to RemoveItem() and pass in SelectedItem
if(Menu) if(Menu)
{ {
Menu->RemoveSelectedItem(); Menu->RemoveSelectedItem();
} }
*/
SelectedItem = NULL; SelectedItem = NULL;
} }
@ -238,10 +267,10 @@ void Page::Highlight()
if(item) if(item)
{ {
if(Menu) if(ActiveMenu)
{ {
Menu->TriggerHighlightEvent(item); ActiveMenu->TriggerHighlightEvent(item);
Menu->SetScrollActive(ScrollActive); ActiveMenu->SetScrollActive(ScrollActive);
} }
for(unsigned int i = 0; i < NUM_LAYERS; ++i) for(unsigned int i = 0; i < NUM_LAYERS; ++i)
@ -277,45 +306,94 @@ void Page::SetScrolling(ScrollDirection direction)
break; break;
} }
if(Menu) ActiveMenu->SetScrollDirection(menuDirection);
{
Menu->SetScrollDirection(menuDirection);
}
} }
void Page::PageScroll(ScrollDirection direction) void Page::PageScroll(ScrollDirection direction)
{ {
if(Menu) if(ActiveMenu)
{ {
if(direction == ScrollDirectionForward) if(direction == ScrollDirectionForward)
{ {
Menu->PageDown(); ActiveMenu->PageDown();
} }
if(direction == ScrollDirectionBack) if(direction == ScrollDirectionBack)
{ {
Menu->PageUp(); ActiveMenu->PageUp();
} }
} }
} }
bool Page::PushCollection(CollectionInfo *collection)
void Page::SetCollection(CollectionInfo *collection)
{ {
Collections.push_back(collection);
std::vector<ComponentItemBinding *> *sprites = ComponentItemBindingBuilder::BuildCollectionItems(collection->GetItems()); std::vector<ComponentItemBinding *> *sprites = ComponentItemBindingBuilder::BuildCollectionItems(collection->GetItems());
if(Menu)
if(ActiveMenu)
{ {
Menu->SetItems(sprites); ActiveMenu->TriggerMenuExitEvent();
} }
ActiveMenu = Menus[MenuDepth];
ActiveMenu->SetCollectionName(collection->GetName());
ActiveMenu->DestroyItems();
ActiveMenu->SetItems(sprites);
ActiveMenu->TriggerMenuEnterEvent();
if(MenuDepth < Menus.size())
{
MenuDepth++;
}
for(unsigned int i = 0; i < NUM_LAYERS; ++i)
{
for(std::vector<Component *>::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it)
{
(*it)->SetCollectionName(collection->GetName());
}
}
return true;
} }
bool Page::PopCollection()
{
if(MenuDepth > 1)
{
if(Collections.size() > 1)
{
Collections.pop_back();
}
if(ActiveMenu)
{
ActiveMenu->TriggerMenuExitEvent();
}
MenuDepth--;
ActiveMenu = Menus[MenuDepth - 1];
if(ActiveMenu)
{
ActiveMenu->TriggerMenuEnterEvent();
}
return true;
}
return false;
}
void Page::Update(float dt) void Page::Update(float dt)
{ {
if(Menu) for(MenuVector_T::iterator it = Menus.begin(); it != Menus.end(); it++)
{ {
Menu->Update(dt); ScrollingList *menu = *it;
menu->Update(dt);
} }
if(SelectedItemChanged && !HasSoundedWhenActive && HighlightSoundChunk) if(SelectedItemChanged && !HasSoundedWhenActive && HighlightSoundChunk)
{ {
// skip the first sound being played (as it is part of the on-enter) // skip the first sound being played (as it is part of the on-enter)
@ -357,24 +435,35 @@ void Page::Draw()
(*it)->Draw(); (*it)->Draw();
} }
if(Menu) for(MenuVector_T::iterator it = Menus.begin(); it != Menus.end(); it++)
{ {
Menu->Draw(i); ScrollingList *menu = *it;
menu->Draw(i);
} }
} }
} }
const std::string& Page::GetCollectionName() const std::string Page::GetCollectionName()
{ {
return CollectionName; CollectionInfo *info = Collections.back();
if(info)
{
return info->GetName();
}
return "";
} }
void Page::FreeGraphicsMemory() void Page::FreeGraphicsMemory()
{ {
Logger::Write(Logger::ZONE_DEBUG, "Page", "Free"); Logger::Write(Logger::ZONE_DEBUG, "Page", "Free");
if(Menu)
for(MenuVector_T::iterator it = Menus.begin(); it != Menus.end(); it++)
{ {
Menu->FreeGraphicsMemory(); ScrollingList *menu = *it;
menu->FreeGraphicsMemory();
} }
if(LoadSoundChunk) LoadSoundChunk->Free(); if(LoadSoundChunk) LoadSoundChunk->Free();
@ -395,9 +484,12 @@ void Page::AllocateGraphicsMemory()
{ {
FirstSoundPlayed = false; FirstSoundPlayed = false;
Logger::Write(Logger::ZONE_DEBUG, "Page", "Allocating graphics memory"); Logger::Write(Logger::ZONE_DEBUG, "Page", "Allocating graphics memory");
if(Menu)
for(MenuVector_T::iterator it = Menus.begin(); it != Menus.end(); it++)
{ {
Menu->AllocateGraphicsMemory(); ScrollingList *menu = *it;
menu->AllocateGraphicsMemory();
} }
if(LoadSoundChunk) LoadSoundChunk->Allocate(); if(LoadSoundChunk) LoadSoundChunk->Allocate();
@ -417,9 +509,9 @@ void Page::AllocateGraphicsMemory()
void Page::LaunchEnter() void Page::LaunchEnter()
{ {
if(Menu) if(ActiveMenu)
{ {
Menu->LaunchEnter(); ActiveMenu->LaunchEnter();
} }
for(unsigned int i = 0; i < NUM_LAYERS; ++i) for(unsigned int i = 0; i < NUM_LAYERS; ++i)
@ -433,9 +525,9 @@ void Page::LaunchEnter()
void Page::LaunchExit() void Page::LaunchExit()
{ {
if(Menu) if(ActiveMenu)
{ {
Menu->LaunchExit(); ActiveMenu->LaunchExit();
} }
for(unsigned int i = 0; i < NUM_LAYERS; ++i) for(unsigned int i = 0; i < NUM_LAYERS; ++i)

View File

@ -1,12 +1,26 @@
/* This file is subject to the terms and conditions defined in /* This file is part of RetroFE.
* file 'LICENSE.txt', which is part of this source code package. *
* 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 #pragma once
#include "MenuNotifierInterface.h" #include "MenuNotifierInterface.h"
#include <vector> #include <map>
#include <string> #include <string>
#include <list>
#include <vector>
class CollectionInfo; class CollectionInfo;
class Component; class Component;
@ -27,11 +41,14 @@ public:
}; };
Page(std::string collectionName, Configuration &c); Page(Configuration &c);
virtual ~Page(); virtual ~Page();
virtual void OnNewItemSelected(Item *); virtual void OnNewItemSelected(Item *);
void SetCollection(CollectionInfo *collection); bool PushCollection(CollectionInfo *collection);
void SetMenu(ScrollingList *s); bool IsMenusFull() { return (MenuDepth > Menus.size()); }
bool PopCollection();
void PushMenu(ScrollingList *s);
void SetLoadSound(Sound *chunk) void SetLoadSound(Sound *chunk)
{ {
LoadSoundChunk = chunk; LoadSoundChunk = chunk;
@ -48,11 +65,14 @@ public:
{ {
SelectSoundChunk = chunk; SelectSoundChunk = chunk;
} }
bool AddComponent(Component *c); bool AddComponent(Component *c);
void PageScroll(ScrollDirection direction); void PageScroll(ScrollDirection direction);
void Start(); void Start();
void StartComponents();
void Stop(); void Stop();
void SetScrolling(ScrollDirection direction); void SetScrolling(ScrollDirection direction);
unsigned int GetMenuDepth() { return MenuDepth; }
Item *GetSelectedItem(); Item *GetSelectedItem();
Item *GetPendingSelectedItem(); Item *GetPendingSelectedItem();
void RemoveSelectedItem(); void RemoveSelectedItem();
@ -65,17 +85,25 @@ public:
void AllocateGraphicsMemory(); void AllocateGraphicsMemory();
void LaunchEnter(); void LaunchEnter();
void LaunchExit(); void LaunchExit();
const std::string& GetCollectionName() const; std::string GetCollectionName();
private: private:
void Highlight(); void Highlight();
std::string CollectionName; std::string CollectionName;
Configuration &Config; Configuration &Config;
ScrollingList *Menu; typedef std::vector<ScrollingList *> MenuVector_T;
typedef std::vector<CollectionInfo *> CollectionInfo_T;
ScrollingList *ActiveMenu;
unsigned int MenuDepth;
MenuVector_T Menus;
CollectionInfo_T Collections;
static const unsigned int NUM_LAYERS = 8; static const unsigned int NUM_LAYERS = 8;
std::vector<Component *> LayerComponents[NUM_LAYERS]; std::vector<Component *> LayerComponents[NUM_LAYERS];
std::vector<Item *> *Items; std::vector<Item *> *Items;
bool ScrollActive; bool ScrollActive;
Item *SelectedItem; Item *SelectedItem;
Text *TextStatusComponent; Text *TextStatusComponent;
bool SelectedItemChanged; bool SelectedItemChanged;
@ -86,4 +114,5 @@ private:
bool HasSoundedWhenActive; bool HasSoundedWhenActive;
bool FirstSoundPlayed; bool FirstSoundPlayed;
}; };

View File

@ -23,6 +23,7 @@
#include "Component/ReloadableText.h" #include "Component/ReloadableText.h"
#include "Component/ReloadableMedia.h" #include "Component/ReloadableMedia.h"
#include "Component/ScrollingList.h" #include "Component/ScrollingList.h"
#include "Animate/TweenSet.h"
#include "Animate/TweenTypes.h" #include "Animate/TweenTypes.h"
#include "../Sound/Sound.h" #include "../Sound/Sound.h"
#include "../Collection/Item.h" #include "../Collection/Item.h"
@ -46,9 +47,8 @@ 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 collection, Configuration &c, FontCache *fc) PageBuilder::PageBuilder(std::string layoutKey, Configuration &c, FontCache *fc)
: LayoutKey(layoutKey) : LayoutKey(layoutKey)
, Collection(collection)
, Config(c) , Config(c)
, ScaleX(1) , ScaleX(1)
, ScaleY(1) , ScaleY(1)
@ -168,7 +168,7 @@ Page *PageBuilder::BuildPage()
ss << layoutWidth << "x" << layoutHeight << " (scale " << ScaleX << "x" << ScaleY << ")"; ss << layoutWidth << "x" << layoutHeight << " (scale " << ScaleX << "x" << ScaleY << ")";
Logger::Write(Logger::ZONE_DEBUG, "Layout", "Layout resolution " + ss.str()); Logger::Write(Logger::ZONE_DEBUG, "Layout", "Layout resolution " + ss.str());
page = new Page(Collection, Config); page = new Page(Config);
// load sounds // load sounds
for(xml_node<> *sound = root->first_node("sound"); sound; sound = sound->next_sibling("sound")) for(xml_node<> *sound = root->first_node("sound"); sound; sound = sound->next_sibling("sound"))
@ -207,6 +207,7 @@ Page *PageBuilder::BuildPage()
} }
} }
} }
if(!BuildComponents(root, page)) if(!BuildComponents(root, page))
{ {
delete page; delete page;
@ -314,15 +315,12 @@ float PageBuilder::GetVerticalAlignment(xml_attribute<> *attribute, float valueI
bool PageBuilder::BuildComponents(xml_node<> *layout, Page *page) bool PageBuilder::BuildComponents(xml_node<> *layout, Page *page)
{ {
xml_node<> *menuXml = layout->first_node("menu"); for(xml_node<> *componentXml = layout->first_node("menu"); componentXml; componentXml = componentXml->next_sibling("menu"))
if(menuXml)
{ {
ScrollingList *scrollingList = BuildMenu(menuXml); ScrollingList *scrollingList = BuildMenu(componentXml);
page->SetMenu(scrollingList); page->PushMenu(scrollingList);
} }
for(xml_node<> *componentXml = layout->first_node("container"); componentXml; componentXml = componentXml->next_sibling("container")) for(xml_node<> *componentXml = layout->first_node("container"); componentXml; componentXml = componentXml->next_sibling("container"))
{ {
Container *c = new Container(); Container *c = new Container();
@ -424,14 +422,6 @@ void PageBuilder::LoadReloadableImages(xml_node<> *layout, std::string tagName,
Logger::Write(Logger::ZONE_ERROR, "Layout", "Image component in layout does not specify a source image file"); Logger::Write(Logger::ZONE_ERROR, "Layout", "Image component in layout does not specify a source image file");
} }
if(type && (tagName == "reloadableVideo" || tagName == "reloadableImage"))
{
std::string configImagePath = "collections." + Collection + ".media." + type->value();
Config.GetMediaPropertyAbsolutePath(Collection, type->value(), reloadableImagePath);
Config.GetMediaPropertyAbsolutePath(Collection, "video", reloadableVideoPath);
}
Component *c = NULL; Component *c = NULL;
@ -441,12 +431,12 @@ void PageBuilder::LoadReloadableImages(xml_node<> *layout, std::string tagName,
if(type) if(type)
{ {
FC->LoadFont(Font, FontSize, FontColor); FC->LoadFont(Font, FontSize, FontColor);
c = new ReloadableText(type->value(), FC->GetFont(Font), FontColor, LayoutKey, Collection, ScaleX, ScaleY); c = new ReloadableText(type->value(), FC->GetFont(Font), FontColor, LayoutKey, ScaleX, ScaleY);
} }
} }
else else
{ {
c = new ReloadableMedia(reloadableImagePath, reloadableVideoPath, (tagName == "reloadableVideo"), ScaleX, ScaleY); c = new ReloadableMedia(Config, type->value(), (tagName == "reloadableVideo"), ScaleX, ScaleY);
} }
if(c) if(c)
@ -463,26 +453,22 @@ void PageBuilder::LoadTweens(Component *c, xml_node<> *componentXml)
BuildViewInfo(componentXml, v); BuildViewInfo(componentXml, v);
Component::TweenSets *tweenSets; c->SetTweens(CreateTweenInstance(componentXml));
tweenSets = new std::vector<std::vector<Tween *> *>(); }
GetTweenSets(componentXml->first_node("onEnter"), tweenSets);
c->SetOnEnterTweens(tweenSets);
tweenSets = new std::vector<std::vector<Tween *> *>(); TweenSet *PageBuilder::CreateTweenInstance(xml_node<> *componentXml)
GetTweenSets(componentXml->first_node("onExit"), tweenSets); {
c->SetOnExitTweens(tweenSets); TweenSet *tweens = new TweenSet();
tweenSets = new std::vector<std::vector<Tween *> *>(); GetTweenSets(componentXml->first_node("onEnter"), tweens->GetOnEnterTweens());
GetTweenSets(componentXml->first_node("onIdle"), tweenSets); GetTweenSets(componentXml->first_node("onExit"), tweens->GetOnExitTweens());
c->SetOnIdleTweens(tweenSets); GetTweenSets(componentXml->first_node("onIdle"), tweens->GetOnIdleTweens());
GetTweenSets(componentXml->first_node("onHighlightEnter"), tweens->GetOnHighlightEnterTweens());
GetTweenSets(componentXml->first_node("onHighlightExit"), tweens->GetOnHighlightExitTweens());
GetTweenSets(componentXml->first_node("onMenuEnter"), tweens->GetOnMenuEnterTweens());
GetTweenSets(componentXml->first_node("onMenuExit"), tweens->GetOnMenuExitTweens());
tweenSets = new std::vector<std::vector<Tween *> *>(); return tweens;
GetTweenSets(componentXml->first_node("onHighlightEnter"), tweenSets);
c->SetOnHighlightEnterTweens(tweenSets);
tweenSets = new std::vector<std::vector<Tween *> *>();
GetTweenSets(componentXml->first_node("onHighlightExit"), tweenSets);
c->SetOnHighlightExitTweens(tweenSets);
} }
@ -515,7 +501,7 @@ ScrollingList * PageBuilder::BuildMenu(xml_node<> *menuXml)
// 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.
FC->LoadFont(Font, FontSize, FontColor); FC->LoadFont(Font, FontSize, FontColor);
menu = new ScrollingList(Config, ScaleX, ScaleY, FC->GetFont(Font), FontColor, LayoutKey, Collection, imageType); menu = new ScrollingList(Config, ScaleX, ScaleY, FC->GetFont(Font), FontColor, LayoutKey, imageType);
ViewInfo *v = menu->GetBaseViewInfo(); ViewInfo *v = menu->GetBaseViewInfo();
BuildViewInfo(menuXml, v); BuildViewInfo(menuXml, v);
@ -529,6 +515,8 @@ ScrollingList * PageBuilder::BuildMenu(xml_node<> *menuXml)
BuildVerticalMenu(menu, menuXml, itemDefaults); BuildVerticalMenu(menu, menuXml, itemDefaults);
} }
LoadTweens(menu, menuXml);
return menu; return menu;
} }
@ -536,6 +524,7 @@ ScrollingList * PageBuilder::BuildMenu(xml_node<> *menuXml)
void PageBuilder::BuildCustomMenu(ScrollingList *menu, xml_node<> *menuXml, xml_node<> *itemDefaults) void PageBuilder::BuildCustomMenu(ScrollingList *menu, xml_node<> *menuXml, xml_node<> *itemDefaults)
{ {
std::vector<ViewInfo *> *points = new std::vector<ViewInfo *>(); std::vector<ViewInfo *> *points = new std::vector<ViewInfo *>();
std::vector<TweenSet *> *tweenPoints = new std::vector<TweenSet *>();
int i = 0; int i = 0;
@ -543,9 +532,9 @@ void PageBuilder::BuildCustomMenu(ScrollingList *menu, xml_node<> *menuXml, xml_
{ {
ViewInfo *viewInfo = new ViewInfo(); ViewInfo *viewInfo = new ViewInfo();
BuildViewInfo(componentXml, viewInfo, itemDefaults); BuildViewInfo(componentXml, viewInfo, itemDefaults);
points->push_back(viewInfo); points->push_back(viewInfo);
tweenPoints->push_back(CreateTweenInstance(componentXml));
xml_attribute<> *selected = componentXml->first_attribute("selected"); xml_attribute<> *selected = componentXml->first_attribute("selected");
if(selected) if(selected)
@ -556,12 +545,13 @@ void PageBuilder::BuildCustomMenu(ScrollingList *menu, xml_node<> *menuXml, xml_
i++; i++;
} }
menu->SetPoints(points); menu->SetPoints(points, tweenPoints);
} }
void PageBuilder::BuildVerticalMenu(ScrollingList *menu, xml_node<> *menuXml, xml_node<> *itemDefaults) void PageBuilder::BuildVerticalMenu(ScrollingList *menu, xml_node<> *menuXml, xml_node<> *itemDefaults)
{ {
std::vector<ViewInfo *> *points = new std::vector<ViewInfo *>(); std::vector<ViewInfo *> *points = new std::vector<ViewInfo *>();
std::vector<TweenSet *> *tweenPoints = new std::vector<TweenSet *>();
int selectedIndex = MENU_FIRST; int selectedIndex = MENU_FIRST;
std::map<int, xml_node<> *> overrideItems; std::map<int, xml_node<> *> overrideItems;
@ -600,6 +590,7 @@ void PageBuilder::BuildVerticalMenu(ScrollingList *menu, xml_node<> *menuXml, xm
xml_node<> *component = overrideItems[MENU_START]; xml_node<> *component = overrideItems[MENU_START];
ViewInfo *viewInfo = CreateMenuItemInfo(component, itemDefaults, menu->GetBaseViewInfo()->GetY() + height); ViewInfo *viewInfo = CreateMenuItemInfo(component, itemDefaults, menu->GetBaseViewInfo()->GetY() + height);
points->push_back(viewInfo); points->push_back(viewInfo);
tweenPoints->push_back(CreateTweenInstance(component));
} }
while(!end) while(!end)
{ {
@ -637,6 +628,7 @@ void PageBuilder::BuildVerticalMenu(ScrollingList *menu, xml_node<> *menuXml, xm
height = nextHeight; height = nextHeight;
viewInfo->SetY(menu->GetBaseViewInfo()->GetY() + (float)height); viewInfo->SetY(menu->GetBaseViewInfo()->GetY() + (float)height);
points->push_back(viewInfo); points->push_back(viewInfo);
tweenPoints->push_back(CreateTweenInstance(component));
index++; index++;
} }
@ -646,6 +638,7 @@ void PageBuilder::BuildVerticalMenu(ScrollingList *menu, xml_node<> *menuXml, xm
xml_node<> *component = overrideItems[MENU_END]; xml_node<> *component = overrideItems[MENU_END];
ViewInfo *viewInfo = CreateMenuItemInfo(component, itemDefaults, menu->GetBaseViewInfo()->GetY() + height); ViewInfo *viewInfo = CreateMenuItemInfo(component, itemDefaults, menu->GetBaseViewInfo()->GetY() + height);
points->push_back(viewInfo); points->push_back(viewInfo);
tweenPoints->push_back(CreateTweenInstance(component));
} }
if(selectedIndex >= ((int)points->size()-2)) if(selectedIndex >= ((int)points->size()-2))
@ -658,7 +651,7 @@ void PageBuilder::BuildVerticalMenu(ScrollingList *menu, xml_node<> *menuXml, xm
menu->SetSelectedIndex(selectedIndex+1); menu->SetSelectedIndex(selectedIndex+1);
} }
menu->SetPoints(points); menu->SetPoints(points, tweenPoints);
} }
ViewInfo *PageBuilder::CreateMenuItemInfo(xml_node<> *component, xml_node<> *defaults, float y) ViewInfo *PageBuilder::CreateMenuItemInfo(xml_node<> *component, xml_node<> *defaults, float y)
@ -780,10 +773,8 @@ void PageBuilder::BuildViewInfo(xml_node<> *componentXml, ViewInfo *info, xml_no
{ {
info->SetBackgroundAlpha( backgroundAlpha ? Utils::ConvertFloat(backgroundAlpha->value()) : 1); info->SetBackgroundAlpha( backgroundAlpha ? Utils::ConvertFloat(backgroundAlpha->value()) : 1);
} }
} }
void PageBuilder::GetTweenSets(xml_node<> *node, std::vector<std::vector<Tween *> *> *tweenSets) void PageBuilder::GetTweenSets(xml_node<> *node, std::vector<std::vector<Tween *> *> *tweenSets)
{ {
if(node) if(node)

View File

@ -18,14 +18,13 @@ class Configuration;
class PageBuilder class PageBuilder
{ {
public: public:
PageBuilder(std::string layoutKey, std::string collection, Configuration &c, FontCache *fc); PageBuilder(std::string layoutKey, Configuration &c, FontCache *fc);
virtual ~PageBuilder(); virtual ~PageBuilder();
Page *BuildPage(); Page *BuildPage();
private: private:
std::string LayoutKey; std::string LayoutKey;
std::string LayoutPath; std::string LayoutPath;
std::string Collection;
Configuration &Config; Configuration &Config;
float ScaleX; float ScaleX;
float ScaleY; float ScaleY;
@ -42,6 +41,7 @@ private:
void BuildViewInfo(rapidxml::xml_node<> *componentXml, ViewInfo *info, rapidxml::xml_node<> *defaultXml = NULL); void BuildViewInfo(rapidxml::xml_node<> *componentXml, ViewInfo *info, rapidxml::xml_node<> *defaultXml = NULL);
bool BuildComponents(rapidxml::xml_node<> *layout, Page *page); bool BuildComponents(rapidxml::xml_node<> *layout, Page *page);
void LoadTweens(Component *c, rapidxml::xml_node<> *componentXml); void LoadTweens(Component *c, rapidxml::xml_node<> *componentXml);
TweenSet *CreateTweenInstance(rapidxml::xml_node<> *componentXml);
ScrollingList * BuildMenu(rapidxml::xml_node<> *menuXml); ScrollingList * BuildMenu(rapidxml::xml_node<> *menuXml);
void BuildCustomMenu(ScrollingList *menu, rapidxml::xml_node<> *menuXml, rapidxml::xml_node<> *itemDefaults); void BuildCustomMenu(ScrollingList *menu, rapidxml::xml_node<> *menuXml, rapidxml::xml_node<> *itemDefaults);
void BuildVerticalMenu(ScrollingList *menu, rapidxml::xml_node<> *menuXml, rapidxml::xml_node<> *itemDefaults); void BuildVerticalMenu(ScrollingList *menu, rapidxml::xml_node<> *menuXml, rapidxml::xml_node<> *itemDefaults);

View File

@ -43,6 +43,7 @@ RetroFE::RetroFE(Configuration &c)
, Config(c) , Config(c)
, Db(NULL) , Db(NULL)
, Input(Config) , Input(Config)
, CurrentPage(NULL)
, KeyInputDisable(0) , KeyInputDisable(0)
, CurrentTime(0) , CurrentTime(0)
{ {
@ -59,15 +60,11 @@ void RetroFE::Render()
SDL_SetRenderDrawColor(SDL::GetRenderer(), 0x0, 0x0, 0x00, 0xFF); SDL_SetRenderDrawColor(SDL::GetRenderer(), 0x0, 0x0, 0x00, 0xFF);
SDL_RenderClear(SDL::GetRenderer()); SDL_RenderClear(SDL::GetRenderer());
if(PageChain.size() > 0) if(CurrentPage)
{ {
Page *page = PageChain.back(); CurrentPage->Draw();
if(page)
{
page->Draw();
}
} }
SDL_RenderPresent(SDL::GetRenderer()); SDL_RenderPresent(SDL::GetRenderer());
SDL_UnlockMutex(SDL::GetMutex()); SDL_UnlockMutex(SDL::GetMutex());
} }
@ -111,11 +108,11 @@ int RetroFE::Initialize(void *context)
void RetroFE::LaunchEnter() void RetroFE::LaunchEnter()
{ {
if(PageChain.size() > 0) if(CurrentPage)
{ {
Page *p = PageChain.back(); CurrentPage->LaunchEnter();
p->LaunchEnter();
} }
SDL_SetWindowGrab(SDL::GetWindow(), SDL_FALSE); SDL_SetWindowGrab(SDL::GetWindow(), SDL_FALSE);
} }
@ -125,20 +122,18 @@ void RetroFE::LaunchExit()
SDL_RestoreWindow(SDL::GetWindow()); SDL_RestoreWindow(SDL::GetWindow());
SDL_SetWindowGrab(SDL::GetWindow(), SDL_TRUE); SDL_SetWindowGrab(SDL::GetWindow(), SDL_TRUE);
if(PageChain.size() > 0) if(CurrentPage)
{ {
Page *p = PageChain.back(); CurrentPage->LaunchExit();
p->LaunchExit();
} }
} }
void RetroFE::FreeGraphicsMemory() void RetroFE::FreeGraphicsMemory()
{ {
if(PageChain.size() > 0) if(CurrentPage)
{ {
Page *p = PageChain.back(); CurrentPage->FreeGraphicsMemory();
p->FreeGraphicsMemory();
} }
FC.DeInitialize(); FC.DeInitialize();
@ -151,11 +146,10 @@ void RetroFE::AllocateGraphicsMemory()
FC.Initialize(); FC.Initialize();
if(PageChain.size() > 0) if(CurrentPage)
{ {
Page *p = PageChain.back(); CurrentPage->AllocateGraphicsMemory();
p->AllocateGraphicsMemory(); CurrentPage->Start();
p->Start();
} }
} }
@ -166,11 +160,10 @@ bool RetroFE::DeInitialize()
bool videoEnable = true; bool videoEnable = true;
while(PageChain.size() > 0) if(CurrentPage)
{ {
Page *page = PageChain.back(); delete CurrentPage;
delete page; CurrentPage = NULL;
PageChain.pop_back();
} }
if(MetaDb) if(MetaDb)
{ {
@ -218,7 +211,7 @@ void RetroFE::Run()
int initializeStatus = 0; int initializeStatus = 0;
// load the initial splash screen, unload it once it is complete // load the initial splash screen, unload it once it is complete
Page * page = LoadSplashPage(); CurrentPage = LoadSplashPage();
bool splashMode = true; bool splashMode = true;
Launcher l(*this, Config); Launcher l(*this, Config);
@ -227,9 +220,8 @@ void RetroFE::Run()
{ {
float lastTime = 0; float lastTime = 0;
float deltaTime = 0; float deltaTime = 0;
page = PageChain.back();
if(!page) if(!CurrentPage)
{ {
Logger::Write(Logger::ZONE_WARNING, "RetroFE", "Could not load page"); Logger::Write(Logger::ZONE_WARNING, "RetroFE", "Could not load page");
running = false; running = false;
@ -239,9 +231,9 @@ void RetroFE::Run()
switch(state) switch(state)
{ {
case RETROFE_IDLE: case RETROFE_IDLE:
if(page && !splashMode) if(CurrentPage && !splashMode)
{ {
state = ProcessUserInput(page); state = ProcessUserInput(CurrentPage);
} }
else else
{ {
@ -253,65 +245,65 @@ void RetroFE::Run()
if(Initialized && splashMode) if(Initialized && splashMode)
{ {
SDL_WaitThread(InitializeThread, &initializeStatus); SDL_WaitThread(InitializeThread, &initializeStatus);
state = RETROFE_BACK_WAIT;
page->Stop(); // delete the splash screen and use the standard menu
delete CurrentPage;
CurrentPage = LoadPage();
splashMode = false;
if(CurrentPage)
{
std::string firstCollection;
Config.GetProperty("firstCollection", firstCollection);
CurrentPage->Start();
Config.SetCurrentCollection(firstCollection);
CollectionInfo *info = GetCollection(firstCollection);
CurrentPage->PushCollection(info);
}
else
{
state = RETROFE_QUIT_REQUEST;
}
} }
break; break;
case RETROFE_NEXT_PAGE_REQUEST: case RETROFE_NEXT_PAGE_REQUEST:
page->Stop(); if(CurrentPage->IsIdle())
state = RETROFE_NEXT_PAGE_WAIT;
break;
case RETROFE_NEXT_PAGE_WAIT:
if(page->IsHidden())
{ {
page = LoadPage(NextPageItem->GetName());
state = RETROFE_NEW; state = RETROFE_NEW;
} }
break; break;
case RETROFE_LAUNCH_REQUEST: case RETROFE_LAUNCH_REQUEST:
l.Run(page->GetCollectionName(), NextPageItem); NextPageItem = CurrentPage->GetSelectedItem();
l.Run(CurrentPage->GetCollectionName(), NextPageItem);
state = RETROFE_IDLE; state = RETROFE_IDLE;
break; break;
case RETROFE_BACK_REQUEST: case RETROFE_BACK_REQUEST:
page->Stop(); CurrentPage->PopCollection();
state = RETROFE_BACK_WAIT; Config.SetCurrentCollection(CurrentPage->GetCollectionName());
break;
case RETROFE_BACK_WAIT: state = RETROFE_NEW;
if(page->IsHidden())
{
PageChain.pop_back();
delete page;
page = (splashMode) ? LoadPage(firstCollection) : PageChain.back();
splashMode = false;
CurrentTime = (float)SDL_GetTicks() / 1000;
page->AllocateGraphicsMemory();
page->Start();
state = RETROFE_NEW;
}
break; break;
case RETROFE_NEW: case RETROFE_NEW:
if(page->IsIdle()) if(CurrentPage->IsIdle())
{ {
state = RETROFE_IDLE; state = RETROFE_IDLE;
} }
break; break;
case RETROFE_QUIT_REQUEST: case RETROFE_QUIT_REQUEST:
page->Stop(); CurrentPage->Stop();
state = RETROFE_QUIT; state = RETROFE_QUIT;
break; break;
case RETROFE_QUIT: case RETROFE_QUIT:
if(page->IsHidden()) if(CurrentPage->IsHidden())
{ {
running = false; running = false;
} }
@ -337,10 +329,10 @@ void RetroFE::Run()
SDL_Delay(static_cast<unsigned int>(sleepTime)); SDL_Delay(static_cast<unsigned int>(sleepTime));
} }
if(page) if(CurrentPage)
{ {
Attract.Update(deltaTime, *page); Attract.Update(deltaTime, *CurrentPage);
page->Update(deltaTime); CurrentPage->Update(deltaTime);
} }
Render(); Render();
@ -353,22 +345,16 @@ void RetroFE::Run()
bool RetroFE::Back(bool &exit) bool RetroFE::Back(bool &exit)
{ {
bool canGoBack = false; bool canGoBack = false;
bool exitOnBack = false; bool exitOnBack = false;
Config.GetProperty("exitOnFirstPageBack", exitOnBack); Config.GetProperty("exitOnFirstPageBack", exitOnBack);
exit = false; exit = false;
if(PageChain.size() > 1) if(CurrentPage->GetMenuDepth() == 0)
{ {
Page *page = PageChain.back(); exit = exitOnBack;
page->Stop();
canGoBack = true;
} }
else if(PageChain.size() == 1 && exitOnBack) else
{ {
Page *page = PageChain.back();
page->Stop();
exit = true;
canGoBack = true; canGoBack = true;
} }
@ -413,10 +399,22 @@ RetroFE::RETROFE_STATE RetroFE::ProcessUserInput(Page *page)
if (keys[Input.GetScancode(UserInput::KeyCodeSelect)]) if (keys[Input.GetScancode(UserInput::KeyCodeSelect)])
{ {
NextPageItem = page->GetSelectedItem(); NextPageItem = page->GetSelectedItem();
Logger::Write(Logger::ZONE_INFO, "RetroFE", "SELECT KEYCODE START");
if(NextPageItem) if(NextPageItem)
{ {
state = (NextPageItem->IsLeaf()) ? RETROFE_LAUNCH_REQUEST : RETROFE_NEXT_PAGE_REQUEST; if(NextPageItem->IsLeaf())
{
state = RETROFE_LAUNCH_REQUEST;
}
else
{
Config.SetCurrentCollection(NextPageItem->GetName());
CollectionInfo *info = GetCollection(NextPageItem->GetName());
page->PushCollection(info);
state = RETROFE_NEXT_PAGE_REQUEST;
}
} }
} }
@ -449,7 +447,7 @@ void RetroFE::WaitToInitialize()
{ {
Logger::Write(Logger::ZONE_INFO, "RetroFE", "Loading splash screen"); Logger::Write(Logger::ZONE_INFO, "RetroFE", "Loading splash screen");
PageBuilder pb("splash", "", Config, &FC); PageBuilder pb("splash", Config, &FC);
Page * page = pb.BuildPage(); Page * page = pb.BuildPage();
while(!Initialized) while(!Initialized)
@ -467,47 +465,32 @@ void RetroFE::WaitToInitialize()
} }
Page *RetroFE::LoadPage(std::string collectionName) Page *RetroFE::LoadPage()
{ {
Logger::Write(Logger::ZONE_INFO, "RetroFE", "Creating page for collection " + collectionName); std::string layoutName;
Page *page = NULL; Config.GetProperty("layout", layoutName);
Config.SetCurrentCollection(collectionName); PageBuilder pb(layoutName, Config, &FC);
CollectionInfo *collection = GetCollection(collectionName); Page *page = pb.BuildPage();
std::string layoutName = GetLayout(collectionName);
if(PageChain.size() > 0)
{
Page *oldPage = PageChain.back();
oldPage->FreeGraphicsMemory();
}
PageBuilder pb(layoutName, collectionName, Config, &FC);
page = pb.BuildPage();
if(!page) if(!page)
{ {
Logger::Write(Logger::ZONE_ERROR, "RetroFE", "Could not create page for " + collectionName); Logger::Write(Logger::ZONE_ERROR, "RetroFE", "Could not create page");
} }
else else
{ {
page->SetCollection(collection);
page->Start(); page->Start();
PageChain.push_back(page);
} }
return page; return page;
} }
Page *RetroFE::LoadSplashPage() Page *RetroFE::LoadSplashPage()
{ {
PageBuilder pb("Splash", "", Config, &FC); PageBuilder pb("Splash", Config, &FC);
Page * page = pb.BuildPage(); Page * page = pb.BuildPage();
Config.SetCurrentCollection("");
page->SetCollection(new CollectionInfo("", "", "", "", ""));
page->Start(); page->Start();
PageChain.push_back(page);
return page; return page;
} }

View File

@ -38,10 +38,8 @@ private:
{ {
RETROFE_IDLE, RETROFE_IDLE,
RETROFE_NEXT_PAGE_REQUEST, RETROFE_NEXT_PAGE_REQUEST,
RETROFE_NEXT_PAGE_WAIT,
RETROFE_LAUNCH_REQUEST, RETROFE_LAUNCH_REQUEST,
RETROFE_BACK_REQUEST, RETROFE_BACK_REQUEST,
RETROFE_BACK_WAIT,
RETROFE_NEW, RETROFE_NEW,
RETROFE_QUIT_REQUEST, RETROFE_QUIT_REQUEST,
RETROFE_QUIT, RETROFE_QUIT,
@ -51,7 +49,7 @@ private:
bool Back(bool &exit); bool Back(bool &exit);
void Quit(); void Quit();
void WaitToInitialize(); void WaitToInitialize();
Page *LoadPage(std::string collectionName); Page *LoadPage();
Page *LoadSplashPage(); Page *LoadSplashPage();
RETROFE_STATE ProcessUserInput(Page *page); RETROFE_STATE ProcessUserInput(Page *page);
void Update(float dt, bool scrollActive); void Update(float dt, bool scrollActive);
@ -61,7 +59,7 @@ private:
DB *Db; DB *Db;
MetadataDatabase *MetaDb; MetadataDatabase *MetaDb;
UserInput Input; UserInput Input;
std::list<Page *> PageChain; Page *CurrentPage;
float KeyInputDisable; float KeyInputDisable;
float CurrentTime; float CurrentTime;
Item *NextPageItem; Item *NextPageItem;