mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-20 08:53:51 +00:00
MADS: Implement loading logic for UI background animations
This commit is contained in:
parent
f6a6ea9741
commit
7e13f488ab
@ -108,15 +108,24 @@ void AnimMessage::load(Common::SeekableReadStream *f) {
|
||||
f->skip(2);
|
||||
}
|
||||
|
||||
void AnimFrameEntry::load(Common::SeekableReadStream *f) {
|
||||
_frameNumber = f->readUint16LE();
|
||||
_seqIndex = f->readByte();
|
||||
_spriteSlot._spritesIndex = f->readByte();
|
||||
_spriteSlot._frameNumber = f->readUint16LE();
|
||||
_spriteSlot._position.x = f->readSint16LE();
|
||||
_spriteSlot._position.y = f->readSint16LE();
|
||||
_spriteSlot._depth = f->readSByte();
|
||||
_spriteSlot._scale = (int8)f->readByte();
|
||||
void AnimFrameEntry::load(Common::SeekableReadStream *f, bool uiFlag) {
|
||||
if (uiFlag) {
|
||||
f->skip(2);
|
||||
_seqIndex = f->readByte();
|
||||
_spriteSlot._spritesIndex = f->readByte();
|
||||
_spriteSlot._frameNumber = f->readUint16LE();
|
||||
_spriteSlot._position.x = f->readSint16LE();
|
||||
_spriteSlot._position.y = f->readSint16LE();
|
||||
} else {
|
||||
_frameNumber = f->readUint16LE();
|
||||
_seqIndex = f->readByte();
|
||||
_spriteSlot._spritesIndex = f->readByte();
|
||||
_spriteSlot._frameNumber = f->readUint16LE();
|
||||
_spriteSlot._position.x = f->readSint16LE();
|
||||
_spriteSlot._position.y = f->readSint16LE();
|
||||
_spriteSlot._depth = f->readSByte();
|
||||
_spriteSlot._scale = (int8)f->readByte();
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
@ -132,6 +141,22 @@ void AnimMiscEntry::load(Common::SeekableReadStream *f) {
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
void AnimUIEntry::load(Common::SeekableReadStream *f) {
|
||||
_probability = f->readUint16LE();
|
||||
_imageCount = f->readUint16LE();
|
||||
_firstImage = f->readUint16LE();
|
||||
_lastImage = f->readUint16LE();
|
||||
_counter = f->readSint16LE();
|
||||
for (int i = 0; i < ANIM_SPAWN_COUNT; ++i)
|
||||
_spawn[i] = f->readByte();
|
||||
for (int i = 0; i < ANIM_SPAWN_COUNT; ++i)
|
||||
_spawnFrame[i] = f->readUint16LE();
|
||||
_sound = f->readUint16LE() & 0xFF;
|
||||
_soundFrame = f->readUint16LE();
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
Animation *Animation::init(MADSEngine *vm, Scene *scene) {
|
||||
return new Animation(vm, scene);
|
||||
}
|
||||
@ -149,7 +174,7 @@ Animation::~Animation() {
|
||||
if (_header._manualFlag)
|
||||
scene._sprites.remove(_spriteListIndexes[_header._spritesIndex]);
|
||||
|
||||
for (uint idx = 0; idx < _header._spriteSetsCount; ++idx) {
|
||||
for (int idx = 0; idx < _header._spriteSetsCount; ++idx) {
|
||||
if (!_header._manualFlag || _header._spritesIndex != idx)
|
||||
scene._sprites.remove(_spriteListIndexes[idx]);
|
||||
}
|
||||
@ -195,12 +220,12 @@ void Animation::load(UserInterface &interfaceSurface, MSurface &depthSurface,
|
||||
delete stream;
|
||||
|
||||
if (_header._animMode == 4)
|
||||
flags |= 0x4000;
|
||||
flags |= PALFLAG_RESERVED;
|
||||
|
||||
if (flags & 0x100) {
|
||||
if (flags & ANIMFLAG_LOAD_BACKGROUND) {
|
||||
loadInterface(interfaceSurface, depthSurface, _header, flags, palAnimData, sceneInfo);
|
||||
}
|
||||
if (flags & 0x200) {
|
||||
if (flags & ANIMFLAG_LOAD_BACKGROUND_ONLY) {
|
||||
// No data
|
||||
_header._messagesCount = 0;
|
||||
_header._frameEntriesCount = 0;
|
||||
@ -234,7 +259,7 @@ void Animation::load(UserInterface &interfaceSurface, MSurface &depthSurface,
|
||||
|
||||
for (int i = 0; i < _header._frameEntriesCount; i++) {
|
||||
AnimFrameEntry rec;
|
||||
rec.load(frameStream);
|
||||
rec.load(frameStream, flags & ANIMFLAG_LOAD_BACKGROUND);
|
||||
_frameEntries.push_back(rec);
|
||||
}
|
||||
|
||||
@ -242,14 +267,23 @@ void Animation::load(UserInterface &interfaceSurface, MSurface &depthSurface,
|
||||
}
|
||||
|
||||
_miscEntries.clear();
|
||||
_uiEntries.clear();
|
||||
if (_header._miscEntriesCount > 0) {
|
||||
// Chunk 4: Misc Data
|
||||
Common::SeekableReadStream *miscStream = madsPack.getItemStream(streamIndex++);
|
||||
|
||||
for (int i = 0; i < _header._miscEntriesCount; ++i) {
|
||||
AnimMiscEntry rec;
|
||||
rec.load(miscStream);
|
||||
_miscEntries.push_back(rec);
|
||||
if (flags & ANIMFLAG_LOAD_BACKGROUND) {
|
||||
for (int i = 0; i < _header._miscEntriesCount; ++i) {
|
||||
AnimUIEntry rec;
|
||||
rec.load(miscStream);
|
||||
_uiEntries.push_back(rec);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < _header._miscEntriesCount; ++i) {
|
||||
AnimMiscEntry rec;
|
||||
rec.load(miscStream);
|
||||
_miscEntries.push_back(rec);
|
||||
}
|
||||
}
|
||||
|
||||
delete miscStream;
|
||||
@ -257,7 +291,7 @@ void Animation::load(UserInterface &interfaceSurface, MSurface &depthSurface,
|
||||
|
||||
// If the animation specifies a font, then load it for access
|
||||
delete _font;
|
||||
if (_header._flags & ANIM_CUSTOM_FONT) {
|
||||
if (_header._flags & ANIMFLAG_CUSTOM_FONT) {
|
||||
Common::String fontName = "*" + _header._fontResource;
|
||||
_font = _vm->_font->getFont(fontName.c_str());
|
||||
} else {
|
||||
|
@ -33,7 +33,12 @@
|
||||
|
||||
namespace MADS {
|
||||
|
||||
enum AnimFlag { ANIM_CUSTOM_FONT = 0x20 };
|
||||
enum AnimFlag {
|
||||
ANIMFLAG_DITHER = 0x0001, // Dither to 16 colors
|
||||
ANIMFLAG_CUSTOM_FONT = 0x0020, // Load ccustom font
|
||||
ANIMFLAG_LOAD_BACKGROUND = 0x0100, // Load background
|
||||
ANIMFLAG_LOAD_BACKGROUND_ONLY = 0x0200 // Load background only
|
||||
};
|
||||
|
||||
class MADSEngine;
|
||||
class Scene;
|
||||
@ -63,7 +68,7 @@ public:
|
||||
/**
|
||||
* Loads data for the record
|
||||
*/
|
||||
void load(Common::SeekableReadStream *f);
|
||||
void load(Common::SeekableReadStream *f, bool uiFlag);
|
||||
};
|
||||
|
||||
class AnimMiscEntry {
|
||||
@ -80,6 +85,26 @@ public:
|
||||
void load(Common::SeekableReadStream *f);
|
||||
};
|
||||
|
||||
#define ANIM_SPAWN_COUNT 2
|
||||
|
||||
class AnimUIEntry {
|
||||
public:
|
||||
int _probability;
|
||||
int _imageCount;
|
||||
int _firstImage;
|
||||
int _lastImage;
|
||||
int _counter;
|
||||
int _spawn[ANIM_SPAWN_COUNT];
|
||||
int _spawnFrame[ANIM_SPAWN_COUNT];
|
||||
int _sound;
|
||||
int _soundFrame;
|
||||
|
||||
/**
|
||||
* Loads the data for the record
|
||||
*/
|
||||
void load(Common::SeekableReadStream *f);
|
||||
};
|
||||
|
||||
class AAHeader {
|
||||
public:
|
||||
int _spriteSetsCount;
|
||||
@ -115,7 +140,6 @@ private:
|
||||
|
||||
Common::Array<int> _spriteListIndexes;
|
||||
Common::Array<AnimMessage> _messages;
|
||||
Common::Array<AnimFrameEntry> _frameEntries;
|
||||
Common::Array<AnimMiscEntry> _miscEntries;
|
||||
Common::Array<SpriteAsset *> _spriteSets;
|
||||
Font *_font;
|
||||
@ -153,6 +177,8 @@ private:
|
||||
protected:
|
||||
Animation(MADSEngine *vm, Scene *scene);
|
||||
public:
|
||||
Common::Array<AnimFrameEntry> _frameEntries;
|
||||
Common::Array<AnimUIEntry> _uiEntries;
|
||||
bool _resetFlag;
|
||||
|
||||
static Animation *init(MADSEngine *vm, Scene *scene);
|
||||
|
@ -52,7 +52,6 @@ Game::Game(MADSEngine *vm): _vm(vm), _surface(nullptr), _objects(vm),
|
||||
_priorSectionNumber = 0;
|
||||
_currentSectionNumber = -1;
|
||||
_kernelMode = KERNEL_GAME_LOAD;
|
||||
_v2 = 0;
|
||||
_quoteEmergency = false;
|
||||
_vocabEmergency = false;
|
||||
_aaName = "*I0.AA";
|
||||
|
@ -131,7 +131,6 @@ public:
|
||||
VisitedScenes _visitedScenes;
|
||||
Scene _scene;
|
||||
KernelMode _kernelMode;
|
||||
int _v2;
|
||||
int _trigger;
|
||||
ScreenTransition _fx;
|
||||
TriggerMode _triggerMode;
|
||||
|
@ -43,6 +43,7 @@ MADSEngine::MADSEngine(OSystem *syst, const MADSGameDescription *gameDesc) :
|
||||
_textWindowStill = false;
|
||||
_screenFade = SCREEN_FADE_SMOOTH;
|
||||
_musicFlag = false;
|
||||
_dithering = false;
|
||||
|
||||
_debugger = nullptr;
|
||||
_dialogs = nullptr;
|
||||
|
@ -104,6 +104,7 @@ public:
|
||||
bool _textWindowStill;
|
||||
ScreenFade _screenFade;
|
||||
bool _musicFlag;
|
||||
bool _dithering;
|
||||
public:
|
||||
MADSEngine(OSystem *syst, const MADSGameDescription *gameDesc);
|
||||
virtual ~MADSEngine();
|
||||
|
@ -32,6 +32,19 @@ class MADSEngine;
|
||||
|
||||
#define PALETTE_USAGE_COUNT 4
|
||||
|
||||
/**
|
||||
* Palette mapping options
|
||||
*/
|
||||
enum {
|
||||
PALFLAG_BACKGROUND = 0x8000, // Loading initial background
|
||||
PALFLAG_RESERVED = 0x4000, // Enable mapping reserved colors
|
||||
PALFLAG_ANY_TO_CLOSEST = 0x2000, // Any color can map to closest
|
||||
PALFLAG_ALL_TO_CLOSEST = 0x1000, // Any colors that can map must map
|
||||
PALFLAG_TOP_COLORS = 0x0800, // Allow mapping to high four colors
|
||||
PALFLAG_DEFINE_RESERVED = 0x0400, // Define initial reserved color
|
||||
PALFLAG_MASK = 0xfc00 // Mask for all the palette flags
|
||||
};
|
||||
|
||||
struct RGB4 {
|
||||
byte r;
|
||||
byte g;
|
||||
|
@ -123,8 +123,12 @@ void Scene::loadScene(int sceneId, const Common::String &prefix, bool palFlag) {
|
||||
_kernelMessages.clear();
|
||||
|
||||
// TODO: palletteUsage reset? setPalette(_nullPalette);
|
||||
int flags = SCENEFLAG_LOAD_SHADOW;
|
||||
if (_vm->_dithering)
|
||||
flags |= SCENEFLAG_DITHER;
|
||||
|
||||
_sceneInfo = SceneInfo::init(_vm);
|
||||
_sceneInfo->load(_currentSceneId, _variant, Common::String(), _vm->_game->_v2 ? 17 : 16,
|
||||
_sceneInfo->load(_currentSceneId, _variant, Common::String(), flags,
|
||||
_depthSurface, _backgroundSurface);
|
||||
|
||||
// Initialise palette animation for the scene
|
||||
@ -143,10 +147,12 @@ void Scene::loadScene(int sceneId, const Common::String &prefix, bool palFlag) {
|
||||
_vm->_palette->_paletteUsage.load(1, 0xF);
|
||||
|
||||
// Load interface
|
||||
int flags = _vm->_game->_v2 ? 0x4101 : 0x4100;
|
||||
if (!_vm->_textWindowStill)
|
||||
flags |= 0x200;
|
||||
|
||||
flags = PALFLAG_RESERVED | ANIMFLAG_LOAD_BACKGROUND;
|
||||
if (_vm->_dithering)
|
||||
flags |= ANIMFLAG_DITHER;
|
||||
if (_vm->_textWindowStill)
|
||||
flags |= ANIMFLAG_LOAD_BACKGROUND_ONLY;
|
||||
|
||||
_animationData = Animation::init(_vm, this);
|
||||
MSurface depthSurface;
|
||||
_animationData->load(_userInterface, depthSurface, prefix, flags, nullptr, nullptr);
|
||||
@ -513,7 +519,7 @@ void Scene::loadAnimation(const Common::String &resName, int abortTimers) {
|
||||
|
||||
_activeAnimation = Animation::init(_vm, this);
|
||||
_activeAnimation->load(interfaceSurface, depthSurface, resName,
|
||||
_vm->_game->_v2 ? 1 : 0, nullptr, nullptr);
|
||||
_vm->_dithering ? ANIMFLAG_DITHER : 0, nullptr, nullptr);
|
||||
_activeAnimation->startAnimation(abortTimers);
|
||||
}
|
||||
|
||||
@ -585,8 +591,4 @@ void Scene::resetScene() {
|
||||
_sequences.clear();
|
||||
}
|
||||
|
||||
void Scene::backgroundAnimation() {
|
||||
warning("TODO: Scene::backgroundAnimation");
|
||||
}
|
||||
|
||||
} // End of namespace MADS
|
||||
|
@ -213,8 +213,6 @@ public:
|
||||
|
||||
void resetScene();
|
||||
|
||||
void backgroundAnimation();
|
||||
|
||||
/**
|
||||
* Removes all the scene specific sprites fromt the sprites list,
|
||||
* leaving any player sprites list in place at the start of the list.
|
||||
|
@ -52,6 +52,11 @@ class SpriteSlot;
|
||||
#define TEXT_DISPLAY_MAX_SIZE 40
|
||||
#define DIRTY_AREAS_SIZE (SPRITE_SLOTS_MAX_SIZE + TEXT_DISPLAY_MAX_SIZE)
|
||||
|
||||
enum {
|
||||
SCENEFLAG_DITHER = 0x01, // Dither to 16 colors
|
||||
SCENEFLAG_LOAD_SHADOW = 0x10 // Load hard shadows
|
||||
};
|
||||
|
||||
class VerbInit {
|
||||
public:
|
||||
int _id;
|
||||
|
@ -354,10 +354,10 @@ void ScreenObjects::check(bool scanFlag) {
|
||||
slot._flags = IMG_ERASE;
|
||||
}
|
||||
|
||||
// Any background animation
|
||||
scene.backgroundAnimation();
|
||||
// Any background animation in the user interface
|
||||
userInterface.doBackgroundAnimation();
|
||||
|
||||
// Handle animating the selected inventory animation
|
||||
// Handle animating the selected inventory item
|
||||
userInterface.inventoryAnim();
|
||||
|
||||
// Set the base time
|
||||
|
@ -48,7 +48,7 @@ void UISlots::add(const Common::Point &pt, int frameNumber, int spritesIndex) {
|
||||
assert(size() < 50);
|
||||
|
||||
UISlot ie;
|
||||
ie._flags = -3;
|
||||
ie._flags = IMG_OVERPRINT;
|
||||
ie._segmentId = IMG_TEXT_UPDATE;
|
||||
ie._position = pt;
|
||||
ie._frameNumber = frameNumber;
|
||||
@ -57,6 +57,20 @@ void UISlots::add(const Common::Point &pt, int frameNumber, int spritesIndex) {
|
||||
push_back(ie);
|
||||
}
|
||||
|
||||
void UISlots::add(const AnimFrameEntry &frameEntry) {
|
||||
assert(size() < 50);
|
||||
|
||||
UISlot ie;
|
||||
ie._flags = IMG_UPDATE;
|
||||
ie._segmentId = frameEntry._seqIndex;
|
||||
ie._spritesIndex = frameEntry._spriteSlot._spritesIndex;
|
||||
ie._frameNumber = frameEntry._frameNumber;
|
||||
ie._position = frameEntry._spriteSlot._position;
|
||||
|
||||
push_back(ie);
|
||||
}
|
||||
|
||||
|
||||
void UISlots::draw(bool updateFlag, bool delFlag) {
|
||||
Scene &scene = _vm->_game->_scene;
|
||||
UserInterface &userInterface = scene._userInterface;
|
||||
@ -633,6 +647,66 @@ void UserInterface::inventoryAnim() {
|
||||
_uiSlots.push_back(slot);
|
||||
}
|
||||
|
||||
void UserInterface::doBackgroundAnimation() {
|
||||
Scene &scene = _vm->_game->_scene;
|
||||
Common::Array<AnimUIEntry> &uiEntries = scene._animationData->_uiEntries;
|
||||
Common::Array<AnimFrameEntry> &frameEntries = scene._animationData->_frameEntries;
|
||||
|
||||
_noSegmentsActive = !_someSegmentsActive;
|
||||
_someSegmentsActive = false;
|
||||
|
||||
for (int idx = 0; idx < uiEntries.size(); ++idx) {
|
||||
AnimUIEntry &uiEntry = uiEntries[idx];
|
||||
|
||||
if (uiEntry._counter < 0) {
|
||||
if (uiEntry._counter == -1) {
|
||||
int probabilityRandom = _vm->getRandomNumber(1, 30000);
|
||||
int probability = uiEntry._probability;
|
||||
if (uiEntry._probability > 30000) {
|
||||
if (_noSegmentsActive) {
|
||||
probability -= 30000;
|
||||
} else {
|
||||
probability = -1;
|
||||
}
|
||||
}
|
||||
if (probabilityRandom <= probability) {
|
||||
uiEntry._counter = uiEntry._firstImage;
|
||||
_someSegmentsActive = true;
|
||||
}
|
||||
} else {
|
||||
uiEntry._counter = uiEntry._firstImage;
|
||||
_someSegmentsActive = true;
|
||||
}
|
||||
} else {
|
||||
for (int idx2 = 0; idx2 < ANIM_SPAWN_COUNT; idx2++) {
|
||||
if (uiEntry._spawnFrame[idx2] == (uiEntry._counter - uiEntry._firstImage)) {
|
||||
int tempIndex = uiEntry._spawn[idx2];
|
||||
if (idx >= tempIndex) {
|
||||
uiEntries[tempIndex]._counter = uiEntries[tempIndex]._firstImage;
|
||||
} else {
|
||||
uiEntries[tempIndex]._counter = -2;
|
||||
}
|
||||
_someSegmentsActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
++uiEntry._counter;
|
||||
if (uiEntry._counter > uiEntry._lastImage) {
|
||||
uiEntry._counter = -1;
|
||||
} else {
|
||||
_someSegmentsActive = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int idx = 0; idx < uiEntries.size(); ++idx) {
|
||||
int imgScan = uiEntries[idx]._counter;
|
||||
if (imgScan >= 0) {
|
||||
_uiSlots.add(frameEntries[imgScan]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UserInterface::categoryChanged() {
|
||||
_highlightedItemIndex = -1;
|
||||
_vm->_events->initVars();
|
||||
|
@ -33,6 +33,8 @@ namespace MADS {
|
||||
|
||||
enum { IMG_SPINNING_OBJECT = 200, IMG_TEXT_UPDATE = 201 };
|
||||
|
||||
class AnimFrameEntry;
|
||||
|
||||
class UISlot {
|
||||
public:
|
||||
int _flags;
|
||||
@ -61,6 +63,11 @@ public:
|
||||
*/
|
||||
void add(const Common::Point &pt, int frameNumber, int spritesIndex);
|
||||
|
||||
/**
|
||||
* Loads the data from an aimation frame entry
|
||||
*/
|
||||
void add(const AnimFrameEntry &frameEntry);
|
||||
|
||||
/**
|
||||
* Adds a special entry for full refresh of the user interface
|
||||
*/
|
||||
@ -83,6 +90,8 @@ private:
|
||||
int _invFrameNumber;
|
||||
uint32 _scrollMilli;
|
||||
bool _scrollFlag;
|
||||
int _noSegmentsActive;
|
||||
int _someSegmentsActive;
|
||||
|
||||
/**
|
||||
* Loads the elements of the user interface
|
||||
@ -182,6 +191,11 @@ public:
|
||||
*/
|
||||
void noInventoryAnim();
|
||||
|
||||
/**
|
||||
* Handles any animation that occurs in the background of the user interface
|
||||
*/
|
||||
void doBackgroundAnimation();
|
||||
|
||||
/**
|
||||
* Handles queuing a new frame of an inventory animation for drawing
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user