Files
o3de/Gems/Maestro/Code/Source/Components/SequenceAgent.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

300 lines
14 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 "SequenceAgent.h"
#include <AzCore/Math/Color.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Component/Entity.h>
namespace Maestro
{
namespace SequenceAgentHelper
{
template <typename T>
AZ_INLINE void DoSafeSet(AZ::BehaviorEBus::VirtualProperty* prop, AZ::EntityId entityId, T& data)
{
if (!prop->m_setter)
{
return;
}
if (prop->m_setter->m_event)
{
prop->m_setter->m_event->Invoke(entityId, data);
}
else if (prop->m_setter->m_broadcast)
{
prop->m_setter->m_broadcast->Invoke(data);
}
}
template <typename T>
AZ_INLINE void DoSafeGet(AZ::BehaviorEBus::VirtualProperty* prop, AZ::EntityId entityId, T& data)
{
if (!prop->m_getter)
{
return;
}
if (prop->m_getter->m_event)
{
prop->m_getter->m_event->InvokeResult(data, entityId);
}
else if (prop->m_getter->m_broadcast)
{
prop->m_getter->m_broadcast->InvokeResult(data);
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////
void SequenceAgent::CacheAllVirtualPropertiesFromBehaviorContext()
{
AZ::BehaviorContext* behaviorContext = nullptr;
EBUS_EVENT_RESULT(behaviorContext, AZ::ComponentApplicationBus, GetBehaviorContext);
AZ::Entity::ComponentArrayType entityComponents;
GetEntityComponents(entityComponents);
m_addressToBehaviorVirtualPropertiesMap.clear();
for (AZ::Component* component : entityComponents)
{
auto findClassIter = behaviorContext->m_typeToClassMap.find(GetComponentTypeUuid(*component));
if (findClassIter != behaviorContext->m_typeToClassMap.end())
{
AZ::BehaviorClass* behaviorClass = findClassIter->second;
// go through all ebuses for this class and find all virtual properties
for (auto reqBusName = behaviorClass->m_requestBuses.begin(); reqBusName != behaviorClass->m_requestBuses.end(); reqBusName++)
{
auto findBusIter = behaviorContext->m_ebuses.find(*reqBusName);
if (findBusIter != behaviorContext->m_ebuses.end())
{
AZ::BehaviorEBus* behaviorEbus = findBusIter->second;
for (auto virtualPropertyIter = behaviorEbus->m_virtualProperties.begin(); virtualPropertyIter != behaviorEbus->m_virtualProperties.end(); virtualPropertyIter++)
{
Maestro::SequenceComponentRequests::AnimatablePropertyAddress address(component->GetId(), virtualPropertyIter->first);
m_addressToBehaviorVirtualPropertiesMap[address] = &virtualPropertyIter->second;
}
// Check for the GetAssetDuration event is present and cache it
for (auto eventIter = behaviorEbus->m_events.begin(); eventIter != behaviorEbus->m_events.end(); eventIter++)
{
if (eventIter->first == "GetAssetDuration")
{
AZ::BehaviorEBusEventSender* sender = &eventIter->second;
// Sanity check, Shouldn't be able to get here.
if (nullptr == sender)
{
AZ_Error("SequenceAgent", false, "EBus %s, GetAssetDuration sender is null.", behaviorEbus->m_name.c_str());
continue;
}
// Sanity check, m_broadcast should always be valid.
if (nullptr == sender->m_broadcast)
{
AZ_Error("SequenceAgent", false, "EBus %s, GetAssetDuration sender->m_broadcast is null.", behaviorEbus->m_name.c_str());
continue;
}
// GetAssetDuration shoulder return a float.
if (!sender->m_broadcast->HasResult())
{
AZ_Error("SequenceAgent", false, "EBus %s, GetAssetDuration should return result", behaviorEbus->m_name.c_str());
continue;
}
// GetAssetDuration should take an asset id.
if (sender->m_broadcast->GetNumArguments() != 1)
{
AZ_Error("SequenceAgent", false, "EBus %s, GetAssetDuration should take one argument, an asset id.", behaviorEbus->m_name.c_str());
continue;
}
m_addressToGetAssetDurationMap[component->GetId()] = sender;
}
}
}
}
}
}
}
/////////////////////////////////////////////////////////////////////////////////////////////
AZ::Uuid SequenceAgent::GetVirtualPropertyTypeId(const Maestro::SequenceComponentRequests::AnimatablePropertyAddress& animatableAddress) const
{
AZ::Uuid retTypeUuid = AZ::Uuid::CreateNull();
auto findIter = m_addressToBehaviorVirtualPropertiesMap.find(animatableAddress);
if (findIter != m_addressToBehaviorVirtualPropertiesMap.end())
{
if (findIter->second->m_getter->m_event)
{
retTypeUuid = findIter->second->m_getter->m_event->GetResult()->m_typeId;
}
else if(findIter->second->m_getter->m_broadcast)
{
retTypeUuid = findIter->second->m_getter->m_broadcast->GetResult()->m_typeId;
}
}
return retTypeUuid;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
bool SequenceAgent::SetAnimatedPropertyValue(AZ::EntityId entityId, const Maestro::SequenceComponentRequests::AnimatablePropertyAddress& animatableAddress, const Maestro::SequenceComponentRequests::AnimatedValue& value)
{
bool changed = false;
const AZ::Uuid propertyTypeId = GetVirtualPropertyTypeId(animatableAddress);
auto findIter = m_addressToBehaviorVirtualPropertiesMap.find(animatableAddress);
if (findIter != m_addressToBehaviorVirtualPropertiesMap.end())
{
if (propertyTypeId == AZ::Vector3::TYPEINFO_Uuid())
{
AZ::Vector3 vector3Value(.0f, .0f, .0f);
value.GetValue(vector3Value); // convert the generic value to a Vector3
SequenceAgentHelper::DoSafeSet(findIter->second, entityId, vector3Value);
changed = true;
}
else if (propertyTypeId == AZ::Color::TYPEINFO_Uuid())
{
AZ::Vector3 vector3Value(.0f, .0f, .0f);
value.GetValue(vector3Value); // convert the generic value to a Vector3
AZ::Color colorValue(AZ::Color::CreateFromVector3(vector3Value));
SequenceAgentHelper::DoSafeSet(findIter->second, entityId, colorValue);
changed = true;
}
else if (propertyTypeId == AZ::Quaternion::TYPEINFO_Uuid())
{
AZ::Quaternion quaternionValue(AZ::Quaternion::CreateIdentity());
value.GetValue(quaternionValue);
SequenceAgentHelper::DoSafeSet(findIter->second, entityId, quaternionValue);
changed = true;
}
else if (propertyTypeId == AZ::AzTypeInfo<bool>::Uuid())
{
bool boolValue = true;
value.GetValue(boolValue); // convert the generic value to a bool
SequenceAgentHelper::DoSafeSet(findIter->second, entityId, boolValue);
changed = true;
}
else if (propertyTypeId == AZ::AzTypeInfo<AZ::s32>::Uuid())
{
AZ::s32 s32value = 0;
value.GetValue(s32value);
findIter->second->m_setter->m_event->Invoke(entityId, s32value);
changed = true;
}
else if (propertyTypeId == AZ::AzTypeInfo<AZ::u32>::Uuid())
{
AZ::u32 u32value = 0;
value.GetValue(u32value);
findIter->second->m_setter->m_event->Invoke(entityId, u32value);
changed = true;
}
else if (propertyTypeId == AZ::AzTypeInfo<AZ::Data::AssetId>::Uuid())
{
AZ::Data::AssetId assetIdValue;
value.GetValue(assetIdValue);
findIter->second->m_setter->m_event->Invoke(entityId, assetIdValue);
changed = true;
}
else
{
// fall-through default is to cast to float
float floatValue = .0f;
value.GetValue(floatValue); // convert the generic value to a float
SequenceAgentHelper::DoSafeSet(findIter->second, entityId, floatValue);
changed = true;
}
}
return changed;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
void SequenceAgent::GetAnimatedPropertyValue(Maestro::SequenceComponentRequests::AnimatedValue& returnValue, AZ::EntityId entityId, const Maestro::SequenceComponentRequests::AnimatablePropertyAddress& animatableAddress)
{
const AZ::Uuid propertyTypeId = GetVirtualPropertyTypeId(animatableAddress);
auto findIter = m_addressToBehaviorVirtualPropertiesMap.find(animatableAddress);
if (findIter != m_addressToBehaviorVirtualPropertiesMap.end())
{
if (propertyTypeId == AZ::Vector3::TYPEINFO_Uuid())
{
AZ::Vector3 vector3Value(AZ::Vector3::CreateZero());
SequenceAgentHelper::DoSafeGet(findIter->second, entityId, vector3Value);
returnValue.SetValue(vector3Value);
}
else if (propertyTypeId == AZ::Color::TYPEINFO_Uuid())
{
AZ::Color colorValue(AZ::Color::CreateZero());
SequenceAgentHelper::DoSafeGet(findIter->second, entityId, colorValue);
returnValue.SetValue((AZ::Vector3)colorValue);
}
else if (propertyTypeId == AZ::Quaternion::TYPEINFO_Uuid())
{
AZ::Quaternion quaternionValue(AZ::Quaternion::CreateIdentity());
SequenceAgentHelper::DoSafeGet(findIter->second, entityId, quaternionValue);
returnValue.SetValue(quaternionValue);
}
else if (propertyTypeId == AZ::AzTypeInfo<bool>::Uuid())
{
bool boolValue = false;
SequenceAgentHelper::DoSafeGet(findIter->second, entityId, boolValue);
returnValue.SetValue(boolValue);
}
else if (propertyTypeId == AZ::AzTypeInfo<AZ::s32>::Uuid())
{
AZ::s32 s32Value;
findIter->second->m_getter->m_event->InvokeResult(s32Value, entityId);
returnValue.SetValue(s32Value);
}
else if (propertyTypeId == AZ::AzTypeInfo<AZ::u32>::Uuid())
{
AZ::u32 u32Value;
findIter->second->m_getter->m_event->InvokeResult(u32Value, entityId);
returnValue.SetValue(u32Value);
}
else if (propertyTypeId == AZ::AzTypeInfo<AZ::Data::AssetId>::Uuid())
{
AZ::Data::AssetId assetIdValue;
findIter->second->m_getter->m_event->InvokeResult(assetIdValue, entityId);
returnValue.SetValue(assetIdValue);
}
else
{
// fall-through default is to cast to float
float floatValue = .0f;
SequenceAgentHelper::DoSafeGet(findIter->second, entityId, floatValue);
returnValue.SetValue(floatValue);
}
}
}
void SequenceAgent::GetAssetDuration(Maestro::SequenceComponentRequests::AnimatedValue& returnValue, AZ::ComponentId componentId, const AZ::Data::AssetId& assetId)
{
auto findIter = m_addressToGetAssetDurationMap.find(componentId);
if (findIter != m_addressToGetAssetDurationMap.end())
{
if (nullptr != findIter->second)
{
AZ::BehaviorEBusEventSender* sender = findIter->second;
if (nullptr != sender)
{
AZ::BehaviorMethod* broadcast = sender->m_broadcast;
if (nullptr != broadcast)
{
float floatValue = 0.0f;
broadcast->InvokeResult(floatValue, assetId);
returnValue.SetValue(floatValue);
}
}
}
}
}
}// namespace Maestro