#pragma once #include "render/Renderer.h" #include "render/TextureManager.h" #include #include #include namespace ZL { struct SparkParticle { Vector3f position; Vector3f velocity; float scale; float lifeTime; float maxLifeTime; bool active; int emitterIndex; SparkParticle() : position({ 0,0,0 }), velocity({ 0,0,0 }), scale(1.0f), lifeTime(0), maxLifeTime(1000.0f), active(false), emitterIndex(0) { } }; class SparkEmitter { private: std::vector particles; std::vector emissionPoints; std::vector prevEmissionPoints; std::chrono::steady_clock::time_point lastEmissionTime; float emissionRate; bool isActive; std::vector drawPositions; std::vector drawTexCoords; bool drawDataDirty; VertexRenderStruct sparkQuad; std::shared_ptr texture; int maxParticles; float particleSize; float biasX; // Ranges (used when config supplies intervals) struct FloatRange { float min=0; float max=0; }; FloatRange speedRange; // XY speed FloatRange zSpeedRange; // Z speed FloatRange scaleRange; FloatRange lifeTimeRange; std::string shaderProgramName; bool configured; void prepareDrawData(bool withRotation); bool useWorldSpace; public: SparkEmitter(); SparkEmitter(const SparkEmitter& copyFrom); SparkEmitter(const std::vector& positions, float rate = 100.0f); SparkEmitter(const std::vector& positions, std::shared_ptr tex, float rate = 100.0f); void setEmissionPoints(const std::vector& positions); void resetEmissionPoints(const std::vector& positions); void setTexture(std::shared_ptr tex); void setEmissionRate(float rate) { emissionRate = rate; } void setShaderProgramName(const std::string& name) { shaderProgramName = name; } void setMaxParticles(int max) { maxParticles = max; particles.resize(maxParticles); } void setParticleSize(float size) { particleSize = size; } void setBiasX(float bias) { biasX = bias; } void setUseWorldSpace(bool use) { useWorldSpace = use; } bool loadFromJsonFile(const std::string& path, Renderer& renderer, const std::string& zipFile = ""); void update(float deltaTimeMs); void emit(float ageMs = 0.0f, float lerpT = 0.0f); // Вызывать ДО draw() в начале кадра: готовит данные и загружает в VBO. void prepareForDraw(bool withRotation = true); void draw(Renderer& renderer, float zoom, int screenWidth, int screenHeight); void draw(Renderer& renderer, float zoom, int screenWidth, int screenHeight, bool withRotation); const std::vector& getParticles() const; size_t getActiveParticleCount() const; std::shared_ptr getTexture() const { return texture; } void setIsActive(bool newActive) { isActive = newActive; } private: void initParticle(SparkParticle& particle, int emitterIndex); Vector3f getRandomVelocity(int emitterIndex); }; } // namespace ZL