/* * All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution (the "License"). All use of this software is governed by the License, * or, if provided, by the license below or the license accompanying this file. Do not * remove or modify any license notices. This file is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ // Original file Copyright Crytek GMBH or its affiliates, used under license. #include "Maestro_precompiled.h" #include #include "AnimPostFXNode.h" #include "AnimSplineTrack.h" #include "CompoundSplineTrack.h" #include "BoolTrack.h" #include "IPostEffectGroup.h" #include "Maestro/Types/AnimNodeType.h" #include "Maestro/Types/AnimParamType.h" #include "Maestro/Types/AnimValueType.h" #include ////////////////////////////////////////////////////////////////////////// //! class CFXNodeDescription : public _i_reference_target_t { public: //----------------------------------------------------------------------------- //! class CControlParamBase : public _i_reference_target_t { public: CControlParamBase(){} virtual void SetDefault(float val) = 0; virtual void SetDefault(bool val) = 0; virtual void SetDefault(Vec4 val) = 0; virtual void GetDefault(float& val) const = 0; virtual void GetDefault(bool& val) const = 0; virtual void GetDefault(Vec4& val) const = 0; string m_name; protected: virtual ~CControlParamBase(){} }; //----------------------------------------------------------------------------- //! template class TControlParam : public CControlParamBase { public: virtual void SetDefault(float val) { assert(0); } virtual void SetDefault(bool val) { assert(0); } virtual void SetDefault(Vec4 val) { assert(0); } virtual void GetDefault(float& val) const { assert(0); } virtual void GetDefault(bool& val) const { assert(0); } virtual void GetDefault(Vec4& val) const { assert(0); } protected: virtual ~TControlParam(){} T m_defaultValue; }; //----------------------------------------------------------------------------- //! CFXNodeDescription() {} //----------------------------------------------------------------------------- //! template void AddSupportedParam(const char* sName, AnimValueType eValueType, const char* sControlName, T defaultValue) { CAnimNode::SParamInfo param; param.name = sName; param.paramType = static_cast(static_cast(AnimParamType::User) + static_cast(m_nodeParams.size())); param.valueType = eValueType; m_nodeParams.push_back(param); TControlParam* control = new TControlParam; control->m_name = sControlName; control->SetDefault(defaultValue); m_controlParams.push_back(control); } //----------------------------------------------------------------------------- //! StaticInstance> m_nodeParams; StaticInstance >> m_controlParams; }; //----------------------------------------------------------------------------- template<> void CFXNodeDescription::TControlParam::SetDefault(float val) { m_defaultValue = val; } template<> void CFXNodeDescription::TControlParam::SetDefault(bool val) { m_defaultValue = val; } template<> void CFXNodeDescription::TControlParam::SetDefault(Vec4 val) { m_defaultValue = val; } template<> void CFXNodeDescription::TControlParam::GetDefault(float& val) const { val = m_defaultValue; } template<> void CFXNodeDescription::TControlParam::GetDefault(bool& val) const { val = m_defaultValue; } template<> void CFXNodeDescription::TControlParam::GetDefault(Vec4& val) const { val = m_defaultValue; } //----------------------------------------------------------------------------- StaticInstance CAnimPostFXNode::s_fxNodeDescriptions; bool CAnimPostFXNode::s_initialized = false; //----------------------------------------------------------------------------- CAnimPostFXNode::CAnimPostFXNode() : CAnimPostFXNode(0, AnimNodeType::Invalid, nullptr) { } //----------------------------------------------------------------------------- CAnimPostFXNode::CAnimPostFXNode(const int id, AnimNodeType nodeType, CFXNodeDescription* pDesc) : CAnimNode(id, nodeType) , m_pDescription(pDesc) { } //----------------------------------------------------------------------------- void CAnimPostFXNode::Initialize() { if (!s_initialized) { s_initialized = true; ////////////////////////////////////////////////////////////////////////// //! Radial Blur { CFXNodeDescription* pDesc = new CFXNodeDescription(); s_fxNodeDescriptions[AnimNodeType::RadialBlur] = pDesc; pDesc->m_nodeParams.reserve(4); pDesc->m_controlParams.reserve(4); pDesc->AddSupportedParam("Amount", AnimValueType::Float, "FilterRadialBlurring_Amount", 0.0f); pDesc->AddSupportedParam("ScreenPosX", AnimValueType::Float, "FilterRadialBlurring_ScreenPosX", 0.5f); pDesc->AddSupportedParam("ScreenPosY", AnimValueType::Float, "FilterRadialBlurring_ScreenPosY", 0.5f); pDesc->AddSupportedParam("BlurringRadius", AnimValueType::Float, "FilterRadialBlurring_Radius", 1.0f); } ////////////////////////////////////////////////////////////////////////// //! Color Correction { CFXNodeDescription* pDesc = new CFXNodeDescription(); s_fxNodeDescriptions[AnimNodeType::ColorCorrection] = pDesc; pDesc->m_nodeParams.reserve(8); pDesc->m_controlParams.reserve(8); pDesc->AddSupportedParam("Cyan", AnimValueType::Float, "Global_User_ColorC", 0.0f); pDesc->AddSupportedParam("Magenta", AnimValueType::Float, "Global_User_ColorM", 0.0f); pDesc->AddSupportedParam("Yellow", AnimValueType::Float, "Global_User_ColorY", 0.0f); pDesc->AddSupportedParam("Luminance", AnimValueType::Float, "Global_User_ColorK", 0.0f); pDesc->AddSupportedParam("Brightness", AnimValueType::Float, "Global_User_Brightness", 1.0f); pDesc->AddSupportedParam("Contrast", AnimValueType::Float, "Global_User_Contrast", 1.0f); pDesc->AddSupportedParam("Saturation", AnimValueType::Float, "Global_User_Saturation", 1.0f); pDesc->AddSupportedParam("Hue", AnimValueType::Float, "Global_User_ColorHue", 0.0f); } ////////////////////////////////////////////////////////////////////////// //! Depth of Field { CFXNodeDescription* pDesc = new CFXNodeDescription(); s_fxNodeDescriptions[AnimNodeType::DepthOfField] = pDesc; pDesc->m_nodeParams.reserve(4); pDesc->m_controlParams.reserve(4); pDesc->AddSupportedParam("Enable", AnimValueType::Bool, "Dof_User_Active", false); pDesc->AddSupportedParam("FocusDistance", AnimValueType::Float, "Dof_User_FocusDistance", 3.5f); pDesc->AddSupportedParam("FocusRange", AnimValueType::Float, "Dof_User_FocusRange", 5.0f); pDesc->AddSupportedParam("BlurAmount", AnimValueType::Float, "Dof_User_BlurAmount", 1.0f); } ////////////////////////////////////////////////////////////////////////// //! Shadow setup - expose couple shadow controls to cinematics { CFXNodeDescription* pDesc = new CFXNodeDescription(); s_fxNodeDescriptions[AnimNodeType::ShadowSetup] = pDesc; pDesc->m_nodeParams.reserve(1); pDesc->m_controlParams.reserve(1); pDesc->AddSupportedParam("GSMCache", AnimValueType::Bool, "GSMCacheParam", true); } } } //----------------------------------------------------------------------------- /*static*/ CFXNodeDescription* CAnimPostFXNode::GetFXNodeDescription(AnimNodeType nodeType) { CFXNodeDescription* retDescription = nullptr; CAnimPostFXNode::Initialize(); FxNodeDescriptionMap::iterator itr = s_fxNodeDescriptions.find(nodeType); if (itr != s_fxNodeDescriptions.end()) { retDescription = itr->second; } return retDescription; } //----------------------------------------------------------------------------- CAnimNode* CAnimPostFXNode::CreateNode(const int id, AnimNodeType nodeType) { CAnimNode* retNode = nullptr; CFXNodeDescription* pDesc = GetFXNodeDescription(nodeType); if (pDesc) { retNode = aznew CAnimPostFXNode(id, nodeType, pDesc); static_cast(retNode)->m_nodeType = nodeType; } return retNode; } //----------------------------------------------------------------------------- void CAnimPostFXNode::InitPostLoad(IAnimSequence* sequence) { CAnimNode::InitPostLoad(sequence); // For AZ::Serialization, m_nodeType will have be reflected and deserialized. Find the appropriate FXNodeDescription for it // and store the pointer m_pDescription = GetFXNodeDescription(m_nodeType); if (!m_pDescription) { // This is not ideal - we should never get here unless someone is tampering with data. We can't remove the node at this point, // we can't use a defatult description without crashing later, so we simply assert. AZ_Assert(false, "Unrecognized PostFX nodeType in Track View node %s. Please remove this node from the sequence.", m_name.c_str()); } } //----------------------------------------------------------------------------- void CAnimPostFXNode::SerializeAnims(XmlNodeRef& xmlNode, bool bLoading, bool bLoadEmptyTracks) { if (bLoading) { int paramIdVersion = 0; xmlNode->getAttr("ParamIdVersion", paramIdVersion); // Fix old param types if (paramIdVersion <= 2) { int num = xmlNode->getChildCount(); for (int i = 0; i < num; ++i) { XmlNodeRef trackNode = xmlNode->getChild(i); CAnimParamType paramType; paramType.Serialize(trackNode, true); // Don't use APARAM_USER because it could change in newer versions // CAnimNode::SerializeAnims will then take care of that static const unsigned int OLD_APARAM_USER = 100; paramType = static_cast(static_cast(paramType.GetType()) + OLD_APARAM_USER); paramType.Serialize(trackNode, false); } } } CAnimNode::SerializeAnims(xmlNode, bLoading, bLoadEmptyTracks); } //----------------------------------------------------------------------------- unsigned int CAnimPostFXNode::GetParamCount() const { return m_pDescription->m_nodeParams.size(); } //----------------------------------------------------------------------------- CAnimParamType CAnimPostFXNode::GetParamType(unsigned int nIndex) const { if (nIndex >= 0 && nIndex < (int)m_pDescription->m_nodeParams.size()) { return m_pDescription->m_nodeParams[nIndex].paramType; } return AnimParamType::Invalid; } //----------------------------------------------------------------------------- bool CAnimPostFXNode::GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const { for (size_t i = 0; i < m_pDescription->m_nodeParams.size(); ++i) { if (m_pDescription->m_nodeParams[i].paramType == paramId) { info = m_pDescription->m_nodeParams[i]; return true; } } return false; } //----------------------------------------------------------------------------- void CAnimPostFXNode::CreateDefaultTracks() { for (size_t i = 0; i < m_pDescription->m_nodeParams.size(); ++i) { IAnimTrack* pTrack = CreateTrackInternal(m_pDescription->m_nodeParams[i].paramType, eAnimCurveType_BezierFloat, m_pDescription->m_nodeParams[i].valueType); //Setup default value AnimValueType valueType = m_pDescription->m_nodeParams[i].valueType; if (valueType == AnimValueType::Float) { C2DSplineTrack* pFloatTrack = static_cast(pTrack); float val(0); m_pDescription->m_controlParams[i]->GetDefault(val); pFloatTrack->SetDefaultValue(Vec2(0, val)); } else if (valueType == AnimValueType::Bool) { CBoolTrack* pBoolTrack = static_cast(pTrack); bool val = false; m_pDescription->m_controlParams[i]->GetDefault(val); pBoolTrack->SetDefaultValue(val); } else if (valueType == AnimValueType::Vector4) { CCompoundSplineTrack* pCompoundTrack = static_cast(pTrack); Vec4 val(0.0f, 0.0f, 0.0f, 0.0f); m_pDescription->m_controlParams[i]->GetDefault(val); pCompoundTrack->SetValue(0.0f, val, true); } } } //----------------------------------------------------------------------------- void CAnimPostFXNode::Animate(SAnimContext& ac) { for (size_t i = 0; i < m_tracks.size(); ++i) { IAnimTrack* pTrack = m_tracks[i].get(); assert(pTrack); size_t paramIndex = (size_t)static_cast(m_tracks[i]->GetParameterType().GetType()) - static_cast(AnimParamType::User); assert(paramIndex < m_pDescription->m_nodeParams.size()); if (pTrack->GetFlags() & IAnimTrack::eAnimTrackFlags_Disabled) { continue; } if (pTrack->IsMasked(ac.trackMask)) { continue; } AnimValueType valueType = m_pDescription->m_nodeParams[paramIndex].valueType; // sorry: quick & dirty solution for c2 shipping - custom type handling for shadows - make this properly after shipping if (GetType() == AnimNodeType::ShadowSetup && valueType == AnimValueType::Bool) { bool val(false); pTrack->GetValue(ac.time, val); gEnv->p3DEngine->SetShadowsGSMCache(val); } else if (valueType == AnimValueType::Float) { float val(0); pTrack->GetValue(ac.time, val); gEnv->p3DEngine->GetPostEffectBaseGroup()->SetParam(m_pDescription->m_controlParams[paramIndex]->m_name.c_str(), val); } else if (valueType == AnimValueType::Bool) { bool val(false); pTrack->GetValue(ac.time, val); gEnv->p3DEngine->GetPostEffectBaseGroup()->SetParam(m_pDescription->m_controlParams[paramIndex]->m_name.c_str(), (val ? 1.f : 0.f)); } else if (valueType == AnimValueType::Vector4) { Vec4 val(0.0f, 0.0f, 0.0f, 0.0f); static_cast(pTrack)->GetValue(ac.time, val); gEnv->p3DEngine->GetPostEffectBaseGroup()->SetParam(m_pDescription->m_controlParams[paramIndex]->m_name.c_str(), val); } } } //----------------------------------------------------------------------------- void CAnimPostFXNode::OnReset() { CAnimNode::OnReset(); // Reset each postFX param to its default. for (size_t i = 0; i < m_tracks.size(); ++i) { IAnimTrack* pTrack = m_tracks[i].get(); assert(pTrack); size_t paramIndex = (size_t)static_cast(m_tracks[i]->GetParameterType().GetType()) - static_cast(AnimParamType::User); assert(paramIndex < m_pDescription->m_nodeParams.size()); AnimValueType valueType = m_pDescription->m_nodeParams[paramIndex].valueType; // sorry: quick & dirty solution for c2 shipping - custom type handling for shadows - make this properly after shipping if (GetType() == AnimNodeType::ShadowSetup && valueType == AnimValueType::Bool) { bool val(false); m_pDescription->m_controlParams[paramIndex]->GetDefault(val); gEnv->p3DEngine->SetShadowsGSMCache(val); } else if (valueType == AnimValueType::Float) { float val(0); m_pDescription->m_controlParams[paramIndex]->GetDefault(val); gEnv->p3DEngine->GetPostEffectBaseGroup()->SetParam(m_pDescription->m_controlParams[paramIndex]->m_name.c_str(), val); } else if (valueType == AnimValueType::Bool) { bool val(false); m_pDescription->m_controlParams[paramIndex]->GetDefault(val); gEnv->p3DEngine->GetPostEffectBaseGroup()->SetParam(m_pDescription->m_controlParams[paramIndex]->m_name.c_str(), (val ? 1.f : 0.f)); } else if (valueType == AnimValueType::Vector4) { Vec4 val(0.0f, 0.0f, 0.0f, 0.0f); m_pDescription->m_controlParams[paramIndex]->GetDefault(val); gEnv->p3DEngine->GetPostEffectBaseGroup()->SetParam(m_pDescription->m_controlParams[paramIndex]->m_name.c_str(), val); } } } ////////////////////////////////////////////////////////////////////////// void CAnimPostFXNode::Reflect(AZ::SerializeContext* serializeContext) { serializeContext->Class() ->Version(1); } ////////////////////////////////////////////////////////////////////////// /*static*/ void CAnimPostFXNode::ClearControlParams() { s_fxNodeDescriptions.clear(); }