mirror of
https://github.com/libretro/scummvm.git
synced 2025-05-13 17:46:22 +00:00
STARK: Implement animation triggered sounds
Mainly used for footstep sounds
This commit is contained in:
parent
bd262446fa
commit
368d71cfd5
@ -26,6 +26,7 @@
|
||||
#include "engines/stark/resources/anim.h"
|
||||
#include "engines/stark/resources/animhierarchy.h"
|
||||
#include "engines/stark/resources/animscript.h"
|
||||
#include "engines/stark/resources/animsoundtrigger.h"
|
||||
#include "engines/stark/resources/bonesmesh.h"
|
||||
#include "engines/stark/resources/bookmark.h"
|
||||
#include "engines/stark/resources/camera.h"
|
||||
@ -275,6 +276,9 @@ Resources::Object *XRCReader::createResource(XRCReadStream *stream, Resources::O
|
||||
case Resources::Type::kLipSync:
|
||||
resource = new Resources::LipSync(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kAnimSoundTrigger:
|
||||
resource = new Resources::AnimSoundTrigger(parent, subType, index, name);
|
||||
break;
|
||||
case Resources::Type::kString:
|
||||
resource = new Resources::String(parent, subType, index, name);
|
||||
break;
|
||||
|
@ -31,6 +31,7 @@ MODULE_OBJS := \
|
||||
resources/anim.o \
|
||||
resources/animhierarchy.o \
|
||||
resources/animscript.o \
|
||||
resources/animsoundtrigger.o \
|
||||
resources/bonesmesh.o \
|
||||
resources/bookmark.o \
|
||||
resources/camera.o \
|
||||
|
@ -514,6 +514,15 @@ uint32 AnimSkeleton::getDuration() const {
|
||||
return _totalTime;
|
||||
}
|
||||
|
||||
uint32 AnimSkeleton::getCurrentTime() const {
|
||||
return _currentTime;
|
||||
}
|
||||
|
||||
uint32 AnimSkeleton::getRemainingTime() const {
|
||||
int32 remainingTime = _totalTime - _currentTime;
|
||||
return CLIP<int32>(remainingTime, 0, _totalTime);
|
||||
}
|
||||
|
||||
void AnimSkeleton::playAsAction(ItemVisual *item) {
|
||||
_actionItem = item;
|
||||
|
||||
|
@ -260,6 +260,12 @@ public:
|
||||
bool isAtTime(uint32 time) const override;
|
||||
uint32 getMovementSpeed() const override;
|
||||
|
||||
/** Get the position in the animation loop in milliseconds */
|
||||
uint32 getCurrentTime() const;
|
||||
|
||||
/** Get the duration in milliseconds before the animation loops ends */
|
||||
uint32 getRemainingTime() const;
|
||||
|
||||
protected:
|
||||
void printData() override;
|
||||
|
||||
|
101
engines/stark/resources/animsoundtrigger.cpp
Normal file
101
engines/stark/resources/animsoundtrigger.cpp
Normal file
@ -0,0 +1,101 @@
|
||||
/* ResidualVM - A 3D game interpreter
|
||||
*
|
||||
* ResidualVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the AUTHORS
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "engines/stark/resources/animsoundtrigger.h"
|
||||
|
||||
#include "engines/stark/formats/xrc.h"
|
||||
#include "engines/stark/resources/anim.h"
|
||||
#include "engines/stark/resources/location.h"
|
||||
#include "engines/stark/resources/sound.h"
|
||||
#include "engines/stark/services/global.h"
|
||||
#include "engines/stark/services/services.h"
|
||||
|
||||
namespace Stark {
|
||||
namespace Resources {
|
||||
|
||||
AnimSoundTrigger::~AnimSoundTrigger() {
|
||||
}
|
||||
|
||||
AnimSoundTrigger::AnimSoundTrigger(Object *parent, byte subType, uint16 index, const Common::String &name) :
|
||||
Object(parent, subType, index, name),
|
||||
_soundStockType(0),
|
||||
_soundTriggerTime(0),
|
||||
_anim(nullptr),
|
||||
_alreadyPlayed(false),
|
||||
_timeRemainingBeforeLoop(34) {
|
||||
_type = TYPE;
|
||||
}
|
||||
|
||||
void AnimSoundTrigger::onAllLoaded() {
|
||||
Object::onAllLoaded();
|
||||
_anim = Object::cast<AnimSkeleton>(_parent);
|
||||
}
|
||||
|
||||
void AnimSoundTrigger::onGameLoop() {
|
||||
Object::onGameLoop();
|
||||
|
||||
if (!_anim || !_anim->isInUse()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_alreadyPlayed && _anim->getCurrentTime() < 33) {
|
||||
// Animation loop detected, reset
|
||||
_alreadyPlayed = false;
|
||||
}
|
||||
|
||||
if ((!_alreadyPlayed && _anim->getCurrentTime() >= _soundTriggerTime) || _timeRemainingBeforeLoop < 33) {
|
||||
if (_timeRemainingBeforeLoop >= 33) {
|
||||
_alreadyPlayed = true;
|
||||
}
|
||||
|
||||
if (_subType == kAnimTriggerSound) {
|
||||
Location *location = StarkGlobal->getCurrent()->getLocation();
|
||||
Sound *sound = location->findStockSound(_soundStockType);
|
||||
if (sound) {
|
||||
// TODO: If the location has a 3D layer set the source position of the sound to the item position
|
||||
sound->play();
|
||||
}
|
||||
} else {
|
||||
warning("Unknown animation trigger subtype '%d'", _subType);
|
||||
}
|
||||
}
|
||||
|
||||
// Special handling for trigger times right before the animation loop point
|
||||
if (!_alreadyPlayed && _soundTriggerTime - _anim->getCurrentTime() < 33) {
|
||||
_timeRemainingBeforeLoop = _anim->getRemainingTime();
|
||||
} else {
|
||||
_timeRemainingBeforeLoop = 34;
|
||||
}
|
||||
}
|
||||
|
||||
void AnimSoundTrigger::readData(Formats::XRCReadStream *stream) {
|
||||
_soundTriggerTime = stream->readUint32LE();
|
||||
_soundStockType = stream->readUint32LE();
|
||||
}
|
||||
|
||||
void AnimSoundTrigger::printData() {
|
||||
debug("triggerTime: %d", _soundTriggerTime);
|
||||
debug("soundStockType: %d", _soundStockType);
|
||||
}
|
||||
|
||||
} // End of namespace Resources
|
||||
} // End of namespace Stark
|
74
engines/stark/resources/animsoundtrigger.h
Normal file
74
engines/stark/resources/animsoundtrigger.h
Normal file
@ -0,0 +1,74 @@
|
||||
/* ResidualVM - A 3D game interpreter
|
||||
*
|
||||
* ResidualVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the AUTHORS
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef STARK_RESOURCES_ANIM_SOUND_TRIGGER_H
|
||||
#define STARK_RESOURCES_ANIM_SOUND_TRIGGER_H
|
||||
|
||||
#include "common/str.h"
|
||||
|
||||
#include "engines/stark/resources/object.h"
|
||||
|
||||
namespace Stark {
|
||||
|
||||
namespace Formats {
|
||||
class XRCReadStream;
|
||||
}
|
||||
|
||||
namespace Resources {
|
||||
|
||||
class AnimSkeleton;
|
||||
|
||||
/**
|
||||
* An AnimSoundTrigger plays a sound when a certain time of an animation is reached
|
||||
*
|
||||
* The sound is played at most once per animation loop.
|
||||
*/
|
||||
class AnimSoundTrigger : public Object {
|
||||
public:
|
||||
static const Type::ResourceType TYPE = Type::kAnimSoundTrigger;
|
||||
|
||||
enum SubType {
|
||||
kAnimTriggerSound = 1
|
||||
};
|
||||
|
||||
AnimSoundTrigger(Object *parent, byte subType, uint16 index, const Common::String &name);
|
||||
virtual ~AnimSoundTrigger();
|
||||
|
||||
// Resource API
|
||||
void readData(Formats::XRCReadStream *stream) override;
|
||||
void printData() override;
|
||||
void onAllLoaded() override;
|
||||
void onGameLoop() override;
|
||||
|
||||
private:
|
||||
uint32 _soundStockType;
|
||||
uint32 _soundTriggerTime;
|
||||
|
||||
AnimSkeleton *_anim;
|
||||
bool _alreadyPlayed;
|
||||
uint _timeRemainingBeforeLoop;
|
||||
};
|
||||
|
||||
} // End of namespace Resources
|
||||
} // End of namespace Stark
|
||||
|
||||
#endif // STARK_RESOURCES_ANIM_SOUND_TRIGGER_H
|
@ -39,7 +39,8 @@ public:
|
||||
static const Type::ResourceType TYPE = Type::kContainer;
|
||||
|
||||
enum SubType {
|
||||
kSounds = 5
|
||||
kSounds = 5,
|
||||
kStockSounds = 8
|
||||
};
|
||||
|
||||
Container(Object *parent, byte subType, uint16 index, const Common::String &name);
|
||||
|
@ -27,9 +27,12 @@
|
||||
|
||||
#include "engines/stark/movement/movement.h"
|
||||
|
||||
#include "engines/stark/resources/container.h"
|
||||
#include "engines/stark/resources/item.h"
|
||||
#include "engines/stark/resources/layer.h"
|
||||
#include "engines/stark/resources/level.h"
|
||||
#include "engines/stark/resources/scroll.h"
|
||||
#include "engines/stark/resources/sound.h"
|
||||
|
||||
#include "engines/stark/scene.h"
|
||||
#include "engines/stark/services/services.h"
|
||||
@ -335,5 +338,37 @@ void Location::resetAnimationBlending() {
|
||||
}
|
||||
}
|
||||
|
||||
Sound *Location::findStockSound(uint32 stockSoundType) const {
|
||||
Sound *sound = findStockSound(this, stockSoundType);
|
||||
|
||||
if (!sound) {
|
||||
Level *currentLevel = StarkGlobal->getCurrent()->getLevel();
|
||||
sound = findStockSound(currentLevel, stockSoundType);
|
||||
}
|
||||
|
||||
if (!sound) {
|
||||
Level *globalLevel = StarkGlobal->getLevel();
|
||||
sound = findStockSound(globalLevel, stockSoundType);
|
||||
}
|
||||
|
||||
return sound;
|
||||
}
|
||||
|
||||
Sound *Location::findStockSound(const Object *parent, uint32 stockSoundType) const {
|
||||
Container *stockSoundContainer = parent->findChildWithSubtype<Container>(Container::kStockSounds);
|
||||
if (stockSoundContainer) {
|
||||
Common::Array<Sound *> stockSounds = stockSoundContainer->listChildren<Sound>(Sound::kSoundStock);
|
||||
|
||||
for (uint i = 0; i < stockSounds.size(); i++) {
|
||||
Sound *sound = stockSounds[i];
|
||||
if (sound->getStockSoundType() == stockSoundType) {
|
||||
return sound;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // End of namespace Resources
|
||||
} // End of namespace Stark
|
||||
|
@ -41,6 +41,7 @@ namespace Resources {
|
||||
class ItemVisual;
|
||||
class Layer;
|
||||
class ModelItem;
|
||||
class Sound;
|
||||
|
||||
/**
|
||||
* A location is a scene of the game
|
||||
@ -115,6 +116,9 @@ public:
|
||||
/** Reset animation blending for all the items in the location */
|
||||
void resetAnimationBlending();
|
||||
|
||||
/** Find a stock sound by its type in the location, the level, or the global level */
|
||||
Sound *findStockSound(uint32 stockSoundType) const;
|
||||
|
||||
protected:
|
||||
void printData() override;
|
||||
|
||||
@ -125,6 +129,8 @@ private:
|
||||
uint getScrollStepFollow();
|
||||
Common::Point getScrollPointFromCoordinate(uint32 coordinate) const;
|
||||
|
||||
Sound *findStockSound(const Object *parent, uint32 stockSoundType) const;
|
||||
|
||||
Common::Array<Layer *> _layers;
|
||||
Layer *_currentLayer;
|
||||
|
||||
|
@ -78,7 +78,7 @@ const char *Type::getName() const {
|
||||
{ Type::kScroll, "Scroll" },
|
||||
{ Type::kFMV, "FMV" },
|
||||
{ Type::kLipSync, "LipSynch" },
|
||||
{ Type::kAnimScriptBonesTrigger, "AnimScriptBonesTrigger" },
|
||||
{ Type::kAnimSoundTrigger, "AnimSoundTrigger" },
|
||||
{ Type::kString, "String" },
|
||||
{ Type::kTextureSet, "TextureSet" }
|
||||
};
|
||||
@ -235,7 +235,7 @@ Object *Object::cast<Object>(Object *resource) {
|
||||
}
|
||||
|
||||
template<>
|
||||
Common::Array<Object *> Object::listChildren<Object>(int subType) {
|
||||
Common::Array<Object *> Object::listChildren<Object>(int subType) const {
|
||||
assert(subType == -1);
|
||||
|
||||
Common::Array<Object *> list;
|
||||
|
@ -71,7 +71,7 @@ public:
|
||||
kScroll = 33,
|
||||
kFMV = 34,
|
||||
kLipSync = 35,
|
||||
kAnimScriptBonesTrigger = 36,
|
||||
kAnimSoundTrigger = 36,
|
||||
kString = 37,
|
||||
kTextureSet = 38
|
||||
};
|
||||
@ -233,7 +233,7 @@ public:
|
||||
|
||||
/** Find a child matching the template parameter type and the specified subtype */
|
||||
template<class T>
|
||||
T *findChildWithSubtype(int subType, bool mustBeUnique = true);
|
||||
T *findChildWithSubtype(int subType, bool mustBeUnique = true) const;
|
||||
|
||||
/** Find a child matching the template parameter type and the specified index */
|
||||
template<class T>
|
||||
@ -245,7 +245,7 @@ public:
|
||||
|
||||
/** List children matching the template parameter type and the specified subtype */
|
||||
template<class T>
|
||||
Common::Array<T *> listChildren(int subType = -1);
|
||||
Common::Array<T *> listChildren(int subType = -1) const;
|
||||
|
||||
/** List children recursively matching the template parameter type and the specified subtype */
|
||||
template<class T>
|
||||
@ -320,7 +320,7 @@ template<>
|
||||
Object *Object::findParent();
|
||||
|
||||
template <class T>
|
||||
Common::Array<T *> Object::listChildren(int subType) {
|
||||
Common::Array<T *> Object::listChildren(int subType) const {
|
||||
Common::Array<T *> list;
|
||||
|
||||
for (uint i = 0; i < _children.size(); i++) {
|
||||
@ -353,7 +353,7 @@ Common::Array<T *> Object::listChildrenRecursive(int subType) {
|
||||
}
|
||||
|
||||
template<>
|
||||
Common::Array<Object *> Object::listChildren<Object>(int subType);
|
||||
Common::Array<Object *> Object::listChildren<Object>(int subType) const;
|
||||
|
||||
template<class T>
|
||||
T *Object::findChild(bool mustBeUnique) {
|
||||
@ -361,7 +361,7 @@ T *Object::findChild(bool mustBeUnique) {
|
||||
}
|
||||
|
||||
template <class T>
|
||||
T *Object::findChildWithSubtype(int subType, bool mustBeUnique) {
|
||||
T *Object::findChildWithSubtype(int subType, bool mustBeUnique) const {
|
||||
Common::Array<T *> list = listChildren<T>(subType);
|
||||
|
||||
if (list.empty()) {
|
||||
|
@ -181,5 +181,9 @@ void Sound::onGameLoop() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32 Sound::getStockSoundType() const {
|
||||
return _stockSoundType;
|
||||
}
|
||||
} // End of namespace Resources
|
||||
} // End of namespace Stark
|
||||
|
@ -48,6 +48,10 @@ class Sound : public Object {
|
||||
public:
|
||||
static const Type::ResourceType TYPE = Type::kSoundItem;
|
||||
|
||||
enum SubType {
|
||||
kSoundStock = 5
|
||||
};
|
||||
|
||||
enum SoundType {
|
||||
kSoundTypeVoice = 0,
|
||||
kSoundTypeEffect = 1,
|
||||
@ -71,6 +75,9 @@ public:
|
||||
/** Stop the sound */
|
||||
void stop();
|
||||
|
||||
/** Get the type for stock sounds */
|
||||
uint32 getStockSoundType() const;
|
||||
|
||||
protected:
|
||||
void printData() override;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user