Fix particles and some fun in the background LOL

This commit is contained in:
Eduardo Bart 2013-01-19 18:24:42 -02:00
parent 62bb91b5a6
commit 9907e9e5c7
26 changed files with 510 additions and 310 deletions

BIN
data/particles/particle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,35 @@
Particle
name: default_particle
duration: 10
min-position-radius: 0
max-position-radius: 256
min-position-angle: 0
max-position-angle: 360
velocity: 10
min-velocity-angle: 0
max-velocity-angle: 360
colors: #ffffff00 #ffffffff #00000000
colors-stops: 0 0.1 1
size: 24 24
texture: /data/particles/particle
composition-mode: normal
Effect
name: background-effect
description: Effect for the game background
System
position: 0 0
Emitter
position: 0 0
delay: 0
duration: 0
burst-rate: 50
burst-count: 1
particle-type: default_particle
AttractionAffector
position: 0 0
acceleration: 1000

View File

@ -12,10 +12,6 @@ ScrollableFlatPanel < ScrollablePanel
image-source: /images/ui/panel_flat image-source: /images/ui/panel_flat
image-border: 1 image-border: 1
ParticlesFlatPanel < Panel
image-source: /images/ui/panel_flat
image-border: 1
LightFlatPanel < Panel LightFlatPanel < Panel
image-source: /images/ui/panel_lightflat image-source: /images/ui/panel_lightflat
image-border: 1 image-border: 1

View File

@ -9,6 +9,68 @@ Panel
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
margin-top: 1 margin-top: 1
focusable: false focusable: false
@onSetup: |
scheduleEvent(function()
local count = 0
cycleEvent(function()
if count > 360 then return end
self:setRotation(count)
count = count + 5
end, 10)
end, 10)
UIParticles
anchors.fill: parent
effect: background-effect
reference-pos: 0.5 0.25
Label
text: :O Just For Fun LOL ^.^
font: sans-bold-16px
color: black
background: #ffffff60
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
margin-left: 10
margin-top: 40
height: 24
rotation: -15
@onSetup: |
local count = 0
cycleEvent(function()
local text = ':O Just For Fun LOL ^.^'
self:setText(string.sub(text, 0, count))
if count > #text + 10 then count = 0 end
count = count + 1
end, 100)
Label
text: PLEASE REMOVE THAT SHIT!
font: sans-bold-16px
color: black
background: #ffffff60
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
margin-left: 10
margin-bottom: 40
height: 24
rotation: 15
visible: false
@onSetup: scheduleEvent(function() self:show() end, 4000)
Label
text: WTF IS WRONG WITH THIS BACKGROUND?
font: sans-bold-16px
color: pink
background: #ffffff99
anchors.top: parent.top
anchors.right: parent.right
margin-left: 10
margin-top: 80
height: 24
rotation: 10
visible: false
@onSetup: scheduleEvent(function() self:show() end, 8000)
UILabel UILabel
id: clientVersionLabel id: clientVersionLabel

View File

@ -13,7 +13,12 @@ function init()
end end
end end
-- TODO load particles local particles = g_resources.listDirectoryFiles('/particles')
for _i,particle in pairs(particles) do
if string.ends(particle, '.otps') then
g_particles.importParticle('/particles/' .. particle)
end
end
end end
function terminate() function terminate()

View File

@ -320,11 +320,13 @@ if(FRAMEWORK_GRAPHICS)
${CMAKE_CURRENT_LIST_DIR}/graphics/particleaffector.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/particleaffector.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/particleaffector.h ${CMAKE_CURRENT_LIST_DIR}/graphics/particleaffector.h
${CMAKE_CURRENT_LIST_DIR}/graphics/particle.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/particle.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/particle.h
${CMAKE_CURRENT_LIST_DIR}/graphics/particletype.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/particletype.h
${CMAKE_CURRENT_LIST_DIR}/graphics/particleemitter.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/particleemitter.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/particleemitter.h ${CMAKE_CURRENT_LIST_DIR}/graphics/particleemitter.h
${CMAKE_CURRENT_LIST_DIR}/graphics/particleeffect.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/particleeffect.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/particleeffect.h ${CMAKE_CURRENT_LIST_DIR}/graphics/particleeffect.h
${CMAKE_CURRENT_LIST_DIR}/graphics/particle.h
${CMAKE_CURRENT_LIST_DIR}/graphics/particlemanager.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/particlemanager.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/particlemanager.h ${CMAKE_CURRENT_LIST_DIR}/graphics/particlemanager.h
${CMAKE_CURRENT_LIST_DIR}/graphics/particlesystem.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/particlesystem.cpp

View File

@ -205,7 +205,7 @@ void GraphicalApplication::poll()
// poll window input events // poll window input events
g_window.poll(); g_window.poll();
g_particles.update(); g_particles.poll();
g_textures.poll(); g_textures.poll();
Application::poll(); Application::poll();

View File

@ -38,6 +38,7 @@ class Shader;
class ShaderProgram; class ShaderProgram;
class PainterShaderProgram; class PainterShaderProgram;
class Particle; class Particle;
class ParticleType;
class ParticleEmitter; class ParticleEmitter;
class ParticleAffector; class ParticleAffector;
class ParticleSystem; class ParticleSystem;
@ -54,6 +55,7 @@ typedef stdext::shared_object_ptr<Shader> ShaderPtr;
typedef stdext::shared_object_ptr<ShaderProgram> ShaderProgramPtr; typedef stdext::shared_object_ptr<ShaderProgram> ShaderProgramPtr;
typedef stdext::shared_object_ptr<PainterShaderProgram> PainterShaderProgramPtr; typedef stdext::shared_object_ptr<PainterShaderProgram> PainterShaderProgramPtr;
typedef stdext::shared_object_ptr<Particle> ParticlePtr; typedef stdext::shared_object_ptr<Particle> ParticlePtr;
typedef stdext::shared_object_ptr<ParticleType> ParticleTypePtr;
typedef stdext::shared_object_ptr<ParticleEmitter> ParticleEmitterPtr; typedef stdext::shared_object_ptr<ParticleEmitter> ParticleEmitterPtr;
typedef stdext::shared_object_ptr<ParticleAffector> ParticleAffectorPtr; typedef stdext::shared_object_ptr<ParticleAffector> ParticleAffectorPtr;
typedef stdext::shared_object_ptr<ParticleSystem> ParticleSystemPtr; typedef stdext::shared_object_ptr<ParticleSystem> ParticleSystemPtr;

View File

