diff --git a/RetroFE/Source/CMakeLists.txt b/RetroFE/Source/CMakeLists.txt index d7084a4..c1be59a 100644 --- a/RetroFE/Source/CMakeLists.txt +++ b/RetroFE/Source/CMakeLists.txt @@ -86,6 +86,7 @@ set(RETROFE_HEADERS "${RETROFE_DIR}/Source/Execute/Launcher.h" "${RETROFE_DIR}/Source/Graphics/Animate/Tween.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/Component/Container.h" "${RETROFE_DIR}/Source/Graphics/Component/Component.h" @@ -126,12 +127,13 @@ set(RETROFE_SOURCES "${RETROFE_DIR}/Source/Database/MetadataDatabase.cpp" "${RETROFE_DIR}/Source/Execute/AttractMode.cpp" "${RETROFE_DIR}/Source/Execute/Launcher.cpp" - "${RETROFE_DIR}/Source/Graphics/Animate/Tween.cpp" "${RETROFE_DIR}/Source/Graphics/Font.cpp" "${RETROFE_DIR}/Source/Graphics/FontCache.cpp" "${RETROFE_DIR}/Source/Graphics/PageBuilder.cpp" "${RETROFE_DIR}/Source/Graphics/Page.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/ComponentItemBinding.cpp" "${RETROFE_DIR}/Source/Graphics/Component/Container.cpp" diff --git a/RetroFE/Source/Collection/MenuParser.cpp b/RetroFE/Source/Collection/MenuParser.cpp index eb76da8..7eda450 100644 --- a/RetroFE/Source/Collection/MenuParser.cpp +++ b/RetroFE/Source/Collection/MenuParser.cpp @@ -56,7 +56,6 @@ bool MenuParser::GetMenuItems(CollectionInfo *collection) // gracefully exit if there is no menu file for the pa if(file.good()) { - Logger::Write(Logger::ZONE_INFO, "Menu", "Found menu"); std::vector buffer((std::istreambuf_iterator(file)), std::istreambuf_iterator()); buffer.push_back('\0'); diff --git a/RetroFE/Source/Database/Configuration.cpp b/RetroFE/Source/Database/Configuration.cpp index 3d3a4be..cb2e187 100644 --- a/RetroFE/Source/Database/Configuration.cpp +++ b/RetroFE/Source/Database/Configuration.cpp @@ -41,6 +41,8 @@ Configuration::~Configuration() void Configuration::Initialize() { + Configuration::SetAbsolutePath("D:/RetroFE"); +#if 0 const char *environment = std::getenv("RETROFE_PATH"); std::string environmentStr; if (environment != NULL) @@ -68,6 +70,7 @@ void Configuration::Initialize() Configuration::SetAbsolutePath(sPath); } +#endif } void Configuration::SetCurrentCollection(std::string collection) diff --git a/RetroFE/Source/Graphics/Animate/Tween.h b/RetroFE/Source/Graphics/Animate/Tween.h index 9afecec..72c0267 100644 --- a/RetroFE/Source/Graphics/Animate/Tween.h +++ b/RetroFE/Source/Graphics/Animate/Tween.h @@ -1,5 +1,17 @@ -/* This file is subject to the terms and conditions defined in - * file 'LICENSE.txt', which is part of this source code package. +/* 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 . */ #pragma once diff --git a/RetroFE/Source/Graphics/Animate/TweenSet.cpp b/RetroFE/Source/Graphics/Animate/TweenSet.cpp new file mode 100644 index 0000000..e69de29 diff --git a/RetroFE/Source/Graphics/Animate/TweenSet.h b/RetroFE/Source/Graphics/Animate/TweenSet.h new file mode 100644 index 0000000..8375bf9 --- /dev/null +++ b/RetroFE/Source/Graphics/Animate/TweenSet.h @@ -0,0 +1,69 @@ +/* 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 . + */ +#pragma once + +#include "Tween.h" +#include +#include + + + +class TweenSet +{ +public: + typedef std::vector *> 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 *GetOnMenuExitTweens() + { + return &OnMenuExitTweens; + } + TweenSets *GetOnMenuEnterTweens() + { + return &OnMenuEnterTweens; + } + +private: + TweenSets OnEnterTweens; + TweenSets OnExitTweens; + TweenSets OnIdleTweens; + TweenSets OnHighlightEnterTweens; + TweenSets OnHighlightExitTweens; + TweenSets OnMenuEnterTweens; + TweenSets OnMenuExitTweens; + +}; \ No newline at end of file diff --git a/RetroFE/Source/Graphics/Component/Component.cpp b/RetroFE/Source/Graphics/Component/Component.cpp index 879cdbe..6b69147 100644 --- a/RetroFE/Source/Graphics/Component/Component.cpp +++ b/RetroFE/Source/Graphics/Component/Component.cpp @@ -21,15 +21,12 @@ Component::Component() { - OnEnterTweens = NULL; - OnExitTweens = NULL; - OnIdleTweens = NULL; - OnHighlightEnterTweens = NULL; - OnHighlightExitTweens = NULL; + Tweens = NULL; SelectedItem = NULL; NewItemSelectedSinceEnter = false; BackgroundTexture = NULL; FreeGraphicsMemory(); + } Component::~Component() @@ -42,6 +39,9 @@ void Component::FreeGraphicsMemory() CurrentAnimationState = HIDDEN; EnterRequested = false; ExitRequested = false; + MenuEnterRequested = false; + MenuExitRequested = false; + NewItemSelected = false; HighlightExitComplete = false; CurrentTweens = NULL; @@ -87,6 +87,22 @@ void Component::TriggerExitEvent() ExitRequested = true; } + + +void Component::TriggerMenuEnterEvent() +{ + std::stringstream ss; + ss << CurrentAnimationState; + ss << " Triggering menu enter request"; + Logger::Write(Logger::ZONE_DEBUG, "Component", ss.str()); + + MenuEnterRequested = true; +} + +void Component::TriggerMenuExitEvent() +{ + MenuExitRequested = true; +} void Component::TriggerHighlightEvent(Item *selectedItem) { NewItemSelected = true; @@ -108,6 +124,22 @@ bool Component::IsWaiting() return (CurrentAnimationState == HIGHLIGHT_WAIT); } +bool Component::IsMenuAnimating() +{ + return (CurrentAnimationState == MENU_ENTER || CurrentAnimationState == MENU_EXIT); +} + + +std::string Component::GetCollectionName() +{ + return CollectionName; +} + +void Component::SetCollectionName(std::string collectionName) +{ + CollectionName = collectionName; +} + void Component::Update(float dt) { ElapsedTweenTime += dt; @@ -122,21 +154,35 @@ void Component::Update(float dt) CurrentTweens = NULL; // There was no request to override our state path. Continue on as normal. + std::stringstream ss; switch(CurrentAnimationState) { + case MENU_ENTER: + Logger::Write(Logger::ZONE_DEBUG, "Page", "MENU EXIT!"); + CurrentTweens = NULL; + CurrentAnimationState = IDLE; + break; + + case MENU_EXIT: + Logger::Write(Logger::ZONE_DEBUG, "Page", "MENU EXIT!"); + CurrentTweens = NULL; + CurrentAnimationState = IDLE; + break; + + case ENTER: - CurrentTweens = OnHighlightEnterTweens; + CurrentTweens = Tweens->GetOnHighlightEnterTweens(); CurrentAnimationState = HIGHLIGHT_ENTER; break; case EXIT: + Logger::Write(Logger::ZONE_DEBUG, "Page", "COMPONENT EXIT!"); CurrentTweens = NULL; CurrentAnimationState = HIDDEN; - break; case HIGHLIGHT_ENTER: - CurrentTweens = OnIdleTweens; + CurrentTweens = Tweens->GetOnIdleTweens(); CurrentAnimationState = IDLE; break; @@ -144,17 +190,36 @@ void Component::Update(float dt) // prevent us from automatically jumping to the exit tween upon enter if(EnterRequested) { - EnterRequested = false; - NewItemSelected = false; + Logger::Write(Logger::ZONE_DEBUG, "Component", "Triggering enter event"); + EnterRequested = false; + NewItemSelected = false; + } + else if(MenuEnterRequested) + { + Logger::Write(Logger::ZONE_DEBUG, "Component", "Triggering menu enter event from idle"); + MenuEnterRequested = false; + CurrentTweens = Tweens->GetOnMenuEnterTweens(); + CurrentAnimationState = MENU_ENTER; + ss << CurrentTweens->size(); + Logger::Write(Logger::ZONE_DEBUG, "Page", "MENU ENTER! SIZE " + ss.str()); + } + else if(MenuExitRequested) + { + Logger::Write(Logger::ZONE_DEBUG, "Component", "Triggering menu exit event from idle"); + MenuExitRequested = false; + CurrentTweens = Tweens->GetOnMenuExitTweens(); + CurrentAnimationState = MENU_EXIT; + ss << CurrentTweens->size(); + Logger::Write(Logger::ZONE_DEBUG, "Page", "MENU ENTER! SIZE " + ss.str()); } else if(IsScrollActive() || NewItemSelected || ExitRequested) { - CurrentTweens = OnHighlightExitTweens; + CurrentTweens = Tweens->GetOnHighlightExitTweens(); CurrentAnimationState = HIGHLIGHT_EXIT; } else { - CurrentTweens = OnIdleTweens; + CurrentTweens = Tweens->GetOnIdleTweens(); CurrentAnimationState = IDLE; } break; @@ -166,14 +231,14 @@ void Component::Update(float dt) if(ExitRequested && (CurrentAnimationState == HIGHLIGHT_WAIT)) { - CurrentTweens = OnHighlightExitTweens; + CurrentTweens = Tweens->GetOnHighlightExitTweens(); CurrentAnimationState = HIGHLIGHT_EXIT; } else if(ExitRequested && (CurrentAnimationState == HIGHLIGHT_EXIT)) { - CurrentTweens = OnExitTweens; + CurrentTweens = Tweens->GetOnExitTweens(); CurrentAnimationState = EXIT; ExitRequested = false; } @@ -184,7 +249,7 @@ void Component::Update(float dt) } else if(NewItemSelected) { - CurrentTweens = OnHighlightEnterTweens; + CurrentTweens = Tweens->GetOnHighlightEnterTweens(); CurrentAnimationState = HIGHLIGHT_ENTER; HighlightExitComplete = true; NewItemSelected = false; @@ -199,9 +264,26 @@ void Component::Update(float dt) case HIDDEN: if(EnterRequested || ExitRequested) { - CurrentTweens = OnEnterTweens; + CurrentTweens = Tweens->GetOnEnterTweens(); CurrentAnimationState = ENTER; } + else if(MenuExitRequested) + { + CurrentTweens = Tweens->GetOnMenuExitTweens(); + ss << CurrentTweens->size(); + Logger::Write(Logger::ZONE_DEBUG, "Component", "Entering menu exit from hidden! " + ss.str()); + CurrentAnimationState = MENU_EXIT; + MenuExitRequested = false; + } + else if(MenuEnterRequested) + { + CurrentTweens = Tweens->GetOnMenuEnterTweens(); + ss << CurrentTweens->size(); + Logger::Write(Logger::ZONE_DEBUG, "Component", "Entering menu enter from hidden!" + ss.str()); + CurrentAnimationState = MENU_ENTER; + MenuEnterRequested = false; + + } else { CurrentTweens = NULL; diff --git a/RetroFE/Source/Graphics/Component/Component.h b/RetroFE/Source/Graphics/Component/Component.h index 24da67e..66d8426 100644 --- a/RetroFE/Source/Graphics/Component/Component.h +++ b/RetroFE/Source/Graphics/Component/Component.h @@ -1,5 +1,17 @@ -/* This file is subject to the terms and conditions defined in - * file 'LICENSE.txt', which is part of this source code package. +/* 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 . */ #pragma once @@ -9,6 +21,7 @@ #include "../MenuNotifierInterface.h" #include "../ViewInfo.h" #include "../Animate/Tween.h" +#include "../Animate/TweenSet.h" #include "../../Collection/Item.h" class Component @@ -22,36 +35,28 @@ public: virtual void LaunchExit() {} void TriggerEnterEvent(); void TriggerExitEvent(); + void TriggerMenuEnterEvent(); + void TriggerMenuExitEvent(); void TriggerHighlightEvent(Item *selectedItem); bool IsIdle(); bool IsHidden(); bool IsWaiting(); + bool IsMenuAnimating(); + std::string GetCollectionName(); + void SetCollectionName(std::string collectionName); typedef std::vector *> 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 Draw(); @@ -78,6 +83,7 @@ public: protected: + std::string CollectionName; Item *GetSelectedItem() { return SelectedItem; @@ -90,12 +96,16 @@ protected: HIGHLIGHT_WAIT, HIGHLIGHT_ENTER, EXIT, + MENU_ENTER, + MENU_EXIT, HIDDEN }; AnimationState CurrentAnimationState; bool EnterRequested; bool ExitRequested; + bool MenuEnterRequested; + bool MenuExitRequested; bool NewItemSelected; bool HighlightExitComplete; bool NewItemSelectedSinceEnter; @@ -103,13 +113,7 @@ private: bool Animate(bool loop); bool IsTweenSequencingComplete(); void ResetTweenSequence(std::vector *tweens); - - TweenSets *OnEnterTweens; - TweenSets *OnExitTweens; - TweenSets *OnIdleTweens; - TweenSets *OnHighlightEnterTweens; - TweenSets *OnHighlightExitTweens; - + TweenSet *Tweens; TweenSets *CurrentTweens; unsigned int CurrentTweenIndex; diff --git a/RetroFE/Source/Graphics/Component/ReloadableMedia.cpp b/RetroFE/Source/Graphics/Component/ReloadableMedia.cpp index f2f63d8..b1bc67d 100644 --- a/RetroFE/Source/Graphics/Component/ReloadableMedia.cpp +++ b/RetroFE/Source/Graphics/Component/ReloadableMedia.cpp @@ -27,12 +27,12 @@ #include #include -ReloadableMedia::ReloadableMedia(std::string imagePath, std::string videoPath, bool isVideo, float scaleX, float scaleY) - : LoadedComponent(NULL) - , ImagePath(imagePath) - , VideoPath(videoPath) +ReloadableMedia::ReloadableMedia(Configuration &config, std::string type, bool isVideo, float scaleX, float scaleY) + : Config(config) + , LoadedComponent(NULL) , ReloadRequested(false) , FirstLoad(true) + , Type(type) , IsVideo(isVideo) , ScaleX(scaleX) , ScaleY(scaleY) @@ -134,19 +134,14 @@ void ReloadableMedia::ReloadTexture() { names.push_back(selectedItem->GetCloneOf()); } + std::string videoPath; + Config.GetMediaPropertyAbsolutePath(GetCollectionName(), "video", videoPath); 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; - LoadedComponent = videoBuild.CreateVideo(VideoPath, names[n], ScaleX, ScaleY); + LoadedComponent = videoBuild.CreateVideo(videoPath, names[n], ScaleX, ScaleY); if(LoadedComponent) { @@ -158,8 +153,10 @@ void ReloadableMedia::ReloadTexture() if(!LoadedComponent) { + std::string imagePath; + Config.GetMediaPropertyAbsolutePath(GetCollectionName(), Type, imagePath); ImageBuilder imageBuild; - LoadedComponent = imageBuild.CreateImage(ImagePath, selectedItem->GetFullTitle(), ScaleX, ScaleY); + LoadedComponent = imageBuild.CreateImage(imagePath, selectedItem->GetFullTitle(), ScaleX, ScaleY); if (LoadedComponent != NULL) { diff --git a/RetroFE/Source/Graphics/Component/ReloadableMedia.h b/RetroFE/Source/Graphics/Component/ReloadableMedia.h index 43d0d37..dca738d 100644 --- a/RetroFE/Source/Graphics/Component/ReloadableMedia.h +++ b/RetroFE/Source/Graphics/Component/ReloadableMedia.h @@ -14,7 +14,7 @@ class Image; class ReloadableMedia : public Component { 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(); void Update(float dt); void Draw(); @@ -25,14 +25,14 @@ public: private: void ReloadTexture(); + Configuration &Config; Component *LoadedComponent; - std::string ImagePath; - std::string VideoPath; bool ReloadRequested; bool FirstLoad; IVideo *VideoInst; bool IsVideo; + std::string Type; float ScaleX; float ScaleY; }; diff --git a/RetroFE/Source/Graphics/Component/ReloadableText.cpp b/RetroFE/Source/Graphics/Component/ReloadableText.cpp index 8a2f5ad..91c368e 100644 --- a/RetroFE/Source/Graphics/Component/ReloadableText.cpp +++ b/RetroFE/Source/Graphics/Component/ReloadableText.cpp @@ -23,10 +23,9 @@ #include #include -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) , LayoutKey(layoutKey) - , Collection(collection) , ReloadRequested(false) , FirstLoad(true) , FontInst(font) diff --git a/RetroFE/Source/Graphics/Component/ReloadableText.h b/RetroFE/Source/Graphics/Component/ReloadableText.h index 71e26c4..91f3d61 100644 --- a/RetroFE/Source/Graphics/Component/ReloadableText.h +++ b/RetroFE/Source/Graphics/Component/ReloadableText.h @@ -12,7 +12,7 @@ class ReloadableText : public Component { 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(); void Update(float dt); void Draw(); @@ -37,7 +37,6 @@ private: Text *ImageInst; TextType Type; std::string LayoutKey; - std::string Collection; bool ReloadRequested; bool FirstLoad; Font *FontInst; diff --git a/RetroFE/Source/Graphics/Component/ScrollingList.cpp b/RetroFE/Source/Graphics/Component/ScrollingList.cpp index 10fc525..7d47ce9 100644 --- a/RetroFE/Source/Graphics/Component/ScrollingList.cpp +++ b/RetroFE/Source/Graphics/Component/ScrollingList.cpp @@ -41,7 +41,6 @@ ScrollingList::ScrollingList(Configuration &c, Font *font, SDL_Color fontColor, std::string layoutKey, - std::string collectionName, std::string imageType) : IsScrollChangedStarted(true) , IsScrollChangedSignalled(false) @@ -64,9 +63,9 @@ ScrollingList::ScrollingList(Configuration &c, , FontInst(font) , FontColor(fontColor) , LayoutKey(layoutKey) - , CollectionName(collectionName) , ImageType(imageType) , MaxLayer(0) + , Focus(false) { } @@ -81,6 +80,7 @@ ScrollingList::~ScrollingList() if(*it != NULL) { DeallocateTexture(*it); + if((*it)->GetCollectionItem()) { delete (*it)->GetCollectionItem(); @@ -131,9 +131,11 @@ void ScrollingList::SetItems(std::vector *spriteList) } } -void ScrollingList::SetPoints(std::vector *scrollPoints) +void ScrollingList::SetPoints(std::vector *scrollPoints, std::vector *tweenPoints) { ScrollPoints = scrollPoints; + TweenPoints = tweenPoints; + for(unsigned int i = 0; i != scrollPoints->size(); ++i) { ViewInfo *info = scrollPoints->at(i); @@ -155,15 +157,18 @@ void ScrollingList::SetSelectedIndex(int selectedIndex) void ScrollingList::Click() { - if(CurrentScrollDirection == ScrollDirectionBack) + if(SpriteList) { - CircularDecrement(FirstSpriteIndex, SpriteList); - IsScrollChangedComplete = true; - } - if(CurrentScrollDirection == ScrollDirectionForward) - { - CircularIncrement(FirstSpriteIndex, SpriteList); - IsScrollChangedComplete = true; + if(CurrentScrollDirection == ScrollDirectionBack) + { + CircularDecrement(FirstSpriteIndex, SpriteList); + IsScrollChangedComplete = true; + } + if(CurrentScrollDirection == ScrollDirectionForward) + { + CircularIncrement(FirstSpriteIndex, SpriteList); + IsScrollChangedComplete = true; + } } } @@ -183,7 +188,7 @@ unsigned int ScrollingList::GetNextTween(unsigned int currentIndex, std::vector< void ScrollingList::PageUp() { - if(ScrollPoints && ScrollPoints->size() > 4) + if(SpriteList && ScrollPoints && ScrollPoints->size() > 4) { ScrollVelocity = 0; unsigned int counts = ScrollPoints->size() - 4; @@ -202,7 +207,7 @@ void ScrollingList::PageUp() void ScrollingList::PageDown() { - if(ScrollPoints && ScrollPoints->size() > 4) + if(SpriteList && ScrollPoints && ScrollPoints->size() > 4) { unsigned int counts = ScrollPoints->size() - 4; @@ -231,7 +236,7 @@ void ScrollingList::FreeGraphicsMemory() ScrollAcceleration = 6; // todo: make configurable ScrollVelocity = 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); @@ -239,6 +244,55 @@ void ScrollingList::FreeGraphicsMemory() } } +void ScrollingList::TriggerMenuEnterEvent() +{ + Focus = true; + + if(ScrollPoints && SpriteList && 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); + + Component *c = s->GetComponent(); + if(c) + { + c->SetTweens(TweenPoints->at(i)); + c->TriggerMenuEnterEvent(); + } + } + } + +} + +void ScrollingList::TriggerMenuExitEvent() +{ + Focus = false; + if(ScrollPoints && SpriteList && 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); + + Component *c = s->GetComponent(); + if(c) + { + c->SetTweens(TweenPoints->at(i)); + c->TriggerMenuExitEvent(); + } + } + } + +} + void ScrollingList::Update(float dt) { @@ -311,7 +365,7 @@ void ScrollingList::Update(float dt) } - if(ScrollPoints && SpriteList->size() > 0 && FirstSpriteIndex < SpriteList->size()) + if(ScrollPoints && SpriteList && SpriteList->size() > 0 && FirstSpriteIndex < SpriteList->size()) { unsigned int spriteIndex = FirstSpriteIndex; unsigned int numIterations = (ScrollPoints->size() > SpriteList->size()) ? SpriteList->size() : ScrollPoints->size(); @@ -320,37 +374,42 @@ void ScrollingList::Update(float dt) 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()); - currentViewInfo->SetImageWidth(c->GetBaseViewInfo()->GetImageWidth()); - nextViewInfo->SetImageHeight(c->GetBaseViewInfo()->GetImageHeight()); - nextViewInfo->SetImageWidth(c->GetBaseViewInfo()->GetImageWidth()); - nextViewInfo->SetBackgroundAlpha(c->GetBaseViewInfo()->GetBackgroundAlpha()); + if(Focus) + { + ViewInfo *spriteViewInfo = c->GetBaseViewInfo(); + ViewInfo *currentViewInfo = ScrollPoints->at(i); + unsigned int nextI = GetNextTween(i, ScrollPoints); + ViewInfo *nextViewInfo = ScrollPoints->at(nextI); + 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()); + 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)); + } + else + { +// c->GetBaseViewInfo()->SetAlpha(0.25); + } - //todo: 30 is a magic number - ViewInfo *spriteViewInfo = c->GetBaseViewInfo(); - 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); } @@ -433,7 +492,7 @@ void ScrollingList::AllocateTexture(ComponentItemBinding *s) //todo: will create a runtime fault if not of the right type //todo: remove coupling from knowing the collection name - std::string videoKey ="collections." + CollectionName + ".media.video"; + std::string videoKey ="collections." + GetCollectionName() + ".media.video"; std::string imagePath; std::string videoPath; @@ -476,6 +535,7 @@ void ScrollingList::DeallocateTexture(ComponentItemBinding *s) if(s && s->GetComponent() != NULL) { 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); } @@ -517,7 +577,7 @@ void ScrollingList::SetScrollDirection(ScrollDirection direction) void ScrollingList::RemoveSelectedItem() { ComponentItemBinding *sprite = GetSelectedCollectionItemSprite(); - if(sprite) + if(sprite && SpriteList) { Item *item = sprite->GetCollectionItem(); DeallocateTexture(sprite); @@ -569,7 +629,7 @@ ComponentItemBinding* ScrollingList::GetPendingCollectionItemSprite() { ComponentItemBinding *item = NULL; unsigned int index = FirstSpriteIndex; - if(CurrentScrollState != ScrollStatePageChange) + if(SpriteList && CurrentScrollState != ScrollStatePageChange) { if(CurrentScrollDirection == ScrollDirectionBack) { @@ -613,22 +673,25 @@ ComponentItemBinding* ScrollingList::GetPendingSelectedCollectionItemSprite() { ComponentItemBinding *item = NULL; - unsigned int index = SelectedSpriteListIndex; - - if(CurrentScrollDirection == ScrollDirectionBack) + if(SpriteList) { - CircularDecrement(index, SpriteList); - } - if(CurrentScrollDirection == ScrollDirectionForward) - { - CircularIncrement(index, SpriteList); - } + unsigned int index = SelectedSpriteListIndex; - if(SpriteList && SpriteList->size() > 0) - { - index = (index + SelectedSpriteListIndex) % SpriteList->size(); + if(CurrentScrollDirection == ScrollDirectionBack) + { + 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; diff --git a/RetroFE/Source/Graphics/Component/ScrollingList.h b/RetroFE/Source/Graphics/Component/ScrollingList.h index c293b75..f9d24cc 100644 --- a/RetroFE/Source/Graphics/Component/ScrollingList.h +++ b/RetroFE/Source/Graphics/Component/ScrollingList.h @@ -31,12 +31,21 @@ 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(); + void TriggerMenuEnterEvent(); + void TriggerMenuExitEvent(); + void AllocateTexture(ComponentItemBinding *s); void DeallocateTexture(ComponentItemBinding *s); void SetItems(std::vector *spriteList); - void SetPoints(std::vector *scrollPoints); + void SetPoints(std::vector *scrollPoints, std::vector *tweenPoints); void SetScrollDirection(ScrollDirection direction); void PageUp(); void PageDown(); @@ -71,8 +80,10 @@ private: std::vector *SpriteList; std::vector *ScrollPoints; + std::vector *TweenPoints; std::vector NotificationComponents; float TweenEnterTime; + bool Focus; unsigned int FirstSpriteIndex; unsigned int SelectedSpriteListIndex; @@ -98,7 +109,6 @@ private: Font *FontInst; SDL_Color FontColor; std::string LayoutKey; - std::string CollectionName; std::string ImageType; unsigned int MaxLayer; }; diff --git a/RetroFE/Source/Graphics/Page.cpp b/RetroFE/Source/Graphics/Page.cpp index 10b2724..adb574f 100644 --- a/RetroFE/Source/Graphics/Page.cpp +++ b/RetroFE/Source/Graphics/Page.cpp @@ -25,10 +25,10 @@ #include "ComponentItemBindingBuilder.h" #include -Page::Page(std::string collectionName, Configuration &config) - : CollectionName(collectionName) - , Config(config) - , Menu(NULL) +Page::Page(Configuration &config) + : Config(config) + , ActiveMenu(NULL) + , MenuDepth(0) , Items(NULL) , ScrollActive(false) , SelectedItem(NULL) @@ -45,9 +45,14 @@ Page::Page(std::string collectionName, Configuration &config) 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) @@ -60,10 +65,6 @@ Page::~Page() LayerComponents[i].clear(); } - if(Menu) - { - delete Menu; - } if(LoadSoundChunk) { @@ -97,14 +98,13 @@ void Page::OnNewItemSelected(Item *item) SelectedItemChanged = true; } -void Page::SetMenu(ScrollingList *s) +void Page::PushMenu(ScrollingList *s) { - // todo: delete the old menu - Menu = s; - - if(Menu) + Menus.push_back(s); + + if(s) { - Menu->AddComponentForNotifications(this); + s->AddComponentForNotifications(this); } } @@ -141,9 +141,15 @@ bool Page::IsIdle() { 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) @@ -160,7 +166,19 @@ bool Page::IsIdle() 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) { @@ -175,9 +193,11 @@ bool Page::IsHidden() void Page::Start() { - if(Menu) + for(MenuVector_T::iterator it = Menus.begin(); it != Menus.end(); it++) { - Menu->TriggerEnterEvent(); + ScrollingList *menu = *it; + menu->TriggerEnterEvent(); + Logger::Write(Logger::ZONE_DEBUG, "Page", "Triggering enter event"); } if(LoadSoundChunk) @@ -185,6 +205,12 @@ void Page::Start() LoadSoundChunk->Play(); } + StartComponents(); +} + + +void Page::StartComponents() +{ for(unsigned int i = 0; i < NUM_LAYERS; ++i) { for(std::vector::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it) @@ -196,10 +222,12 @@ void Page::Start() 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) { UnloadSoundChunk->Play(); @@ -222,11 +250,13 @@ Item *Page::GetSelectedItem() void Page::RemoveSelectedItem() { + /* //todo: change method to RemoveItem() and pass in SelectedItem if(Menu) { Menu->RemoveSelectedItem(); } + */ SelectedItem = NULL; } @@ -238,10 +268,10 @@ void Page::Highlight() if(item) { - if(Menu) + if(ActiveMenu) { - Menu->TriggerHighlightEvent(item); - Menu->SetScrollActive(ScrollActive); + ActiveMenu->TriggerHighlightEvent(item); + ActiveMenu->SetScrollActive(ScrollActive); } for(unsigned int i = 0; i < NUM_LAYERS; ++i) @@ -277,45 +307,99 @@ void Page::SetScrolling(ScrollDirection direction) break; } - if(Menu) + if(ActiveMenu) { - Menu->SetScrollDirection(menuDirection); + ActiveMenu->SetScrollDirection(menuDirection); } } void Page::PageScroll(ScrollDirection direction) { - if(Menu) + if(ActiveMenu) { if(direction == ScrollDirectionForward) { - Menu->PageDown(); + ActiveMenu->PageDown(); } if(direction == ScrollDirectionBack) { - Menu->PageUp(); + ActiveMenu->PageUp(); } } } - -void Page::SetCollection(CollectionInfo *collection) +bool Page::PushCollection(CollectionInfo *collection) { + Collections.push_back(collection); std::vector *sprites = ComponentItemBindingBuilder::BuildCollectionItems(collection->GetItems()); - if(Menu) + + if(ActiveMenu) { - Menu->SetItems(sprites); + Logger::Write(Logger::ZONE_INFO, "Page", "Trigger exit event, expect focus immediate"); + ActiveMenu->TriggerMenuExitEvent(); } + + ActiveMenu = Menus[MenuDepth]; + + ActiveMenu->SetItems(sprites); + ActiveMenu->SetCollectionName(collection->GetName()); + Logger::Write(Logger::ZONE_INFO, "Page", "Trigger enter event, expect focus immediate"); + ActiveMenu->TriggerMenuEnterEvent(); + + if(MenuDepth < Menus.size()) + { + MenuDepth++; + } + + for(unsigned int i = 0; i < NUM_LAYERS; ++i) + { + for(std::vector::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it) + { + (*it)->SetCollectionName(collection->GetName()); + } + } + Logger::Write(Logger::ZONE_INFO, "Page", "PUSH COMPLETE, expect updates"); + + 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) { - 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) { // skip the first sound being played (as it is part of the on-enter) @@ -357,24 +441,35 @@ void Page::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() { 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(); @@ -395,9 +490,12 @@ void Page::AllocateGraphicsMemory() { FirstSoundPlayed = false; 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(); @@ -417,9 +515,9 @@ void Page::AllocateGraphicsMemory() void Page::LaunchEnter() { - if(Menu) + if(ActiveMenu) { - Menu->LaunchEnter(); + ActiveMenu->LaunchEnter(); } for(unsigned int i = 0; i < NUM_LAYERS; ++i) @@ -433,9 +531,9 @@ void Page::LaunchEnter() void Page::LaunchExit() { - if(Menu) + if(ActiveMenu) { - Menu->LaunchExit(); + ActiveMenu->LaunchExit(); } for(unsigned int i = 0; i < NUM_LAYERS; ++i) diff --git a/RetroFE/Source/Graphics/Page.h b/RetroFE/Source/Graphics/Page.h index 3be321b..e29be46 100644 --- a/RetroFE/Source/Graphics/Page.h +++ b/RetroFE/Source/Graphics/Page.h @@ -1,12 +1,26 @@ -/* This file is subject to the terms and conditions defined in - * file 'LICENSE.txt', which is part of this source code package. +/* 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 . */ #pragma once #include "MenuNotifierInterface.h" -#include +#include #include +#include +#include class CollectionInfo; class Component; @@ -27,11 +41,14 @@ public: }; - Page(std::string collectionName, Configuration &c); + Page(Configuration &c); virtual ~Page(); virtual void OnNewItemSelected(Item *); - void SetCollection(CollectionInfo *collection); - void SetMenu(ScrollingList *s); + bool PushCollection(CollectionInfo *collection); + bool IsMenusFull() { return (MenuDepth > Menus.size()); } + bool PopCollection(); + void PushMenu(ScrollingList *s); + void SetLoadSound(Sound *chunk) { LoadSoundChunk = chunk; @@ -51,8 +68,10 @@ public: bool AddComponent(Component *c); void PageScroll(ScrollDirection direction); void Start(); + void StartComponents(); void Stop(); void SetScrolling(ScrollDirection direction); + unsigned int GetMenuDepth() { return MenuDepth; } Item *GetSelectedItem(); Item *GetPendingSelectedItem(); void RemoveSelectedItem(); @@ -65,13 +84,20 @@ public: void AllocateGraphicsMemory(); void LaunchEnter(); void LaunchExit(); - const std::string& GetCollectionName() const; + std::string GetCollectionName(); private: void Highlight(); std::string CollectionName; Configuration &Config; - ScrollingList *Menu; + typedef std::vector MenuVector_T; + typedef std::vector CollectionInfo_T; + + ScrollingList *ActiveMenu; + unsigned int MenuDepth; + MenuVector_T Menus; + CollectionInfo_T Collections; + static const unsigned int NUM_LAYERS = 8; std::vector LayerComponents[NUM_LAYERS]; std::vector *Items; @@ -86,4 +112,5 @@ private: bool HasSoundedWhenActive; bool FirstSoundPlayed; + }; diff --git a/RetroFE/Source/Graphics/PageBuilder.cpp b/RetroFE/Source/Graphics/PageBuilder.cpp index 18c6cd1..01adf7b 100644 --- a/RetroFE/Source/Graphics/PageBuilder.cpp +++ b/RetroFE/Source/Graphics/PageBuilder.cpp @@ -23,6 +23,7 @@ #include "Component/ReloadableText.h" #include "Component/ReloadableMedia.h" #include "Component/ScrollingList.h" +#include "Animate/TweenSet.h" #include "Animate/TweenTypes.h" #include "../Sound/Sound.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; //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) - , Collection(collection) , Config(c) , ScaleX(1) , ScaleY(1) @@ -168,7 +168,7 @@ Page *PageBuilder::BuildPage() ss << layoutWidth << "x" << layoutHeight << " (scale " << ScaleX << "x" << ScaleY << ")"; Logger::Write(Logger::ZONE_DEBUG, "Layout", "Layout resolution " + ss.str()); - page = new Page(Collection, Config); + page = new Page(Config); // load sounds 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)) { delete page; @@ -314,15 +315,12 @@ float PageBuilder::GetVerticalAlignment(xml_attribute<> *attribute, float valueI bool PageBuilder::BuildComponents(xml_node<> *layout, Page *page) { - xml_node<> *menuXml = layout->first_node("menu"); - - if(menuXml) + for(xml_node<> *componentXml = layout->first_node("menu"); componentXml; componentXml = componentXml->next_sibling("menu")) { - ScrollingList *scrollingList = BuildMenu(menuXml); - page->SetMenu(scrollingList); + ScrollingList *scrollingList = BuildMenu(componentXml); + page->PushMenu(scrollingList); } - for(xml_node<> *componentXml = layout->first_node("container"); componentXml; componentXml = componentXml->next_sibling("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"); } - 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; @@ -441,12 +431,12 @@ void PageBuilder::LoadReloadableImages(xml_node<> *layout, std::string tagName, if(type) { 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 { - c = new ReloadableMedia(reloadableImagePath, reloadableVideoPath, (tagName == "reloadableVideo"), ScaleX, ScaleY); + c = new ReloadableMedia(Config, type->value(), (tagName == "reloadableVideo"), ScaleX, ScaleY); } if(c) @@ -463,26 +453,22 @@ void PageBuilder::LoadTweens(Component *c, xml_node<> *componentXml) BuildViewInfo(componentXml, v); - Component::TweenSets *tweenSets; - tweenSets = new std::vector *>(); - GetTweenSets(componentXml->first_node("onEnter"), tweenSets); - c->SetOnEnterTweens(tweenSets); + c->SetTweens(CreateTweenInstance(componentXml)); +} - tweenSets = new std::vector *>(); - GetTweenSets(componentXml->first_node("onExit"), tweenSets); - c->SetOnExitTweens(tweenSets); +TweenSet *PageBuilder::CreateTweenInstance(xml_node<> *componentXml) +{ + TweenSet *tweens = new TweenSet(); - tweenSets = new std::vector *>(); - GetTweenSets(componentXml->first_node("onIdle"), tweenSets); - c->SetOnIdleTweens(tweenSets); + GetTweenSets(componentXml->first_node("onEnter"), tweens->GetOnEnterTweens()); + GetTweenSets(componentXml->first_node("onExit"), tweens->GetOnExitTweens()); + 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 *>(); - GetTweenSets(componentXml->first_node("onHighlightEnter"), tweenSets); - c->SetOnHighlightEnterTweens(tweenSets); - - tweenSets = new std::vector *>(); - GetTweenSets(componentXml->first_node("onHighlightExit"), tweenSets); - c->SetOnHighlightExitTweens(tweenSets); + return tweens; } @@ -515,7 +501,7 @@ ScrollingList * PageBuilder::BuildMenu(xml_node<> *menuXml) // on default, text will be rendered to the menu. Preload it into cache. 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(); BuildViewInfo(menuXml, v); @@ -529,6 +515,8 @@ ScrollingList * PageBuilder::BuildMenu(xml_node<> *menuXml) BuildVerticalMenu(menu, menuXml, itemDefaults); } + LoadTweens(menu, menuXml); + return menu; } @@ -536,6 +524,7 @@ ScrollingList * PageBuilder::BuildMenu(xml_node<> *menuXml) void PageBuilder::BuildCustomMenu(ScrollingList *menu, xml_node<> *menuXml, xml_node<> *itemDefaults) { std::vector *points = new std::vector(); + std::vector *tweenPoints = new std::vector(); int i = 0; @@ -543,9 +532,9 @@ void PageBuilder::BuildCustomMenu(ScrollingList *menu, xml_node<> *menuXml, xml_ { ViewInfo *viewInfo = new ViewInfo(); BuildViewInfo(componentXml, viewInfo, itemDefaults); - + points->push_back(viewInfo); - + tweenPoints->push_back(CreateTweenInstance(componentXml)); xml_attribute<> *selected = componentXml->first_attribute("selected"); if(selected) @@ -556,12 +545,13 @@ void PageBuilder::BuildCustomMenu(ScrollingList *menu, xml_node<> *menuXml, xml_ i++; } - menu->SetPoints(points); + menu->SetPoints(points, tweenPoints); } void PageBuilder::BuildVerticalMenu(ScrollingList *menu, xml_node<> *menuXml, xml_node<> *itemDefaults) { std::vector *points = new std::vector(); + std::vector *tweenPoints = new std::vector(); int selectedIndex = MENU_FIRST; std::map *> overrideItems; @@ -600,6 +590,7 @@ void PageBuilder::BuildVerticalMenu(ScrollingList *menu, xml_node<> *menuXml, xm xml_node<> *component = overrideItems[MENU_START]; ViewInfo *viewInfo = CreateMenuItemInfo(component, itemDefaults, menu->GetBaseViewInfo()->GetY() + height); points->push_back(viewInfo); + tweenPoints->push_back(CreateTweenInstance(component)); } while(!end) { @@ -637,6 +628,7 @@ void PageBuilder::BuildVerticalMenu(ScrollingList *menu, xml_node<> *menuXml, xm height = nextHeight; viewInfo->SetY(menu->GetBaseViewInfo()->GetY() + (float)height); points->push_back(viewInfo); + tweenPoints->push_back(CreateTweenInstance(component)); index++; } @@ -646,6 +638,7 @@ void PageBuilder::BuildVerticalMenu(ScrollingList *menu, xml_node<> *menuXml, xm xml_node<> *component = overrideItems[MENU_END]; ViewInfo *viewInfo = CreateMenuItemInfo(component, itemDefaults, menu->GetBaseViewInfo()->GetY() + height); points->push_back(viewInfo); + tweenPoints->push_back(CreateTweenInstance(component)); } if(selectedIndex >= ((int)points->size()-2)) @@ -658,7 +651,7 @@ void PageBuilder::BuildVerticalMenu(ScrollingList *menu, xml_node<> *menuXml, xm menu->SetSelectedIndex(selectedIndex+1); } - menu->SetPoints(points); + menu->SetPoints(points, tweenPoints); } 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); } - } - void PageBuilder::GetTweenSets(xml_node<> *node, std::vector *> *tweenSets) { if(node) diff --git a/RetroFE/Source/Graphics/PageBuilder.h b/RetroFE/Source/Graphics/PageBuilder.h index 26ff93a..8eee594 100644 --- a/RetroFE/Source/Graphics/PageBuilder.h +++ b/RetroFE/Source/Graphics/PageBuilder.h @@ -18,14 +18,13 @@ class Configuration; class PageBuilder { public: - PageBuilder(std::string layoutKey, std::string collection, Configuration &c, FontCache *fc); + PageBuilder(std::string layoutKey, Configuration &c, FontCache *fc); virtual ~PageBuilder(); Page *BuildPage(); private: std::string LayoutKey; std::string LayoutPath; - std::string Collection; Configuration &Config; float ScaleX; float ScaleY; @@ -42,6 +41,7 @@ private: void BuildViewInfo(rapidxml::xml_node<> *componentXml, ViewInfo *info, rapidxml::xml_node<> *defaultXml = NULL); bool BuildComponents(rapidxml::xml_node<> *layout, Page *page); void LoadTweens(Component *c, rapidxml::xml_node<> *componentXml); + TweenSet *CreateTweenInstance(rapidxml::xml_node<> *componentXml); ScrollingList * BuildMenu(rapidxml::xml_node<> *menuXml); void BuildCustomMenu(ScrollingList *menu, rapidxml::xml_node<> *menuXml, rapidxml::xml_node<> *itemDefaults); void BuildVerticalMenu(ScrollingList *menu, rapidxml::xml_node<> *menuXml, rapidxml::xml_node<> *itemDefaults); diff --git a/RetroFE/Source/RetroFE.cpp b/RetroFE/Source/RetroFE.cpp index 803be1d..0b88410 100644 --- a/RetroFE/Source/RetroFE.cpp +++ b/RetroFE/Source/RetroFE.cpp @@ -43,6 +43,7 @@ RetroFE::RetroFE(Configuration &c) , Config(c) , Db(NULL) , Input(Config) + , CurrentPage(NULL) , KeyInputDisable(0) , CurrentTime(0) { @@ -59,15 +60,11 @@ void RetroFE::Render() SDL_SetRenderDrawColor(SDL::GetRenderer(), 0x0, 0x0, 0x00, 0xFF); SDL_RenderClear(SDL::GetRenderer()); - if(PageChain.size() > 0) + if(CurrentPage) { - Page *page = PageChain.back(); - - if(page) - { - page->Draw(); - } + CurrentPage->Draw(); } + SDL_RenderPresent(SDL::GetRenderer()); SDL_UnlockMutex(SDL::GetMutex()); } @@ -111,11 +108,11 @@ int RetroFE::Initialize(void *context) void RetroFE::LaunchEnter() { - if(PageChain.size() > 0) + if(CurrentPage) { - Page *p = PageChain.back(); - p->LaunchEnter(); + CurrentPage->LaunchEnter(); } + SDL_SetWindowGrab(SDL::GetWindow(), SDL_FALSE); } @@ -125,20 +122,18 @@ void RetroFE::LaunchExit() SDL_RestoreWindow(SDL::GetWindow()); SDL_SetWindowGrab(SDL::GetWindow(), SDL_TRUE); - if(PageChain.size() > 0) + if(CurrentPage) { - Page *p = PageChain.back(); - p->LaunchExit(); + CurrentPage->LaunchExit(); } } void RetroFE::FreeGraphicsMemory() { - if(PageChain.size() > 0) + if(CurrentPage) { - Page *p = PageChain.back(); - p->FreeGraphicsMemory(); + CurrentPage->FreeGraphicsMemory(); } FC.DeInitialize(); @@ -151,11 +146,10 @@ void RetroFE::AllocateGraphicsMemory() FC.Initialize(); - if(PageChain.size() > 0) + if(CurrentPage) { - Page *p = PageChain.back(); - p->AllocateGraphicsMemory(); - p->Start(); + CurrentPage->AllocateGraphicsMemory(); + CurrentPage->Start(); } } @@ -166,11 +160,10 @@ bool RetroFE::DeInitialize() bool videoEnable = true; - while(PageChain.size() > 0) + if(CurrentPage) { - Page *page = PageChain.back(); - delete page; - PageChain.pop_back(); + delete CurrentPage; + CurrentPage = NULL; } if(MetaDb) { @@ -218,7 +211,7 @@ void RetroFE::Run() int initializeStatus = 0; // load the initial splash screen, unload it once it is complete - Page * page = LoadSplashPage(); + CurrentPage = LoadSplashPage(); bool splashMode = true; Launcher l(*this, Config); @@ -227,9 +220,8 @@ void RetroFE::Run() { float lastTime = 0; float deltaTime = 0; - page = PageChain.back(); - if(!page) + if(!CurrentPage) { Logger::Write(Logger::ZONE_WARNING, "RetroFE", "Could not load page"); running = false; @@ -239,9 +231,9 @@ void RetroFE::Run() switch(state) { case RETROFE_IDLE: - if(page && !splashMode) + if(CurrentPage && !splashMode) { - state = ProcessUserInput(page); + state = ProcessUserInput(CurrentPage); } else { @@ -253,65 +245,65 @@ void RetroFE::Run() if(Initialized && splashMode) { 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; case RETROFE_NEXT_PAGE_REQUEST: - page->Stop(); - state = RETROFE_NEXT_PAGE_WAIT; - break; - - case RETROFE_NEXT_PAGE_WAIT: - if(page->IsHidden()) + if(CurrentPage->IsIdle()) { - page = LoadPage(NextPageItem->GetName()); state = RETROFE_NEW; } break; case RETROFE_LAUNCH_REQUEST: - l.Run(page->GetCollectionName(), NextPageItem); + NextPageItem = CurrentPage->GetSelectedItem(); + l.Run(CurrentPage->GetCollectionName(), NextPageItem); state = RETROFE_IDLE; break; case RETROFE_BACK_REQUEST: - page->Stop(); - state = RETROFE_BACK_WAIT; - break; + CurrentPage->PopCollection(); + Config.SetCurrentCollection(CurrentPage->GetCollectionName()); - case RETROFE_BACK_WAIT: - if(page->IsHidden()) - { - PageChain.pop_back(); - delete page; + state = RETROFE_NEW; - page = (splashMode) ? LoadPage(firstCollection) : PageChain.back(); - splashMode = false; - CurrentTime = (float)SDL_GetTicks() / 1000; - - page->AllocateGraphicsMemory(); - page->Start(); - state = RETROFE_NEW; - } break; case RETROFE_NEW: - if(page->IsIdle()) + if(CurrentPage->IsIdle()) { state = RETROFE_IDLE; } break; case RETROFE_QUIT_REQUEST: - page->Stop(); + CurrentPage->Stop(); state = RETROFE_QUIT; break; case RETROFE_QUIT: - if(page->IsHidden()) + if(CurrentPage->IsHidden()) { running = false; } @@ -337,10 +329,10 @@ void RetroFE::Run() SDL_Delay(static_cast(sleepTime)); } - if(page) + if(CurrentPage) { - Attract.Update(deltaTime, *page); - page->Update(deltaTime); + Attract.Update(deltaTime, *CurrentPage); + CurrentPage->Update(deltaTime); } Render(); @@ -353,22 +345,16 @@ void RetroFE::Run() bool RetroFE::Back(bool &exit) { bool canGoBack = false; - bool exitOnBack = false; Config.GetProperty("exitOnFirstPageBack", exitOnBack); exit = false; - if(PageChain.size() > 1) + if(CurrentPage->GetMenuDepth() == 0) { - Page *page = PageChain.back(); - page->Stop(); - canGoBack = true; + exit = exitOnBack; } - else if(PageChain.size() == 1 && exitOnBack) + else { - Page *page = PageChain.back(); - page->Stop(); - exit = true; canGoBack = true; } @@ -413,10 +399,23 @@ RetroFE::RETROFE_STATE RetroFE::ProcessUserInput(Page *page) if (keys[Input.GetScancode(UserInput::KeyCodeSelect)]) { NextPageItem = page->GetSelectedItem(); + Logger::Write(Logger::ZONE_INFO, "RetroFE", "SELECT KEYCODE START"); 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()); + + Logger::Write(Logger::ZONE_INFO, "RetroFE", "PUSH COLLECTION. EXPECT FOCUS IMMEDIATE"); + page->PushCollection(info); + state = RETROFE_NEXT_PAGE_REQUEST; + } } } @@ -449,7 +448,7 @@ void RetroFE::WaitToInitialize() { Logger::Write(Logger::ZONE_INFO, "RetroFE", "Loading splash screen"); - PageBuilder pb("splash", "", Config, &FC); + PageBuilder pb("splash", Config, &FC); Page * page = pb.BuildPage(); while(!Initialized) @@ -467,47 +466,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); - CollectionInfo *collection = GetCollection(collectionName); - std::string layoutName = GetLayout(collectionName); - - if(PageChain.size() > 0) - { - Page *oldPage = PageChain.back(); - oldPage->FreeGraphicsMemory(); - } - - PageBuilder pb(layoutName, collectionName, Config, &FC); - page = pb.BuildPage(); + PageBuilder pb(layoutName, Config, &FC); + Page *page = pb.BuildPage(); 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 { - page->SetCollection(collection); page->Start(); - - PageChain.push_back(page); } return page; } + Page *RetroFE::LoadSplashPage() { - PageBuilder pb("Splash", "", Config, &FC); + PageBuilder pb("Splash", Config, &FC); Page * page = pb.BuildPage(); - Config.SetCurrentCollection(""); - page->SetCollection(new CollectionInfo("", "", "", "", "")); page->Start(); - PageChain.push_back(page); return page; } diff --git a/RetroFE/Source/RetroFE.h b/RetroFE/Source/RetroFE.h index be8cda0..df9c1eb 100644 --- a/RetroFE/Source/RetroFE.h +++ b/RetroFE/Source/RetroFE.h @@ -38,10 +38,8 @@ private: { RETROFE_IDLE, RETROFE_NEXT_PAGE_REQUEST, - RETROFE_NEXT_PAGE_WAIT, RETROFE_LAUNCH_REQUEST, RETROFE_BACK_REQUEST, - RETROFE_BACK_WAIT, RETROFE_NEW, RETROFE_QUIT_REQUEST, RETROFE_QUIT, @@ -51,7 +49,7 @@ private: bool Back(bool &exit); void Quit(); void WaitToInitialize(); - Page *LoadPage(std::string collectionName); + Page *LoadPage(); Page *LoadSplashPage(); RETROFE_STATE ProcessUserInput(Page *page); void Update(float dt, bool scrollActive); @@ -61,7 +59,7 @@ private: DB *Db; MetadataDatabase *MetaDb; UserInput Input; - std::list PageChain; + Page *CurrentPage; float KeyInputDisable; float CurrentTime; Item *NextPageItem;