From bdb09d26fc6c489228cb2c28be75024f9a49eb75 Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Thu, 28 Aug 2008 20:29:06 +0000 Subject: Accepted Patch by Scraggy that moves text in such a way that no text overlaps --- src/Makefile.am | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/Makefile.am') diff --git a/src/Makefile.am b/src/Makefile.am index 3156a800..340f1947 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -291,6 +291,10 @@ tmw_SOURCES = gui/widgets/resizegrip.cpp \ sound.cpp \ sound.h \ sprite.h \ + text.cpp \ + text.h \ + textmanager.cpp \ + textmanager.h \ textparticle.cpp \ textparticle.h \ tileset.h \ -- cgit v1.2.3-70-g09d2 From 56410d9ff28448a73be7a7d115d54c1ee578972c Mon Sep 17 00:00:00 2001 From: Philipp Sehmisch Date: Sun, 26 Oct 2008 01:46:40 +0000 Subject: Implemented particle emitters with properties which change over time according to wave functions. --- ChangeLog | 8 ++++ src/CMakeLists.txt | 2 +- src/Makefile.am | 2 +- src/particle.cpp | 2 +- src/particleemitter.cpp | 100 ++++++++++++++++++++++++----------------- src/particleemitter.h | 37 +++++++-------- src/particleemitterprop.h | 112 ++++++++++++++++++++++++++++++++++++++++++++++ src/utils/minmax.h | 50 --------------------- tmw.cbp | 29 +++++++++--- 9 files changed, 225 insertions(+), 117 deletions(-) create mode 100644 src/particleemitterprop.h delete mode 100644 src/utils/minmax.h (limited to 'src/Makefile.am') diff --git a/ChangeLog b/ChangeLog index cad907ba..afdc97da 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2008-10-26 Philipp Sehmisch + + * src/particle.cpp, src/particleemitter.cpp, src/particleemitter.h, + src/particleemitterprop.h, src/utils/minmax.h: Implemented particle + emitters with properties which change over time according to wave + functions. + * src/Makefile.am, src/CMakeLists.txt, tmw.cbp: Updated project files. + 2008-10-23 Dennis Friis * src/net/tradehandler.cpp: Add support for new athena trade-add diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 20f2f761..94ee854a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -265,7 +265,6 @@ SET(SRCS utils/base64.h utils/dtor.h utils/fastsqrt.h - utils/minmax.h utils/strprintf.cpp utils/strprintf.h utils/tostring.h @@ -328,6 +327,7 @@ SET(SRCS particle.h particleemitter.cpp particleemitter.h + particleemitterprop.h player.cpp player.h player_relations.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 340f1947..867953ab 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -215,7 +215,6 @@ tmw_SOURCES = gui/widgets/resizegrip.cpp \ utils/base64.h \ utils/dtor.h \ utils/fastsqrt.h \ - utils/minmax.h \ utils/strprintf.cpp \ utils/strprintf.h \ utils/tostring.h \ @@ -278,6 +277,7 @@ tmw_SOURCES = gui/widgets/resizegrip.cpp \ particle.h \ particleemitter.cpp \ particleemitter.h \ + particleemitterprop.h \ player.cpp \ player.h \ player_relations.cpp \ diff --git a/src/particle.cpp b/src/particle.cpp index 8591838f..1521e75b 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -181,7 +181,7 @@ Particle::update() e++ ) { - Particles newParticles = (*e)->createParticles(); + Particles newParticles = (*e)->createParticles(mLifetimePast); for ( ParticleIterator p = newParticles.begin(); p != newParticles.end(); p++ diff --git a/src/particleemitter.cpp b/src/particleemitter.cpp index 816a5d28..bb4a7c6e 100644 --- a/src/particleemitter.cpp +++ b/src/particleemitter.cpp @@ -74,20 +74,22 @@ ParticleEmitter::ParticleEmitter(xmlNodePtr emitterNode, Particle *target, Map * if (name == "position-x") { - mParticlePosX = readMinMax(propertyNode, 0.0f); + mParticlePosX = readParticleEmitterProp(propertyNode, 0.0f); } else if (name == "position-y") { - mParticlePosY = readMinMax(propertyNode, 0.0f); + mParticlePosY = readParticleEmitterProp(propertyNode, 0.0f); mParticlePosY.minVal *= SIN45; mParticlePosY.maxVal *= SIN45; + mParticlePosY.changeAmplitude *= SIN45; } else if (name == "position-z") { - mParticlePosZ = readMinMax(propertyNode, 0.0f); + mParticlePosZ = readParticleEmitterProp(propertyNode, 0.0f); mParticlePosZ.minVal *= SIN45; mParticlePosZ.maxVal *= SIN45; + mParticlePosZ.changeAmplitude *= SIN45; } else if (name == "image") { @@ -101,70 +103,72 @@ ParticleEmitter::ParticleEmitter(xmlNodePtr emitterNode, Particle *target, Map * } else if (name == "horizontal-angle") { - mParticleAngleHorizontal = readMinMax(propertyNode, 0.0f); + mParticleAngleHorizontal = readParticleEmitterProp(propertyNode, 0.0f); mParticleAngleHorizontal.minVal *= DEG_RAD_FACTOR; mParticleAngleHorizontal.maxVal *= DEG_RAD_FACTOR; + mParticleAngleHorizontal.changeAmplitude *= DEG_RAD_FACTOR; } else if (name == "vertical-angle") { - mParticleAngleVertical = readMinMax(propertyNode, 0.0f); + mParticleAngleVertical = readParticleEmitterProp(propertyNode, 0.0f); mParticleAngleVertical.minVal *= DEG_RAD_FACTOR; mParticleAngleVertical.maxVal *= DEG_RAD_FACTOR; + mParticleAngleVertical.changeAmplitude *= DEG_RAD_FACTOR; } else if (name == "power") { - mParticlePower = readMinMax(propertyNode, 0.0f); + mParticlePower = readParticleEmitterProp(propertyNode, 0.0f); } else if (name == "gravity") { - mParticleGravity = readMinMax(propertyNode, 0.0f); + mParticleGravity = readParticleEmitterProp(propertyNode, 0.0f); } else if (name == "randomnes" || name == "randomness") // legacy bug { - mParticleRandomness = readMinMax(propertyNode, 0); + mParticleRandomness = readParticleEmitterProp(propertyNode, 0); } else if (name == "bounce") { - mParticleBounce = readMinMax(propertyNode, 0.0f); + mParticleBounce = readParticleEmitterProp(propertyNode, 0.0f); } else if (name == "lifetime") { - mParticleLifetime = readMinMax(propertyNode, 0); + mParticleLifetime = readParticleEmitterProp(propertyNode, 0); mParticleLifetime.minVal += 1; } else if (name == "output") { - mOutput = readMinMax(propertyNode, 0); + mOutput = readParticleEmitterProp(propertyNode, 0); mOutput.maxVal +=1; } else if (name == "output-pause") { - mOutputPause = readMinMax(propertyNode, 0); - mOutputPauseLeft = mOutputPause.value(); + mOutputPause = readParticleEmitterProp(propertyNode, 0); + mOutputPauseLeft = mOutputPause.value(0); } else if (name == "acceleration") { - mParticleAcceleration = readMinMax(propertyNode, 0.0f); + mParticleAcceleration = readParticleEmitterProp(propertyNode, 0.0f); } else if (name == "die-distance") { - mParticleDieDistance = readMinMax(propertyNode, 0.0f); + mParticleDieDistance = readParticleEmitterProp(propertyNode, 0.0f); } else if (name == "momentum") { - mParticleMomentum = readMinMax(propertyNode, 1.0f); + mParticleMomentum = readParticleEmitterProp(propertyNode, 1.0f); } else if (name == "fade-out") { - mParticleFadeOut = readMinMax(propertyNode, 0); + mParticleFadeOut = readParticleEmitterProp(propertyNode, 0); } else if (name == "fade-in") { - mParticleFadeIn = readMinMax(propertyNode, 0); + mParticleFadeIn = readParticleEmitterProp(propertyNode, 0); } else if (name == "alpha") { - mParticleAlpha = readMinMax(propertyNode, 1.0f); + mParticleAlpha = readParticleEmitterProp(propertyNode, 1.0f); } else if (name == "follow-parent") { @@ -299,21 +303,35 @@ ParticleEmitter::~ParticleEmitter() } -template MinMax -ParticleEmitter::readMinMax(xmlNodePtr propertyNode, T def) +template ParticleEmitterProp +ParticleEmitter::readParticleEmitterProp(xmlNodePtr propertyNode, T def) { - MinMax retval; + ParticleEmitterProp retval; def = (T) XML::getFloatProperty(propertyNode, "value", (double) def); retval.set((T) XML::getFloatProperty(propertyNode, "min", (double) def), (T) XML::getFloatProperty(propertyNode, "max", (double) def)); + std::string change = XML::getProperty(propertyNode, "change-func", "none"); + T amplitude = (T) XML::getFloatProperty(propertyNode, "change-amplitude", 0.0); + int period = XML::getProperty(propertyNode, "change-period", 0); + int phase = XML::getProperty(propertyNode, "change-phase", 0); + if (change == "saw" || change == "sawtooth") { + retval.setFunction(FUNC_SAW, amplitude, period, phase); + } else if (change == "sine" || change == "sinewave") { + retval.setFunction(FUNC_SINE, amplitude, period, phase); + } else if (change == "triangle") { + retval.setFunction(FUNC_TRIANGLE, amplitude, period, phase); + } else if (change == "square"){ + retval.setFunction(FUNC_SQUARE, amplitude, period, phase); + } + return retval; } std::list -ParticleEmitter::createParticles() +ParticleEmitter::createParticles(int tick) { std::list newParticles; @@ -322,9 +340,9 @@ ParticleEmitter::createParticles() mOutputPauseLeft--; return newParticles; } - mOutputPauseLeft = mOutputPause.value(); + mOutputPauseLeft = mOutputPause.value(tick); - for (int i = mOutput.value(); i > 0; i--) + for (int i = mOutput.value(tick); i > 0; i--) { // Limit maximum particles if (Particle::particleCount > Particle::maxCount) break; @@ -346,33 +364,33 @@ ParticleEmitter::createParticles() newParticle->setPosition( - mParticlePosX.value(), - mParticlePosY.value(), - mParticlePosZ.value()); + mParticlePosX.value(tick), + mParticlePosY.value(tick), + mParticlePosZ.value(tick)); - float angleH = mParticleAngleHorizontal.value(); - float angleV = mParticleAngleVertical.value(); - float power = mParticlePower.value(); + float angleH = mParticleAngleHorizontal.value(tick); + float angleV = mParticleAngleVertical.value(tick); + float power = mParticlePower.value(tick); newParticle->setVelocity( cos(angleH) * cos(angleV) * power, sin(angleH) * cos(angleV) * power, sin(angleV) * power); - newParticle->setRandomness(mParticleRandomness.value()); - newParticle->setGravity(mParticleGravity.value()); - newParticle->setBounce(mParticleBounce.value()); + newParticle->setRandomness(mParticleRandomness.value(tick)); + newParticle->setGravity(mParticleGravity.value(tick)); + newParticle->setBounce(mParticleBounce.value(tick)); newParticle->setFollow(mParticleFollow); newParticle->setDestination(mParticleTarget, - mParticleAcceleration.value(), - mParticleMomentum.value() + mParticleAcceleration.value(tick), + mParticleMomentum.value(tick) ); - newParticle->setDieDistance(mParticleDieDistance.value()); + newParticle->setDieDistance(mParticleDieDistance.value(tick)); - newParticle->setLifetime(mParticleLifetime.value()); - newParticle->setFadeOut(mParticleFadeOut.value()); - newParticle->setFadeIn(mParticleFadeIn.value()); - newParticle->setAlpha(mParticleAlpha.value()); + newParticle->setLifetime(mParticleLifetime.value(tick)); + newParticle->setFadeOut(mParticleFadeOut.value(tick)); + newParticle->setFadeIn(mParticleFadeIn.value(tick)); + newParticle->setAlpha(mParticleAlpha.value(tick)); for (std::list::iterator i = mParticleChildEmitters.begin(); i != mParticleChildEmitters.end(); diff --git a/src/particleemitter.h b/src/particleemitter.h index 5cf3fd46..4ef088f6 100644 --- a/src/particleemitter.h +++ b/src/particleemitter.h @@ -27,10 +27,11 @@ #include #include "utils/xml.h" -#include "utils/minmax.h" #include "resources/animation.h" +#include "particleemitterprop.h" + class Image; class Map; class Particle; @@ -66,7 +67,7 @@ class ParticleEmitter * Spawns new particles * @return: a list of created particles */ - std::list createParticles(); + std::list createParticles(int tick); /** * Sets the target of the particles that are created @@ -76,50 +77,50 @@ class ParticleEmitter { mParticleTarget = target; }; private: - template MinMax readMinMax(xmlNodePtr propertyNode, T def); + template ParticleEmitterProp readParticleEmitterProp(xmlNodePtr propertyNode, T def); /** * initial position of particles: */ - MinMax mParticlePosX, mParticlePosY, mParticlePosZ; + ParticleEmitterProp mParticlePosX, mParticlePosY, mParticlePosZ; /** * initial vector of particles: */ - MinMax mParticleAngleHorizontal, mParticleAngleVertical; + ParticleEmitterProp mParticleAngleHorizontal, mParticleAngleVertical; /** * Initial velocity of particles */ - MinMax mParticlePower; + ParticleEmitterProp mParticlePower; /* * Vector changing of particles: */ - MinMax mParticleGravity; - MinMax mParticleRandomness; - MinMax mParticleBounce; + ParticleEmitterProp mParticleGravity; + ParticleEmitterProp mParticleRandomness; + ParticleEmitterProp mParticleBounce; bool mParticleFollow; /* * Properties of targeting particles: */ Particle *mParticleTarget; - MinMax mParticleAcceleration; - MinMax mParticleDieDistance; - MinMax mParticleMomentum; + ParticleEmitterProp mParticleAcceleration; + ParticleEmitterProp mParticleDieDistance; + ParticleEmitterProp mParticleMomentum; /* * Behavior over time of the particles: */ - MinMax mParticleLifetime; - MinMax mParticleFadeOut; - MinMax mParticleFadeIn; + ParticleEmitterProp mParticleLifetime; + ParticleEmitterProp mParticleFadeOut; + ParticleEmitterProp mParticleFadeIn; Map *mMap; /**< Map the particles are spawned on */ - MinMax mOutput; /**< Number of particles spawned per update */ - MinMax mOutputPause; /**< Pause in frames between two spawns */ + ParticleEmitterProp mOutput; /**< Number of particles spawned per update */ + ParticleEmitterProp mOutputPause; /**< Pause in frames between two spawns */ int mOutputPauseLeft; /* @@ -127,7 +128,7 @@ class ParticleEmitter */ Image *mParticleImage; /**< Particle image, if used */ Animation mParticleAnimation; /**< Filename of particle animation file */ - MinMax mParticleAlpha; /**< Opacity of the graphical representation of the particles */ + ParticleEmitterProp mParticleAlpha; /**< Opacity of the graphical representation of the particles */ /** List of emitters the spawned particles are equipped with */ std::list mParticleChildEmitters; diff --git a/src/particleemitterprop.h b/src/particleemitterprop.h new file mode 100644 index 00000000..e645c169 --- /dev/null +++ b/src/particleemitterprop.h @@ -0,0 +1,112 @@ +/* + * The Mana World + * Copyright 2006 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * The Mana World is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * $Id$ + */ + +#include +#include + +/** + * Returns a random numeric value that is larger than or equal min and smaller + * than max + */ + +enum ChangeFunc +{ + FUNC_NONE, + FUNC_SINE, + FUNC_SAW, + FUNC_TRIANGLE, + FUNC_SQUARE +}; + +template struct ParticleEmitterProp +{ + ParticleEmitterProp(): + changeFunc(FUNC_NONE) + { + } + + void set(T min, T max) + { + minVal=min; maxVal=max; + } + + void set(T val) + { + set(val, val); + } + + void setFunction(ChangeFunc func, T amplitude, int period, int phase) + { + changeFunc = func; + changeAmplitude = amplitude; + changePeriod = period; + changePhase = phase; + } + + T value(int tick) + { + tick += changePhase; + T val = (T) (minVal + (maxVal - minVal) * (rand() / ((double) RAND_MAX + 1))); + + switch (changeFunc) + { + case FUNC_SINE: + val += (T) std::sin(M_PI * 2 * ((double)(tick%changePeriod) / (double)changePeriod)) * changeAmplitude; + break; + case FUNC_SAW: + val += (T) (changeAmplitude * ((double)(tick%changePeriod) / (double)changePeriod)) * 2 - changeAmplitude; + break; + case FUNC_TRIANGLE: + if ((tick%changePeriod) * 2 < changePeriod) + { + val += changeAmplitude - (T)((tick%changePeriod) / (double)changePeriod) * changeAmplitude * 4; + } else { + val += changeAmplitude * -3 + (T)((tick%changePeriod) / (double)changePeriod) * changeAmplitude * 4; + // I have no idea why this works but it does + } + break; + case FUNC_SQUARE: + if ((tick%changePeriod) * 2 < changePeriod) + { + val += changeAmplitude; + } else { + val -= changeAmplitude; + } + break; + case FUNC_NONE: + default: + //nothing + break; + } + + return val; + } + + T minVal; + T maxVal; + + ChangeFunc changeFunc; + T changeAmplitude; + int changePeriod; + int changePhase; +}; diff --git a/src/utils/minmax.h b/src/utils/minmax.h deleted file mode 100644 index 427c5da7..00000000 --- a/src/utils/minmax.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * The Mana World - * Copyright 2006 The Mana World Development Team - * - * This file is part of The Mana World. - * - * The Mana World is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * any later version. - * - * The Mana World is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with The Mana World; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * $Id$ - */ - -#include - -/** - * Returns a random numeric value that is larger than or equal min and smaller - * than max - */ - -template struct MinMax -{ - void set(T min, T max) - { - minVal=min; maxVal=max; - } - - void set(T val) - { - set(val, val); - } - - T value() - { - return (T)(minVal + (maxVal - minVal) * (rand() / ((double) RAND_MAX + 1))); - } - - T minVal; - T maxVal; -}; diff --git a/tmw.cbp b/tmw.cbp index 9c009766..f108d01d 100644 --- a/tmw.cbp +++ b/tmw.cbp @@ -95,6 +95,8 @@ + + @@ -105,6 +107,8 @@ + + @@ -152,6 +156,8 @@ + + @@ -172,6 +178,7 @@ + @@ -274,6 +281,7 @@ + @@ -290,6 +298,7 @@ + @@ -301,6 +310,8 @@ + + @@ -341,22 +352,30 @@ + + + + - + + + + + + - - + + -- cgit v1.2.3-70-g09d2 From 6ac9c3bce62a8fc79e23477417188108f0ad9fa6 Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Fri, 5 Dec 2008 21:38:31 +0100 Subject: Fix race condition with a std::string access The downloading thread was writing to a std::string while the main thread was trying to draw it, for example. Now access to the label caption is guarded with a mutex. Should fix crashes while downloading updates. --- src/Makefile.am | 1 + src/gui/updatewindow.cpp | 31 +++++++++------- src/gui/updatewindow.h | 13 +++++-- src/utils/mutex.h | 94 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+), 15 deletions(-) create mode 100644 src/utils/mutex.h (limited to 'src/Makefile.am') diff --git a/src/Makefile.am b/src/Makefile.am index 867953ab..3387690a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -219,6 +219,7 @@ tmw_SOURCES = gui/widgets/resizegrip.cpp \ utils/strprintf.h \ utils/tostring.h \ utils/trim.h \ + utils/mutex.h \ utils/xml.cpp \ utils/xml.h \ animatedsprite.cpp \ diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp index ea0f86cd..6083725e 100644 --- a/src/gui/updatewindow.cpp +++ b/src/gui/updatewindow.cpp @@ -47,7 +47,7 @@ /** * Calculates the Alder-32 checksum for the given file. */ -unsigned long fadler32(FILE *file) +static unsigned long fadler32(FILE *file) { // Obtain file size fseek(file, 0, SEEK_END); @@ -146,15 +146,9 @@ UpdaterWindow::UpdaterWindow(const std::string &updateHost, UpdaterWindow::~UpdaterWindow() { if (mThread) - { - SDL_WaitThread(mThread, NULL); - mThread = NULL; - } + SDL_WaitThread(mThread, NULL); - if (mMemoryBuffer) - { - free(mMemoryBuffer); - } + free(mMemoryBuffer); // Remove possibly leftover temporary download ::remove((mUpdatesDir + "/download.temp").c_str()); @@ -169,8 +163,9 @@ void UpdaterWindow::setProgress(float p) void UpdaterWindow::setLabel(const std::string &str) { - mLabel->setCaption(str); - mLabel->adjustSize(); + // Do delayed label text update, since Guichan isn't thread-safe + MutexLocker lock(mLabelMutex); + mNewLabelCaption = str; } void UpdaterWindow::enable() @@ -413,6 +408,17 @@ void UpdaterWindow::logic() // Update Scroll logic mScrollArea->logic(); + // Synchronize label caption when necessary + { + MutexLocker lock(mLabelMutex); + + if (mLabel->getCaption() != mNewLabelCaption) + { + mLabel->setCaption(mNewLabelCaption); + mLabel->adjustSize(); + } + } + switch (mDownloadStatus) { case UPDATE_ERROR: @@ -434,7 +440,8 @@ void UpdaterWindow::logic() mBrowserBox->addRow("##1 It is strongly recommended that"); mBrowserBox->addRow("##1 you try again later"); mBrowserBox->addRow(mCurlError); - mScrollArea->setVerticalScrollAmount(mScrollArea->getVerticalMaxScroll()); + mScrollArea->setVerticalScrollAmount( + mScrollArea->getVerticalMaxScroll()); mDownloadStatus = UPDATE_COMPLETE; break; case UPDATE_NEWS: diff --git a/src/gui/updatewindow.h b/src/gui/updatewindow.h index d7e3c4c7..a7dfe2cb 100644 --- a/src/gui/updatewindow.h +++ b/src/gui/updatewindow.h @@ -30,12 +30,13 @@ #include "../guichanfwd.h" +#include "../utils/mutex.h" + class BrowserBox; class Button; class ProgressBar; class ScrollArea; -struct SDL_mutex; struct SDL_Thread; /** @@ -88,7 +89,7 @@ class UpdaterWindow : public Window, public gcn::ActionListener int updateState; - protected: +private: void download(); /** @@ -133,6 +134,12 @@ class UpdaterWindow : public Window, public gcn::ActionListener /** The file currently downloading. */ std::string mCurrentFile; + /** The new label caption to be set in the logic method. */ + std::string mNewLabelCaption; + + /** The mutex used to guard access to mNewLabelCaption. */ + Mutex mLabelMutex; + /** The Adler32 checksum of the file currently downloading. */ unsigned long mCurrentChecksum; @@ -164,7 +171,7 @@ class UpdaterWindow : public Window, public gcn::ActionListener Button *mCancelButton; /**< Button to stop the update process. */ Button *mPlayButton; /**< Button to start playing. */ ProgressBar *mProgressBar; /**< Update progress bar. */ - BrowserBox* mBrowserBox; /**< Box to display news. */ + BrowserBox *mBrowserBox; /**< Box to display news. */ ScrollArea *mScrollArea; /**< Used to scroll news box. */ }; diff --git a/src/utils/mutex.h b/src/utils/mutex.h new file mode 100644 index 00000000..6c35987c --- /dev/null +++ b/src/utils/mutex.h @@ -0,0 +1,94 @@ +/* + * The Mana World + * Copyright 2008 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * The Mana World is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TMW_MUTEX_H +#define TMW_MUTEX_H + +#include + +#include "../log.h" + +/** + * A mutex provides mutual exclusion of access to certain data that is + * accessed by multiple threads. + */ +class Mutex +{ +public: + Mutex(); + ~Mutex(); + + void lock(); + void unlock(); + +private: + SDL_mutex *mMutex; +}; + +/** + * A convenience class for locking a mutex. + */ +class MutexLocker +{ +public: + MutexLocker(Mutex mutex); + ~MutexLocker(); + +private: + Mutex mMutex; +}; + + +inline Mutex::Mutex() +{ + mMutex = SDL_CreateMutex(); +} + +inline Mutex::~Mutex() +{ + SDL_DestroyMutex(mMutex); +} + +inline void Mutex::lock() +{ + if (SDL_mutexP(mMutex) == -1) + logger->log("Mutex locking failed: %s", SDL_GetError()); +} + +inline void Mutex::unlock() +{ + if (SDL_mutexV(mMutex) == -1) + logger->log("Mutex unlocking failed: %s", SDL_GetError()); +} + + +inline MutexLocker::MutexLocker(Mutex mutex): + mMutex(mutex) +{ + mMutex.lock(); +} + +inline MutexLocker::~MutexLocker() +{ + mMutex.unlock(); +} + +#endif // TMW_MUTEX_H -- cgit v1.2.3-70-g09d2 From 704f58c9033599c871c176df68ffe7ac3bc8c969 Mon Sep 17 00:00:00 2001 From: Fate Date: Sat, 6 Dec 2008 12:20:16 -0700 Subject: Added particle containers and refactored beings to use them (to clean up responsibilities a little) --- src/Makefile.am | 2 + src/being.cpp | 34 ++-------- src/being.h | 12 +++- src/particlecontainer.cpp | 158 ++++++++++++++++++++++++++++++++++++++++++++++ src/particlecontainer.h | 106 +++++++++++++++++++++++++++++++ 5 files changed, 281 insertions(+), 31 deletions(-) create mode 100644 src/particlecontainer.cpp create mode 100644 src/particlecontainer.h (limited to 'src/Makefile.am') diff --git a/src/Makefile.am b/src/Makefile.am index 3387690a..e9d69b5e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -279,6 +279,8 @@ tmw_SOURCES = gui/widgets/resizegrip.cpp \ particleemitter.cpp \ particleemitter.h \ particleemitterprop.h \ + particlecontainer.cpp \ + particlecontainer.h \ player.cpp \ player.h \ player_relations.cpp \ diff --git a/src/being.cpp b/src/being.cpp index ef257f43..7c6d91e7 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -74,7 +74,9 @@ Being::Being(int id, int job, Map *map): mPx(0), mPy(0), mSprites(VECTOREND_SPRITE, NULL), mSpriteIDs(VECTOREND_SPRITE, 0), - mSpriteColors(VECTOREND_SPRITE, "") + mSpriteColors(VECTOREND_SPRITE, ""), + mStatusParticleEffects(&mStunParticleEffects, false), + mChildParticleEffects(&mStatusParticleEffects, false) { setMap(map); @@ -95,13 +97,6 @@ Being::~Being() std::for_each(mSprites.begin(), mSprites.end(), make_dtor(mSprites)); clearPath(); - for ( std::list::iterator i = mChildParticleEffects.begin(); - i != mChildParticleEffects.end(); - i++) - { - (*i)->kill(); - } - setMap(NULL); instances--; @@ -233,12 +228,7 @@ Being::setMap(Map *map) void Being::controlParticle(Particle *particle) { - if (particle) - { - // The effect may not die without the beings permission or we segfault - particle->disableAutoDelete(); - mChildParticleEffects.push_back(particle); - } + mChildParticleEffects.addLocally(particle); } void @@ -413,21 +403,7 @@ Being::logic() } //Update particle effects - for ( std::list::iterator i = mChildParticleEffects.begin(); - i != mChildParticleEffects.end(); - - ) - { - (*i)->setPosition((float)mPx + 16.0f, (float)mPy + 32.0f); - if ((*i)->isExtinct()) - { - (*i)->kill(); - i = mChildParticleEffects.erase(i); - } - else { - i++; - } - } + mChildParticleEffects.setPositions((float)mPx + 16.0f, (float)mPy + 32.0f); } void diff --git a/src/being.h b/src/being.h index 0dbc41db..568d51c7 100644 --- a/src/being.h +++ b/src/being.h @@ -26,13 +26,15 @@ #include #include #include -#include +#include #include "sprite.h" #include "map.h" #include "animatedsprite.h" +#include "particlecontainer.h" #define FIRST_IGNORE_EMOTE 14 +#define STATUS_EFFECTS 32 class AnimatedSprite; class Equipment; @@ -405,6 +407,8 @@ class Being : public Sprite std::string mName; /**< Name of character */ SpriteIterator mSpriteIterator; + typedef std::bitset StatusEffects; + /** Engine-related infos about weapon. */ const ItemInfo* mEquippedWeapon; @@ -414,11 +418,15 @@ class Being : public Sprite Uint8 mGender; Uint32 mSpeechTime; Sint32 mPx, mPy; /**< Pixel coordinates */ + Uint16 mStunMode; /**< Stun mode; zero if not stunned */ + StatusEffects mStatusEffects; /**< Bitset of active status effects */ std::vector mSprites; std::vector mSpriteIDs; std::vector mSpriteColors; - std::list mChildParticleEffects; + ParticleContainer mStunParticleEffects; + ParticleVector mStatusParticleEffects; + ParticleContainer mChildParticleEffects; private: /** diff --git a/src/particlecontainer.cpp b/src/particlecontainer.cpp new file mode 100644 index 00000000..4df45b26 --- /dev/null +++ b/src/particlecontainer.cpp @@ -0,0 +1,158 @@ +/* + * The Mana World + * Copyright 2008 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * The Mana World is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include + +#include "particlecontainer.h" + + +ParticleContainer::ParticleContainer(ParticleContainer *parent, bool delParent) : + mDelParent(delParent), + mNext(parent) +{}; + +ParticleContainer::~ParticleContainer() +{ + clearLocally(); + if (mNext && mDelParent) + delete mNext; +} + +void +ParticleContainer::addLocally(Particle *particle) +{ + if (particle) + { + // The effect may not die without the beings permission or we segfault + particle->disableAutoDelete(); + mElements.push_back(particle); + } +} + +void +ParticleContainer::removeLocally(Particle *particle) +{ + for (std::list::iterator it = mElements.begin(); + it != mElements.end(); it++) + if (*it == particle) { + (*it)->kill(); + mElements.erase(it); + } +} + +void +ParticleContainer::clear() +{ + clearLocally(); + if (mNext) + mNext->clear(); +} + +void +ParticleContainer::clearLocally() +{ + for (std::list::iterator it = mElements.begin(); + it != mElements.end(); it++) + (*it)->kill(); + + mElements.clear(); +} + +void +ParticleContainer::setPositions(float x, float y) +{ + for (std::list::iterator it = mElements.begin(); + it != mElements.end();) + { + (*it)->setPosition(x, y); + if ((*it)->isExtinct()) + { + (*it)->kill(); + it = mElements.erase(it); + } + else + it++; + } +} + + + + +ParticleVector::ParticleVector(ParticleContainer *next, bool delParent) +{ + ParticleContainer::ParticleContainer(next, delParent); +} + +void +ParticleVector::setLocally(int index, Particle *particle) +{ + assert(index >= 0); + + delLocally(index); + + if (mIndexedElements.size() <= (unsigned) index) + mIndexedElements.resize(index + 1, NULL); + + mIndexedElements[index] = particle; +} + +void +ParticleVector::delLocally(int index) +{ + assert(index >= 0); + + if (mIndexedElements.size() <= (unsigned) index) + return; + + Particle *p = mIndexedElements[index]; + if (p) + { + mIndexedElements[index] = NULL; + p->kill(); + } +} + +void +ParticleVector::clearLocally() +{ + for (unsigned int i = 0; i < mIndexedElements.size(); i++) + delLocally(i); +} + +void +ParticleVector::setPositions(float x, float y) +{ + ParticleContainer::setPositions(x, y); + + for (std::vector::iterator it = mIndexedElements.begin(); + it != mIndexedElements.end(); it++) + if (*it) + { + (*it)->setPosition(x, y); + + if ((*it)->isExtinct()) + { + (*it)->kill(); + *it = NULL; + } + } +} + diff --git a/src/particlecontainer.h b/src/particlecontainer.h new file mode 100644 index 00000000..a6a1b1c8 --- /dev/null +++ b/src/particlecontainer.h @@ -0,0 +1,106 @@ +/* + * The Mana World + * Copyright 2008 The Mana World Development Team + * + * This file is part of The Mana World. + * + * The Mana World is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * The Mana World is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with The Mana World; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _PARTICLE_CONTAINER_H +#define _PARTICLE_CONTAINER_H + +#include +#include + +#include "particle.h" + + +/** + * Set of particle effects. May be stacked with other ParticleContainers. All + * operations herein affect such stacked containers, unless the operations end + * in `Locally'. + */ +class ParticleContainer +{ +public: + /** + * Constructs a new particle container and assumes responsibility for + * its parent (for all operations defined herein, except when ending in `Locally') + * + * delParent means that the destructor should also free the parent. + */ + ParticleContainer(ParticleContainer *parent = NULL, bool delParent = true); + ~ParticleContainer(); + + /** + * Takes control of and adds a particle + */ + void addLocally(Particle *); + + /** + * `kills' and removes a particle + */ + void removeLocally(Particle *); + + /** + * Kills and removes all particle effects + */ + void clear(); + + /** + * Kills and removes all particle effects (only in this container) + */ + virtual void clearLocally(); + + /** + * Sets the positions of all elements + */ + virtual void setPositions(float x, float y); + +protected: + bool mDelParent; /**< Delete mNext in destructor */ + std::list mElements; /**< Contained particle effects */ + ParticleContainer *mNext; /**< Contained container, if any */ +}; + + +/** + * Particle container with indexing facilities + */ +class ParticleVector : public ParticleContainer +{ +public: + ParticleVector(ParticleContainer *parent = NULL, bool delParent = true); + + /** + * Sets a particle at a specified index. Kills the previous particle + * there, if needed. + */ + virtual void setLocally(int index, Particle *particle); + + /** + * Removes a particle at a specified index + */ + virtual void delLocally(int index); + + virtual void clearLocally(); + virtual void setPositions(float x, float y); + +protected: + std::vector mIndexedElements; +}; + +#endif -- cgit v1.2.3-70-g09d2