@@ -246,6 +246,14 @@ namespace FlaxEditor.Viewport.Previews
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void OnDebugDraw(GPUContext context, ref RenderContext renderContext)
|
||||||
|
{
|
||||||
|
base.OnDebugDraw(context, ref renderContext);
|
||||||
|
|
||||||
|
_previewEffect.OnDebugDraw();
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void Draw()
|
public override void Draw()
|
||||||
{
|
{
|
||||||
@@ -295,7 +303,8 @@ namespace FlaxEditor.Viewport.Previews
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override void OnDestroy()
|
public override void OnDestroy()
|
||||||
{
|
{
|
||||||
// Cleanup objects
|
if (IsDisposing)
|
||||||
|
return;
|
||||||
_previewEffect.ParticleSystem = null;
|
_previewEffect.ParticleSystem = null;
|
||||||
Object.Destroy(ref _previewEffect);
|
Object.Destroy(ref _previewEffect);
|
||||||
Object.Destroy(ref _boundsModel);
|
Object.Destroy(ref _boundsModel);
|
||||||
|
|||||||
@@ -127,6 +127,8 @@ namespace FlaxEditor.Windows.Assets
|
|||||||
PlaySimulation = true,
|
PlaySimulation = true,
|
||||||
Parent = _split2.Panel1
|
Parent = _split2.Panel1
|
||||||
};
|
};
|
||||||
|
_preview.PreviewActor.ShowDebugDraw = true;
|
||||||
|
_preview.ShowDebugDraw = true;
|
||||||
|
|
||||||
// Asset properties proxy
|
// Asset properties proxy
|
||||||
_properties = new PropertiesProxy();
|
_properties = new PropertiesProxy();
|
||||||
|
|||||||
@@ -2,8 +2,16 @@
|
|||||||
|
|
||||||
#include "ParticleEmitterGraph.CPU.h"
|
#include "ParticleEmitterGraph.CPU.h"
|
||||||
#include "Engine/Core/Random.h"
|
#include "Engine/Core/Random.h"
|
||||||
|
#include "Engine/Core/Math/Vector2.h"
|
||||||
|
#include "Engine/Core/Math/Vector3.h"
|
||||||
|
#include "Engine/Core/Math/Vector4.h"
|
||||||
|
#include "Engine/Core/Math/Matrix.h"
|
||||||
|
#include "Engine/Core/Math/Quaternion.h"
|
||||||
|
#include "Engine/Core/Math/BoundingBox.h"
|
||||||
|
#include "Engine/Core/Math/BoundingSphere.h"
|
||||||
|
#include "Engine/Core/Math/OrientedBoundingBox.h"
|
||||||
#include "Engine/Utilities/Noise.h"
|
#include "Engine/Utilities/Noise.h"
|
||||||
#include "Engine/Core/Types/CommonValue.h"
|
#include "Engine/Debug/DebugDraw.h"
|
||||||
|
|
||||||
// ReSharper disable CppCStyleCast
|
// ReSharper disable CppCStyleCast
|
||||||
// ReSharper disable CppClangTidyClangDiagnosticCastAlign
|
// ReSharper disable CppClangTidyClangDiagnosticCastAlign
|
||||||
@@ -1468,3 +1476,89 @@ void ParticleEmitterGraphCPUExecutor::ProcessModule(ParticleEmitterGraphCPUNode*
|
|||||||
#undef COLLISION_LOGIC
|
#undef COLLISION_LOGIC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if USE_EDITOR
|
||||||
|
|
||||||
|
void ParticleEmitterGraphCPUExecutor::DebugDrawModule(ParticleEmitterGraphCPUNode* node, const Transform& transform)
|
||||||
|
{
|
||||||
|
// Skip modules that rely on particle data
|
||||||
|
if (node->UsePerParticleDataResolve())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const Color color = Color::White;
|
||||||
|
switch (node->TypeID)
|
||||||
|
{
|
||||||
|
case 202: // Position (sphere surface)
|
||||||
|
case 211: // Position (sphere volume)
|
||||||
|
{
|
||||||
|
const Float3 center = transform.LocalToWorld((Float3)GetValue(node->GetBox(0), 2));
|
||||||
|
const float radius = (float)GetValue(node->GetBox(1), 3);
|
||||||
|
DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(center, radius), color, 0.0f, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 203: // Position (plane)
|
||||||
|
{
|
||||||
|
const Float3 center = (Float3)GetValue(node->GetBox(0), 2);
|
||||||
|
const Float2 size = (Float2)GetValue(node->GetBox(1), 3);
|
||||||
|
const Float3 halfExtent = Float3(size.X * 0.5f, 0.0f, size.Y * 0.5f);
|
||||||
|
OrientedBoundingBox box(halfExtent, Transform(center));
|
||||||
|
box.Transform(transform);
|
||||||
|
DEBUG_DRAW_WIRE_BOX(box, color, 0.0f, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 204: // Position (circle)
|
||||||
|
case 205: // Position (disc)
|
||||||
|
{
|
||||||
|
const Float3 center = transform.LocalToWorld((Float3)GetValue(node->GetBox(0), 2));
|
||||||
|
const float radius = (float)GetValue(node->GetBox(1), 3);
|
||||||
|
DEBUG_DRAW_WIRE_CYLINDER(center, transform.Orientation * Quaternion::Euler(90, 0, 0), radius, 0.0f, color, 0.0f, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 206: // Position (box surface)
|
||||||
|
case 207: // Position (box volume)
|
||||||
|
{
|
||||||
|
const Float3 center = (Float3)GetValue(node->GetBox(0), 2);
|
||||||
|
const Float3 size = (Float3)GetValue(node->GetBox(1), 3);
|
||||||
|
OrientedBoundingBox box(size * 0.5f, Transform(center));
|
||||||
|
box.Transform(transform);
|
||||||
|
DEBUG_DRAW_WIRE_BOX(box, color, 0.0f, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Position (cylinder)
|
||||||
|
case 208:
|
||||||
|
{
|
||||||
|
const float height = (float)GetValue(node->GetBox(2), 4);
|
||||||
|
const Float3 center = transform.LocalToWorld((Float3)GetValue(node->GetBox(0), 2) + Float3(0, 0, height * 0.5f));
|
||||||
|
const float radius = (float)GetValue(node->GetBox(1), 3);
|
||||||
|
DEBUG_DRAW_WIRE_CYLINDER(center, transform.Orientation * Quaternion::Euler(90, 0, 0), radius, height, color, 0.0f, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Position (line)
|
||||||
|
case 209:
|
||||||
|
{
|
||||||
|
const Float3 start = transform.LocalToWorld((Float3)GetValue(node->GetBox(0), 2));
|
||||||
|
const Float3 end = transform.LocalToWorld((Float3)GetValue(node->GetBox(1), 3));
|
||||||
|
DEBUG_DRAW_LINE(start, end, color, 0.0f, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Position (torus)
|
||||||
|
case 210:
|
||||||
|
{
|
||||||
|
const Float3 center = transform.LocalToWorld((Float3)GetValue(node->GetBox(0), 2));
|
||||||
|
const float radius = Math::Max((float)GetValue(node->GetBox(1), 3), ZeroTolerance);
|
||||||
|
const float thickness = (float)GetValue(node->GetBox(2), 4);
|
||||||
|
DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(center, radius + thickness), color, 0.0f, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Position (spiral)
|
||||||
|
case 214:
|
||||||
|
{
|
||||||
|
const Float3 center = transform.LocalToWorld((Float3)GetValue(node->GetBox(0), 2));
|
||||||
|
DEBUG_DRAW_WIRE_SPHERE(BoundingSphere(center, 5.0f), color, 0.0f, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "Engine/Particles/ParticleEffect.h"
|
#include "Engine/Particles/ParticleEffect.h"
|
||||||
#include "Engine/Engine/Time.h"
|
#include "Engine/Engine/Time.h"
|
||||||
#include "Engine/Profiler/ProfilerCPU.h"
|
#include "Engine/Profiler/ProfilerCPU.h"
|
||||||
|
#include "Engine/Debug/DebugDraw.h"
|
||||||
|
|
||||||
ThreadLocal<ParticleEmitterGraphCPUContext*> ParticleEmitterGraphCPUExecutor::Context;
|
ThreadLocal<ParticleEmitterGraphCPUContext*> ParticleEmitterGraphCPUExecutor::Context;
|
||||||
|
|
||||||
@@ -423,6 +424,23 @@ void ParticleEmitterGraphCPUExecutor::Draw(ParticleEmitter* emitter, ParticleEff
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if USE_EDITOR
|
||||||
|
|
||||||
|
void ParticleEmitterGraphCPUExecutor::DrawDebug(ParticleEmitter* emitter, ParticleEffect* effect, ParticleEmitterInstance& data)
|
||||||
|
{
|
||||||
|
// Prepare graph data
|
||||||
|
Init(emitter, effect, data);
|
||||||
|
Transform transform = emitter->SimulationSpace == ParticlesSimulationSpace::Local ? effect->GetTransform() : Transform::Identity;
|
||||||
|
|
||||||
|
// Draw modules
|
||||||
|
for (auto module : emitter->Graph.SpawnModules)
|
||||||
|
DebugDrawModule(module, transform);
|
||||||
|
for (auto module : emitter->Graph.InitModules)
|
||||||
|
DebugDrawModule(module, transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void ParticleEmitterGraphCPUExecutor::Update(ParticleEmitter* emitter, ParticleEffect* effect, ParticleEmitterInstance& data, float dt, bool canSpawn)
|
void ParticleEmitterGraphCPUExecutor::Update(ParticleEmitter* emitter, ParticleEffect* effect, ParticleEmitterInstance& data, float dt, bool canSpawn)
|
||||||
{
|
{
|
||||||
// Prepare data
|
// Prepare data
|
||||||
|
|||||||
@@ -162,6 +162,16 @@ public:
|
|||||||
/// <param name="transform">The effect transform matrix.</param>
|
/// <param name="transform">The effect transform matrix.</param>
|
||||||
void Draw(ParticleEmitter* emitter, ParticleEffect* effect, ParticleEmitterInstance& data, RenderContext& renderContext, Matrix& transform);
|
void Draw(ParticleEmitter* emitter, ParticleEffect* effect, ParticleEmitterInstance& data, RenderContext& renderContext, Matrix& transform);
|
||||||
|
|
||||||
|
#if USE_EDITOR
|
||||||
|
/// <summary>
|
||||||
|
/// Draws the particles debug shapes.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="emitter">The owning emitter.</param>
|
||||||
|
/// <param name="effect">The instance effect.</param>
|
||||||
|
/// <param name="data">The instance data.</param>
|
||||||
|
void DrawDebug(ParticleEmitter* emitter, ParticleEffect* effect, ParticleEmitterInstance& data);
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the particles simulation (the CPU simulation).
|
/// Updates the particles simulation (the CPU simulation).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -195,6 +205,9 @@ private:
|
|||||||
|
|
||||||
int32 ProcessSpawnModule(int32 index);
|
int32 ProcessSpawnModule(int32 index);
|
||||||
void ProcessModule(ParticleEmitterGraphCPUNode* node, int32 particlesStart, int32 particlesEnd);
|
void ProcessModule(ParticleEmitterGraphCPUNode* node, int32 particlesStart, int32 particlesEnd);
|
||||||
|
#if USE_EDITOR
|
||||||
|
void DebugDrawModule(ParticleEmitterGraphCPUNode* node, const Transform& transform);
|
||||||
|
#endif
|
||||||
|
|
||||||
FORCE_INLINE Value GetValue(Box* box, int32 defaultValueBoxIndex)
|
FORCE_INLINE Value GetValue(Box* box, int32 defaultValueBoxIndex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -581,10 +581,19 @@ void ParticleEffect::OnDebugDrawSelected()
|
|||||||
{
|
{
|
||||||
DEBUG_DRAW_WIRE_BOX(_box, Color::Violet * 0.7f, 0, true);
|
DEBUG_DRAW_WIRE_BOX(_box, Color::Violet * 0.7f, 0, true);
|
||||||
|
|
||||||
// Base
|
|
||||||
Actor::OnDebugDrawSelected();
|
Actor::OnDebugDrawSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParticleEffect::OnDebugDraw()
|
||||||
|
{
|
||||||
|
if (ShowDebugDraw)
|
||||||
|
{
|
||||||
|
Particles::DebugDraw(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Actor::OnDebugDraw();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void ParticleEffect::OnLayerChanged()
|
void ParticleEffect::OnLayerChanged()
|
||||||
|
|||||||
@@ -244,6 +244,13 @@ public:
|
|||||||
API_FIELD(Attributes="EditorDisplay(\"Particle Effect\"), EditorOrder(80), DefaultValue(0)")
|
API_FIELD(Attributes="EditorDisplay(\"Particle Effect\"), EditorOrder(80), DefaultValue(0)")
|
||||||
int8 SortOrder = 0;
|
int8 SortOrder = 0;
|
||||||
|
|
||||||
|
#if USE_EDITOR
|
||||||
|
/// <summary>
|
||||||
|
/// If checked, the particle emitter debug shapes will be shawn during debug drawing. This includes particle spawn location shapes display.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD(Attributes = "EditorDisplay(\"Particle Effect\"), EditorOrder(200)") bool ShowDebugDraw = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the effect parameters collection. Those parameters are instanced from the <see cref="ParticleSystem"/> that contains a linear list of emitters and every emitter has a list of own parameters.
|
/// Gets the effect parameters collection. Those parameters are instanced from the <see cref="ParticleSystem"/> that contains a linear list of emitters and every emitter has a list of own parameters.
|
||||||
@@ -394,6 +401,7 @@ public:
|
|||||||
void Draw(RenderContext& renderContext) override;
|
void Draw(RenderContext& renderContext) override;
|
||||||
#if USE_EDITOR
|
#if USE_EDITOR
|
||||||
void OnDebugDrawSelected() override;
|
void OnDebugDrawSelected() override;
|
||||||
|
void OnDebugDraw() override;
|
||||||
#endif
|
#endif
|
||||||
void OnLayerChanged() override;
|
void OnLayerChanged() override;
|
||||||
void Serialize(SerializeStream& stream, const void* otherObj) override;
|
void Serialize(SerializeStream& stream, const void* otherObj) override;
|
||||||
|
|||||||
@@ -933,6 +933,7 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe
|
|||||||
const DrawPass drawModes = view.Pass & effect->DrawModes;
|
const DrawPass drawModes = view.Pass & effect->DrawModes;
|
||||||
if (drawModes == DrawPass::None || SpriteRenderer.Init())
|
if (drawModes == DrawPass::None || SpriteRenderer.Init())
|
||||||
return;
|
return;
|
||||||
|
ConcurrentSystemLocker::ReadScope systemScope(SystemLocker);
|
||||||
Matrix worlds[2];
|
Matrix worlds[2];
|
||||||
Matrix::Translation(-renderContext.View.Origin, worlds[0]); // World
|
Matrix::Translation(-renderContext.View.Origin, worlds[0]); // World
|
||||||
renderContext.View.GetWorldMatrix(effect->GetTransform(), worlds[1]); // Local
|
renderContext.View.GetWorldMatrix(effect->GetTransform(), worlds[1]); // Local
|
||||||
@@ -1065,6 +1066,28 @@ void Particles::DrawParticles(RenderContext& renderContext, ParticleEffect* effe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if USE_EDITOR
|
||||||
|
|
||||||
|
void Particles::DebugDraw(ParticleEffect* effect)
|
||||||
|
{
|
||||||
|
PROFILE_CPU_NAMED("Particles.DrawDebug");
|
||||||
|
ConcurrentSystemLocker::ReadScope systemScope(SystemLocker);
|
||||||
|
|
||||||
|
// Draw all emitters
|
||||||
|
for (auto& emitterData : effect->Instance.Emitters)
|
||||||
|
{
|
||||||
|
const auto buffer = emitterData.Buffer;
|
||||||
|
if (!buffer)
|
||||||
|
continue;
|
||||||
|
auto emitter = buffer->Emitter;
|
||||||
|
if (!emitter || !emitter->IsLoaded())
|
||||||
|
continue;
|
||||||
|
emitter->GraphExecutorCPU.DrawDebug(emitter, effect, emitterData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#if COMPILE_WITH_GPU_PARTICLES
|
#if COMPILE_WITH_GPU_PARTICLES
|
||||||
|
|
||||||
void UpdateGPU(RenderTask* task, GPUContext* context)
|
void UpdateGPU(RenderTask* task, GPUContext* context)
|
||||||
|
|||||||
@@ -52,6 +52,14 @@ public:
|
|||||||
/// <param name="effect">The owning actor.</param>
|
/// <param name="effect">The owning actor.</param>
|
||||||
static void DrawParticles(RenderContext& renderContext, ParticleEffect* effect);
|
static void DrawParticles(RenderContext& renderContext, ParticleEffect* effect);
|
||||||
|
|
||||||
|
#if USE_EDITOR
|
||||||
|
/// <summary>
|
||||||
|
/// Draws the particles debug shapes.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="effect">The owning actor.</param>
|
||||||
|
static void DebugDraw(ParticleEffect* effect);
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enables or disables particle buffer pooling.
|
/// Enables or disables particle buffer pooling.
|
||||||
|
|||||||
Reference in New Issue
Block a user