@ -50,10 +50,8 @@ void Particle::render()
if(!m_texture) if(!m_texture)
g_painter->drawFilledRect(m_rect); g_painter->drawFilledRect(m_rect);
else { else {
g_painter->saveState();
g_painter->setCompositionMode(m_compositionMode); g_painter->setCompositionMode(m_compositionMode);
g_painter->drawTexturedRect(m_rect, m_texture); g_painter->drawTexturedRect(m_rect, m_texture);
g_painter->restoreSavedState();
} }
} }
@ -94,31 +92,22 @@ void Particle::updatePosition(float elapsedTime)
void Particle::updateSize() void Particle::updateSize()
{ {
Size size = m_startSize + (m_finalSize - m_startSize) / m_duration * m_elapsedTime; m_size = m_startSize + (m_finalSize - m_startSize) / m_duration * m_elapsedTime;
if(m_size != size) {
m_size = size;
}
m_rect.resize(m_size); m_rect.resize(m_size);
} }
void Particle::updateColor() void Particle::updateColor()
{ {
if(m_elapsedTime < m_colorsStops[1]) { float currentLife = m_elapsedTime / m_duration;
Color color = Color(m_colors[0].r() + (m_colors[1].r() - m_colors[0].r()) / (m_colorsStops[1] - m_colorsStops[0]) * (m_elapsedTime - m_colorsStops[0]), if(currentLife < m_colorsStops[1]) {
m_colors[0].g() + (m_colors[1].g() - m_colors[0].g()) / (m_colorsStops[1] - m_colorsStops[0]) * (m_elapsedTime - m_colorsStops[0]), float range = m_colorsStops[1] - m_colorsStops[0];
m_colors[0].b() + (m_colors[1].b() - m_colors[0].b()) / (m_colorsStops[1] - m_colorsStops[0]) * (m_elapsedTime - m_colorsStops[0]), float factor = (currentLife - m_colorsStops[0])/range;
m_colors[0].a() + (m_colors[1].a() - m_colors[0].a()) / (m_colorsStops[1] - m_colorsStops[0]) * (m_elapsedTime - m_colorsStops[0])); m_color = m_colors[0] * (1.0f - factor) + m_colors[1] * factor;
if(m_color != color) { } else {
m_color = color;
}
}
else {
if(m_colors.size() > 1) { if(m_colors.size() > 1) {
m_colors.erase(m_colors.begin()); m_colors.erase(m_colors.begin());
m_colorsStops.erase(m_colorsStops.begin()); m_colorsStops.erase(m_colorsStops.begin());
} } else {
else {
if(m_color != m_colors[0]) { if(m_color != m_colors[0]) {
m_color = m_colors[0]; m_color = m_colors[0];
} }

View File

@ -25,7 +25,6 @@
#include "declarations.h" #include "declarations.h"
#include "painter.h" #include "painter.h"
#include <framework/global.h>
class Particle : public stdext::shared_object class Particle : public stdext::shared_object
{ {

View File

@ -46,7 +46,7 @@ void ParticleAffector::update(float elapsedTime)
m_elapsedTime += elapsedTime; m_elapsedTime += elapsedTime;
} }
bool ParticleAffector::load(const OTMLNodePtr& node) void ParticleAffector::load(const OTMLNodePtr& node)
{ {
float minDelay = 0, maxDelay = 0; float minDelay = 0, maxDelay = 0;
float minDuration = -1, maxDuration = -1; float minDuration = -1, maxDuration = -1;
@ -55,17 +55,14 @@ bool ParticleAffector::load(const OTMLNodePtr& node)
if(childNode->tag() == "delay") { if(childNode->tag() == "delay") {
minDelay = childNode->value<float>(); minDelay = childNode->value<float>();
maxDelay = childNode->value<float>(); maxDelay = childNode->value<float>();
} } else if(childNode->tag() == "min-delay")
else if(childNode->tag() == "min-delay")
minDelay = childNode->value<float>(); minDelay = childNode->value<float>();
else if(childNode->tag() == "max-delay") else if(childNode->tag() == "max-delay")
maxDelay = childNode->value<float>(); maxDelay = childNode->value<float>();
else if(childNode->tag() == "duration") {
if(childNode->tag() == "duration") {
minDuration = childNode->value<float>(); minDuration = childNode->value<float>();
maxDuration = childNode->value<float>(); maxDuration = childNode->value<float>();
} } else if(childNode->tag() == "min-duration")
else if(childNode->tag() == "min-duration")
minDuration = childNode->value<float>(); minDuration = childNode->value<float>();
else if(childNode->tag() == "max-duration") else if(childNode->tag() == "max-duration")
maxDuration = childNode->value<float>(); maxDuration = childNode->value<float>();
@ -73,14 +70,11 @@ bool ParticleAffector::load(const OTMLNodePtr& node)
m_delay = stdext::random_range(minDelay, maxDelay); m_delay = stdext::random_range(minDelay, maxDelay);
m_duration = stdext::random_range(minDuration, maxDuration); m_duration = stdext::random_range(minDuration, maxDuration);
return true;
} }
bool GravityAffector::load(const OTMLNodePtr& node) void GravityAffector::load(const OTMLNodePtr& node)
{ {
if(!ParticleAffector::load(node)) ParticleAffector::load(node);
return false;
m_angle = 270 * DEG_TO_RAD; m_angle = 270 * DEG_TO_RAD;
m_gravity = 9.8; m_gravity = 9.8;
@ -91,7 +85,6 @@ bool GravityAffector::load(const OTMLNodePtr& node)
else if(childNode->tag() == "gravity") else if(childNode->tag() == "gravity")
m_gravity = childNode->value<float>(); m_gravity = childNode->value<float>();
} }
return true;
} }
void GravityAffector::updateParticle(const ParticlePtr& particle, float elapsedTime) void GravityAffector::updateParticle(const ParticlePtr& particle, float elapsedTime)
@ -100,14 +93,13 @@ void GravityAffector::updateParticle(const ParticlePtr& particle, float elapsedT
return; return;
PointF velocity = particle->getVelocity(); PointF velocity = particle->getVelocity();
velocity += PointF(m_gravity * elapsedTime * cos(m_angle), m_gravity * elapsedTime * sin(m_angle)); velocity += PointF(m_gravity * elapsedTime * std::cos(m_angle), m_gravity * elapsedTime * std::sin(m_angle));
particle->setVelocity(velocity); particle->setVelocity(velocity);
} }
bool AttractionAffector::load(const OTMLNodePtr& node) void AttractionAffector::load(const OTMLNodePtr& node)
{ {
if(!ParticleAffector::load(node)) ParticleAffector::load(node);
return false;
m_acceleration = 32; m_acceleration = 32;
m_reduction = 0; m_reduction = 0;
@ -123,7 +115,6 @@ bool AttractionAffector::load(const OTMLNodePtr& node)
else if(childNode->tag() == "repelish") else if(childNode->tag() == "repelish")
m_repelish = childNode->value<bool>(); m_repelish = childNode->value<bool>();
} }
return true;
} }
void AttractionAffector::updateParticle(const ParticlePtr& particle, float elapsedTime) void AttractionAffector::updateParticle(const ParticlePtr& particle, float elapsedTime)

View File

@ -32,7 +32,7 @@ public:
ParticleAffector(); ParticleAffector();
void update(float elapsedTime); void update(float elapsedTime);
virtual bool load(const OTMLNodePtr& node); virtual void load(const OTMLNodePtr& node);
virtual void updateParticle(const ParticlePtr&, float) {} virtual void updateParticle(const ParticlePtr&, float) {}
bool hasFinished() { return m_finished; } bool hasFinished() { return m_finished; }
@ -45,7 +45,7 @@ protected:
class GravityAffector : public ParticleAffector { class GravityAffector : public ParticleAffector {
public: public:
bool load(const OTMLNodePtr& node); void load(const OTMLNodePtr& node);
void updateParticle(const ParticlePtr& particle, float elapsedTime); void updateParticle(const ParticlePtr& particle, float elapsedTime);
private: private:
@ -54,7 +54,7 @@ private:
class AttractionAffector : public ParticleAffector { class AttractionAffector : public ParticleAffector {
public: public:
bool load(const OTMLNodePtr& node); void load(const OTMLNodePtr& node);
void updateParticle(const ParticlePtr& particle, float elapsedTime); void updateParticle(const ParticlePtr& particle, float elapsedTime);
private: private:

View File

@ -27,34 +27,29 @@ ParticleEffectType::ParticleEffectType()
} }
bool ParticleEffectType::load(const OTMLNodePtr& node) void ParticleEffectType::load(const OTMLNodePtr& node)
{ {
m_node = node; m_node = node->clone();
for(const OTMLNodePtr& childNode : node->children()) { for(const OTMLNodePtr& childNode : node->children()) {
if(childNode->tag() == "name") { if(childNode->tag() == "name")
setName(childNode->value()); m_name = childNode->value();
else if(childNode->tag() == "description")
m_description = childNode->value();
} }
else if(childNode->tag() == "description") {
setDescription(childNode->value());
}
}
return !m_name.empty();
} }
bool ParticleEffect::load(const ParticleEffectTypePtr& effectType) void ParticleEffect::load(const ParticleEffectTypePtr& effectType)
{ {
if(!effectType) if(!effectType)
return false; stdext::throw_exception("effect type not found");
for(const OTMLNodePtr& childNode : effectType->getNode()->children()) { for(const OTMLNodePtr& childNode : effectType->getNode()->children()) {
if(childNode->tag() == "System") { if(childNode->tag() == "System") {
ParticleSystemPtr system = ParticleSystemPtr(new ParticleSystem); ParticleSystemPtr system = ParticleSystemPtr(new ParticleSystem);
if(system->load(childNode)) { system->load(childNode);
m_systems.push_back(system); m_systems.push_back(system);
} }
} }
}
return true;
} }
void ParticleEffect::render() void ParticleEffect::render()
@ -65,15 +60,14 @@ void ParticleEffect::render()
void ParticleEffect::update() void ParticleEffect::update()
{ {
for(auto it = m_systems.begin(), end = m_systems.end(); it != end;) { for(auto it = m_systems.begin(); it != m_systems.end();) {
const ParticleSystemPtr& system = *it; const ParticleSystemPtr& system = *it;
if(system->hasFinished()) { if(system->hasFinished()) {
it = m_systems.erase(it); it = m_systems.erase(it);
continue; } else {
}
system->update(); system->update();
++it; ++it;
} }
}
} }

View File

@ -33,20 +33,14 @@ class ParticleEffectType : public LuaObject
public: public:
ParticleEffectType(); ParticleEffectType();
bool load(const OTMLNodePtr& node); void load(const OTMLNodePtr& node);
void setName(const std::string& name) { m_name = name; }
void setFile(const std::string& file) { m_file = file; }
void setDescription(const std::string& description) { m_description = description; }
std::string getName() { return m_name; } std::string getName() { return m_name; }
std::string getFile() { return m_file; }
std::string getDescription() { return m_description; } std::string getDescription() { return m_description; }
OTMLNodePtr getNode() { return m_node; } OTMLNodePtr getNode() { return m_node; }
private: private:
std::string m_name; std::string m_name;
std::string m_file;
std::string m_description; std::string m_description;
OTMLNodePtr m_node; OTMLNodePtr m_node;
}; };
@ -56,7 +50,7 @@ class ParticleEffect : public LuaObject
public: public:
ParticleEffect() {} ParticleEffect() {}
bool load(const ParticleEffectTypePtr& effectType); void load(const ParticleEffectTypePtr& effectType);
bool hasFinished() { return m_systems.size() == 0; } bool hasFinished() { return m_systems.size() == 0; }
void render(); void render();
void update(); void update();

View File

@ -25,39 +25,22 @@
#include "particlesystem.h" #include "particlesystem.h"
#include <framework/core/clock.h> #include <framework/core/clock.h>
#include <framework/graphics/texturemanager.h> #include <framework/graphics/texturemanager.h>
#include "particlemanager.h"
ParticleEmitter::ParticleEmitter() ParticleEmitter::ParticleEmitter()
{ {
m_position = Point(0, 0); m_position = Point(0, 0);
m_duration = -1; m_duration = -1;
m_delay = 0; m_delay = 0;
m_burstRate = 1; m_burstCount = 32; m_burstRate = 1;
m_burstCount = 32;
m_currentBurst = 0; m_currentBurst = 0;
m_elapsedTime = 0; m_elapsedTime = 0;
m_finished = false; m_finished = false;
m_active = false; m_active = false;
// particles default configuration. (make them reasonable for user detect missing properties on scripts)
m_pMinPositionRadius = 0;
m_pMaxPositionRadius = 3;
m_pMinPositionAngle = 0;
m_pMaxPositionAngle = 360;
m_pStartSize = Size(32, 32);
m_pFinalSize = Size(32, 32);
m_pMinDuration = 0;
m_pMaxDuration = 10;
m_pIgnorePhysicsAfter = -1;
m_pMinVelocity = 32;
m_pMaxVelocity = 64;
m_pMinVelocityAngle = 0;
m_pMaxVelocityAngle = 360;
m_pMinAcceleration = 32;
m_pMaxAcceleration = 64;
m_pMinAccelerationAngle = 0;
m_pMaxAccelerationAngle = 360;
} }
bool ParticleEmitter::load(const OTMLNodePtr& node) void ParticleEmitter::load(const OTMLNodePtr& node)
{ {
for(const OTMLNodePtr& childNode : node->children()) { for(const OTMLNodePtr& childNode : node->children()) {
// self related // self related
@ -67,120 +50,24 @@ bool ParticleEmitter::load(const OTMLNodePtr& node)
m_duration = childNode->value<float>(); m_duration = childNode->value<float>();
else if(childNode->tag() == "delay") else if(childNode->tag() == "delay")
m_delay = childNode->value<float>(); m_delay = childNode->value<float>();
else if(childNode->tag() == "burstRate") else if(childNode->tag() == "burst-rate")
m_burstRate = childNode->value<float>(); m_burstRate = childNode->value<float>();
else if(childNode->tag() == "burstCount") else if(childNode->tag() == "burst-count")
m_burstCount = childNode->value<int>(); m_burstCount = childNode->value<int>();
else if(childNode->tag() == "particle-type")
// particles generation related m_particleType = g_particles.getParticleType(childNode->value());
else if(childNode->tag() == "particle-position-radius") {
m_pMinPositionRadius = childNode->value<float>();
m_pMaxPositionRadius = childNode->value<float>();
}
else if(childNode->tag() == "particle-min-position-radius")
m_pMinPositionRadius = childNode->value<float>();
else if(childNode->tag() == "particle-max-position-radius")
m_pMaxPositionRadius = childNode->value<float>();
else if(childNode->tag() == "particle-position-angle") {
m_pMinPositionAngle = childNode->value<float>() * DEG_TO_RAD;
m_pMaxPositionAngle = childNode->value<float>() * DEG_TO_RAD;
}
else if(childNode->tag() == "particle-min-position-angle")
m_pMinPositionAngle = childNode->value<float>() * DEG_TO_RAD;
else if(childNode->tag() == "particle-max-position-angle")
m_pMaxPositionAngle = childNode->value<float>() * DEG_TO_RAD;
// velocity
else if(childNode->tag() == "particle-velocity") {
m_pMinVelocity = childNode->value<float>();
m_pMaxVelocity = childNode->value<float>();
}
else if(childNode->tag() == "particle-min-velocity")
m_pMinVelocity = childNode->value<float>();
else if(childNode->tag() == "particle-max-velocity")
m_pMaxVelocity = childNode->value<float>();
else if(childNode->tag() == "particle-velocity-angle") {
m_pMinVelocityAngle = childNode->value<float>() * DEG_TO_RAD;
m_pMaxVelocityAngle = childNode->value<float>() * DEG_TO_RAD;
}
else if(childNode->tag() == "particle-min-velocity-angle")
m_pMinVelocityAngle = childNode->value<float>() * DEG_TO_RAD;
else if(childNode->tag() == "particle-max-velocity-angle")
m_pMaxVelocityAngle = childNode->value<float>() * DEG_TO_RAD;
else if(childNode->tag() == "particle-acceleration") {
m_pMinAcceleration = childNode->value<float>();
m_pMaxAcceleration = childNode->value<float>();
} }
// acceleration if(!m_particleType)
else if(childNode->tag() == "particle-min-acceleration") stdext::throw_exception("emitter didn't provide a valid particle type");
m_pMinAcceleration = childNode->value<float>();
else if(childNode->tag() == "particle-max-acceleration")
m_pMaxAcceleration = childNode->value<float>();
else if(childNode->tag() == "particle-acceleration-angle") {
m_pMinAccelerationAngle = childNode->value<float>() * DEG_TO_RAD;
m_pMaxAccelerationAngle = childNode->value<float>() * DEG_TO_RAD;
}
else if(childNode->tag() == "particle-min-acceleration-angle")
m_pMinAccelerationAngle = childNode->value<float>() * DEG_TO_RAD;
else if(childNode->tag() == "particle-max-acceleration-angle")
m_pMaxAccelerationAngle = childNode->value<float>() * DEG_TO_RAD;
// duration
else if(childNode->tag() == "particle-duration") {
m_pMinDuration = childNode->value<float>();
m_pMaxDuration = childNode->value<float>();
}
else if(childNode->tag() == "particle-min-duration")
m_pMinDuration = childNode->value<float>();
else if(childNode->tag() == "particle-max-duration")
m_pMaxDuration = childNode->value<float>();
else if(childNode->tag() == "particle-ignore-physics-after")
m_pIgnorePhysicsAfter = childNode->value<float>();
// visual
else if(childNode->tag() == "particle-size") {
m_pStartSize = childNode->value<Size>();
m_pFinalSize = childNode->value<Size>();
}
else if(childNode->tag() == "particle-start-size")
m_pStartSize = childNode->value<Size>();
else if(childNode->tag() == "particle-final-size")
m_pFinalSize = childNode->value<Size>();
else if(childNode->tag() == "particle-colors")
m_pColors = stdext::split<Color>(childNode->value());
else if(childNode->tag() == "particle-colors-stops")
m_pColorsStops = stdext::split<float>(childNode->value());
else if(childNode->tag() == "particle-texture")
m_pTexture = g_textures.getTexture(childNode->value());
else if(childNode->tag() == "particle-composition-mode") {
if(childNode->value() == "normal")
m_pCompositionMode = Painter::CompositionMode_Normal;
else if(childNode->value() == "multiply")
m_pCompositionMode = Painter::CompositionMode_Multiply;
else if(childNode->value() == "addition")
m_pCompositionMode = Painter::CompositionMode_Add;
}
}
if(m_pColors.empty())
m_pColors.push_back(Color(255, 255, 255, 128));
if(m_pColorsStops.empty())
m_pColorsStops.push_back(0);
if(m_pColors.size() != m_pColorsStops.size()) {
g_logger.error("particle colors must be equal to colorstops-1");
return false;
}
return true;
} }
void ParticleEmitter::update(float elapsedTime, const ParticleSystemPtr& system) void ParticleEmitter::update(float elapsedTime, const ParticleSystemPtr& system)
{ {
m_elapsedTime += elapsedTime;
// check if finished // check if finished
if(m_duration >= 0 && m_elapsedTime >= m_duration + m_delay) { if(m_duration > 0 && m_elapsedTime >= m_duration + m_delay) {
m_finished = true; m_finished = true;
return; return;
} }
@ -188,36 +75,39 @@ void ParticleEmitter::update(float elapsedTime, const ParticleSystemPtr& system)
if(!m_active && m_elapsedTime > m_delay) if(!m_active && m_elapsedTime > m_delay)
m_active = true; m_active = true;
if(m_active) { if(!m_active)
int currentBurst = std::floor((m_elapsedTime - m_delay) / m_burstRate) + 1; return;
for(int b = m_currentBurst; b < currentBurst; ++b) {
int nextBurst = std::floor((m_elapsedTime - m_delay) * m_burstRate) + 1;
const ParticleType *type = m_particleType.get();
for(int b = m_currentBurst; b < nextBurst; ++b) {
// every burst created at same position. // every burst created at same position.
float pRadius = stdext::random_range(m_pMinPositionRadius, m_pMaxPositionRadius); float pRadius = stdext::random_range(type->pMinPositionRadius, type->pMaxPositionRadius);
float pAngle = stdext::random_range(m_pMinPositionAngle, m_pMaxPositionAngle); float pAngle = stdext::random_range(type->pMinPositionAngle, type->pMaxPositionAngle);
Point pPosition = m_position + Point(pRadius * cos(pAngle), pRadius * sin(pAngle)); Point pPosition = m_position + Point(pRadius * std::cos(pAngle), pRadius * std::sin(pAngle));
for(int p = 0; p < m_burstCount; ++p) { for(int p = 0; p < m_burstCount; ++p) {
float pDuration = stdext::random_range(type->pMinDuration, type->pMaxDuration);
float pDuration = stdext::random_range(m_pMinDuration, m_pMaxDuration);
// particles initial velocity // particles initial velocity
float pVelocityAbs = stdext::random_range(m_pMinVelocity, m_pMaxVelocity); float pVelocityAbs = stdext::random_range(type->pMinVelocity, type->pMaxVelocity);
float pVelocityAngle = stdext::random_range(m_pMinVelocityAngle, m_pMaxVelocityAngle); float pVelocityAngle = stdext::random_range(type->pMinVelocityAngle, type->pMaxVelocityAngle);
PointF pVelocity(pVelocityAbs * cos(pVelocityAngle), pVelocityAbs * sin(pVelocityAngle)); PointF pVelocity(pVelocityAbs * std::cos(pVelocityAngle), pVelocityAbs * std::sin(pVelocityAngle));
// particles initial acceleration // particles initial acceleration
float pAccelerationAbs = stdext::random_range(m_pMinAcceleration, m_pMaxAcceleration); float pAccelerationAbs = stdext::random_range(type->pMinAcceleration, type->pMaxAcceleration);
float pAccelerationAngle = stdext::random_range(m_pMinAccelerationAngle, m_pMaxAccelerationAngle); float pAccelerationAngle = stdext::random_range(type->pMinAccelerationAngle, type->pMaxAccelerationAngle);
PointF pAcceleration(pAccelerationAbs * cos(pAccelerationAngle), pAccelerationAbs * sin(pAccelerationAngle)); PointF pAcceleration(pAccelerationAbs * std::cos(pAccelerationAngle), pAccelerationAbs * std::sin(pAccelerationAngle));
system->addParticle(ParticlePtr(new Particle(pPosition, m_pStartSize, m_pFinalSize, pVelocity, pAcceleration, pDuration, m_pIgnorePhysicsAfter, m_pColors, m_pColorsStops, m_pCompositionMode, m_pTexture))); ParticlePtr particle(new Particle(pPosition, type->pStartSize, type->pFinalSize,
pVelocity, pAcceleration,
pDuration, type->pIgnorePhysicsAfter,
type->pColors, type->pColorsStops,
type->pCompositionMode, type->pTexture));
system->addParticle(particle);
} }
} }
m_currentBurst = currentBurst; m_currentBurst = nextBurst;
}
m_elapsedTime += elapsedTime;
} }

View File

@ -34,7 +34,7 @@ class ParticleEmitter : public stdext::shared_object
public: public:
ParticleEmitter(); ParticleEmitter();
bool load(const OTMLNodePtr& node); void load(const OTMLNodePtr& node);
void update(float elapsedTime, const ParticleSystemPtr& system); void update(float elapsedTime, const ParticleSystemPtr& system);
@ -48,30 +48,7 @@ private:
bool m_finished, m_active; bool m_finished, m_active;
float m_burstRate; float m_burstRate;
int m_currentBurst, m_burstCount; int m_currentBurst, m_burstCount;
ParticleTypePtr m_particleType;
// particles size
Size m_pStartSize, m_pFinalSize;
// particles initial position related to emitter position
float m_pMinPositionRadius, m_pMaxPositionRadius;
float m_pMinPositionAngle, m_pMaxPositionAngle;
// particles initial velocity
float m_pMinVelocity, m_pMaxVelocity;
float m_pMinVelocityAngle, m_pMaxVelocityAngle;
// particles initial acceleration
float m_pMinAcceleration, m_pMaxAcceleration;
float m_pMinAccelerationAngle, m_pMaxAccelerationAngle;
// particles duration
float m_pMinDuration, m_pMaxDuration, m_pIgnorePhysicsAfter;
// visual ralated
std::vector<Color> m_pColors;
std::vector<float> m_pColorsStops;
TexturePtr m_pTexture;
Painter::CompositionMode m_pCompositionMode;
}; };
#endif #endif

