Files
o3de/Gems/LyShine/Code/Editor/Animation/UiAnimViewSequenceManager.cpp
T
Esteban Papp 1f9b284de2 Merge branch 'development' into cmake/SPEC-7179
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>

# Conflicts:
#	Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h
#	Code/Editor/Plugins/EditorCommon/EditorCommon_precompiled.h
#	Code/Editor/Plugins/EditorCommon/stdafx.cpp
#	Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin_precompiled.h
#	Code/Editor/Plugins/PerforcePlugin/PerforcePlugin_precompiled.h
#	Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsTool_precompiled.h
#	Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFramework_precompiled.h
#	Code/Tools/AssetProcessor/native/precompiled.h
#	Code/Tools/Standalone/StandaloneTools_precompiled.h
#	Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer_precompiled.h
#	Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageProcessing_precompiled.h
#	Gems/Atom/RHI/DX12/Code/Source/RHI/Atom_RHI_DX12_precompiled.h
#	Gems/Atom/RHI/Metal/Code/Include/Platform/Mac/Atom_RHI_Metal_precompiled_Platform.h
#	Gems/Atom/RHI/Metal/Code/Include/Platform/iOS/Atom_RHI_Metal_precompiled_Platform.h
#	Gems/Atom/RHI/Metal/Code/Source/Atom_RHI_Metal_precompiled.h
#	Gems/Atom/RHI/Metal/Code/atom_rhi_metal_common_files.cmake
#	Gems/Atom/RHI/Null/Code/Source/Atom_RHI_Null_precompiled.h
#	Gems/Atom/RHI/Null/Code/atom_rhi_null_common_files.cmake
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Android/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Linux/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Mac/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Windows/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Source/Atom_RHI_Vulkan_precompiled.h
#	Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp
#	Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_common_files.cmake
#	Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont_precompiled.h
#	Gems/Blast/Code/Source/StdAfx.cpp
#	Gems/Camera/Code/Source/Camera_precompiled.h
#	Gems/EMotionFX/Code/Source/EMotionFX_precompiled.h
#	Gems/FastNoise/Code/Source/FastNoise_precompiled.h
#	Gems/Gestures/Code/Source/Gestures_precompiled.h
#	Gems/GradientSignal/Code/Source/GradientSignal_precompiled.h
#	Gems/GraphCanvas/Code/precompiled.h
#	Gems/ImGui/Code/Source/ImGui_precompiled.h
#	Gems/InAppPurchases/Code/Source/InAppPurchases_precompiled.h
#	Gems/LmbrCentral/Code/Source/LmbrCentral_precompiled.h
#	Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp
#	Gems/LyShine/Code/Editor/UiCanvasEditor_precompiled.h
#	Gems/LyShine/Code/Source/Animation/LyShine_precompiled.h
#	Gems/LyShine/Code/Source/LyShine_precompiled.h
#	Gems/LyShineExamples/Code/Source/LyShineExamples_precompiled.h
#	Gems/Maestro/Code/Source/Cinematics/Maestro_precompiled.h
#	Gems/Maestro/Code/Source/Maestro_precompiled.h
#	Gems/MessagePopup/Code/Source/MessagePopup_precompiled.h
#	Gems/Metastream/Code/Source/Metastream_precompiled.h
#	Gems/Microphone/Code/Source/Microphone_precompiled.h
#	Gems/Multiplayer/Code/Source/Multiplayer_precompiled.h
#	Gems/PhysX/Code/NumericalMethods/Source/NumericalMethods_precompiled.h
#	Gems/PhysX/Code/Source/PhysXUnsupported_precompiled.h
#	Gems/PhysX/Code/Source/PhysX_precompiled.h
#	Gems/PhysX/Code/physx_unsupported_files.cmake
#	Gems/PhysXDebug/Code/Source/PhysXDebugUnsupported_precompiled.h
#	Gems/PhysXDebug/Code/Source/PhysXDebug_precompiled.h
#	Gems/ScriptCanvas/Code/Editor/precompiled.h
#	Gems/ScriptCanvas/Code/Source/precompiled.h
#	Gems/ScriptCanvasDeveloper/Code/Source/precompiled.h
#	Gems/ScriptCanvasPhysics/Code/Source/ScriptCanvasPhysics_precompiled.h
#	Gems/ScriptEvents/Code/Source/precompiled.h
#	Gems/ScriptEvents/Code/Tests/Editor/EditorTests.cpp
#	Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweener_precompiled.h
#	Gems/SliceFavorites/Code/Source/SliceFavorites_precompiled.h
#	Gems/StartingPointCamera/Code/Source/StartingPointCamera_precompiled.h
#	Gems/StartingPointInput/Code/Source/StartingPointInput_precompiled.h
#	Gems/StartingPointMovement/Code/Source/StartingPointMovement_precompiled.h
#	Gems/SurfaceData/Code/Source/SurfaceData_precompiled.h
#	Gems/TextureAtlas/Code/Source/TextureAtlas_precompiled.h
#	Gems/TickBusOrderViewer/Code/Source/TickBusOrderViewer_precompiled.h
#	Gems/Twitch/Code/Source/Twitch_precompiled.h
#	Gems/VirtualGamepad/Code/Source/VirtualGamepad_precompiled.h
#	Gems/WhiteBox/Code/Source/WhiteBoxUnsupported_precompiled.h
#	Gems/WhiteBox/Code/Source/WhiteBox_precompiled.h
2021-07-16 15:42:37 -07:00

