Fix particles and some fun in the background LOL
This commit is contained in:
parent
62bb91b5a6
commit
9907e9e5c7
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
|
@ -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
|
|
@ -12,10 +12,6 @@ ScrollableFlatPanel < ScrollablePanel
|
|||
image-source: /images/ui/panel_flat
|
||||
image-border: 1
|
||||
|
||||
ParticlesFlatPanel < Panel
|
||||
image-source: /images/ui/panel_flat
|
||||
image-border: 1
|
||||
|
||||
LightFlatPanel < Panel
|
||||
image-source: /images/ui/panel_lightflat
|
||||
image-border: 1
|
||||
|
|
|
@ -9,6 +9,68 @@ Panel
|
|||
anchors.bottom: parent.bottom
|
||||
margin-top: 1
|
||||
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
|
||||
id: clientVersionLabel
|
||||
|
|
|
@ -13,7 +13,12 @@ function init()
|
|||
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
|
||||
|
||||
function terminate()
|
||||
|
|
|
@ -320,11 +320,13 @@ if(FRAMEWORK_GRAPHICS)
|
|||
${CMAKE_CURRENT_LIST_DIR}/graphics/particleaffector.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/particleaffector.h
|
||||
${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.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/particleeffect.cpp
|
||||
${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.h
|
||||
${CMAKE_CURRENT_LIST_DIR}/graphics/particlesystem.cpp
|
||||
|
|
|
@ -205,7 +205,7 @@ void GraphicalApplication::poll()
|
|||
|
||||
// poll window input events
|
||||
g_window.poll();
|
||||
g_particles.update();
|
||||
g_particles.poll();
|
||||
g_textures.poll();
|
||||
|
||||
Application::poll();
|
||||
|
|
|
@ -38,6 +38,7 @@ class Shader;
|
|||
class ShaderProgram;
|
||||
class PainterShaderProgram;
|
||||
class Particle;
|
||||
class ParticleType;
|
||||
class ParticleEmitter;
|
||||
class ParticleAffector;
|
||||
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<PainterShaderProgram> PainterShaderProgramPtr;
|
||||
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<ParticleAffector> ParticleAffectorPtr;
|
||||
typedef stdext::shared_object_ptr<ParticleSystem> ParticleSystemPtr;
|
||||
|
|
|
@ -50,10 +50,8 @@ void Particle::render()
|
|||
if(!m_texture)
|
||||
g_painter->drawFilledRect(m_rect);
|
||||
else {
|
||||
g_painter->saveState();
|
||||
g_painter->setCompositionMode(m_compositionMode);
|
||||
g_painter->drawTexturedRect(m_rect, m_texture);
|
||||
g_painter->restoreSavedState();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -94,31 +92,22 @@ void Particle::updatePosition(float elapsedTime)
|
|||
|
||||
void Particle::updateSize()
|
||||
{
|
||||
Size size = m_startSize + (m_finalSize - m_startSize) / m_duration * m_elapsedTime;
|
||||
if(m_size != size) {
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
m_size = m_startSize + (m_finalSize - m_startSize) / m_duration * m_elapsedTime;
|
||||
m_rect.resize(m_size);
|
||||
}
|
||||
|
||||
void Particle::updateColor()
|
||||
{
|
||||
if(m_elapsedTime < m_colorsStops[1]) {
|
||||
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]),
|
||||
m_colors[0].g() + (m_colors[1].g() - m_colors[0].g()) / (m_colorsStops[1] - m_colorsStops[0]) * (m_elapsedTime - 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]),
|
||||
m_colors[0].a() + (m_colors[1].a() - m_colors[0].a()) / (m_colorsStops[1] - m_colorsStops[0]) * (m_elapsedTime - m_colorsStops[0]));
|
||||
if(m_color != color) {
|
||||
m_color = color;
|
||||
}
|
||||
}
|
||||
else {
|
||||
float currentLife = m_elapsedTime / m_duration;
|
||||
if(currentLife < m_colorsStops[1]) {
|
||||
float range = m_colorsStops[1] - m_colorsStops[0];
|
||||
float factor = (currentLife - m_colorsStops[0])/range;
|
||||
m_color = m_colors[0] * (1.0f - factor) + m_colors[1] * factor;
|
||||
} else {
|
||||
if(m_colors.size() > 1) {
|
||||
m_colors.erase(m_colors.begin());
|
||||
m_colorsStops.erase(m_colorsStops.begin());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if(m_color != m_colors[0]) {
|
||||
m_color = m_colors[0];
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
#include "declarations.h"
|
||||
#include "painter.h"
|
||||
#include <framework/global.h>
|
||||
|
||||
class Particle : public stdext::shared_object
|
||||
{
|
||||
|
|
|
@ -46,7 +46,7 @@ void ParticleAffector::update(float elapsedTime)
|
|||
m_elapsedTime += elapsedTime;
|
||||
}
|
||||
|
||||
bool ParticleAffector::load(const OTMLNodePtr& node)
|
||||
void ParticleAffector::load(const OTMLNodePtr& node)
|
||||
{
|
||||
float minDelay = 0, maxDelay = 0;
|
||||
float minDuration = -1, maxDuration = -1;
|
||||
|
@ -55,17 +55,14 @@ bool ParticleAffector::load(const OTMLNodePtr& node)
|
|||
if(childNode->tag() == "delay") {
|
||||
minDelay = childNode->value<float>();
|
||||
maxDelay = childNode->value<float>();
|
||||
}
|
||||
else if(childNode->tag() == "min-delay")
|
||||
} else if(childNode->tag() == "min-delay")
|
||||
minDelay = childNode->value<float>();
|
||||
else if(childNode->tag() == "max-delay")
|
||||
maxDelay = childNode->value<float>();
|
||||
|
||||
if(childNode->tag() == "duration") {
|
||||
else if(childNode->tag() == "duration") {
|
||||
minDuration = childNode->value<float>();
|
||||
maxDuration = childNode->value<float>();
|
||||
}
|
||||
else if(childNode->tag() == "min-duration")
|
||||
} else if(childNode->tag() == "min-duration")
|
||||
minDuration = childNode->value<float>();
|
||||
else if(childNode->tag() == "max-duration")
|
||||
maxDuration = childNode->value<float>();
|
||||
|
@ -73,14 +70,11 @@ bool ParticleAffector::load(const OTMLNodePtr& node)
|
|||
|
||||
m_delay = stdext::random_range(minDelay, maxDelay);
|
||||
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))
|
||||
return false;
|
||||
ParticleAffector::load(node);
|
||||
|
||||
m_angle = 270 * DEG_TO_RAD;
|
||||
m_gravity = 9.8;
|
||||
|
@ -91,7 +85,6 @@ bool GravityAffector::load(const OTMLNodePtr& node)
|
|||
else if(childNode->tag() == "gravity")
|
||||
m_gravity = childNode->value<float>();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GravityAffector::updateParticle(const ParticlePtr& particle, float elapsedTime)
|
||||
|
@ -100,14 +93,13 @@ void GravityAffector::updateParticle(const ParticlePtr& particle, float elapsedT
|
|||
return;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
bool AttractionAffector::load(const OTMLNodePtr& node)
|
||||
void AttractionAffector::load(const OTMLNodePtr& node)
|
||||
{
|
||||
if(!ParticleAffector::load(node))
|
||||
return false;
|
||||
ParticleAffector::load(node);
|
||||
|
||||
m_acceleration = 32;
|
||||
m_reduction = 0;
|
||||
|
@ -123,7 +115,6 @@ bool AttractionAffector::load(const OTMLNodePtr& node)
|
|||
else if(childNode->tag() == "repelish")
|
||||
m_repelish = childNode->value<bool>();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void AttractionAffector::updateParticle(const ParticlePtr& particle, float elapsedTime)
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
ParticleAffector();
|
||||
|
||||
void update(float elapsedTime);
|
||||
virtual bool load(const OTMLNodePtr& node);
|
||||
virtual void load(const OTMLNodePtr& node);
|
||||
virtual void updateParticle(const ParticlePtr&, float) {}
|
||||
|
||||
bool hasFinished() { return m_finished; }
|
||||
|
@ -45,7 +45,7 @@ protected:
|
|||
|
||||
class GravityAffector : public ParticleAffector {
|
||||
public:
|
||||
bool load(const OTMLNodePtr& node);
|
||||
void load(const OTMLNodePtr& node);
|
||||
void updateParticle(const ParticlePtr& particle, float elapsedTime);
|
||||
|
||||
private:
|
||||
|
@ -54,7 +54,7 @@ private:
|
|||
|
||||
class AttractionAffector : public ParticleAffector {
|
||||
public:
|
||||
bool load(const OTMLNodePtr& node);
|
||||
void load(const OTMLNodePtr& node);
|
||||
void updateParticle(const ParticlePtr& particle, float elapsedTime);
|
||||
|
||||
private:
|
||||
|
|
|
@ -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()) {
|
||||
if(childNode->tag() == "name") {
|
||||
setName(childNode->value());
|
||||
}
|
||||
else if(childNode->tag() == "description") {
|
||||
setDescription(childNode->value());
|
||||
}
|
||||
if(childNode->tag() == "name")
|
||||
m_name = childNode->value();
|
||||
else if(childNode->tag() == "description")
|
||||
m_description = childNode->value();
|
||||
}
|
||||
return !m_name.empty();
|
||||
}
|
||||
|
||||
bool ParticleEffect::load(const ParticleEffectTypePtr& effectType)
|
||||
void ParticleEffect::load(const ParticleEffectTypePtr& effectType)
|
||||
{
|
||||
if(!effectType)
|
||||
return false;
|
||||
stdext::throw_exception("effect type not found");
|
||||
|
||||
for(const OTMLNodePtr& childNode : effectType->getNode()->children()) {
|
||||
if(childNode->tag() == "System") {
|
||||
ParticleSystemPtr system = ParticleSystemPtr(new ParticleSystem);
|
||||
if(system->load(childNode)) {
|
||||
m_systems.push_back(system);
|
||||
}
|
||||
system->load(childNode);
|
||||
m_systems.push_back(system);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ParticleEffect::render()
|
||||
|
@ -65,15 +60,14 @@ void ParticleEffect::render()
|
|||
|
||||
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;
|
||||
|
||||
if(system->hasFinished()) {
|
||||
it = m_systems.erase(it);
|
||||
continue;
|
||||
} else {
|
||||
system->update();
|
||||
++it;
|
||||
}
|
||||
|
||||
system->update();
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,20 +33,14 @@ class ParticleEffectType : public LuaObject
|
|||
public:
|
||||
ParticleEffectType();
|
||||
|
||||
bool 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; }
|
||||
void load(const OTMLNodePtr& node);
|
||||
|
||||
std::string getName() { return m_name; }
|
||||
std::string getFile() { return m_file; }
|
||||
std::string getDescription() { return m_description; }
|
||||
OTMLNodePtr getNode() { return m_node; }
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
std::string m_file;
|
||||
std::string m_description;
|
||||
OTMLNodePtr m_node;
|
||||
};
|
||||
|
@ -56,7 +50,7 @@ class ParticleEffect : public LuaObject
|
|||
public:
|
||||
ParticleEffect() {}
|
||||
|
||||
bool load(const ParticleEffectTypePtr& effectType);
|
||||
void load(const ParticleEffectTypePtr& effectType);
|
||||
bool hasFinished() { return m_systems.size() == 0; }
|
||||
void render();
|
||||
void update();
|
||||
|
|
|
@ -25,39 +25,22 @@
|
|||
#include "particlesystem.h"
|
||||
#include <framework/core/clock.h>
|
||||
#include <framework/graphics/texturemanager.h>
|
||||
#include "particlemanager.h"
|
||||
|
||||
ParticleEmitter::ParticleEmitter()
|
||||
{
|
||||
m_position = Point(0, 0);
|
||||
m_duration = -1;
|
||||
m_delay = 0;
|
||||
m_burstRate = 1; m_burstCount = 32;
|
||||
m_burstRate = 1;
|
||||
m_burstCount = 32;
|
||||
m_currentBurst = 0;
|
||||
m_elapsedTime = 0;
|
||||
m_finished = 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()) {
|
||||
// self related
|
||||
|
@ -67,120 +50,24 @@ bool ParticleEmitter::load(const OTMLNodePtr& node)
|
|||
m_duration = childNode->value<float>();
|
||||
else if(childNode->tag() == "delay")
|
||||
m_delay = childNode->value<float>();
|
||||
else if(childNode->tag() == "burstRate")
|
||||
else if(childNode->tag() == "burst-rate")
|
||||
m_burstRate = childNode->value<float>();
|
||||
else if(childNode->tag() == "burstCount")
|
||||
else if(childNode->tag() == "burst-count")
|
||||
m_burstCount = childNode->value<int>();
|
||||
|
||||
// particles generation related
|
||||
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
|
||||
else if(childNode->tag() == "particle-min-acceleration")
|
||||
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;
|
||||
}
|
||||
else if(childNode->tag() == "particle-type")
|
||||
m_particleType = g_particles.getParticleType(childNode->value());
|
||||
}
|
||||
|
||||
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;
|
||||
if(!m_particleType)
|
||||
stdext::throw_exception("emitter didn't provide a valid particle type");
|
||||
}
|
||||
|
||||
void ParticleEmitter::update(float elapsedTime, const ParticleSystemPtr& system)
|
||||
{
|
||||
m_elapsedTime += elapsedTime;
|
||||
|
||||
// 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;
|
||||
return;
|
||||
}
|
||||
|
@ -188,36 +75,39 @@ void ParticleEmitter::update(float elapsedTime, const ParticleSystemPtr& system)
|
|||
if(!m_active && m_elapsedTime > m_delay)
|
||||
m_active = true;
|
||||
|
||||
if(m_active) {
|
||||
int currentBurst = std::floor((m_elapsedTime - m_delay) / m_burstRate) + 1;
|
||||
for(int b = m_currentBurst; b < currentBurst; ++b) {
|
||||
if(!m_active)
|
||||
return;
|
||||
|
||||
// every burst created at same position.
|
||||
float pRadius = stdext::random_range(m_pMinPositionRadius, m_pMaxPositionRadius);
|
||||
float pAngle = stdext::random_range(m_pMinPositionAngle, m_pMaxPositionAngle);
|
||||
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.
|
||||
float pRadius = stdext::random_range(type->pMinPositionRadius, type->pMaxPositionRadius);
|
||||
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
|
||||
float pVelocityAbs = stdext::random_range(type->pMinVelocity, type->pMaxVelocity);
|
||||
float pVelocityAngle = stdext::random_range(type->pMinVelocityAngle, type->pMaxVelocityAngle);
|
||||
PointF pVelocity(pVelocityAbs * std::cos(pVelocityAngle), pVelocityAbs * std::sin(pVelocityAngle));
|
||||
|
||||
// particles initial velocity
|
||||
float pVelocityAbs = stdext::random_range(m_pMinVelocity, m_pMaxVelocity);
|
||||
float pVelocityAngle = stdext::random_range(m_pMinVelocityAngle, m_pMaxVelocityAngle);
|
||||
PointF pVelocity(pVelocityAbs * cos(pVelocityAngle), pVelocityAbs * sin(pVelocityAngle));
|
||||
// particles initial acceleration
|
||||
float pAccelerationAbs = stdext::random_range(type->pMinAcceleration, type->pMaxAcceleration);
|
||||
float pAccelerationAngle = stdext::random_range(type->pMinAccelerationAngle, type->pMaxAccelerationAngle);
|
||||
PointF pAcceleration(pAccelerationAbs * std::cos(pAccelerationAngle), pAccelerationAbs * std::sin(pAccelerationAngle));
|
||||
|
||||
// particles initial acceleration
|
||||
float pAccelerationAbs = stdext::random_range(m_pMinAcceleration, m_pMaxAcceleration);
|
||||
float pAccelerationAngle = stdext::random_range(m_pMinAccelerationAngle, m_pMaxAccelerationAngle);
|
||||
PointF pAcceleration(pAccelerationAbs * cos(pAccelerationAngle), pAccelerationAbs * 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_elapsedTime += elapsedTime;
|
||||
m_currentBurst = nextBurst;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ class ParticleEmitter : public stdext::shared_object
|
|||
public:
|
||||
ParticleEmitter();
|
||||
|
||||
bool load(const OTMLNodePtr& node);
|
||||
void load(const OTMLNodePtr& node);
|
||||
|
||||
void update(float elapsedTime, const ParticleSystemPtr& system);
|
||||
|
||||
|
@ -48,30 +48,7 @@ private:
|
|||
bool m_finished, m_active;
|
||||
float m_burstRate;
|
||||
int m_currentBurst, m_burstCount;
|
||||
|
||||
// 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;
|
||||
ParticleTypePtr m_particleType;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,13 +35,14 @@ bool ParticleManager::importParticle(std::string file)
|
|||
for(const OTMLNodePtr& node : doc->children()) {
|
||||
if(node->tag() == "Effect") {
|
||||
ParticleEffectTypePtr particleEffectType = ParticleEffectTypePtr(new ParticleEffectType);
|
||||
if(particleEffectType->load(node)) {
|
||||
particleEffectType->setFile(g_resources.resolvePath(file));
|
||||
m_effectsTypes[particleEffectType->getName()] = particleEffectType;
|
||||
}
|
||||
particleEffectType->load(node);
|
||||
m_effectsTypes[particleEffectType->getName()] = particleEffectType;
|
||||
}
|
||||
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;
|
||||
|
@ -53,29 +54,34 @@ bool ParticleManager::importParticle(std::string file)
|
|||
|
||||
ParticleEffectPtr ParticleManager::createEffect(const std::string& name)
|
||||
{
|
||||
ParticleEffectPtr particleEffect = ParticleEffectPtr(new ParticleEffect);
|
||||
if(particleEffect->load(m_effectsTypes[name]))
|
||||
try {
|
||||
ParticleEffectPtr particleEffect = ParticleEffectPtr(new ParticleEffect);
|
||||
particleEffect->load(m_effectsTypes[name]);
|
||||
m_effects.push_back(particleEffect);
|
||||
return particleEffect;
|
||||
return nullptr;
|
||||
} catch(stdext::exception& e) {
|
||||
g_logger.error(stdext::format("failed to create effect '%s': %s", name, e.what()));
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleManager::terminate()
|
||||
{
|
||||
m_effects.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;
|
||||
|
||||
if(particleEffect->hasFinished()) {
|
||||
it = m_effects.erase(it);
|
||||
continue;
|
||||
} else {
|
||||
particleEffect->update();
|
||||
++it;
|
||||
}
|
||||
|
||||
particleEffect->update();
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include "declarations.h"
|
||||
#include "particleeffect.h"
|
||||
#include "particletype.h"
|
||||
|
||||
class ParticleManager
|
||||
{
|
||||
|
@ -33,13 +34,18 @@ public:
|
|||
ParticleEffectPtr createEffect(const std::string& name);
|
||||
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:
|
||||
std::list<ParticleEffectPtr> m_effects;
|
||||
std::map<std::string, ParticleEffectTypePtr> m_effectsTypes;
|
||||
std::map<std::string, ParticleTypePtr> m_particleTypes;
|
||||
};
|
||||
|
||||
extern ParticleManager g_particles;
|
||||
|
|
|
@ -30,13 +30,12 @@ ParticleSystem::ParticleSystem()
|
|||
m_lastUpdateTime = g_clock.seconds();
|
||||
}
|
||||
|
||||
bool ParticleSystem::load(const OTMLNodePtr& node)
|
||||
void ParticleSystem::load(const OTMLNodePtr& node)
|
||||
{
|
||||
for(const OTMLNodePtr& childNode : node->children()) {
|
||||
if(childNode->tag() == "Emitter") {
|
||||
ParticleEmitterPtr emitter = ParticleEmitterPtr(new ParticleEmitter());
|
||||
if(!emitter->load(childNode))
|
||||
return false;
|
||||
emitter->load(childNode);
|
||||
m_emitters.push_back(emitter);
|
||||
}
|
||||
else if(childNode->tag().find("Affector") != std::string::npos) {
|
||||
|
@ -48,13 +47,11 @@ bool ParticleSystem::load(const OTMLNodePtr& node)
|
|||
affector = ParticleAffectorPtr(new AttractionAffector);
|
||||
|
||||
if(affector) {
|
||||
if(!affector->load(childNode))
|
||||
return false;
|
||||
affector->load(childNode);
|
||||
m_affectors.push_back(affector);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ParticleSystem::addParticle(const ParticlePtr& particle)
|
||||
|
@ -66,63 +63,64 @@ void ParticleSystem::render()
|
|||
{
|
||||
for(auto it = m_particles.begin(), end = m_particles.end(); it != end; ++it)
|
||||
(*it)->render();
|
||||
g_painter->resetCompositionMode();
|
||||
}
|
||||
|
||||
void ParticleSystem::update()
|
||||
{
|
||||
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
|
||||
if(m_particles.empty() && m_emitters.empty()) {
|
||||
m_finished = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// check time
|
||||
float elapsedTime = g_clock.seconds() - m_lastUpdateTime;
|
||||
if(elapsedTime < delay)
|
||||
return;
|
||||
m_lastUpdateTime = g_clock.seconds() - std::fmod(elapsedTime, delay);
|
||||
|
||||
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
|
||||
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;
|
||||
if(emitter->hasFinished()) {
|
||||
it = m_emitters.erase(it);
|
||||
continue;
|
||||
} else {
|
||||
emitter->update(delay, self);
|
||||
++it;
|
||||
}
|
||||
emitter->update(delay, self);
|
||||
++it;
|
||||
}
|
||||
|
||||
// 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;
|
||||
if(affector->hasFinished()) {
|
||||
it = m_affectors.erase(it);
|
||||
continue;
|
||||
} else {
|
||||
affector->update(delay);
|
||||
++it;
|
||||
}
|
||||
affector->update(delay);
|
||||
++it;
|
||||
}
|
||||
|
||||
// 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;
|
||||
if(particle->hasFinished()) {
|
||||
it = m_particles.erase(it);
|
||||
continue;
|
||||
} else {
|
||||
// pass particles through affectors
|
||||
for(const ParticleAffectorPtr& particleAffector : m_affectors)
|
||||
particleAffector->updateParticle(particle, delay);
|
||||
|
||||
particle->update(delay);
|
||||
++it;
|
||||
}
|
||||
|
||||
// pass particles through affectors
|
||||
for(const ParticleAffectorPtr& particleAffector : m_affectors)
|
||||
particleAffector->updateParticle(particle, delay);
|
||||
|
||||
particle->update(delay);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ class ParticleSystem : public stdext::shared_object {
|
|||
public:
|
||||
ParticleSystem();
|
||||
|
||||
bool load(const OTMLNodePtr& node);
|
||||
void load(const OTMLNodePtr& node);
|
||||
|
||||
void addParticle(const ParticlePtr& particle);
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -682,7 +682,6 @@ void Application::registerLuaFunctions()
|
|||
g_lua.registerClass<ParticleEffectType>();
|
||||
g_lua.bindClassStaticFunction<ParticleEffectType>("create", []{ return ParticleEffectTypePtr(new ParticleEffectType); });
|
||||
g_lua.bindClassMemberFunction<ParticleEffectType>("getName", &ParticleEffectType::getName);
|
||||
g_lua.bindClassMemberFunction<ParticleEffectType>("getFile", &ParticleEffectType::getFile);
|
||||
g_lua.bindClassMemberFunction<ParticleEffectType>("getDescription", &ParticleEffectType::getDescription);
|
||||
|
||||
// UIParticles
|
||||
|
|
|
@ -23,27 +23,49 @@
|
|||
#include "uiparticles.h"
|
||||
#include <framework/graphics/particlemanager.h>
|
||||
|
||||
UIParticles::UIParticles()
|
||||
{
|
||||
m_referencePos = PointF(-1,-1);
|
||||
}
|
||||
|
||||
void UIParticles::drawSelf(Fw::DrawPane drawPane)
|
||||
{
|
||||
if((drawPane & Fw::ForegroundPane) == 0)
|
||||
return;
|
||||
if(drawPane & Fw::ForegroundPane) {
|
||||
if(drawPane != Fw::BothPanes) {
|
||||
glDisable(GL_BLEND);
|
||||
g_painter->setColor(Color::alpha);
|
||||
g_painter->drawFilledRect(m_rect);
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
for(auto it = m_effects.begin(), end = m_effects.end(); it != end; ++it)
|
||||
(*it)->render();
|
||||
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)
|
||||
(*it)->render();
|
||||
g_painter->restoreSavedState();
|
||||
}
|
||||
}
|
||||
|
||||
void UIParticles::onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode)
|
||||
{
|
||||
UIWidget::onStyleApply(styleName, styleNode);
|
||||
|
||||
/*for(const OTMLNodePtr& node : styleNode->children()) {
|
||||
if(node->tag() == "reference")
|
||||
setItemId(node->value<int>());
|
||||
else if(node->tag() == "item-count")
|
||||
setItemCount(node->value<int>());
|
||||
else if(node->tag() == "virtual")
|
||||
setVirtual(node->value<bool>());
|
||||
}*/
|
||||
for(const OTMLNodePtr& node : styleNode->children()) {
|
||||
if(node->tag() == "effect")
|
||||
addEffect(node->value());
|
||||
else if(node->tag() == "reference-pos")
|
||||
setReferencePos(node->value<PointF>());
|
||||
}
|
||||
}
|
||||
|
||||
void UIParticles::addEffect(const std::string& name)
|
||||
|
|
|
@ -29,14 +29,20 @@
|
|||
class UIParticles : public UIWidget
|
||||
{
|
||||
public:
|
||||
UIParticles();
|
||||
|
||||
void drawSelf(Fw::DrawPane drawPane);
|
||||
|
||||
void addEffect(const std::string& name);
|
||||
|
||||
void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode);
|
||||
|
||||
void setReferencePos(const PointF& point) { m_referencePos = point; }
|
||||
PointF getReferencePos() { return m_referencePos; }
|
||||
|
||||
private:
|
||||
std::vector<ParticleEffectPtr> m_effects;
|
||||
PointF m_referencePos;
|
||||
};
|
||||
|
||||
#endif // UIPARTICLES_H
|
||||
#endif
|
||||
|
|
|
@ -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->drawTextureCoords(m_imageCoordsBuffer, m_imageTexture);
|
||||
|
|
Loading…
Reference in New Issue