View File

@ -35,13 +35,14 @@ bool ParticleManager::importParticle(std::string file)
for(const OTMLNodePtr& node : doc->children()) { for(const OTMLNodePtr& node : doc->children()) {
if(node->tag() == "Effect") { if(node->tag() == "Effect") {
ParticleEffectTypePtr particleEffectType = ParticleEffectTypePtr(new ParticleEffectType); ParticleEffectTypePtr particleEffectType = ParticleEffectTypePtr(new ParticleEffectType);
if(particleEffectType->load(node)) { particleEffectType->load(node);
particleEffectType->setFile(g_resources.resolvePath(file));
m_effectsTypes[particleEffectType->getName()] = particleEffectType; m_effectsTypes[particleEffectType->getName()] = particleEffectType;
} }
}
else if(node->tag() == "Particle") { else if(node->tag() == "Particle") {
// nothing yet ParticleTypePtr particleType = ParticleTypePtr(new ParticleType);
particleType->load(node);
m_particleTypes[particleType->getName()] = particleType;
dump << particleType->getName();
} }
} }
return true; return true;
@ -53,29 +54,34 @@ bool ParticleManager::importParticle(std::string file)
ParticleEffectPtr ParticleManager::createEffect(const std::string& name) ParticleEffectPtr ParticleManager::createEffect(const std::string& name)
{ {
try {
ParticleEffectPtr particleEffect = ParticleEffectPtr(new ParticleEffect); ParticleEffectPtr particleEffect = ParticleEffectPtr(new ParticleEffect);
if(particleEffect->load(m_effectsTypes[name])) particleEffect->load(m_effectsTypes[name]);
m_effects.push_back(particleEffect);
return particleEffect; return particleEffect;
} catch(stdext::exception& e) {
g_logger.error(stdext::format("failed to create effect '%s': %s", name, e.what()));
return nullptr; return nullptr;
}
} }
void ParticleManager::terminate() void ParticleManager::terminate()
{ {
m_effects.clear(); m_effects.clear();
m_effectsTypes.clear(); m_effectsTypes.clear();
m_particleTypes.clear();
} }
void ParticleManager::update() void ParticleManager::poll()
{ {
for(auto it = m_effects.begin(), end = m_effects.end(); it != end;) { for(auto it = m_effects.begin(); it != m_effects.end();) {
const ParticleEffectPtr& particleEffect = *it; const ParticleEffectPtr& particleEffect = *it;
if(particleEffect->hasFinished()) { if(particleEffect->hasFinished()) {
it = m_effects.erase(it); it = m_effects.erase(it);
continue; } else {
}
particleEffect->update(); particleEffect->update();
++it; ++it;
} }
}
} }

