ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

anim.cpp

Go to the documentation of this file.
00001 /* ResidualVM - A 3D game interpreter
00002  *
00003  * ResidualVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the AUTHORS
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "common/debug.h"
00024 
00025 #include "engines/stark/debug.h"
00026 #include "engines/stark/formats/biffmesh.h"
00027 #include "engines/stark/formats/tm.h"
00028 #include "engines/stark/formats/xrc.h"
00029 
00030 #include "engines/stark/gfx/driver.h"
00031 #include "engines/stark/resources/anim.h"
00032 #include "engines/stark/resources/animscript.h"
00033 #include "engines/stark/resources/bonesmesh.h"
00034 #include "engines/stark/resources/direction.h"
00035 #include "engines/stark/resources/image.h"
00036 #include "engines/stark/resources/item.h"
00037 #include "engines/stark/resources/textureset.h"
00038 
00039 #include "engines/stark/services/archiveloader.h"
00040 #include "engines/stark/services/global.h"
00041 #include "engines/stark/services/services.h"
00042 #include "engines/stark/services/settings.h"
00043 #include "engines/stark/services/stateprovider.h"
00044 
00045 #include "engines/stark/model/animhandler.h"
00046 #include "engines/stark/model/skeleton_anim.h"
00047 #include "engines/stark/visual/actor.h"
00048 #include "engines/stark/visual/prop.h"
00049 #include "engines/stark/visual/smacker.h"
00050 
00051 namespace Stark {
00052 namespace Resources {
00053 
00054 Object *Anim::construct(Object *parent, byte subType, uint16 index, const Common::String &name) {
00055     switch (subType) {
00056     case kAnimImages:
00057         return new AnimImages(parent, subType, index, name);
00058     case kAnimProp:
00059         return new AnimProp(parent, subType, index, name);
00060     case kAnimVideo:
00061         return new AnimVideo(parent, subType, index, name);
00062     case kAnimSkeleton:
00063         return new AnimSkeleton(parent, subType, index, name);
00064     default:
00065         error("Unknown anim subtype %d", subType);
00066     }
00067 }
00068 
00069 Anim::~Anim() {
00070 }
00071 
00072 Anim::Anim(Object *parent, byte subType, uint16 index, const Common::String &name) :
00073         Object(parent, subType, index, name),
00074         _activity(0),
00075         _currentFrame(0),
00076         _numFrames(0),
00077         _refCount(0) {
00078     _type = TYPE;
00079 }
00080 
00081 void Anim::readData(Formats::XRCReadStream *stream) {
00082     _activity = stream->readUint32LE();
00083     _numFrames = stream->readUint32LE();
00084 }
00085 
00086 void Anim::selectFrame(uint32 frameIndex) {
00087 }
00088 
00089 uint32 Anim::getActivity() const {
00090     return _activity;
00091 }
00092 
00093 void Anim::applyToItem(Item *item) {
00094     _refCount++;
00095 }
00096 void Anim::removeFromItem(Item *item) {
00097     _refCount--;
00098 }
00099 
00100 bool Anim::isInUse() const {
00101     return _refCount > 0;
00102 }
00103 
00104 int Anim::getPointHotspotIndex(const Common::Point &point) const {
00105     // Most anim types only have one hotspot
00106     return 0;
00107 }
00108 
00109 void Anim::playAsAction(ItemVisual *item) {
00110     AnimScript *animScript = findChild<AnimScript>();
00111     animScript->goToScriptItem(0);
00112 }
00113 
00114 bool Anim::isAtTime(uint32 time) const {
00115     warning("Anim::isAtTime is not implemented");
00116     return true;
00117 }
00118 
00119 void Anim::shouldResetItem(bool resetItem) {
00120     // Script animations don't keep track of the item
00121 }
00122 
00123 void Anim::resetItem() {
00124     // Script animations don't keep track of the item
00125 }
00126 
00127 bool Anim::isDone() const {
00128     AnimScript *animScript = findChild<AnimScript>();
00129     return animScript->isDone();
00130 }
00131 
00132 uint32 Anim::getMovementSpeed() const {
00133     return 100;
00134 }
00135 
00136 uint32 Anim::getIdleActionFrequency() const {
00137     return 1;
00138 }
00139 
00140 void Anim::printData() {
00141     debug("activity: %d", _activity);
00142     debug("numFrames: %d", _numFrames);
00143 }
00144 
00145 AnimImages::~AnimImages() {
00146 }
00147 
00148 AnimImages::AnimImages(Object *parent, byte subType, uint16 index, const Common::String &name) :
00149         Anim(parent, subType, index, name),
00150         _field_3C(0),
00151         _currentDirection(0),
00152         _currentFrameImage(nullptr) {
00153 }
00154 
00155 void AnimImages::readData(Formats::XRCReadStream *stream) {
00156     Anim::readData(stream);
00157 
00158     _field_3C = stream->readFloatLE();
00159 }
00160 
00161 void AnimImages::onAllLoaded() {
00162     Anim::onAllLoaded();
00163 
00164     _directions = listChildren<Direction>();
00165 }
00166 
00167 void AnimImages::selectFrame(uint32 frameIndex) {
00168     if (frameIndex > _numFrames) {
00169         // The original silently ignores this as well
00170         warning("Request for frame %d for anim '%s' has been ignored, it is above max frame %d", frameIndex, getName().c_str(), _numFrames);
00171         _currentFrame = 0;
00172     }
00173 
00174     _currentFrame = frameIndex;
00175 }
00176 
00177 Visual *AnimImages::getVisual() {
00178     Direction *direction = _directions[_currentDirection];
00179     _currentFrameImage = direction->findChildWithIndex<Image>(_currentFrame);
00180     return _currentFrameImage->getVisual();
00181 }
00182 
00183 void AnimImages::printData() {
00184     Anim::printData();
00185 
00186     debug("field_3C: %f", _field_3C);
00187 }
00188 
00189 int AnimImages::getPointHotspotIndex(const Common::Point &point) const {
00190     if (_currentFrameImage) {
00191         return _currentFrameImage->indexForPoint(point);
00192     }
00193     return -1;
00194 }
00195 
00196 Common::Point AnimImages::getHotspotPosition(uint index) const {
00197     if (_currentFrameImage) {
00198         return _currentFrameImage->getHotspotPosition(index);
00199     }
00200     return Common::Point(-1, -1);
00201 }
00202 
00203 void AnimImages::saveLoad(ResourceSerializer *serializer) {
00204     Anim::saveLoad(serializer);
00205 
00206     serializer->syncAsUint32LE(_currentFrame);
00207 
00208     if (serializer->isLoading()) {
00209         selectFrame(_currentFrame);
00210     }
00211 }
00212 
00213 AnimProp::~AnimProp() {
00214     delete _visual;
00215 }
00216 
00217 AnimProp::AnimProp(Object *parent, byte subType, uint16 index, const Common::String &name) :
00218         Anim(parent, subType, index, name),
00219         _movementSpeed(100) {
00220     _visual = StarkGfx->createPropRenderer();
00221 }
00222 
00223 Visual *AnimProp::getVisual() {
00224     return _visual;
00225 }
00226 
00227 uint32 AnimProp::getMovementSpeed() const {
00228     return _movementSpeed;
00229 }
00230 
00231 void AnimProp::readData(Formats::XRCReadStream *stream) {
00232     Anim::readData(stream);
00233 
00234     _field_3C = stream->readString();
00235 
00236     uint32 meshCount = stream->readUint32LE();
00237     for (uint i = 0; i < meshCount; i++) {
00238         _meshFilenames.push_back(stream->readString());
00239     }
00240 
00241     _textureFilename = stream->readString();
00242     _movementSpeed = stream->readUint32LE();
00243     _archiveName = stream->getArchiveName();
00244 }
00245 
00246 void AnimProp::onPostRead() {
00247     if (_meshFilenames.size() != 1) {
00248         error("Unexpected mesh count in prop anim: '%d'", _meshFilenames.size());
00249     }
00250 
00251     ArchiveReadStream *stream = StarkArchiveLoader->getFile(_meshFilenames[0], _archiveName);
00252     _visual->setModel(Formats::BiffMeshReader::read(stream));
00253     delete stream;
00254 
00255     stream = StarkArchiveLoader->getFile(_textureFilename, _archiveName);
00256     _visual->setTexture(Formats::TextureSetReader::read(stream));
00257     delete stream;
00258 }
00259 
00260 void AnimProp::printData() {
00261     Anim::printData();
00262 
00263     debug("field_3C: %s", _field_3C.c_str());
00264 
00265     Common::String description;
00266     for (uint32 i = 0; i < _meshFilenames.size(); i++) {
00267         debug("meshFilename[%d]: %s", i, _meshFilenames[i].c_str());
00268     }
00269     debug("textureFilename: %s", _textureFilename.c_str());
00270     debug("movementSpeed: %d", _movementSpeed);
00271 }
00272 
00273 AnimVideo::~AnimVideo() {
00274     delete _smacker;
00275 }
00276 
00277 AnimVideo::AnimVideo(Object *parent, byte subType, uint16 index, const Common::String &name) :
00278         Anim(parent, subType, index, name),
00279         _width(0),
00280         _height(0),
00281         _smacker(nullptr),
00282         _frameRateOverride(-1),
00283         _preload(false),
00284         _loop(false),
00285         _actionItem(nullptr),
00286         _shouldResetItem(true),
00287         _done(false) {
00288 }
00289 
00290 void AnimVideo::readData(Formats::XRCReadStream *stream) {
00291     Anim::readData(stream);
00292     _smackerFile = stream->readString();
00293     _width = stream->readUint32LE();
00294     _height = stream->readUint32LE();
00295 
00296     _positions.clear();
00297     _sizes.clear();
00298 
00299     uint32 size = stream->readUint32LE();
00300     for (uint i = 0; i < size; i++) {
00301         _positions.push_back(stream->readPoint());
00302         _sizes.push_back(stream->readRect());
00303     }
00304 
00305     _loop = stream->readBool();
00306     _frameRateOverride = stream->readUint32LE();
00307 
00308     if (stream->isDataLeft()) {
00309         _preload = stream->readBool();
00310     }
00311 
00312     _archiveName = stream->getArchiveName();
00313 }
00314 
00315 void AnimVideo::onAllLoaded() {
00316     if (!_smacker) {
00317 
00318         _smacker = new VisualSmacker(StarkGfx);
00319 
00320         Common::SeekableReadStream *overrideStreamBink = nullptr;
00321         Common::SeekableReadStream *overrideStreamSmacker = nullptr;
00322         if (StarkSettings->isAssetsModEnabled()) {
00323             overrideStreamBink = openOverrideFile(".bik");
00324             if (!overrideStreamBink) {
00325                 overrideStreamSmacker = openOverrideFile(".smk");
00326             }
00327         }
00328 
00329         Common::SeekableReadStream *stream = StarkArchiveLoader->getExternalFile(_smackerFile, _archiveName);
00330         if (overrideStreamBink) {
00331             _smacker->loadBink(overrideStreamBink);
00332             _smacker->readOriginalSize(stream);
00333         } else if (overrideStreamSmacker) {
00334             _smacker->loadSmacker(overrideStreamSmacker);
00335             _smacker->readOriginalSize(stream);
00336         } else {
00337             _smacker->loadSmacker(stream);
00338         }
00339 
00340         _smacker->overrideFrameRate(_frameRateOverride);
00341 
00342         updateSmackerPosition();
00343     }
00344 }
00345 
00346 Common::SeekableReadStream *AnimVideo::openOverrideFile(const Common::String &extension) const {
00347     if (!_smackerFile.hasSuffixIgnoreCase(".sss")) {
00348         return nullptr;
00349     }
00350 
00351     Common::String filename = Common::String(_smackerFile.c_str(), _smackerFile.size() - 4) + extension;
00352     Common::String filePath = StarkArchiveLoader->getExternalFilePath(filename, _archiveName);
00353 
00354     debugC(kDebugModding, "Attempting to load %s", filePath.c_str());
00355 
00356     Common::SeekableReadStream *smkStream = SearchMan.createReadStreamForMember(filePath);
00357     if (!smkStream) {
00358         return nullptr;
00359     }
00360 
00361     debugC(kDebugModding, "Loaded %s", filePath.c_str());
00362 
00363     return smkStream;
00364 }
00365 
00366 void AnimVideo::onGameLoop() {
00367     if (!_smacker || !isInUse()) {
00368         return; // Animation not in use, no need to update the movie
00369     }
00370 
00371     if (_smacker->isDone()) {
00372         // The last frame has been reached
00373         _done = true;
00374 
00375         if (_shouldResetItem) {
00376             resetItem();
00377         }
00378 
00379         if (_loop) {
00380             _smacker->rewind();
00381         }
00382     }
00383 
00384     if (!_smacker->isDone()) {
00385         _smacker->update();
00386         updateSmackerPosition();
00387     }
00388 }
00389 
00390 void AnimVideo::resetItem() {
00391     if (!_loop && _actionItem) {
00392         // Reset our item if needed
00393         if (_actionItem->getActionAnim() == this) {
00394             _actionItem->resetActionAnim();
00395         }
00396         _actionItem = nullptr;
00397     }
00398 }
00399 
00400 void AnimVideo::onEnginePause(bool pause) {
00401     Object::onEnginePause(pause);
00402 
00403     if (_smacker && isInUse()) {
00404         _smacker->pause(pause);
00405     }
00406 }
00407 
00408 Visual *AnimVideo::getVisual() {
00409     return _smacker;
00410 }
00411 
00412 void AnimVideo::updateSmackerPosition() {
00413     int frame = _smacker->getFrameNumber();
00414     if (frame == -1) {
00415         return;
00416     }
00417 
00418     if (frame < (int) _positions.size()) {
00419         _smacker->setPosition(_positions[frame]);
00420     }
00421 }
00422 
00423 void AnimVideo::shouldResetItem(bool resetItem) {
00424     _shouldResetItem = resetItem;
00425 }
00426 
00427 void AnimVideo::playAsAction(ItemVisual *item) {
00428     _actionItem = item;
00429     _shouldResetItem = true;
00430     _done = false;
00431 
00432     if (!_loop) {
00433         _smacker->rewind();
00434     }
00435 
00436     // Update here so we have something up to date to show when rendering this frame
00437     _smacker->update();
00438 }
00439 
00440 bool AnimVideo::isAtTime(uint32 time) const {
00441     uint32 currentTime = _smacker->getCurrentTime();
00442     return currentTime >= time;
00443 }
00444 
00445 void AnimVideo::saveLoadCurrent(ResourceSerializer *serializer) {
00446     Anim::saveLoadCurrent(serializer);
00447 
00448     int32 frameNumber = _smacker->getFrameNumber();
00449     serializer->syncAsSint32LE(frameNumber);
00450     serializer->syncAsSint32LE(_refCount);
00451 
00452     // TODO: Seek to the saved frame number when loading
00453 }
00454 
00455 void AnimVideo::printData() {
00456     Anim::printData();
00457 
00458     debug("smackerFile: %s", _smackerFile.c_str());
00459     debug("size: x %d, y %d", _width, _height);
00460 
00461     Common::String description;
00462     for (uint32 i = 0; i < _positions.size(); i++) {
00463         description += Common::String::format("(x %d, y %d) ", _positions[i].x, _positions[i].y);
00464     }
00465     debug("positions: %s", description.c_str());
00466 
00467     description.clear();
00468     for (uint32 i = 0; i < _sizes.size(); i++) {
00469         description += Common::String::format("(l %d, t %d, r %d, b %d) ",
00470                 _sizes[i].left, _sizes[i].top, _sizes[i].right, _sizes[i].bottom);
00471     }
00472     debug("sizes: %s", description.c_str());
00473 
00474     debug("frameRateOverride: %d", _frameRateOverride);
00475     debug("preload: %d", _preload);
00476     debug("loop: %d", _loop);
00477 }
00478 
00479 AnimSkeleton::~AnimSkeleton() {
00480     delete _visual;
00481     delete _skeletonAnim;
00482 }
00483 
00484 AnimSkeleton::AnimSkeleton(Object *parent, byte subType, uint16 index, const Common::String &name) :
00485         Anim(parent, subType, index, name),
00486         _castsShadow(true),
00487         _loop(false),
00488         _movementSpeed(100),
00489         _idleActionFrequency(1),
00490         _skeletonAnim(nullptr),
00491         _currentTime(0),
00492         _totalTime(0),
00493         _done(false),
00494         _actionItem(nullptr),
00495         _shouldResetItem(true) {
00496     _visual = StarkGfx->createActorRenderer();
00497 }
00498 
00499 void AnimSkeleton::applyToItem(Item *item) {
00500     Anim::applyToItem(item);
00501 
00502     if (!_loop) {
00503         _currentTime = 0;
00504     }
00505 
00506     if (_currentTime > _totalTime) {
00507         _currentTime = 0;
00508     }
00509 
00510     debugC(kDebugAnimation, "%s: add %s", item->getName().c_str(), getName().c_str());
00511 
00512     ModelItem *modelItem = Object::cast<ModelItem>(item);
00513 
00514     BonesMesh *mesh = modelItem->findBonesMesh();
00515     TextureSet *texture = modelItem->findTextureSet(TextureSet::kTextureNormal);
00516 
00517     AnimHandler *animHandler = modelItem->getAnimHandler();
00518     animHandler->setModel(mesh->getModel());
00519     animHandler->setAnim(_skeletonAnim);
00520 
00521     _visual->setModel(mesh->getModel());
00522     _visual->setAnimHandler(animHandler);
00523     _visual->setTexture(texture->getTexture());
00524     _visual->setTextureFacial(nullptr);
00525     _visual->setTime(_currentTime);
00526     _visual->setCastShadow(_castsShadow);
00527 }
00528 
00529 void AnimSkeleton::removeFromItem(Item *item) {
00530     Anim::removeFromItem(item);
00531 
00532     debugC(kDebugAnimation, "%s: remove %s", item->getName().c_str(), getName().c_str());
00533 
00534     _actionItem = nullptr;
00535 }
00536 
00537 Visual *AnimSkeleton::getVisual() {
00538     return _visual;
00539 }
00540 
00541 void AnimSkeleton::readData(Formats::XRCReadStream *stream) {
00542     Anim::readData(stream);
00543 
00544     _animFilename = stream->readString();
00545     stream->readString(); // Skipped in the original
00546     stream->readString(); // Skipped in the original
00547     stream->readString(); // Skipped in the original
00548 
00549     _loop = stream->readBool();
00550     _movementSpeed = stream->readUint32LE();
00551 
00552     if (_movementSpeed < 1) {
00553         _movementSpeed = 100;
00554     }
00555 
00556     if (stream->isDataLeft()) {
00557         _castsShadow = stream->readBool();
00558     } else {
00559         _castsShadow = true;
00560     }
00561 
00562     if (stream->isDataLeft()) {
00563         _idleActionFrequency = stream->readUint32LE();
00564     } else {
00565         _idleActionFrequency = 1;
00566     }
00567 
00568     _archiveName = stream->getArchiveName();
00569 }
00570 
00571 void AnimSkeleton::onPostRead() {
00572     ArchiveReadStream *stream = StarkArchiveLoader->getFile(_animFilename, _archiveName);
00573 
00574     _skeletonAnim = new SkeletonAnim();
00575     _skeletonAnim->createFromStream(stream);
00576 
00577     delete stream;
00578 }
00579 
00580 void AnimSkeleton::onAllLoaded() {
00581     Anim::onAllLoaded();
00582 
00583     _totalTime = _skeletonAnim->getLength();
00584     _currentTime = 0;
00585 }
00586 
00587 void AnimSkeleton::onGameLoop() {
00588     Anim::onGameLoop();
00589 
00590     if (isInUse() && _totalTime) {
00591         uint32 newTime = _currentTime + StarkGlobal->getMillisecondsPerGameloop();
00592 
00593         if (!_loop && newTime >= _totalTime) {
00594             _done = true;
00595 
00596             if (_shouldResetItem) {
00597                 resetItem();
00598             }
00599         } else {
00600             _currentTime = newTime % _totalTime;
00601             _visual->setTime(_currentTime);
00602         }
00603     }
00604 }
00605 
00606 void AnimSkeleton::resetItem() {
00607     if (_actionItem) {
00608         if (_actionItem->getActionAnim() == this) {
00609             _actionItem->resetActionAnim();
00610         }
00611         _actionItem = nullptr;
00612     }
00613 }
00614 
00615 void AnimSkeleton::onPreDestroy() {
00616     resetItem();
00617 
00618     Anim::onPreDestroy();
00619 }
00620 
00621 uint32 AnimSkeleton::getMovementSpeed() const {
00622     return _movementSpeed;
00623 }
00624 
00625 uint32 AnimSkeleton::getCurrentTime() const {
00626     return _currentTime;
00627 }
00628 
00629 uint32 AnimSkeleton::getRemainingTime() const {
00630     int32 remainingTime = _totalTime - _currentTime;
00631     return CLIP<int32>(remainingTime, 0, _totalTime);
00632 }
00633 
00634 void AnimSkeleton::shouldResetItem(bool resetItem) {
00635     _shouldResetItem = resetItem;
00636 }
00637 
00638 void AnimSkeleton::playAsAction(ItemVisual *item) {
00639     _actionItem = item;
00640     _done = false;
00641     _shouldResetItem = true;
00642 
00643     if (!_loop) {
00644         _currentTime = 0;
00645     }
00646 }
00647 
00648 bool AnimSkeleton::isAtTime(uint32 time) const {
00649     return _currentTime >= time;
00650 }
00651 
00652 uint32 AnimSkeleton::getIdleActionFrequency() const {
00653     return _idleActionFrequency;
00654 }
00655 
00656 void AnimSkeleton::printData() {
00657     Anim::printData();
00658 
00659     debug("filename: %s", _animFilename.c_str());
00660     debug("castsShadow: %d", _castsShadow);
00661     debug("loop: %d", _loop);
00662     debug("movementSpeed: %d", _movementSpeed);
00663     debug("idleActionFrequency: %d", _idleActionFrequency);
00664 }
00665 
00666 } // End of namespace Resources
00667 } // End of namespace Stark


Generated on Sat Mar 23 2019 05:01:16 for ResidualVM by doxygen 1.7.1
curved edge   curved edge