| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include "UiAnimationSystem.h"
- #include "AnimSplineTrack.h"
- #include "AnimSequence.h"
- #include "AzEntityNode.h"
- #include "UiAnimSerialize.h"
- #include <AzCore/Component/ComponentApplicationBus.h>
- #include <AzCore/std/containers/map.h>
- #include <AzCore/std/containers/unordered_map.h>
- #include <ISystem.h>
- #include <ILog.h>
- #include <IConsole.h>
- //////////////////////////////////////////////////////////////////////////
- // Serialization for anim nodes & param types
- #define REGISTER_NODE_TYPE(name) assert(!m_animNodeEnumToStringMap.contains(eUiAnimNodeType_ ## name)); \
- m_animNodeEnumToStringMap[eUiAnimNodeType_ ## name] = AZ_STRINGIZE(name); \
- m_animNodeStringToEnumMap[UiAnimParamSystemString(AZ_STRINGIZE(name))] = eUiAnimNodeType_ ## name;
- #define REGISTER_PARAM_TYPE(name) assert(!m_animParamEnumToStringMap.contains(eUiAnimParamType_ ## name)); \
- m_animParamEnumToStringMap[eUiAnimParamType_ ## name] = AZ_STRINGIZE(name); \
- m_animParamStringToEnumMap[UiAnimParamSystemString(AZ_STRINGIZE(name))] = eUiAnimParamType_ ## name;
- // If you get an assert in this function, it means two node types have the same enum value.
- void UiAnimationSystem::RegisterNodeTypes()
- {
- REGISTER_NODE_TYPE(Entity)
- REGISTER_NODE_TYPE(Director)
- REGISTER_NODE_TYPE(Camera)
- REGISTER_NODE_TYPE(CVar)
- REGISTER_NODE_TYPE(ScriptVar)
- REGISTER_NODE_TYPE(Material)
- REGISTER_NODE_TYPE(Event)
- REGISTER_NODE_TYPE(Group)
- REGISTER_NODE_TYPE(Layer)
- REGISTER_NODE_TYPE(Comment)
- REGISTER_NODE_TYPE(RadialBlur)
- REGISTER_NODE_TYPE(ColorCorrection)
- REGISTER_NODE_TYPE(DepthOfField)
- REGISTER_NODE_TYPE(ScreenFader)
- REGISTER_NODE_TYPE(Light)
- REGISTER_NODE_TYPE(HDRSetup)
- REGISTER_NODE_TYPE(ShadowSetup)
- REGISTER_NODE_TYPE(Alembic)
- REGISTER_NODE_TYPE(GeomCache)
- REGISTER_NODE_TYPE(Environment)
- REGISTER_NODE_TYPE(ScreenDropsSetup)
- REGISTER_NODE_TYPE(AzEntity)
- }
- // If you get an assert in this function, it means two param types have the same enum value.
- void UiAnimationSystem::RegisterParamTypes()
- {
- REGISTER_PARAM_TYPE(Event)
- REGISTER_PARAM_TYPE(Float)
- REGISTER_PARAM_TYPE(TrackEvent)
- REGISTER_PARAM_TYPE(AzComponentField)
- }
- //////////////////////////////////////////////////////////////////////////
- UiAnimationSystem::UiAnimationSystem()
- {
- m_pSystem = (gEnv) ? gEnv->pSystem : nullptr;
- m_bRecording = false;
- m_pCallback = NULL;
- m_bPaused = false;
- m_sequenceStopBehavior = eSSB_GotoEndTime;
- m_lastUpdateTime = AZ::Time::ZeroTimeUs;
- m_nextSequenceId = 1;
- RegisterNodeTypes();
- RegisterParamTypes();
- }
- //////////////////////////////////////////////////////////////////////////
- bool UiAnimationSystem::Load(const char* pszFile, const char* pszMission)
- {
- INDENT_LOG_DURING_SCOPE (true, "UI Animation system is loading the file '%s' (mission='%s')", pszFile, pszMission);
- XmlNodeRef rootNode = m_pSystem->LoadXmlFromFile(pszFile);
- if (!rootNode)
- {
- return false;
- }
- XmlNodeRef Node = NULL;
- for (int i = 0; i < rootNode->getChildCount(); i++)
- {
- XmlNodeRef missionNode = rootNode->getChild(i);
- XmlString sName;
- if (!(sName = missionNode->getAttr("Name")))
- {
- continue;
- }
- if (_stricmp(sName.c_str(), pszMission))
- {
- continue;
- }
- Node = missionNode;
- break;
- }
- if (!Node)
- {
- return false;
- }
- Serialize(Node, true, true, false);
- return true;
- }
- //////////////////////////////////////////////////////////////////////////
- IUiAnimTrack* UiAnimationSystem::CreateTrack([[maybe_unused]] EUiAnimCurveType type)
- {
- #if 0
- switch (type)
- {
- case eUiAnimCurveType_TCBFloat:
- return new CTcbFloatTrack;
- case eUiAnimCurveType_TCBVector:
- return new CTcbVectorTrack;
- case eUiAnimCurveType_TCBQuat:
- return new CTcbQuatTrack;
- }
- ;
- #endif
- assert(0);
- return 0;
- }
- //////////////////////////////////////////////////////////////////////////
- IUiAnimSequence* UiAnimationSystem::CreateSequence(const char* pSequenceName, bool bLoad, uint32 id)
- {
- if (!bLoad)
- {
- id = m_nextSequenceId++;
- }
- IUiAnimSequence* pSequence = aznew CUiAnimSequence(this, id);
- pSequence->SetName(pSequenceName);
- m_sequences.push_back(pSequence);
- return pSequence;
- }
- //////////////////////////////////////////////////////////////////////////
- IUiAnimSequence* UiAnimationSystem::LoadSequence(const char* pszFilePath)
- {
- XmlNodeRef sequenceNode = m_pSystem->LoadXmlFromFile(pszFilePath);
- if (sequenceNode)
- {
- return LoadSequence(sequenceNode);
- }
- return NULL;
- }
- //////////////////////////////////////////////////////////////////////////
- IUiAnimSequence* UiAnimationSystem::LoadSequence(XmlNodeRef& xmlNode, bool bLoadEmpty)
- {
- IUiAnimSequence* pSequence = aznew CUiAnimSequence(this, 0);
- pSequence->Serialize(xmlNode, true, bLoadEmpty);
- // Delete previous sequence with the same name.
- const char* pFullName = pSequence->GetName();
- IUiAnimSequence* pPrevSeq = FindSequence(pFullName);
- if (pPrevSeq)
- {
- RemoveSequence(pPrevSeq);
- }
- m_sequences.push_back(pSequence);
- return pSequence;
- }
- //////////////////////////////////////////////////////////////////////////
- IUiAnimSequence* UiAnimationSystem::FindSequence(const char* pSequenceName) const
- {
- assert(pSequenceName);
- if (!pSequenceName)
- {
- return NULL;
- }
- for (Sequences::const_iterator it = m_sequences.begin(); it != m_sequences.end(); ++it)
- {
- IUiAnimSequence* pCurrentSequence = it->get();
- const char* fullname = pCurrentSequence->GetName();
- if (_stricmp(fullname, pSequenceName) == 0)
- {
- return pCurrentSequence;
- }
- }
- return NULL;
- }
- //////////////////////////////////////////////////////////////////////////
- IUiAnimSequence* UiAnimationSystem::FindSequenceById(uint32 id) const
- {
- if (id == 0 || id >= m_nextSequenceId)
- {
- return NULL;
- }
- for (Sequences::const_iterator it = m_sequences.begin(); it != m_sequences.end(); ++it)
- {
- IUiAnimSequence* pCurrentSequence = it->get();
- if (id == pCurrentSequence->GetId())
- {
- return pCurrentSequence;
- }
- }
- return NULL;
- }
- //////////////////////////////////////////////////////////////////////////
- bool UiAnimationSystem::FindSequence(IUiAnimSequence* pSequence, PlayingSequences::const_iterator& sequenceIteratorOut) const
- {
- PlayingSequences::const_iterator itend = m_playingSequences.end();
- for (sequenceIteratorOut = m_playingSequences.begin(); sequenceIteratorOut != itend; ++sequenceIteratorOut)
- {
- if (sequenceIteratorOut->sequence == pSequence)
- {
- return true;
- }
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- bool UiAnimationSystem::FindSequence(IUiAnimSequence* pSequence, PlayingSequences::iterator& sequenceIteratorOut)
- {
- PlayingSequences::const_iterator itend = m_playingSequences.end();
- for (sequenceIteratorOut = m_playingSequences.begin(); sequenceIteratorOut != itend; ++sequenceIteratorOut)
- {
- if (sequenceIteratorOut->sequence == pSequence)
- {
- return true;
- }
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- IUiAnimSequence* UiAnimationSystem::GetSequence(int i) const
- {
- assert(i >= 0 && i < GetNumSequences());
- if (i < 0 || i >= GetNumSequences())
- {
- return NULL;
- }
- return m_sequences[i].get();
- }
- //////////////////////////////////////////////////////////////////////////
- int UiAnimationSystem::GetNumSequences() const
- {
- return static_cast<int>(m_sequences.size());
- }
- //////////////////////////////////////////////////////////////////////////
- IUiAnimSequence* UiAnimationSystem::GetPlayingSequence(int i) const
- {
- assert(i >= 0 && i < GetNumPlayingSequences());
- if (i < 0 || i >= GetNumPlayingSequences())
- {
- return NULL;
- }
- return m_playingSequences[i].sequence.get();
- }
- //////////////////////////////////////////////////////////////////////////
- int UiAnimationSystem::GetNumPlayingSequences() const
- {
- return static_cast<int>(m_playingSequences.size());
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::AddSequence(IUiAnimSequence* pSequence)
- {
- m_sequences.push_back(pSequence);
- }
- //////////////////////////////////////////////////////////////////////////
- bool UiAnimationSystem::IsCutScenePlaying() const
- {
- const uint numPlayingSequences = static_cast<uint>(m_playingSequences.size());
- for (uint i = 0; i < numPlayingSequences; ++i)
- {
- const IUiAnimSequence* pAnimSequence = m_playingSequences[i].sequence.get();
- if (pAnimSequence && (pAnimSequence->GetFlags() & IUiAnimSequence::eSeqFlags_CutScene) != 0)
- {
- return true;
- }
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::RemoveSequence(IUiAnimSequence* pSequence)
- {
- assert(pSequence != 0);
- if (pSequence)
- {
- IUiAnimationCallback* pCallback = GetCallback();
- SetCallback(NULL);
- StopSequence(pSequence);
- for (Sequences::iterator it = m_sequences.begin(); it != m_sequences.end(); ++it)
- {
- if (pSequence == *it)
- {
- m_animationListenerMap.erase(pSequence);
- m_sequences.erase(it);
- break;
- }
- }
- SetCallback(pCallback);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- int UiAnimationSystem::OnSequenceRenamed(const char* before, const char* after)
- {
- assert(before && after);
- if (before == NULL || after == NULL)
- {
- return 0;
- }
- if (_stricmp(before, after) == 0)
- {
- return 0;
- }
- int count = 0;
- // UI_ANIMATION_REVISIT : this only did anything for director nodes
- return count;
- }
- //////////////////////////////////////////////////////////////////////////
- int UiAnimationSystem::OnCameraRenamed([[maybe_unused]] const char* before, [[maybe_unused]] const char* after)
- {
- // UI_ANIMATION_REVISIT - not used
- return 0;
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::RemoveAllSequences()
- {
- IUiAnimationCallback* pCallback = GetCallback();
- SetCallback(NULL);
- InternalStopAllSequences(true, false);
- stl::free_container(m_sequences);
- for (TUiAnimationListenerMap::iterator it = m_animationListenerMap.begin(); it != m_animationListenerMap.end(); )
- {
- if (it->first)
- {
- m_animationListenerMap.erase(it++);
- }
- else
- {
- ++it;
- }
- }
- SetCallback(pCallback);
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::PlaySequence(const char* pSequenceName, IUiAnimSequence* pParentSeq, bool bResetFx, bool bTrackedSequence, float startTime, float endTime)
- {
- IUiAnimSequence* pSequence = FindSequence(pSequenceName);
- if (pSequence)
- {
- PlaySequence(pSequence, pParentSeq, bResetFx, bTrackedSequence, startTime, endTime);
- }
- else
- {
- gEnv->pLog->Log ("UiAnimationSystem::PlaySequence: Error: Sequence \"%s\" not found", pSequenceName);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::PlaySequence(IUiAnimSequence* pSequence, IUiAnimSequence* parentSeq,
- [[maybe_unused]] bool bResetFx, bool bTrackedSequence, float startTime, float endTime)
- {
- assert(pSequence != 0);
- if (!pSequence || IsPlaying(pSequence))
- {
- return;
- }
- // If this sequence is cut scene disable player.
- if (pSequence->GetFlags() & IUiAnimSequence::eSeqFlags_CutScene)
- {
- OnCameraCut();
- pSequence->SetParentSequence(parentSeq);
- }
- pSequence->Activate();
- pSequence->Resume();
- static_cast<CUiAnimSequence*>(pSequence)->OnStart();
- PlayingUIAnimSequence ps;
- ps.sequence = pSequence;
- ps.startTime = startTime == -FLT_MAX ? pSequence->GetTimeRange().start : startTime;
- ps.endTime = endTime == -FLT_MAX ? pSequence->GetTimeRange().end : endTime;
- ps.currentTime = startTime == -FLT_MAX ? pSequence->GetTimeRange().start : startTime;
- ps.currentSpeed = 1.0f;
- ps.trackedSequence = bTrackedSequence;
- ps.bSingleFrame = false;
- // Make sure all members are initialized before pushing.
- m_playingSequences.push_back(ps);
- // tell all interested listeners
- NotifyListeners(pSequence, IUiAnimationListener::eUiAnimationEvent_Started);
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::NotifyListeners(IUiAnimSequence* pSequence, IUiAnimationListener::EUiAnimationEvent event)
- {
- TUiAnimationListenerMap::iterator found (m_animationListenerMap.find(pSequence));
- if (found != m_animationListenerMap.end())
- {
- TUiAnimationListenerVec listForSeq = (*found).second;
- TUiAnimationListenerVec::iterator iter (listForSeq.begin());
- while (iter != listForSeq.end())
- {
- (*iter)->OnUiAnimationEvent(event, pSequence);
- ++iter;
- }
- }
- // 'NULL' ones are listeners interested in every sequence. Do not send "update" here
- if (event != IUiAnimationListener::eUiAnimationEvent_Updated)
- {
- TUiAnimationListenerMap::iterator found2 (m_animationListenerMap.find((IUiAnimSequence*)0));
- if (found2 != m_animationListenerMap.end())
- {
- TUiAnimationListenerVec listForSeq = (*found2).second;
- TUiAnimationListenerVec::iterator iter (listForSeq.begin());
- while (iter != listForSeq.end())
- {
- (*iter)->OnUiAnimationEvent(event, pSequence);
- ++iter;
- }
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::NotifyTrackEventListeners(const char* eventName, const char* valueName, IUiAnimSequence* pSequence)
- {
- TUiAnimationListenerMap::iterator found(m_animationListenerMap.find(pSequence));
- if (found != m_animationListenerMap.end())
- {
- TUiAnimationListenerVec listForSeq = (*found).second;
- TUiAnimationListenerVec::iterator iter(listForSeq.begin());
- while (iter != listForSeq.end())
- {
- (*iter)->OnUiTrackEvent(AZStd::string(eventName), AZStd::string(valueName), pSequence);
- ++iter;
- }
- }
- // 'NULL' ones are listeners interested in every sequence.
- TUiAnimationListenerMap::iterator found2(m_animationListenerMap.find(static_cast<IUiAnimSequence*>(nullptr)));
- if (found2 != m_animationListenerMap.end())
- {
- TUiAnimationListenerVec listForSeq = (*found2).second;
- TUiAnimationListenerVec::iterator iter(listForSeq.begin());
- while (iter != listForSeq.end())
- {
- (*iter)->OnUiTrackEvent(AZStd::string(eventName), AZStd::string(valueName), pSequence);
- ++iter;
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- bool UiAnimationSystem::StopSequence(const char* pSequenceName)
- {
- IUiAnimSequence* pSequence = FindSequence(pSequenceName);
- if (pSequence)
- {
- return StopSequence(pSequence);
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- bool UiAnimationSystem::StopSequence(IUiAnimSequence* pSequence)
- {
- return InternalStopSequence(pSequence, false, true);
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::InternalStopAllSequences(bool bAbort, bool bAnimate)
- {
- while (!m_playingSequences.empty())
- {
- InternalStopSequence(m_playingSequences.begin()->sequence.get(), bAbort, bAnimate);
- }
- stl::free_container(m_playingSequences);
- }
- //////////////////////////////////////////////////////////////////////////
- bool UiAnimationSystem::InternalStopSequence(IUiAnimSequence* pSequence, bool bAbort, bool bAnimate)
- {
- assert(pSequence != 0);
- bool bRet = false;
- PlayingSequences::iterator it;
- if (FindSequence(pSequence, it))
- {
- if (bAnimate)
- {
- if (m_sequenceStopBehavior == eSSB_GotoEndTime)
- {
- SUiAnimContext ac;
- ac.bSingleFrame = true;
- ac.time = pSequence->GetTimeRange().end;
- pSequence->Animate(ac);
- }
- else if (m_sequenceStopBehavior == eSSB_GotoStartTime)
- {
- SUiAnimContext ac;
- ac.bSingleFrame = true;
- ac.time = pSequence->GetTimeRange().start;
- pSequence->Animate(ac);
- }
- pSequence->Deactivate();
- }
- // tell all interested listeners
- NotifyListeners(pSequence, bAbort ? IUiAnimationListener::eUiAnimationEvent_Aborted : IUiAnimationListener::eUiAnimationEvent_Stopped);
- // erase the sequence after notifying listeners so if they choose to they can get the ending time of this sequence
- if (FindSequence(pSequence, it))
- {
- m_playingSequences.erase(it);
- }
- pSequence->Resume();
- static_cast<CUiAnimSequence*>(pSequence)->OnStop();
- bRet = true;
- }
- return bRet;
- }
- //////////////////////////////////////////////////////////////////////////
- bool UiAnimationSystem::AbortSequence(IUiAnimSequence* pSequence, bool bLeaveTime)
- {
- return InternalStopSequence(pSequence, true, !bLeaveTime);
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::StopAllSequences()
- {
- InternalStopAllSequences(false, true);
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::StopAllCutScenes()
- {
- bool bAnyStoped;
- PlayingSequences::iterator next;
- do
- {
- bAnyStoped = false;
- for (PlayingSequences::iterator it = m_playingSequences.begin(); it != m_playingSequences.end(); it = next)
- {
- next = it;
- ++next;
- IUiAnimSequence* pCurrentSequence = it->sequence.get();
- if (pCurrentSequence->GetFlags() & IUiAnimSequence::eSeqFlags_CutScene)
- {
- bAnyStoped = true;
- StopSequence(pCurrentSequence);
- break;
- }
- }
- } while (bAnyStoped);
- if (m_playingSequences.empty())
- {
- stl::free_container(m_playingSequences);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- bool UiAnimationSystem::IsPlaying(IUiAnimSequence* pSequence) const
- {
- for (PlayingSequences::const_iterator it = m_playingSequences.begin(); it != m_playingSequences.end(); ++it)
- {
- if (it->sequence == pSequence)
- {
- return true;
- }
- }
- return false;
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::Reset(bool bPlayOnReset, bool bSeekToStart)
- {
- InternalStopAllSequences(true, false);
- // Reset all sequences.
- for (Sequences::iterator iter = m_sequences.begin(); iter != m_sequences.end(); ++iter)
- {
- IUiAnimSequence* pCurrentSequence = iter->get();
- NotifyListeners(pCurrentSequence, IUiAnimationListener::eUiAnimationEvent_Started);
- pCurrentSequence->Reset(bSeekToStart);
- NotifyListeners(pCurrentSequence, IUiAnimationListener::eUiAnimationEvent_Stopped);
- }
- if (bPlayOnReset)
- {
- for (Sequences::iterator iter = m_sequences.begin(); iter != m_sequences.end(); ++iter)
- {
- IUiAnimSequence* pCurrentSequence = iter->get();
- if (pCurrentSequence->GetFlags() & IUiAnimSequence::eSeqFlags_PlayOnReset)
- {
- PlaySequence(pCurrentSequence);
- }
- }
- }
- // un-pause the UI animation system
- m_bPaused = false;
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::PlayOnLoadSequences()
- {
- for (Sequences::iterator sit = m_sequences.begin(); sit != m_sequences.end(); ++sit)
- {
- IUiAnimSequence* pSequence = sit->get();
- if (pSequence->GetFlags() & IUiAnimSequence::eSeqFlags_PlayOnReset)
- {
- PlaySequence(pSequence);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::StillUpdate()
- {
- if (!gEnv->IsEditor())
- {
- return;
- }
- for (PlayingSequences::iterator it = m_playingSequences.begin(); it != m_playingSequences.end(); ++it)
- {
- PlayingUIAnimSequence& playingSequence = *it;
- playingSequence.sequence->StillUpdate();
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::ShowPlayedSequencesDebug()
- {
- constexpr f32 green[4] = {0, 1, 0, 1};
- constexpr f32 purple[4] = {1, 0, 1, 1};
- constexpr f32 white[4] = {1, 1, 1, 1};
- float y = 10.0f;
- AZStd::vector<AZStd::string> names;
- //TODO: needs an implementation
- auto Draw2dLabel = [](float /*x*/,float /*y*/,float /*depth*/,const f32* /*color*/,bool /*center*/, const char* /*fmt*/, ...) {};
- for (PlayingSequences::iterator it = m_playingSequences.begin(); it != m_playingSequences.end(); ++it)
- {
- PlayingUIAnimSequence& playingSequence = *it;
- if (playingSequence.sequence == nullptr)
- {
- continue;
- }
- AZ_Assert(false,"gEnv->pRenderer is always null so it can't be used here");
- const char* fullname = playingSequence.sequence->GetName();
- Draw2dLabel(1.0f, y, 1.3f, green, false, "Sequence %s : %f (x %f)", fullname, playingSequence.currentTime, playingSequence.currentSpeed);
- y += 16.0f;
- for (int i = 0; i < playingSequence.sequence->GetNodeCount(); ++i)
- {
- // Checks nodes which happen to be in several sequences.
- // Those can be a bug, since several sequences may try to control the same entity.
- AZStd::string name = playingSequence.sequence->GetNode(i)->GetName();
- bool alreadyThere = false;
- if (AZStd::find(names.begin(), names.end(), name) != names.end())
- {
- alreadyThere = true;
- }
- else
- {
- names.push_back(name);
- }
- Draw2dLabel((21.0f + 100.0f * i), ((i % 2) ? (y + 8.0f) : y), 1.0f, alreadyThere ? white : purple, false, "%s", name.c_str());
- }
- y += 32.0f;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::PreUpdate(float deltaTime)
- {
- UpdateInternal(deltaTime, true);
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::PostUpdate(float deltaTime)
- {
- UpdateInternal(deltaTime, false);
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::UpdateInternal(const float deltaTime, const bool bPreUpdate)
- {
- SUiAnimContext animContext;
- if (m_bPaused)
- {
- return;
- }
- // don't update more than once if dt==0.0
- const AZ::TimeUs curTime = AZ::GetElapsedTimeUs();
- if (deltaTime == 0.0f && curTime == m_lastUpdateTime && !gEnv->IsEditor())
- {
- return;
- }
- m_lastUpdateTime = curTime;
- float fps = 60.0f;
- std::vector<IUiAnimSequence*> stopSequences;
- const size_t numPlayingSequences = m_playingSequences.size();
- for (size_t i = 0; i < numPlayingSequences; ++i)
- {
- PlayingUIAnimSequence& playingSequence = m_playingSequences[i];
- if (playingSequence.sequence->IsPaused())
- {
- continue;
- }
- const float scaledTimeDelta = deltaTime * playingSequence.currentSpeed;
- // Increase play time in pre-update
- if (bPreUpdate)
- {
- playingSequence.currentTime += scaledTimeDelta;
- }
- // Skip sequence if current update does not apply
- const bool bSequenceEarlyUpdate = (playingSequence.sequence->GetFlags() & IUiAnimSequence::eSeqFlags_EarlyAnimationUpdate) != 0;
- if (bPreUpdate && !bSequenceEarlyUpdate || !bPreUpdate && bSequenceEarlyUpdate)
- {
- continue;
- }
- animContext.time = playingSequence.currentTime;
- animContext.pSequence = playingSequence.sequence.get();
- animContext.dt = scaledTimeDelta;
- animContext.fps = fps;
- animContext.startTime = playingSequence.startTime;
- // Check time out of range, setting up playingSequence for the next Update
- bool wasLooped = false;
- if (playingSequence.currentTime > playingSequence.endTime)
- {
- int seqFlags = playingSequence.sequence->GetFlags();
- if (seqFlags & IUiAnimSequence::eSeqFlags_OutOfRangeLoop)
- {
- // Time wrap's back to the start of the time range.
- playingSequence.currentTime = playingSequence.startTime; // should there be a fmodf here?
- wasLooped = true;
- }
- else if (seqFlags & IUiAnimSequence::eSeqFlags_OutOfRangeConstant)
- {
- // Time just continues normally past the end of time range.
- }
- else
- {
- // If no out-of-range type specified sequence stopped when time reaches end of range.
- // Que sequence for stopping.
- if (playingSequence.trackedSequence == false)
- {
- stopSequences.push_back(playingSequence.sequence.get());
- }
- continue;
- }
- }
- else
- {
- NotifyListeners(playingSequence.sequence.get(), IUiAnimationListener::eUiAnimationEvent_Updated);
- }
- animContext.bSingleFrame = playingSequence.bSingleFrame;
- playingSequence.bSingleFrame = false;
- // Animate sequence. (Can invalidate iterator)
- playingSequence.sequence->Animate(animContext);
- // we call OnLoop() *after* Animate() to reset sounds (for CUiAnimSceneNodes), for the next update (the looped update)
- if (wasLooped)
- {
- playingSequence.sequence->OnLoop();
- }
- }
- // Stop queued sequences.
- for (int i = 0; i < (int)stopSequences.size(); i++)
- {
- StopSequence(stopSequences[i]);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::Render()
- {
- for (PlayingSequences::iterator it = m_playingSequences.begin(); it != m_playingSequences.end(); ++it)
- {
- PlayingUIAnimSequence& playingSequence = *it;
- playingSequence.sequence->Render();
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::Callback(IUiAnimationCallback::ECallbackReason reason, IUiAnimNode* pNode)
- {
- if (m_pCallback)
- {
- m_pCallback->OnUiAnimationCallback(reason, pNode);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::Serialize(XmlNodeRef& xmlNode, bool bLoading, [[maybe_unused]] bool bRemoveOldNodes, bool bLoadEmpty)
- {
- if (bLoading)
- {
- //////////////////////////////////////////////////////////////////////////
- // Load sequences from XML.
- //////////////////////////////////////////////////////////////////////////
- XmlNodeRef seqNode = xmlNode->findChild("SequenceData");
- if (seqNode)
- {
- RemoveAllSequences();
- INDENT_LOG_DURING_SCOPE(true, "SequenceData tag contains %u sequences", seqNode->getChildCount());
- for (int i = 0; i < seqNode->getChildCount(); i++)
- {
- XmlNodeRef childNode = seqNode->getChild(i);
- if (!LoadSequence(childNode, bLoadEmpty))
- {
- return;
- }
- }
- }
- }
- else
- {
- XmlNodeRef sequencesNode = xmlNode->newChild("SequenceData");
- for (int i = 0; i < GetNumSequences(); ++i)
- {
- IUiAnimSequence* pSequence = GetSequence(i);
- XmlNodeRef sequenceNode = sequencesNode->newChild("Sequence");
- pSequence->Serialize(sequenceNode, false);
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::InitPostLoad(bool remapIds, LyShine::EntityIdMap* entityIdMap)
- {
- for (int i = 0; i < GetNumSequences(); ++i)
- {
- IUiAnimSequence* pSequence = GetSequence(i);
- pSequence->InitPostLoad(this, remapIds, entityIdMap);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::Pause()
- {
- m_bPaused = true;
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::Resume()
- {
- m_bPaused = false;
- }
- //////////////////////////////////////////////////////////////////////////
- float UiAnimationSystem::GetPlayingTime(IUiAnimSequence* pSequence)
- {
- if (!pSequence || !IsPlaying(pSequence))
- {
- return -1.0;
- }
- PlayingSequences::const_iterator it;
- if (FindSequence(pSequence, it))
- {
- return it->currentTime;
- }
- return -1.0f;
- }
- float UiAnimationSystem::GetPlayingSpeed(IUiAnimSequence* pSequence)
- {
- if (!pSequence || !IsPlaying(pSequence))
- {
- return -1.0f;
- }
- PlayingSequences::const_iterator it;
- if (FindSequence(pSequence, it))
- {
- return it->currentSpeed;
- }
- return -1.0f;
- }
- bool UiAnimationSystem::SetPlayingTime(IUiAnimSequence* pSequence, float fTime)
- {
- if (!pSequence || !IsPlaying(pSequence))
- {
- return false;
- }
- PlayingSequences::iterator it;
- if (FindSequence(pSequence, it) && !(pSequence->GetFlags() & IUiAnimSequence::eSeqFlags_NoSeek))
- {
- it->currentTime = fTime;
- it->bSingleFrame = true;
- NotifyListeners(pSequence, IUiAnimationListener::eUiAnimationEvent_Updated);
- return true;
- }
- return false;
- }
- bool UiAnimationSystem::SetPlayingSpeed(IUiAnimSequence* pSequence, float fSpeed)
- {
- if (!pSequence)
- {
- return false;
- }
- PlayingSequences::iterator it;
- if (FindSequence(pSequence, it) && !(pSequence->GetFlags() & IUiAnimSequence::eSeqFlags_NoSpeed))
- {
- NotifyListeners(pSequence, IUiAnimationListener::eUiAnimationEvent_Updated);
- it->currentSpeed = fSpeed;
- return true;
- }
- return false;
- }
- bool UiAnimationSystem::GetStartEndTime(IUiAnimSequence* pSequence, float& fStartTime, float& fEndTime)
- {
- fStartTime = 0.0f;
- fEndTime = 0.0f;
- if (!pSequence || !IsPlaying(pSequence))
- {
- return false;
- }
- PlayingSequences::const_iterator it;
- if (FindSequence(pSequence, it))
- {
- fStartTime = it->startTime;
- fEndTime = it->endTime;
- return true;
- }
- return false;
- }
- bool UiAnimationSystem::SetStartEndTime(IUiAnimSequence* pSeq, const float fStartTime, const float fEndTime)
- {
- if (!pSeq || !IsPlaying(pSeq))
- {
- return false;
- }
- PlayingSequences::iterator it;
- if (FindSequence(pSeq, it))
- {
- it->startTime = fStartTime;
- it->endTime = fEndTime;
- return true;
- }
- return false;
- }
- void UiAnimationSystem::SetSequenceStopBehavior(ESequenceStopBehavior behavior)
- {
- m_sequenceStopBehavior = behavior;
- }
- IUiAnimationSystem::ESequenceStopBehavior UiAnimationSystem::GetSequenceStopBehavior()
- {
- return m_sequenceStopBehavior;
- }
- bool UiAnimationSystem::AddUiAnimationListener(IUiAnimSequence* pSequence, IUiAnimationListener* pListener)
- {
- assert (pListener != 0);
- if (pSequence != NULL && std::find(m_sequences.begin(), m_sequences.end(), pSequence) == m_sequences.end())
- {
- gEnv->pLog->Log ("UiAnimationSystem::AddUiAnimationListener: Sequence %p unknown to UiAnimationSystem", pSequence);
- return false;
- }
- return stl::push_back_unique(m_animationListenerMap[pSequence], pListener);
- }
- bool UiAnimationSystem::RemoveUiAnimationListener(IUiAnimSequence* pSequence, IUiAnimationListener* pListener)
- {
- assert (pListener != 0);
- if (pSequence != NULL
- && std::find(m_sequences.begin(), m_sequences.end(), pSequence) == m_sequences.end())
- {
- gEnv->pLog->Log ("UiAnimationSystem::AddUiAnimationListener: Sequence %p unknown to UiAnimationSystem", pSequence);
- return false;
- }
- return stl::find_and_erase(m_animationListenerMap[pSequence], pListener);
- }
- void UiAnimationSystem::GoToFrame(const char* seqName, float targetFrame)
- {
- assert(seqName != NULL);
- for (PlayingSequences::iterator it = m_playingSequences.begin();
- it != m_playingSequences.end(); ++it)
- {
- PlayingUIAnimSequence& ps = *it;
- const char* fullname = ps.sequence->GetName();
- if (strcmp(fullname, seqName) == 0)
- {
- assert(ps.sequence->GetTimeRange().start <= targetFrame && targetFrame <= ps.sequence->GetTimeRange().end);
- ps.currentTime = targetFrame;
- ps.bSingleFrame = true;
- break;
- }
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::SerializeNodeType(EUiAnimNodeType& animNodeType, XmlNodeRef& xmlNode, bool bLoading, const uint version, int flags)
- {
- static const char* kType = "Type";
- if (bLoading)
- {
- // Old serialization values that are no longer
- // defined in IUiAnimationSystem.h, but needed for conversion:
- static const int kOldParticleNodeType = 0x18;
- animNodeType = eUiAnimNodeType_Invalid;
- // In old versions there was special code for particles
- // that is now handles by generic entity node code
- if (version == 0 && animNodeType == kOldParticleNodeType)
- {
- animNodeType = eUiAnimNodeType_Entity;
- return;
- }
- // Convert light nodes that are not part of a light
- // animation set to common entity nodes
- if (version <= 1 && animNodeType == eUiAnimNodeType_Light && !(flags & IUiAnimSequence::eSeqFlags_LightAnimationSet))
- {
- animNodeType = eUiAnimNodeType_Entity;
- return;
- }
- if (version <= 2)
- {
- int type;
- if (xmlNode->getAttr(kType, type))
- {
- animNodeType = (EUiAnimNodeType)type;
- }
- return;
- }
- else
- {
- XmlString nodeTypeString;
- if (xmlNode->getAttr(kType, nodeTypeString))
- {
- assert(m_animNodeStringToEnumMap.contains(nodeTypeString.c_str()));
- animNodeType = stl::find_in_map(m_animNodeStringToEnumMap, nodeTypeString.c_str(), eUiAnimNodeType_Invalid);
- }
- }
- }
- else
- {
- const char* pTypeString = "Invalid";
- assert(m_animNodeEnumToStringMap.find(animNodeType) != m_animNodeEnumToStringMap.end());
- pTypeString = m_animNodeEnumToStringMap[animNodeType].c_str();
- xmlNode->setAttr(kType, pTypeString);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::SerializeParamType(CUiAnimParamType& animParamType, XmlNodeRef& xmlNode, bool bLoading, const uint version)
- {
- static const char* kByNameAttrName = "paramIdIsName";
- static const char* kParamUserValue = "paramUserValue";
- if (bLoading)
- {
- animParamType.m_type = eUiAnimParamType_Invalid;
- if (version <= 6)
- {
- static const char* kParamId = "paramId";
- if (xmlNode->haveAttr(kByNameAttrName))
- {
- XmlString name;
- if (xmlNode->getAttr(kParamId, name))
- {
- animParamType.m_type = eUiAnimParamType_ByString;
- animParamType.m_name = name.c_str();
- }
- }
- else
- {
- int type;
- xmlNode->getAttr(kParamId, type);
- animParamType.m_type = (EUiAnimParamType)type;
- }
- }
- else
- {
- static const char* kParamType = "paramType";
- XmlString paramTypeString;
- if (xmlNode->getAttr(kParamType, paramTypeString))
- {
- if (paramTypeString == "ByString")
- {
- animParamType.m_type = eUiAnimParamType_ByString;
- XmlString userValue;
- xmlNode->getAttr(kParamUserValue, userValue);
- animParamType.m_name = userValue;
- }
- else if (paramTypeString == "User")
- {
- animParamType.m_type = eUiAnimParamType_User;
- int type;
- xmlNode->getAttr(kParamUserValue, type);
- animParamType.m_type = (EUiAnimParamType)type;
- }
- else
- {
- assert(m_animParamStringToEnumMap.contains(paramTypeString.c_str()));
- animParamType.m_type = stl::find_in_map(m_animParamStringToEnumMap, paramTypeString.c_str(), eUiAnimParamType_Invalid);
- }
- }
- }
- }
- else
- {
- static const char* kParamType = "paramType";
- const char* pTypeString = "Invalid";
- if (animParamType.m_type == eUiAnimParamType_ByString)
- {
- pTypeString = "ByString";
- xmlNode->setAttr(kParamUserValue, animParamType.m_name.c_str());
- }
- else if (animParamType.m_type >= eUiAnimParamType_User)
- {
- pTypeString = "User";
- xmlNode->setAttr(kParamUserValue, (int)animParamType.m_type);
- }
- else
- {
- assert(m_animParamEnumToStringMap.find(animParamType.m_type) != m_animParamEnumToStringMap.end());
- pTypeString = m_animParamEnumToStringMap[animParamType.m_type].c_str();
- }
- xmlNode->setAttr(kParamType, pTypeString);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::SerializeParamData(UiAnimParamData& animParamData, XmlNodeRef& xmlNode, bool bLoading)
- {
- static const char* kLabelComponentIdHi = "ParamComponentIdHi";
- static const char* kLabelComponentIdLo = "ParamComponentIdLo";
- static const char* kLabelTypeId = "ParamTypeId";
- static const char* kLabelName = "ParamName";
- static const char* kLabelOffset = "ParamOffset";
- if (bLoading)
- {
- unsigned long idHi = 0;
- unsigned long idLo = 0;
- XmlString uuidStr;
- XmlString nameStr;
- size_t offset = 0;
- xmlNode->getAttr(kLabelComponentIdHi, idHi);
- xmlNode->getAttr(kLabelComponentIdLo, idLo);
- xmlNode->getAttr(kLabelTypeId, uuidStr);
- xmlNode->getAttr(kLabelName, nameStr);
- xmlNode->getAttr(kLabelOffset, offset);
- AZ::u64 id64 = ((AZ::u64)idHi) << 32 | idLo;
- AZ::Uuid uuid(uuidStr.c_str(), uuidStr.length());
- animParamData = UiAnimParamData(id64, nameStr.c_str(), uuid, offset);
- }
- else
- {
- AZ::u64 id64 = animParamData.GetComponentId();
- unsigned long idHi = id64 >> 32;
- unsigned long idLo = id64 & 0xFFFFFFFF;
- XmlString uuidStr;
- uuidStr += animParamData.GetTypeId().ToString<AZStd::string>();
- XmlString nameStr(animParamData.GetName());
- size_t offset = animParamData.GetOffset();
- xmlNode->setAttr(kLabelComponentIdHi, idHi);
- xmlNode->setAttr(kLabelComponentIdLo, idLo);
- xmlNode->setAttr(kLabelTypeId, uuidStr);
- xmlNode->setAttr(kLabelName, nameStr);
- xmlNode->setAttr(kLabelOffset, offset);
- }
- }
- //////////////////////////////////////////////////////////////////////////
- const char* UiAnimationSystem::GetParamTypeName(const CUiAnimParamType& animParamType)
- {
- if (animParamType.m_type == eUiAnimParamType_ByString)
- {
- return animParamType.GetName();
- }
- else if (animParamType.m_type >= eUiAnimParamType_User)
- {
- return "User";
- }
- else
- {
- if (m_animParamEnumToStringMap.find(animParamType.m_type) != m_animParamEnumToStringMap.end())
- {
- return m_animParamEnumToStringMap[animParamType.m_type].c_str();
- }
- }
- return "Invalid";
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::OnCameraCut()
- {
- }
- //////////////////////////////////////////////////////////////////////////
- void UiAnimationSystem::Reflect(AZ::SerializeContext* serializeContext)
- {
- serializeContext->Class<UiAnimationSystem>()
- ->Version(1)
- ->Field("Sequences", &UiAnimationSystem::m_sequences);
- UiAnimSerialize::ReflectUiAnimTypes(serializeContext);
- // These rely on these classes having a friend declaration for this class
- serializeContext->Class<CUiAnimParamType>()
- ->Version(1)
- ->Field("Type", &CUiAnimParamType::m_type);
- serializeContext->Class<UiAnimParamData>()
- ->Version(1)
- ->Field("ComponentId", &UiAnimParamData::m_componentId)
- ->Field("TypeId", &UiAnimParamData::m_typeId)
- ->Field("Name", &UiAnimParamData::m_name);
- }
- #ifdef UI_ANIMATION_SYSTEM_SUPPORT_EDITING
- //////////////////////////////////////////////////////////////////////////
- EUiAnimNodeType UiAnimationSystem::GetNodeTypeFromString(const char* pString) const
- {
- return stl::find_in_map(m_animNodeStringToEnumMap, pString, eUiAnimNodeType_Invalid);
- }
- //////////////////////////////////////////////////////////////////////////
- CUiAnimParamType UiAnimationSystem::GetParamTypeFromString(const char* pString) const
- {
- const EUiAnimParamType paramType = stl::find_in_map(m_animParamStringToEnumMap, pString, eUiAnimParamType_Invalid);
- if (paramType != eUiAnimParamType_Invalid)
- {
- return CUiAnimParamType(paramType);
- }
- return CUiAnimParamType(pString);
- }
- #endif
|