BVB Source Codes

CRYENGINE Show ParticleConvert.cpp Source code

Return Download CRYENGINE: download ParticleConvert.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. // -------------------------------------------------------------------------
  4. //
  5. ////////////////////////////////////////////////////////////////////////////
  6.  
  7. #include "StdAfx.h"
  8. #include "ParticleSystem.h"
  9. #include "Features/ParamMod.h"
  10. #include "../ParticleEffect.h"
  11. #include <CrySerialization/IArchiveHost.h>
  12. #include <yasli/JSONOArchive.h>
  13.  
  14. CRY_PFX2_DBG
  15.  
  16. namespace pfx2
  17. {
  18.  
  19. // PFX1 to PFX2
  20.  
  21. ///////////////////////////////////////////////////////////////////////
  22. // XML utilities for params
  23.  
  24. template<typename T, typename D> T ResetValue(T& ref, D def)
  25. {
  26.         T val = ref;
  27.         ref = T(def);
  28.         return val;
  29. }
  30.  
  31. template<typename T> T ResetValue(T& ref)
  32. {
  33.         return ResetValue(ref, T());
  34. }
  35.  
  36. template<typename P, typename T>
  37. bool IsConstant(const P& value, const T& defValue)
  38. {
  39.         return value(VMAX) == defValue && value(VMIN) == defValue;
  40. }
  41.  
  42. XmlNodeRef MakeFeature(cstr name)
  43. {
  44.         return gEnv->pSystem->CreateXmlNode(name);
  45. }
  46.  
  47. template<typename T>
  48. void AddValue(XmlNodeRef node, cstr name, const T& value)
  49. {
  50.         node->newChild(name)->setAttr("value", value);
  51. }
  52.  
  53. template<typename T>
  54. void AddValue(XmlNodeRef node, cstr name, const Vec2_tpl<T>& value)
  55. {
  56.         XmlNodeRef paramNode = node->newChild(name);
  57.         AddValue(paramNode, "Element", value.x);
  58.         AddValue(paramNode, "Element", value.y);
  59. }
  60.  
  61. template<typename T>
  62. void AddValue(XmlNodeRef node, cstr name, const Vec3_tpl<T>& value)
  63. {
  64.         XmlNodeRef paramNode = node->newChild(name);
  65.         AddValue(paramNode, "Element", value.x);
  66.         AddValue(paramNode, "Element", value.y);
  67.         AddValue(paramNode, "Element", value.z);
  68. }
  69.  
  70. void AddValue(XmlNodeRef node, cstr name, const Color3F& color)
  71. {
  72.         XmlNodeRef paramNode = node->newChild(name);
  73.         AddValue(paramNode, "Element", float_to_ufrac8(color.x));
  74.         AddValue(paramNode, "Element", float_to_ufrac8(color.y));
  75.         AddValue(paramNode, "Element", float_to_ufrac8(color.z));
  76. }
  77.  
  78. template<typename T>
  79. void AddValue(XmlNodeRef node, cstr name, const Vec3_Zero<T>& value)
  80. {
  81.         // Convert Y-up to Z-up.
  82.         XmlNodeRef paramNode = node->newChild(name);
  83.         AddValue(paramNode, "Element", value.x);
  84.         if (T(-value.z))
  85.                 // signed and non-zero
  86.                 AddValue(paramNode, "Element", -value.z);
  87.         else
  88.                 // unsigned or zero
  89.                 AddValue(paramNode, "Element", value.z);
  90.         AddValue(paramNode, "Element", value.y);
  91. }
  92.  
  93. template<typename T, typename D>
  94. void ConvertValue(XmlNodeRef node, cstr name, T& value, D defValue)
  95. {
  96.         if (value != T(defValue))
  97.         {
  98.                 AddValue(node, name, value);
  99.                 value = T(defValue);
  100.         }
  101. }
  102.  
  103. template<typename T>
  104. void ConvertValue(XmlNodeRef node, cstr name, T& value)
  105. {
  106.         ConvertValue(node, name, value, T());
  107. }
  108.  
  109. template<typename T>
  110. void ConvertValueString(XmlNodeRef node, cstr name, T& value, T defValue = T())
  111. {
  112.         if (value != defValue)
  113.         {
  114.                 AddValue(node, name, TypeInfo(&value).ToString(&value));
  115.                 value = defValue;
  116.         }
  117. }
  118.  
  119. template<typename T>
  120. void ConvertScalarValue(XmlNodeRef node, cstr name, Vec3_tpl<T>& value)
  121. {
  122.         if (value.y)
  123.                 AddValue(node, name, value.y);
  124.         value.zero();
  125. }
  126.  
  127. template<typename T>
  128. struct SerializeNames
  129. {
  130.         static cstr value() { return "value"; }
  131.         static cstr mods()  { return "modifiers"; }
  132.         static cstr curve() { return "Curve"; }
  133. };
  134.  
  135. template<>
  136. struct SerializeNames<Color3F>
  137. {
  138.         static cstr value() { return "Color"; }
  139.         static cstr mods()  { return "Modifiers"; }
  140.         static cstr curve() { return "ColorCurve"; }
  141. };
  142.  
  143. XmlNodeRef AddPtrElement(XmlNodeRef container, cstr typeName)
  144. {
  145.         XmlNodeRef elem = container->newChild("Element");
  146.         AddValue(elem, "type", typeName);
  147.         return elem->newChild("data");
  148. }
  149.  
  150. // Convert pfx1 variant parameters, with randomness and time curves
  151. template<typename T>
  152. void AddParamMods(XmlNodeRef mods, TVarParam<T>& param)
  153. {
  154.         if (param.GetRandomRange())
  155.         {
  156.                 XmlNodeRef data = AddPtrElement(mods, "Random");
  157.                 AddValue(data, "Amount", param.GetRandomRange());
  158.         }
  159. }
  160.  
  161. template<>
  162. void AddParamMods(XmlNodeRef mods, TVarParam<Color3F>& param)
  163. {
  164.         if (param.GetRandomRange())
  165.         {
  166.                 XmlNodeRef data = AddPtrElement(mods, "ColorRandom");
  167.                 if (param.GetRandomRange().HasRandomHue())
  168.                         AddValue(data, "RGB", param.GetRandomRange());
  169.                 else
  170.                         AddValue(data, "Luminance", param.GetRandomRange());
  171.         }
  172. }
  173.  
  174. template<typename T>
  175. void AddCurve(XmlNodeRef node, const TCurve<T>& curve)
  176. {
  177.         AddValue(node, "Curve", curve.ToString());
  178. }
  179.  
  180. template<>
  181. void AddCurve(XmlNodeRef node, const TCurve<Color3F>& curve)
  182. {
  183.         XmlNodeRef paramNode = node->newChild("ColorCurve");
  184.  
  185.         // Separate out color components into 3 curves
  186.         for (int c = 0; c < 3; ++c)
  187.         {
  188.                 typedef spline::SplineKey<float> KeyType;
  189.                 struct ScalarSpline : public spline::CSplineKeyInterpolator<KeyType>
  190.                 {
  191.                         virtual spline::Formatting GetFormatting() const override
  192.                         {
  193.                                 return ";,:";
  194.                         }
  195.                 };
  196.  
  197.                 ScalarSpline sspline;
  198.  
  199.                 for (int i = 0, n = curve.num_keys(); i < n; ++i)
  200.                 {
  201.                         auto key = curve.key(i);
  202.                         KeyType scalarkey;
  203.                         scalarkey.time = key.time;
  204.                         scalarkey.flags = key.flags;
  205.                         scalarkey.value = key.value[c];
  206.                         sspline.insert_key(scalarkey);
  207.                 }
  208.                 AddValue(paramNode, "Element", sspline.ToString());
  209.         }
  210. }
  211.  
  212. template<typename T>
  213. void AddParamMods(XmlNodeRef mods, TVarEParam<T>& param)
  214. {
  215.         AddParamMods(mods, static_cast<TVarParam<T>&>(param));
  216.         if (param.GetStrengthCurve()(VMIN) != T(1.f))
  217.         {
  218.                 XmlNodeRef data = AddPtrElement(mods, SerializeNames<T>::curve());
  219.                 AddValue(data, "TimeSource", "ParentTime");
  220.                 AddValue(data, "SpawnOnly", "true");
  221.                 AddCurve(data, param.GetStrengthCurve());
  222.         }
  223. }
  224.  
  225. template<typename T>
  226. void AddParamMods(XmlNodeRef mods, TVarEPParam<T>& param)
  227. {
  228.         AddParamMods(mods, static_cast<TVarEParam<T>&>(param));
  229.         if (param.GetAgeCurve()(VMIN) != T(1.f))
  230.         {
  231.                 XmlNodeRef data = AddPtrElement(mods, SerializeNames<T>::curve());
  232.                 AddValue(data, "TimeSource", "SelfTime");
  233.                 AddCurve(data, param.GetAgeCurve());
  234.         }
  235. }
  236.  
  237. template<typename P>
  238. bool ConvertParam(XmlNodeRef node, cstr name, P& param, float defValue = 0.f)
  239. {
  240.         typedef typename P::T PT;
  241.         if (param(VMAX) == PT(0))
  242.                 ResetValue(param);
  243.         if (IsConstant(param, PT(defValue)))
  244.                 return false;
  245.  
  246.         XmlNodeRef p = node->newChild(name);
  247.         AddValue(p, SerializeNames<PT>::value(), param(VMAX));
  248.         XmlNodeRef mods = p->newChild(SerializeNames<PT>::mods());
  249.         AddParamMods(mods, param);
  250.  
  251.         // Reset param to default value, to mark converted
  252.         ResetValue(param, defValue);
  253.         return true;
  254. }
  255.  
  256. // Convert just the base value of a pfx1 variant parameter; the variance remains unconverted
  257. template<typename P>
  258. bool ConvertParamBase(XmlNodeRef node, cstr name, P& param, float defValue = 0.f)
  259. {
  260.         if (param(VMAX) == 0.f)
  261.                 ResetValue(param);
  262.         if (param(VMAX) == defValue)
  263.                 return false;
  264.  
  265.         AddValue(node, name, param(VMAX));
  266.  
  267.         param.Set(defValue);
  268.         return true;
  269. }
  270.  
  271. ///////////////////////////////////////////////////////////////////////
  272. // Feature creation
  273.  
  274. void AddFeature(IParticleComponent& component, XmlNodeRef params, bool force = false);
  275.  
  276. void LogError(const string& error, IParticleComponent* component = 0)
  277. {
  278.         if (component)
  279.         {
  280.                 gEnv->pLog->Log(" Component %s: ! %s", component->GetName(), error.c_str());
  281.  
  282.                 static int nest = 0;
  283.                 if (!nest++)
  284.                 {
  285.                         // component->SetComment(string(component->GetComment()) + "! " + error + "\n");
  286.                         XmlNodeRef comment = MakeFeature("GeneralComment");
  287.                         AddValue(comment, "Text", error);
  288.                         AddFeature(*component, comment);
  289.                 }
  290.                 --nest;
  291.         }
  292.         else
  293.         {
  294.                 gEnv->pLog->Log("! %s", error.c_str());
  295.         }
  296. }
  297.  
  298. IParticleFeature* AddFeature(IParticleComponent& component, cstr featureName)
  299. {
  300.         // Search for feature
  301.         uint nFeatures = GetIParticleSystem()->GetNumFeatureParams();
  302.         for (uint i = 0; i < nFeatures; ++i)
  303.         {
  304.                 auto const& fp = GetIParticleSystem()->GetFeatureParam(i);
  305.                 if (string(fp.m_groupName) + fp.m_featureName == featureName)
  306.                 {
  307.                         // Add feature
  308.                         uint index = component.GetNumFeatures();
  309.                         component.AddFeature(index, fp);
  310.                         return component.GetFeature(index);
  311.                 }
  312.         }
  313.  
  314.         LogError(string("Feature not found: ") + featureName, &component);
  315.         return nullptr;
  316. }
  317.  
  318. void AddFeature(IParticleComponent& component, XmlNodeRef params, bool force)
  319. {
  320.         if (force || params->getChildCount())
  321.         {
  322.                 if (IParticleFeature* feature = AddFeature(component, params->getTag()))
  323.                 {
  324.                         if (!Serialization::LoadXmlNode(*feature, params))
  325.                                 LogError(string("Feature serialization error: ") + params->getTag(), &component);
  326.                 }
  327.         }
  328. }
  329.  
  330. ///////////////////////////////////////////////////////////////////////
  331. // Feature-specific conversion
  332.  
  333. void ConvertChild(IParticleComponent& parent, IParticleComponent& component, ParticleParams& params)
  334. {
  335.         XmlNodeRef feature;
  336.  
  337.         switch (params.eSpawnIndirection)
  338.         {
  339.         case ParticleParams::ESpawn::ParentStart:
  340.                 feature = MakeFeature("SecondGenOnSpawn");
  341.                 break;
  342.         case ParticleParams::ESpawn::ParentDeath:
  343.                 feature = MakeFeature("SecondGenOnDeath");
  344.                 break;
  345.         default:
  346.                 return;
  347.         }
  348.  
  349.         XmlNodeRef comp = feature->newChild("Components");
  350.         AddValue(comp, "Element", component.GetName());
  351.         AddFeature(parent, feature);
  352.  
  353.         ResetValue(params.eSpawnIndirection);
  354. }
  355.  
  356. void ConvertSpawn(IParticleComponent& component, ParticleParams& params)
  357. {
  358.         XmlNodeRef spawn;
  359.  
  360.         spawn = MakeFeature("SpawnCount");
  361.  
  362.         ConvertParam(spawn, "Amount", params.fCount);
  363.         ConvertParam(spawn, "Delay", params.fSpawnDelay);
  364.         if (params.bContinuous)
  365.         {
  366.                 XmlNodeRef delay = spawn->newChild("Duration");
  367.                 delay->newChild("State")->setAttr("value", params.fEmitterLifeTime ? "true" : "false");
  368.                 ConvertParam(delay, "Value", params.fEmitterLifeTime);
  369.         }
  370.  
  371.         AddFeature(component, spawn);
  372.  
  373.         if (params.fParticleLifeTime)
  374.         {
  375.                 XmlNodeRef life = MakeFeature("LifeTime");
  376.                 ConvertParam(life, "LifeTime", params.fParticleLifeTime);
  377.                 AddFeature(component, life);
  378.         }
  379. }
  380.  
  381. void ConvertAppearance(IParticleComponent& component, ParticleParams& params)
  382. {
  383.         // Blending feature
  384.         XmlNodeRef blending = MakeFeature("AppearanceBlending");
  385.         ConvertValueString(blending, "BlendMode", params.eBlendType, ParticleParams::EBlend(ParticleParams::EBlend::AlphaBased));
  386.         AddFeature(component, blending);
  387.  
  388.         // Material feature
  389.         XmlNodeRef material = MakeFeature("AppearanceMaterial");
  390.  
  391.         if (!params.sMaterial.empty())
  392.                 ConvertValueString(material, "Material", params.sMaterial);
  393.         if (!params.sTexture.empty())
  394.                 ConvertValueString(material, "Texture", params.sTexture);
  395.  
  396.         AddFeature(component, material);
  397.  
  398.         // TextureTiling feature
  399.         auto& tiling = params.TextureTiling;
  400.         if (tiling.nTilesX > 1 || tiling.nTilesY > 1)
  401.         {
  402.                 XmlNodeRef tile = MakeFeature("AppearanceTexture Tiling");
  403.                 ConvertValue(tile, "TilesX", tiling.nTilesX);
  404.                 ConvertValue(tile, "TilesY", tiling.nTilesY);
  405.                 ConvertValue(tile, "FirstTile", tiling.nFirstTile);
  406.                 AddValue(tile, "TileCount", ResetValue(tiling.nVariantCount) * tiling.nAnimFramesCount);
  407.  
  408.                 if (tiling.nAnimFramesCount > 1)
  409.                 {
  410.                         XmlNodeRef anim = tile->newChild("Animation");
  411.                         ConvertValue(anim, "FrameCount", tiling.nAnimFramesCount);
  412.                         ConvertValue(anim, "FrameRate", tiling.fAnimFramerate);
  413.                         ConvertValueString(anim, "CycleMode", tiling.eAnimCycle);
  414.                         ConvertValue(anim, "FrameBlending", tiling.bAnimBlend);
  415.                 }
  416.                 AddFeature(component, tile);
  417.         }
  418.  
  419.         // Lighting feature
  420.         XmlNodeRef lighting = MakeFeature("AppearanceLighting");
  421.         if (params.fDiffuseLighting != 1.f)
  422.         {
  423.                 AddValue(lighting, "Albedo", params.fDiffuseLighting * 100.f);
  424.                 params.fDiffuseLighting = 1.f;
  425.         }
  426.         if (params.fDiffuseLighting && params.fCurvature)
  427.                 AddValue(lighting, "Curvature", params.fCurvature);
  428.         params.fCurvature = 1.f;
  429.         bool affecteByFog = !params.bNotAffectedByFog;
  430.         ConvertValue(lighting, "BackLight", params.fDiffuseBacklighting);
  431.         ConvertValue(lighting, "Emissive", params.fEmissiveLighting);
  432.         ConvertValue(lighting, "ReceiveShadows", params.bReceiveShadows);
  433.         ConvertValue(lighting, "AffectedByFog", affecteByFog);
  434.  
  435.         AddFeature(component, lighting);
  436.  
  437.         if (params.bSoftParticle)
  438.         {
  439.                 XmlNodeRef soft = MakeFeature("AppearanceSoftIntersect");
  440.                 AddValue(soft, "Softness", params.bSoftParticle.fSoftness);
  441.                 ResetValue(params.bSoftParticle);
  442.                 AddFeature(component, soft);
  443.         }
  444. }
  445.  
  446. void ConvertSprites(IParticleComponent& component, ParticleParams& params)
  447. {
  448.         if ((!params.sTexture.empty() || !params.sMaterial.empty()) && params.sGeometry.empty())
  449.         {
  450.                 // RenderSprite feature
  451.                 XmlNodeRef sprite = MakeFeature("RenderSprites");
  452.  
  453.                 if (params.eFacing == ParticleParams::EFacing::Camera)
  454.                 {
  455.                         ResetValue(params.eFacing);
  456.                         if (ResetValue(params.bOrientToVelocity) || params.fStretch)
  457.                         {
  458.                                 AddValue(sprite, "FacingMode", "Velocity");
  459.                                 ConvertParamBase(sprite, "AxisScale", params.fStretch);
  460.                         }
  461.                         else
  462.                                 AddValue(sprite, "FacingMode", "Camera");
  463.                         AddValue(sprite, "SphericalProjection", ResetValue(params.fSphericalApproximation, 1.f));
  464.                 }
  465.                 else if (params.eFacing == ParticleParams::EFacing::Free)
  466.                 {
  467.                         ResetValue(params.eFacing);
  468.                         AddValue(sprite, "FacingMode", "Free");
  469.                 }
  470.  
  471.                 ConvertParamBase(sprite, "AspectRatio", params.fAspect, 1.f);
  472.  
  473.                 AddFeature(component, sprite);
  474.  
  475.                 ConvertAppearance(component, params);
  476.         }
  477. }
  478.  
  479. void ConvertGeometry(IParticleComponent& component, ParticleParams& params)
  480. {
  481.         if (!params.sGeometry.empty())
  482.         {
  483.                 XmlNodeRef mesh = MakeFeature("RenderMeshes");
  484.                 ConvertValueString(mesh, "Mesh", params.sGeometry);
  485.  
  486.                 AddValue(mesh, "Scale", Vec3(params.fSize(VMAX)));
  487.                 params.fSize.Set(1.0f);
  488.  
  489.                 AddValue(mesh, "SizeMode", "Scale");
  490.                 AddValue(mesh, "OriginMode", params.bNoOffset ? "Origin" : "Center");
  491.                 AddValue(mesh, "PiecePlacement", ResetValue(params.bNoOffset) ? "SubPlacement" : "Standard");
  492.  
  493.                 ConvertValueString(mesh, "PiecesMode", params.eGeometryPieces);
  494.  
  495.                 // Material feature
  496.                 if (!params.sMaterial.empty())
  497.                 {
  498.                         XmlNodeRef material = MakeFeature("AppearanceMaterial");
  499.                         ConvertValueString(material, "Material", params.sMaterial);
  500.                         AddFeature(component, material);
  501.                 }
  502.  
  503.                 if (params.eFacing == ParticleParams::EFacing::Free)
  504.                         ResetValue(params.eFacing);
  505.  
  506.                 // Clear unused params
  507.                 ResetValue(params.sTexture);
  508.                 ResetValue(params.eBlendType);
  509.                 ResetValue(params.TextureTiling);
  510.                 ResetValue(params.fDiffuseLighting);
  511.                 ResetValue(params.fDiffuseBacklighting);
  512.                 ResetValue(params.fEmissiveLighting);
  513.                 ResetValue(params.bCastShadows);
  514.                 ResetValue(params.bReceiveShadows);
  515.                 ResetValue(params.bSoftParticle);
  516.  
  517.                 AddFeature(component, mesh);
  518.         }
  519. }
  520.  
  521. void ConvertFields(IParticleComponent& component, ParticleParams& params)
  522. {
  523.         // Opacity
  524.         XmlNodeRef opacity = MakeFeature("FieldOpacity");
  525.         ConvertParam(opacity, "value", params.fAlpha, 1.f);
  526.         ConvertValue(opacity, "AlphaScale", reinterpret_cast<Vec2&>(params.AlphaClip.fScale), Vec2(0, 1));
  527.         ConvertValue(opacity, "ClipLow", reinterpret_cast<Vec2&>(params.AlphaClip.fSourceMin), Vec2(0, 0));
  528.         ConvertValue(opacity, "ClipRange", reinterpret_cast<Vec2&>(params.AlphaClip.fSourceWidth), Vec2(1, 1));
  529.         AddFeature(component, opacity);
  530.  
  531.         // Color
  532.         XmlNodeRef color = MakeFeature("FieldColor");
  533.         ConvertParam(color, "Color", params.cColor, 1.f);
  534.         AddFeature(component, color);
  535.  
  536.         // Size
  537.         XmlNodeRef size = MakeFeature("FieldSize");
  538.         ConvertParam(size, "value", params.fSize);
  539.         ResetValue(params.fSize, 1.f);
  540.         AddFeature(component, size);
  541.  
  542.         // Pixel size
  543.         if (params.fMinPixels)
  544.         {
  545.                 XmlNodeRef pix = MakeFeature("FieldPixelSize");
  546.                 ConvertValue(pix, "MinSize", params.fMinPixels);
  547.                 AddValue(pix, "AffectOpacity", false);
  548.                 AddFeature(component, pix);
  549.         }
  550. }
  551.  
  552. void ConvertLocation(IParticleComponent& component, ParticleParams& params)
  553. {
  554.         if (params.eAttachType)
  555.         {
  556.                 XmlNodeRef attach = MakeFeature("LocationGeometry");
  557.                 ConvertValueString(attach, "Source", params.eAttachType);
  558.                 ConvertValueString(attach, "Location", params.eAttachForm);
  559.                 if (params.fSpeed)
  560.                 {
  561.                         AddValue(attach, "OrientParticles", true);
  562.                         if (params.fStretch)
  563.                         {
  564.                                 TVarEParam<::UFloat> offset = params.fStretch;
  565.                                 offset.Set(offset(VMAX) * params.fStretch.fOffsetRatio * params.fSpeed(VMAX));
  566.                                 ConvertParam(attach, "Offset", offset);
  567.                         }
  568.                 }
  569.                 ConvertParam(attach, "Velocity", params.fSpeed);
  570.                 AddFeature(component, attach);
  571.         }
  572.  
  573.         if (ResetValue(params.bSpaceLoop))
  574.         {
  575.                 XmlNodeRef omni = MakeFeature("LocationOmni");
  576.                 TVarParam<UFloat> vis(max<float>(params.fCameraMaxDistance, params.vPositionOffset.y + params.vRandomOffset.y));
  577.                 ResetValue(params.fCameraMaxDistance);
  578.                 ResetValue(params.vPositionOffset);
  579.                 ResetValue(params.vRandomOffset);
  580.                 ConvertParam(omni, "Visibility", vis);
  581.                 AddFeature(component, omni);
  582.         }
  583.  
  584.         XmlNodeRef loc = MakeFeature("LocationOffset");
  585.         ConvertValue(loc, "Offset", params.vPositionOffset);
  586.         AddFeature(component, loc);
  587.  
  588.         if (params.vRandomOffset.IsZero())
  589.         {
  590.                 params.fOffsetRoundness = params.fOffsetInnerFraction = 0.f;
  591.         }
  592.         if (params.fOffsetRoundness < 0.5f)
  593.         {
  594.                 XmlNodeRef box = MakeFeature("LocationBox");
  595.                 ConvertValue(box, "Dimension", params.vRandomOffset);
  596.                 AddFeature(component, box);
  597.         }
  598.         else
  599.         {
  600.                 XmlNodeRef sphere = MakeFeature("LocationSphere");
  601.                 ConvertValue(sphere, "AxisScale", params.vRandomOffset);
  602.                 TVarParam<::UFloat> radius(1.f);
  603.                 ConvertParam(sphere, "Radius", radius);
  604.                 AddFeature(component, sphere);
  605.                 if (params.fOffsetRoundness == 1.f)
  606.                         params.fOffsetRoundness = 0.f;
  607.         }
  608. }
  609.  
  610. void ConvertMotion(IParticleComponent& component, ParticleParams& params)
  611. {
  612.         bool hasMotion = false;
  613.         if (params.fSpeed)
  614.         {
  615.                 hasMotion = true;
  616.                 if (!params.fEmitAngle)
  617.                 {
  618.                         XmlNodeRef vel = MakeFeature("VelocityDirectional");
  619.                         ConvertParam(vel, "Scale", params.fSpeed);
  620.                         AddValue(vel, "Velocity", Vec3(0, 0, 1));
  621.                         AddFeature(component, vel);
  622.                 }
  623.                 else if (params.fEmitAngle(VMAX) == 180.f && params.fEmitAngle(VMIN) == 0.0f)
  624.                 {
  625.                         XmlNodeRef vel = MakeFeature("VelocityOmniDirectional");
  626.                         ConvertParam(vel, "Velocity", params.fSpeed);
  627.                         AddFeature(component, vel);
  628.                 }
  629.                 else
  630.                 {
  631.                         XmlNodeRef vel = MakeFeature("VelocityCone");
  632.                         ConvertParam(vel, "Velocity", params.fSpeed);
  633.                         ConvertParam(vel, "Angle", params.fEmitAngle);
  634.                         AddFeature(component, vel);
  635.                 }
  636.                 if (params.fFocusAngle || params.fFocusAzimuth)
  637.                 {
  638.                         XmlNodeRef vel = MakeFeature("VelocityCompass");
  639.                         ConvertParam(vel, "Azimuth", params.fFocusAzimuth);
  640.                         ConvertParam(vel, "Angle", params.fFocusAngle);
  641.                         ConvertParam(vel, "Velocity", params.fSpeed);
  642.                         AddFeature(component, vel);
  643.                 }
  644.         }
  645.         else
  646.         {
  647.                 ResetValue(params.fSpeed);
  648.                 ResetValue(params.fEmitAngle);
  649.         }
  650.         if (params.fInheritVelocity)
  651.         {
  652.                 hasMotion = true;
  653.                 XmlNodeRef vel = MakeFeature("VelocityInherit");
  654.                 TVarParam<SFloat> scale(ResetValue(params.fInheritVelocity));
  655.                 ConvertParam(vel, "Scale", scale);
  656.                 AddFeature(component, vel);
  657.         }
  658.         if (ResetValue(params.bMoveRelativeEmitter))
  659.         {
  660.                 hasMotion = true;
  661.                 XmlNodeRef vel = MakeFeature("VelocityMoveRelativeToEmitter");
  662.                 AddValue(vel, "PositionInherit", 1.f);
  663.                 AddFeature(component, vel);
  664.         }
  665.  
  666.         // General motion physics
  667.         XmlNodeRef phys = MakeFeature("MotionPhysics");
  668.         ConvertParam(phys, "gravity", params.fGravityScale);
  669.         if (params.fAirResistance(VMAX) == 0.f)
  670.                 ResetValue(params.fAirResistance);
  671.         ConvertParam(phys, "drag", static_cast<TVarEPParam<::UFloat>&>(params.fAirResistance));
  672.         ConvertValue(phys, "UniformAcceleration", params.vAcceleration);
  673.         ConvertValue(phys, "WindMultiplier", params.fAirResistance.fWindScale, 1.f);
  674.         ConvertValue(phys, "AngularDragMultiplier", params.fAirResistance.fRotationalDragScale, 1.f);
  675.  
  676.         if (params.fTurbulence3DSpeed)
  677.         {
  678.                 XmlNodeRef effectors = phys->newChild("localEffectors");
  679.                 XmlNodeRef data = AddPtrElement(effectors, "Turbulence");
  680.                 AddValue(data, "mode", "Brownian");
  681.                 ConvertParamBase(data, "speed", params.fTurbulence3DSpeed);
  682.         }
  683.  
  684.         AddFeature(component, phys, hasMotion);
  685. }
  686.  
  687. void ConvertAngles2D(IParticleComponent& component, ParticleParams& params)
  688. {
  689.         XmlNodeRef ang = MakeFeature("AnglesRotate2D");
  690.         ConvertScalarValue(ang, "InitialAngle", params.vInitAngles);
  691.         ConvertScalarValue(ang, "RandomAngle", params.vRandomAngles);
  692.         ConvertScalarValue(ang, "InitialSpin", params.vRotationRate);
  693.         ConvertScalarValue(ang, "RandomSpin", params.vRandomRotationRate);
  694.         AddFeature(component, ang);
  695. }
  696.  
  697. void ConvertAngles3D(IParticleComponent& component, ParticleParams& params)
  698. {
  699.         XmlNodeRef ang = MakeFeature("AnglesRotate3D");
  700.         ConvertValue(ang, "InitialAngle", params.vInitAngles);
  701.         ConvertValue(ang, "RandomAngle", params.vRandomAngles);
  702.         ConvertValue(ang, "InitialSpin", params.vRotationRate);
  703.         ConvertValue(ang, "RandomSpin", params.vRandomRotationRate);
  704.         AddFeature(component, ang);
  705. }
  706.  
  707. void ConvertVisibility(IParticleComponent& component, ParticleParams& params)
  708. {
  709.         XmlNodeRef vis = MakeFeature("AppearanceVisibility");
  710.         ConvertValue(vis, "ViewDistanceMultiple", params.fViewDistanceAdjust, 1.f);
  711.         ConvertValue(vis, "MinCameraDistance", params.fCameraMinDistance);
  712.         ConvertValue(vis, "MaxCameraDistance", params.fCameraMaxDistance);
  713.         ConvertValue(vis, "DrawNear", params.bDrawNear);
  714.         ConvertValue(vis, "DrawOnTop", params.bDrawOnTop);
  715.         AddFeature(component, vis);
  716. }
  717.  
  718. void ConvertConfigSpec(IParticleComponent& component, ParticleParams& params)
  719. {
  720.         if (params.eConfigMin == ParticleParams::EConfigSpecBrief::Low &&
  721.                 params.eConfigMax == ParticleParams::EConfigSpecBrief::VeryHigh &&
  722.                 params.Platforms.PCDX11 && params.Platforms.XBoxOne && params.Platforms.PS4)
  723.                 return;
  724.  
  725.         auto toString = [](ParticleParams::EConfigSpecBrief config)
  726.         {
  727.                 switch (config)
  728.                 {
  729.                 case ParticleParams::EConfigSpecBrief::Medium: return "Medium";
  730.                 case ParticleParams::EConfigSpecBrief::High: return "High";
  731.                 case ParticleParams::EConfigSpecBrief::VeryHigh: return "VeryHigh";
  732.                 default: return "Low";
  733.                 }
  734.         };
  735.         const char* minName = toString(params.eConfigMin);
  736.         const char* maxName = toString(params.eConfigMax);
  737.  
  738.         XmlNodeRef spec = MakeFeature("ComponentEnableByConfig");
  739.         ConvertValue(spec, "Minimum", minName);
  740.         ConvertValue(spec, "Maximum", maxName);
  741.         ConvertValue(spec, "PC", params.Platforms.PCDX11);
  742.         ConvertValue(spec, "XBoxOne", params.Platforms.XBoxOne);
  743.         ConvertValue(spec, "PS4", params.Platforms.PS4);
  744.         AddFeature(component, spec);
  745. }
  746.  
  747. // Convert all features
  748. void ConvertParamsToFeatures(IParticleComponent& component, const ParticleParams& origParams, IParticleComponent* pParent = nullptr)
  749. {
  750.         ParticleParams params = origParams;
  751.  
  752.         // Convert params to features, resetting params as we do.
  753.         // Any non-default params afterwards have not been converted.
  754.         if (pParent)
  755.                 ConvertChild(*pParent, component, params);
  756.         ConvertSpawn(component, params);
  757.         ConvertSprites(component, params);
  758.         ConvertGeometry(component, params);
  759.         ConvertFields(component, params);
  760.         ConvertLocation(component, params);
  761.         ConvertMotion(component, params);
  762.         if (origParams.eFacing == ParticleParams::EFacing::Free || !origParams.sGeometry.empty())
  763.                 ConvertAngles3D(component, params);
  764.         else
  765.                 ConvertAngles2D(component, params);
  766.         ConvertVisibility(component, params);
  767.         ConvertConfigSpec(component, params);
  768.  
  769.         static ParticleParams defaultParams;
  770.         string unconverted = TypeInfo(&params).ToString(&params, FToString().NamedFields(1).SkipDefault(1), &defaultParams);
  771.         if (!unconverted.empty())
  772.         {
  773.                 unconverted.replace(",", ", ");
  774.                 LogError("Unconverted parameters: " + unconverted, &component);
  775.         }
  776. }
  777.  
  778. void ConvertSubEffects(IParticleEffectPfx2& newEffect, const ::IParticleEffect& oldSubEffect, IParticleComponent* pParent = nullptr)
  779. {
  780.         IParticleComponent* component = nullptr;
  781.         if (oldSubEffect.IsEnabled())
  782.         {
  783.                 if (!oldSubEffect.GetParticleParams().eSpawnIndirection || pParent)
  784.                 {
  785.                         uint index = newEffect.GetNumComponents();
  786.                         newEffect.AddComponent(index);
  787.                         component = newEffect.GetComponent(index);
  788.  
  789.                         cstr name = oldSubEffect.GetName();
  790.                         if (cstr base = strrchr(name, '.'))
  791.                         {
  792.                                 name = base + 1;
  793.                         }
  794.                         component->SetName(name);
  795.  
  796.                         ConvertParamsToFeatures(*component, oldSubEffect.GetParticleParams(), pParent);
  797.                 }
  798.         }
  799.  
  800.         int childCount = oldSubEffect.GetChildCount();
  801.         for (int i = 0; i < childCount; ++i)
  802.         {
  803.                 ConvertSubEffects(newEffect, *oldSubEffect.GetChild(i), component);
  804.         }
  805. }
  806.  
  807. string CParticleSystem::ConvertPfx1Name(cstr oldEffectName)
  808. {
  809.         string newName = string(gEnv->pCryPak->GetGameFolder()) + "/Particles/pfx1/";
  810.         newName += oldEffectName;
  811.         newName.replace('.', '/');
  812.         newName += ".pfx";
  813.         return newName;
  814. }
  815.  
  816. PParticleEffect CParticleSystem::ConvertEffect(const ::IParticleEffect* pOldEffect, bool bReplace)
  817. {
  818.         string oldName = pOldEffect->GetFullName();
  819.         string newName = ConvertPfx1Name(oldName);
  820.         PParticleEffect pNewEffect = FindEffect(newName);
  821.         if (pNewEffect && !bReplace)
  822.                 return pNewEffect;
  823.  
  824.         pNewEffect = CreateEffect();
  825.         RenameEffect(pNewEffect, newName);
  826.         gEnv->pLog->Log("PFX1 to PFX2 \"%s\":", oldName.c_str());
  827.         ConvertSubEffects(*pNewEffect, *pOldEffect);
  828.  
  829.         gEnv->pLog->Log(" - Saving as \"%s\":", newName.c_str());
  830.         gEnv->pCryPak->MakeDir(PathUtil::GetParentDirectory(newName).c_str());
  831.         Serialization::SaveJsonFile(newName, *pNewEffect);
  832.  
  833.         return pNewEffect;
  834. }
  835.  
  836. }
  837.  
downloadParticleConvert.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