/* * 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 "MaterialNode.h" #include "AnimTrack.h" #include #include #include #include #include "AnimSplineTrack.h" #include "CompoundSplineTrack.h" #include "Maestro/Types/AnimNodeType.h" #include "Maestro/Types/AnimValueType.h" #include "Maestro/Types/AnimParamType.h" // Don't remove or the console builds will break! #define s_nodeParamsInitialized s_nodeParamsInitializedMat #define s_nodeParams s_nodeParamsMat #define AddSupportedParam AddSupportedParamMat namespace { bool s_nodeParamsInitialized = false; StaticInstance> s_nodeParams; void AddSupportedParam(const char* sName, AnimParamType paramId, AnimValueType valueType) { CAnimNode::SParamInfo param; param.name = sName; param.paramType = paramId; param.valueType = valueType; s_nodeParams.push_back(param); } } enum EMaterialNodeParam { MTL_PARAM_SHADER_PARAM1 = static_cast(AnimParamType::User) + 100, }; ////////////////////////////////////////////////////////////////////////// void CAnimMaterialNode::InitializeTrack(IAnimTrack* pTrack, const CAnimParamType& paramType) { if (paramType == AnimParamType::MaterialOpacity) { pTrack->SetKeyValueRange(0.0f, 100.f); } else if (paramType == AnimParamType::MaterialSmoothness) { pTrack->SetKeyValueRange(0.0f, 255.f); } } ////////////////////////////////////////////////////////////////////////// CAnimMaterialNode::CAnimMaterialNode() : CAnimMaterialNode(0) { } ////////////////////////////////////////////////////////////////////////// CAnimMaterialNode::CAnimMaterialNode(const int id) : CAnimNode(id, AnimNodeType::Material) { SetFlags(GetFlags() | eAnimNodeFlags_CanChangeName); CAnimMaterialNode::Initialize(); } ////////////////////////////////////////////////////////////////////////// void CAnimMaterialNode::Initialize() { if (!s_nodeParamsInitialized) { s_nodeParamsInitialized = true; s_nodeParams.reserve(5); AddSupportedParam("Diffuse", AnimParamType::MaterialDiffuse, AnimValueType::RGB); AddSupportedParam("Emissive Color", AnimParamType::MaterialEmissive, AnimValueType::RGB); AddSupportedParam("Emissive Intensity", AnimParamType::MaterialEmissiveIntensity, AnimValueType::Float); AddSupportedParam("Glossiness", AnimParamType::MaterialSmoothness, AnimValueType::Float); AddSupportedParam("Opacity", AnimParamType::MaterialOpacity, AnimValueType::Float); AddSupportedParam("Specular", AnimParamType::MaterialSpecular, AnimValueType::RGB); } } ////////////////////////////////////////////////////////////////////////// void CAnimMaterialNode::SetName(const char* name) { CAnimNode::SetName(name); UpdateDynamicParams(); } ////////////////////////////////////////////////////////////////////////// void CAnimMaterialNode::UpdateDynamicParamsInternal() { m_dynamicShaderParamInfos.clear(); m_nameToDynamicShaderParam.clear(); const char* pName = GetName(); _smart_ptr pMtl = GetMaterialByName(pName); if (!pMtl) { return; } const SShaderItem& shaderItem = pMtl->GetShaderItem(); IRenderShaderResources* pShaderResources = shaderItem.m_pShaderResources; if (!pShaderResources) { return; } DynArrayRef& shaderParams = pShaderResources->GetParameters(); for (int i = 0; i < shaderParams.size(); ++i) { SShaderParam& shaderParam = shaderParams[i]; m_nameToDynamicShaderParam[ shaderParams[i].m_Name.c_str() ] = i; CAnimNode::SParamInfo paramInfo; switch (shaderParam.m_Type) { case eType_FLOAT: // Fall through case eType_HALF: paramInfo.valueType = AnimValueType::Float; break; case eType_VECTOR: paramInfo.valueType = AnimValueType::Vector; break; case eType_FCOLOR: paramInfo.valueType = AnimValueType::RGB; break; case eType_BOOL: paramInfo.valueType = AnimValueType::Bool; break; default: continue; } paramInfo.name = shaderParam.m_Name.c_str(); paramInfo.paramType = shaderParam.m_Name; paramInfo.flags = IAnimNode::ESupportedParamFlags(0); m_dynamicShaderParamInfos.push_back(paramInfo); } // Make sure any color tracks that are animated "ByString" // have the track multiplier set. int trackCount = NumTracks(); for (int trackIndex = 0; trackIndex < trackCount; trackIndex++) { IAnimTrack* track = m_tracks[trackIndex].get(); if (!(track->GetFlags() & IAnimTrack::eAnimTrackFlags_Disabled)) { CAnimParamType param = track->GetParameterType(); if (param.GetType() == AnimParamType::ByString && track->GetValueType() == AnimValueType::RGB) { track->SetMultiplier(255.0f); } } } } ////////////////////////////////////////////////////////////////////////// unsigned int CAnimMaterialNode::GetParamCount() const { return s_nodeParams.size() + m_dynamicShaderParamInfos.size(); } ////////////////////////////////////////////////////////////////////////// CAnimParamType CAnimMaterialNode::GetParamType(unsigned int nIndex) const { if (nIndex >= 0 && nIndex < (int)s_nodeParams.size()) { return s_nodeParams[nIndex].paramType; } else if (nIndex >= (unsigned int)s_nodeParams.size() && nIndex < ((unsigned int)s_nodeParams.size() + (unsigned int)m_dynamicShaderParamInfos.size())) { return m_dynamicShaderParamInfos[nIndex - (int)s_nodeParams.size()].paramType; } return AnimParamType::Invalid; } ////////////////////////////////////////////////////////////////////////// bool CAnimMaterialNode::GetParamInfoFromType(const CAnimParamType& paramId, SParamInfo& info) const { for (size_t i = 0; i < s_nodeParams.size(); ++i) { if (s_nodeParams[i].paramType == paramId) { info = s_nodeParams[i]; return true; } } for (size_t i = 0; i < m_dynamicShaderParamInfos.size(); ++i) { if (m_dynamicShaderParamInfos[i].paramType == paramId) { info = m_dynamicShaderParamInfos[i]; return true; } } return false; } ////////////////////////////////////////////////////////////////////////// const char* CAnimMaterialNode::GetParamName(const CAnimParamType& param) const { if (param.GetType() == AnimParamType::ByString) { return param.GetName(); } else if ((int)param.GetType() >= (int)MTL_PARAM_SHADER_PARAM1) { switch ((int)param.GetType()) { case MTL_PARAM_SHADER_PARAM1: return "Shader Param 1"; case MTL_PARAM_SHADER_PARAM1 + 1: return "Shader Param 2"; case MTL_PARAM_SHADER_PARAM1 + 2: return "Shader Param 3"; case MTL_PARAM_SHADER_PARAM1 + 3: return "Shader Param 4"; case MTL_PARAM_SHADER_PARAM1 + 4: return "Shader Param 5"; case MTL_PARAM_SHADER_PARAM1 + 5: return "Shader Param 6"; case MTL_PARAM_SHADER_PARAM1 + 6: return "Shader Param 7"; case MTL_PARAM_SHADER_PARAM1 + 7: return "Shader Param 8"; case MTL_PARAM_SHADER_PARAM1 + 8: return "Shader Param 9"; default: return "Unknown Shader Param"; } } return CAnimNode::GetParamName(param); } ////////////////////////////////////////////////////////////////////////// void CAnimMaterialNode::Animate(SAnimContext& ec) { int paramCount = NumTracks(); if (paramCount <= 0) { return; } // Find material. const char* pName = GetName(); _smart_ptr pMtl = GetMaterialByName(pName); if (!pMtl) { return; } const SShaderItem& shaderItem = pMtl->GetShaderItem(); IRenderShaderResources* pShaderResources = shaderItem.m_pShaderResources; if (!pShaderResources) { return; } float fValue; Vec3 vValue; int trackCount = NumTracks(); for (int paramIndex = 0; paramIndex < trackCount; paramIndex++) { CAnimParamType paramId = m_tracks[paramIndex]->GetParameterType(); IAnimTrack* pTrack = m_tracks[paramIndex].get(); if (pTrack->GetFlags() & IAnimTrack::eAnimTrackFlags_Disabled) { continue; } switch (paramId.GetType()) { case AnimParamType::MaterialOpacity: pTrack->GetValue(ec.time, fValue); pShaderResources->SetStrengthValue(EFTT_OPACITY, fValue); break; case AnimParamType::MaterialDiffuse: pTrack->GetValue(ec.time, vValue); { pShaderResources->SetColorValue(EFTT_DIFFUSE, vValue / 255.0f); } break; case AnimParamType::MaterialSpecular: pTrack->GetValue(ec.time, vValue); { pShaderResources->SetColorValue(EFTT_SPECULAR, vValue / 255.0f); } break; case AnimParamType::MaterialEmissive: pTrack->GetValue(ec.time, vValue); pShaderResources->SetColorValue(EFTT_EMITTANCE, vValue / 255.0f); break; case AnimParamType::MaterialEmissiveIntensity: pTrack->GetValue(ec.time, fValue); pShaderResources->SetStrengthValue(EFTT_EMITTANCE, fValue); break; case AnimParamType::MaterialSmoothness: pTrack->GetValue(ec.time, fValue); { pShaderResources->SetStrengthValue(EFTT_SMOOTHNESS, fValue / 255.0f); } break; case AnimParamType::ByString: AnimateNamedParameter(ec, pShaderResources, paramId.GetName(), pTrack); break; default: // Legacy support code if (paramId.GetType() >= (AnimParamType)MTL_PARAM_SHADER_PARAM1) { int id = static_cast(paramId.GetType()) - MTL_PARAM_SHADER_PARAM1; if (id < (int)pShaderResources->GetParameters().size()) { pTrack->GetValue(ec.time, fValue); pShaderResources->GetParameters()[id].m_Value.m_Float = fValue; } } } } IShader* pShader = shaderItem.m_pShader; if (pShader) { shaderItem.m_pShaderResources->UpdateConstants(pShader); } } void CAnimMaterialNode::AnimateNamedParameter(SAnimContext& ec, IRenderShaderResources* pShaderResources, const char* name, IAnimTrack* pTrack) { TDynamicShaderParamsMap::iterator findIter = m_nameToDynamicShaderParam.find(name); if (findIter != m_nameToDynamicShaderParam.end()) { SShaderParam& param = pShaderResources->GetParameters()[findIter->second]; float fValue; Vec3 vecValue; Vec3 colorValue; bool boolValue; switch (pTrack->GetValueType()) { case AnimValueType::Float: pTrack->GetValue(ec.time, fValue); param.m_Value.m_Float = fValue; break; case AnimValueType::Vector: pTrack->GetValue(ec.time, vecValue); param.m_Value.m_Vector[0] = vecValue[0]; param.m_Value.m_Vector[1] = vecValue[1]; param.m_Value.m_Vector[2] = vecValue[2]; break; case AnimValueType::RGB: pTrack->GetValue(ec.time, colorValue, true); param.m_Value.m_Color[0] = colorValue[0]; param.m_Value.m_Color[1] = colorValue[1]; param.m_Value.m_Color[2] = colorValue[2]; param.m_Value.m_Color[3] = 0.0f; break; case AnimValueType::Bool: pTrack->GetValue(ec.time, boolValue); param.m_Value.m_Bool = boolValue; break; } } } _smart_ptr CAnimMaterialNode::GetMaterialByName(const char* pName) { const char* pCh; if (pCh = strstr(pName, ".[")) { char MatName[256]; cry_strcpy(MatName, pName, (size_t)(pCh - pName)); _smart_ptr pMat = gEnv->p3DEngine->GetMaterialManager()->FindMaterial(MatName); if (!pMat) { return NULL; } pCh += 2; if (!(*pCh)) { return NULL; } int index = atoi(pCh) - 1; if (index < 0 || index >= pMat->GetSubMtlCount()) { return NULL; } return pMat->GetSubMtl(index); } else { return gEnv->p3DEngine->GetMaterialManager()->FindMaterial(GetName()); } } ////////////////////////////////////////////////////////////////////////// void CAnimMaterialNode::AddTrack(IAnimTrack* track) { CAnimNode::AddTrack(track); UpdateDynamicParams(); } ////////////////////////////////////////////////////////////////////////// void CAnimMaterialNode::Reflect(AZ::SerializeContext* serializeContext) { serializeContext->Class() ->Version(1); } #undef s_nodeParamsInitialized #undef s_nodeParams #undef AddSupportedParam