aboutsummaryrefslogtreecommitdiff
path: root/engines/wintermute/base/particles/part_emitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/wintermute/base/particles/part_emitter.cpp')
-rw-r--r--engines/wintermute/base/particles/part_emitter.cpp2512
1 files changed, 1256 insertions, 1256 deletions
diff --git a/engines/wintermute/base/particles/part_emitter.cpp b/engines/wintermute/base/particles/part_emitter.cpp
index 7012bef86f..3655b89131 100644
--- a/engines/wintermute/base/particles/part_emitter.cpp
+++ b/engines/wintermute/base/particles/part_emitter.cpp
@@ -1,1256 +1,1256 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program 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 (at your option) any later version.
-
- * This program 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 this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-/*
- * This file is based on WME Lite.
- * http://dead-code.org/redir.php?target=wmelite
- * Copyright (c) 2011 Jan Nedoma
- */
-
-#include "engines/wintermute/base/particles/part_emitter.h"
-#include "engines/wintermute/base/particles/part_particle.h"
-#include "engines/wintermute/math/vector2.h"
-#include "engines/wintermute/math/matrix4.h"
-#include "engines/wintermute/base/scriptables/script_value.h"
-#include "engines/wintermute/base/scriptables/script_stack.h"
-#include "engines/wintermute/base/base_game.h"
-#include "engines/wintermute/base/base_region.h"
-#include "engines/wintermute/base/base_file_manager.h"
-#include "engines/wintermute/utils/utils.h"
-#include "engines/wintermute/platform_osystem.h"
-#include "common/str.h"
-#include "common/math.h"
-
-namespace Wintermute {
-
-IMPLEMENT_PERSISTENT(PartEmitter, false)
-
-//////////////////////////////////////////////////////////////////////////
-PartEmitter::PartEmitter(BaseGame *inGame, BaseScriptHolder *owner) : BaseObject(inGame) {
- _width = _height = 0;
-
- BasePlatform::setRectEmpty(&_border);
- _borderThicknessLeft = _borderThicknessRight = _borderThicknessTop = _borderThicknessBottom = 0;
-
- _angle1 = _angle2 = 0;
-
- _velocity1 = _velocity2 = 0.0f;
- _velocityZBased = false;
-
- _scale1 = _scale2 = 100.0f;
- _scaleZBased = false;
-
- _maxParticles = 100;
-
- _lifeTime1 = _lifeTime2 = 1000;
- _lifeTimeZBased = false;
-
- _lastGenTime = 0;
- _genInterval = 0;
- _genAmount = 1;
-
- _overheadTime = 0;
- _running = false;
-
- _maxBatches = 0;
- _batchesGenerated = 0;
-
- _fadeInTime = _fadeOutTime = 0;
-
- _alpha1 = _alpha2 = 255;
- _alphaTimeBased = false;
-
- _rotation1 = _rotation2 = 0.0f;
- _angVelocity1 = _angVelocity2 = 0.0f;
-
- _growthRate1 = _growthRate2 = 0.0f;
- _exponentialGrowth = false;
-
- _useRegion = false;
-
- _emitEvent = NULL;
- _owner = owner;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-PartEmitter::~PartEmitter(void) {
- for (uint32 i = 0; i < _particles.size(); i++) {
- delete _particles[i];
- }
- _particles.clear();
-
- for (uint32 i = 0; i < _forces.size(); i++) {
- delete _forces[i];
- }
- _forces.clear();
-
-
- for (uint32 i = 0; i < _sprites.size(); i++) {
- delete[] _sprites[i];
- }
- _sprites.clear();
-
- delete[] _emitEvent;
- _emitEvent = NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool PartEmitter::addSprite(const char *filename) {
- if (!filename) {
- return STATUS_FAILED;
- }
-
- // do we already have the file?
- for (uint32 i = 0; i < _sprites.size(); i++) {
- if (scumm_stricmp(filename, _sprites[i]) == 0) {
- return STATUS_OK;
- }
- }
-
- // check if file exists
- Common::SeekableReadStream *File = BaseFileManager::getEngineInstance()->openFile(filename);
- if (!File) {
- _gameRef->LOG(0, "Sprite '%s' not found", filename);
- return STATUS_FAILED;
- } else {
- BaseFileManager::getEngineInstance()->closeFile(File);
- }
-
- char *str = new char[strlen(filename) + 1];
- strcpy(str, filename);
- _sprites.add(str);
-
- return STATUS_OK;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool PartEmitter::removeSprite(const char *filename) {
- for (uint32 i = 0; i < _sprites.size(); i++) {
- if (scumm_stricmp(filename, _sprites[i]) == 0) {
- delete[] _sprites[i];
- _sprites.remove_at(i);
- return STATUS_OK;
- }
- }
- return STATUS_FAILED;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool PartEmitter::initParticle(PartParticle *particle, uint32 currentTime, uint32 timerDelta) {
- if (!particle) {
- return STATUS_FAILED;
- }
- if (_sprites.size() == 0) {
- return STATUS_FAILED;
- }
-
- int posX = BaseUtils::randomInt(_posX, _posX + _width);
- int posY = BaseUtils::randomInt(_posY, _posY + _height);
- float posZ = BaseUtils::randomFloat(0.0f, 100.0f);
-
- float velocity;
- if (_velocityZBased) {
- velocity = _velocity1 + posZ * (_velocity2 - _velocity1) / 100;
- } else {
- velocity = BaseUtils::randomFloat(_velocity1, _velocity2);
- }
-
- float scale;
- if (_scaleZBased) {
- scale = _scale1 + posZ * (_scale2 - _scale1) / 100;
- } else {
- scale = BaseUtils::randomFloat(_scale1, _scale2);
- }
-
- int lifeTime;
- if (_lifeTimeZBased) {
- lifeTime = (int)(_lifeTime2 - posZ * (_lifeTime2 - _lifeTime1) / 100);
- } else {
- lifeTime = BaseUtils::randomInt(_lifeTime1, _lifeTime2);
- }
-
- float angle = BaseUtils::randomAngle(_angle1, _angle2);
- int spriteIndex = BaseUtils::randomInt(0, _sprites.size() - 1);
-
- float rotation = BaseUtils::randomAngle(_rotation1, _rotation2);
- float angVelocity = BaseUtils::randomFloat(_angVelocity1, _angVelocity2);
- float growthRate = BaseUtils::randomFloat(_growthRate1, _growthRate2);
-
- if (!BasePlatform::isRectEmpty(&_border)) {
- int thicknessLeft = (int)(_borderThicknessLeft - (float)_borderThicknessLeft * posZ / 100.0f);
- int thicknessRight = (int)(_borderThicknessRight - (float)_borderThicknessRight * posZ / 100.0f);
- int thicknessTop = (int)(_borderThicknessTop - (float)_borderThicknessTop * posZ / 100.0f);
- int thicknessBottom = (int)(_borderThicknessBottom - (float)_borderThicknessBottom * posZ / 100.0f);
-
- particle->_border = _border;
- particle->_border.left += thicknessLeft;
- particle->_border.right -= thicknessRight;
- particle->_border.top += thicknessTop;
- particle->_border.bottom -= thicknessBottom;
- }
-
- Vector2 vecPos((float)posX, (float)posY);
- Vector2 vecVel(0, velocity);
-
- Matrix4 matRot;
- matRot.rotationZ(Common::deg2rad(BaseUtils::normalizeAngle(angle - 180)));
- matRot.transformVector2(vecVel);
-
- if (_alphaTimeBased) {
- particle->_alpha1 = _alpha1;
- particle->_alpha2 = _alpha2;
- } else {
- int alpha = BaseUtils::randomInt(_alpha1, _alpha2);
- particle->_alpha1 = alpha;
- particle->_alpha2 = alpha;
- }
-
- particle->_creationTime = currentTime;
- particle->_pos = vecPos;
- particle->_posZ = posZ;
- particle->_velocity = vecVel;
- particle->_scale = scale;
- particle->_lifeTime = lifeTime;
- particle->_rotation = rotation;
- particle->_angVelocity = angVelocity;
- particle->_growthRate = growthRate;
- particle->_exponentialGrowth = _exponentialGrowth;
- particle->_isDead = DID_FAIL(particle->setSprite(_sprites[spriteIndex]));
- particle->fadeIn(currentTime, _fadeInTime);
-
-
- if (particle->_isDead) {
- return STATUS_FAILED;
- } else {
- return STATUS_OK;
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool PartEmitter::update() {
- if (!_running) {
- return STATUS_OK;
- } else {
- return updateInternal(_gameRef->_timer, _gameRef->_timerDelta);
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool PartEmitter::updateInternal(uint32 currentTime, uint32 timerDelta) {
- int numLive = 0;
-
- for (uint32 i = 0; i < _particles.size(); i++) {
- _particles[i]->update(this, currentTime, timerDelta);
-
- if (!_particles[i]->_isDead) {
- numLive++;
- }
- }
-
-
- // we're understaffed
- if (numLive < _maxParticles) {
- bool needsSort = false;
- if ((int)(currentTime - _lastGenTime) > _genInterval) {
- _lastGenTime = currentTime;
- _batchesGenerated++;
-
- if (_maxBatches > 0 && _batchesGenerated > _maxBatches) {
- return STATUS_OK;
- }
-
- int toGen = MIN(_genAmount, _maxParticles - numLive);
- while (toGen > 0) {
- int firstDeadIndex = -1;
- for (uint32 i = 0; i < _particles.size(); i++) {
- if (_particles[i]->_isDead) {
- firstDeadIndex = i;
- break;
- }
- }
-
- PartParticle *particle;
- if (firstDeadIndex >= 0) {
- particle = _particles[firstDeadIndex];
- } else {
- particle = new PartParticle(_gameRef);
- _particles.add(particle);
- }
- initParticle(particle, currentTime, timerDelta);
- needsSort = true;
-
- toGen--;
- }
- }
- if (needsSort && (_scaleZBased || _velocityZBased || _lifeTimeZBased)) {
- sortParticlesByZ();
- }
-
- // we actually generated some particles and we're not in fast-forward mode
- if (needsSort && _overheadTime == 0) {
- if (_owner && _emitEvent) {
- _owner->applyEvent(_emitEvent);
- }
- }
- }
-
- return STATUS_OK;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool PartEmitter::display(BaseRegion *region) {
- if (_sprites.size() <= 1) {
- _gameRef->_renderer->startSpriteBatch();
- }
-
- for (uint32 i = 0; i < _particles.size(); i++) {
- if (region != NULL && _useRegion) {
- if (!region->pointInRegion((int)_particles[i]->_pos.x, (int)_particles[i]->_pos.y)) {
- continue;
- }
- }
-
- _particles[i]->display(this);
- }
-
- if (_sprites.size() <= 1) {
- _gameRef->_renderer->endSpriteBatch();
- }
-
- return STATUS_OK;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool PartEmitter::start() {
- for (uint32 i = 0; i < _particles.size(); i++) {
- _particles[i]->_isDead = true;
- }
- _running = true;
- _batchesGenerated = 0;
-
-
- if (_overheadTime > 0) {
- uint32 delta = 500;
- int steps = _overheadTime / delta;
- uint32 currentTime = _gameRef->_timer - _overheadTime;
-
- for (int i = 0; i < steps; i++) {
- updateInternal(currentTime, delta);
- currentTime += delta;
- }
- _overheadTime = 0;
- }
-
- return STATUS_OK;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool PartEmitter::sortParticlesByZ() {
- // sort particles by _posY
- Common::sort(_particles.begin(), _particles.end(), PartEmitter::compareZ);
- return STATUS_OK;
-}
-
-//////////////////////////////////////////////////////////////////////////
-int PartEmitter::compareZ(const void *obj1, const void *obj2) {
- const PartParticle *p1 = *(const PartParticle *const *)obj1;
- const PartParticle *p2 = *(const PartParticle *const *)obj2;
-
- if (p1->_posZ < p2->_posZ) {
- return -1;
- } else if (p1->_posZ > p2->_posZ) {
- return 1;
- } else {
- return 0;
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool PartEmitter::setBorder(int x, int y, int width, int height) {
- BasePlatform::setRect(&_border, x, y, x + width, y + height);
-
- return STATUS_OK;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool PartEmitter::setBorderThickness(int thicknessLeft, int thicknessRight, int thicknessTop, int thicknessBottom) {
- _borderThicknessLeft = thicknessLeft;
- _borderThicknessRight = thicknessRight;
- _borderThicknessTop = thicknessTop;
- _borderThicknessBottom = thicknessBottom;
-
- return STATUS_OK;
-}
-
-//////////////////////////////////////////////////////////////////////////
-PartForce *PartEmitter::addForceByName(const Common::String &name) {
- PartForce *force = NULL;
-
- for (uint32 i = 0; i < _forces.size(); i++) {
- if (scumm_stricmp(name.c_str(), _forces[i]->getName()) == 0) {
- force = _forces[i];
- break;
- }
- }
- if (!force) {
- force = new PartForce(_gameRef);
- if (force) {
- force->setName(name.c_str());
- _forces.add(force);
- }
- }
- return force;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool PartEmitter::addForce(const Common::String &name, PartForce::TForceType type, int posX, int posY, float angle, float strength) {
- PartForce *force = addForceByName(name);
- if (!force) {
- return STATUS_FAILED;
- }
-
- force->_type = type;
- force->_pos = Vector2(posX, posY);
-
- force->_direction = Vector2(0, strength);
- Matrix4 matRot;
- matRot.rotationZ(Common::deg2rad(BaseUtils::normalizeAngle(angle - 180)));
- matRot.transformVector2(force->_direction);
-
- return STATUS_OK;
-}
-
-//////////////////////////////////////////////////////////////////////////
-bool PartEmitter::removeForce(const Common::String &name) {
- for (uint32 i = 0; i < _forces.size(); i++) {
- if (scumm_stricmp(name.c_str(), _forces[i]->getName()) == 0) {
- delete _forces[i];
- _forces.remove_at(i);
- return STATUS_OK;
- }
- }
- return STATUS_FAILED;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-// high level scripting interface
-//////////////////////////////////////////////////////////////////////////
-bool PartEmitter::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
- //////////////////////////////////////////////////////////////////////////
- // SetBorder
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "SetBorder") == 0) {
- stack->correctParams(4);
- int borderX = stack->pop()->getInt();
- int borderY = stack->pop()->getInt();
- int borderWidth = stack->pop()->getInt();
- int borderHeight = stack->pop()->getInt();
-
- stack->pushBool(DID_SUCCEED(setBorder(borderX, borderY, borderWidth, borderHeight)));
-
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // SetBorderThickness
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "SetBorderThickness") == 0) {
- stack->correctParams(4);
- int left = stack->pop()->getInt();
- int right = stack->pop()->getInt();
- int top = stack->pop()->getInt();
- int bottom = stack->pop()->getInt();
-
- stack->pushBool(DID_SUCCEED(setBorderThickness(left, right, top, bottom)));
-
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // AddSprite
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AddSprite") == 0) {
- stack->correctParams(1);
- const char *spriteFile = stack->pop()->getString();
- stack->pushBool(DID_SUCCEED(addSprite(spriteFile)));
-
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // RemoveSprite
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "RemoveSprite") == 0) {
- stack->correctParams(1);
- const char *spriteFile = stack->pop()->getString();
- stack->pushBool(DID_SUCCEED(removeSprite(spriteFile)));
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Start
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Start") == 0) {
- stack->correctParams(1);
- _overheadTime = stack->pop()->getInt();
- stack->pushBool(DID_SUCCEED(start()));
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Stop
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Stop") == 0) {
- stack->correctParams(0);
-
- for (uint32 i = 0; i < _particles.size(); i++) {
- delete _particles[i];
- }
- _particles.clear();
-
- _running = false;
- stack->pushBool(true);
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Pause
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Pause") == 0) {
- stack->correctParams(0);
- _running = false;
- stack->pushBool(true);
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Resume
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Resume") == 0) {
- stack->correctParams(0);
- _running = true;
- stack->pushBool(true);
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // AddGlobalForce
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AddGlobalForce") == 0) {
- stack->correctParams(3);
- const char *forceName = stack->pop()->getString();
- float angle = stack->pop()->getFloat();
- float strength = stack->pop()->getFloat();
-
- stack->pushBool(DID_SUCCEED(addForce(forceName, PartForce::FORCE_GLOBAL, 0, 0, angle, strength)));
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // AddPointForce
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AddPointForce") == 0) {
- stack->correctParams(5);
- const char *forceName = stack->pop()->getString();
- int posX = stack->pop()->getInt();
- int posY = stack->pop()->getInt();
- float angle = stack->pop()->getFloat();
- float strength = stack->pop()->getFloat();
-
- stack->pushBool(DID_SUCCEED(addForce(forceName, PartForce::FORCE_GLOBAL, posX, posY, angle, strength)));
-
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // RemoveForce
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "RemoveForce") == 0) {
- stack->correctParams(1);
- const char *forceName = stack->pop()->getString();
-
- stack->pushBool(DID_SUCCEED(removeForce(forceName)));
-
- return STATUS_OK;
- } else {
- return BaseObject::scCallMethod(script, stack, thisStack, name);
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-ScValue *PartEmitter::scGetProperty(const char *name) {
- _scValue->setNULL();
-
- //////////////////////////////////////////////////////////////////////////
- // Type
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "Type") == 0) {
- _scValue->setString("particle-emitter");
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // X
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "X") == 0) {
- _scValue->setInt(_posX);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // Y
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Y") == 0) {
- _scValue->setInt(_posY);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // Width
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Width") == 0) {
- _scValue->setInt(_width);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // Height
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Height") == 0) {
- _scValue->setInt(_height);
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Scale1
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Scale1") == 0) {
- _scValue->setFloat(_scale1);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // Scale2
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Scale2") == 0) {
- _scValue->setFloat(_scale2);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // ScaleZBased
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ScaleZBased") == 0) {
- _scValue->setBool(_scaleZBased);
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Velocity1
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Velocity1") == 0) {
- _scValue->setFloat(_velocity1);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // Velocity2
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Velocity2") == 0) {
- _scValue->setFloat(_velocity2);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // VelocityZBased
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "VelocityZBased") == 0) {
- _scValue->setBool(_velocityZBased);
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // LifeTime1
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "LifeTime1") == 0) {
- _scValue->setInt(_lifeTime1);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // LifeTime2
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "LifeTime2") == 0) {
- _scValue->setInt(_lifeTime2);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // LifeTimeZBased
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "LifeTimeZBased") == 0) {
- _scValue->setBool(_lifeTimeZBased);
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Angle1
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Angle1") == 0) {
- _scValue->setInt(_angle1);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // Angle2
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Angle2") == 0) {
- _scValue->setInt(_angle2);
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // AngVelocity1
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AngVelocity1") == 0) {
- _scValue->setFloat(_angVelocity1);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // AngVelocity2
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AngVelocity2") == 0) {
- _scValue->setFloat(_angVelocity2);
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Rotation1
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Rotation1") == 0) {
- _scValue->setFloat(_rotation1);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // Rotation2
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Rotation2") == 0) {
- _scValue->setFloat(_rotation2);
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Alpha1
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Alpha1") == 0) {
- _scValue->setInt(_alpha1);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // Alpha2
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Alpha2") == 0) {
- _scValue->setInt(_alpha2);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // AlphaTimeBased
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AlphaTimeBased") == 0) {
- _scValue->setBool(_alphaTimeBased);
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // MaxParticles
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MaxParticles") == 0) {
- _scValue->setInt(_maxParticles);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // NumLiveParticles (RO)
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "NumLiveParticles") == 0) {
- int numAlive = 0;
- for (uint32 i = 0; i < _particles.size(); i++) {
- if (_particles[i] && !_particles[i]->_isDead) {
- numAlive++;
- }
- }
- _scValue->setInt(numAlive);
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // GenerationInterval
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GenerationInterval") == 0) {
- _scValue->setInt(_genInterval);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // GenerationAmount
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GenerationAmount") == 0) {
- _scValue->setInt(_genAmount);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // MaxBatches
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MaxBatches") == 0) {
- _scValue->setInt(_maxBatches);
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // FadeInTime
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "FadeInTime") == 0) {
- _scValue->setInt(_fadeInTime);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // FadeOutTime
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "FadeOutTime") == 0) {
- _scValue->setInt(_fadeOutTime);
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // GrowthRate1
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GrowthRate1") == 0) {
- _scValue->setFloat(_growthRate1);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // GrowthRate2
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GrowthRate2") == 0) {
- _scValue->setFloat(_growthRate2);
- return _scValue;
- }
- //////////////////////////////////////////////////////////////////////////
- // ExponentialGrowth
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ExponentialGrowth") == 0) {
- _scValue->setBool(_exponentialGrowth);
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // UseRegion
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "UseRegion") == 0) {
- _scValue->setBool(_useRegion);
- return _scValue;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // EmitEvent
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "EmitEvent") == 0) {
- if (!_emitEvent) {
- _scValue->setNULL();
- } else {
- _scValue->setString(_emitEvent);
- }
- return _scValue;
- } else {
- return BaseObject::scGetProperty(name);
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-bool PartEmitter::scSetProperty(const char *name, ScValue *value) {
- //////////////////////////////////////////////////////////////////////////
- // X
- //////////////////////////////////////////////////////////////////////////
- if (strcmp(name, "X") == 0) {
- _posX = value->getInt();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // Y
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Y") == 0) {
- _posY = value->getInt();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // Width
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Width") == 0) {
- _width = value->getInt();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // Height
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Height") == 0) {
- _height = value->getInt();
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Scale1
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Scale1") == 0) {
- _scale1 = value->getFloat();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // Scale2
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Scale2") == 0) {
- _scale2 = value->getFloat();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // ScaleZBased
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ScaleZBased") == 0) {
- _scaleZBased = value->getBool();
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Velocity1
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Velocity1") == 0) {
- _velocity1 = value->getFloat();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // Velocity2
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Velocity2") == 0) {
- _velocity2 = value->getFloat();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // VelocityZBased
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "VelocityZBased") == 0) {
- _velocityZBased = value->getBool();
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // LifeTime1
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "LifeTime1") == 0) {
- _lifeTime1 = value->getInt();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // LifeTime2
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "LifeTime2") == 0) {
- _lifeTime2 = value->getInt();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // LifeTimeZBased
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "LifeTimeZBased") == 0) {
- _lifeTimeZBased = value->getBool();
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Angle1
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Angle1") == 0) {
- _angle1 = value->getInt();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // Angle2
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Angle2") == 0) {
- _angle2 = value->getInt();
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // AngVelocity1
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AngVelocity1") == 0) {
- _angVelocity1 = value->getFloat();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // AngVelocity2
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AngVelocity2") == 0) {
- _angVelocity2 = value->getFloat();
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Rotation1
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Rotation1") == 0) {
- _rotation1 = value->getFloat();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // Rotation2
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Rotation2") == 0) {
- _rotation2 = value->getFloat();
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // Alpha1
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Alpha1") == 0) {
- _alpha1 = value->getInt();
- if (_alpha1 < 0) {
- _alpha1 = 0;
- }
- if (_alpha1 > 255) {
- _alpha1 = 255;
- }
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // Alpha2
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "Alpha2") == 0) {
- _alpha2 = value->getInt();
- if (_alpha2 < 0) {
- _alpha2 = 0;
- }
- if (_alpha2 > 255) {
- _alpha2 = 255;
- }
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // AlphaTimeBased
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "AlphaTimeBased") == 0) {
- _alphaTimeBased = value->getBool();
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // MaxParticles
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MaxParticles") == 0) {
- _maxParticles = value->getInt();
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // GenerationInterval
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GenerationInterval") == 0) {
- _genInterval = value->getInt();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // GenerationAmount
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GenerationAmount") == 0) {
- _genAmount = value->getInt();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // MaxBatches
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "MaxBatches") == 0) {
- _maxBatches = value->getInt();
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // FadeInTime
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "FadeInTime") == 0) {
- _fadeInTime = value->getInt();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // FadeOutTime
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "FadeOutTime") == 0) {
- _fadeOutTime = value->getInt();
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // GrowthRate1
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GrowthRate1") == 0) {
- _growthRate1 = value->getFloat();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // GrowthRate2
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "GrowthRate2") == 0) {
- _growthRate2 = value->getFloat();
- return STATUS_OK;
- }
- //////////////////////////////////////////////////////////////////////////
- // ExponentialGrowth
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "ExponentialGrowth") == 0) {
- _exponentialGrowth = value->getBool();
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // UseRegion
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "UseRegion") == 0) {
- _useRegion = value->getBool();
- return STATUS_OK;
- }
-
- //////////////////////////////////////////////////////////////////////////
- // EmitEvent
- //////////////////////////////////////////////////////////////////////////
- else if (strcmp(name, "EmitEvent") == 0) {
- delete[] _emitEvent;
- _emitEvent = NULL;
- if (!value->isNULL()) {
- BaseUtils::setString(&_emitEvent, value->getString());
- }
- return STATUS_OK;
- } else {
- return BaseObject::scSetProperty(name, value);
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-const char *PartEmitter::scToString() {
- return "[particle emitter]";
-}
-
-
-
-
-//////////////////////////////////////////////////////////////////////////
-bool PartEmitter::persist(BasePersistenceManager *persistMgr) {
- BaseObject::persist(persistMgr);
-
- persistMgr->transfer(TMEMBER(_width));
- persistMgr->transfer(TMEMBER(_height));
-
- persistMgr->transfer(TMEMBER(_angle1));
- persistMgr->transfer(TMEMBER(_angle2));
-
- persistMgr->transfer(TMEMBER(_velocity1));
- persistMgr->transfer(TMEMBER(_velocity2));
- persistMgr->transfer(TMEMBER(_velocityZBased));
-
- persistMgr->transfer(TMEMBER(_scale1));
- persistMgr->transfer(TMEMBER(_scale2));
- persistMgr->transfer(TMEMBER(_scaleZBased));
-
- persistMgr->transfer(TMEMBER(_maxParticles));
-
- persistMgr->transfer(TMEMBER(_lifeTime1));
- persistMgr->transfer(TMEMBER(_lifeTime2));
- persistMgr->transfer(TMEMBER(_lifeTimeZBased));
-
- persistMgr->transfer(TMEMBER(_genInterval));
- persistMgr->transfer(TMEMBER(_genAmount));
-
- persistMgr->transfer(TMEMBER(_running));
- persistMgr->transfer(TMEMBER(_overheadTime));
-
- persistMgr->transfer(TMEMBER(_border));
- persistMgr->transfer(TMEMBER(_borderThicknessLeft));
- persistMgr->transfer(TMEMBER(_borderThicknessRight));
- persistMgr->transfer(TMEMBER(_borderThicknessTop));
- persistMgr->transfer(TMEMBER(_borderThicknessBottom));
-
- persistMgr->transfer(TMEMBER(_fadeInTime));
- persistMgr->transfer(TMEMBER(_fadeOutTime));
-
- persistMgr->transfer(TMEMBER(_alpha1));
- persistMgr->transfer(TMEMBER(_alpha2));
- persistMgr->transfer(TMEMBER(_alphaTimeBased));
-
- persistMgr->transfer(TMEMBER(_angVelocity1));
- persistMgr->transfer(TMEMBER(_angVelocity2));
-
- persistMgr->transfer(TMEMBER(_rotation1));
- persistMgr->transfer(TMEMBER(_rotation2));
-
- persistMgr->transfer(TMEMBER(_growthRate1));
- persistMgr->transfer(TMEMBER(_growthRate2));
- persistMgr->transfer(TMEMBER(_exponentialGrowth));
-
- persistMgr->transfer(TMEMBER(_useRegion));
-
- persistMgr->transfer(TMEMBER_INT(_maxBatches));
- persistMgr->transfer(TMEMBER_INT(_batchesGenerated));
-
- persistMgr->transfer(TMEMBER(_emitEvent));
- persistMgr->transfer(TMEMBER(_owner));
-
-
- _sprites.persist(persistMgr);
-
- uint32 numForces;
- if (persistMgr->getIsSaving()) {
- numForces = _forces.size();
- persistMgr->transfer(TMEMBER(numForces));
- for (uint32 i = 0; i < _forces.size(); i++) {
- _forces[i]->persist(persistMgr);
- }
- } else {
- persistMgr->transfer(TMEMBER(numForces));
- for (uint32 i = 0; i < numForces; i++) {
- PartForce *force = new PartForce(_gameRef);
- force->persist(persistMgr);
- _forces.add(force);
- }
- }
-
- uint32 numParticles;
- if (persistMgr->getIsSaving()) {
- numParticles = _particles.size();
- persistMgr->transfer(TMEMBER(numParticles));
- for (uint32 i = 0; i < _particles.size(); i++) {
- _particles[i]->persist(persistMgr);
- }
- } else {
- persistMgr->transfer(TMEMBER(numParticles));
- for (uint32 i = 0; i < numParticles; i++) {
- PartParticle *particle = new PartParticle(_gameRef);
- particle->persist(persistMgr);
- _particles.add(particle);
- }
- }
-
- return STATUS_OK;
-}
-
-} // end of namespace Wintermute
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program 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 (at your option) any later version.
+
+ * This program 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/particles/part_emitter.h"
+#include "engines/wintermute/base/particles/part_particle.h"
+#include "engines/wintermute/math/vector2.h"
+#include "engines/wintermute/math/matrix4.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_region.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/utils/utils.h"
+#include "engines/wintermute/platform_osystem.h"
+#include "common/str.h"
+#include "common/math.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(PartEmitter, false)
+
+//////////////////////////////////////////////////////////////////////////
+PartEmitter::PartEmitter(BaseGame *inGame, BaseScriptHolder *owner) : BaseObject(inGame) {
+ _width = _height = 0;
+
+ BasePlatform::setRectEmpty(&_border);
+ _borderThicknessLeft = _borderThicknessRight = _borderThicknessTop = _borderThicknessBottom = 0;
+
+ _angle1 = _angle2 = 0;
+
+ _velocity1 = _velocity2 = 0.0f;
+ _velocityZBased = false;
+
+ _scale1 = _scale2 = 100.0f;
+ _scaleZBased = false;
+
+ _maxParticles = 100;
+
+ _lifeTime1 = _lifeTime2 = 1000;
+ _lifeTimeZBased = false;
+
+ _lastGenTime = 0;
+ _genInterval = 0;
+ _genAmount = 1;
+
+ _overheadTime = 0;
+ _running = false;
+
+ _maxBatches = 0;
+ _batchesGenerated = 0;
+
+ _fadeInTime = _fadeOutTime = 0;
+
+ _alpha1 = _alpha2 = 255;
+ _alphaTimeBased = false;
+
+ _rotation1 = _rotation2 = 0.0f;
+ _angVelocity1 = _angVelocity2 = 0.0f;
+
+ _growthRate1 = _growthRate2 = 0.0f;
+ _exponentialGrowth = false;
+
+ _useRegion = false;
+
+ _emitEvent = NULL;
+ _owner = owner;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+PartEmitter::~PartEmitter(void) {
+ for (uint32 i = 0; i < _particles.size(); i++) {
+ delete _particles[i];
+ }
+ _particles.clear();
+
+ for (uint32 i = 0; i < _forces.size(); i++) {
+ delete _forces[i];
+ }
+ _forces.clear();
+
+
+ for (uint32 i = 0; i < _sprites.size(); i++) {
+ delete[] _sprites[i];
+ }
+ _sprites.clear();
+
+ delete[] _emitEvent;
+ _emitEvent = NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::addSprite(const char *filename) {
+ if (!filename) {
+ return STATUS_FAILED;
+ }
+
+ // do we already have the file?
+ for (uint32 i = 0; i < _sprites.size(); i++) {
+ if (scumm_stricmp(filename, _sprites[i]) == 0) {
+ return STATUS_OK;
+ }
+ }
+
+ // check if file exists
+ Common::SeekableReadStream *File = BaseFileManager::getEngineInstance()->openFile(filename);
+ if (!File) {
+ _gameRef->LOG(0, "Sprite '%s' not found", filename);
+ return STATUS_FAILED;
+ } else {
+ BaseFileManager::getEngineInstance()->closeFile(File);
+ }
+
+ char *str = new char[strlen(filename) + 1];
+ strcpy(str, filename);
+ _sprites.add(str);
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::removeSprite(const char *filename) {
+ for (uint32 i = 0; i < _sprites.size(); i++) {
+ if (scumm_stricmp(filename, _sprites[i]) == 0) {
+ delete[] _sprites[i];
+ _sprites.remove_at(i);
+ return STATUS_OK;
+ }
+ }
+ return STATUS_FAILED;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::initParticle(PartParticle *particle, uint32 currentTime, uint32 timerDelta) {
+ if (!particle) {
+ return STATUS_FAILED;
+ }
+ if (_sprites.size() == 0) {
+ return STATUS_FAILED;
+ }
+
+ int posX = BaseUtils::randomInt(_posX, _posX + _width);
+ int posY = BaseUtils::randomInt(_posY, _posY + _height);
+ float posZ = BaseUtils::randomFloat(0.0f, 100.0f);
+
+ float velocity;
+ if (_velocityZBased) {
+ velocity = _velocity1 + posZ * (_velocity2 - _velocity1) / 100;
+ } else {
+ velocity = BaseUtils::randomFloat(_velocity1, _velocity2);
+ }
+
+ float scale;
+ if (_scaleZBased) {
+ scale = _scale1 + posZ * (_scale2 - _scale1) / 100;
+ } else {
+ scale = BaseUtils::randomFloat(_scale1, _scale2);
+ }
+
+ int lifeTime;
+ if (_lifeTimeZBased) {
+ lifeTime = (int)(_lifeTime2 - posZ * (_lifeTime2 - _lifeTime1) / 100);
+ } else {
+ lifeTime = BaseUtils::randomInt(_lifeTime1, _lifeTime2);
+ }
+
+ float angle = BaseUtils::randomAngle(_angle1, _angle2);
+ int spriteIndex = BaseUtils::randomInt(0, _sprites.size() - 1);
+
+ float rotation = BaseUtils::randomAngle(_rotation1, _rotation2);
+ float angVelocity = BaseUtils::randomFloat(_angVelocity1, _angVelocity2);
+ float growthRate = BaseUtils::randomFloat(_growthRate1, _growthRate2);
+
+ if (!BasePlatform::isRectEmpty(&_border)) {
+ int thicknessLeft = (int)(_borderThicknessLeft - (float)_borderThicknessLeft * posZ / 100.0f);
+ int thicknessRight = (int)(_borderThicknessRight - (float)_borderThicknessRight * posZ / 100.0f);
+ int thicknessTop = (int)(_borderThicknessTop - (float)_borderThicknessTop * posZ / 100.0f);
+ int thicknessBottom = (int)(_borderThicknessBottom - (float)_borderThicknessBottom * posZ / 100.0f);
+
+ particle->_border = _border;
+ particle->_border.left += thicknessLeft;
+ particle->_border.right -= thicknessRight;
+ particle->_border.top += thicknessTop;
+ particle->_border.bottom -= thicknessBottom;
+ }
+
+ Vector2 vecPos((float)posX, (float)posY);
+ Vector2 vecVel(0, velocity);
+
+ Matrix4 matRot;
+ matRot.rotationZ(Common::deg2rad(BaseUtils::normalizeAngle(angle - 180)));
+ matRot.transformVector2(vecVel);
+
+ if (_alphaTimeBased) {
+ particle->_alpha1 = _alpha1;
+ particle->_alpha2 = _alpha2;
+ } else {
+ int alpha = BaseUtils::randomInt(_alpha1, _alpha2);
+ particle->_alpha1 = alpha;
+ particle->_alpha2 = alpha;
+ }
+
+ particle->_creationTime = currentTime;
+ particle->_pos = vecPos;
+ particle->_posZ = posZ;
+ particle->_velocity = vecVel;
+ particle->_scale = scale;
+ particle->_lifeTime = lifeTime;
+ particle->_rotation = rotation;
+ particle->_angVelocity = angVelocity;
+ particle->_growthRate = growthRate;
+ particle->_exponentialGrowth = _exponentialGrowth;
+ particle->_isDead = DID_FAIL(particle->setSprite(_sprites[spriteIndex]));
+ particle->fadeIn(currentTime, _fadeInTime);
+
+
+ if (particle->_isDead) {
+ return STATUS_FAILED;
+ } else {
+ return STATUS_OK;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::update() {
+ if (!_running) {
+ return STATUS_OK;
+ } else {
+ return updateInternal(_gameRef->_timer, _gameRef->_timerDelta);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::updateInternal(uint32 currentTime, uint32 timerDelta) {
+ int numLive = 0;
+
+ for (uint32 i = 0; i < _particles.size(); i++) {
+ _particles[i]->update(this, currentTime, timerDelta);
+
+ if (!_particles[i]->_isDead) {
+ numLive++;
+ }
+ }
+
+
+ // we're understaffed
+ if (numLive < _maxParticles) {
+ bool needsSort = false;
+ if ((int)(currentTime - _lastGenTime) > _genInterval) {
+ _lastGenTime = currentTime;
+ _batchesGenerated++;
+
+ if (_maxBatches > 0 && _batchesGenerated > _maxBatches) {
+ return STATUS_OK;
+ }
+
+ int toGen = MIN(_genAmount, _maxParticles - numLive);
+ while (toGen > 0) {
+ int firstDeadIndex = -1;
+ for (uint32 i = 0; i < _particles.size(); i++) {
+ if (_particles[i]->_isDead) {
+ firstDeadIndex = i;
+ break;
+ }
+ }
+
+ PartParticle *particle;
+ if (firstDeadIndex >= 0) {
+ particle = _particles[firstDeadIndex];
+ } else {
+ particle = new PartParticle(_gameRef);
+ _particles.add(particle);
+ }
+ initParticle(particle, currentTime, timerDelta);
+ needsSort = true;
+
+ toGen--;
+ }
+ }
+ if (needsSort && (_scaleZBased || _velocityZBased || _lifeTimeZBased)) {
+ sortParticlesByZ();
+ }
+
+ // we actually generated some particles and we're not in fast-forward mode
+ if (needsSort && _overheadTime == 0) {
+ if (_owner && _emitEvent) {
+ _owner->applyEvent(_emitEvent);
+ }
+ }
+ }
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::display(BaseRegion *region) {
+ if (_sprites.size() <= 1) {
+ _gameRef->_renderer->startSpriteBatch();
+ }
+
+ for (uint32 i = 0; i < _particles.size(); i++) {
+ if (region != NULL && _useRegion) {
+ if (!region->pointInRegion((int)_particles[i]->_pos.x, (int)_particles[i]->_pos.y)) {
+ continue;
+ }
+ }
+
+ _particles[i]->display(this);
+ }
+
+ if (_sprites.size() <= 1) {
+ _gameRef->_renderer->endSpriteBatch();
+ }
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::start() {
+ for (uint32 i = 0; i < _particles.size(); i++) {
+ _particles[i]->_isDead = true;
+ }
+ _running = true;
+ _batchesGenerated = 0;
+
+
+ if (_overheadTime > 0) {
+ uint32 delta = 500;
+ int steps = _overheadTime / delta;
+ uint32 currentTime = _gameRef->_timer - _overheadTime;
+
+ for (int i = 0; i < steps; i++) {
+ updateInternal(currentTime, delta);
+ currentTime += delta;
+ }
+ _overheadTime = 0;
+ }
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::sortParticlesByZ() {
+ // sort particles by _posY
+ Common::sort(_particles.begin(), _particles.end(), PartEmitter::compareZ);
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+int PartEmitter::compareZ(const void *obj1, const void *obj2) {
+ const PartParticle *p1 = *(const PartParticle *const *)obj1;
+ const PartParticle *p2 = *(const PartParticle *const *)obj2;
+
+ if (p1->_posZ < p2->_posZ) {
+ return -1;
+ } else if (p1->_posZ > p2->_posZ) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::setBorder(int x, int y, int width, int height) {
+ BasePlatform::setRect(&_border, x, y, x + width, y + height);
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::setBorderThickness(int thicknessLeft, int thicknessRight, int thicknessTop, int thicknessBottom) {
+ _borderThicknessLeft = thicknessLeft;
+ _borderThicknessRight = thicknessRight;
+ _borderThicknessTop = thicknessTop;
+ _borderThicknessBottom = thicknessBottom;
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+PartForce *PartEmitter::addForceByName(const Common::String &name) {
+ PartForce *force = NULL;
+
+ for (uint32 i = 0; i < _forces.size(); i++) {
+ if (scumm_stricmp(name.c_str(), _forces[i]->getName()) == 0) {
+ force = _forces[i];
+ break;
+ }
+ }
+ if (!force) {
+ force = new PartForce(_gameRef);
+ if (force) {
+ force->setName(name.c_str());
+ _forces.add(force);
+ }
+ }
+ return force;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::addForce(const Common::String &name, PartForce::TForceType type, int posX, int posY, float angle, float strength) {
+ PartForce *force = addForceByName(name);
+ if (!force) {
+ return STATUS_FAILED;
+ }
+
+ force->_type = type;
+ force->_pos = Vector2(posX, posY);
+
+ force->_direction = Vector2(0, strength);
+ Matrix4 matRot;
+ matRot.rotationZ(Common::deg2rad(BaseUtils::normalizeAngle(angle - 180)));
+ matRot.transformVector2(force->_direction);
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::removeForce(const Common::String &name) {
+ for (uint32 i = 0; i < _forces.size(); i++) {
+ if (scumm_stricmp(name.c_str(), _forces[i]->getName()) == 0) {
+ delete _forces[i];
+ _forces.remove_at(i);
+ return STATUS_OK;
+ }
+ }
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
+ //////////////////////////////////////////////////////////////////////////
+ // SetBorder
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "SetBorder") == 0) {
+ stack->correctParams(4);
+ int borderX = stack->pop()->getInt();
+ int borderY = stack->pop()->getInt();
+ int borderWidth = stack->pop()->getInt();
+ int borderHeight = stack->pop()->getInt();
+
+ stack->pushBool(DID_SUCCEED(setBorder(borderX, borderY, borderWidth, borderHeight)));
+
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // SetBorderThickness
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetBorderThickness") == 0) {
+ stack->correctParams(4);
+ int left = stack->pop()->getInt();
+ int right = stack->pop()->getInt();
+ int top = stack->pop()->getInt();
+ int bottom = stack->pop()->getInt();
+
+ stack->pushBool(DID_SUCCEED(setBorderThickness(left, right, top, bottom)));
+
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // AddSprite
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AddSprite") == 0) {
+ stack->correctParams(1);
+ const char *spriteFile = stack->pop()->getString();
+ stack->pushBool(DID_SUCCEED(addSprite(spriteFile)));
+
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // RemoveSprite
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "RemoveSprite") == 0) {
+ stack->correctParams(1);
+ const char *spriteFile = stack->pop()->getString();
+ stack->pushBool(DID_SUCCEED(removeSprite(spriteFile)));
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Start
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Start") == 0) {
+ stack->correctParams(1);
+ _overheadTime = stack->pop()->getInt();
+ stack->pushBool(DID_SUCCEED(start()));
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Stop
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Stop") == 0) {
+ stack->correctParams(0);
+
+ for (uint32 i = 0; i < _particles.size(); i++) {
+ delete _particles[i];
+ }
+ _particles.clear();
+
+ _running = false;
+ stack->pushBool(true);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Pause
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Pause") == 0) {
+ stack->correctParams(0);
+ _running = false;
+ stack->pushBool(true);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Resume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Resume") == 0) {
+ stack->correctParams(0);
+ _running = true;
+ stack->pushBool(true);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AddGlobalForce
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AddGlobalForce") == 0) {
+ stack->correctParams(3);
+ const char *forceName = stack->pop()->getString();
+ float angle = stack->pop()->getFloat();
+ float strength = stack->pop()->getFloat();
+
+ stack->pushBool(DID_SUCCEED(addForce(forceName, PartForce::FORCE_GLOBAL, 0, 0, angle, strength)));
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AddPointForce
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AddPointForce") == 0) {
+ stack->correctParams(5);
+ const char *forceName = stack->pop()->getString();
+ int posX = stack->pop()->getInt();
+ int posY = stack->pop()->getInt();
+ float angle = stack->pop()->getFloat();
+ float strength = stack->pop()->getFloat();
+
+ stack->pushBool(DID_SUCCEED(addForce(forceName, PartForce::FORCE_GLOBAL, posX, posY, angle, strength)));
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // RemoveForce
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "RemoveForce") == 0) {
+ stack->correctParams(1);
+ const char *forceName = stack->pop()->getString();
+
+ stack->pushBool(DID_SUCCEED(removeForce(forceName)));
+
+ return STATUS_OK;
+ } else {
+ return BaseObject::scCallMethod(script, stack, thisStack, name);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *PartEmitter::scGetProperty(const char *name) {
+ _scValue->setNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Type") == 0) {
+ _scValue->setString("particle-emitter");
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // X
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "X") == 0) {
+ _scValue->setInt(_posX);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Y
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Y") == 0) {
+ _scValue->setInt(_posY);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Width
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Width") == 0) {
+ _scValue->setInt(_width);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Height
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Height") == 0) {
+ _scValue->setInt(_height);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Scale1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Scale1") == 0) {
+ _scValue->setFloat(_scale1);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Scale2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Scale2") == 0) {
+ _scValue->setFloat(_scale2);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // ScaleZBased
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ScaleZBased") == 0) {
+ _scValue->setBool(_scaleZBased);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Velocity1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Velocity1") == 0) {
+ _scValue->setFloat(_velocity1);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Velocity2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Velocity2") == 0) {
+ _scValue->setFloat(_velocity2);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // VelocityZBased
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "VelocityZBased") == 0) {
+ _scValue->setBool(_velocityZBased);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // LifeTime1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "LifeTime1") == 0) {
+ _scValue->setInt(_lifeTime1);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // LifeTime2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "LifeTime2") == 0) {
+ _scValue->setInt(_lifeTime2);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // LifeTimeZBased
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "LifeTimeZBased") == 0) {
+ _scValue->setBool(_lifeTimeZBased);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Angle1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Angle1") == 0) {
+ _scValue->setInt(_angle1);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Angle2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Angle2") == 0) {
+ _scValue->setInt(_angle2);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AngVelocity1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AngVelocity1") == 0) {
+ _scValue->setFloat(_angVelocity1);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // AngVelocity2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AngVelocity2") == 0) {
+ _scValue->setFloat(_angVelocity2);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Rotation1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Rotation1") == 0) {
+ _scValue->setFloat(_rotation1);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Rotation2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Rotation2") == 0) {
+ _scValue->setFloat(_rotation2);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Alpha1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Alpha1") == 0) {
+ _scValue->setInt(_alpha1);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Alpha2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Alpha2") == 0) {
+ _scValue->setInt(_alpha2);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // AlphaTimeBased
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AlphaTimeBased") == 0) {
+ _scValue->setBool(_alphaTimeBased);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MaxParticles
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MaxParticles") == 0) {
+ _scValue->setInt(_maxParticles);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // NumLiveParticles (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "NumLiveParticles") == 0) {
+ int numAlive = 0;
+ for (uint32 i = 0; i < _particles.size(); i++) {
+ if (_particles[i] && !_particles[i]->_isDead) {
+ numAlive++;
+ }
+ }
+ _scValue->setInt(numAlive);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GenerationInterval
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GenerationInterval") == 0) {
+ _scValue->setInt(_genInterval);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // GenerationAmount
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GenerationAmount") == 0) {
+ _scValue->setInt(_genAmount);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // MaxBatches
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MaxBatches") == 0) {
+ _scValue->setInt(_maxBatches);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // FadeInTime
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "FadeInTime") == 0) {
+ _scValue->setInt(_fadeInTime);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // FadeOutTime
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "FadeOutTime") == 0) {
+ _scValue->setInt(_fadeOutTime);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GrowthRate1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GrowthRate1") == 0) {
+ _scValue->setFloat(_growthRate1);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // GrowthRate2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GrowthRate2") == 0) {
+ _scValue->setFloat(_growthRate2);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // ExponentialGrowth
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ExponentialGrowth") == 0) {
+ _scValue->setBool(_exponentialGrowth);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // UseRegion
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "UseRegion") == 0) {
+ _scValue->setBool(_useRegion);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // EmitEvent
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "EmitEvent") == 0) {
+ if (!_emitEvent) {
+ _scValue->setNULL();
+ } else {
+ _scValue->setString(_emitEvent);
+ }
+ return _scValue;
+ } else {
+ return BaseObject::scGetProperty(name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::scSetProperty(const char *name, ScValue *value) {
+ //////////////////////////////////////////////////////////////////////////
+ // X
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "X") == 0) {
+ _posX = value->getInt();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Y
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Y") == 0) {
+ _posY = value->getInt();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Width
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Width") == 0) {
+ _width = value->getInt();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Height
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Height") == 0) {
+ _height = value->getInt();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Scale1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Scale1") == 0) {
+ _scale1 = value->getFloat();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Scale2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Scale2") == 0) {
+ _scale2 = value->getFloat();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // ScaleZBased
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ScaleZBased") == 0) {
+ _scaleZBased = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Velocity1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Velocity1") == 0) {
+ _velocity1 = value->getFloat();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Velocity2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Velocity2") == 0) {
+ _velocity2 = value->getFloat();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // VelocityZBased
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "VelocityZBased") == 0) {
+ _velocityZBased = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // LifeTime1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "LifeTime1") == 0) {
+ _lifeTime1 = value->getInt();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // LifeTime2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "LifeTime2") == 0) {
+ _lifeTime2 = value->getInt();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // LifeTimeZBased
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "LifeTimeZBased") == 0) {
+ _lifeTimeZBased = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Angle1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Angle1") == 0) {
+ _angle1 = value->getInt();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Angle2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Angle2") == 0) {
+ _angle2 = value->getInt();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AngVelocity1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AngVelocity1") == 0) {
+ _angVelocity1 = value->getFloat();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // AngVelocity2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AngVelocity2") == 0) {
+ _angVelocity2 = value->getFloat();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Rotation1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Rotation1") == 0) {
+ _rotation1 = value->getFloat();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Rotation2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Rotation2") == 0) {
+ _rotation2 = value->getFloat();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Alpha1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Alpha1") == 0) {
+ _alpha1 = value->getInt();
+ if (_alpha1 < 0) {
+ _alpha1 = 0;
+ }
+ if (_alpha1 > 255) {
+ _alpha1 = 255;
+ }
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Alpha2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Alpha2") == 0) {
+ _alpha2 = value->getInt();
+ if (_alpha2 < 0) {
+ _alpha2 = 0;
+ }
+ if (_alpha2 > 255) {
+ _alpha2 = 255;
+ }
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // AlphaTimeBased
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AlphaTimeBased") == 0) {
+ _alphaTimeBased = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MaxParticles
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MaxParticles") == 0) {
+ _maxParticles = value->getInt();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GenerationInterval
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GenerationInterval") == 0) {
+ _genInterval = value->getInt();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // GenerationAmount
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GenerationAmount") == 0) {
+ _genAmount = value->getInt();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // MaxBatches
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MaxBatches") == 0) {
+ _maxBatches = value->getInt();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // FadeInTime
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "FadeInTime") == 0) {
+ _fadeInTime = value->getInt();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // FadeOutTime
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "FadeOutTime") == 0) {
+ _fadeOutTime = value->getInt();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GrowthRate1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GrowthRate1") == 0) {
+ _growthRate1 = value->getFloat();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // GrowthRate2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GrowthRate2") == 0) {
+ _growthRate2 = value->getFloat();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // ExponentialGrowth
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ExponentialGrowth") == 0) {
+ _exponentialGrowth = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // UseRegion
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "UseRegion") == 0) {
+ _useRegion = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // EmitEvent
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "EmitEvent") == 0) {
+ delete[] _emitEvent;
+ _emitEvent = NULL;
+ if (!value->isNULL()) {
+ BaseUtils::setString(&_emitEvent, value->getString());
+ }
+ return STATUS_OK;
+ } else {
+ return BaseObject::scSetProperty(name, value);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *PartEmitter::scToString() {
+ return "[particle emitter]";
+}
+
+
+
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::persist(BasePersistenceManager *persistMgr) {
+ BaseObject::persist(persistMgr);
+
+ persistMgr->transfer(TMEMBER(_width));
+ persistMgr->transfer(TMEMBER(_height));
+
+ persistMgr->transfer(TMEMBER(_angle1));
+ persistMgr->transfer(TMEMBER(_angle2));
+
+ persistMgr->transfer(TMEMBER(_velocity1));
+ persistMgr->transfer(TMEMBER(_velocity2));
+ persistMgr->transfer(TMEMBER(_velocityZBased));
+
+ persistMgr->transfer(TMEMBER(_scale1));
+ persistMgr->transfer(TMEMBER(_scale2));
+ persistMgr->transfer(TMEMBER(_scaleZBased));
+
+ persistMgr->transfer(TMEMBER(_maxParticles));
+
+ persistMgr->transfer(TMEMBER(_lifeTime1));
+ persistMgr->transfer(TMEMBER(_lifeTime2));
+ persistMgr->transfer(TMEMBER(_lifeTimeZBased));
+
+ persistMgr->transfer(TMEMBER(_genInterval));
+ persistMgr->transfer(TMEMBER(_genAmount));
+
+ persistMgr->transfer(TMEMBER(_running));
+ persistMgr->transfer(TMEMBER(_overheadTime));
+
+ persistMgr->transfer(TMEMBER(_border));
+ persistMgr->transfer(TMEMBER(_borderThicknessLeft));
+ persistMgr->transfer(TMEMBER(_borderThicknessRight));
+ persistMgr->transfer(TMEMBER(_borderThicknessTop));
+ persistMgr->transfer(TMEMBER(_borderThicknessBottom));
+
+ persistMgr->transfer(TMEMBER(_fadeInTime));
+ persistMgr->transfer(TMEMBER(_fadeOutTime));
+
+ persistMgr->transfer(TMEMBER(_alpha1));
+ persistMgr->transfer(TMEMBER(_alpha2));
+ persistMgr->transfer(TMEMBER(_alphaTimeBased));
+
+ persistMgr->transfer(TMEMBER(_angVelocity1));
+ persistMgr->transfer(TMEMBER(_angVelocity2));
+
+ persistMgr->transfer(TMEMBER(_rotation1));
+ persistMgr->transfer(TMEMBER(_rotation2));
+
+ persistMgr->transfer(TMEMBER(_growthRate1));
+ persistMgr->transfer(TMEMBER(_growthRate2));
+ persistMgr->transfer(TMEMBER(_exponentialGrowth));
+
+ persistMgr->transfer(TMEMBER(_useRegion));
+
+ persistMgr->transfer(TMEMBER_INT(_maxBatches));
+ persistMgr->transfer(TMEMBER_INT(_batchesGenerated));
+
+ persistMgr->transfer(TMEMBER(_emitEvent));
+ persistMgr->transfer(TMEMBER(_owner));
+
+
+ _sprites.persist(persistMgr);
+
+ uint32 numForces;
+ if (persistMgr->getIsSaving()) {
+ numForces = _forces.size();
+ persistMgr->transfer(TMEMBER(numForces));
+ for (uint32 i = 0; i < _forces.size(); i++) {
+ _forces[i]->persist(persistMgr);
+ }
+ } else {
+ persistMgr->transfer(TMEMBER(numForces));
+ for (uint32 i = 0; i < numForces; i++) {
+ PartForce *force = new PartForce(_gameRef);
+ force->persist(persistMgr);
+ _forces.add(force);
+ }
+ }
+
+ uint32 numParticles;
+ if (persistMgr->getIsSaving()) {
+ numParticles = _particles.size();
+ persistMgr->transfer(TMEMBER(numParticles));
+ for (uint32 i = 0; i < _particles.size(); i++) {
+ _particles[i]->persist(persistMgr);
+ }
+ } else {
+ persistMgr->transfer(TMEMBER(numParticles));
+ for (uint32 i = 0; i < numParticles; i++) {
+ PartParticle *particle = new PartParticle(_gameRef);
+ particle->persist(persistMgr);
+ _particles.add(particle);
+ }
+ }
+
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute