From 09790bb08c8d6c3d00b4db7f00b5c3a857d0a8e0 Mon Sep 17 00:00:00 2001 From: emb <> Date: Fri, 30 Jan 2015 12:53:50 -0600 Subject: [PATCH] Cleaned up ScrollingList. Support for multiple menus. --- RetroFE/Source/Graphics/Animate/TweenSet.h | 13 +- .../Source/Graphics/Component/Component.cpp | 48 +- RetroFE/Source/Graphics/Component/Component.h | 5 +- .../Graphics/Component/ScrollingList.cpp | 656 ++++++++++-------- .../Source/Graphics/Component/ScrollingList.h | 18 +- .../Source/Graphics/ComponentItemBinding.h | 17 +- RetroFE/Source/Graphics/Page.cpp | 12 +- RetroFE/Source/Graphics/Page.h | 2 + RetroFE/Source/RetroFE.cpp | 1 - 9 files changed, 426 insertions(+), 346 deletions(-) diff --git a/RetroFE/Source/Graphics/Animate/TweenSet.h b/RetroFE/Source/Graphics/Animate/TweenSet.h index 8375bf9..35a5dfd 100644 --- a/RetroFE/Source/Graphics/Animate/TweenSet.h +++ b/RetroFE/Source/Graphics/Animate/TweenSet.h @@ -48,14 +48,18 @@ public: { return &OnHighlightExitTweens; } - TweenSets *GetOnMenuExitTweens() - { - return &OnMenuExitTweens; - } TweenSets *GetOnMenuEnterTweens() { return &OnMenuEnterTweens; } + TweenSets *GetOnMenuScrollTweens() + { + return &OnMenuScrollTweens; + } + TweenSets *GetOnMenuExitTweens() + { + return &OnMenuExitTweens; + } private: TweenSets OnEnterTweens; @@ -64,6 +68,7 @@ private: TweenSets OnHighlightEnterTweens; TweenSets OnHighlightExitTweens; TweenSets OnMenuEnterTweens; + TweenSets OnMenuScrollTweens; 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 6b69147..bc3d538 100644 --- a/RetroFE/Source/Graphics/Component/Component.cpp +++ b/RetroFE/Source/Graphics/Component/Component.cpp @@ -40,6 +40,7 @@ void Component::FreeGraphicsMemory() EnterRequested = false; ExitRequested = false; MenuEnterRequested = false; + MenuScrollRequested = false; MenuExitRequested = false; NewItemSelected = false; @@ -91,14 +92,15 @@ void Component::TriggerExitEvent() 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::TriggerMenuScrollEvent() +{ + MenuScrollRequested = true; +} + + void Component::TriggerMenuExitEvent() { MenuExitRequested = true; @@ -124,9 +126,9 @@ bool Component::IsWaiting() return (CurrentAnimationState == HIGHLIGHT_WAIT); } -bool Component::IsMenuAnimating() +bool Component::IsMenuScrolling() { - return (CurrentAnimationState == MENU_ENTER || CurrentAnimationState == MENU_EXIT); + return (CurrentAnimationState == MENU_ENTER || CurrentAnimationState == MENU_SCROLL || CurrentAnimationState == MENU_EXIT || MenuScrollRequested); } @@ -158,15 +160,19 @@ void Component::Update(float dt) switch(CurrentAnimationState) { case MENU_ENTER: - Logger::Write(Logger::ZONE_DEBUG, "Page", "MENU EXIT!"); + CurrentTweens = NULL; + CurrentAnimationState = IDLE; + break; + + case MENU_SCROLL: CurrentTweens = NULL; CurrentAnimationState = IDLE; break; case MENU_EXIT: - Logger::Write(Logger::ZONE_DEBUG, "Page", "MENU EXIT!"); CurrentTweens = NULL; CurrentAnimationState = IDLE; + Logger::Write(Logger::ZONE_ERROR, "Component", "completed menu exit tween (hidden)"); break; @@ -176,7 +182,6 @@ void Component::Update(float dt) break; case EXIT: - Logger::Write(Logger::ZONE_DEBUG, "Page", "COMPONENT EXIT!"); CurrentTweens = NULL; CurrentAnimationState = HIDDEN; break; @@ -190,27 +195,26 @@ void Component::Update(float dt) // prevent us from automatically jumping to the exit tween upon enter if(EnterRequested) { - 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(MenuScrollRequested) + { + MenuScrollRequested = false; + CurrentTweens = Tweens->GetOnMenuScrollTweens(); + CurrentAnimationState = MENU_SCROLL; } 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) { @@ -270,20 +274,22 @@ void Component::Update(float dt) 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 if(MenuScrollRequested) + { + MenuScrollRequested = false; + CurrentTweens = Tweens->GetOnMenuScrollTweens(); + CurrentAnimationState = MENU_SCROLL; + } else { CurrentTweens = NULL; diff --git a/RetroFE/Source/Graphics/Component/Component.h b/RetroFE/Source/Graphics/Component/Component.h index 66d8426..25555b0 100644 --- a/RetroFE/Source/Graphics/Component/Component.h +++ b/RetroFE/Source/Graphics/Component/Component.h @@ -37,11 +37,12 @@ public: void TriggerExitEvent(); void TriggerMenuEnterEvent(); void TriggerMenuExitEvent(); + void TriggerMenuScrollEvent(); void TriggerHighlightEvent(Item *selectedItem); bool IsIdle(); bool IsHidden(); bool IsWaiting(); - bool IsMenuAnimating(); + bool IsMenuScrolling(); std::string GetCollectionName(); void SetCollectionName(std::string collectionName); typedef std::vector *> TweenSets; @@ -97,6 +98,7 @@ protected: HIGHLIGHT_ENTER, EXIT, MENU_ENTER, + MENU_SCROLL, MENU_EXIT, HIDDEN }; @@ -105,6 +107,7 @@ protected: bool EnterRequested; bool ExitRequested; bool MenuEnterRequested; + bool MenuScrollRequested; bool MenuExitRequested; bool NewItemSelected; bool HighlightExitComplete; diff --git a/RetroFE/Source/Graphics/Component/ScrollingList.cpp b/RetroFE/Source/Graphics/Component/ScrollingList.cpp index 7d47ce9..154e888 100644 --- a/RetroFE/Source/Graphics/Component/ScrollingList.cpp +++ b/RetroFE/Source/Graphics/Component/ScrollingList.cpp @@ -42,21 +42,17 @@ ScrollingList::ScrollingList(Configuration &c, SDL_Color fontColor, std::string layoutKey, std::string imageType) - : IsScrollChangedStarted(true) - , IsScrollChangedSignalled(false) - , IsScrollChangedComplete(false) - , SpriteList(NULL) + : SpriteList(NULL) , ScrollPoints(NULL) , TweenEnterTime(0) , FirstSpriteIndex(0) , SelectedSpriteListIndex(0) - , CurrentAnimateTime(0) // in seconds - , ScrollTime(0) // in seconds + , ScrollStopRequested(true) , CurrentScrollDirection(ScrollDirectionIdle) , RequestedScrollDirection(ScrollDirectionIdle) , CurrentScrollState(ScrollStateIdle) , ScrollAcceleration(6) // todo: make configurable - , ScrollVelocity(0) + , ScrollPeriod(0) , Config(c) , ScaleX(scaleX) , ScaleY(scaleY) @@ -71,6 +67,72 @@ ScrollingList::ScrollingList(Configuration &c, ScrollingList::~ScrollingList() { + DestroyItems(); +} + +void ScrollingList::SetItems(std::vector *spriteList) +{ + SpriteList = spriteList; + FirstSpriteIndex = 0; + + + if(!SpriteList) { return ; } + unsigned int originalSize = SpriteList->size(); + + // loop the scroll points if there are not enough, the +2 represents the head and tail nodes (for when the item is allocated) + while(ScrollPoints && ScrollPoints->size()+2 > SpriteList->size() && SpriteList->size() > 0) + { + for(unsigned int i = 0; i < originalSize; ++i) + { + Item *newItem = new Item(); + Item *originalItem = SpriteList->at(i)->GetCollectionItem(); + + *newItem = *originalItem; + ComponentItemBinding *newSprite = new ComponentItemBinding(newItem); + SpriteList->push_back(newSprite); + } + } + + for(unsigned int i = 0; ScrollPoints && i < SelectedSpriteListIndex; ++i) + { + CircularDecrement(FirstSpriteIndex, SpriteList); + } + + AllocateSpritePoints(); +} + +void ScrollingList::DeallocateSpritePoints() +{ + unsigned int spriteIndex = FirstSpriteIndex; + + for(unsigned int i = 0; i < ScrollPoints->size(); ++i) + { + DeallocateTexture(SpriteList->at(spriteIndex)); + CircularIncrement(spriteIndex, SpriteList); + } +} + +void ScrollingList::AllocateSpritePoints() +{ + unsigned int spriteIndex = FirstSpriteIndex; + + for(unsigned int i = 0; i < ScrollPoints->size(); ++i) + { + + AllocateTexture(SpriteList->at(spriteIndex)); + Component *c = SpriteList->at(spriteIndex)->GetComponent(); + ViewInfo *currentViewInfo = ScrollPoints->at(i); + unsigned int nextI = GetNextTween(i, ScrollPoints); + ViewInfo *nextViewInfo = ScrollPoints->at(nextI); + + ResetTweens(c, TweenPoints->at(i), currentViewInfo, nextViewInfo, 0); + + CircularIncrement(spriteIndex, SpriteList); + } +} + +void ScrollingList::DestroyItems() +{ if(SpriteList) { std::vector::iterator it = SpriteList->begin(); @@ -89,6 +151,7 @@ ScrollingList::~ScrollingList() delete *it; } + SpriteList->erase(it); it = SpriteList->begin(); @@ -97,39 +160,8 @@ ScrollingList::~ScrollingList() delete SpriteList; SpriteList = NULL; } -} +} -void ScrollingList::SetItems(std::vector *spriteList) -{ - SpriteList = spriteList; - FirstSpriteIndex = 0; - - // loop the scroll points if there are not enough - - if(SpriteList) - { - unsigned int originalSize = SpriteList->size(); - - while(ScrollPoints && ScrollPoints->size()+4 > SpriteList->size() && SpriteList->size() > 0) - { - for(unsigned int i = 0; i < originalSize; ++i) - { - Item *newItem = new Item(); - Item *originalItem = SpriteList->at(i)->GetCollectionItem(); - - *newItem = *originalItem; - ComponentItemBinding *newSprite = new ComponentItemBinding(newItem); - SpriteList->push_back(newSprite); - } - } - for(unsigned int i = 0; ScrollPoints && i < SelectedSpriteListIndex; ++i) - { - CircularDecrement(FirstSpriteIndex, SpriteList); - } - - IsScrollChangedComplete = true; - } -} void ScrollingList::SetPoints(std::vector *scrollPoints, std::vector *tweenPoints) { @@ -152,24 +184,47 @@ void ScrollingList::SetSelectedIndex(int selectedIndex) { CircularDecrement(FirstSpriteIndex, SpriteList); } - } -void ScrollingList::Click() +void ScrollingList::Click(double nextScrollTime) { - if(SpriteList) + if(!SpriteList) { return; } + if(SpriteList->size() == 0) { return; } + + unsigned int listSize = ScrollPoints->size(); + unsigned int end = CircularIncrement(FirstSpriteIndex, listSize - 1, SpriteList); + unsigned int allocSpriteIndex = 0; + unsigned int deallocSpriteIndex = 0; + unsigned int allocPoint = 0; + + if(CurrentScrollDirection == ScrollDirectionBack) { - if(CurrentScrollDirection == ScrollDirectionBack) - { - CircularDecrement(FirstSpriteIndex, SpriteList); - IsScrollChangedComplete = true; - } - if(CurrentScrollDirection == ScrollDirectionForward) - { - CircularIncrement(FirstSpriteIndex, SpriteList); - IsScrollChangedComplete = true; - } + deallocSpriteIndex = end; + CircularDecrement(FirstSpriteIndex, SpriteList); + allocSpriteIndex = FirstSpriteIndex; + allocPoint = 0; } + else if(CurrentScrollDirection == ScrollDirectionForward) + { + deallocSpriteIndex = FirstSpriteIndex; + CircularIncrement(FirstSpriteIndex, SpriteList); + allocSpriteIndex = CircularIncrement(FirstSpriteIndex, listSize - 1, SpriteList); + allocPoint = listSize - 1; + } + else + { + return; + } + + DeallocateTexture(SpriteList->at(deallocSpriteIndex)); + AllocateTexture(SpriteList->at(allocSpriteIndex)); + + Component *c = SpriteList->at(allocSpriteIndex)->GetComponent(); + ViewInfo *currentViewInfo = ScrollPoints->at(allocPoint); + unsigned int nextI = GetNextTween(allocPoint, ScrollPoints); + ViewInfo *nextViewInfo = ScrollPoints->at(nextI); + + ResetTweens(c, TweenPoints->at(allocPoint), currentViewInfo, nextViewInfo, nextScrollTime); } unsigned int ScrollingList::GetNextTween(unsigned int currentIndex, std::vector *list) @@ -188,10 +243,12 @@ unsigned int ScrollingList::GetNextTween(unsigned int currentIndex, std::vector< void ScrollingList::PageUp() { - if(SpriteList && ScrollPoints && ScrollPoints->size() > 4) + DeallocateSpritePoints(); + + if(SpriteList && ScrollPoints && ScrollPoints->size() > 2) { - ScrollVelocity = 0; - unsigned int counts = ScrollPoints->size() - 4; + ScrollPeriod = 0; + unsigned int counts = ScrollPoints->size() - 2; for(unsigned int i = 0; i < counts; i++) { @@ -199,42 +256,40 @@ void ScrollingList::PageUp() } } - CurrentScrollState = ScrollStatePageChange; - IsScrollChangedStarted = true; - IsScrollChangedSignalled = false; - IsScrollChangedComplete = false; + AllocateSpritePoints(); + +// CurrentScrollState = ScrollStatePageChange; } void ScrollingList::PageDown() { - if(SpriteList && ScrollPoints && ScrollPoints->size() > 4) - { - unsigned int counts = ScrollPoints->size() - 4; + DeallocateSpritePoints(); - ScrollVelocity = 0; + 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); } } - CurrentScrollState = ScrollStatePageChange; - IsScrollChangedStarted = true; - IsScrollChangedSignalled = false; - IsScrollChangedComplete = false; + AllocateSpritePoints(); +//todo: may want to handle this properly +// CurrentScrollState = ScrollStatePageChange; } void ScrollingList::FreeGraphicsMemory() { Component::FreeGraphicsMemory(); TweenEnterTime = 0; - CurrentAnimateTime = 0; - ScrollTime = 0; CurrentScrollDirection = ScrollDirectionIdle; RequestedScrollDirection = ScrollDirectionIdle; CurrentScrollState = ScrollStateIdle; ScrollAcceleration = 6; // todo: make configurable - ScrollVelocity = 0; + ScrollPeriod = 0; for(unsigned int i = 0; SpriteList && i < SpriteList->size(); i++) { @@ -248,206 +303,147 @@ 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(); - } - } - } + if(!ScrollPoints) { return; } + if(!SpriteList) { return; } + if(SpriteList->size() == 0 ) { return; } + if(FirstSpriteIndex >= SpriteList->size()) { return; } + unsigned int spriteIndex = FirstSpriteIndex; + + for(unsigned int i = 0; i < ScrollPoints->size(); ++i) + { + ComponentItemBinding *s = SpriteList->at(spriteIndex); + + Component *c = s->GetComponent(); + if(c) + { + c->TriggerMenuEnterEvent(); + } + + CircularIncrement(spriteIndex, SpriteList); + } } void ScrollingList::TriggerMenuExitEvent() { Focus = false; - if(ScrollPoints && SpriteList && SpriteList->size() > 0 && FirstSpriteIndex < SpriteList->size()) + if(!ScrollPoints) { return; } + if(!SpriteList) { return; } + if(SpriteList->size() == 0 ) { return; } + if(FirstSpriteIndex >= SpriteList->size()) { return; } + + unsigned int spriteIndex = FirstSpriteIndex; + + for(unsigned int i = 0; i < ScrollPoints->size(); ++i) { - unsigned int spriteIndex = FirstSpriteIndex; - unsigned int numIterations = (ScrollPoints->size() > SpriteList->size()) ? SpriteList->size() : ScrollPoints->size(); - unsigned int start = (ScrollPoints->size() > SpriteList->size()) ? SelectedSpriteListIndex : 0; + ComponentItemBinding *s = SpriteList->at(spriteIndex); - for(unsigned int i = start; i < start+numIterations && spriteIndex < SpriteList->size(); i++) + Component *c = s->GetComponent(); + if(c) { - ComponentItemBinding *s = SpriteList->at(spriteIndex); - - Component *c = s->GetComponent(); - if(c) - { - c->SetTweens(TweenPoints->at(i)); - c->TriggerMenuExitEvent(); - } + c->TriggerMenuExitEvent(); } + + CircularIncrement(spriteIndex, SpriteList); } - } - void ScrollingList::Update(float dt) { float scrollPeriod = 0; + bool initializePoints = false; Component::Update(dt); - if(!ScrollPoints) + if(!ScrollPoints) { return; } + if(!SpriteList) { return; } + if(SpriteList->size() == 0) { return; } + + bool readyToScroll = true; + bool scrollChanged = false; + bool scrollRequested = false; + bool scrollStopped = false; + + // validate all scroll points are done tweening to the next position + for(unsigned int i = 0; i < SpriteList->size(); i++) { - return; + ComponentItemBinding *s = SpriteList->at(i); + Component *c = s->GetComponent(); + + if(c && c->IsMenuScrolling()) + { + readyToScroll = false; + break; + } } - switch(CurrentScrollState) + // check if it was requested to change directions + if(CurrentScrollState == ScrollStateActive && RequestedScrollDirection != CurrentScrollDirection) { - case ScrollStateActive: - if(RequestedScrollDirection != CurrentScrollDirection) - { - CurrentScrollState = ScrollStateStopping; - - } - - break; - - case ScrollStateIdle: - ScrollTime = 0; - CurrentAnimateTime = 0; - ScrollVelocity = 0; - + CurrentScrollState = ScrollStateStopping; + } + else if(CurrentScrollState == ScrollStateIdle && readyToScroll) + { + ScrollPeriod = 0.500; + // check to see if requested to scroll if(RequestedScrollDirection != ScrollDirectionIdle) { + initializePoints = true; CurrentScrollState = ScrollStateActive; CurrentScrollDirection = RequestedScrollDirection; + scrollRequested = true; } - break; - default: - break; + } - }; - - if(CurrentScrollState != ScrollStatePageChange && CurrentScrollState != ScrollStateIdle) + // if currently scrolling, process it + if(!scrollRequested && readyToScroll) { - IsScrollChangedStarted = true; - ScrollTime += dt; - CurrentAnimateTime += dt; - ScrollVelocity = ScrollTime * ScrollAcceleration; - - // clip at 5 items scrolled per second - if(ScrollVelocity > 30) + if(CurrentScrollState == ScrollStateStopping) { - ScrollVelocity = 30; - } - if(ScrollVelocity > 0) - { - scrollPeriod = 1 / ScrollVelocity; - } - - // have we exceeded the time of when to stop on the next item in the list? - if(CurrentScrollState == ScrollStateStopping && CurrentAnimateTime >= scrollPeriod) - { - Click(); - CurrentAnimateTime = 0; - ScrollVelocity = 0; + Click(0); CurrentScrollState = ScrollStateIdle; - } - } + scrollStopped = true; + + // update the tweens now that we are done + unsigned int spriteIndex = FirstSpriteIndex; - while(CurrentScrollState != ScrollStatePageChange && ScrollVelocity > 0 && CurrentAnimateTime >= scrollPeriod) - { - Click(); - CurrentAnimateTime -= scrollPeriod; - } - - - 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); - - AllocateTexture(s); - - Component *c = s->GetComponent(); - if(c) + for(unsigned int i = 0; i < TweenPoints->size(); ++i) { - if(Focus) + ComponentItemBinding *s = SpriteList->at(spriteIndex); + + Component *c = s->GetComponent(); + if(c) { - 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); + c->SetTweens(TweenPoints->at(i)); } - - c->Update(dt); - - } - - CircularIncrement(spriteIndex, SpriteList); - } - - // start freeing up memory if the list is too large - if(SpriteList->size() + 4 > ScrollPoints->size()) - { - spriteIndex = FirstSpriteIndex; - - CircularDecrement(spriteIndex, SpriteList); - DeallocateTexture(SpriteList->at(spriteIndex)); - - CircularDecrement(spriteIndex, SpriteList); - DeallocateTexture(SpriteList->at(spriteIndex)); - - - // point to the end of the list to start deallocating.. - // It's not fast, but it's easy to read - spriteIndex = FirstSpriteIndex; - for(unsigned int i = 0; i < ScrollPoints->size(); i++) - { CircularIncrement(spriteIndex, SpriteList); } - CircularIncrement(spriteIndex, SpriteList); - DeallocateTexture(SpriteList->at(spriteIndex)); + } - CircularIncrement(spriteIndex, SpriteList); - DeallocateTexture(SpriteList->at(spriteIndex)); + else if(CurrentScrollState == ScrollStateActive) + { + ScrollPeriod -= 0.050f; + if(ScrollPeriod < 0.050) + { + ScrollPeriod = 0.050f; + } + + Click(ScrollPeriod); + scrollChanged = true; } } - if(IsScrollChangedStarted && !IsScrollChangedSignalled) + + unsigned int spriteIndex = FirstSpriteIndex; + for(unsigned int i = 0; i < ScrollPoints->size(); i++) + { + UpdateSprite(spriteIndex, i, (scrollRequested || scrollChanged), dt, ScrollPeriod); + CircularIncrement(spriteIndex, SpriteList); + } + + if(scrollStopped || scrollChanged) { - IsScrollChangedSignalled = true; ComponentItemBinding *sprite = GetPendingCollectionItemSprite(); Item *item = NULL; @@ -469,65 +465,122 @@ void ScrollingList::Update(float dt) if(CurrentScrollState == ScrollStatePageChange) { - IsScrollChangedComplete = true; CurrentScrollState = ScrollStateIdle; } } - - if(IsScrollChangedStarted && IsScrollChangedSignalled && IsScrollChangedComplete) - { - IsScrollChangedStarted = false; - IsScrollChangedComplete = false; - IsScrollChangedSignalled = false; - } - } -void ScrollingList::AllocateTexture(ComponentItemBinding *s) +void ScrollingList::UpdateSprite(unsigned int spriteIndex, unsigned int pointIndex, bool newScroll, float dt, double nextScrollTime) { - //todo: move this outside of the Draw routine - if(s && s->GetComponent() == NULL) + ComponentItemBinding *s = SpriteList->at(spriteIndex); + + Component *c = s->GetComponent(); + //todo: remove me + if(c && newScroll) { - const Item *item = s->GetCollectionItem(); - //todo: will create a runtime fault if not of the right type - //todo: remove coupling from knowing the collection name + ViewInfo *currentViewInfo = ScrollPoints->at(pointIndex); + unsigned int nextI = GetNextTween(pointIndex, ScrollPoints); + ViewInfo *nextViewInfo = ScrollPoints->at(nextI); - std::string videoKey ="collections." + GetCollectionName() + ".media.video"; - std::string imagePath; - std::string videoPath; - - Component *t = NULL; - - /* - // todo: to be supported at a later date - if(c->GetProperty(videoKey, videoPath)) - { - t = new VideoComponent(videoPath, item->GetFullTitle(), ScaleX, ScaleY); - } - */ - if(!t) - { - - ImageBuilder imageBuild; - Config.GetMediaPropertyAbsolutePath(CollectionName, ImageType, imagePath); - t = imageBuild.CreateImage(imagePath, item->GetName(), ScaleX, ScaleY); - - if(!t && item->GetTitle() != item->GetFullTitle()) - { - t = imageBuild.CreateImage(imagePath, item->GetFullTitle(), ScaleX, ScaleY); - } - } - if (!t) - { - t = new Text(item->GetTitle(), FontInst, FontColor, ScaleX, ScaleY); - } - - if(t) - { - s->SetComponent(t); - } + ResetTweens(c, TweenPoints->at(pointIndex), currentViewInfo, nextViewInfo, nextScrollTime); + c->TriggerMenuScrollEvent(); + } + if(c) + { + c->Update(dt); } + CircularIncrement(spriteIndex, SpriteList); +} + +void ScrollingList::ResetTweens(Component *c, TweenSet *sets, ViewInfo *currentViewInfo, ViewInfo *nextViewInfo, double scrollTime) +{ + if(!c) { return; } + if(!sets) { return; } + if(!currentViewInfo) { return; } + if(!nextViewInfo) { return; } + + currentViewInfo->SetImageHeight(c->GetBaseViewInfo()->GetImageHeight()); + currentViewInfo->SetImageWidth(c->GetBaseViewInfo()->GetImageWidth()); + nextViewInfo->SetImageHeight(c->GetBaseViewInfo()->GetImageHeight()); + nextViewInfo->SetImageWidth(c->GetBaseViewInfo()->GetImageWidth()); + nextViewInfo->SetBackgroundAlpha(c->GetBaseViewInfo()->GetBackgroundAlpha()); + + //todo: delete properly, memory leak (big), proof of concept + c->SetTweens(sets); + + TweenSets *scrollTween = sets->GetOnMenuScrollTweens(); + TweenSets::iterator it = scrollTween->begin(); + + while(it != scrollTween->end()) + { + std::vector::iterator it2 = (*it)->begin(); + while(it2 != (*it)->end()) + { + delete *it2; + (*it)->erase(it2); + it2 = (*it)->begin(); + } + delete *it; + scrollTween->erase(it); + it = scrollTween->begin(); + + } + + scrollTween->clear(); + c->UpdateBaseViewInfo(*currentViewInfo); + + std::vector *set = new std::vector(); + set->push_back(new Tween(TWEEN_PROPERTY_HEIGHT, LINEAR, currentViewInfo->GetHeight(), nextViewInfo->GetHeight(), scrollTime)); + set->push_back(new Tween(TWEEN_PROPERTY_WIDTH, LINEAR, currentViewInfo->GetWidth(), nextViewInfo->GetWidth(), scrollTime)); + set->push_back(new Tween(TWEEN_PROPERTY_ANGLE, LINEAR, currentViewInfo->GetAngle(), nextViewInfo->GetAngle(), scrollTime)); + set->push_back(new Tween(TWEEN_PROPERTY_ALPHA, LINEAR, currentViewInfo->GetAlpha(), nextViewInfo->GetAlpha(), scrollTime)); + set->push_back(new Tween(TWEEN_PROPERTY_X, LINEAR, currentViewInfo->GetX(), nextViewInfo->GetX(), scrollTime)); + set->push_back(new Tween(TWEEN_PROPERTY_Y, LINEAR, currentViewInfo->GetY(), nextViewInfo->GetY(), scrollTime)); + set->push_back(new Tween(TWEEN_PROPERTY_X_ORIGIN, LINEAR, currentViewInfo->GetXOrigin(), nextViewInfo->GetXOrigin(), scrollTime)); + set->push_back(new Tween(TWEEN_PROPERTY_Y_ORIGIN, LINEAR, currentViewInfo->GetYOrigin(), nextViewInfo->GetYOrigin(), scrollTime)); + set->push_back(new Tween(TWEEN_PROPERTY_X_OFFSET, LINEAR, currentViewInfo->GetXOffset(), nextViewInfo->GetXOffset(), scrollTime)); + set->push_back(new Tween(TWEEN_PROPERTY_Y_OFFSET, LINEAR, currentViewInfo->GetYOffset(), nextViewInfo->GetYOffset(), scrollTime)); + set->push_back(new Tween(TWEEN_PROPERTY_FONT_SIZE, LINEAR, currentViewInfo->GetFontSize(), nextViewInfo->GetFontSize(), scrollTime)); + set->push_back(new Tween(TWEEN_PROPERTY_BACKGROUND_ALPHA, LINEAR, currentViewInfo->GetBackgroundAlpha(), nextViewInfo->GetBackgroundAlpha(), scrollTime)); + scrollTween->push_back(set); +} + + +bool ScrollingList::AllocateTexture(ComponentItemBinding *s) +{ + + if(!s || s->GetComponent() != NULL) { return false; } + + const Item *item = s->GetCollectionItem(); + //todo: will create a runtime fault if not of the right type + //todo: remove coupling from knowing the collection name + + std::string videoKey ="collections." + GetCollectionName() + ".media.video"; + std::string imagePath; + std::string videoPath; + + Component *t = NULL; + + ImageBuilder imageBuild; + Config.GetMediaPropertyAbsolutePath(GetCollectionName(), ImageType, imagePath); + t = imageBuild.CreateImage(imagePath, item->GetName(), ScaleX, ScaleY); + + if(!t && item->GetTitle() != item->GetFullTitle()) + { + t = imageBuild.CreateImage(imagePath, item->GetFullTitle(), ScaleX, ScaleY); + } + if (!t) + { + t = new Text(item->GetTitle(), FontInst, FontColor, ScaleX, ScaleY); + } + + if(t) + { + s->SetComponent(t); + } + + return true; } void ScrollingList::DeallocateTexture(ComponentItemBinding *s) @@ -546,25 +599,25 @@ void ScrollingList::Draw() // caller should instead call ScrollingList::Draw(unsigned int layer) } -//todo: this is kind of a hack. Aggregation needs to happen differently void ScrollingList::Draw(unsigned int layer) { - if(ScrollPoints && SpriteList && SpriteList->size() > 0 && FirstSpriteIndex < SpriteList->size()) + if(!ScrollPoints) { return; } + if(!SpriteList) { return; } + if(SpriteList->size() == 0) { return; } + + unsigned int spriteIndex = FirstSpriteIndex; + + for(unsigned int i = 0; i < ScrollPoints->size(); i++) { - unsigned int spriteIndex = FirstSpriteIndex; + ComponentItemBinding *s = SpriteList->at(spriteIndex); + Component *c = s->GetComponent(); + ViewInfo *currentViewInfo = ScrollPoints->at(i); - for(unsigned int i = 0; i < ScrollPoints->size(); i++) + if(c && currentViewInfo && currentViewInfo->GetLayer() == layer) { - std::vector::iterator it = SpriteList->begin() + spriteIndex; - Component *c = (*it)->GetComponent(); - ViewInfo *currentViewInfo = ScrollPoints->at(i); - - if(currentViewInfo && currentViewInfo->GetLayer() == layer) - { - c->Draw(); - } - CircularIncrement(spriteIndex, SpriteList); + c->Draw(); } + CircularIncrement(spriteIndex, SpriteList); } } @@ -572,6 +625,8 @@ void ScrollingList::Draw(unsigned int layer) void ScrollingList::SetScrollDirection(ScrollDirection direction) { RequestedScrollDirection = direction; + + ScrollStopRequested = (direction == ScrollDirection::ScrollDirectionIdle); } void ScrollingList::RemoveSelectedItem() @@ -602,7 +657,6 @@ void ScrollingList::RemoveSelectedItem() FirstSpriteIndex = 0; } } - IsScrollChangedComplete = true; } @@ -629,17 +683,6 @@ ComponentItemBinding* ScrollingList::GetPendingCollectionItemSprite() { ComponentItemBinding *item = NULL; unsigned int index = FirstSpriteIndex; - if(SpriteList && CurrentScrollState != ScrollStatePageChange) - { - if(CurrentScrollDirection == ScrollDirectionBack) - { - CircularDecrement(index, SpriteList); - } - if(CurrentScrollDirection == ScrollDirectionForward) - { - CircularIncrement(index, SpriteList); - } - } if(SpriteList && SpriteList->size() > 0) { index = (index + SelectedSpriteListIndex) % SpriteList->size(); @@ -731,6 +774,18 @@ void ScrollingList::CircularDecrement(unsigned int &index, 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) { @@ -741,6 +796,7 @@ void ScrollingList::CircularIncrement(unsigned int &index, std::vector *list) { if(index > 0) diff --git a/RetroFE/Source/Graphics/Component/ScrollingList.h b/RetroFE/Source/Graphics/Component/ScrollingList.h index f9d24cc..5ee1969 100644 --- a/RetroFE/Source/Graphics/Component/ScrollingList.h +++ b/RetroFE/Source/Graphics/Component/ScrollingList.h @@ -42,9 +42,10 @@ public: void TriggerMenuEnterEvent(); void TriggerMenuExitEvent(); - void AllocateTexture(ComponentItemBinding *s); + 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(); @@ -64,11 +65,12 @@ public: void Draw(unsigned int layer); private: - void Click(); + void Click(double nextScrollTime); + void DeallocateSpritePoints(); + void AllocateSpritePoints(); + void UpdateSprite(unsigned int spriteIndex, unsigned int pointIndex, bool newScroll, float dt, double nextScrollTime); unsigned int GetNextTween(unsigned int currentIndex, std::vector *list); - bool IsScrollChangedStarted; - bool IsScrollChangedSignalled; - bool IsScrollChangedComplete; + void ResetTweens(Component *c, TweenSet *sets, ViewInfo *currentViewInfo, ViewInfo *nextViewInfo, double scrollTime); enum ScrollState { @@ -87,15 +89,15 @@ private: unsigned int FirstSpriteIndex; unsigned int SelectedSpriteListIndex; - float CurrentAnimateTime; - float ScrollTime; + bool ScrollStopRequested; ScrollDirection CurrentScrollDirection; ScrollDirection RequestedScrollDirection; ScrollState CurrentScrollState; float ScrollAcceleration; - float ScrollVelocity; + 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); diff --git a/RetroFE/Source/Graphics/ComponentItemBinding.h b/RetroFE/Source/Graphics/ComponentItemBinding.h index 50b3221..40f42eb 100644 --- a/RetroFE/Source/Graphics/ComponentItemBinding.h +++ b/RetroFE/Source/Graphics/ComponentItemBinding.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 @@ -17,6 +29,7 @@ public: void SetComponent(Component *c); Component* GetComponent() const; + private: Component *CollectionComponent; Item *CollectionItem; diff --git a/RetroFE/Source/Graphics/Page.cpp b/RetroFE/Source/Graphics/Page.cpp index adb574f..7a9aa23 100644 --- a/RetroFE/Source/Graphics/Page.cpp +++ b/RetroFE/Source/Graphics/Page.cpp @@ -197,7 +197,6 @@ void Page::Start() { ScrollingList *menu = *it; menu->TriggerEnterEvent(); - Logger::Write(Logger::ZONE_DEBUG, "Page", "Triggering enter event"); } if(LoadSoundChunk) @@ -307,10 +306,7 @@ void Page::SetScrolling(ScrollDirection direction) break; } - if(ActiveMenu) - { - ActiveMenu->SetScrollDirection(menuDirection); - } + ActiveMenu->SetScrollDirection(menuDirection); } void Page::PageScroll(ScrollDirection direction) @@ -335,15 +331,14 @@ bool Page::PushCollection(CollectionInfo *collection) if(ActiveMenu) { - 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->DestroyItems(); + ActiveMenu->SetItems(sprites); ActiveMenu->TriggerMenuEnterEvent(); if(MenuDepth < Menus.size()) @@ -358,7 +353,6 @@ bool Page::PushCollection(CollectionInfo *collection) (*it)->SetCollectionName(collection->GetName()); } } - Logger::Write(Logger::ZONE_INFO, "Page", "PUSH COMPLETE, expect updates"); return true; } diff --git a/RetroFE/Source/Graphics/Page.h b/RetroFE/Source/Graphics/Page.h index e29be46..e5185ee 100644 --- a/RetroFE/Source/Graphics/Page.h +++ b/RetroFE/Source/Graphics/Page.h @@ -65,6 +65,7 @@ public: { SelectSoundChunk = chunk; } + bool AddComponent(Component *c); void PageScroll(ScrollDirection direction); void Start(); @@ -102,6 +103,7 @@ private: std::vector LayerComponents[NUM_LAYERS]; std::vector *Items; bool ScrollActive; + Item *SelectedItem; Text *TextStatusComponent; bool SelectedItemChanged; diff --git a/RetroFE/Source/RetroFE.cpp b/RetroFE/Source/RetroFE.cpp index 0b88410..558d10a 100644 --- a/RetroFE/Source/RetroFE.cpp +++ b/RetroFE/Source/RetroFE.cpp @@ -412,7 +412,6 @@ RetroFE::RETROFE_STATE RetroFE::ProcessUserInput(Page *page) 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; }