BVB Source Codes

CRYENGINE Show FlowMaterialNodes.cpp Source code

Return Download CRYENGINE: download FlowMaterialNodes.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //  File name:   FlowMaterialNodes.cpp
  5. //  Version:     v1.00
  6. //  Created:     04/11/2013 by Marco H.
  7. //  Description: flownodes copied and updated from FlowEngineNodes.cpp
  8. // -------------------------------------------------------------------------
  9. //  History:
  10. //
  11. ////////////////////////////////////////////////////////////////////////////
  12.  
  13. #include "StdAfx.h"
  14.  
  15. #include <CryFlowGraph/IFlowBaseNode.h>
  16.  
  17. class CFlowNodeEntityMaterial : public CFlowBaseNode<eNCT_Instanced>
  18. {
  19. public:
  20.         CFlowNodeEntityMaterial(SActivationInfo * pActInfo) {}
  21.         virtual IFlowNodePtr Clone(SActivationInfo *pActInfo)
  22.         {
  23.                 return new CFlowNodeEntityMaterial(pActInfo);
  24.         }
  25.  
  26.         enum EInputs
  27.         {
  28.                 IN_SET,
  29.                 IN_GET,
  30.                 IN_SLOT,
  31.                 IN_MATERIAL,
  32.                 IN_RESET,
  33.                 IN_SERIALIZE,
  34.         };
  35.  
  36.         enum EOutputs
  37.         {
  38.                 OUT_VALUE,
  39.         };
  40.  
  41.         _smart_ptr<IMaterial> m_pMaterial;
  42.         _smart_ptr<IMaterial> m_pEditorMaterial;
  43.  
  44.         virtual void Serialize(SActivationInfo* pActInfo, TSerialize ser)
  45.         {
  46.                 if (GetPortBool(pActInfo, IN_SERIALIZE))
  47.                 {
  48.                         IEntity* pEntity = pActInfo->pEntity;
  49.  
  50.                         if (ser.IsReading())
  51.                         {
  52.                                 if (pEntity)
  53.                                 {
  54.                                         string matSavedName;
  55.                                         ser.Value("material", matSavedName);
  56.  
  57.                                         if (matSavedName.empty())
  58.                                                 pEntity->SetMaterial(NULL);
  59.                                         else
  60.                                         {
  61.                                                 IMaterial* pMatCurr = pEntity->GetMaterial();
  62.                                                 if (!pMatCurr || matSavedName != pMatCurr->GetName())
  63.                                                 {
  64.                                                         IMaterial* pMtl = gEnv->p3DEngine->GetMaterialManager()->LoadMaterial(matSavedName.c_str());
  65.                                                         pEntity->SetMaterial(pMtl);
  66.                                                 }
  67.                                         }
  68.                                 }
  69.                         }
  70.                         else
  71.                         {
  72.                                 string matName;
  73.                                 if (pEntity)
  74.                                 {
  75.                                         IMaterial* pMat = pEntity->GetMaterial();
  76.                                         if (pMat)
  77.                                                 matName = pMat->GetName();
  78.                                 }
  79.                                 ser.Value("material", matName);
  80.                         }
  81.                 }
  82.         }
  83.  
  84.         virtual void GetConfiguration(SFlowNodeConfig& config)
  85.         {
  86.                 static const SInputPortConfig in_config[] =
  87.                 {
  88.                         InputPortConfig_Void("Set",             _HELP("Trigger to set the material")),
  89.                         InputPortConfig_Void("Get",             _HELP("Trigger to get the material name")),
  90.                         InputPortConfig<int>("slot",            -1,                                              _HELP("Slot on which to apply the material. -1 if it should be applied to the whole entity.")),
  91.                         InputPortConfig<string>("mat_Material", _HELP("Name of material to apply")),
  92.                         InputPortConfig_Void("Reset",           _HELP("Trigger to reset the original material")),
  93.                         InputPortConfig<bool>("Serialize",      _HELP("Serialize this change")),
  94.                         { 0 }
  95.                 };
  96.  
  97.                 static const SOutputPortConfig out_config[] =
  98.                 {
  99.                         OutputPortConfig<string>("Value", _HELP("Returns the name of the material"), _HELP("Name")),
  100.                         { 0 }
  101.                 };
  102.  
  103.                 config.sDescription = _HELP("Apply material to the entity");
  104.                 config.nFlags |= EFLN_TARGET_ENTITY;
  105.                 config.pInputPorts = in_config;
  106.                 config.pOutputPorts = out_config;
  107.                 config.SetCategory(EFLN_APPROVED);
  108.         };
  109.  
  110.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  111.         {
  112.                 IEntity* pEntity = pActInfo->pEntity;
  113.                 if (pEntity == 0)
  114.                         return;
  115.  
  116.                 switch (event)
  117.                 {
  118.                 case eFE_Initialize:
  119.                         {
  120.                                 // workaround to the fact that the entity does not clear the material when going back to editor mode,
  121.                                 // and to the fact that there is not any special event to signal when its going back to editor mode
  122.                                 if (gEnv->IsEditor())
  123.                                 {
  124.                                         if (pEntity)
  125.                                         {
  126.                                                 if (gEnv->IsEditing())
  127.                                                         m_pEditorMaterial = pEntity->GetMaterial();
  128.                                                 else
  129.                                                         pEntity->SetMaterial(m_pEditorMaterial);
  130.                                         }
  131.                                 }
  132.                                 break;
  133.                         }
  134.  
  135.                 case eFE_PrecacheResources:
  136.                         {
  137.                                 // Preload target material.
  138.                                 const string& mtlName = GetPortString(pActInfo, IN_MATERIAL);
  139.                                 m_pMaterial = gEnv->p3DEngine->GetMaterialManager()->LoadMaterial(mtlName.c_str());
  140.                                 break;
  141.                         }
  142.  
  143.                 case eFE_Activate:
  144.                         {
  145.                                 if (pEntity)
  146.                                 {
  147.                                         if (IsPortActive(pActInfo, IN_SET))
  148.                                         {
  149.                                                 ChangeMat(pActInfo, pEntity);
  150.                                         }
  151.  
  152.                                         if (IsPortActive(pActInfo, IN_RESET))
  153.                                         {
  154.                                                 ApplyMaterialChange(pActInfo, pEntity, nullptr);
  155.                                         }
  156.  
  157.                                         if (!IsPortActive(pActInfo, IN_MATERIAL) && !IsPortActive(pActInfo, IN_SERIALIZE))
  158.                                         {
  159.                                                 if (pEntity->GetMaterial())
  160.                                                 {
  161.                                                         ActivateOutput(pActInfo, OUT_VALUE, string(pEntity->GetMaterial()->GetName()));
  162.                                                 }
  163.                                                 else
  164.                                                 {
  165.                                                         IEntityRender* pIEntityRender = pEntity->GetRenderInterface();
  166.                                                        
  167.                                                         {
  168.                                                                 IMaterial* pMtl = pIEntityRender->GetRenderMaterial(0);
  169.                                                                 if (pMtl)
  170.                                                                         ActivateOutput(pActInfo, OUT_VALUE, string(pMtl->GetName()));
  171.                                                         }
  172.                                                 }
  173.                                         }
  174.                                 }
  175.                         }
  176.                         break;
  177.                 }
  178.         }
  179.  
  180.         void ChangeMat(SActivationInfo* pActInfo, IEntity* pEntity)
  181.         {
  182.                 const string& mtlName = GetPortString(pActInfo, IN_MATERIAL);
  183.                 _smart_ptr<IMaterial> pMtl = gEnv->p3DEngine->GetMaterialManager()->LoadMaterial(mtlName.c_str());
  184.                 if (pMtl != NULL)
  185.                 {
  186.                         ApplyMaterialChange(pActInfo, pEntity, pMtl);
  187.                 }
  188.         }
  189.  
  190.         void ApplyMaterialChange(SActivationInfo* pActInfo, IEntity* pEntity, IMaterial* pMtl)
  191.         {
  192.                 const int slot = GetPortInt(pActInfo, IN_SLOT);
  193.                 if (slot == -1)
  194.                 {
  195.                         pEntity->SetMaterial(pMtl);
  196.                 }
  197.                 else
  198.                 {
  199.                         if (IEntityRender* pIEntityRender = pEntity->GetRenderInterface())
  200.                         {
  201.                                 pIEntityRender->SetSlotMaterial(slot, pMtl);
  202.                         }
  203.                 }
  204.         }
  205.  
  206.         virtual void GetMemoryUsage(ICrySizer* s) const
  207.         {
  208.                 s->Add(*this);
  209.         }
  210. };
  211.  
  212. ////////////////////////////////////////////////////////////////////////////////////////
  213. // Flow node for setting entity render parameters (opacity, glow, motionblur, etc). Same than CFlowNodeMaterialShaderParam, but it serializes the changes
  214. ////////////////////////////////////////////////////////////////////////////////////////
  215. class CFlowNodeMaterialShaderParams : public CFlowBaseNode<eNCT_Singleton>
  216. {
  217. public:
  218.         CFlowNodeMaterialShaderParams(SActivationInfo* pActInfo)
  219.         {
  220.         }
  221.  
  222.         enum EInputPorts
  223.         {
  224.                 EIP_Get = 0,
  225.                 EIP_Name,
  226.                 EIP_SubMtlId,
  227.                 EIP_ParamFloat,
  228.                 EIP_Float,
  229.                 EIP_ParamColor,
  230.                 EIP_Color,
  231.                 EIP_Serialize
  232.         };
  233.  
  234.         enum EOutputPorts
  235.         {
  236.                 EOP_Float = 0,
  237.                 EOP_Color,
  238.         };
  239.  
  240.         virtual void GetConfiguration(SFlowNodeConfig& config)
  241.         {
  242.                 static const SInputPortConfig in_config[] = {
  243.                         InputPortConfig_Void("Get",               _HELP("Trigger to get current value")),
  244.                         InputPortConfig<string>("mat_Material",   _HELP("Material Name")),
  245.                         InputPortConfig<int>("SubMtlId",          0,                                                     _HELP("Sub Material Id, starting at 0"),                 _HELP("SubMaterialId")),
  246.                         InputPortConfig<string>("ParamFloat",     _HELP("Float Parameter to be set/get"),                0,                                                       _UICONFIG("dt=matparamname,name_ref=mat_Material,sub_ref=SubMtlId,param=float")),
  247.                         InputPortConfig<float>("ValueFloat",      0.0f,                                                  _HELP("Trigger and value to set the Float parameter")),
  248.                         InputPortConfig<string>("ParamColor",     _HELP("Color Parameter to be set/get"),                0,                                                       _UICONFIG("dt=matparamname,name_ref=mat_Material,sub_ref=SubMtlId,param=vec")),
  249.                         InputPortConfig<Vec3>("color_ValueColor", _HELP("Trigger and value to set the Color parameter")),
  250.                         InputPortConfig<bool>("Serialize",        _HELP("Serialize this change")),
  251.                         { 0 }
  252.                 };
  253.  
  254.                 static const SOutputPortConfig out_config[] = {
  255.                         OutputPortConfig<float>("ValueFloat", _HELP("Current Float Value")),
  256.                         OutputPortConfig<Vec3>("ValueColor",  _HELP("Current Color Value")),
  257.                         { 0 }
  258.                 };
  259.  
  260.                 config.sDescription = _HELP("Set/Get Material's Shader Parameters, with 'Set' serialization");
  261.                 config.pInputPorts = in_config;
  262.                 config.pOutputPorts = out_config;
  263.                 config.SetCategory(EFLN_ADVANCED);
  264.         }
  265.  
  266.         virtual void Serialize(SActivationInfo* pActInfo, TSerialize ser)
  267.         {
  268.                 if (GetPortBool(pActInfo, EIP_Serialize))
  269.                 {
  270.                         if (ser.IsWriting())
  271.                         {
  272.                                 bool validFloat = false;
  273.                                 bool validColor = false;
  274.                                 float floatValue = 0;
  275.                                 Vec3 colorValue(0.f, 0.f, 0.f);
  276.  
  277.                                 GetValues(pActInfo, floatValue, colorValue, validFloat, validColor);
  278.                                 ser.Value("validFloat", validFloat);
  279.                                 ser.Value("validColor", validColor);
  280.                                 ser.Value("floatValue", floatValue);
  281.                                 ser.Value("colorValue", colorValue);
  282.                         }
  283.  
  284.                         if (ser.IsReading())
  285.                         {
  286.                                 bool validFloat = false;
  287.                                 bool validColor = false;
  288.                                 float floatValue = 0;
  289.                                 Vec3 colorValue(0.f, 0.f, 0.f);
  290.  
  291.                                 ser.Value("validFloat", validFloat);
  292.                                 ser.Value("validColor", validColor);
  293.                                 ser.Value("floatValue", floatValue);
  294.                                 ser.Value("colorValue", colorValue);
  295.  
  296.                                 SetValues(pActInfo, validFloat, validColor, floatValue, colorValue);
  297.                         }
  298.                 }
  299.         }
  300.  
  301.         IMaterial* ObtainMaterial(SActivationInfo* pActInfo)
  302.         {
  303.                 const string& matName = GetPortString(pActInfo, EIP_Name);
  304.                 IMaterial* pMtl = gEnv->p3DEngine->GetMaterialManager()->FindMaterial(matName);
  305.                 if (pMtl == 0)
  306.                 {
  307.                         GameWarning("[flow] CFlowNodeMaterialShaderParamSerialize: Material '%s' not found.", matName.c_str());
  308.                         return NULL;
  309.                 }
  310.  
  311.                 const int& subMtlId = GetPortInt(pActInfo, EIP_SubMtlId);
  312.                 pMtl = pMtl->GetSafeSubMtl(subMtlId);
  313.                 if (pMtl == 0)
  314.                 {
  315.                         GameWarning("[flow] CFlowNodeMaterialShaderParamSerialize: Material '%s' has no sub-material %d", matName.c_str(), subMtlId);
  316.                         return NULL;
  317.                 }
  318.                 return pMtl;
  319.         }
  320.  
  321.         IRenderShaderResources* ObtainRendRes(SActivationInfo* pActInfo, IMaterial* pMtl)
  322.         {
  323.                 assert(pMtl);
  324.                 const SShaderItem& shaderItem = pMtl->GetShaderItem();
  325.                 IRenderShaderResources* pRendRes = shaderItem.m_pShaderResources;
  326.                 if (pRendRes == 0)
  327.                 {
  328.                         const string& matName = GetPortString(pActInfo, EIP_Name);
  329.                         const int& subMtlId = GetPortInt(pActInfo, EIP_SubMtlId);
  330.                         GameWarning("[flow] CFlowNodeMaterialShaderParamSerialize: Material '%s' (submtl %d) has no shader-resources.", matName.c_str(), subMtlId);
  331.                 }
  332.                 return pRendRes;
  333.         }
  334.  
  335.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  336.         {
  337.                 if (event != eFE_Activate)
  338.                         return;
  339.  
  340.                 const bool bGet = IsPortActive(pActInfo, EIP_Get);
  341.                 const bool bSetFloat = IsPortActive(pActInfo, EIP_Float);
  342.                 const bool bSetColor = IsPortActive(pActInfo, EIP_Color);
  343.  
  344.                 if (!bGet && !bSetFloat && !bSetColor)
  345.                         return;
  346.  
  347.                 if (bSetFloat || bSetColor)
  348.                 {
  349.                         float floatValue = GetPortFloat(pActInfo, EIP_Float);
  350.                         Vec3 colorValue = GetPortVec3(pActInfo, EIP_Color);
  351.  
  352.                         SetValues(pActInfo, bSetFloat, bSetColor, floatValue, colorValue);
  353.                 }
  354.  
  355.                 if (bGet)
  356.                 {
  357.                         bool validFloat = false;
  358.                         bool validColor = false;
  359.                         float floatValue = 0;
  360.                         Vec3 colorValue(0.f, 0.f, 0.f);
  361.  
  362.                         GetValues(pActInfo, floatValue, colorValue, validFloat, validColor);
  363.  
  364.                         if (validFloat)
  365.                                 ActivateOutput(pActInfo, EOP_Float, floatValue);
  366.                         if (validColor)
  367.                                 ActivateOutput(pActInfo, EOP_Color, colorValue);
  368.                 }
  369.         }
  370.  
  371.         void GetValues(SActivationInfo* pActInfo, float& floatValue, Vec3& colorValue, bool& validFloat, bool& validColor)
  372.         {
  373.                 validFloat = false;
  374.                 validColor = false;
  375.                 const string& paramNameFloat = GetPortString(pActInfo, EIP_ParamFloat);
  376.                 const string& paramNameColor = GetPortString(pActInfo, EIP_ParamColor);
  377.  
  378.                 IMaterial* pMtl = ObtainMaterial(pActInfo);
  379.                 if (!pMtl)
  380.                         return;
  381.                 IRenderShaderResources* pRendRes = ObtainRendRes(pActInfo, pMtl);
  382.                 if (!pRendRes)
  383.                         return;
  384.                 DynArrayRef<SShaderParam>& params = pRendRes->GetParameters();
  385.  
  386.                 validFloat = pMtl->SetGetMaterialParamFloat(paramNameFloat, floatValue, true);
  387.                 validColor = pMtl->SetGetMaterialParamVec3(paramNameColor, colorValue, true);
  388.  
  389.                 if (!validFloat)
  390.                 {
  391.                         for (int i = 0; i < params.size(); ++i)
  392.                         {
  393.                                 SShaderParam& param = params[i];
  394.                                 if (stricmp(param.m_Name, paramNameFloat) == 0)
  395.                                 {
  396.                                         switch (param.m_Type)
  397.                                         {
  398.                                         case eType_BOOL:
  399.                                                 floatValue = param.m_Value.m_Bool;
  400.                                                 validFloat = true;
  401.                                                 break;
  402.                                         case eType_SHORT:
  403.                                                 floatValue = param.m_Value.m_Short;
  404.                                                 validFloat = true;
  405.                                                 break;
  406.                                         case eType_INT:
  407.                                                 floatValue = (float)param.m_Value.m_Int;
  408.                                                 validFloat = true;
  409.                                                 break;
  410.                                         case eType_FLOAT:
  411.                                                 floatValue = param.m_Value.m_Float;
  412.                                                 validFloat = true;
  413.                                                 break;
  414.                                         default:
  415.                                                 break;
  416.                                         }
  417.                                 }
  418.                         }
  419.                 }
  420.  
  421.                 if (!validColor)
  422.                 {
  423.                         for (int i = 0; i < params.size(); ++i)
  424.                         {
  425.                                 SShaderParam& param = params[i];
  426.  
  427.                                 if (stricmp(param.m_Name, paramNameColor) == 0)
  428.                                 {
  429.                                         if (param.m_Type == eType_VECTOR)
  430.                                         {
  431.                                                 colorValue.Set(param.m_Value.m_Vector[0], param.m_Value.m_Vector[1], param.m_Value.m_Vector[2]);
  432.                                                 validColor = true;
  433.                                         }
  434.                                         if (param.m_Type == eType_FCOLOR)
  435.                                         {
  436.                                                 colorValue.Set(param.m_Value.m_Color[0], param.m_Value.m_Color[1], param.m_Value.m_Color[2]);
  437.                                                 validColor = true;
  438.                                         }
  439.                                         break;
  440.                                 }
  441.                         }
  442.                 }
  443.         }
  444.  
  445.         void SetValues(SActivationInfo* pActInfo, bool bSetFloat, bool bSetColor, float floatValue, Vec3& colorValue)
  446.         {
  447.                 IMaterial* pMtl = ObtainMaterial(pActInfo);
  448.                 if (!pMtl)
  449.                         return;
  450.  
  451.                 IRenderShaderResources* pRendRes = ObtainRendRes(pActInfo, pMtl);
  452.                 if (!pRendRes)
  453.                         return;
  454.                 DynArrayRef<SShaderParam>& params = pRendRes->GetParameters();
  455.                 const SShaderItem& shaderItem = pMtl->GetShaderItem();
  456.  
  457.                 const string& paramNameFloat = GetPortString(pActInfo, EIP_ParamFloat);
  458.                 const string& paramNameColor = GetPortString(pActInfo, EIP_ParamColor);
  459.  
  460.                 bool bUpdateShaderConstants = false;
  461.                 if (bSetFloat)
  462.                 {
  463.                         if (pMtl->SetGetMaterialParamFloat(paramNameFloat, floatValue, false) == false)
  464.                         {
  465.                                 UParamVal val;
  466.                                 val.m_Float = floatValue;
  467.                                 SShaderParam::SetParam(paramNameFloat, &params, val);
  468.                                 bUpdateShaderConstants = true;
  469.                         }
  470.                 }
  471.                 if (bSetColor)
  472.                 {
  473.                         if (pMtl->SetGetMaterialParamVec3(paramNameColor, colorValue, false) == false)
  474.                         {
  475.                                 UParamVal val;
  476.                                 val.m_Color[0] = colorValue[0];
  477.                                 val.m_Color[1] = colorValue[1];
  478.                                 val.m_Color[2] = colorValue[2];
  479.                                 val.m_Color[3] = 1.0f;
  480.                                 SShaderParam::SetParam(paramNameColor, &params, val);
  481.                                 bUpdateShaderConstants = true;
  482.                         }
  483.                 }
  484.                 if (bUpdateShaderConstants)
  485.                 {
  486.                         shaderItem.m_pShaderResources->UpdateConstants(shaderItem.m_pShader);
  487.                 }
  488.         }
  489.  
  490.         virtual void GetMemoryUsage(ICrySizer* s) const
  491.         {
  492.                 s->Add(*this);
  493.         }
  494. };
  495.  
  496. ////////////////////////////////////////////////////////////////////////////////////////
  497. // Flow node for setting entity render parameters (opacity, glow, motionblur, etc)
  498. ////////////////////////////////////////////////////////////////////////////////////////
  499.  
  500. class CFlowNodeEntityMaterialShaderParams : public CFlowBaseNode<eNCT_Instanced>
  501. {
  502. public:
  503.         CFlowNodeEntityMaterialShaderParams(SActivationInfo* pActInfo)
  504.         {
  505.                 //m_entityId = (EntityId)(UINT_PTR)pActInfo->m_pUserData;
  506.                 m_anyChangeDone = false;
  507.                 m_pMaterial = NULL;
  508.         }
  509.  
  510.         virtual IFlowNodePtr Clone(SActivationInfo *pActInfo)
  511.         {
  512.                 return new CFlowNodeEntityMaterialShaderParams(pActInfo);
  513.         }
  514.  
  515.         enum EInputPorts
  516.         {
  517.                 EIP_Get = 0,
  518.                 EIP_Slot,
  519.                 EIP_SubMtlId,
  520.                 EIP_ParamFloat,
  521.                 EIP_Float,
  522.                 EIP_ParamColor,
  523.                 EIP_Color,
  524.         };
  525.  
  526.         enum EOutputPorts
  527.         {
  528.                 EOP_Float = 0,
  529.                 EOP_Color,
  530.         };
  531.  
  532.         //////////////////////////////////////////////////////////////////////////
  533.         /// this serialize is *NOT* perfect. If any of the following inputs: "slot, submtlid, paramFloat, paramColor" do change and the node is triggered more than once  with different values for them, the serializing wont be 100% correct.
  534.         /// this does not happens in crysis2, so is good enough for now.
  535.         /// to make it perfect, either the materials should be serialized at engine level, or either we would need to create an intermediate module to handle changes on materials from game side,
  536.         /// make the flownodes to use that module instead of the materials directly, and serialize the changes there instead of in the flownodes.
  537.  
  538.         void Serialize(SActivationInfo* pActInfo, TSerialize ser)
  539.         {
  540.                 if (!pActInfo->pEntity)
  541.                         return;
  542.  
  543.                 // we do assume that those inputs never change, which is ok for crysis2, but of course is not totally right
  544.                 const int slot = GetPortInt(pActInfo, EIP_Slot);
  545.                 const int subMtlId = GetPortInt(pActInfo, EIP_SubMtlId);
  546.                 const string& paramNameFloat = GetPortString(pActInfo, EIP_ParamFloat);
  547.                 const string& paramNameColor = GetPortString(pActInfo, EIP_ParamColor);
  548.  
  549.                 ser.Value("m_anyChangeDone", m_anyChangeDone);
  550.  
  551.                 //---------------------
  552.                 if (ser.IsWriting())
  553.                 {
  554.                         IMaterial* pSubMtl;
  555.                         IRenderShaderResources* pRendShaderRes;
  556.                         if (!ObtainMaterialPtrs(pActInfo->pEntity, slot, subMtlId, false, pSubMtl, pRendShaderRes))
  557.                                 return;
  558.                         DynArrayRef<SShaderParam>& shaderParams = pRendShaderRes->GetParameters();
  559.  
  560.                         if (!paramNameFloat.empty())
  561.                         {
  562.                                 float floatValue = 0;
  563.                                 ReadFloatValueFromMat(pSubMtl, pRendShaderRes, paramNameFloat, floatValue);
  564.                                 ser.Value("floatValue", floatValue);
  565.                         }
  566.  
  567.                         if (!paramNameColor.empty())
  568.                         {
  569.                                 Vec3 colorValue(ZERO);
  570.                                 ReadColorValueFromMat(pSubMtl, pRendShaderRes, paramNameColor, colorValue);
  571.                                 ser.Value("colorValue", colorValue);
  572.                         }
  573.                 }
  574.  
  575.                 //----------------
  576.                 if (ser.IsReading())
  577.                 {
  578.                         // if there was no change done, we still need to set values to the material, in case it was changed after the savegame.
  579.                         // But in that case, we dont need to create a clone, we just use the current material
  580.                         bool cloneMaterial = m_anyChangeDone;
  581.                         IMaterial* pSubMtl;
  582.                         IRenderShaderResources* pRendShaderRes;
  583.                         if (!ObtainMaterialPtrs(pActInfo->pEntity, slot, subMtlId, cloneMaterial, pSubMtl, pRendShaderRes))
  584.                                 return;
  585.                         DynArrayRef<SShaderParam>& shaderParams = pRendShaderRes->GetParameters();
  586.  
  587.                         // if we *potentially* can change one of them, we have to restore them, even if we in theory didnt change any. that is why this checks the name of the parameters, instead of actualy changedone
  588.                         {
  589.                                 bool bUpdateShaderConstants = false;
  590.                                 if (!paramNameFloat.empty())
  591.                                 {
  592.                                         float floatValue;
  593.                                         ser.Value("floatValue", floatValue);
  594.                                         if (pSubMtl->SetGetMaterialParamFloat(paramNameFloat, floatValue, false) == false)
  595.                                         {
  596.                                                 UParamVal val;
  597.                                                 val.m_Float = floatValue;
  598.                                                 SShaderParam::SetParam(paramNameFloat, &shaderParams, val);
  599.                                                 bUpdateShaderConstants = true;
  600.                                         }
  601.                                 }
  602.                                 if (!paramNameColor.empty())
  603.                                 {
  604.                                         Vec3 colorValue;
  605.                                         ser.Value("colorValue", colorValue);
  606.                                         if (pSubMtl->SetGetMaterialParamVec3(paramNameColor, colorValue, false) == false)
  607.                                         {
  608.                                                 UParamVal val;
  609.                                                 val.m_Color[0] = colorValue[0];
  610.                                                 val.m_Color[1] = colorValue[1];
  611.                                                 val.m_Color[2] = colorValue[2];
  612.                                                 val.m_Color[3] = 1.0f;
  613.                                                 SShaderParam::SetParam(paramNameColor, &shaderParams, val);
  614.                                                 bUpdateShaderConstants = true;
  615.                                         }
  616.                                 }
  617.  
  618.                                 if (bUpdateShaderConstants)
  619.                                 {
  620.                                         const SShaderItem& shaderItem = pSubMtl->GetShaderItem();
  621.                                         shaderItem.m_pShaderResources->UpdateConstants(shaderItem.m_pShader);
  622.                                 }
  623.                         }
  624.                 }
  625.         }
  626.  
  627.         virtual void GetConfiguration(SFlowNodeConfig& config)
  628.         {
  629.                 static const SInputPortConfig in_config[] =
  630.                 {
  631.                         InputPortConfig_Void("Get",               _HELP("Trigger to get current value")),
  632.                         InputPortConfig<int>("Slot",              0,                                                 _HELP("Material Slot")),
  633.                         InputPortConfig<int>("SubMtlId",          0,                                                 _HELP("Sub Material Id, starting at 0"),                _HELP("SubMaterialId")),
  634.                         InputPortConfig<string>("ParamFloat",     _HELP("Float Parameter to be set/get"),            0,                                                      _UICONFIG("dt=matparamslot,slot_ref=Slot,sub_ref=SubMtlId,param=float")),
  635.                         InputPortConfig<float>("ValueFloat",      0.0f,                                              _HELP("Trigger and value to set the Float parameter")),
  636.                         InputPortConfig<string>("ParamColor",     _HELP("Color Parameter to be set/get"),            0,                                                      _UICONFIG("dt=matparamslot,slot_ref=Slot,sub_ref=SubMtlId,param=vec")),
  637.                         InputPortConfig<Vec3>("color_ValueColor", _HELP("Trigger and value to set the Color value")),
  638.                         { 0 }
  639.                 };
  640.  
  641.                 static const SOutputPortConfig out_config[] =
  642.                 {
  643.                         OutputPortConfig<float>("ValueFloat", _HELP("Current Float Value")),
  644.                         OutputPortConfig<Vec3>("ValueColor",  _HELP("Current Color Value")),
  645.                         { 0 }
  646.                 };
  647.  
  648.                 config.sDescription = _HELP("Set/Get Entity's Material Shader Parameters");
  649.                 config.nFlags |= EFLN_TARGET_ENTITY;
  650.                 config.pInputPorts = in_config;
  651.                 config.pOutputPorts = out_config;
  652.                 config.SetCategory(EFLN_APPROVED);
  653.         }
  654.  
  655.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  656.         {
  657.                 if (!pActInfo->pEntity)
  658.                         return;
  659.  
  660.                 if (event != eFE_Activate)
  661.                         return;
  662.  
  663.                 const bool bGet = IsPortActive(pActInfo, EIP_Get);
  664.                 const bool bSetFloat = IsPortActive(pActInfo, EIP_Float);
  665.                 const bool bSetColor = IsPortActive(pActInfo, EIP_Color);
  666.                 const int slot = GetPortInt(pActInfo, EIP_Slot);
  667.                 const int subMtlId = GetPortInt(pActInfo, EIP_SubMtlId);
  668.                 const string& paramNameFloat = GetPortString(pActInfo, EIP_ParamFloat);
  669.                 const string& paramNameColor = GetPortString(pActInfo, EIP_ParamColor);
  670.  
  671.                 if (!bGet && !bSetFloat && !bSetColor)
  672.                         return;
  673.  
  674.                 bool cloneMaterial = bSetFloat || bSetColor;
  675.                 IMaterial* pSubMtl;
  676.                 IRenderShaderResources* pRendShaderRes;
  677.  
  678.                 if (!ObtainMaterialPtrs(pActInfo->pEntity, slot, subMtlId, cloneMaterial, pSubMtl, pRendShaderRes))
  679.                         return;
  680.  
  681.                 DynArrayRef<SShaderParam>& shaderParams = pRendShaderRes->GetParameters();
  682.  
  683.                 //..........sets.......
  684.                 {
  685.                         bool bUpdateShaderConstants = false;
  686.                         if (bSetFloat)
  687.                         {
  688.                                 m_anyChangeDone = true;
  689.                                 float floatValue = GetPortFloat(pActInfo, EIP_Float);
  690.                                 if (pSubMtl->SetGetMaterialParamFloat(paramNameFloat, floatValue, false) == false)
  691.                                 {
  692.                                         UParamVal val;
  693.                                         val.m_Float = floatValue;
  694.                                         SShaderParam::SetParam(paramNameFloat, &shaderParams, val);
  695.                                         bUpdateShaderConstants = true;
  696.                                 }
  697.                         }
  698.                         if (bSetColor)
  699.                         {
  700.                                 m_anyChangeDone = true;
  701.                                 Vec3 colorValue = GetPortVec3(pActInfo, EIP_Color);
  702.                                 if (pSubMtl->SetGetMaterialParamVec3(paramNameColor, colorValue, false) == false)
  703.                                 {
  704.                                         UParamVal val;
  705.                                         val.m_Color[0] = colorValue[0];
  706.                                         val.m_Color[1] = colorValue[1];
  707.                                         val.m_Color[2] = colorValue[2];
  708.                                         val.m_Color[3] = 1.0f;
  709.                                         SShaderParam::SetParam(paramNameColor, &shaderParams, val);
  710.                                         bUpdateShaderConstants = true;
  711.                                 }
  712.                         }
  713.  
  714.                         if (bUpdateShaderConstants)
  715.                         {
  716.                                 const SShaderItem& shaderItem = pSubMtl->GetShaderItem();
  717.                                 shaderItem.m_pShaderResources->UpdateConstants(shaderItem.m_pShader);
  718.                         }
  719.                 }
  720.  
  721.                 //........get
  722.                 if (bGet)
  723.                 {
  724.                         float floatValue;
  725.                         if (ReadFloatValueFromMat(pSubMtl, pRendShaderRes, paramNameFloat, floatValue))
  726.                                 ActivateOutput(pActInfo, EOP_Float, floatValue);
  727.  
  728.                         Vec3 colorValue;
  729.                         if (ReadColorValueFromMat(pSubMtl, pRendShaderRes, paramNameColor, colorValue))
  730.                                 ActivateOutput(pActInfo, EOP_Color, colorValue);
  731.                 }
  732.         }
  733.  
  734.         bool ReadFloatValueFromMat(IMaterial* pSubMtl, IRenderShaderResources* pRendShaderRes, const char* paramName, float& floatValue)
  735.         {
  736.                 if (pSubMtl->SetGetMaterialParamFloat(paramName, floatValue, true))
  737.                         return true;
  738.  
  739.                 DynArrayRef<SShaderParam>& shaderParams = pRendShaderRes->GetParameters();
  740.  
  741.                 for (int i = 0; i < shaderParams.size(); ++i)
  742.                 {
  743.                         SShaderParam& param = shaderParams[i];
  744.                         if (stricmp(param.m_Name, paramName) == 0)
  745.                         {
  746.                                 floatValue = 0.0f;
  747.                                 switch (param.m_Type)
  748.                                 {
  749.                                 case eType_BOOL:
  750.                                         floatValue = param.m_Value.m_Bool;
  751.                                         break;
  752.                                 case eType_SHORT:
  753.                                         floatValue = param.m_Value.m_Short;
  754.                                         break;
  755.                                 case eType_INT:
  756.                                         floatValue = (float)param.m_Value.m_Int;
  757.                                         break;
  758.                                 case eType_FLOAT:
  759.                                         floatValue = param.m_Value.m_Float;
  760.                                         break;
  761.                                 }
  762.                                 return true;
  763.                         }
  764.                 }
  765.                 return false;
  766.         }
  767.  
  768.         bool ReadColorValueFromMat(IMaterial* pSubMtl, IRenderShaderResources* pRendShaderRes, const char* paramName, Vec3& colorValue)
  769.         {
  770.                 if (pSubMtl->SetGetMaterialParamVec3(paramName, colorValue, true))
  771.                         return true;
  772.  
  773.                 DynArrayRef<SShaderParam>& shaderParams = pRendShaderRes->GetParameters();
  774.  
  775.                 for (int i = 0; i < shaderParams.size(); ++i)
  776.                 {
  777.                         SShaderParam& param = shaderParams[i];
  778.                         if (stricmp(param.m_Name, paramName) == 0)
  779.                         {
  780.                                 colorValue.Set(0, 0, 0);
  781.                                 if (param.m_Type == eType_VECTOR)
  782.                                 {
  783.                                         colorValue.Set(param.m_Value.m_Vector[0], param.m_Value.m_Vector[1], param.m_Value.m_Vector[2]);
  784.                                 }
  785.                                 if (param.m_Type == eType_FCOLOR)
  786.                                 {
  787.                                         colorValue.Set(param.m_Value.m_Color[0], param.m_Value.m_Color[1], param.m_Value.m_Color[2]);
  788.                                 }
  789.                                 return true;
  790.                         }
  791.                 }
  792.                 return false;
  793.         }
  794.  
  795.         /*
  796.            void OnEntityEvent( IEntity *pEntity,SEntityEvent &event )
  797.            {
  798.            }
  799.          */
  800.         virtual void GetMemoryUsage(ICrySizer* s) const
  801.         {
  802.                 s->Add(*this);
  803.         }
  804.  
  805.         //////////////////////////////////////////////////////////////////////////
  806.         bool ObtainMaterialPtrs(IEntity* pEntity, int slot, int subMtlId, bool cloneMaterial, IMaterial*& pSubMtl, IRenderShaderResources*& pRenderShaderRes)
  807.         {
  808.                 //const bool RETFAIL = false;
  809.                 //const bool RETOK = true;
  810.  
  811.                 //IEntity* pEntity = GetEntity();
  812.                 if (!pEntity)
  813.                         return false;
  814.  
  815.                 IEntityRender* pIEntityRender = pEntity->GetRenderInterface();
  816.                 if (pIEntityRender == 0)
  817.                         return false;
  818.  
  819.                 IMaterial* pMaterial = pIEntityRender->GetRenderMaterial(slot);
  820.                 if (pMaterial == 0)
  821.                 {
  822.                         GameWarning("[flow] CFlowNodeEntityMaterialShaderParam: Entity '%s' [%d] has no material at slot %d", pEntity->GetName(), pEntity->GetId(), slot);
  823.                         return false;
  824.                 }
  825.  
  826.                 if (cloneMaterial && m_pMaterial != pMaterial)
  827.                 {
  828.                         pMaterial = gEnv->p3DEngine->GetMaterialManager()->CloneMultiMaterial(pMaterial);
  829.                         if (!pMaterial)
  830.                         {
  831.                                 GameWarning("[flow] CFlowNodeEntityMaterialShaderParam: Entity '%s' [%d] Can't clone material at slot %d", pEntity->GetName(), pEntity->GetId(), slot);
  832.                                 return false;
  833.                         }
  834.                         pIEntityRender->SetSlotMaterial(slot, pMaterial);
  835.                         m_pMaterial = pMaterial;
  836.                 }
  837.  
  838.                 pSubMtl = pMaterial->GetSafeSubMtl(subMtlId);
  839.                 if (pSubMtl == 0)
  840.                 {
  841.                         GameWarning("[flow] CFlowNodeEntityMaterialShaderParam: Entity '%s' [%d] has no sub-material %d at slot %d", pEntity->GetName(), pEntity->GetId(), subMtlId, slot);
  842.                         return false;
  843.                 }
  844.  
  845.                 const SShaderItem& shaderItem = pSubMtl->GetShaderItem();
  846.                 pRenderShaderRes = shaderItem.m_pShaderResources;
  847.                 if (!pRenderShaderRes)
  848.                 {
  849.                         GameWarning("[flow] CFlowNodeEntityMaterialShaderParam: Entity '%s' [%d] Material's '%s' sub-material [%d] '%s' has not shader-resources", pEntity->GetName(), pEntity->GetId(), pMaterial->GetName(), subMtlId, pSubMtl->GetName());
  850.                         return false;
  851.                 }
  852.                 return true;
  853.         }
  854.  
  855. protected:
  856.         bool                  m_anyChangeDone;
  857.         _smart_ptr<IMaterial> m_pMaterial;// this is only used to know if we need to clone or not. And is in purpose not reseted on flow initialize, and also not serialized.
  858.         // the situation is:
  859.         // if we already cloned the material, it will stay cloned even if we load a checkpoint previous to the point where the change happened, so we dont need to clone it again.
  860.         // On the other side, if we are doing a 'resumegame", we need to clone the material even if we already cloned it when the checkpoint happened.
  861.         // By not serializing or reseting this member, we cover those cases correctly
  862. };
  863.  
  864. ////////////////////////////////////////////////////////////////////////////////////////
  865. // Flow node for cloning an entity's material
  866. ////////////////////////////////////////////////////////////////////////////////////////
  867. class CFlowNodeEntityCloneMaterial : public CFlowBaseNode<eNCT_Singleton>
  868. {
  869. public:
  870.         CFlowNodeEntityCloneMaterial(SActivationInfo* pActInfo)
  871.         {
  872.         }
  873.  
  874.         enum EInputPorts
  875.         {
  876.                 EIP_Clone = 0,
  877.                 EIP_Reset,
  878.                 EIP_Slot,
  879.         };
  880.  
  881.         enum EOutputPorts
  882.         {
  883.                 EOP_Cloned = 0,
  884.                 EOP_Reset
  885.         };
  886.  
  887.         virtual void GetConfiguration(SFlowNodeConfig& config)
  888.         {
  889.                 static const SInputPortConfig in_config[] = {
  890.                         InputPortConfig_Void("Clone", _HELP("Trigger to clone material")),
  891.                         InputPortConfig_Void("Reset", _HELP("Trigger to reset material")),
  892.                         InputPortConfig<int>("Slot",  0,                                  _HELP("Material Slot")),
  893.                         { 0 }
  894.                 };
  895.  
  896.                 static const SOutputPortConfig out_config[] = {
  897.                         OutputPortConfig_Void("Cloned", _HELP("Triggered when cloned.")),
  898.                         OutputPortConfig_Void("Reset",  _HELP("Triggered when reset.")),
  899.                         { 0 }
  900.                 };
  901.  
  902.                 config.sDescription = _HELP("Clone an Entity's Material and Reset it back to original.");
  903.                 config.nFlags |= EFLN_TARGET_ENTITY;
  904.                 config.pInputPorts = in_config;
  905.                 config.pOutputPorts = out_config;
  906.                 config.SetCategory(EFLN_APPROVED);
  907.         }
  908.  
  909.         virtual void ProcessEvent(EFlowEvent event, SActivationInfo* pActInfo)
  910.         {
  911.                 switch (event)
  912.                 {
  913.                 case eFE_Initialize:
  914.                         {
  915.                                 const int slot = GetPortInt(pActInfo, EIP_Slot);
  916.                                 UnApplyMaterial(pActInfo->pEntity, slot);
  917.                         }
  918.                         break;
  919.  
  920.                 case eFE_Activate:
  921.                         {
  922.                                 if (IsPortActive(pActInfo, EIP_Reset))
  923.                                 {
  924.                                         const int slot = GetPortInt(pActInfo, EIP_Slot);
  925.                                         UnApplyMaterial(pActInfo->pEntity, slot);
  926.                                         ActivateOutput(pActInfo, EOP_Reset, true);
  927.                                 }
  928.                                 if (IsPortActive(pActInfo, EIP_Clone))
  929.                                 {
  930.                                         const int slot = GetPortInt(pActInfo, EIP_Slot);
  931.                                         UnApplyMaterial(pActInfo->pEntity, slot);
  932.                                         CloneAndApplyMaterial(pActInfo->pEntity, slot);
  933.                                         ActivateOutput(pActInfo, EOP_Cloned, true);
  934.                                 }
  935.                         }
  936.                         break;
  937.                 default:
  938.                         break;
  939.                 }
  940.         }
  941.  
  942.         void UnApplyMaterial(IEntity* pEntity, int slot)
  943.         {
  944.                 if (pEntity == 0)
  945.                         return;
  946.                 IEntityRender* pIEntityRender = pEntity->GetRenderInterface();
  947.                 if (pIEntityRender == 0)
  948.                         return;
  949.                 pIEntityRender->SetSlotMaterial(slot, 0);
  950.         }
  951.  
  952.         void CloneAndApplyMaterial(IEntity* pEntity, int slot)
  953.         {
  954.                 if (pEntity == 0)
  955.                         return;
  956.  
  957.                 IEntityRender* pIEntityRender = pEntity->GetRenderInterface();
  958.                 if (pIEntityRender == 0)
  959.                         return;
  960.  
  961.                 IMaterial* pMtl = pIEntityRender->GetSlotMaterial(slot);
  962.                 if (pMtl)
  963.                         return;
  964.  
  965.                 pMtl = pIEntityRender->GetRenderMaterial(slot);
  966.                 if (pMtl == 0)
  967.                 {
  968.                         GameWarning("[flow] CFlowNodeEntityCloneMaterial: Entity '%s' [%d] has no material at slot %d", pEntity->GetName(), pEntity->GetId(), slot);
  969.                         return;
  970.                 }
  971.                 pMtl = gEnv->p3DEngine->GetMaterialManager()->CloneMultiMaterial(pMtl);
  972.                 pIEntityRender->SetSlotMaterial(slot, pMtl);
  973.         }
  974.  
  975.         virtual void GetMemoryUsage(ICrySizer* s) const
  976.         {
  977.                 s->Add(*this);
  978.         }
  979. };
  980.  
  981. REGISTER_FLOW_NODE("Material:EntityMaterialChange", CFlowNodeEntityMaterial)
  982. REGISTER_FLOW_NODE("Material:MaterialParams", CFlowNodeMaterialShaderParams)
  983. REGISTER_FLOW_NODE("Material:EntityMaterialParams", CFlowNodeEntityMaterialShaderParams)
  984. REGISTER_FLOW_NODE("Material:MaterialClone", CFlowNodeEntityCloneMaterial)
  985.  
downloadFlowMaterialNodes.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top