From 6a85c31a7717fe28985e323bd97cbd54ab17fe2a Mon Sep 17 00:00:00 2001 From: Henrique Santiago Date: Fri, 6 Jul 2012 02:00:49 -0300 Subject: [PATCH] Some particle stuff, far from done --- modules/client/client.otmod | 1 + modules/client_locales/locales.lua | 8 +- modules/client_particles/particles.lua | 95 +++++++++++++ modules/client_particles/particles.otmod | 17 +++ modules/client_particles/particles.otui | 130 ++++++++++++++++++ modules/client_particles/particles.png | Bin 0 -> 571 bytes modules/client_skins/skins.lua | 22 ++- modules/client_skins/skins/default.lua | 4 + .../skins/default/particles/shiny.otps | 52 +++++++ .../skins/default/styles/panels.otui | 6 +- modules/client_skins/skins/example.lua | 2 - modules/corelib/const.lua | 5 +- src/framework/CMakeLists.txt | 4 + src/framework/application.cpp | 5 +- src/framework/graphics/declarations.h | 4 + src/framework/graphics/particleeffect.cpp | 79 +++++++++++ src/framework/graphics/particleeffect.h | 68 +++++++++ src/framework/graphics/particlemanager.cpp | 45 +++--- src/framework/graphics/particlemanager.h | 18 ++- src/framework/luafunctions.cpp | 18 +++ src/framework/ui/declarations.h | 2 + src/framework/ui/ui.h | 1 + src/framework/ui/uiparticles.cpp | 54 ++++++++ src/framework/ui/uiparticles.h | 42 ++++++ src/otclient/core/map.cpp | 2 +- 25 files changed, 645 insertions(+), 39 deletions(-) create mode 100644 modules/client_particles/particles.lua create mode 100644 modules/client_particles/particles.otmod create mode 100644 modules/client_particles/particles.otui create mode 100644 modules/client_particles/particles.png create mode 100644 modules/client_skins/skins/default/particles/shiny.otps create mode 100644 src/framework/graphics/particleeffect.cpp create mode 100644 src/framework/graphics/particleeffect.h create mode 100644 src/framework/ui/uiparticles.cpp create mode 100644 src/framework/ui/uiparticles.h diff --git a/modules/client/client.otmod b/modules/client/client.otmod index 8c80bf23..4931b72d 100644 --- a/modules/client/client.otmod +++ b/modules/client/client.otmod @@ -8,6 +8,7 @@ Module load-later: - client_skins - client_locales + - client_particles - client_topmenu - client_background //- client_about diff --git a/modules/client_locales/locales.lua b/modules/client_locales/locales.lua index 7b0ab2a1..833dc1a7 100644 --- a/modules/client_locales/locales.lua +++ b/modules/client_locales/locales.lua @@ -13,7 +13,7 @@ local localeComboBox local function sendLocale(localeName) local protocolGame = g_game.getProtocolGame() if protocolGame then - protocolGame:sendExtendedOpcode(1, localeName) + protocolGame:sendExtendedOpcode(ExtendedLocales, localeName) return true end return false @@ -32,7 +32,7 @@ local function onGameStart() sendLocale(currentLocale.name) end -local function onServerSetLocale(protocol, opcode, buffer) +local function onExtendedLocales(protocol, opcode, buffer) local locale = installedLocales[buffer] if locale then localeComboBox:setCurrentOption(locale.languageName) @@ -63,7 +63,7 @@ function Locales.init() localeComboBox.onOptionChange = onLocaleComboBoxOptionChange end, false) - Extended.register(1, onServerSetLocale) + Extended.register(ExtendedLocales, onExtendedLocales) connect(g_game, { onGameStart = onGameStart }) end @@ -71,7 +71,7 @@ function Locales.terminate() installedLocales = nil currentLocale = nil localeComboBox = nil - Extended.unregister(1) + Extended.unregister(ExtendedLocales) disconnect(g_game, { onGameStart = onGameStart }) end diff --git a/modules/client_particles/particles.lua b/modules/client_particles/particles.lua new file mode 100644 index 00000000..44196129 --- /dev/null +++ b/modules/client_particles/particles.lua @@ -0,0 +1,95 @@ +Particles = { } + +-- private variables +local particlesWindow +local particlesButton + +-- private functions +local function onExtendedParticles(protocol, opcode, buffer) + +end + +-- public functions +function Particles.init() + particlesWindow = g_ui.displayUI('particles.otui') + particlesButton = TopMenu.addLeftButton('particlesButton', tr('Particles Manager'), 'particles.png', Particles.toggle) + + local particlesList = particlesWindow:getChildById('particlesList') + g_keyboard.bindKeyPress('Up', function() particlesList:focusPreviousChild(KeyboardFocusReason) end, particlesWindow) + g_keyboard.bindKeyPress('Down', function() particlesList:focusNextChild(KeyboardFocusReason) end, particlesWindow) + + Extended.register(ExtendedParticles, onExtendedParticles) +end + +function Particles.terminate() + particlesWindow:destroy() + particlesWindow = nil + + particlesButton:destroy() + particlesButton = nil + + Extended.unregister(ExtendedParticles) +end + +function Particles.show() + Particles.refreshList() + particlesWindow:show() + particlesWindow:raise() + particlesWindow:focus() +end + +function Particles.hide() + particlesWindow:hide() +end + +function Particles.toggle() + if particlesWindow:isVisible() then + Particles.hide() + else + Particles.show() + end +end + +function Particles.refreshInfo() + local particlesList = particlesWindow:getChildById('particlesList') + local widget = particlesList:getFocusedChild() + + local name = particlesWindow:getChildById('name') + name:setText(widget.effect:getName()) + + local location = particlesWindow:getChildById('location') + location:setText(widget.effect:getFile()) + + local description = particlesWindow:getChildById('description') + description:setText(widget.effect:getDescription()) +end + +function Particles.refreshList() + local particlesList = particlesWindow:getChildById('particlesList') + particlesList.onChildFocusChange = nil + particlesList:destroyChildren() + + local firstChild = nil + local effects = g_particles.getEffectsTypes() + for name,effect in pairs(effects) do + local label = g_ui.createWidget('ParticlesListLabel', particlesList) + label:setText(name) + label.effect = effect + + if not firstChild then + firstChild = label + end + end + + particlesList.onChildFocusChange = Particles.refreshInfo + if firstChild then + firstChild:focus() + end +end + +function Particles.start() + local particlesList = particlesWindow:getChildById('particlesList') + local focusedEffect = particlesList:getFocusedChild() + local preview = particlesWindow:getChildById('preview') + preview:addEffect(focusedEffect:getText()) +end diff --git a/modules/client_particles/particles.otmod b/modules/client_particles/particles.otmod new file mode 100644 index 00000000..fa38eda3 --- /dev/null +++ b/modules/client_particles/particles.otmod @@ -0,0 +1,17 @@ +Module + name: client_particles + description: Manages particles systems + author: baxnie + website: www.otclient.info + + dependencies: + - client_extended + - client_locales + - client_topmenu + + @onLoad: | + dofile 'particles' + Particles.init() + + @onUnload: | + Particles.terminate() diff --git a/modules/client_particles/particles.otui b/modules/client_particles/particles.otui new file mode 100644 index 00000000..229102a6 --- /dev/null +++ b/modules/client_particles/particles.otui @@ -0,0 +1,130 @@ +ParticlesListLabel < Label + font: verdana-11px-monochrome + background-color: alpha + text-offset: 2 0 + focusable: true + + $focus: + background-color: #ffffff22 + color: #ffffff + +MainWindow + id: particlesWindow + !text: tr('Particles Manager') + size: 450 450 + visible: false + @onEscape: Particles.hide() + + TextList + id: particlesList + anchors.top: parent.top + anchors.left: parent.left + anchors.bottom: separator.top + width: 128 + padding: 1 + focusable: false + margin-bottom: 10 + vertical-scrollbar: particlesListScrollBar + + VerticalScrollBar + id: particlesListScrollBar + anchors.top: particlesList.top + anchors.bottom: particlesList.bottom + anchors.left: particlesList.right + step: 14 + pixels-scroll: true + + Label + !text: tr('Name') + anchors.top: parent.top + anchors.left: prev.right + margin-left: 10 + + FlatLabel + id: name + anchors.top: prev.bottom + anchors.left: prev.left + anchors.right: parent.right + margin-top: 3 + + Label + !text: tr('Location') + anchors.top: prev.bottom + anchors.left: prev.left + margin-top: 10 + + FlatLabel + id: location + anchors.top: prev.bottom + anchors.left: prev.left + anchors.right: parent.right + margin-top: 3 + + Label + !text: tr('Description') + anchors.top: prev.bottom + anchors.left: prev.left + margin-top: 10 + + FlatLabel + id: description + anchors.top: prev.bottom + anchors.left: prev.left + anchors.right: parent.right + margin-top: 3 + + Label + !text: tr('Preview') + anchors.top: prev.bottom + anchors.left: prev.left + margin-top: 10 + + ParticlesFlatPanel + id: preview + margin-top: 3 + margin-bottom: 10 + anchors.top: prev.bottom + anchors.bottom: next.top + anchors.left: prev.left + anchors.right: parent.right + + reference: 10 10 + + Button + id: startButton + !text: tr('Start') + width: 64 + anchors.bottom: separator.top + anchors.left: location.left + margin-bottom: 10 + + Button + id: pauseButton + !text: tr('Pause') + width: 64 + anchors.bottom: prev.bottom + anchors.left: prev.right + margin-left: 5 + + Button + id: reloadButton + !text: tr('Reload') + width: 64 + anchors.bottom: separator.top + anchors.right: parent.right + margin-bottom: 10 + + HorizontalSeparator + id: separator + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: next.top + margin-bottom: 10 + + Button + id: closeButton + !text: tr('Close') + width: 64 + anchors.right: parent.right + anchors.bottom: parent.bottom + @onClick: Particles.hide() diff --git a/modules/client_particles/particles.png b/modules/client_particles/particles.png new file mode 100644 index 0000000000000000000000000000000000000000..a52cc2454d2d384cf2470868681e98ee4b9e5940 GIT binary patch literal 571 zcmV-B0>u4^P)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iyh~ z6etW1Yt7UE00Fy6L_t(I%Y~CmYZFlzhM&1)7H4E4gu19G{+m#`7?4=(N*W;|h=Rf_ zvZ)0PGF@x!2t!vEEC{nGW!5e97udBR#1IWS6DEsfE-sqH%%n-*-MPKzd!O$dOh>2Y z8q{0^)6pqvclY(JWn)=rf}^c~owZ|xCgu!olq=m{zeoE|n_j<1rLx+cT~`4vI%h1B zEUDBF?^a8y@&#ZNCmVo2H5d#BY@e(%UYs+?G7y?@KR@ak7o9WS`1f6iZch!oM#M6u zNzAe;RjyH*#tepo`u55CBtkuBU^+S_Rbdn-xtv}j@&Sf%!eRZF|D*lAd}s9@`_3L7 zujacTG~pg?1;)Db0$E8%#2>SthAKxP*VOdSsJXj&iGQRyhW%FPqSB>fD)tYMrHP;AC zN3RCqU*6eor{>rG1+NkLw%sbHWNbWmn7?@f@u~=mz!nb!`~xe8)_!$18NvVn002ov JPDHLkV1nR}?o|K) literal 0 HcmV?d00001 diff --git a/modules/client_skins/skins.lua b/modules/client_skins/skins.lua index b3c5c8ef..6e89bdd0 100644 --- a/modules/client_skins/skins.lua +++ b/modules/client_skins/skins.lua @@ -110,15 +110,25 @@ end function Skins.loadSkin(skin) local lowerName = string.lower(skin.name) - for i=1,#skin.fonts do - g_fonts.importFont('skins/' .. lowerName .. '/fonts/' .. skin.fonts[i]) + if skin.fonts then + for i=1,#skin.fonts do + g_fonts.importFont('skins/' .. lowerName .. '/fonts/' .. skin.fonts[i]) - if i == 1 then - g_fonts.setDefaultFont(skin.fonts[i]) + if i == 1 then + g_fonts.setDefaultFont(skin.fonts[i]) + end end end - for i=1,#skin.styles do - g_ui.importStyle('skins/' .. lowerName .. '/styles/' .. skin.styles[i]) + if skin.styles then + for i=1,#skin.styles do + g_ui.importStyle('skins/' .. lowerName .. '/styles/' .. skin.styles[i]) + end + end + + if skin.particles then + for i=1,#skin.particles do + g_particles.importParticle('skins/' .. lowerName .. '/particles/' .. skin.particles[i]) + end end end diff --git a/modules/client_skins/skins/default.lua b/modules/client_skins/skins/default.lua index f0618f26..163307cc 100644 --- a/modules/client_skins/skins/default.lua +++ b/modules/client_skins/skins/default.lua @@ -29,6 +29,10 @@ local skin = { 'miniwindow.otui', 'items.otui', 'creatures.otui' + }, + + particles = { + 'shiny.otps' } } diff --git a/modules/client_skins/skins/default/particles/shiny.otps b/modules/client_skins/skins/default/particles/shiny.otps new file mode 100644 index 00000000..de322a67 --- /dev/null +++ b/modules/client_skins/skins/default/particles/shiny.otps @@ -0,0 +1,52 @@ +Particle + name: shiny_star + + min-position-radius: 0 + max-position-radius: 8 + min-position-angle: 0 + max-position-angle: 360 + velocity: 4 + min-velocity-angle: 0 + max-velocity-angle: 360 + + particle-size: 4 4 + texture: shiny_star.png + composition-mode: addition + +Effect + name: Shiny3 + description: 3 Shiny stars derping aroud + + System + position: 0 0 + + Emitter + position: 0 0 + delay: 0 + duration: 0 + burstRate: 0 + burstCount: 3 + particle-type: shiny_star + + AttractionAffector + position: 0 0 + acceleration: 2 + +Effect + name: Shiny5 + description: 5 Shiny stars derping aroud + + System + position: 0 0 + + Emitter + position: 0 0 + delay: 0 + duration: 0 + burstRate: 0 + burstCount: 5 + particle-type: shiny_star + + AttractionAffector + position: 0 0 + acceleration: 2 diff --git a/modules/client_skins/skins/default/styles/panels.otui b/modules/client_skins/skins/default/styles/panels.otui index 5c73110c..3e98bc79 100644 --- a/modules/client_skins/skins/default/styles/panels.otui +++ b/modules/client_skins/skins/default/styles/panels.otui @@ -10,4 +10,8 @@ FlatPanel < Panel ScrollableFlatPanel < ScrollablePanel image-source: /images/panel_flat.png - image-border: 1 \ No newline at end of file + image-border: 1 + +ParticlesFlatPanel < Panel + image-source: /images/panel_flat.png + image-border: 1 diff --git a/modules/client_skins/skins/example.lua b/modules/client_skins/skins/example.lua index a4eef558..3f43ecea 100644 --- a/modules/client_skins/skins/example.lua +++ b/modules/client_skins/skins/example.lua @@ -1,8 +1,6 @@ local skin = { name = 'Example', - fonts = {}, - styles = { 'topmenu.otui' } diff --git a/modules/corelib/const.lua b/modules/corelib/const.lua index 962a54e2..a6eba07e 100644 --- a/modules/corelib/const.lua +++ b/modules/corelib/const.lua @@ -186,7 +186,6 @@ SpeakChannelOrange = 12 SpeakMonsterSay = 13 SpeakMonsterYell = 14 - FightOffensive = 1 FightBalanced = 2 FightDefensive = 3 @@ -194,6 +193,10 @@ FightDefensive = 3 DontChase = 0 ChaseOpponent = 1 +ExtendedActivate = 0 +ExtendedLocales = 1 +ExtendedParticles = 2 + -- @} KeyCodeDescs = { diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index 6ad2271a..88203ea6 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -229,6 +229,8 @@ SET(framework_SOURCES ${framework_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/graphics/particle.cpp ${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 @@ -350,6 +352,8 @@ SET(framework_SOURCES ${framework_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/ui/uilayout.h ${CMAKE_CURRENT_LIST_DIR}/ui/uimanager.cpp ${CMAKE_CURRENT_LIST_DIR}/ui/uimanager.h + ${CMAKE_CURRENT_LIST_DIR}/ui/uiparticles.cpp + ${CMAKE_CURRENT_LIST_DIR}/ui/uiparticles.h ${CMAKE_CURRENT_LIST_DIR}/ui/uirichtext.cpp ${CMAKE_CURRENT_LIST_DIR}/ui/uirichtext.h ${CMAKE_CURRENT_LIST_DIR}/ui/uitextedit.cpp diff --git a/src/framework/application.cpp b/src/framework/application.cpp index e5d086b7..0ae07a57 100644 --- a/src/framework/application.cpp +++ b/src/framework/application.cpp @@ -136,6 +136,9 @@ void Application::terminate() { assert(m_initialized); + // destroy particles + g_particles.terminate(); + // destroy any remaining widget g_ui.terminate(); @@ -278,7 +281,7 @@ void Application::poll() // poll input events g_window.poll(); - //g_particleManager.update(); + //g_particles.update(); Connection::poll(); g_dispatcher.poll(); diff --git a/src/framework/graphics/declarations.h b/src/framework/graphics/declarations.h index dda811d3..6eb9361e 100644 --- a/src/framework/graphics/declarations.h +++ b/src/framework/graphics/declarations.h @@ -41,6 +41,8 @@ class Particle; class ParticleEmitter; class ParticleAffector; class ParticleSystem; +class ParticleEffect; +class ParticleEffectType; typedef std::weak_ptr TextureWeakPtr; typedef std::weak_ptr ParticleSystemWeakPtr; @@ -58,6 +60,8 @@ typedef std::shared_ptr ParticlePtr; typedef std::shared_ptr ParticleEmitterPtr; typedef std::shared_ptr ParticleAffectorPtr; typedef std::shared_ptr ParticleSystemPtr; +typedef std::shared_ptr ParticleEffectPtr; +typedef std::shared_ptr ParticleEffectTypePtr; typedef std::vector ShaderList; #endif diff --git a/src/framework/graphics/particleeffect.cpp b/src/framework/graphics/particleeffect.cpp new file mode 100644 index 00000000..3aaeb6ed --- /dev/null +++ b/src/framework/graphics/particleeffect.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2010-2012 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 "particleeffect.h" + +ParticleEffectType::ParticleEffectType() +{ + +} + +bool ParticleEffectType::load(const OTMLNodePtr& node) +{ + m_node = node; + for(const OTMLNodePtr& childNode : node->children()) { + if(childNode->tag() == "name") { + setName(childNode->value()); + } + else if(childNode->tag() == "description") { + setDescription(childNode->value()); + } + } + return !m_name.empty(); +} + +bool ParticleEffect::load(const ParticleEffectTypePtr& effectType) +{ + if(!effectType) + return false; + + 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); + } + } + } + return true; +} + +void ParticleEffect::render() +{ + for(auto it = m_systems.begin(), end = m_systems.end(); it != end; ++it) + (*it)->render(); +} + +void ParticleEffect::update() +{ + for(auto it = m_systems.begin(), end = m_systems.end(); it != end;) { + const ParticleSystemPtr& system = *it; + + if(system->hasFinished()) { + it = m_systems.erase(it); + continue; + } + + system->update(); + ++it; + } +} diff --git a/src/framework/graphics/particleeffect.h b/src/framework/graphics/particleeffect.h new file mode 100644 index 00000000..6d00434e --- /dev/null +++ b/src/framework/graphics/particleeffect.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2010-2012 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 PARTICLEEFFECT_H +#define PARTICLEEFFECT_H + +#include "declarations.h" +#include "particlesystem.h" +#include +#include + +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; } + + 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; +}; + +class ParticleEffect : public LuaObject +{ +public: + ParticleEffect() {} + + bool load(const ParticleEffectTypePtr& effectType); + bool hasFinished() { return m_systems.size() == 0; } + void render(); + void update(); + +private: + std::vector m_systems; +}; + +#endif diff --git a/src/framework/graphics/particlemanager.cpp b/src/framework/graphics/particlemanager.cpp index 84aa7214..148006c9 100644 --- a/src/framework/graphics/particlemanager.cpp +++ b/src/framework/graphics/particlemanager.cpp @@ -24,43 +24,56 @@ #include #include -ParticleManager g_particleManager; +ParticleManager g_particles; -bool ParticleManager::load(const std::string& filename) +bool ParticleManager::importParticle(const std::string& file) { try { - OTMLDocumentPtr doc = OTMLDocument::parse(filename); + OTMLDocumentPtr doc = OTMLDocument::parse(file); for(const OTMLNodePtr& node : doc->children()) { - if(node->tag() == "ParticleSystem") { - ParticleSystemPtr particleSystem = ParticleSystemPtr(new ParticleSystem); - particleSystem->load(node); - m_systems.push_back(particleSystem); + if(node->tag() == "Effect") { + ParticleEffectTypePtr particleEffectType = ParticleEffectTypePtr(new ParticleEffectType); + if(particleEffectType->load(node)) { + particleEffectType->setFile(g_resources.resolvePath(file)); + m_effectsTypes[particleEffectType->getName()] = particleEffectType; + } + } + else if(node->tag() == "Particle") { + // nothing yet } } return true; } catch(stdext::exception& e) { - g_logger.error(stdext::format("could not load particles: %s", e.what())); + g_logger.error(stdext::format("could not load particles file %s: %s", file, e.what())); return false; } } -void ParticleManager::render() +ParticleEffectPtr ParticleManager::createEffect(const std::string& name) +{ + ParticleEffectPtr particleEffect = ParticleEffectPtr(new ParticleEffect); + if(particleEffect->load(m_effectsTypes[name])) + return particleEffect; + return nullptr; +} + +void ParticleManager::terminate() { - for(auto it = m_systems.begin(), end = m_systems.end(); it != end; ++it) - (*it)->render(); + m_effects.clear(); + m_effectsTypes.clear(); } void ParticleManager::update() { - for(auto it = m_systems.begin(), end = m_systems.end(); it != end;) { - const ParticleSystemPtr& particleSystem = *it; + for(auto it = m_effects.begin(), end = m_effects.end(); it != end;) { + const ParticleEffectPtr& particleEffect = *it; - if(particleSystem->hasFinished()) { - it = m_systems.erase(it); + if(particleEffect->hasFinished()) { + it = m_effects.erase(it); continue; } - particleSystem->update(); + particleEffect->update(); ++it; } } diff --git a/src/framework/graphics/particlemanager.h b/src/framework/graphics/particlemanager.h index 7191ad26..cbc07313 100644 --- a/src/framework/graphics/particlemanager.h +++ b/src/framework/graphics/particlemanager.h @@ -24,20 +24,24 @@ #define PARTICLEMANAGER_H #include "declarations.h" -#include "particlesystem.h" -#include "particleaffector.h" +#include "particleeffect.h" -class ParticleManager { +class ParticleManager +{ public: - bool load(const std::string& filename); + bool importParticle(const std::string& file); + ParticleEffectPtr createEffect(const std::string& name); + void terminate(); - void render(); void update(); + std::map getEffectsTypes() { return m_effectsTypes; } + private: - std::list m_systems; + std::list m_effects; + std::map m_effectsTypes; }; -extern ParticleManager g_particleManager; +extern ParticleManager g_particles; #endif diff --git a/src/framework/luafunctions.cpp b/src/framework/luafunctions.cpp index 14f71b3c..e19340d4 100644 --- a/src/framework/luafunctions.cpp +++ b/src/framework/luafunctions.cpp @@ -35,6 +35,7 @@ #include #include #include +#include void Application::registerLuaFunctions() { @@ -648,4 +649,21 @@ void Application::registerLuaFunctions() g_lua.bindSingletonFunction("g_resources", "fileExists", &ResourceManager::fileExists, &g_resources); g_lua.bindSingletonFunction("g_resources", "getRealDir", &ResourceManager::getRealDir, &g_resources); g_lua.bindSingletonFunction("g_resources", "getWorkDir", &ResourceManager::getWorkDir, &g_resources); + + // ParticleManager + g_lua.registerSingletonClass("g_particles"); + g_lua.bindSingletonFunction("g_particles", "importParticle", &ParticleManager::importParticle, &g_particles); + g_lua.bindSingletonFunction("g_particles", "getEffectsTypes", &ParticleManager::getEffectsTypes, &g_particles); + + // ParticleEffect + 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 + g_lua.registerClass(); + g_lua.bindClassStaticFunction("create", []{ return UIParticlesPtr(new UIParticles); } ); + g_lua.bindClassMemberFunction("addEffect", &UIParticles::addEffect); } diff --git a/src/framework/ui/declarations.h b/src/framework/ui/declarations.h index 10635fb4..31ccb1f4 100644 --- a/src/framework/ui/declarations.h +++ b/src/framework/ui/declarations.h @@ -34,10 +34,12 @@ class UIHorizontalLayout; class UIVerticalLayout; class UIGridLayout; class UIAnchorLayout; +class UIParticles; typedef std::shared_ptr UIWidgetPtr; typedef std::weak_ptr UIWidgetWeakPtr; +typedef std::shared_ptr UIParticlesPtr; typedef std::shared_ptr UITextEditPtr; typedef std::shared_ptr UILayoutPtr; typedef std::shared_ptr UIBoxLayoutPtr; diff --git a/src/framework/ui/ui.h b/src/framework/ui/ui.h index 01af51ee..93048fcf 100644 --- a/src/framework/ui/ui.h +++ b/src/framework/ui/ui.h @@ -31,5 +31,6 @@ #include "uiverticallayout.h" #include "uigridlayout.h" #include "uianchorlayout.h" +#include "uiparticles.h" #endif diff --git a/src/framework/ui/uiparticles.cpp b/src/framework/ui/uiparticles.cpp new file mode 100644 index 00000000..dec4561b --- /dev/null +++ b/src/framework/ui/uiparticles.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2010-2012 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 "uiparticles.h" +#include + +void UIParticles::drawSelf(Fw::DrawPane drawPane) +{ + if((drawPane & Fw::ForegroundPane) == 0) + return; + + for(auto it = m_effects.begin(), end = m_effects.end(); it != end; ++it) + (*it)->render(); +} + +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()); + }*/ +} + +void UIParticles::addEffect(const std::string& name) +{ + ParticleEffectPtr effect = g_particles.createEffect(name); + if(effect) + m_effects.push_back(effect); +} diff --git a/src/framework/ui/uiparticles.h b/src/framework/ui/uiparticles.h new file mode 100644 index 00000000..21d47635 --- /dev/null +++ b/src/framework/ui/uiparticles.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2010-2012 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 UIPARTICLES_H +#define UIPARTICLES_H + +#include +#include + +class UIParticles : public UIWidget +{ +public: + void drawSelf(Fw::DrawPane drawPane); + + void addEffect(const std::string& name); + + void onStyleApply(const std::string& styleName, const OTMLNodePtr& styleNode); + +private: + std::vector m_effects; +}; + +#endif // UIPARTICLES_H diff --git a/src/otclient/core/map.cpp b/src/otclient/core/map.cpp index 42058e5e..e16ac8e4 100644 --- a/src/otclient/core/map.cpp +++ b/src/otclient/core/map.cpp @@ -68,7 +68,7 @@ bool Map::loadOtbm(const std::string& fileName) } if (!g_things.isOtbLoaded() || !g_things.isXmlLoaded()) { - g_logger.error(stdext::format("OTB and XML are not loaded yet to load a map.")); + g_logger.error("OTB and XML are not loaded yet to load a map."); return false; }