View File

@ -25,6 +25,7 @@
#include "declarations.h" #include "declarations.h"
#include "particleeffect.h" #include "particleeffect.h"
#include "particletype.h"
class ParticleManager class ParticleManager
{ {
@ -33,13 +34,18 @@ public:
ParticleEffectPtr createEffect(const std::string& name); ParticleEffectPtr createEffect(const std::string& name);
void terminate(); void terminate();
void update(); void poll();
std::map<std::string, ParticleEffectTypePtr> getEffectsTypes() { return m_effectsTypes; } ParticleTypePtr getParticleType(std::string name) { return m_particleTypes[name]; }
ParticleEffectTypePtr getParticleEffectType(std::string name) { return m_effectsTypes[name]; }
const std::map<std::string, ParticleTypePtr>& getParticleTypes() { return m_particleTypes; }
const std::map<std::string, ParticleEffectTypePtr>& getEffectsTypes() { return m_effectsTypes; }
private: private:
std::list<ParticleEffectPtr> m_effects; std::list<ParticleEffectPtr> m_effects;
std::map<std::string, ParticleEffectTypePtr> m_effectsTypes; std::map<std::string, ParticleEffectTypePtr> m_effectsTypes;
std::map<std::string, ParticleTypePtr> m_particleTypes;
}; };
extern ParticleManager g_particles; extern ParticleManager g_particles;

