From 8bd246818c79e0a1feba29dd393cd43a774b0991 Mon Sep 17 00:00:00 2001 From: Don Honerbrink Date: Tue, 28 Jul 2015 16:37:45 -0500 Subject: [PATCH 1/7] playlist support - crashes --- Package/Environment/Common/controls.conf | 1 + RetroFE/Source/Collection/CollectionInfo.cpp | 12 +++++++++--- RetroFE/Source/Collection/CollectionInfo.h | 4 ++++ .../Collection/CollectionInfoBuilder.cpp | 8 ++++++++ RetroFE/Source/Control/UserInput.cpp | 1 + RetroFE/Source/Control/UserInput.h | 1 + .../Graphics/Component/ScrollingList.cpp | 8 +++----- RetroFE/Source/Graphics/Page.cpp | 18 ++++++++++++++++++ RetroFE/Source/Graphics/Page.h | 4 +++- RetroFE/Source/RetroFE.cpp | 5 ++++- 10 files changed, 52 insertions(+), 10 deletions(-) diff --git a/Package/Environment/Common/controls.conf b/Package/Environment/Common/controls.conf index 6e8b4c1..a315ed2 100644 --- a/Package/Environment/Common/controls.conf +++ b/Package/Environment/Common/controls.conf @@ -6,6 +6,7 @@ pageUp = A pageDown = B letterUp = N letterDown = M +nextPlaylist = P select = Space back = Escape quit = Q diff --git a/RetroFE/Source/Collection/CollectionInfo.cpp b/RetroFE/Source/Collection/CollectionInfo.cpp index 508e357..d74955b 100644 --- a/RetroFE/Source/Collection/CollectionInfo.cpp +++ b/RetroFE/Source/Collection/CollectionInfo.cpp @@ -37,11 +37,17 @@ CollectionInfo::~CollectionInfo() { // remove items from the subcollections so their destructors do not // delete the items since the parent collection will delete them. - std::vector::iterator subit; - for (subit != subcollections_.begin(); subit != subcollections_.end(); subit++) + std::vector::iterator subit = subcollections_.begin(); + while (subit != subcollections_.end()) { CollectionInfo *info = *subit; - info->items.clear(); + subcollections_.erase(subit); + + if(info != this) + { + delete info; + } + subit = subcollections_.begin(); } diff --git a/RetroFE/Source/Collection/CollectionInfo.h b/RetroFE/Source/Collection/CollectionInfo.h index a1b5812..d4086da 100644 --- a/RetroFE/Source/Collection/CollectionInfo.h +++ b/RetroFE/Source/Collection/CollectionInfo.h @@ -17,6 +17,7 @@ #include #include +#include class Item; @@ -36,6 +37,9 @@ public: std::string launcher; std::vector items; + typedef std::map > Playlists_T; + Playlists_T playlists; + private: std::vector subcollections_; std::string metadataPath_; diff --git a/RetroFE/Source/Collection/CollectionInfoBuilder.cpp b/RetroFE/Source/Collection/CollectionInfoBuilder.cpp index 5209b73..595b70c 100644 --- a/RetroFE/Source/Collection/CollectionInfoBuilder.cpp +++ b/RetroFE/Source/Collection/CollectionInfoBuilder.cpp @@ -242,8 +242,10 @@ bool CollectionInfoBuilder::ImportDirectory(CollectionInfo *info, std::string me struct dirent *dirp; std::string path = info->listpath; std::map includeFilter; + std::map favoritesFilter; std::map excludeFilter; std::string includeFile = Utils::combinePath(Configuration::absolutePath, "collections", info->name, "include.txt"); + std::string favoritesFile = Utils::combinePath(Configuration::absolutePath, "collections", info->name, "favorites.txt"); std::string excludeFile = Utils::combinePath(Configuration::absolutePath, "collections", info->name, "exclude.txt"); std::string launcher; @@ -269,6 +271,7 @@ bool CollectionInfoBuilder::ImportDirectory(CollectionInfo *info, std::string me { Logger::write(Logger::ZONE_INFO, "CollectionInfoBuilder", "Checking for \"" + includeFile + "\""); ImportBasicList(info, includeFile, includeFilter); + ImportBasicList(info, favoritesFile, favoritesFilter); ImportBasicList(info, excludeFile, excludeFilter); } @@ -297,6 +300,10 @@ bool CollectionInfoBuilder::ImportDirectory(CollectionInfo *info, std::string me } } } + for(std::map::iterator it = favoritesFilter.begin(); it != favoritesFilter.end(); it++) + { + info->playlists["favorites"].push_back(it->second); + } while((dirp = readdir(dp)) != NULL) { @@ -327,6 +334,7 @@ bool CollectionInfoBuilder::ImportDirectory(CollectionInfo *info, std::string me i->collectionInfo = info; info->items.push_back(i); + info->playlists["include"].push_back(i); } } } diff --git a/RetroFE/Source/Control/UserInput.cpp b/RetroFE/Source/Control/UserInput.cpp index 4449fcc..8dcc048 100644 --- a/RetroFE/Source/Control/UserInput.cpp +++ b/RetroFE/Source/Control/UserInput.cpp @@ -67,6 +67,7 @@ bool UserInput::initialize() retVal = MapKey("select", KeyCodeSelect) && retVal; retVal = MapKey("back", KeyCodeBack) && retVal; retVal = MapKey("quit", KeyCodeQuit) && retVal; + MapKey("nextPlaylist", KeyCodeNextPlaylist); // these features will need to be implemented at a later time // retVal = MapKey("admin", KeyCodeAdminMode) && retVal; // retVal = MapKey("remove", KeyCodeHideItem) && retVal; diff --git a/RetroFE/Source/Control/UserInput.h b/RetroFE/Source/Control/UserInput.h index 4fbb66a..34ed4ab 100644 --- a/RetroFE/Source/Control/UserInput.h +++ b/RetroFE/Source/Control/UserInput.h @@ -38,6 +38,7 @@ public: KeyCodePageUp, KeyCodeLetterDown, KeyCodeLetterUp, + KeyCodeNextPlaylist, KeyCodeAdminMode, KeyCodeHideItem, KeyCodeQuit, diff --git a/RetroFE/Source/Graphics/Component/ScrollingList.cpp b/RetroFE/Source/Graphics/Component/ScrollingList.cpp index c42c291..090d110 100644 --- a/RetroFE/Source/Graphics/Component/ScrollingList.cpp +++ b/RetroFE/Source/Graphics/Component/ScrollingList.cpp @@ -125,6 +125,7 @@ ScrollingList::~ScrollingList() destroyItems(); } + void ScrollingList::setItems(std::vector *spriteList) { notifyAllRequested_ = true; @@ -227,6 +228,7 @@ void ScrollingList::destroyItems() { return; } + std::vector::iterator it = spriteList_->begin(); while(it != spriteList_->end()) @@ -235,11 +237,7 @@ void ScrollingList::destroyItems() { deallocateTexture(*it); - if((*it)->item) - { - delete (*it)->item; - } - + // items are destroyed when collections are destroyed delete *it; } diff --git a/RetroFE/Source/Graphics/Page.cpp b/RetroFE/Source/Graphics/Page.cpp index eb7392e..7a4c3eb 100644 --- a/RetroFE/Source/Graphics/Page.cpp +++ b/RetroFE/Source/Graphics/Page.cpp @@ -438,6 +438,7 @@ bool Page::pushCollection(CollectionInfo *collection) activeMenu_->destroyItems(); activeMenu_->setItems(sprites); activeMenu_->triggerMenuEnterEvent(); + playlist_ = collection->playlists.begin(); if(menuDepth_ < menus_.size()) { @@ -514,9 +515,26 @@ bool Page::popCollection() } } + if(collection) + { + delete collection; + } + return true; } +void Page::nextPlaylist() +{ + CollectionInfo *collection = collections_.back(); + playlist_++; + if(playlist_ == collection->playlists.end()) playlist_ = collection->playlists.begin(); + + std::vector *sprites = ComponentItemBindingBuilder::buildCollectionItems(&playlist_->second); + + activeMenu_->destroyItems(); + activeMenu_->setItems(sprites); + activeMenu_->triggerMenuEnterEvent(); +} void Page::update(float dt) { diff --git a/RetroFE/Source/Graphics/Page.h b/RetroFE/Source/Graphics/Page.h index 617fa76..2591d5e 100644 --- a/RetroFE/Source/Graphics/Page.h +++ b/RetroFE/Source/Graphics/Page.h @@ -16,13 +16,13 @@ #pragma once #include "MenuNotifierInterface.h" +#include "../Collection/CollectionInfo.h" #include #include #include #include -class CollectionInfo; class Component; class Configuration; class ScrollingList; @@ -46,6 +46,7 @@ public: virtual void onNewItemSelected(Item *); bool pushCollection(CollectionInfo *collection); bool popCollection(); + void nextPlaylist(); void pushMenu(ScrollingList *s); bool isMenusFull(); void setLoadSound(Sound *chunk); @@ -105,6 +106,7 @@ private: Sound *selectSoundChunk_; float minShowTime_; float elapsedTime_; + CollectionInfo::Playlists_T::iterator playlist_; }; diff --git a/RetroFE/Source/RetroFE.cpp b/RetroFE/Source/RetroFE.cpp index 76fefb1..a7317e0 100644 --- a/RetroFE/Source/RetroFE.cpp +++ b/RetroFE/Source/RetroFE.cpp @@ -489,7 +489,10 @@ RetroFE::RETROFE_STATE RetroFE::processUserInput(Page *page) } } } - + if(input_.keystate(UserInput::KeyCodeNextPlaylist) && page->isMenuIdle()) + { + page->nextPlaylist(); + } if (input_.keystate(UserInput::KeyCodeBack) && page->isMenuIdle()) { if(back(exit) || exit) From f912afcdf017a8a12296b273a48432b0f428c8af Mon Sep 17 00:00:00 2001 From: Don Honerbrink Date: Fri, 31 Jul 2015 17:33:54 -0500 Subject: [PATCH 2/7] Refactoring ScrollingList to address memory leak issues (required for playlists) --- .../Graphics/Component/ScrollingList.cpp | 722 ++++-------------- .../Source/Graphics/Component/ScrollingList.h | 266 ++++--- RetroFE/Source/Graphics/Page.cpp | 11 +- 3 files changed, 298 insertions(+), 701 deletions(-) diff --git a/RetroFE/Source/Graphics/Component/ScrollingList.cpp b/RetroFE/Source/Graphics/Component/ScrollingList.cpp index 090d110..c4e6a21 100644 --- a/RetroFE/Source/Graphics/Component/ScrollingList.cpp +++ b/RetroFE/Source/Graphics/Component/ScrollingList.cpp @@ -19,7 +19,6 @@ #include "../Animate/Animation.h" #include "../Animate/AnimationEvents.h" #include "../Animate/TweenTypes.h" -#include "../ComponentItemBinding.h" #include "../Font.h" #include "ScrollingList.h" #include "ImageBuilder.h" @@ -50,10 +49,9 @@ ScrollingList::ScrollingList(Configuration &c, , spriteList_(NULL) , scrollPoints_(NULL) , tweenPoints_(NULL) - , tweenEnterTime_(0) , focus_(false) - , firstSpriteIndex_(0) - , selectedSpriteListIndex_(0) + , itemIndex_(0) + , componentIndex_(0) , scrollStopRequested_(true) , notifyAllRequested_(false) , currentScrollDirection_(ScrollDirectionIdle) @@ -68,6 +66,7 @@ ScrollingList::ScrollingList(Configuration &c, , fontInst_(font) , layoutKey_(layoutKey) , imageType_(imageType) + , items_(NULL) { } @@ -75,10 +74,7 @@ ScrollingList::ScrollingList(const ScrollingList ©) : Component(copy) , horizontalScroll(copy.horizontalScroll) , spriteList_(NULL) - , tweenEnterTime_(0) , focus_(false) - , firstSpriteIndex_(0) - , selectedSpriteListIndex_(copy.selectedSpriteListIndex_) , scrollStopRequested_(true) , notifyAllRequested_(false) , currentScrollDirection_(ScrollDirectionIdle) @@ -93,6 +89,7 @@ ScrollingList::ScrollingList(const ScrollingList ©) , fontInst_(copy.fontInst_) , layoutKey_(copy.layoutKey_) , imageType_(copy.imageType_) + , items_(NULL) { scrollPoints_ = NULL; @@ -126,38 +123,34 @@ ScrollingList::~ScrollingList() } -void ScrollingList::setItems(std::vector *spriteList) +void ScrollingList::setItems(CollectionInfo *info) { - notifyAllRequested_ = true; - spriteList_ = spriteList; - firstSpriteIndex_ = 0; + std::cout << "setItems" << std::endl; + deallocateSpritePoints(); - 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)->item; - - *newItem = *originalItem; - ComponentItemBinding *newSprite = new ComponentItemBinding(newItem); - spriteList_->push_back(newSprite); - } - } - - for(unsigned int i = 0; scrollPoints_ && i < selectedSpriteListIndex_; ++i) - { - circularDecrement(firstSpriteIndex_, spriteList_); - } + collection_ = info; + items_ = &collection_->items; + itemIndex_ = 0; + componentIndex_ = 0; + allocateSpritePoints(); + + notifyAllRequested_ = true; + +} + +unsigned int ScrollingList::loopIncrement(unsigned int offset, unsigned int i, unsigned int size) +{ + if(size == 0) return 0; + return (offset + i) % size; +} + +unsigned int ScrollingList::loopDecrement(unsigned int offset, unsigned int i, unsigned int size) +{ + if(size == 0) return 0; + // (A - B) % C = ((A % C) - (B % C)) % C + return ((offset % size) - (i % size) ) % size; } @@ -173,214 +166,125 @@ void ScrollingList::setStartScrollTime(float value) void ScrollingList::deallocateSpritePoints() { - if(!spriteList_) + for(unsigned int i = 0; i < components_.size(); ++i) { - return; - } - - unsigned int spriteIndex = firstSpriteIndex_; - - for(unsigned int i = 0; i < scrollPoints_->size() && spriteList_->size() > spriteIndex; ++i) - { - deallocateTexture(spriteList_->at(spriteIndex)); - circularIncrement(spriteIndex, spriteList_); + deallocateTexture(i); } } void ScrollingList::allocateSpritePoints() { - if(!scrollPoints_) + for(unsigned int i = 0; items_ && i < scrollPoints_->size(); ++i) { - return; - } - if(!spriteList_) - { - return; - } - if(spriteList_->size() == 0) - { - return; - } - if(!tweenPoints_) - { - return; - } + unsigned int index = loopIncrement(itemIndex_, i, items_->size()); + Item *item = items_->at(index); - unsigned int spriteIndex = firstSpriteIndex_; + allocateTexture(i, item); + Component *c = components_.at(i); - for(unsigned int i = 0; i < scrollPoints_->size(); ++i) - { - allocateTexture(spriteList_->at(spriteIndex)); - Component *c = spriteList_->at(spriteIndex)->component; - ViewInfo *currentViewInfo = scrollPoints_->at(i); - unsigned int nextI = getNextTween(i, scrollPoints_); - ViewInfo *nextViewInfo = scrollPoints_->at(nextI); + ViewInfo *current = scrollPoints_->at(i); - resetTweens(c, tweenPoints_->at(i), currentViewInfo, nextViewInfo, 0); + unsigned int nextI = loopIncrement(i, 1, scrollPoints_->size()); + ViewInfo *next = scrollPoints_->at(nextI); - circularIncrement(spriteIndex, spriteList_); + resetTweens(c, tweenPoints_->at(i), current, next, 0); } } void ScrollingList::destroyItems() { - if(!spriteList_) - { - return; - } - - std::vector::iterator it = spriteList_->begin(); - - while(it != spriteList_->end()) - { - if(*it != NULL) - { - deallocateTexture(*it); - - // items are destroyed when collections are destroyed - delete *it; - } - - - spriteList_->erase(it); - - it = spriteList_->begin(); - } - - delete spriteList_; - spriteList_ = NULL; + deallocateSpritePoints(); +//todo: who deletes the CollectionInfo? } void ScrollingList::setPoints(std::vector *scrollPoints, std::vector *tweenPoints) { + deallocateSpritePoints(); + scrollPoints_ = scrollPoints; tweenPoints_ = tweenPoints; + + // empty out the list as we will resize it + components_.clear(); + + if(scrollPoints && scrollPoints_->size() > components_.size()) + { + components_.resize(scrollPoints_->size(), NULL); + } + allocateSpritePoints(); } unsigned int ScrollingList::getScrollOffsetIndex() { - return firstSpriteIndex_; + return itemIndex_; } void ScrollingList::setScrollOffsetIndex(unsigned int index) { - if(spriteList_ && index < spriteList_->size()) - { - deallocateSpritePoints(); - firstSpriteIndex_ = index; - allocateSpritePoints(); - } + itemIndex_ = index; } void ScrollingList::setSelectedIndex(int selectedIndex) { - selectedSpriteListIndex_ = selectedIndex; - - for(unsigned int i = 0; spriteList_ && scrollPoints_ && i < selectedSpriteListIndex_; ++i) - { - circularDecrement(firstSpriteIndex_, spriteList_); - } + selectedOffsetIndex_ = selectedIndex; } 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; - + ViewInfo *cur; + ViewInfo *next; if(currentScrollDirection_ == ScrollDirectionBack) { - deallocSpriteIndex = end; - circularDecrement(firstSpriteIndex_, spriteList_); - allocSpriteIndex = firstSpriteIndex_; - allocPoint = 0; + next = scrollPoints_->at(componentIndex_); + itemIndex_ = loopIncrement(itemIndex_, 1, items_->size()); + componentIndex_ = loopIncrement(componentIndex_, 1, components_.size()); + cur = scrollPoints_->at(componentIndex_); } else if(currentScrollDirection_ == ScrollDirectionForward) { - deallocSpriteIndex = firstSpriteIndex_; - circularIncrement(firstSpriteIndex_, spriteList_); - allocSpriteIndex = circularIncrement(firstSpriteIndex_, listSize - 1, spriteList_); - allocPoint = listSize - 1; + next = scrollPoints_->at(componentIndex_); + itemIndex_ = loopDecrement(itemIndex_, 1, items_->size()); + componentIndex_ = loopDecrement(componentIndex_, 1, components_.size()); + cur = scrollPoints_->at(componentIndex_); } else { return; } - deallocateTexture(spriteList_->at(deallocSpriteIndex)); - allocateTexture(spriteList_->at(allocSpriteIndex)); + Item *i = items_->at(itemIndex_); - Component *c = spriteList_->at(allocSpriteIndex)->component; - ViewInfo *currentViewInfo = scrollPoints_->at(allocPoint); - unsigned int nextI = getNextTween(allocPoint, scrollPoints_); - ViewInfo *nextViewInfo = scrollPoints_->at(nextI); + deallocateTexture(componentIndex_); + allocateTexture(componentIndex_, i); + Component *c = components_.at(componentIndex_); - resetTweens(c, tweenPoints_->at(allocPoint), currentViewInfo, nextViewInfo, nextScrollTime); -} + resetTweens(c, tweenPoints_->at(componentIndex_), cur, next, 0); -unsigned int ScrollingList::getNextTween(unsigned int currentIndex, std::vector *list) -{ - if(currentScrollDirection_ == ScrollDirectionForward) - { - circularDecrement(currentIndex, list); - } - else if(currentScrollDirection_ == ScrollDirectionBack) - { - circularIncrement(currentIndex, list); - } - - return currentIndex; } void ScrollingList::pageUp() { notifyAllRequested_ = true; + + if(components_.size() == 0) return; + deallocateSpritePoints(); - if(spriteList_ && scrollPoints_ && scrollPoints_->size() > 2) - { - scrollPeriod_ = 0; - unsigned int counts = scrollPoints_->size() - 2; - - for(unsigned int i = 0; i < counts; i++) - { - circularDecrement(firstSpriteIndex_, spriteList_); - } - } - + itemIndex_ = loopDecrement(itemIndex_, components_.size(), items_->size()); + allocateSpritePoints(); - -// CurrentScrollState = ScrollStatePageChange; } void ScrollingList::pageDown() { notifyAllRequested_ = true; + if(components_.size() == 0) return; + deallocateSpritePoints(); - if(spriteList_ && scrollPoints_ && scrollPoints_->size() > 2) - { - unsigned int counts = scrollPoints_->size() - 2; - - scrollPeriod_ = 0; - for(unsigned int i = 0; i < counts; i++) - { - circularIncrement(firstSpriteIndex_, spriteList_); - } - } + itemIndex_ = loopIncrement(itemIndex_, components_.size(), items_->size()); allocateSpritePoints(); } @@ -388,77 +292,39 @@ void ScrollingList::pageDown() void ScrollingList::letterUp() { - notifyAllRequested_ = true; - deallocateSpritePoints(); - - if(spriteList_ && scrollPoints_ && getSelectedCollectionItemSprite()) - { - unsigned int i = 0; - - // Select the previous item in the list in case we are at the top of all the items - // for the currently selected letter. - circularDecrement(firstSpriteIndex_, spriteList_); - std::string startname = getSelectedCollectionItemSprite()->item->lowercaseFullTitle(); - ++i; - - bool done = false; - - // traverse up through the list until we find the first item that starts with a different letter - while(!done && i < spriteList_->size()) - { - circularDecrement(firstSpriteIndex_, spriteList_); - std::string endname = getSelectedCollectionItemSprite()->item->lowercaseFullTitle(); - ++i; - - // check if we are changing characters from a-z, or changing from alpha character to non-alpha character - if(isalpha(startname[0]) ^ isalpha(endname[0])) - { - done = true; - } - else if(isalpha(startname[0]) && isalpha(endname[0]) && startname[0] != endname[0]) - { - done = true; - } - - if(done) - { - // our searching went too far, rewind to the first item in the list that matches the starting letter - circularIncrement(firstSpriteIndex_, spriteList_); - } - } - } - - allocateSpritePoints(); + letterChange(true); } void ScrollingList::letterDown() +{ + letterChange(false); +} + +void ScrollingList::letterChange(bool increment) { notifyAllRequested_ = true; deallocateSpritePoints(); - if(spriteList_ && scrollPoints_ && getSelectedCollectionItemSprite()) + std::string startname = items_->at(itemIndex_)->lowercaseFullTitle(); + + for(unsigned int i = 0; i < items_->size(); ++i) { + unsigned int index = 0; + if(increment) index = loopIncrement(itemIndex_, i, items_->size()); + else index = loopDecrement(itemIndex_, i, items_->size()); - std::string startname = getSelectedCollectionItemSprite()->item->lowercaseFullTitle(); - std::string endname = startname; + std::string endname = items_->at(index)->lowercaseFullTitle(); - unsigned int i = 0; - bool done = false; - while(!done && i < spriteList_->size()) + // check if we are changing characters from a-z, or changing from alpha character to non-alpha character + if(isalpha(startname[0]) ^ isalpha(endname[0])) { - circularIncrement(firstSpriteIndex_, spriteList_); - endname = getSelectedCollectionItemSprite()->item->lowercaseFullTitle(); - ++i; - - // check if we are changing characters from a-z, or changing from alpha character to non-alpha character - if(isalpha(startname[0]) ^ isalpha(endname[0])) - { - done = true; - } - else if(isalpha(startname[0]) && isalpha(endname[0]) && startname[0] != endname[0]) - { - done = true; - } + break; + itemIndex_ = index; + } + else if(isalpha(startname[0]) && isalpha(endname[0]) && startname[0] != endname[0]) + { + itemIndex_ = index; + break; } } @@ -469,18 +335,12 @@ void ScrollingList::letterDown() void ScrollingList::freeGraphicsMemory() { Component::freeGraphicsMemory(); - tweenEnterTime_ = 0; currentScrollDirection_ = ScrollDirectionIdle; requestedScrollDirection_ = ScrollDirectionIdle; currentScrollState_ = ScrollStateIdle; scrollPeriod_ = 0; - - for(unsigned int i = 0; spriteList_ && i < spriteList_->size(); i++) - { - ComponentItemBinding *s = spriteList_->at(i); - - deallocateTexture(s); - } + + deallocateSpritePoints(); } void ScrollingList::triggerMenuEnterEvent() @@ -488,36 +348,10 @@ void ScrollingList::triggerMenuEnterEvent() focus_ = true; notifyAllRequested_ = true; - if(!scrollPoints_) + for(unsigned int i = 0; i < components_.size(); ++i) { - 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->component; - if(c) - { - c->triggerMenuEnterEvent(); - } - - circularIncrement(spriteIndex, spriteList_); + Component *c = components_.at(i); + if(c) c->triggerMenuEnterEvent(); } } @@ -526,36 +360,10 @@ void ScrollingList::triggerMenuExitEvent() focus_ = false; notifyAllRequested_ = true; - if(!scrollPoints_) + for(unsigned int i = 0; i < components_.size(); ++i) { - 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->component; - if(c) - { - c->triggerMenuExitEvent(); - } - - circularIncrement(spriteIndex, spriteList_); + Component *c = components_.at(i); + if(c) c->triggerMenuExitEvent(); } } @@ -563,29 +371,15 @@ void ScrollingList::update(float dt) { Component::update(dt); - 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++) + for(unsigned int i = 0; i < components_.size(); i++) { - ComponentItemBinding *s = spriteList_->at(i); - Component *c = s->component; + Component *c = components_.at(i); if(c && c->isMenuScrolling()) { @@ -620,20 +414,11 @@ void ScrollingList::update(float dt) currentScrollState_ = ScrollStateIdle; scrollStopped = true; - // update the tweens now that we are done - unsigned int spriteIndex = firstSpriteIndex_; - for(unsigned int i = 0; i < tweenPoints_->size(); ++i) { - ComponentItemBinding *s = spriteList_->at(spriteIndex); + Component *c = components_.at(i); - Component *c = s->component; - if(c) - { - c->setTweens(tweenPoints_->at(i)); - } - - circularIncrement(spriteIndex, spriteList_); + if(c) c->setTweens(tweenPoints_->at(i)); } } @@ -652,28 +437,44 @@ void ScrollingList::update(float dt) } - unsigned int spriteIndex = firstSpriteIndex_; for(unsigned int i = 0; i < scrollPoints_->size(); i++) { - updateSprite(spriteIndex, i, (scrollRequested || scrollChanged), dt, scrollPeriod_); - circularIncrement(spriteIndex, spriteList_); + unsigned int cindex = loopIncrement(componentIndex_, i, components_.size()); + Component *c = components_.at(cindex); + + if(c && (scrollRequested || scrollChanged)) + { + ViewInfo *currentvi = scrollPoints_->at(i); + unsigned int nextI = 0; + if(currentScrollDirection_ == ScrollDirectionBack) + { + nextI = loopIncrement(i, 1, scrollPoints_->size()); + } + if(currentScrollDirection_ == ScrollDirectionForward) + { + nextI = loopDecrement(i, 1, scrollPoints_->size()); + } + + ViewInfo *nextvi = scrollPoints_->at(nextI); + + resetTweens(c, tweenPoints_->at(i), currentvi, nextvi, scrollPeriod_); + c->triggerMenuScrollEvent(); + } + + if(c) c->update(dt); + } if(scrollStopped || (notifyAllRequested_ && focus_)) { - ComponentItemBinding *sprite = getPendingCollectionItemSprite(); - Item *item = NULL; - - if(sprite) - { - item = sprite->item; - } + Item *item = getPendingItem(); for(std::vector::iterator it = notificationComponents_.begin(); it != notificationComponents_.end(); it++) { MenuNotifierInterface *c = *it; + if(c && item) { c->onNewItemSelected(item); @@ -689,47 +490,12 @@ void ScrollingList::update(float dt) notifyAllRequested_ = false; } -void ScrollingList::updateSprite(unsigned int spriteIndex, unsigned int pointIndex, bool newScroll, float dt, double nextScrollTime) -{ - ComponentItemBinding *s = spriteList_->at(spriteIndex); - - Component *c = s->component; - //todo: remove me - if(c && newScroll) - { - ViewInfo *currentViewInfo = scrollPoints_->at(pointIndex); - unsigned int nextI = getNextTween(pointIndex, scrollPoints_); - ViewInfo *nextViewInfo = scrollPoints_->at(nextI); - - resetTweens(c, tweenPoints_->at(pointIndex), currentViewInfo, nextViewInfo, nextScrollTime); - c->triggerMenuScrollEvent(); - } - if(c) - { - c->update(dt); - } - - circularIncrement(spriteIndex, spriteList_); -} - void ScrollingList::resetTweens(Component *c, AnimationEvents *sets, ViewInfo *currentViewInfo, ViewInfo *nextViewInfo, double scrollTime) { - if(!c) - { - return; - } - if(!sets) - { - return; - } - if(!currentViewInfo) - { - return; - } - if(!nextViewInfo) - { - return; - } + if(!c) return; + if(!sets) return; + if(!currentViewInfo) return; + if(!nextViewInfo) return; currentViewInfo->ImageHeight = c->baseViewInfo.ImageHeight; currentViewInfo->ImageWidth = c->baseViewInfo.ImageWidth; @@ -761,15 +527,11 @@ void ScrollingList::resetTweens(Component *c, AnimationEvents *sets, ViewInfo *c } -bool ScrollingList::allocateTexture(ComponentItemBinding *s) +bool ScrollingList::allocateTexture(unsigned int index, Item *item) { - if(!s || s->component != NULL) - { - return false; - } + if(index >= components_.size()) return false; - const Item *item = s->item; //todo: will create a runtime fault if not of the right type //todo: remove coupling from knowing the collection name @@ -834,20 +596,23 @@ bool ScrollingList::allocateTexture(ComponentItemBinding *s) if(t) { - s->component = t; + components_.at(index) = t; } return true; } -void ScrollingList::deallocateTexture(ComponentItemBinding *s) +void ScrollingList::deallocateTexture(unsigned int index) { - if(s && s->component != NULL) + if(components_.size() <= index) return; + + Component *s = components_.at(index); + + if(s) { - delete s->component; - //todo: memory leak here, need to destroy allocated tween points here and in page (cannot be destroyed by component) + delete s; + components_.at(index) = NULL; } - s->component = NULL; } void ScrollingList::draw() @@ -858,32 +623,11 @@ void ScrollingList::draw() void ScrollingList::draw(unsigned int layer) { - if(!scrollPoints_) + + for(unsigned int i = 0; i < components_.size(); ++i) { - return; - } - if(!spriteList_) - { - return; - } - if(spriteList_->size() == 0) - { - return; - } - - unsigned int spriteIndex = firstSpriteIndex_; - - for(unsigned int i = 0; i < scrollPoints_->size(); i++) - { - ComponentItemBinding *s = spriteList_->at(spriteIndex); - Component *c = s->component; - ViewInfo *currentViewInfo = scrollPoints_->at(i); - - if(c && currentViewInfo && currentViewInfo->Layer == layer) - { - c->draw(); - } - circularIncrement(spriteIndex, spriteList_); + Component *c = components_.at(i); + if(c) c->draw(); } } @@ -895,69 +639,6 @@ void ScrollingList::setScrollDirection(ScrollDirection direction) scrollStopRequested_ = (direction == ScrollDirectionIdle); } -void ScrollingList::removeSelectedItem() -{ - ComponentItemBinding *sprite = getSelectedCollectionItemSprite(); - if(sprite && spriteList_) - { - Item *item = sprite->item; - deallocateTexture(sprite); - int index = (firstSpriteIndex_ + selectedSpriteListIndex_) % spriteList_->size(); - - std::vector::iterator it = spriteList_->begin() + index; - - spriteList_->erase(it); - delete sprite; - - if(item) - { - delete item; - } - - if(selectedSpriteListIndex_ >= spriteList_->size()) - { - selectedSpriteListIndex_ = 0; - } - if(firstSpriteIndex_ >= spriteList_->size()) - { - firstSpriteIndex_ = 0; - } - } -} - - -std::vector *ScrollingList::getCollectionItemSprites() -{ - return spriteList_; -} - -ComponentItemBinding* ScrollingList::getSelectedCollectionItemSprite() -{ - ComponentItemBinding *item = NULL; - - if(spriteList_ && spriteList_->size() > 0) - { - int index = (firstSpriteIndex_ + selectedSpriteListIndex_) % spriteList_->size(); - - item = spriteList_->at(index); - } - - return item; -} - -ComponentItemBinding* ScrollingList::getPendingCollectionItemSprite() -{ - ComponentItemBinding *item = NULL; - unsigned int index = firstSpriteIndex_; - if(spriteList_ && spriteList_->size() > 0) - { - index = (index + selectedSpriteListIndex_) % spriteList_->size(); - - item = spriteList_->at(index); - } - - return item; -} void ScrollingList::addComponentForNotifications(MenuNotifierInterface *c) { @@ -978,29 +659,24 @@ void ScrollingList::removeComponentForNotifications(MenuNotifierInterface *c) } -ComponentItemBinding* ScrollingList::getPendingSelectedCollectionItemSprite() +Item* ScrollingList::getPendingItem() { - ComponentItemBinding *item = NULL; + Item *item = NULL; - if(spriteList_) + if(items_ && items_->size() > 0) { - unsigned int index = selectedSpriteListIndex_; + unsigned int index = itemIndex_; if(currentScrollDirection_ == ScrollDirectionBack) { - circularDecrement(index, spriteList_); + index = loopDecrement(index, 1, items_->size()); } if(currentScrollDirection_ == ScrollDirectionForward) { - circularIncrement(index, spriteList_); + index = loopIncrement(index, 1, items_->size()); } - if(spriteList_ && spriteList_->size() > 0) - { - index = (index + selectedSpriteListIndex_) % spriteList_->size(); - - item = spriteList_->at(index); - } + item = items_->at(index); } return item; @@ -1011,74 +687,4 @@ bool ScrollingList::isIdle() return (Component::isIdle() && currentScrollState_ == ScrollStateIdle); } -void ScrollingList::circularIncrement(unsigned int &index, std::vector* list) -{ - index++; - - if(index >= list->size()) - { - index = 0; - } -} - -void ScrollingList::circularDecrement(unsigned int &index, std::vector* list) -{ - if(index > 0) - { - index--; - } - else - { - if(list->size() > 0) - { - index = list->size() - 1; - } - else - { - index = 0; - } - } -} - -int ScrollingList::circularIncrement(unsigned int index, unsigned int offset, std::vector *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 *list) -{ - index++; - - if(index >= list->size()) - { - index = 0; - } -} - -void ScrollingList::circularDecrement(unsigned int &index, std::vector *list) -{ - if(index > 0) - { - index--; - } - else - { - if(list && list->size() > 0) - { - index = list->size() - 1; - } - else - { - index = 0; - } - } -} diff --git a/RetroFE/Source/Graphics/Component/ScrollingList.h b/RetroFE/Source/Graphics/Component/ScrollingList.h index 2a87fb9..d0f45f0 100644 --- a/RetroFE/Source/Graphics/Component/ScrollingList.h +++ b/RetroFE/Source/Graphics/Component/ScrollingList.h @@ -1,136 +1,134 @@ -/* 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 -#include "Component.h" -#include "../Animate/Tween.h" -#include "../ComponentItemBinding.h" -#include "../MenuNotifierInterface.h" -#include "../ViewInfo.h" -#include "../../Database/Configuration.h" -#include - - -//todo: This scrolling implementation needs to be overhauled -// It needs to have a common interface to support different menu types -// (It was originally sandbox code that creeped into here) - -class Configuration; -class Font; - -class ScrollingList : public Component -{ -public: - enum ScrollDirection - { - ScrollDirectionBack, - ScrollDirectionForward, - ScrollDirectionIdle, - - }; - - ScrollingList(Configuration &c, - float scaleX, - float scaleY, - Font *font, - std::string layoutKey, - std::string imageType); - - ScrollingList(const ScrollingList ©); - virtual ~ScrollingList(); - void triggerMenuEnterEvent(); - void triggerMenuExitEvent(); - - bool allocateTexture(ComponentItemBinding *s); - void deallocateTexture(ComponentItemBinding *s); - void setItems(std::vector *spriteList); - void destroyItems(); - void setPoints(std::vector *scrollPoints, std::vector *tweenPoints); - void setScrollDirection(ScrollDirection direction); - void pageUp(); - void pageDown(); - void letterUp(); - void letterDown(); - bool isIdle(); +/* 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 +#include "Component.h" +#include "../Animate/Tween.h" +#include "../MenuNotifierInterface.h" +#include "../ViewInfo.h" +#include "../../Database/Configuration.h" +#include + + +//todo: This scrolling implementation needs to be overhauled +// It needs to have a common interface to support different menu types +// (It was originally sandbox code that creeped into here) + +class Configuration; +class Font; + +class ScrollingList : public Component +{ +public: + enum ScrollDirection + { + ScrollDirectionBack, + ScrollDirectionForward, + ScrollDirectionIdle, + + }; + + ScrollingList(Configuration &c, + float scaleX, + float scaleY, + Font *font, + std::string layoutKey, + std::string imageType); + + ScrollingList(const ScrollingList ©); + virtual ~ScrollingList(); + void triggerMenuEnterEvent(); + void triggerMenuExitEvent(); + + bool allocateTexture(unsigned int index, Item *i); + void deallocateTexture(unsigned int index); + void setItems(CollectionInfo *info); + void destroyItems(); + void setPoints(std::vector *scrollPoints, std::vector *tweenPoints); + void setScrollDirection(ScrollDirection direction); + void pageUp(); + void pageDown(); + void letterUp(); + void letterDown(); + void letterChange(bool increment); + bool isIdle(); unsigned int getScrollOffsetIndex(); void setScrollOffsetIndex(unsigned int index); - void setSelectedIndex(int selectedIndex); - ComponentItemBinding *getSelectedCollectionItemSprite(); - ComponentItemBinding *getPendingCollectionItemSprite(); - ComponentItemBinding *getPendingSelectedCollectionItemSprite(); - void addComponentForNotifications(MenuNotifierInterface *c); - void removeComponentForNotifications(MenuNotifierInterface *c); - std::vector *getCollectionItemSprites(); - void removeSelectedItem(); - void freeGraphicsMemory(); - void update(float dt); - void draw(); - void draw(unsigned int layer); - void setScrollAcceleration(float value); - void setStartScrollTime(float value); - bool horizontalScroll; - -private: - 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 *list); - void resetTweens(Component *c, AnimationEvents *sets, ViewInfo *currentViewInfo, ViewInfo *nextViewInfo, double scrollTime); - - enum ScrollState - { - ScrollStateActive, - ScrollStatePageChange, - ScrollStateStopping, - ScrollStateIdle - }; - - std::vector *spriteList_; - std::vector *scrollPoints_; - std::vector *tweenPoints_; - std::vector notificationComponents_; - float tweenEnterTime_; - bool focus_; - - unsigned int firstSpriteIndex_; - unsigned int selectedSpriteListIndex_; - bool scrollStopRequested_; - bool notifyAllRequested_; - ScrollDirection currentScrollDirection_; - ScrollDirection requestedScrollDirection_; - ScrollState currentScrollState_; - float scrollAcceleration_; - float startScrollTime_; - float scrollPeriod_; - - int circularIncrement(unsigned int index, unsigned int offset, std::vector *list); - void circularIncrement(unsigned &index, std::vector *list); - void circularDecrement(unsigned &index, std::vector *list); - void circularIncrement(unsigned &index, std::vector *list); - void circularDecrement(unsigned &index, std::vector *list); - void updateOffset(float dt); - - std::string collection_; - Configuration &config_; - float scaleX_; - float scaleY_; - Font *fontInst_; - std::string layoutKey_; - std::string imageType_; -}; - + void setSelectedIndex(int selectedIndex); + Item *getPendingItem(); + void addComponentForNotifications(MenuNotifierInterface *c); + void removeComponentForNotifications(MenuNotifierInterface *c); + void freeGraphicsMemory(); + void update(float dt); + void draw(); + void draw(unsigned int layer); + void setScrollAcceleration(float value); + void setStartScrollTime(float value); + bool horizontalScroll; + + +private: + void click(double nextScrollTime); + void deallocateSpritePoints(); + void allocateSpritePoints(); + void resetTweens(Component *c, AnimationEvents *sets, ViewInfo *currentViewInfo, ViewInfo *nextViewInfo, double scrollTime); + unsigned int loopIncrement(unsigned int offset, unsigned int i, unsigned int size); + unsigned int loopDecrement(unsigned int offset, unsigned int i, unsigned int size); + + enum ScrollState + { + ScrollStateActive, + ScrollStatePageChange, + ScrollStateStopping, + ScrollStateIdle + }; + + std::vector *spriteList_; + std::vector *scrollPoints_; + std::vector *tweenPoints_; + std::vector notificationComponents_; + bool focus_; + + unsigned int itemIndex_; + unsigned int componentIndex_; + unsigned int selectedOffsetIndex_; + + bool scrollStopRequested_; + bool notifyAllRequested_; + + ScrollDirection currentScrollDirection_; + ScrollDirection requestedScrollDirection_; + ScrollState currentScrollState_; + + float scrollAcceleration_; + float startScrollTime_; + float scrollPeriod_; + + Configuration &config_; + float scaleX_; + float scaleY_; + Font *fontInst_; + std::string layoutKey_; + std::string imageType_; + CollectionInfo *collection_; + + + std::vector *items_; + std::vector components_; + +}; + diff --git a/RetroFE/Source/Graphics/Page.cpp b/RetroFE/Source/Graphics/Page.cpp index 7a4c3eb..d16b578 100644 --- a/RetroFE/Source/Graphics/Page.cpp +++ b/RetroFE/Source/Graphics/Page.cpp @@ -411,7 +411,6 @@ void Page::letterScroll(ScrollDirection direction) bool Page::pushCollection(CollectionInfo *collection) { collections_.push_back(collection); - std::vector *sprites = ComponentItemBindingBuilder::buildCollectionItems(&collection->items); int menuExitIndex = -1; int menuEnterIndex = -1; @@ -436,7 +435,7 @@ bool Page::pushCollection(CollectionInfo *collection) activeMenu_ = menus_[menuDepth_]; activeMenu_->collectionName = collection->name; activeMenu_->destroyItems(); - activeMenu_->setItems(sprites); + activeMenu_->setItems(collection); activeMenu_->triggerMenuEnterEvent(); playlist_ = collection->playlists.begin(); @@ -515,10 +514,6 @@ bool Page::popCollection() } } - if(collection) - { - delete collection; - } return true; } @@ -529,10 +524,8 @@ void Page::nextPlaylist() playlist_++; if(playlist_ == collection->playlists.end()) playlist_ = collection->playlists.begin(); - std::vector *sprites = ComponentItemBindingBuilder::buildCollectionItems(&playlist_->second); - activeMenu_->destroyItems(); - activeMenu_->setItems(sprites); + activeMenu_->setItems(collection); activeMenu_->triggerMenuEnterEvent(); } From b5e3384893c5312441d4d18ada18c240c22e5992 Mon Sep 17 00:00:00 2001 From: Don Honerbrink Date: Tue, 4 Aug 2015 15:23:54 -0500 Subject: [PATCH 3/7] Cleanup ScrollingList logic. --- .../Graphics/Component/ScrollingList.cpp | 49 ++++++++----------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/RetroFE/Source/Graphics/Component/ScrollingList.cpp b/RetroFE/Source/Graphics/Component/ScrollingList.cpp index c4e6a21..a4de020 100644 --- a/RetroFE/Source/Graphics/Component/ScrollingList.cpp +++ b/RetroFE/Source/Graphics/Component/ScrollingList.cpp @@ -91,7 +91,6 @@ ScrollingList::ScrollingList(const ScrollingList ©) , imageType_(copy.imageType_) , items_(NULL) { - scrollPoints_ = NULL; tweenPoints_ = NULL; @@ -125,7 +124,6 @@ ScrollingList::~ScrollingList() void ScrollingList::setItems(CollectionInfo *info) { - std::cout << "setItems" << std::endl; deallocateSpritePoints(); collection_ = info; @@ -149,8 +147,7 @@ unsigned int ScrollingList::loopIncrement(unsigned int offset, unsigned int i, u unsigned int ScrollingList::loopDecrement(unsigned int offset, unsigned int i, unsigned int size) { if(size == 0) return 0; - // (A - B) % C = ((A % C) - (B % C)) % C - return ((offset % size) - (i % size) ) % size; + return ((offset % size) - (i % size) + size) % size; } @@ -170,12 +167,15 @@ void ScrollingList::deallocateSpritePoints() { deallocateTexture(i); } + + componentIndex_ = 0; } void ScrollingList::allocateSpritePoints() { for(unsigned int i = 0; items_ && i < scrollPoints_->size(); ++i) { + componentIndex_ = 0; unsigned int index = loopIncrement(itemIndex_, i, items_->size()); Item *item = items_->at(index); @@ -232,35 +232,27 @@ void ScrollingList::setSelectedIndex(int selectedIndex) void ScrollingList::click(double nextScrollTime) { - ViewInfo *cur; - ViewInfo *next; if(currentScrollDirection_ == ScrollDirectionBack) { - next = scrollPoints_->at(componentIndex_); - itemIndex_ = loopIncrement(itemIndex_, 1, items_->size()); - componentIndex_ = loopIncrement(componentIndex_, 1, components_.size()); - cur = scrollPoints_->at(componentIndex_); + // get the previous item + itemIndex_ = loopDecrement(itemIndex_, 1, items_->size()); + Item *i = items_->at(itemIndex_); + + componentIndex_ = loopDecrement(componentIndex_, 1, components_.size()); + + deallocateTexture(componentIndex_); + allocateTexture(componentIndex_, i); } else if(currentScrollDirection_ == ScrollDirectionForward) { - next = scrollPoints_->at(componentIndex_); - itemIndex_ = loopDecrement(itemIndex_, 1, items_->size()); - componentIndex_ = loopDecrement(componentIndex_, 1, components_.size()); - cur = scrollPoints_->at(componentIndex_); + itemIndex_ = loopIncrement(itemIndex_, 1, items_->size()); + Item *i = items_->at(itemIndex_); + + deallocateTexture(componentIndex_); + allocateTexture(componentIndex_, i); + + componentIndex_ = loopIncrement(componentIndex_, 1, components_.size()); } - else - { - return; - } - - Item *i = items_->at(itemIndex_); - - deallocateTexture(componentIndex_); - allocateTexture(componentIndex_, i); - Component *c = components_.at(componentIndex_); - - resetTweens(c, tweenPoints_->at(componentIndex_), cur, next, 0); - } void ScrollingList::pageUp() @@ -416,7 +408,8 @@ void ScrollingList::update(float dt) for(unsigned int i = 0; i < tweenPoints_->size(); ++i) { - Component *c = components_.at(i); + unsigned int cindex = loopIncrement(componentIndex_, i, components_.size()); + Component *c = components_.at(cindex); if(c) c->setTweens(tweenPoints_->at(i)); } From 9330e85f31eeb0a172c94f7fcdcdad54909dbd11 Mon Sep 17 00:00:00 2001 From: Don Honerbrink Date: Tue, 4 Aug 2015 16:57:47 -0500 Subject: [PATCH 4/7] Checkpoint, forward scrolling broken --- .../Graphics/Component/ScrollingList.cpp | 37 +++++-------------- .../Source/Graphics/Component/ScrollingList.h | 1 - 2 files changed, 9 insertions(+), 29 deletions(-) diff --git a/RetroFE/Source/Graphics/Component/ScrollingList.cpp b/RetroFE/Source/Graphics/Component/ScrollingList.cpp index a4de020..7e44526 100644 --- a/RetroFE/Source/Graphics/Component/ScrollingList.cpp +++ b/RetroFE/Source/Graphics/Component/ScrollingList.cpp @@ -75,6 +75,8 @@ ScrollingList::ScrollingList(const ScrollingList ©) , horizontalScroll(copy.horizontalScroll) , spriteList_(NULL) , focus_(false) + , itemIndex_(0) + , componentIndex_(0) , scrollStopRequested_(true) , notifyAllRequested_(false) , currentScrollDirection_(ScrollDirectionIdle) @@ -237,7 +239,6 @@ void ScrollingList::click(double nextScrollTime) // get the previous item itemIndex_ = loopDecrement(itemIndex_, 1, items_->size()); Item *i = items_->at(itemIndex_); - componentIndex_ = loopDecrement(componentIndex_, 1, components_.size()); deallocateTexture(componentIndex_); @@ -248,6 +249,7 @@ void ScrollingList::click(double nextScrollTime) itemIndex_ = loopIncrement(itemIndex_, 1, items_->size()); Item *i = items_->at(itemIndex_); + deallocateTexture(componentIndex_); allocateTexture(componentIndex_, i); @@ -402,9 +404,9 @@ void ScrollingList::update(float dt) { if(currentScrollState_ == ScrollStateStopping) { - click(0); currentScrollState_ = ScrollStateIdle; scrollStopped = true; + click(0); for(unsigned int i = 0; i < tweenPoints_->size(); ++i) { @@ -433,11 +435,11 @@ void ScrollingList::update(float dt) for(unsigned int i = 0; i < scrollPoints_->size(); i++) { unsigned int cindex = loopIncrement(componentIndex_, i, components_.size()); + Component *c = components_.at(cindex); if(c && (scrollRequested || scrollChanged)) { - ViewInfo *currentvi = scrollPoints_->at(i); unsigned int nextI = 0; if(currentScrollDirection_ == ScrollDirectionBack) { @@ -448,6 +450,7 @@ void ScrollingList::update(float dt) nextI = loopDecrement(i, 1, scrollPoints_->size()); } + ViewInfo *currentvi = scrollPoints_->at(i); ViewInfo *nextvi = scrollPoints_->at(nextI); resetTweens(c, tweenPoints_->at(i), currentvi, nextvi, scrollPeriod_); @@ -460,7 +463,9 @@ void ScrollingList::update(float dt) if(scrollStopped || (notifyAllRequested_ && focus_)) { - Item *item = getPendingItem(); + Item *item = NULL; + unsigned index = loopIncrement(itemIndex_, selectedOffsetIndex_, items_->size()); + item = items_->at(index); for(std::vector::iterator it = notificationComponents_.begin(); it != notificationComponents_.end(); @@ -651,30 +656,6 @@ void ScrollingList::removeComponentForNotifications(MenuNotifierInterface *c) } } - -Item* ScrollingList::getPendingItem() -{ - Item *item = NULL; - - if(items_ && items_->size() > 0) - { - unsigned int index = itemIndex_; - - if(currentScrollDirection_ == ScrollDirectionBack) - { - index = loopDecrement(index, 1, items_->size()); - } - if(currentScrollDirection_ == ScrollDirectionForward) - { - index = loopIncrement(index, 1, items_->size()); - } - - item = items_->at(index); - } - - return item; -} - bool ScrollingList::isIdle() { return (Component::isIdle() && currentScrollState_ == ScrollStateIdle); diff --git a/RetroFE/Source/Graphics/Component/ScrollingList.h b/RetroFE/Source/Graphics/Component/ScrollingList.h index d0f45f0..2522aa8 100644 --- a/RetroFE/Source/Graphics/Component/ScrollingList.h +++ b/RetroFE/Source/Graphics/Component/ScrollingList.h @@ -69,7 +69,6 @@ public: unsigned int getScrollOffsetIndex(); void setScrollOffsetIndex(unsigned int index); void setSelectedIndex(int selectedIndex); - Item *getPendingItem(); void addComponentForNotifications(MenuNotifierInterface *c); void removeComponentForNotifications(MenuNotifierInterface *c); void freeGraphicsMemory(); From c20ac31fea22af9e9c762e08ea77b1fdf429b969 Mon Sep 17 00:00:00 2001 From: emb <> Date: Wed, 5 Aug 2015 10:44:27 -0500 Subject: [PATCH 5/7] Scrolling now works. ReloadableImages are not always updating properly from component states. --- RetroFE/Source/Graphics/Component/ScrollingList.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RetroFE/Source/Graphics/Component/ScrollingList.cpp b/RetroFE/Source/Graphics/Component/ScrollingList.cpp index 7e44526..99dbf3e 100644 --- a/RetroFE/Source/Graphics/Component/ScrollingList.cpp +++ b/RetroFE/Source/Graphics/Component/ScrollingList.cpp @@ -36,7 +36,7 @@ #include #include #include - +#include //todo: remove coupling from configuration data (if possible) ScrollingList::ScrollingList(Configuration &c, @@ -246,10 +246,10 @@ void ScrollingList::click(double nextScrollTime) } else if(currentScrollDirection_ == ScrollDirectionForward) { + unsigned int itemIncrement = loopIncrement(itemIndex_, scrollPoints_->size(), items_->size()); itemIndex_ = loopIncrement(itemIndex_, 1, items_->size()); - Item *i = items_->at(itemIndex_); + Item *i = items_->at(itemIncrement); - deallocateTexture(componentIndex_); allocateTexture(componentIndex_, i); From 3fc64ed01d07723b5f317078da1e23149de7333f Mon Sep 17 00:00:00 2001 From: Don Honerbrink Date: Thu, 6 Aug 2015 09:18:04 -0500 Subject: [PATCH 6/7] Set viewInfo when allocating tweens --- RetroFE/Source/Graphics/Component/ScrollingList.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/RetroFE/Source/Graphics/Component/ScrollingList.cpp b/RetroFE/Source/Graphics/Component/ScrollingList.cpp index 99dbf3e..b622429 100644 --- a/RetroFE/Source/Graphics/Component/ScrollingList.cpp +++ b/RetroFE/Source/Graphics/Component/ScrollingList.cpp @@ -243,6 +243,10 @@ void ScrollingList::click(double nextScrollTime) deallocateTexture(componentIndex_); allocateTexture(componentIndex_, i); + + Component *c = components_.at(componentIndex_); + ViewInfo *v = scrollPoints_->at(0); + resetTweens(c, tweenPoints_->at(componentIndex_), v, v, 0); } else if(currentScrollDirection_ == ScrollDirectionForward) { @@ -253,6 +257,10 @@ void ScrollingList::click(double nextScrollTime) deallocateTexture(componentIndex_); allocateTexture(componentIndex_, i); + Component *c = components_.at(componentIndex_); + ViewInfo *v = scrollPoints_->back(); + resetTweens(c, tweenPoints_->at(componentIndex_), v, v, 0); + componentIndex_ = loopIncrement(componentIndex_, 1, components_.size()); } } From 8fdc7ece6436ff8cdd5d47713c6e202d4c59d79c Mon Sep 17 00:00:00 2001 From: Don Honerbrink Date: Thu, 6 Aug 2015 13:17:40 -0500 Subject: [PATCH 7/7] Supporting favorites --- RetroFE/Source/Collection/CollectionInfo.cpp | 12 +++ RetroFE/Source/Collection/CollectionInfo.h | 2 +- .../Collection/CollectionInfoBuilder.cpp | 12 ++- RetroFE/Source/Collection/MenuParser.cpp | 3 - .../Graphics/Component/ScrollingList.cpp | 44 +++++---- .../Source/Graphics/Component/ScrollingList.h | 4 +- RetroFE/Source/Graphics/Page.cpp | 95 +++++++++++++------ RetroFE/Source/Graphics/Page.h | 17 +++- 8 files changed, 129 insertions(+), 60 deletions(-) diff --git a/RetroFE/Source/Collection/CollectionInfo.cpp b/RetroFE/Source/Collection/CollectionInfo.cpp index d74955b..85ac94c 100644 --- a/RetroFE/Source/Collection/CollectionInfo.cpp +++ b/RetroFE/Source/Collection/CollectionInfo.cpp @@ -51,6 +51,18 @@ CollectionInfo::~CollectionInfo() } + Playlists_T::iterator pit = playlists.begin(); + + while(pit != playlists.end()) + { + if(pit->second != &items) + { + delete pit->second; + } + playlists.erase(pit); + pit = playlists.begin(); + } + std::vector::iterator it = items.begin(); while(it != items.end()) { diff --git a/RetroFE/Source/Collection/CollectionInfo.h b/RetroFE/Source/Collection/CollectionInfo.h index d4086da..b6450ec 100644 --- a/RetroFE/Source/Collection/CollectionInfo.h +++ b/RetroFE/Source/Collection/CollectionInfo.h @@ -37,7 +37,7 @@ public: std::string launcher; std::vector items; - typedef std::map > Playlists_T; + typedef std::map *> Playlists_T; Playlists_T playlists; private: diff --git a/RetroFE/Source/Collection/CollectionInfoBuilder.cpp b/RetroFE/Source/Collection/CollectionInfoBuilder.cpp index 595b70c..475a18b 100644 --- a/RetroFE/Source/Collection/CollectionInfoBuilder.cpp +++ b/RetroFE/Source/Collection/CollectionInfoBuilder.cpp @@ -279,6 +279,8 @@ bool CollectionInfoBuilder::ImportDirectory(CollectionInfo *info, std::string me std::vector::iterator extensionsIt; info->extensionList(extensions); + info->playlists["all"] = &info->items; + info->playlists["favorites"] = new std::vector(); dp = opendir(path.c_str()); @@ -300,10 +302,11 @@ bool CollectionInfoBuilder::ImportDirectory(CollectionInfo *info, std::string me } } } - for(std::map::iterator it = favoritesFilter.begin(); it != favoritesFilter.end(); it++) - { - info->playlists["favorites"].push_back(it->second); - } + // add the favorites list + for(std::map::iterator it = favoritesFilter.begin(); it != favoritesFilter.end(); it++) + { + info->playlists["favorites"]->push_back(it->second); + } while((dirp = readdir(dp)) != NULL) { @@ -334,7 +337,6 @@ bool CollectionInfoBuilder::ImportDirectory(CollectionInfo *info, std::string me i->collectionInfo = info; info->items.push_back(i); - info->playlists["include"].push_back(i); } } } diff --git a/RetroFE/Source/Collection/MenuParser.cpp b/RetroFE/Source/Collection/MenuParser.cpp index 5e62290..766dc75 100644 --- a/RetroFE/Source/Collection/MenuParser.cpp +++ b/RetroFE/Source/Collection/MenuParser.cpp @@ -149,9 +149,6 @@ bool MenuParser::buildLegacyXmlMenu(CollectionInfo *collection, bool sort) } - std::sort( collection->items.begin(), collection->items.end(), VectorSort); - - // todo: sorting should occur within the collection itself, not externally if(sort) { // sort the menu if requested diff --git a/RetroFE/Source/Graphics/Component/ScrollingList.cpp b/RetroFE/Source/Graphics/Component/ScrollingList.cpp index b622429..d140618 100644 --- a/RetroFE/Source/Graphics/Component/ScrollingList.cpp +++ b/RetroFE/Source/Graphics/Component/ScrollingList.cpp @@ -124,15 +124,12 @@ ScrollingList::~ScrollingList() } -void ScrollingList::setItems(CollectionInfo *info) +void ScrollingList::setItems(std::vector *items) { deallocateSpritePoints(); - collection_ = info; - items_ = &collection_->items; - + items_ = items; itemIndex_ = 0; - componentIndex_ = 0; allocateSpritePoints(); @@ -175,7 +172,10 @@ void ScrollingList::deallocateSpritePoints() void ScrollingList::allocateSpritePoints() { - for(unsigned int i = 0; items_ && i < scrollPoints_->size(); ++i) + if(!items_ || items_->size() == 0) return; + if(!scrollPoints_) return; + + for(unsigned int i = 0; i < scrollPoints_->size(); ++i) { componentIndex_ = 0; unsigned int index = loopIncrement(itemIndex_, i, items_->size()); @@ -210,10 +210,11 @@ void ScrollingList::setPoints(std::vector *scrollPoints, std::vector // empty out the list as we will resize it components_.clear(); - if(scrollPoints && scrollPoints_->size() > components_.size()) - { - components_.resize(scrollPoints_->size(), NULL); - } + int size = 0; + + if(scrollPoints) size = scrollPoints_->size(); + components_.resize(size); + allocateSpritePoints(); } @@ -378,12 +379,13 @@ void ScrollingList::update(float dt) bool scrollRequested = false; bool scrollStopped = false; - // validate all scroll points are done tweening to the next position - for(unsigned int i = 0; i < components_.size(); i++) - { - Component *c = components_.at(i); + if(components_.size() == 0) return; + if(!items_ || items_->size() == 0) return; - if(c && c->isMenuScrolling()) + // validate all scroll points are done tweening to the next position + for(std::vector::iterator c = components_.begin(); c != components_.end(); c++) + { + if(*c && (*c)->isMenuScrolling()) { readyToScroll = false; break; @@ -630,6 +632,8 @@ void ScrollingList::draw() void ScrollingList::draw(unsigned int layer) { + if(components_.size() == 0) return; + for(unsigned int i = 0; i < components_.size(); ++i) { Component *c = components_.at(i); @@ -666,7 +670,15 @@ void ScrollingList::removeComponentForNotifications(MenuNotifierInterface *c) bool ScrollingList::isIdle() { - return (Component::isIdle() && currentScrollState_ == ScrollStateIdle); + if(!Component::isIdle() || currentScrollState_ != ScrollStateIdle) return false; + + for(unsigned int i = 0; i < components_.size(); ++i) + { + Component *c = components_.at(i); + if(c && !c->isIdle()) return false; + } + + return true; } diff --git a/RetroFE/Source/Graphics/Component/ScrollingList.h b/RetroFE/Source/Graphics/Component/ScrollingList.h index 2522aa8..9680317 100644 --- a/RetroFE/Source/Graphics/Component/ScrollingList.h +++ b/RetroFE/Source/Graphics/Component/ScrollingList.h @@ -56,7 +56,7 @@ public: bool allocateTexture(unsigned int index, Item *i); void deallocateTexture(unsigned int index); - void setItems(CollectionInfo *info); + void setItems(std::vector *items); void destroyItems(); void setPoints(std::vector *scrollPoints, std::vector *tweenPoints); void setScrollDirection(ScrollDirection direction); @@ -123,11 +123,11 @@ private: Font *fontInst_; std::string layoutKey_; std::string imageType_; - CollectionInfo *collection_; std::vector *items_; std::vector components_; + }; diff --git a/RetroFE/Source/Graphics/Page.cpp b/RetroFE/Source/Graphics/Page.cpp index d16b578..9054507 100644 --- a/RetroFE/Source/Graphics/Page.cpp +++ b/RetroFE/Source/Graphics/Page.cpp @@ -23,13 +23,13 @@ #include "Component/ScrollingList.h" #include "../Sound/Sound.h" #include "ComponentItemBindingBuilder.h" +#include #include Page::Page(Configuration &config) : config_(config) , activeMenu_(NULL) , menuDepth_(0) - , items_(NULL) , scrollActive_(false) , selectedItem_(NULL) , textStatusComponent_(NULL) @@ -410,7 +410,6 @@ void Page::letterScroll(ScrollDirection direction) bool Page::pushCollection(CollectionInfo *collection) { - collections_.push_back(collection); int menuExitIndex = -1; int menuEnterIndex = -1; @@ -425,6 +424,7 @@ bool Page::pushCollection(CollectionInfo *collection) menuExitIndex = menuDepth_ - 1; } + // grow the menu as needed if(menus_.size() >= menuDepth_ && activeMenu_) { ScrollingList *newList = new ScrollingList(*activeMenu_); @@ -432,12 +432,21 @@ bool Page::pushCollection(CollectionInfo *collection) pushMenu(newList); } + activeMenu_ = menus_[menuDepth_]; activeMenu_->collectionName = collection->name; - activeMenu_->destroyItems(); - activeMenu_->setItems(collection); + activeMenu_->setItems(&collection->items); activeMenu_->triggerMenuEnterEvent(); - playlist_ = collection->playlists.begin(); + + // build the collection info instance + MenuInfo_S info; + info.collection = collection; + info.menu = activeMenu_; + info.playlist = collection->playlists.begin(); + info.queueDelete = false; + collections_.push_back(info); + + playlist_ = info.playlist; if(menuDepth_ < menus_.size()) { @@ -469,18 +478,19 @@ bool Page::popCollection() { int menuExitIndex = -1; int menuEnterIndex = -1; - CollectionInfo *collection = NULL; - if(menuDepth_ <= 1) - { - return false; - } - if(collections_.size() <= 1) - { - return false; - } + if(!activeMenu_) return false; + if(menuDepth_ <= 1) return false; + if(collections_.size() <= 1) return false; + + // queue the collection for deletion + MenuInfo_S &info = collections_.back(); + info.queueDelete = true; + + // get the next collection off of the stack collections_.pop_back(); - collection = collections_.back(); + info = collections_.back(); + playlist_ = info.playlist; if(activeMenu_) { @@ -500,7 +510,7 @@ bool Page::popCollection() { for(std::vector::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it) { - (*it)->collectionName = collection->name; + (*it)->collectionName = info.collection->name; if(menuEnterIndex >= 0) { @@ -514,18 +524,25 @@ bool Page::popCollection() } } - return true; } void Page::nextPlaylist() { - CollectionInfo *collection = collections_.back(); - playlist_++; - if(playlist_ == collection->playlists.end()) playlist_ = collection->playlists.begin(); + MenuInfo_S &info = collections_.back(); + unsigned int numlists = info.collection->playlists.size(); - activeMenu_->destroyItems(); - activeMenu_->setItems(collection); + for(unsigned int i = 0; i <= numlists; ++i) + { + playlist_++; + // wrap + if(playlist_ == info.collection->playlists.end()) playlist_ = info.collection->playlists.begin(); + + // find the first playlist + if(playlist_->second->size() != 0) break; + } + + activeMenu_->setItems(playlist_->second); activeMenu_->triggerMenuEnterEvent(); } @@ -555,7 +572,28 @@ void Page::update(float dt) { for(std::vector::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it) { - (*it)->update(dt); + if(*it) (*it)->update(dt); + } + } + + // many nodes still have handles on the collection info. We need to delete + // them once everything is done using them + std::list::iterator del = collections_.begin(); + + while(del != collections_.end()) + { + MenuInfo_S &info = *del; + if(info.queueDelete && info.menu && info.menu->isIdle()) + { + std::list::iterator next = del; + ++next; + + if(info.collection) delete info.collection; + collections_.erase(del); + } + else + { + ++del; } } } @@ -566,7 +604,7 @@ void Page::draw() { for(std::vector::iterator it = LayerComponents[i].begin(); it != LayerComponents[i].end(); ++it) { - (*it)->draw(); + if(*it) (*it)->draw(); } for(MenuVector_T::iterator it = menus_.begin(); it != menus_.end(); it++) @@ -580,14 +618,11 @@ void Page::draw() std::string Page::getCollectionName() { - CollectionInfo *info = collections_.back(); + if(collections_.size() == 0) return ""; - if(info) - { - return info->name; - } + MenuInfo_S &info = collections_.back(); + return info.collection->name; - return ""; } void Page::freeGraphicsMemory() diff --git a/RetroFE/Source/Graphics/Page.h b/RetroFE/Source/Graphics/Page.h index 2591d5e..cbf6406 100644 --- a/RetroFE/Source/Graphics/Page.h +++ b/RetroFE/Source/Graphics/Page.h @@ -84,17 +84,28 @@ private: void highlight(); std::string collectionName_; Configuration &config_; + + struct MenuInfo_S + { + CollectionInfo *collection; + ScrollingList *menu; + CollectionInfo::Playlists_T::iterator playlist; + bool queueDelete; + }; + typedef std::vector MenuVector_T; - typedef std::vector CollectionInfo_T; + typedef std::list CollectionVector_T; ScrollingList *activeMenu_; unsigned int menuDepth_; MenuVector_T menus_; - CollectionInfo_T collections_; + CollectionVector_T collections_; static const unsigned int NUM_LAYERS = 8; std::vector LayerComponents[NUM_LAYERS]; - std::vector *items_; + std::list deleteMenuList_; + std::list deleteCollectionList_; + bool scrollActive_; Item *selectedItem_;