载入中...
搜索中...
未找到
ParticleEmitter.h
浏览该文件的文档.
1#pragma once
2#include "common/Export.h"
3
4
5#include "common/ECS.h"
7#include "common/Time.h"
9
10#include <algorithm>
11#include <cstdint>
12#include <random>
13#include <string>
14#include <unordered_map>
15#include <vector>
16
17namespace eve {
18class IParticleSdfField;
19}
20
21namespace eve::graphics {
22class Graphics;
23class Camera2D;
24class Canvas;
25class Light2D;
26class Shader;
27class Texture;
28}
29
30namespace eve::animation {
31class AnimPose;
32class AnimSkeleton;
33class AnimSkin;
34class SpineSkeleton;
35}
36
37namespace eve::ik {
38class Skeleton2D;
39class Skeleton3D;
40}
41
42namespace eve::particles {
43
44using eve::Color;
45
47struct Particle {
48 float x = 0.f;
49 float y = 0.f;
50 float vx = 0.f;
51 float vy = 0.f;
52 float ax = 0.f;
53 float ay = 0.f;
54 float radial = 0.f;
55 float tangential = 0.f;
56 float life = 0.f;
57 float lifetime = 1.f;
58 float size = 1.f;
59 float rot = 0.f;
60 float spin = 0.f;
62 float frame = 0.f;
64 float noisePhase = 0.f;
65};
66
71class EVENGINE_API_DOMAINS ParticleEmitter : public ecs::Entity {
72public:
74 ENTITY(ParticleEmitter, ecs::Entity)
75
76
77 void release() override;
78
80 struct Config {
82 struct Burst {
83 float time = 0.f;
84 int count = 0;
85 bool emitted = false;
86 };
87
88 float x = 0.f;
89 float y = 0.f;
90 float emissionRate = 0.f;
92 float emissionRateOverDistance = 0.f;
93 float lifeMin = 1.f;
94 float lifeMax = 1.f;
95 float emitterLife = -1.f; // -1 = forever
97 bool looping = false;
99 float playbackSpeed = 1.f;
101 float fixedTimeStep = 0.f;
103 int maxSubSteps = 8;
105 int randomSeed = 0;
107 bool autoRandomSeed = true;
110 std::string parameter;
111 float scale = 1.f;
112 float offset = 0.f;
113 };
115 std::unordered_map<std::string, float> floatParameters;
116 std::unordered_map<std::string, ParameterBinding> parameterBindings;
118 float resolvedParameterScale(const std::string& target) const {
119 auto binding = parameterBindings.find(target);
120 if (binding == parameterBindings.end()) return 1.f;
121 auto value = floatParameters.find(binding->second.parameter);
122 if (value == floatParameters.end()) return 1.f;
124 return std::max(0.f, value->second * binding->second.scale + binding->second.offset);
125 }
126 float direction = 0.f;
127 float spread = 0.f;
128 float speedMin = 0.f;
129 float speedMax = 0.f;
130 float accelXMin = 0.f, accelYMin = 0.f;
131 float accelXMax = 0.f, accelYMax = 0.f;
132 float radialMin = 0.f, radialMax = 0.f;
133 float tangentialMin = 0.f, tangentialMax = 0.f;
134 float particleW = 8.f;
135 float particleH = 8.f;
136 float sizeStart = 1.f;
137 float sizeEnd = 1.f;
138 float sizeVariation = 0.f; // 0..1
139 float spinMin = 0.f;
140 float spinMax = 0.f;
142 float gravityX = 0.f;
143 float gravityY = 0.f;
145 float damping = 0.f;
147 float limitVelocity = 0.f;
151 float inheritVelocity = 0.f;
153 std::string simSpace = "world";
155 float noiseStrength = 0.f;
156 float noiseFrequency = 1.f;
157 float noiseSpeed = 1.f;
159 std::string collisionMode = "none";
160 float collisionRadius = 0.f; // 0 = particle size/2
161 float collisionRestitution = 0.6f;
162 float collisionLifetimeLoss = 0.f; // fraction of life removed per hit
163 bool collisionBoundsEnabled = false;
164 float boundsMinX = 0.f;
165 float boundsMinY = 0.f;
166 float boundsMaxX = 0.f;
167 float boundsMaxY = 0.f;
169 bool worldCollision = false;
174 eve::IParticleSdfField* sdfField = nullptr;
180 std::string motionVectorPolicy = "none";
182 std::string renderMode = "billboard";
183 float stretchFactor = 1.f;
185 float renderAxisDegrees = 0.f;
187 std::string sortMode = "none";
189 std::string materialMode = "unlit";
191 float distortionStrength = 8.f;
193 float ribbonWidth = 1.f;
194 float ribbonMinSegmentLength = 1.f;
196 bool softParticles = false;
197 float softParticleDepth = 0.5f;
198 float softFadeDistance = 0.05f;
200 std::string overflowMode = "drop";
202 float maxDeltaTime = 0.f;
204 float prewarmSeconds = 0.f;
206 bool gpuSimulation = false;
208 int priority = 0;
210 int minimumQuality = 0;
212 std::string cullingMode = "automatic";
214 float cullDistance = 0.f;
216 int maxSpawnPerFrame = 0;
217 std::vector<Burst> bursts;
219 struct ForceField {
220 float x = 0.f;
221 float y = 0.f;
222 float radius = 0.f;
223 float strength = 0.f;
224 float falloff = 1.f; // exponent; 1 = linear
225 };
226 std::vector<ForceField> forceFields;
228 struct LightCfg {
229 bool enabled = false;
230 int max = 4; // capped at 8 per emitter (engine limit per canvas)
231 float radius = 120.f;
232 float intensity = 1.f;
233 float r = 1.f;
234 float g = 1.f;
235 float b = 1.f;
238 struct SubEmitter {
240 std::string trigger = "birth"; // "birth" | "death" | "collision"
241 float inheritVelocity = 0.f;
242 };
243 std::vector<SubEmitter> subEmitters;
245 float startRotMin = 0.f;
246 float startRotMax = 0.f;
248 int hframes = 1;
249 int vframes = 1;
250 float frameRate = 0.f;
252 float frameRandomStart = 0.f;
260 std::string areaType = "none";
261 float areaX = 0.f;
262 float areaY = 0.f;
263 Color colorStart{1.f, 1.f, 1.f, 1.f};
264 Color colorEnd{1.f, 1.f, 1.f, 0.f};
265 ParticleEmitter *entity = nullptr;
266 };
267
268 struct Sim {
269 std::vector<Particle> particles;
270 int alive = 0;
271 float emitAccum = 0.f;
272 float distanceEmitAccum = 0.f;
273 float fixedTimeAccum = 0.f;
274 float emitterAge = 0.f;
275 bool active = false;
276 bool paused = false;
277 bool hasLastPos = false;
278 float lastX = 0.f;
279 float lastY = 0.f;
280 bool overflowWarned = false;
281 int activeSeed = 0;
284 bool hasSimulationTick = false;
286 int spawnQuota = -1;
287 int spawnedThisFrame = 0;
288 int droppedSpawnsThisFrame = 0;
289 std::mt19937 rng;
290 };
291
292 struct Draw {
293 graphics::Texture *texture = nullptr;
295 graphics::Texture* normalTexture = nullptr;
296 graphics::Canvas *canvas = nullptr; // nullptr → screen
297 graphics::Camera2D *camera = nullptr; // nullptr → screen space (no camera)
298 BlendMode blend = BlendMode::Alpha;
299 graphics::Shader *shader = nullptr; // custom fragment pipeline (textured quads only)
300 int layer = 0;
301 bool visible = true;
302 };
303
305 struct Resource {
307 enum class ReloadObservation {
308 Unbound,
309 AutoReloadDisabled,
310 MtimePollingUnchanged,
311 MtimePollingReloaded,
312 MtimeUnavailable,
313 MtimePollingReloadFailed,
314 };
315 std::string path;
316 std::string texturePath;
317 std::string normalTexturePath;
318 int64_t modtime = -1;
319 bool autoReload = true;
321 ReloadObservation lastReloadObservation = ReloadObservation::Unbound;
322 };
323
334 struct Attach {
336 enum class Kind { None, AnimPose, Spine, Ik2D, Ik3D };
337
338 Kind kind = Kind::None;
340 animation::AnimSkeleton *skeleton = nullptr; // optional (name lookup)
341 animation::SpineSkeleton *spine = nullptr;
342 eve::ik::Skeleton2D *ik2d = nullptr;
343 eve::ik::Skeleton3D *ik3d = nullptr;
344 int boneIndex = -1;
345 float offsetX = 0.f;
346 float offsetY = 0.f;
347 float offsetZ = 0.f;
349 std::string plane = "xy";
350 float scale = 1.f;
351 bool followRotation = false;
352 bool enabled = false;
353 };
354
359 struct SkinSource {
360 animation::AnimSkin *skin = nullptr;
362 animation::AnimSkeleton *skeleton = nullptr; // optional (name filter)
363 int filterBone = -1; // skeleton bone index, -1 = all
364 float minWeight = 0.f;
366 std::string plane = "xy";
367 float scale = 1.f;
368 bool enabled = false;
370 std::vector<int> candidates;
371 bool candidatesDirty = true;
372 int lastSkinnedFrame = -1;
373 };
374
376 struct Lights {
377 std::vector<graphics::Light2D *> pool;
378 };
379
381 struct GpuSim {
382 bool enabled = false;
383 bool failed = false;
385 std::uint64_t residentHandle = 0;
387 bool residentActive = false;
389 int estimatedAlive = 0;
391 double timeline = 0.0;
393 std::vector<float> deathTimes;
395 float pendingWorldOffsetX = 0.f;
396 float pendingWorldOffsetY = 0.f;
398 std::uint32_t nextBirthSerial = 1;
399 };
400
401 COMPONENT(Config, config)
402 COMPONENT(Sim, sim)
403 COMPONENT(Draw, draw)
404 COMPONENT(Resource, resource)
405 COMPONENT(Attach, attach)
406 COMPONENT(SkinSource, skinSource)
407 COMPONENT(Lights, lights)
408 COMPONENT(GpuSim, gpuSim)
409
410 static ParticleEmitter *createEmitter(int bufferSize = 1000);
411
412 void setPosition(float x, float y);
413 void moveTo(float x, float y);
414 float getX();
415 float getY();
416
417 void setEmissionRate(float rate);
418 float getEmissionRate();
420 void setEmissionRateOverDistance(float rate);
422 float getEmissionRateOverDistance();
423
424 void setParticleLifetime(float minLife, float maxLife);
425 float getParticleLifetimeMin();
426 float getParticleLifetimeMax();
427
428 void setEmitterLifetime(float seconds);
429 float getEmitterLifetime();
431 void setLooping(bool looping);
433 bool getLooping();
435 void setPlaybackSpeed(float speed);
437 float getPlaybackSpeed();
439 void setFixedTimeStep(float seconds, int maxSubSteps = 8);
441 float getFixedTimeStep();
443 void setRandomSeed(int seed);
445 int getRandomSeed();
447 void setAutoRandomSeed(bool enabled);
449 bool getAutoRandomSeed();
450
451 void setDirection(float radians);
452 float getDirection();
453
454 void setSpread(float radians);
455 float getSpread();
456
457 void setSpeed(float minSpeed, float maxSpeed);
458 void setLinearAcceleration(float xmin, float ymin, float xmax, float ymax);
459 void setRadialAcceleration(float minA, float maxA);
460 void setTangentialAcceleration(float minA, float maxA);
461
462 void setEmissionArea(const std::string &type, float x, float y);
463 std::string getEmissionAreaType();
464 float getEmissionAreaX();
465 float getEmissionAreaY();
466
467 void setParticleSize(float width, float height);
468 float getParticleWidth();
469 float getParticleHeight();
470
471 void setSizes(float startScale, float endScale);
472 void setSizeVariation(float variation);
473 float getSizeVariation();
474
475 void setSpin(float minSpin, float maxSpin);
476 void setStartRotation(float minDeg, float maxDeg);
477
478 void addBurst(float time, int count);
479 void clearBursts();
480 void setPrewarm(float seconds);
481 float getPrewarmSeconds();
482
483 void setGravity(float x, float y);
484 void setDamping(float perSecond);
485 void setLimitVelocity(float maxSpeed);
486 void clearVelocityCurve();
487 void addVelocityCurvePoint(float t, float v);
488 void setInheritVelocity(float fraction);
489 void setSimulationSpace(const std::string &space);
490 void setNoise(float strength, float frequency = 1.f, float speed = 1.f);
491 void setGpuSimulation(bool enable);
492 bool getGpuSimulation();
494 bool isGpuSimulationActive();
496 bool isGpuFeatureSetSupported();
498 std::string getSimulationBackend();
500 std::string getGpuFallbackReason();
501
503 void setFloatParameter(const std::string& name, float value);
505 float getFloatParameter(const std::string& name, float fallback = 0.f);
507 bool hasFloatParameter(const std::string& name);
509 void clearFloatParameters();
511 void bindFloatParameter(const std::string& name, const std::string& target, float scale = 1.f, float offset = 0.f);
513 void clearFloatParameterBindings();
515 float getResolvedParameterScale(const std::string& target);
516
518 void setPriority(int priority);
520 int getPriority();
522 void setMinimumQuality(int quality);
524 int getMinimumQuality();
526 void setCullingMode(const std::string &mode);
528 std::string getCullingMode();
530 void setCullDistance(float distance);
532 float getCullDistance();
534 void setMaxSpawnPerFrame(int count);
536 int getMaxSpawnPerFrame();
537
538 void setCollision(const std::string &mode, float radius = 0.f, float restitution = 0.6f,
539 float lifetimeLoss = 0.f);
540 void setCollisionBounds(bool enabled, float minX, float minY, float maxX, float maxY);
541 void setWorldCollision(bool enabled);
546 void setSdfField(eve::IParticleSdfField* field);
553 eve::IParticleSdfField* getSdfField();
559 void setMotionVectorPolicy(const std::string& policy);
561 std::string getMotionVectorPolicy();
563 bool isMotionVectorActive();
564
565 void setRenderMode(const std::string &mode, float stretchFactor = 1.f);
567 void setRibbon(float width = 1.f, float minSegmentLength = 1.f);
569 void setSoftParticles(bool enabled, float particleDepth = 0.5f, float fadeDistance = 0.05f);
571 bool isSoftParticlesActive();
573 void setRenderAxis(float degrees);
575 void setSortMode(const std::string& mode);
577 std::string getSortMode();
579 void setMaterialMode(const std::string& mode);
581 std::string getMaterialMode();
583 void setDistortionStrength(float strengthPixels);
585 float getDistortionStrength();
586 void setOverflowMode(const std::string &mode);
587 void setMaxDeltaTime(float seconds);
588
589 void addSubEmitter(ParticleEmitter *target, const std::string &trigger,
590 float inheritVelocity = 0.f);
591 void clearSubEmitters();
592
593 void addForceField(float x, float y, float radius, float strength, float falloff = 1.f);
594 void clearForceFields();
595
596 void setShader(graphics::Shader *shader);
597 graphics::Shader *getShader();
598
599 void setLights(bool enabled, float radius = 120.f, float intensity = 1.f, float r = 1.f,
600 float g = 1.f, float b = 1.f, int maxLights = 4);
601 bool getLightsEnabled();
602
603 void setBlendMode(const std::string &mode);
604 std::string getBlendMode();
605
606 void setFlipbook(int hframes, int vframes, float framesPerSecond = 0.f,
607 float randomStart = 0.f);
608
609 void clearColorGradient();
610 void addColorStop(float t, float r, float g, float b, float a);
611 void clearSizeCurve();
612 void addSizeCurvePoint(float t, float v);
613 void clearRotationCurve();
614 void addRotationCurvePoint(float t, float v);
615
616 void setColorStart(float r, float g, float b, float a = 1.f);
617 void setColorEnd(float r, float g, float b, float a = 1.f);
618
619 void setTexture(graphics::Texture *texture);
620 graphics::Texture *getTexture();
622 void setNormalTexture(graphics::Texture* texture);
624 graphics::Texture* getNormalTexture();
625
626 void setCanvas(graphics::Canvas *canvas);
627 void setCamera(graphics::Camera2D *camera);
628
629 void setLayer(int layer);
630 int getLayer();
631
632 void setVisible(bool visible);
633 bool isVisible();
634
635 void start();
636 void stop();
637 void pause();
638 void reset();
639 void emit(int count);
640
651 [[nodiscard]] eve::Result<void> advance(const eve::SimulationStep &step);
652
654 [[nodiscard]] eve::SimulationTick currentSimulationTick() const noexcept {
655 // ECS.hpp's generated accessor has no const overload and would create
656 // a missing component. Query the existing table buffer directly so a
657 // read-only tick query neither casts away constness nor mutates ECS.
658 auto *const buffer = storage ? storage->getComponentBuffer<Sim>() : nullptr;
659 if (!buffer || id >= buffer->size()) return eve::SimulationTick::zero();
660 // The size guard makes this existing-slot read non-mutating; ECS.hpp's
661 // const overload currently attempts to resize its deque.
662 return buffer->get(id).simulationTick;
663 }
664
665 bool isActive();
666 bool isPaused();
667 bool isStopped();
668
669 int getCount();
670 int getBufferSize();
671
673 void applyPreset(const std::string &name);
674
675 bool applyConfig(const std::string &json);
676 bool loadConfig(const std::string &path);
677 bool reloadConfig();
678 void setAutoReload(bool enable);
679 bool getAutoReload();
680 std::string getConfigPath();
682 [[nodiscard]] std::string getConfigReloadObservation() const;
683
684 // --- Bone attachment (3D AnimPose / 2D Spine / IK 2D·3D) ---
685 void attachToBone(animation::AnimPose *pose, int boneIndex);
686 void attachToBoneByName(animation::AnimPose *pose, animation::AnimSkeleton *skeleton,
687 const std::string &boneName);
688 void attachToSpineBone(animation::SpineSkeleton *spine, int boneIndex);
689 void attachToSpineBoneByName(animation::SpineSkeleton *spine, const std::string &boneName);
690 void attachToSkeleton2D(eve::ik::Skeleton2D *skeleton, int boneId);
691 void attachToSkeleton3D(eve::ik::Skeleton3D *skeleton, int boneId);
692 void setAttachOffset(float x, float y, float z);
693 void setAttachPlane(const std::string &plane);
694 void setAttachScale(float scale);
695 void setFollowBoneRotation(bool enable);
696 void detach();
697 bool isAttached();
698 int getAttachBone();
700 std::string getAttachKind();
702 void syncAttach();
703
704 // --- Skinned mesh surface emission ---
705 void setSkinSource(animation::AnimSkin *skin, animation::AnimPose *pose);
706 void setSkinBoneFilter(int skeletonBoneIndex, float minWeight = 0.f);
707 void setSkinBoneFilterByName(animation::AnimSkeleton *skeleton, const std::string &boneName,
708 float minWeight = 0.f);
709 void setSkinPlane(const std::string &plane);
710 void setSkinScale(float scale);
711 void clearSkinSource();
712 bool hasSkinSource();
714 void emitFromSkin(int count);
715};
716
718bool spawnParticle(ParticleEmitter::Config &cfg, ParticleEmitter::Sim &sim);
720bool spawnParticleAt(ParticleEmitter::Config &cfg, ParticleEmitter::Sim &sim, float x, float y);
722void stepEmitterSim(ParticleEmitter::Config &cfg, ParticleEmitter::Sim &sim, float dt);
724EVENGINE_API_DOMAINS float advanceEmitterSim(ParticleEmitter::Config &cfg, ParticleEmitter::Sim &sim, float dt);
726[[nodiscard]] EVENGINE_API_DOMAINS eve::Result<void> advanceEmitterSim(ParticleEmitter::Config &cfg,
727 ParticleEmitter::Sim &sim,
730using WorldCollisionFn = bool (*)(float x, float y, float radius, float &nx, float &ny);
740 float &outY);
741
742} // namespace eve::particles
LogicalId target
double value
Duration start
bool & active
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
eve::EntitySpatialPose pose
int priority
float degrees
Definition CardTypes.cpp:35
float nx
float ny
#define EVENGINE_API_DOMAINS
Definition Export.h:110
tensor::Graph g
Definition GpuGraph.cpp:7
std::vector< eve::ProcgenProbeDesc > lights
float camera[2]
std::uint32_t alive
float colorStart[4]
std::uint32_t sortMode
float colorEnd[4]
double r
float v
float blend
std::uint32_t height
std::uint32_t width
TokenKind kind
size_t offset
std::array< float, 3 > scale
std::string name
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
float distance
MeshVfxBatchedDraw draw
std::unique_ptr< gpgpu::GpuBuffer > buffer
Definition OnnxGpgpu.cpp:26
eve::action::ActionVfxBinding binding
TileLayer * layer
float radius
std::string path
Definition PlayHost.cpp:110
std::uint32_t seed
Definition PointSet.cpp:807
std::function< eve::Result< void >()> release
Definition Procgen.cpp:86
float t
Shader * shader
RoadLaneDirection direction
std::string resource
std::uint32_t count
double restitution
float offsetX
float offsetY
bool visible
Common time values and an injectable deterministic simulation clock.
float step
Definition TreeMesh.cpp:314
Borrowed 2D signed-distance field consumed by particle collision.
Definition ParticleSdf.h:25
Move-only operation result carrying either a value or Status.
Definition Result.h:155
Evaluated local (and optional world) pose for an AnimSkeleton. Script type: AnimPose.
Definition AnimPose.h:17
3D bone hierarchy + bind-pose local TRS for skeletal animation. Independent of ik::Skeleton3D (FABRIK...
CPU linear-blend skinning binding for one mesh against an AnimSkeleton.
Definition AnimSkin.h:47
Runtime Spine skeleton pose (local + world bone transforms, slot attachments). Script type: SpineSkel...
static constexpr StrongUint64 zero() noexcept
Returns the zero value for this strong type.
Declarative 2D camera (viewport center + zoom).
Canvas public API.
Definition Canvas.h:17
Custom GPU program.
Definition Shader.h:39
GPU texture created via Graphics::newTexture. Owns GPU resources through an opaque backend handle.
Definition Texture.h:18
Script-facing 2D skeleton + pose state (ik::skeleton2d + ik::ecs2d). Bone indices are stable after ea...
Definition Skeleton2D.h:14
Script-facing 3D skeleton + pose state (ik::skeleton3d + ik::ecs3d). Local angles are yaw/pitch in th...
Definition Skeleton3D.h:13
Multi-point scalar curve sampled with linear interpolation between points. Empty curve means "use the...
ECS emitter entity. Script configures components; ParticleSimSystem / ParticleRenderSystem drive per-...
eve::SimulationTick currentSimulationTick() const noexcept
Last scheduler tick consumed by the checked emitter API.
Multi-stop color gradient sampled with linear interpolation between stops. Stops are kept sorted by t...
卡牌游戏 UI 工具模块:工厂 + 脚本绑定入口。 功能参考 ycarowr/UiCard:扇形手牌布局、抽牌/洗牌、悬浮放大、拖拽到落牌区、 敌方手牌(背面/偷看)、费用不足置灰,以及可实时调节的布局...
Definition Animation.h:25
EVENGINE_API_DOMAINS float advanceEmitterSim(ParticleEmitter::Config &cfg, ParticleEmitter::Sim &sim, float dt)
Apply playback speed and optional bounded fixed stepping before simulation.
bool spawnParticle(ParticleEmitter::Config &cfg, ParticleEmitter::Sim &sim)
Spawn particle.
void setWorldCollisionResolver(WorldCollisionFn fn)
Sets the world collision resolver.
bool(*)(float x, float y, float radius, float &nx, float &ny) WorldCollisionFn
World collision query used by emitters with worldCollision enabled.
void stepEmitterSim(ParticleEmitter::Config &cfg, ParticleEmitter::Sim &sim, float dt)
Step emitter sim.
WorldCollisionFn getWorldCollisionResolver()
Returns the world collision resolver.
bool sampleSkinSpawn(ParticleEmitter::SkinSource &skinSrc, ParticleEmitter::Sim &sim, float &outX, float &outY)
Sample skin spawn.
void syncEmitterSources(ParticleEmitter::Config &cfg, ParticleEmitter::Sim &, ParticleEmitter::Attach &attach, ParticleEmitter::SkinSource &skinSrc)
Sync bone attach + refresh skin cache; call before stepEmitterSim when using Attach/SkinSource.
bool spawnParticleAt(ParticleEmitter::Config &cfg, ParticleEmitter::Sim &sim, float x, float y)
Spawn particle at.
Build metadata (engine git commit, build time, third-party version).
Definition Build.cpp:16
BlendMode
Render-neutral 2D blend mode shared by graphics-facing modules.
Definition RenderTypes.h:11
glm::vec4 Color
Render-neutral RGBA color shared by graphics-facing modules.
Definition RenderTypes.h:8
SettlementPipeline::Stage fn
bool enabled
One deterministic fixed-step emitted by SimulationClock.
Definition Time.h:158
Optional bone attachment. When enabled, syncAttach() writes Config.x/y (and optionally direction) fro...
Timed burst emission (fired once while the emitter is active).
Radial attract/repel force fields (strength > 0 attract, < 0 repel).
Emitter-level 2D light emission (pooled Light2D entities).
Script-linked sub-emitters (birth / death / collision triggers).
std::unordered_map< std::string, float > floatParameters
Gameplay-owned exposed values and target bindings.
std::unordered_map< std::string, ParameterBinding > parameterBindings
float resolvedParameterScale(const std::string &target) const
Resolved parameter scale.
ParticleCurve rotationCurve
Optional extra rotation (degrees) over lifetime; added on top of spin.
ParticleCurve sizeCurve
Optional size scale curve over lifetime; overrides sizeStart/sizeEnd.
ParticleCurve velocityCurve
Optional speed multiplier curve over lifetime.
ParticleGradient colorGradient
Optional multi-stop gradient; overrides colorStart/colorEnd when non-empty.
Backend-owned GPU-resident simulation state and delayed CPU counters.
std::vector< float > deathTimes
Absolute death times; min-heap with std::greater<float>.
Pooled Light2D entities driven by ParticleLightSystem (lights.enabled).
std::vector< graphics::Light2D * > pool
Bound config file for hot reload (empty path = unbound).
ReloadObservation
ReloadObservation public API.
Optional skinned-mesh surface source. When enabled, newly spawned particles sample random (optionally...
std::vector< int > candidates
Vertex indices eligible for sampling (rebuilt when filter changes).
Single live particle (CPU simulation).
float noisePhase
Random noise phase per particle (turbulence offset).
float frame
Flipbook frame progress (float frame index; grid resolved at render).