Fix missing particle layout attributes when using Particle Emitter Function
#1640
This commit is contained in:
@@ -37,12 +37,12 @@ public:
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Flag valid for used particle nodes that need per-particle data to evaluate its value (including dependant nodes linked to input boxes). Used to skip per-particle graph evaluation if graph uses the same value for all particles (eg. is not using per-particle seed or position node).
|
/// Flag valid for used particle nodes that need per-particle data to evaluate its value (including dependant nodes linked to input boxes). Used to skip per-particle graph evaluation if graph uses the same value for all particles (eg. is not using per-particle seed or position node).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool UsesParticleData;
|
bool UsesParticleData = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Flag valid for used particle nodes that result in constant data (nothing random nor particle data).
|
/// Flag valid for used particle nodes that result in constant data (nothing random nor particle data).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool IsConstant;
|
bool IsConstant = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The cached particle attribute indices used by the simulation graph to access particle properties.
|
/// The cached particle attribute indices used by the simulation graph to access particle properties.
|
||||||
@@ -50,6 +50,8 @@ public:
|
|||||||
int32 Attributes[PARTICLE_EMITTER_MAX_ATTRIBUTES_REFS_PER_NODE];
|
int32 Attributes[PARTICLE_EMITTER_MAX_ATTRIBUTES_REFS_PER_NODE];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void InitParticleEmitterFunctionCall(const Guid& assetId, AssetReference<Asset>& asset, bool& usesParticleData, ParticleLayout& layout);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Particle Emitter Graph used to simulate particles.
|
/// The Particle Emitter Graph used to simulate particles.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -157,8 +159,6 @@ public:
|
|||||||
if (node->Used)
|
if (node->Used)
|
||||||
return;
|
return;
|
||||||
node->Used = true;
|
node->Used = true;
|
||||||
node->UsesParticleData = false;
|
|
||||||
node->IsConstant = true;
|
|
||||||
|
|
||||||
#define USE_ATTRIBUTE(name, valueType, slot) \
|
#define USE_ATTRIBUTE(name, valueType, slot) \
|
||||||
{ \
|
{ \
|
||||||
@@ -292,14 +292,11 @@ public:
|
|||||||
case GRAPH_NODE_MAKE_TYPE(14, 214):
|
case GRAPH_NODE_MAKE_TYPE(14, 214):
|
||||||
case GRAPH_NODE_MAKE_TYPE(14, 215):
|
case GRAPH_NODE_MAKE_TYPE(14, 215):
|
||||||
case GRAPH_NODE_MAKE_TYPE(14, 216):
|
case GRAPH_NODE_MAKE_TYPE(14, 216):
|
||||||
{
|
|
||||||
node->IsConstant = false;
|
node->IsConstant = false;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
// Particle Emitter Function
|
// Particle Emitter Function
|
||||||
case GRAPH_NODE_MAKE_TYPE(14, 300):
|
case GRAPH_NODE_MAKE_TYPE(14, 300):
|
||||||
node->Assets[0] = Content::LoadAsync<Asset>((Guid)node->Values[0]);
|
InitParticleEmitterFunctionCall((Guid)node->Values[0], node->Assets[0], node->UsesParticleData, Layout);
|
||||||
node->UsesParticleData = true; // TODO: analyze emitter function graph to detect if it's actually using any particle data at all (even from inputs after inline)
|
|
||||||
break;
|
break;
|
||||||
// Particle Index
|
// Particle Index
|
||||||
case GRAPH_NODE_MAKE_TYPE(14, 301):
|
case GRAPH_NODE_MAKE_TYPE(14, 301):
|
||||||
@@ -564,7 +561,7 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Compute particle data layout and initialize used nodes (for only used nodes, start depth searching rom the modules)
|
// Compute particle data layout and initialize used nodes (for only used nodes, start depth searching rom the modules)
|
||||||
Layout.AddAttribute(TEXT("Position"), ParticleAttribute::ValueTypes::Float3);
|
//Layout.AddAttribute(TEXT("Position"), ParticleAttribute::ValueTypes::Float3);
|
||||||
#define PROCESS_MODULES(modules) for (int32 i = 0; i < modules.Count(); i++) { modules[i]->Used = false; InitializeNode(modules[i]); }
|
#define PROCESS_MODULES(modules) for (int32 i = 0; i < modules.Count(); i++) { modules[i]->Used = false; InitializeNode(modules[i]); }
|
||||||
PROCESS_MODULES(SpawnModules);
|
PROCESS_MODULES(SpawnModules);
|
||||||
PROCESS_MODULES(InitModules);
|
PROCESS_MODULES(InitModules);
|
||||||
|
|||||||
@@ -9,6 +9,27 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "Engine/Content/Factories/BinaryAssetFactory.h"
|
#include "Engine/Content/Factories/BinaryAssetFactory.h"
|
||||||
|
|
||||||
|
void InitParticleEmitterFunctionCall(const Guid& assetId, AssetReference<Asset>& asset, bool& usesParticleData, ParticleLayout& layout)
|
||||||
|
{
|
||||||
|
const auto function = Content::Load<ParticleEmitterFunction>(assetId);
|
||||||
|
asset = function;
|
||||||
|
if (function)
|
||||||
|
{
|
||||||
|
// Insert any used particle data into the calling graph
|
||||||
|
for (const ParticleAttribute& e : function->Graph.Layout.Attributes)
|
||||||
|
{
|
||||||
|
if (layout.FindAttribute(e.Name, e.ValueType) == -1)
|
||||||
|
layout.AddAttribute(e.Name, e.ValueType);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect if function needs to be evaluated per-particle
|
||||||
|
for (int32 i = 0; i < function->Outputs.Count() && !usesParticleData; i++)
|
||||||
|
{
|
||||||
|
usesParticleData = function->Graph.Nodes[function->Outputs.Get()[i]].UsesParticleData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
REGISTER_BINARY_ASSET(ParticleEmitterFunction, "FlaxEngine.ParticleEmitterFunction", false);
|
REGISTER_BINARY_ASSET(ParticleEmitterFunction, "FlaxEngine.ParticleEmitterFunction", false);
|
||||||
|
|
||||||
ParticleEmitterFunction::ParticleEmitterFunction(const SpawnParams& params, const AssetInfo* info)
|
ParticleEmitterFunction::ParticleEmitterFunction(const SpawnParams& params, const AssetInfo* info)
|
||||||
|
|||||||
@@ -262,11 +262,11 @@ protected:
|
|||||||
|
|
||||||
FORCE_INLINE Value tryGetValue(Box* box)
|
FORCE_INLINE Value tryGetValue(Box* box)
|
||||||
{
|
{
|
||||||
return box && box->HasConnection() ? eatBox(box->GetParent<Node>(), box->FirstConnection()) : Value::Zero;
|
return box && box->Connections.HasItems() ? eatBox(box->GetParent<Node>(), (VisjectGraphBox*)box->Connections.Get()[0]) : Value::Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE Value tryGetValue(Box* box, const Value& defaultValue)
|
FORCE_INLINE Value tryGetValue(Box* box, const Value& defaultValue)
|
||||||
{
|
{
|
||||||
return box && box->HasConnection() ? eatBox(box->GetParent<Node>(), box->FirstConnection()) : defaultValue;
|
return box && box->Connections.HasItems() ? eatBox(box->GetParent<Node>(), (VisjectGraphBox*)box->Connections.Get()[0]) : defaultValue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user