From 9907e9e5c7ddc9bc9f67d2eb9d2b7d9907ad2f84 Mon Sep 17 00:00:00 2001 From: Eduardo Bart Date: Sat, 19 Jan 2013 18:24:42 -0200 Subject: [PATCH] Fix particles and some fun in the background LOL --- data/particles/particle.png | Bin 0 -> 1503 bytes data/particles/particles.otps | 35 ++++ data/styles/10-panels.otui | 4 - modules/client_background/background.otui | 62 ++++++ modules/client_styles/styles.lua | 7 +- src/framework/CMakeLists.txt | 4 +- src/framework/core/graphicalapplication.cpp | 2 +- src/framework/graphics/declarations.h | 2 + src/framework/graphics/particle.cpp | 27 +-- src/framework/graphics/particle.h | 1 - src/framework/graphics/particleaffector.cpp | 27 +-- src/framework/graphics/particleaffector.h | 6 +- src/framework/graphics/particleeffect.cpp | 34 ++-- src/framework/graphics/particleeffect.h | 10 +- src/framework/graphics/particleemitter.cpp | 198 +++++--------------- src/framework/graphics/particleemitter.h | 27 +-- src/framework/graphics/particlemanager.cpp | 34 ++-- src/framework/graphics/particlemanager.h | 10 +- src/framework/graphics/particlesystem.cpp | 54 +++--- src/framework/graphics/particlesystem.h | 2 +- src/framework/graphics/particletype.cpp | 154 +++++++++++++++ src/framework/graphics/particletype.h | 72 +++++++ src/framework/luafunctions.cpp | 1 - src/framework/ui/uiparticles.cpp | 46 +++-- src/framework/ui/uiparticles.h | 8 +- src/framework/ui/uiwidgetimage.cpp | 3 +- 26 files changed, 515 insertions(+), 315 deletions(-) create mode 100644 data/particles/particle.png create mode 100644 data/particles/particles.otps create mode 100644 src/framework/graphics/particletype.cpp create mode 100644 src/framework/graphics/particletype.h diff --git a/data/particles/particle.png b/data/particles/particle.png new file mode 100644 index 0000000000000000000000000000000000000000..044d6298804d6df5863e0b05bc6336ef081913ad GIT binary patch literal 1503 zcmV<51t9u~P)=Z_B{4ENk!B_TI8B(=_+MVH%pI0fDlcW@Vnn zVe0y!Z`-zS+PbT&rfr(K?XiCKz_%7_s^&PZ<$0dt`JU~%o&ylp9?LWh0MIoB9#CNY zI89^McYWKmZC%$*DMVEWQHw%UWnDJYIE@bhpaS0y+$fB^FbaJv&vQN3vTeuQn>Hd~ zsykJu2j+Q)5RCBu&|yJ+Q$-*GIvGN?XSfVq)6z665Tfo!0JIzm{o~Vf zbUYpp(IJZcAc*mGgvTMohd2;x4FEDg8c2l%EfBU0b~uKCgwX&SDLX4WB~8vbL$wJ& zMa=1TSRFhapAJvQ_=x*wB-;}nQwSn}xY7g03II24AtfY-c!p_OQ4|@d7QUm5Oq6~Y z)9hS~GABL(aFK9f7`GFeDVHEAP~xbKhvEX}H}Q7jE} zp}zvKQRe_)2SMoJv}lR!O*n%o0E=Ex#(K=cx$xHD2IXeqB|x9;?0r zfTfycJ9}g<64-TZ+xBI`MN(-juLqfg)>hk)pl+4ZQYsVH-YQVaImF5Bj3E#g047>1 zJYYJGgNA20z~f0p!Hs;Ue7&q2<(13}l(6ohlpXwozb#Xd@l)8^(Oir@zGjn=Zgga< zJ$ZHRP`(DS^?MsV#%5bLt-Wytz%peLqSnzbbW^(0lGpX;N7m*Z@Gcy_tPcQ~YG~_B z1x`3!CYLVD%vjw&I%&V`!TqU6S9SFYfCEKUmeG0{F3b0~vU?D~=03Z3E$Xu00)X>e znK;&GWnn1OhCIq#HuqU{urDq9EiG~y=V=)6$7VSVvZe>w-TKx2BWrUH?mtoy_`?SP ze9;a4W#LID8%iUu>(7s@%{`#2qpnVl<_mzK#~^RozH7iHz$awmsN`S~@>ixB@DYDh$f>rL;tmkacfW;q1$0#C#tm%kuEU6Qsj2E# zfJU)Ndms~>=c}o9+g^W~1(j5Ih9vTuLNZXb%Md6_QE@1Jnuf5wC5J2WOt`j_fp|I~ zCzhyPDLRKSe$3c z`IIF|l5^j#`%KL@2Ta?w-8oHj9<|8fSTkV86{;gAU%q(z3_dh~xA!JyC|J!I|M>e`Akfoukrl zGRkWq%Bm`>23~*cWF%+ANX76#2aD?5vP*aXWZN=0)H%ZGfoYyDv*da zv*Ef#xkw~=GA3`)7Xon^t(>5vJRJiA56E|&j=BC5U;x|3$AimcoUi}@002ovPDHLk FV1hh-#DxF= literal 0 HcmV?d00001 diff --git a/data/particles/particles.otps b/data/particles/particles.otps new file mode 100644 index 00000000..11dcaee6 --- /dev/null +++ b/data/particles/particles.otps @@ -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 diff --git a/data/styles/10-panels.otui b/data/styles/10-panels.otui index 17fe09de..d4e4e5a3 100644 --- a/data/styles/10-panels.otui +++ b/data/styles/10-panels.otui @@ -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 diff --git a/modules/client_background/background.otui b/modules/client_background/background.otui index e14fb9e7..3ccf90a9 100644 --- a/modules/client_background/background.otui +++ b/modules/client_background/background.otui @@ -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 diff --git a/modules/client_styles/styles.lua b/modules/client_styles/styles.lua index c8152664..bb7b20eb 100644 --- a/modules/client_styles/styles.lua +++ b/modules/client_styles/styles.lua @@ -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() diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index 30febf3d..3d778e80 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -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 diff --git a/src/framework/core/graphicalapplication.cpp b/src/framework/core/graphicalapplication.cpp index f1007509..20a0abb1 100644 --- a/src/framework/core/graphicalapplication.cpp +++ b/src/framework/core/graphicalapplication.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(); diff --git a/src/framework/graphics/declarations.h b/src/framework/graphics/declarations.h index dcf427b5..9acfcca6 100644 --- a/src/framework/graphics/declarations.h +++ b/src/framework/graphics/declarations.h @@ -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 ShaderPtr; typedef stdext::shared_object_ptr ShaderProgramPtr; typedef stdext::shared_object_ptr PainterShaderProgramPtr; typedef stdext::shared_object_ptr ParticlePtr; +typedef stdext::shared_object_ptr ParticleTypePtr; typedef stdext::shared_object_ptr ParticleEmitterPtr; typedef stdext::shared_object_ptr ParticleAffectorPtr; typedef stdext::shared_object_ptr ParticleSystemPtr; diff --git a/src/framework/graphics/particle.cpp b/src/framework/graphics/particle.cpp index 1b464a2e..96b120a2 100644 --- a/src/framework/graphics/particle.cpp +++ b/src/framework/graphics/particle.cpp @@ -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]; } diff --git a/src/framework/graphics/particle.h b/src/framework/graphics/particle.h index 5ce697ce..f75f2dad 100644 --- a/src/framework/graphics/particle.h +++ b/src/framework/graphics/particle.h @@ -25,7 +25,6 @@ #include "declarations.h" #include "painter.h" -#include class Particle : public stdext::shared_object { diff --git a/src/framework/graphics/particleaffector.cpp b/src/framework/graphics/particleaffector.cpp index f9a9eb6d..ea735925 100644 --- a/src/framework/graphics/particleaffector.cpp +++ b/src/framework/graphics/particleaffector.cpp @@ -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(); maxDelay = childNode->value(); - } - else if(childNode->tag() == "min-delay") + } else if(childNode->tag() == "min-delay") minDelay = childNode->value(); else if(childNode->tag() == "max-delay") maxDelay = childNode->value(); - - if(childNode->tag() == "duration") { + else if(childNode->tag() == "duration") { minDuration = childNode->value(); maxDuration = childNode->value(); - } - else if(childNode->tag() == "min-duration") + } else if(childNode->tag() == "min-duration") minDuration = childNode->value(); else if(childNode->tag() == "max-duration") maxDuration = childNode->value(); @@ -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(); } - 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(); } - return true; } void AttractionAffector::updateParticle(const ParticlePtr& particle, float elapsedTime) diff --git a/src/framework/graphics/particleaffector.h b/src/framework/graphics/particleaffector.h index 5cac17bd..0f15549d 100644 --- a/src/framework/graphics/particleaffector.h +++ b/src/framework/graphics/particleaffector.h @@ -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: diff --git a/src/framework/graphics/particleeffect.cpp b/src/framework/graphics/particleeffect.cpp index 2d604b2b..386146d4 100644 --- a/src/framework/graphics/particleeffect.cpp +++ b/src/framework/graphics/particleeffect.cpp @@ -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; } } diff --git a/src/framework/graphics/particleeffect.h b/src/framework/graphics/particleeffect.h index 4de607f6..795c3636 100644 --- a/src/framework/graphics/particleeffect.h +++ b/src/framework/graphics/particleeffect.h @@ -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(); diff --git a/src/framework/graphics/particleemitter.cpp b/src/framework/graphics/particleemitter.cpp index 043d51c5..cfc94071 100644 --- a/src/framework/graphics/particleemitter.cpp +++ b/src/framework/graphics/particleemitter.cpp @@ -25,39 +25,22 @@ #include "particlesystem.h" #include #include +#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(); else if(childNode->tag() == "delay") m_delay = childNode->value(); - else if(childNode->tag() == "burstRate") + else if(childNode->tag() == "burst-rate") m_burstRate = childNode->value(); - else if(childNode->tag() == "burstCount") + else if(childNode->tag() == "burst-count") m_burstCount = childNode->value(); - - // particles generation related - else if(childNode->tag() == "particle-position-radius") { - m_pMinPositionRadius = childNode->value(); - m_pMaxPositionRadius = childNode->value(); - } - else if(childNode->tag() == "particle-min-position-radius") - m_pMinPositionRadius = childNode->value(); - else if(childNode->tag() == "particle-max-position-radius") - m_pMaxPositionRadius = childNode->value(); - else if(childNode->tag() == "particle-position-angle") { - m_pMinPositionAngle = childNode->value() * DEG_TO_RAD; - m_pMaxPositionAngle = childNode->value() * DEG_TO_RAD; - } - else if(childNode->tag() == "particle-min-position-angle") - m_pMinPositionAngle = childNode->value() * DEG_TO_RAD; - else if(childNode->tag() == "particle-max-position-angle") - m_pMaxPositionAngle = childNode->value() * DEG_TO_RAD; - - // velocity - else if(childNode->tag() == "particle-velocity") { - m_pMinVelocity = childNode->value(); - m_pMaxVelocity = childNode->value(); - } - else if(childNode->tag() == "particle-min-velocity") - m_pMinVelocity = childNode->value(); - else if(childNode->tag() == "particle-max-velocity") - m_pMaxVelocity = childNode->value(); - else if(childNode->tag() == "particle-velocity-angle") { - m_pMinVelocityAngle = childNode->value() * DEG_TO_RAD; - m_pMaxVelocityAngle = childNode->value() * DEG_TO_RAD; - } - else if(childNode->tag() == "particle-min-velocity-angle") - m_pMinVelocityAngle = childNode->value() * DEG_TO_RAD; - else if(childNode->tag() == "particle-max-velocity-angle") - m_pMaxVelocityAngle = childNode->value() * DEG_TO_RAD; - else if(childNode->tag() == "particle-acceleration") { - m_pMinAcceleration = childNode->value(); - m_pMaxAcceleration = childNode->value(); - } - - // acceleration - else if(childNode->tag() == "particle-min-acceleration") - m_pMinAcceleration = childNode->value(); - else if(childNode->tag() == "particle-max-acceleration") - m_pMaxAcceleration = childNode->value(); - else if(childNode->tag() == "particle-acceleration-angle") { - m_pMinAccelerationAngle = childNode->value() * DEG_TO_RAD; - m_pMaxAccelerationAngle = childNode->value() * DEG_TO_RAD; - } - else if(childNode->tag() == "particle-min-acceleration-angle") - m_pMinAccelerationAngle = childNode->value() * DEG_TO_RAD; - else if(childNode->tag() == "particle-max-acceleration-angle") - m_pMaxAccelerationAngle = childNode->value() * DEG_TO_RAD; - - // duration - else if(childNode->tag() == "particle-duration") { - m_pMinDuration = childNode->value(); - m_pMaxDuration = childNode->value(); - } - else if(childNode->tag() == "particle-min-duration") - m_pMinDuration = childNode->value(); - else if(childNode->tag() == "particle-max-duration") - m_pMaxDuration = childNode->value(); - else if(childNode->tag() == "particle-ignore-physics-after") - m_pIgnorePhysicsAfter = childNode->value(); - - // visual - else if(childNode->tag() == "particle-size") { - m_pStartSize = childNode->value(); - m_pFinalSize = childNode->value(); - } - else if(childNode->tag() == "particle-start-size") - m_pStartSize = childNode->value(); - else if(childNode->tag() == "particle-final-size") - m_pFinalSize = childNode->value(); - - else if(childNode->tag() == "particle-colors") - m_pColors = stdext::split(childNode->value()); - else if(childNode->tag() == "particle-colors-stops") - m_pColorsStops = stdext::split(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; + else if(childNode->tag() == "particle-type") + m_particleType = g_particles.getParticleType(childNode->value()); } - 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) { - - // every burst created at same position. - float pRadius = stdext::random_range(m_pMinPositionRadius, m_pMaxPositionRadius); - float pAngle = stdext::random_range(m_pMinPositionAngle, m_pMaxPositionAngle); - - Point pPosition = m_position + Point(pRadius * cos(pAngle), pRadius * sin(pAngle)); - - for(int p = 0; p < m_burstCount; ++p) { - - float pDuration = stdext::random_range(m_pMinDuration, m_pMaxDuration); - - // 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(m_pMinAcceleration, m_pMaxAcceleration); - float pAccelerationAngle = stdext::random_range(m_pMinAccelerationAngle, m_pMaxAccelerationAngle); - PointF pAcceleration(pAccelerationAbs * cos(pAccelerationAngle), pAccelerationAbs * sin(pAccelerationAngle)); + if(!m_active) + return; - system->addParticle(ParticlePtr(new Particle(pPosition, m_pStartSize, m_pFinalSize, pVelocity, pAcceleration, pDuration, m_pIgnorePhysicsAfter, m_pColors, m_pColorsStops, m_pCompositionMode, m_pTexture))); - } + 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 * std::cos(pAngle), pRadius * std::sin(pAngle)); + + for(int p = 0; p < m_burstCount; ++p) { + float pDuration = stdext::random_range(type->pMinDuration, type->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 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)); + + 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; } diff --git a/src/framework/graphics/particleemitter.h b/src/framework/graphics/particleemitter.h index c8b069f9..7836ded7 100644 --- a/src/framework/graphics/particleemitter.h +++ b/src/framework/graphics/particleemitter.h @@ -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 m_pColors; - std::vector m_pColorsStops; - TexturePtr m_pTexture; - Painter::CompositionMode m_pCompositionMode; + ParticleTypePtr m_particleType; }; #endif diff --git a/src/framework/graphics/particlemanager.cpp b/src/framework/graphics/particlemanager.cpp index 9a248f8f..3629ae8b 100644 --- a/src/framework/graphics/particlemanager.cpp +++ b/src/framework/graphics/particlemanager.cpp @@ -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; } } diff --git a/src/framework/graphics/particlemanager.h b/src/framework/graphics/particlemanager.h index 0d4ce0ce..3f5adeb1 100644 --- a/src/framework/graphics/particlemanager.h +++ b/src/framework/graphics/particlemanager.h @@ -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 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& getParticleTypes() { return m_particleTypes; } + const std::map& getEffectsTypes() { return m_effectsTypes; } private: std::list m_effects; std::map m_effectsTypes; + std::map m_particleTypes; }; extern ParticleManager g_particles; diff --git a/src/framework/graphics/particlesystem.cpp b/src/framework/graphics/particlesystem.cpp index 20dabbc0..80ab10af 100644 --- a/src/framework/graphics/particlesystem.cpp +++ b/src/framework/graphics/particlesystem.cpp @@ -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(); - 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; - } - - // pass particles through affectors - for(const ParticleAffectorPtr& particleAffector : m_affectors) - particleAffector->updateParticle(particle, delay); + } else { + // pass particles through affectors + for(const ParticleAffectorPtr& particleAffector : m_affectors) + particleAffector->updateParticle(particle, delay); - particle->update(delay); - ++it; + particle->update(delay); + ++it; + } } } } diff --git a/src/framework/graphics/particlesystem.h b/src/framework/graphics/particlesystem.h index ea15d13f..316769b9 100644 --- a/src/framework/graphics/particlesystem.h +++ b/src/framework/graphics/particlesystem.h @@ -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); diff --git a/src/framework/graphics/particletype.cpp b/src/framework/graphics/particletype.cpp new file mode 100644 index 00000000..e741a4d2 --- /dev/null +++ b/src/framework/graphics/particletype.cpp @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2010-2013 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 + +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(); + pMaxPositionRadius = childNode->value(); + } + else if(childNode->tag() == "min-position-radius") + pMinPositionRadius = childNode->value(); + else if(childNode->tag() == "max-position-radius") + pMaxPositionRadius = childNode->value(); + else if(childNode->tag() == "position-angle") { + pMinPositionAngle = childNode->value() * DEG_TO_RAD; + pMaxPositionAngle = childNode->value() * DEG_TO_RAD; + } + else if(childNode->tag() == "min-position-angle") + pMinPositionAngle = childNode->value() * DEG_TO_RAD; + else if(childNode->tag() == "max-position-angle") + pMaxPositionAngle = childNode->value() * DEG_TO_RAD; + + // velocity + else if(childNode->tag() == "velocity") { + pMinVelocity = childNode->value(); + pMaxVelocity = childNode->value(); + } + else if(childNode->tag() == "min-velocity") + pMinVelocity = childNode->value(); + else if(childNode->tag() == "max-velocity") + pMaxVelocity = childNode->value(); + else if(childNode->tag() == "velocity-angle") { + pMinVelocityAngle = childNode->value() * DEG_TO_RAD; + pMaxVelocityAngle = childNode->value() * DEG_TO_RAD; + } + else if(childNode->tag() == "min-velocity-angle") + pMinVelocityAngle = childNode->value() * DEG_TO_RAD; + else if(childNode->tag() == "max-velocity-angle") + pMaxVelocityAngle = childNode->value() * DEG_TO_RAD; + else if(childNode->tag() == "acceleration") { + pMinAcceleration = childNode->value(); + pMaxAcceleration = childNode->value(); + } + + // acceleration + else if(childNode->tag() == "min-acceleration") + pMinAcceleration = childNode->value(); + else if(childNode->tag() == "max-acceleration") + pMaxAcceleration = childNode->value(); + else if(childNode->tag() == "acceleration-angle") { + pMinAccelerationAngle = childNode->value() * DEG_TO_RAD; + pMaxAccelerationAngle = childNode->value() * DEG_TO_RAD; + } + else if(childNode->tag() == "min-acceleration-angle") + pMinAccelerationAngle = childNode->value() * DEG_TO_RAD; + else if(childNode->tag() == "max-acceleration-angle") + pMaxAccelerationAngle = childNode->value() * DEG_TO_RAD; + + // duration + else if(childNode->tag() == "duration") { + pMinDuration = childNode->value(); + pMaxDuration = childNode->value(); + } + else if(childNode->tag() == "min-duration") + pMinDuration = childNode->value(); + else if(childNode->tag() == "max-duration") + pMaxDuration = childNode->value(); + else if(childNode->tag() == "ignore-physics-after") + pIgnorePhysicsAfter = childNode->value(); + + // visual + else if(childNode->tag() == "size") { + pStartSize = childNode->value(); + pFinalSize = childNode->value(); + } + else if(childNode->tag() == "start-size") + pStartSize = childNode->value(); + else if(childNode->tag() == "final-size") + pFinalSize = childNode->value(); + + else if(childNode->tag() == "colors") + pColors = stdext::split(childNode->value()); + else if(childNode->tag() == "colors-stops") + pColorsStops = stdext::split(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(); +} diff --git a/src/framework/graphics/particletype.h b/src/framework/graphics/particletype.h new file mode 100644 index 00000000..fbad2136 --- /dev/null +++ b/src/framework/graphics/particletype.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2010-2013 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 +#include +#include + +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 pColors; + std::vector pColorsStops; + TexturePtr pTexture; + ParticleTypePtr particleType; + Painter::CompositionMode pCompositionMode; + + friend class ParticleEmitter; +}; + +#endif diff --git a/src/framework/luafunctions.cpp b/src/framework/luafunctions.cpp index 88bca32e..e73dbc55 100644 --- a/src/framework/luafunctions.cpp +++ b/src/framework/luafunctions.cpp @@ -682,7 +682,6 @@ void Application::registerLuaFunctions() g_lua.registerClass(); g_lua.bindClassStaticFunction("create", []{ return ParticleEffectTypePtr(new ParticleEffectType); }); g_lua.bindClassMemberFunction("getName", &ParticleEffectType::getName); - g_lua.bindClassMemberFunction("getFile", &ParticleEffectType::getFile); g_lua.bindClassMemberFunction("getDescription", &ParticleEffectType::getDescription); // UIParticles diff --git a/src/framework/ui/uiparticles.cpp b/src/framework/ui/uiparticles.cpp index c1ee0d3d..9f89d879 100644 --- a/src/framework/ui/uiparticles.cpp +++ b/src/framework/ui/uiparticles.cpp @@ -23,27 +23,49 @@ #include "uiparticles.h" #include +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); + } + } + + 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(); + 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()); - else if(node->tag() == "item-count") - setItemCount(node->value()); - else if(node->tag() == "virtual") - setVirtual(node->value()); - }*/ + for(const OTMLNodePtr& node : styleNode->children()) { + if(node->tag() == "effect") + addEffect(node->value()); + else if(node->tag() == "reference-pos") + setReferencePos(node->value()); + } } void UIParticles::addEffect(const std::string& name) diff --git a/src/framework/ui/uiparticles.h b/src/framework/ui/uiparticles.h index 3d815f8c..a56eda1b 100644 --- a/src/framework/ui/uiparticles.h +++ b/src/framework/ui/uiparticles.h @@ -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 m_effects; + PointF m_referencePos; }; -#endif // UIPARTICLES_H +#endif diff --git a/src/framework/ui/uiwidgetimage.cpp b/src/framework/ui/uiwidgetimage.cpp index edc9e928..29a96302 100644 --- a/src/framework/ui/uiwidgetimage.cpp +++ b/src/framework/ui/uiwidgetimage.cpp @@ -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);