334 lines
10 KiB
C++

/*
* 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 "UiEditorAnimationBus.h"
#include "UiEditorDLLBus.h"
#include "UiAnimViewSequenceManager.h"
#include "UiAnimViewUndo.h"
#include "AnimationContext.h"
#include "GameEngine.h"
#include <LyShine/Bus/UiCanvasBus.h>
CUiAnimViewSequenceManager* CUiAnimViewSequenceManager::s_instance = nullptr;
////////////////////////////////////////////////////////////////////////////
CUiAnimViewSequenceManager::CUiAnimViewSequenceManager()
: m_nextSequenceId(0)
, m_animationSystem(nullptr)
{
GetIEditor()->RegisterNotifyListener(this);
UiEditorAnimationBus::Handler::BusConnect();
// get the undo stack from the UI editor, if no editor is active this will be null
UndoStack* undoStack = nullptr;
EBUS_EVENT_RESULT(undoStack, UiEditorDLLBus, GetActiveUndoStack);
m_undoManager.SetActiveUndoStack(undoStack);
s_instance = this;
m_animationContext = new CUiAnimationContext;
}
////////////////////////////////////////////////////////////////////////////
CUiAnimViewSequenceManager::~CUiAnimViewSequenceManager()
{
GetIEditor()->UnregisterNotifyListener(this);
UiEditorAnimationBus::Handler::BusDisconnect();
delete m_animationContext;
s_instance = nullptr;
}
////////////////////////////////////////////////////////////////////////////
void CUiAnimViewSequenceManager::OnEditorNotifyEvent([[maybe_unused]] EEditorNotifyEvent event)
{
}
////////////////////////////////////////////////////////////////////////////
CUiAnimViewSequence* CUiAnimViewSequenceManager::GetSequenceByName(QString name) const
{
for (auto iter = m_sequences.begin(); iter != m_sequences.end(); ++iter)
{
CUiAnimViewSequence* pSequence = (*iter).get();
if (pSequence->GetName() == name)
{
return pSequence;
}
}
return nullptr;
}
////////////////////////////////////////////////////////////////////////////
CUiAnimViewSequence* CUiAnimViewSequenceManager::GetSequenceByAnimSequence(IUiAnimSequence* pAnimSequence) const
{
for (auto iter = m_sequences.begin(); iter != m_sequences.end(); ++iter)
{
CUiAnimViewSequence* pSequence = (*iter).get();
if (pSequence->m_pAnimSequence == pAnimSequence)
{
return pSequence;
}
}
return nullptr;
}
////////////////////////////////////////////////////////////////////////////
CUiAnimViewSequence* CUiAnimViewSequenceManager::GetSequenceByIndex(unsigned int index) const
{
if (index >= m_sequences.size())
{
return nullptr;
}
return m_sequences[index].get();
}
////////////////////////////////////////////////////////////////////////////
void CUiAnimViewSequenceManager::CreateSequence(QString name)
{
CUiAnimViewSequence* pExistingSequence = GetSequenceByName(name);
if (pExistingSequence)
{
return;
}
UiAnimUndo undo("Create Animation Sequence");
IUiAnimationSystem* animationSystem = nullptr;
EBUS_EVENT_RESULT(animationSystem, UiEditorAnimationBus, GetAnimationSystem);
IUiAnimSequence* pNewUiAnimationSequence = animationSystem->CreateSequence(name.toUtf8().data(), false, ++m_nextSequenceId);
CUiAnimViewSequence* pNewSequence = new CUiAnimViewSequence(pNewUiAnimationSequence);
m_sequences.push_back(std::unique_ptr<CUiAnimViewSequence>(pNewSequence));
UiAnimUndo::Record(new CUndoSequenceAdd(pNewSequence));
SortSequences();
OnSequenceAdded(pNewSequence);
}
////////////////////////////////////////////////////////////////////////////
void CUiAnimViewSequenceManager::DeleteSequence(CUiAnimViewSequence* pSequence)
{
assert(pSequence);
IUiAnimationSystem* animationSystem = nullptr;
EBUS_EVENT_RESULT(animationSystem, UiEditorAnimationBus, GetAnimationSystem);
uint32 animSequenceId = 0;
IUiAnimSequence* animSequence = nullptr;
if (pSequence)
{
animSequenceId = pSequence->GetSequenceId();
animSequence = animationSystem->FindSequenceById(animSequenceId);
// this is to solve an issue of mismatched calls to the sequence from the undo system
pSequence->BeginUndoTransaction();
UiAnimUndo undo("Delete Animation Sequence");
UiAnimUndo::Record(new CUndoSequenceRemove(pSequence));
SortSequences();
OnSequenceRemoved(pSequence);
}
if (animSequence)
{
// animSequence->SetOwner(nullptr);
}
}
////////////////////////////////////////////////////////////////////////////
void CUiAnimViewSequenceManager::SortSequences()
{
std::stable_sort(m_sequences.begin(), m_sequences.end(),
[](const std::unique_ptr<CUiAnimViewSequence>& a, const std::unique_ptr<CUiAnimViewSequence>& b) -> bool
{
QString aName = a.get()->GetName();
QString bName = b.get()->GetName();
return aName < bName;
});
}
////////////////////////////////////////////////////////////////////////////
void CUiAnimViewSequenceManager::OnSequenceAdded(CUiAnimViewSequence* pSequence)
{
for (auto iter = m_listeners.begin(); iter != m_listeners.end(); ++iter)
{
(*iter)->OnSequenceAdded(pSequence);
}
UiAnimUndoManager::Get()->AddListener(pSequence);
}
////////////////////////////////////////////////////////////////////////////
void CUiAnimViewSequenceManager::OnSequenceRemoved(CUiAnimViewSequence* pSequence)
{
UiAnimUndoManager::Get()->RemoveListener(pSequence);
for (auto iter = m_listeners.begin(); iter != m_listeners.end(); ++iter)
{
(*iter)->OnSequenceRemoved(pSequence);
}
}
////////////////////////////////////////////////////////////////////////////
CUiAnimViewSequenceManager* CUiAnimViewSequenceManager::GetSequenceManager()
{
return s_instance;
}
////////////////////////////////////////////////////////////////////////////
void CUiAnimViewSequenceManager::Create()
{
new CUiAnimViewSequenceManager;
}
////////////////////////////////////////////////////////////////////////////
void CUiAnimViewSequenceManager::Destroy()
{
delete s_instance;
}
//////////////////////////////////////////////////////////////////////////
CUiAnimationContext* CUiAnimViewSequenceManager::GetAnimationContext()
{
return m_animationContext;
}
//////////////////////////////////////////////////////////////////////////
IUiAnimationSystem* CUiAnimViewSequenceManager::GetAnimationSystem()
{
return m_animationSystem;
}
//////////////////////////////////////////////////////////////////////////
CUiAnimViewSequence* CUiAnimViewSequenceManager::GetCurrentSequence()
{
return m_animationContext->GetSequence();
}
//////////////////////////////////////////////////////////////////////////
void CUiAnimViewSequenceManager::ActiveCanvasChanged()
{
// Get the animation system from the active canvas, this must be updated if the UI Editor
// switches to a different canvas
AZ::EntityId canvasId;
EBUS_EVENT_RESULT(canvasId, UiEditorDLLBus, GetActiveCanvasId);
// Note: the canvasId may be invalid if the UI Editor window has closed in which case
// the GetAnimationSystem event does nothing
m_animationSystem = nullptr;
EBUS_EVENT_ID_RESULT(m_animationSystem, canvasId, UiCanvasBus, GetAnimationSystem);
// get the undo stack from the UI editor, if no editor is active this will be null
UndoStack* undoStack = nullptr;
EBUS_EVENT_RESULT(undoStack, UiEditorDLLBus, GetActiveUndoStack);
UiAnimUndoManager::Get()->SetActiveUndoStack(undoStack);
m_animationContext->ActiveCanvasChanged();
DeleteAllSequences();
CreateSequencesFromAnimationSystem();
// tell listeners in UI animation system the active canvas has changed
EBUS_EVENT(UiEditorAnimListenerBus, OnActiveCanvasChanged);
}
////////////////////////////////////////////////////////////////////////////
void CUiAnimViewSequenceManager::DeleteAllSequences()
{
// This is called when the active canvas changes
while (m_sequences.size() > 0)
{
auto iterator = m_sequences.begin();
CUiAnimViewSequence* pSequence = iterator->get();
assert(pSequence);
// UI_ANIMATION_REVISIT,some clients of OnSequenceRemoved expect the pSequence to be still valid
// so call before the erase
if (pSequence)
{
OnSequenceRemoved(pSequence);
}
m_sequences.erase(iterator);
}
// UI_ANIMATION_REVISIT,some clients of OnSequenceRemoved expect the pSequence to be removed
// from the list already so call again
OnSequenceRemoved(nullptr);
}
////////////////////////////////////////////////////////////////////////////
void CUiAnimViewSequenceManager::CreateSequencesFromAnimationSystem()
{
IUiAnimationSystem* animationSystem = nullptr;
EBUS_EVENT_RESULT(animationSystem, UiEditorAnimationBus, GetAnimationSystem);
if (!animationSystem)
{
return;
}
int numSequences = animationSystem->GetNumSequences();
for (int sequenceIndex = 0; sequenceIndex < numSequences; ++sequenceIndex)
{
IUiAnimSequence* sequence = animationSystem->GetSequence(sequenceIndex);
CUiAnimViewSequence* pNewSequence = new CUiAnimViewSequence(sequence);
m_sequences.push_back(std::unique_ptr<CUiAnimViewSequence>(pNewSequence));
pNewSequence->Load();
SortSequences();
OnSequenceAdded(pNewSequence);
}
}
////////////////////////////////////////////////////////////////////////////
CUiAnimViewAnimNodeBundle CUiAnimViewSequenceManager::GetAllRelatedAnimNodes(const AZ::Entity* pEntityObject) const
{
CUiAnimViewAnimNodeBundle nodeBundle;
const uint sequenceCount = GetCount();
for (uint sequenceIndex = 0; sequenceIndex < sequenceCount; ++sequenceIndex)
{
CUiAnimViewSequence* pSequence = GetSequenceByIndex(sequenceIndex);
nodeBundle.AppendAnimNodeBundle(pSequence->GetAllOwnedNodes(pEntityObject));
}
return nodeBundle;
}
////////////////////////////////////////////////////////////////////////////
CUiAnimViewAnimNode* CUiAnimViewSequenceManager::GetActiveAnimNode(const AZ::Entity* pEntityObject) const
{
CUiAnimViewAnimNodeBundle nodeBundle = GetAllRelatedAnimNodes(pEntityObject);
const uint nodeCount = nodeBundle.GetCount();
for (uint nodeIndex = 0; nodeIndex < nodeCount; ++nodeIndex)
{
CUiAnimViewAnimNode* pAnimNode = nodeBundle.GetNode(nodeIndex);
if (pAnimNode->IsActive())
{
return pAnimNode;
}
}
return nullptr;
}