载入中...
搜索中...
未找到
Particles.cpp
浏览该文件的文档.
2#include "common/Module.h"
3#include "data/DataModule.h"
4#include "data/JsonDocument.h"
7#include "graphics/Graphics.h"
11
12#include <Poco/Dynamic/Var.h>
13#include <Poco/JSON/Object.h>
14
15#include <memory>
16#include <simplesquirrel/simplesquirrel.hpp>
17
18namespace eve::particles {
19
21
22namespace {
23
24int bufferFromJson(const std::string &json, int fallback) {
25 auto *dm = eve::data::DataModule::create();
26 std::string err;
27 std::unique_ptr<data::JsonDocument> doc(dm->decodeJson(json, &err));
28 if (!doc || !doc->isObject()) return fallback;
29 auto obj = doc->object();
30 if (!obj || !obj->has("buffer")) return fallback;
31 try {
32 int n = obj->getValue<int>("buffer");
33 return n > 0 ? n : fallback;
34 } catch (...) {
35 return fallback;
36 }
37}
38
39} // namespace
40
42
44 return ParticleEmitter::createEmitter(bufferSize);
45}
46
48 auto *fs = eve::ModuleManager::getInstance<eve::filesystem::Filesystem>("Filesystem");
49 if (!fs) fs = eve::filesystem::Filesystem::create();
50
51 std::unique_ptr<eve::filesystem::FileData> data;
52 try {
53 data.reset(fs->read(path));
54 } catch (...) {
55 return nullptr;
56 }
57 if (!data || data->getSize() == 0) return nullptr;
58
59 std::string text(static_cast<const char *>(data->getData()), data->getSize());
60 int buffer = bufferFromJson(text, 1000);
62 if (!loadConfigFile(e, path, nullptr)) {
63 // Entity stays in ECS registry; still return for inspection, or null?
64 // Prefer null on failed apply after create — leave entity (ECS has no destroy).
65 return e; // path may have failed; emitter still usable
66 }
67 return e;
68}
69
75
77
79
81 if (ecs::current()->getManager<ParticleEmitter>() == nullptr) return 0;
82 int n = 0;
83 auto view = ecs::View<ParticleEmitter, ParticleEmitter::Config>();
84 for (auto it = view.begin(); it != view.end(); ++it) ++n;
85 return n;
86}
87
88void Particles::expose(ssq::Table &table) {
89 auto cls = table.addClass(name, Particles::create, false);
90 expose(cls);
91
92 auto em = table.addClass<ParticleEmitter>(
93 "Emitter", std::function<ParticleEmitter *()>([]() -> ParticleEmitter * { return nullptr; }),
94 true);
95 em.addFunc("setPosition", &ParticleEmitter::setPosition);
96 em.addFunc("moveTo", &ParticleEmitter::moveTo);
97 em.addFunc("getX", &ParticleEmitter::getX);
98 em.addFunc("getY", &ParticleEmitter::getY);
99 em.addFunc("setEmissionRate", &ParticleEmitter::setEmissionRate);
100 em.addFunc("getEmissionRate", &ParticleEmitter::getEmissionRate);
101 em.addFunc("setParticleLifetime", &ParticleEmitter::setParticleLifetime);
102 // Alias — scripts often say "Life" for the same knob.
103 em.addFunc("setParticleLife", &ParticleEmitter::setParticleLifetime);
104 em.addFunc("getParticleLifetimeMin", &ParticleEmitter::getParticleLifetimeMin);
105 em.addFunc("getParticleLifetimeMax", &ParticleEmitter::getParticleLifetimeMax);
106 em.addFunc("setEmitterLifetime", &ParticleEmitter::setEmitterLifetime);
107 // Aliases — scripts may say Life/Time for the same knob.
108 em.addFunc("setEmitterLife", &ParticleEmitter::setEmitterLifetime);
109 em.addFunc("setEmitterTime", &ParticleEmitter::setEmitterLifetime);
110 em.addFunc("getEmitterLifetime", &ParticleEmitter::getEmitterLifetime);
111 em.addFunc("setDirection", &ParticleEmitter::setDirection);
112 em.addFunc("getDirection", &ParticleEmitter::getDirection);
113 em.addFunc("setSpread", &ParticleEmitter::setSpread);
114 em.addFunc("getSpread", &ParticleEmitter::getSpread);
115 em.addFunc("setSpeed", &ParticleEmitter::setSpeed);
116 em.addFunc("setLinearAcceleration", &ParticleEmitter::setLinearAcceleration);
117 em.addFunc("setRadialAcceleration", &ParticleEmitter::setRadialAcceleration);
118 em.addFunc("setTangentialAcceleration", &ParticleEmitter::setTangentialAcceleration);
119 em.addFunc("setEmissionArea", &ParticleEmitter::setEmissionArea);
120 em.addFunc("getEmissionAreaType", &ParticleEmitter::getEmissionAreaType);
121 em.addFunc("getEmissionAreaX", &ParticleEmitter::getEmissionAreaX);
122 em.addFunc("getEmissionAreaY", &ParticleEmitter::getEmissionAreaY);
123 em.addFunc("setParticleSize", &ParticleEmitter::setParticleSize);
124 em.addFunc("getParticleWidth", &ParticleEmitter::getParticleWidth);
125 em.addFunc("getParticleHeight", &ParticleEmitter::getParticleHeight);
126 em.addFunc("setSizes", &ParticleEmitter::setSizes);
127 em.addFunc("setSizeVariation", &ParticleEmitter::setSizeVariation);
128 em.addFunc("getSizeVariation", &ParticleEmitter::getSizeVariation);
129 em.addFunc("setSpin", &ParticleEmitter::setSpin);
130 em.addFunc("setStartRotation", &ParticleEmitter::setStartRotation);
131 em.addFunc("addBurst", &ParticleEmitter::addBurst);
132 em.addFunc("clearBursts", &ParticleEmitter::clearBursts);
133 em.addFunc("setPrewarm", &ParticleEmitter::setPrewarm);
134 em.addFunc("getPrewarmSeconds", &ParticleEmitter::getPrewarmSeconds);
135 em.addFunc("setGravity", &ParticleEmitter::setGravity);
136 em.addFunc("setDamping", &ParticleEmitter::setDamping);
137 em.addFunc("setLimitVelocity", &ParticleEmitter::setLimitVelocity);
138 em.addFunc("clearVelocityCurve", &ParticleEmitter::clearVelocityCurve);
139 em.addFunc("addVelocityCurvePoint", &ParticleEmitter::addVelocityCurvePoint);
140 em.addFunc("setInheritVelocity", &ParticleEmitter::setInheritVelocity);
141 em.addFunc("setSimulationSpace", &ParticleEmitter::setSimulationSpace);
142 em.addFunc("setNoise", &ParticleEmitter::setNoise);
143 em.addFunc("setGpuSimulation", &ParticleEmitter::setGpuSimulation);
144 em.addFunc("getGpuSimulation", &ParticleEmitter::getGpuSimulation);
145 em.addFunc("setCollision", &ParticleEmitter::setCollision);
146 em.addFunc("setCollisionBounds", &ParticleEmitter::setCollisionBounds);
147 em.addFunc("setWorldCollision", &ParticleEmitter::setWorldCollision);
148 em.addFunc("setRenderMode", &ParticleEmitter::setRenderMode);
149 em.addFunc("setOverflowMode", &ParticleEmitter::setOverflowMode);
150 em.addFunc("setMaxDeltaTime", &ParticleEmitter::setMaxDeltaTime);
151 em.addFunc("addSubEmitter", &ParticleEmitter::addSubEmitter);
152 em.addFunc("clearSubEmitters", &ParticleEmitter::clearSubEmitters);
153 em.addFunc("addForceField", &ParticleEmitter::addForceField);
154 em.addFunc("clearForceFields", &ParticleEmitter::clearForceFields);
155 em.addFunc("setShader", &ParticleEmitter::setShader);
156 em.addFunc("getShader", &ParticleEmitter::getShader);
157 em.addFunc("setLights", &ParticleEmitter::setLights);
158 em.addFunc("getLightsEnabled", &ParticleEmitter::getLightsEnabled);
159 em.addFunc("setBlendMode", &ParticleEmitter::setBlendMode);
160 em.addFunc("getBlendMode", &ParticleEmitter::getBlendMode);
161 em.addFunc("setFlipbook", &ParticleEmitter::setFlipbook);
162 em.addFunc("clearColorGradient", &ParticleEmitter::clearColorGradient);
163 em.addFunc("addColorStop", &ParticleEmitter::addColorStop);
164 em.addFunc("clearSizeCurve", &ParticleEmitter::clearSizeCurve);
165 em.addFunc("addSizeCurvePoint", &ParticleEmitter::addSizeCurvePoint);
166 em.addFunc("clearRotationCurve", &ParticleEmitter::clearRotationCurve);
167 em.addFunc("addRotationCurvePoint", &ParticleEmitter::addRotationCurvePoint);
168 em.addFunc("setColorStart", &ParticleEmitter::setColorStart);
169 em.addFunc("setColorEnd", &ParticleEmitter::setColorEnd);
170 em.addFunc("setTexture", &ParticleEmitter::setTexture);
171 em.addFunc("setCanvas", &ParticleEmitter::setCanvas);
172 em.addFunc("setCamera", &ParticleEmitter::setCamera);
173 em.addFunc("setLayer", &ParticleEmitter::setLayer);
174 em.addFunc("getLayer", &ParticleEmitter::getLayer);
175 em.addFunc("setVisible", &ParticleEmitter::setVisible);
176 em.addFunc("isVisible", &ParticleEmitter::isVisible);
177 em.addFunc("start", &ParticleEmitter::start);
178 em.addFunc("stop", &ParticleEmitter::stop);
179 em.addFunc("pause", &ParticleEmitter::pause);
180 em.addFunc("reset", &ParticleEmitter::reset);
181 em.addFunc("emit", &ParticleEmitter::emit);
182 em.addFunc("isActive", &ParticleEmitter::isActive);
183 em.addFunc("isPaused", &ParticleEmitter::isPaused);
184 em.addFunc("isStopped", &ParticleEmitter::isStopped);
185 em.addFunc("getCount", &ParticleEmitter::getCount);
186 em.addFunc("getBufferSize", &ParticleEmitter::getBufferSize);
187 em.addFunc("applyPreset", &ParticleEmitter::applyPreset);
188 em.addFunc("applyConfig", &ParticleEmitter::applyConfig);
189 em.addFunc("loadConfig", &ParticleEmitter::loadConfig);
190 em.addFunc("reloadConfig", &ParticleEmitter::reloadConfig);
191 em.addFunc("setAutoReload", &ParticleEmitter::setAutoReload);
192 em.addFunc("getAutoReload", &ParticleEmitter::getAutoReload);
193 em.addFunc("getConfigPath", &ParticleEmitter::getConfigPath);
194 em.addFunc("attachToBone", &ParticleEmitter::attachToBone);
195 em.addFunc("attachToBoneByName", &ParticleEmitter::attachToBoneByName);
196 em.addFunc("attachToSpineBone", &ParticleEmitter::attachToSpineBone);
197 em.addFunc("attachToSpineBoneByName", &ParticleEmitter::attachToSpineBoneByName);
198 em.addFunc("attachToSkeleton2D", &ParticleEmitter::attachToSkeleton2D);
199 em.addFunc("attachToSkeleton3D", &ParticleEmitter::attachToSkeleton3D);
200 em.addFunc("setAttachOffset", &ParticleEmitter::setAttachOffset);
201 em.addFunc("setAttachPlane", &ParticleEmitter::setAttachPlane);
202 em.addFunc("setAttachScale", &ParticleEmitter::setAttachScale);
203 em.addFunc("setFollowBoneRotation", &ParticleEmitter::setFollowBoneRotation);
204 em.addFunc("detach", &ParticleEmitter::detach);
205 em.addFunc("isAttached", &ParticleEmitter::isAttached);
206 em.addFunc("getAttachBone", &ParticleEmitter::getAttachBone);
207 em.addFunc("getAttachKind", &ParticleEmitter::getAttachKind);
208 em.addFunc("syncAttach", &ParticleEmitter::syncAttach);
209 em.addFunc("setSkinSource", &ParticleEmitter::setSkinSource);
210 em.addFunc("setSkinBoneFilter", &ParticleEmitter::setSkinBoneFilter);
211 em.addFunc("setSkinBoneFilterByName", &ParticleEmitter::setSkinBoneFilterByName);
212 em.addFunc("setSkinPlane", &ParticleEmitter::setSkinPlane);
213 em.addFunc("setSkinScale", &ParticleEmitter::setSkinScale);
214 em.addFunc("clearSkinSource", &ParticleEmitter::clearSkinSource);
215 em.addFunc("hasSkinSource", &ParticleEmitter::hasSkinSource);
216 em.addFunc("emitFromSkin", &ParticleEmitter::emitFromSkin);
217}
218
219void Particles::expose(ssq::Class &cls) {
220 cls.addFunc("getName", &Particles::getName);
221 cls.addFunc("newEmitter", &Particles::newEmitter);
222 cls.addFunc("newEmitterFromFile", &Particles::newEmitterFromFile);
223 cls.addFunc("update", &Particles::update);
224 cls.addFunc("render", &Particles::render);
225 cls.addFunc("pollConfigs", &Particles::pollConfigs);
226 cls.addFunc("getEmitterCount", &Particles::getEmitterCount);
227}
228
229} // namespace eve::particles
HSQOBJECT cls
Definition ECS.cpp:21
glm::vec3 n
Definition Grass.cpp:64
#define Module_IMPL(ModuleName, newExpr)
Definition Module.h:24
glm::mat4 view
Light2D::Data * data
const char * name
Definition RockMesh.cpp:21
virtual std::string getName() const =0
ECS emitter entity. Script configures components; ParticleSimSystem / ParticleRenderSystem drive per-...
void applyPreset(const std::string &name)
Named preset: "spark" / "smoke" / "fire". Unknown → no-op.
void addSizeCurvePoint(float t, float v)
void setFlipbook(int hframes, int vframes, float framesPerSecond=0.f, float randomStart=0.f)
void addColorStop(float t, float r, float g, float b, float a)
void setSkinBoneFilter(int skeletonBoneIndex, float minWeight=0.f)
void addVelocityCurvePoint(float t, float v)
void attachToSkeleton2D(eve::ik::Skeleton2D *skeleton, int boneId)
void attachToSkeleton3D(eve::ik::Skeleton3D *skeleton, int boneId)
void setSpin(float minSpin, float maxSpin)
void setTexture(graphics::Texture *texture)
void setPosition(float x, float y)
void setRenderMode(const std::string &mode, float stretchFactor=1.f)
void attachToSpineBone(animation::SpineSkeleton *spine, int boneIndex)
static ParticleEmitter * createEmitter(int bufferSize=1000)
void setSkinBoneFilterByName(animation::AnimSkeleton *skeleton, const std::string &boneName, float minWeight=0.f)
bool loadConfig(const std::string &path)
void setCollisionBounds(bool enabled, float minX, float minY, float maxX, float maxY)
std::string getAttachKind()
"none" | "anim" | "spine" | "ik2d" | "ik3d"
void setSkinPlane(const std::string &plane)
void setSizes(float startScale, float endScale)
void setRadialAcceleration(float minA, float maxA)
void setSpeed(float minSpeed, float maxSpeed)
void setBlendMode(const std::string &mode)
void addForceField(float x, float y, float radius, float strength, float falloff=1.f)
void setCanvas(graphics::Canvas *canvas)
void attachToBone(animation::AnimPose *pose, int boneIndex)
void setOverflowMode(const std::string &mode)
void setStartRotation(float minDeg, float maxDeg)
void setCamera(graphics::Camera2D *camera)
void setLinearAcceleration(float xmin, float ymin, float xmax, float ymax)
void emitFromSkin(int count)
Burst-emit count particles from the current skinned surface.
void syncAttach()
Sync Config.x/y (and direction) from the attached bone. Also called by ParticleSimSystem.
void setTangentialAcceleration(float minA, float maxA)
bool applyConfig(const std::string &json)
void setSkinSource(animation::AnimSkin *skin, animation::AnimPose *pose)
void addRotationCurvePoint(float t, float v)
void setCollision(const std::string &mode, float radius=0.f, float restitution=0.6f, float lifetimeLoss=0.f)
void addSubEmitter(ParticleEmitter *target, const std::string &trigger, float inheritVelocity=0.f)
void setColorEnd(float r, float g, float b, float a=1.f)
void setEmissionArea(const std::string &type, float x, float y)
void setColorStart(float r, float g, float b, float a=1.f)
void setNoise(float strength, float frequency=1.f, float speed=1.f)
void attachToSpineBoneByName(animation::SpineSkeleton *spine, const std::string &boneName)
void setShader(graphics::Shader *shader)
void setSizeVariation(float variation)
void attachToBoneByName(animation::AnimPose *pose, animation::AnimSkeleton *skeleton, const std::string &boneName)
void setSimulationSpace(const std::string &space)
void setAttachOffset(float x, float y, float z)
void setLights(bool enabled, float radius=120.f, float intensity=1.f, float r=1.f, float g=1.f, float b=1.f, int maxLights=4)
void setParticleLifetime(float minLife, float maxLife)
void addBurst(float time, int count)
void setAttachPlane(const std::string &plane)
void setInheritVelocity(float fraction)
void setParticleSize(float width, float height)
static void render(graphics::Graphics *gfx)
Particles module — factory + script binding. Per-frame: ParticleConfigSystem (hot reload) → ParticleS...
Definition Particles.h:19
ParticleEmitter * newEmitter(int bufferSize=1000)
Definition Particles.cpp:43
int pollConfigs()
Explicit hot-reload poll; also invoked from update().
Definition Particles.cpp:78
ParticleEmitter * newEmitterFromFile(const std::string &path)
Create emitter from JSON config file (reads optional "buffer").
Definition Particles.cpp:47
void render(graphics::Graphics *gfx)
Definition Particles.cpp:76
bool loadConfigFile(ParticleEmitter *emitter, const std::string &path, std::string *error)
Read path via Filesystem, apply, and bind Resource.path + modtime for hot reload. Returns false if fi...