View File

@ -30,13 +30,12 @@ ParticleSystem::ParticleSystem()
m_lastUpdateTime = g_clock.seconds(); m_lastUpdateTime = g_clock.seconds();
} }
bool ParticleSystem::load(const OTMLNodePtr& node) void ParticleSystem::load(const OTMLNodePtr& node)
{ {
for(const OTMLNodePtr& childNode : node->children()) { for(const OTMLNodePtr& childNode : node->children()) {
if(childNode->tag() == "Emitter") { if(childNode->tag() == "Emitter") {
ParticleEmitterPtr emitter = ParticleEmitterPtr(new ParticleEmitter()); ParticleEmitterPtr emitter = ParticleEmitterPtr(new ParticleEmitter());
if(!emitter->load(childNode)) emitter->load(childNode);
return false;
m_emitters.push_back(emitter); m_emitters.push_back(emitter);
} }
else if(childNode->tag().find("Affector") != std::string::npos) { else if(childNode->tag().find("Affector") != std::string::npos) {
@ -48,13 +47,11 @@ bool ParticleSystem::load(const OTMLNodePtr& node)
affector = ParticleAffectorPtr(new AttractionAffector); affector = ParticleAffectorPtr(new AttractionAffector);
if(affector) { if(affector) {
if(!affector->load(childNode)) affector->load(childNode);
return false;
m_affectors.push_back(affector); m_affectors.push_back(affector);
} }
} }
} }
return true;
} }
void ParticleSystem::addParticle(const ParticlePtr& particle) void ParticleSystem::addParticle(const ParticlePtr& particle)
@ -66,57 +63,57 @@ void ParticleSystem::render()
{ {
for(auto it = m_particles.begin(), end = m_particles.end(); it != end; ++it) for(auto it = m_particles.begin(), end = m_particles.end(); it != end; ++it)
(*it)->render(); (*it)->render();
g_painter->resetCompositionMode();
} }
void ParticleSystem::update() void ParticleSystem::update()
{ {
static const float delay = 0.0166; // 60 updates/s static const float delay = 0.0166; // 60 updates/s
// check time
float elapsedTime = g_clock.seconds() - m_lastUpdateTime;
if(elapsedTime < delay)
return;
// check if finished // check if finished
if(m_particles.empty() && m_emitters.empty()) { if(m_particles.empty() && m_emitters.empty()) {
m_finished = true; m_finished = true;
return; return;
} }
// check time
float elapsedTime = g_clock.seconds() - m_lastUpdateTime;
if(elapsedTime < delay)
return;
m_lastUpdateTime = g_clock.seconds() - std::fmod(elapsedTime, delay); m_lastUpdateTime = g_clock.seconds() - std::fmod(elapsedTime, delay);
auto self = static_self_cast<ParticleSystem>(); auto self = static_self_cast<ParticleSystem>();
for(int i = 0; i < elapsedTime / delay; ++i) { for(int i = 0; i < std::floor(elapsedTime / delay); ++i) {
// update emitters // update emitters
for(auto it = m_emitters.begin(), end = m_emitters.end(); it != end;) { for(auto it = m_emitters.begin(); it != m_emitters.end();) {
const ParticleEmitterPtr& emitter = *it; const ParticleEmitterPtr& emitter = *it;
if(emitter->hasFinished()) { if(emitter->hasFinished()) {
it = m_emitters.erase(it); it = m_emitters.erase(it);
continue; } else {
}
emitter->update(delay, self); emitter->update(delay, self);
++it; ++it;
} }
}
// update affectors // update affectors
for(auto it = m_affectors.begin(), end = m_affectors.end(); it != end;) { for(auto it = m_affectors.begin(); it != m_affectors.end();) {
const ParticleAffectorPtr& affector = *it; const ParticleAffectorPtr& affector = *it;
if(affector->hasFinished()) { if(affector->hasFinished()) {
it = m_affectors.erase(it); it = m_affectors.erase(it);
continue; } else {
}
affector->update(delay); affector->update(delay);
++it; ++it;
} }
}
// update particles // update particles
for(auto it = m_particles.begin(), end = m_particles.end(); it != end;) { for(auto it = m_particles.begin(); it != m_particles.end();) {
const ParticlePtr& particle = *it; const ParticlePtr& particle = *it;
if(particle->hasFinished()) { if(particle->hasFinished()) {
it = m_particles.erase(it); it = m_particles.erase(it);
continue; } else {
}
// pass particles through affectors // pass particles through affectors
for(const ParticleAffectorPtr& particleAffector : m_affectors) for(const ParticleAffectorPtr& particleAffector : m_affectors)
particleAffector->updateParticle(particle, delay); particleAffector->updateParticle(particle, delay);
@ -125,4 +122,5 @@ void ParticleSystem::update()
++it; ++it;
} }
} }
}
} }

View File

@ -32,7 +32,7 @@ class ParticleSystem : public stdext::shared_object {
public: public:
ParticleSystem(); ParticleSystem();
bool load(const OTMLNodePtr& node); void load(const OTMLNodePtr& node);
void addParticle(const ParticlePtr& particle); void addParticle(const ParticlePtr& particle);

View File

@ -0,0 +1,154 @@
/*
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "particletype.h"
#include <framework/graphics/texturemanager.h>
ParticleType::ParticleType()
{
// particles default configuration. (make them reasonable for user detect missing properties on scripts)
pMinPositionRadius = 0;
pMaxPositionRadius = 3;
pMinPositionAngle = 0;
pMaxPositionAngle = 360;
pStartSize = Size(32, 32);
pFinalSize = Size(32, 32);
pMinDuration = 0;
pMaxDuration = 10;
pIgnorePhysicsAfter = -1;
pMinVelocity = 32;
pMaxVelocity = 64;
pMinVelocityAngle = 0;
pMaxVelocityAngle = 360;
pMinAcceleration = 32;
pMaxAcceleration = 64;
pMinAccelerationAngle = 0;
pMaxAccelerationAngle = 360;
}
void ParticleType::load(const OTMLNodePtr& node)
{
for(const OTMLNodePtr& childNode : node->children()) {
if(childNode->tag() == "name")
pName = childNode->value();
else if(childNode->tag() == "position-radius") {
pMinPositionRadius = childNode->value<float>();
pMaxPositionRadius = childNode->value<float>();
}
else if(childNode->tag() == "min-position-radius")
pMinPositionRadius = childNode->value<float>();
else if(childNode->tag() == "max-position-radius")
pMaxPositionRadius = childNode->value<float>();
else if(childNode->tag() == "position-angle") {
pMinPositionAngle = childNode->value<float>() * DEG_TO_RAD;
pMaxPositionAngle = childNode->value<float>() * DEG_TO_RAD;
}
else if(childNode->tag() == "min-position-angle")
pMinPositionAngle = childNode->value<float>() * DEG_TO_RAD;
else if(childNode->tag() == "max-position-angle")
pMaxPositionAngle = childNode->value<float>() * DEG_TO_RAD;
// velocity
else if(childNode->tag() == "velocity") {
pMinVelocity = childNode->value<float>();
pMaxVelocity = childNode->value<float>();
}
else if(childNode->tag() == "min-velocity")
pMinVelocity = childNode->value<float>();
else if(childNode->tag() == "max-velocity")
pMaxVelocity = childNode->value<float>();
else if(childNode->tag() == "velocity-angle") {
pMinVelocityAngle = childNode->value<float>() * DEG_TO_RAD;
pMaxVelocityAngle = childNode->value<float>() * DEG_TO_RAD;
}
else if(childNode->tag() == "min-velocity-angle")
pMinVelocityAngle = childNode->value<float>() * DEG_TO_RAD;
else if(childNode->tag() == "max-velocity-angle")
pMaxVelocityAngle = childNode->value<float>() * DEG_TO_RAD;
else if(childNode->tag() == "acceleration") {
pMinAcceleration = childNode->value<float>();
pMaxAcceleration = childNode->value<float>();
}
// acceleration
else if(childNode->tag() == "min-acceleration")
pMinAcceleration = childNode->value<float>();
else if(childNode->tag() == "max-acceleration")
pMaxAcceleration = childNode->value<float>();
else if(childNode->tag() == "acceleration-angle") {
pMinAccelerationAngle = childNode->value<float>() * DEG_TO_RAD;
pMaxAccelerationAngle = childNode->value<float>() * DEG_TO_RAD;
}
else if(childNode->tag() == "min-acceleration-angle")
pMinAccelerationAngle = childNode->value<float>() * DEG_TO_RAD;
else if(childNode->tag() == "max-acceleration-angle")
pMaxAccelerationAngle = childNode->value<float>() * DEG_TO_RAD;
// duration
else if(childNode->tag() == "duration") {
pMinDuration = childNode->value<float>();
pMaxDuration = childNode->value<float>();
}
else if(childNode->tag() == "min-duration")
pMinDuration = childNode->value<float>();
else if(childNode->tag() == "max-duration")
pMaxDuration = childNode->value<float>();
else if(childNode->tag() == "ignore-physics-after")
pIgnorePhysicsAfter = childNode->value<float>();
// visual
else if(childNode->tag() == "size") {
pStartSize = childNode->value<Size>();
pFinalSize = childNode->value<Size>();
}
else if(childNode->tag() == "start-size")
pStartSize = childNode->value<Size>();
else if(childNode->tag() == "final-size")
pFinalSize = childNode->value<Size>();
else if(childNode->tag() == "colors")
pColors = stdext::split<Color>(childNode->value());
else if(childNode->tag() == "colors-stops")
pColorsStops = stdext::split<float>(childNode->value());
else if(childNode->tag() == "texture")
pTexture = g_textures.getTexture(childNode->value());
else if(childNode->tag() == "composition-mode") {
if(childNode->value() == "normal")
pCompositionMode = Painter::CompositionMode_Normal;
else if(childNode->value() == "multiply")
pCompositionMode = Painter::CompositionMode_Multiply;
else if(childNode->value() == "addition")
pCompositionMode = Painter::CompositionMode_Add;
}
}
if(pColors.empty())
pColors.push_back(Color(255, 255, 255, 128));
if(pColorsStops.empty())
pColorsStops.push_back(0);
if(pColors.size() != pColorsStops.size())
stdext::throw_exception("particle colors must be equal to colorstops-1");
pTexture->setSmooth(true);
pTexture->buildHardwareMipmaps();
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2010-2013 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef PARTICLETYPE_H
#define PARTICLETYPE_H
#include "declarations.h"
#include <framework/graphics/painter.h>
#include <framework/luaengine/luaobject.h>
#include <framework/otml/otml.h>
class ParticleType : public LuaObject
{
public:
ParticleType();
void load(const OTMLNodePtr& node);
std::string getName() { return pName; }
protected:
// name
std::string pName;
// size
Size pStartSize, pFinalSize;
// initial position related to emitter position
float pMinPositionRadius, pMaxPositionRadius;
float pMinPositionAngle, pMaxPositionAngle;
// initial velocity
float pMinVelocity, pMaxVelocity;
float pMinVelocityAngle, pMaxVelocityAngle;
// initial acceleration
float pMinAcceleration, pMaxAcceleration;
float pMinAccelerationAngle, pMaxAccelerationAngle;
// duration
float pMinDuration, pMaxDuration, pIgnorePhysicsAfter;
// visual ralated
std::vector<Color> pColors;
std::vector<float> pColorsStops;
TexturePtr pTexture;
ParticleTypePtr particleType;
Painter::CompositionMode pCompositionMode;
friend class ParticleEmitter;
};
#endif

View File

@ -682,7 +682,6 @@ void Application::registerLuaFunctions()
g_lua.registerClass<ParticleEffectType>(); g_lua.registerClass<ParticleEffectType>();
g_lua.bindClassStaticFunction<ParticleEffectType>("create", []{ return ParticleEffectTypePtr(new ParticleEffectType); }); g_lua.bindClassStaticFunction<ParticleEffectType>("create", []{ return ParticleEffectTypePtr(new ParticleEffectType); });
g_lua.bindClassMemberFunction<ParticleEffectType>("getName", &ParticleEffectType::getName); g_lua.bindClassMemberFunction<ParticleEffectType>("getName", &ParticleEffectType::getName);
g_lua.bindClassMemberFunction<ParticleEffectType>("getFile", &ParticleEffectType::getFile);
g_lua.bindClassMemberFunction<ParticleEffectType>("getDescription", &ParticleEffectType::getDescription); g_lua.bindClassMemberFunction<ParticleEffectType>("getDescription", &ParticleEffectType::getDescription);
// UIParticles // UIParticles

View File

@ -23,27 +23,49 @@
#include "uiparticles.h" #include "uiparticles.h"
#include <framework/graphics/particlemanager.h> #include <framework/graphics/particlemanager.h>
UIParticles::UIParticles()
{
m_referencePos = PointF(-1,-1);
}
void UIParticles::drawSelf(Fw::DrawPane drawPane) void UIParticles::drawSelf(Fw::DrawPane drawPane)
{ {
if((drawPane & Fw::ForegroundPane) == 0) if(drawPane & Fw::ForegroundPane) {
return; if(drawPane != Fw::BothPanes) {
glDisable(GL_BLEND);
g_painter->setColor(Color::alpha);
g_painter->drawFilledRect(m_rect);
glEnable(GL_BLEND);
}
}
if(drawPane & Fw::BackgroundPane) {
UIWidget::drawSelf(Fw::ForegroundPane);
g_painter->saveAndResetState();
g_painter->setColor(Color::white);
g_painter->setClipRect(getPaddingRect());
if(m_referencePos.x < 0 && m_referencePos.y < 0)
g_painter->translate(m_rect.center());
else
g_painter->translate(m_rect.x() + m_referencePos.x * m_rect.width(), m_rect.y() + m_referencePos.y * m_rect.height());
for(auto it = m_effects.begin(), end = m_effects.end(); it != end; ++it) for(auto it = m_effects.begin(), end = m_effects.end(); it != end; ++it)
(*it)->render(); (*it)->render();
g_painter->restoreSavedState();
}
} }
void UIParticles::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode) void UIParticles::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
{ {
UIWidget::onStyleApply(styleName, styleNode); UIWidget::onStyleApply(styleName, styleNode);
/*for(const OTMLNodePtr& node : styleNode->children()) { for(const OTMLNodePtr& node : styleNode->children()) {
if(node->tag() == "reference") if(node->tag() == "effect")
setItemId(node->value<int>()); addEffect(node->value());
else if(node->tag() == "item-count") else if(node->tag() == "reference-pos")
setItemCount(node->value<int>()); setReferencePos(node->value<PointF>());
else if(node->tag() == "virtual") }
setVirtual(node->value<bool>());
}*/
} }
void UIParticles::addEffect(const std::string& name) void UIParticles::addEffect(const std::string& name)

View File

@ -29,14 +29,20 @@
class UIParticles : public UIWidget class UIParticles : public UIWidget
{ {
public: public:
UIParticles();
void drawSelf(Fw::DrawPane drawPane); void drawSelf(Fw::DrawPane drawPane);
void addEffect(const std::string& name); void addEffect(const std::string& name);
void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode); void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
void setReferencePos(const PointF& point) { m_referencePos = point; }
PointF getReferencePos() { return m_referencePos; }
private: private:
std::vector<ParticleEffectPtr> m_effects; std::vector<ParticleEffectPtr> m_effects;
PointF m_referencePos;
}; };
#endif // UIPARTICLES_H #endif

View File

@ -167,7 +167,8 @@ void UIWidget::drawImage(const Rect& screenCoords)
} }
} }
m_imageTexture->setSmooth(m_imageSmooth); // smooth is now enabled by default for all textures
//m_imageTexture->setSmooth(m_imageSmooth);
g_painter->setColor(m_imageColor); g_painter->setColor(m_imageColor);
g_painter->drawTextureCoords(m_imageCoordsBuffer, m_imageTexture); g_painter->drawTextureCoords(m_imageCoordsBuffer, m_imageTexture);