mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-22 01:39:57 +00:00
MYST3: Add transition support
This commit is contained in:
parent
7712eb6c5e
commit
4d5d5d6a81
@ -260,7 +260,7 @@ bool Console::Cmd_Go(int argc, const char **argv) {
|
||||
_vm->_state->setLocationNextRoom(roomID);
|
||||
_vm->_state->setLocationNextNode(nodeId);
|
||||
|
||||
_vm->goToNode(0, 1);
|
||||
_vm->goToNode(0, kTransitionFade);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ void Inventory::openBook(uint16 age, uint16 room, uint16 node) {
|
||||
|
||||
_vm->_state->setLocationNextAge(age);
|
||||
_vm->_state->setLocationNextRoom(room);
|
||||
_vm->goToNode(node, 1);
|
||||
_vm->goToNode(node, kTransitionFade);
|
||||
}
|
||||
|
||||
void Inventory::addSaavedroChapter(uint16 var) {
|
||||
|
@ -142,7 +142,7 @@ void Menu::goToNode(uint16 node) {
|
||||
_vm->_state->setMenuEscapePressed(0);
|
||||
_vm->_state->setLocationNextAge(9);
|
||||
_vm->_state->setLocationNextRoom(901);
|
||||
_vm->goToNode(node, 2);
|
||||
_vm->goToNode(node, kTransitionNone);
|
||||
}
|
||||
|
||||
Dialog::Dialog(Myst3Engine *vm, uint id):
|
||||
@ -330,7 +330,7 @@ void Menu::loadMenuLoad() {
|
||||
_vm->_state->setMenuSavedRoom(0);
|
||||
_vm->_state->setMenuSavedNode(0);
|
||||
|
||||
_vm->goToNode(0, 1);
|
||||
_vm->goToNode(0, kTransitionFade);
|
||||
}
|
||||
|
||||
void Menu::saveMenuOpen() {
|
||||
|
@ -27,7 +27,8 @@ MODULE_OBJS := \
|
||||
script.o \
|
||||
sound.o \
|
||||
state.o \
|
||||
subtitles.o
|
||||
subtitles.o \
|
||||
transition.o
|
||||
|
||||
# This module can be built as a plugin
|
||||
ifeq ($(ENABLE_MYST3), DYNAMIC_PLUGIN)
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "engines/myst3/menu.h"
|
||||
#include "engines/myst3/sound.h"
|
||||
#include "engines/myst3/ambient.h"
|
||||
#include "engines/myst3/transition.h"
|
||||
|
||||
#include "image/jpeg.h"
|
||||
|
||||
@ -500,7 +501,7 @@ void Myst3Engine::processInput(bool lookOnly) {
|
||||
}
|
||||
}
|
||||
|
||||
void Myst3Engine::drawFrame() {
|
||||
void Myst3Engine::drawFrame(bool noSwap) {
|
||||
_sound->update();
|
||||
_gfx->clear();
|
||||
|
||||
@ -573,9 +574,11 @@ void Myst3Engine::drawFrame() {
|
||||
if (_cursor->isVisible())
|
||||
_cursor->draw();
|
||||
|
||||
_system->updateScreen();
|
||||
_system->delayMillis(10);
|
||||
_state->updateFrameCounters();
|
||||
if (!noSwap) {
|
||||
_system->updateScreen();
|
||||
_system->delayMillis(10);
|
||||
_state->updateFrameCounters();
|
||||
}
|
||||
}
|
||||
|
||||
bool Myst3Engine::isInventoryVisible() {
|
||||
@ -588,7 +591,7 @@ bool Myst3Engine::isInventoryVisible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Myst3Engine::goToNode(uint16 nodeID, uint transition) {
|
||||
void Myst3Engine::goToNode(uint16 nodeID, TransitionType transitionType) {
|
||||
uint16 node = _state->getLocationNextNode();
|
||||
if (node == 0)
|
||||
node = nodeID;
|
||||
@ -596,7 +599,10 @@ void Myst3Engine::goToNode(uint16 nodeID, uint transition) {
|
||||
uint16 room = _state->getLocationNextRoom();
|
||||
uint16 age = _state->getLocationNextAge();
|
||||
|
||||
if (_state->getViewType() == kCube) {
|
||||
Transition *transition = Transition::initialize(this, transitionType);
|
||||
|
||||
ViewType sourceViewType = _state->getViewType();
|
||||
if (sourceViewType == kCube) {
|
||||
// The lookat direction in the next node should be
|
||||
// the direction of the mouse cursor
|
||||
float pitch, heading;
|
||||
@ -613,6 +619,11 @@ void Myst3Engine::goToNode(uint16 nodeID, uint transition) {
|
||||
if (_state->getAmbiantPreviousFadeOutDelay() > 0) {
|
||||
_ambient->playCurrentNode(100, _state->getAmbiantPreviousFadeOutDelay());
|
||||
}
|
||||
|
||||
if (transition) {
|
||||
transition->draw();
|
||||
delete transition;
|
||||
}
|
||||
}
|
||||
|
||||
void Myst3Engine::loadNode(uint16 nodeID, uint32 roomID, uint32 ageID) {
|
||||
@ -1180,7 +1191,7 @@ Common::Error Myst3Engine::loadGameState(int slot) {
|
||||
_state->setMenuSavedRoom(0);
|
||||
_state->setMenuSavedNode(0);
|
||||
|
||||
goToNode(0, 1);
|
||||
goToNode(0, kTransitionFade);
|
||||
return Common::kNoError;
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,14 @@ enum {
|
||||
kDebugScript = (1 << 3)
|
||||
};
|
||||
|
||||
enum TransitionType {
|
||||
kTransitionFade = 1,
|
||||
kTransitionNone,
|
||||
kTransitionZip,
|
||||
kTransitionLeftToRight,
|
||||
kTransitionRightToLeft
|
||||
};
|
||||
|
||||
class Console;
|
||||
class GameState;
|
||||
class HotSpot;
|
||||
@ -123,7 +131,7 @@ public:
|
||||
Graphics::Surface *loadTexture(uint16 id);
|
||||
static Graphics::Surface *decodeJpeg(const DirectorySubEntry *jpegDesc);
|
||||
|
||||
void goToNode(uint16 nodeID, uint transition);
|
||||
void goToNode(uint16 nodeID, TransitionType transition);
|
||||
void loadNode(uint16 nodeID, uint32 roomID = 0, uint32 ageID = 0);
|
||||
void unloadNode();
|
||||
void loadNodeCubeFaces(uint16 nodeID);
|
||||
@ -161,7 +169,7 @@ public:
|
||||
void getMovieLookAt(uint16 id, bool start, float &pitch, float &heading);
|
||||
|
||||
void processInput(bool lookOnly);
|
||||
void drawFrame();
|
||||
void drawFrame(bool noSwap = false);
|
||||
|
||||
bool inputValidatePressed();
|
||||
bool inputEscapePressed();
|
||||
@ -208,6 +216,9 @@ private:
|
||||
|
||||
bool isInventoryVisible();
|
||||
|
||||
void transitionDraw(TransitionType type, Graphics::Surface *source);
|
||||
void transitionDrawStep(TransitionType type, uint32 *target, uint targetPitch, uint32 *source, uint sourcePitch, uint32 *destination, uint destinationPitch, uint destinationHeight, uint completion);
|
||||
|
||||
friend class Console;
|
||||
};
|
||||
|
||||
|
@ -1898,19 +1898,19 @@ void Script::chooseNextNode(Context &c, const Opcode &cmd) {
|
||||
void Script::goToNodeTransition(Context &c, const Opcode &cmd) {
|
||||
debugC(kDebugScript, "Opcode %d: Go to node %d with transition %d", cmd.op, cmd.args[0], cmd.args[1]);
|
||||
|
||||
_vm->goToNode(cmd.args[0], cmd.args[1]);
|
||||
_vm->goToNode(cmd.args[0], static_cast<TransitionType>(cmd.args[1]));
|
||||
}
|
||||
|
||||
void Script::goToNodeTrans2(Context &c, const Opcode &cmd) {
|
||||
debugC(kDebugScript, "Opcode %d: Go to node %d", cmd.op, cmd.args[0]);
|
||||
|
||||
_vm->goToNode(cmd.args[0], 2);
|
||||
_vm->goToNode(cmd.args[0], kTransitionNone);
|
||||
}
|
||||
|
||||
void Script::goToNodeTrans1(Context &c, const Opcode &cmd) {
|
||||
debugC(kDebugScript, "Opcode %d: Go to node %d", cmd.op, cmd.args[0]);
|
||||
|
||||
_vm->goToNode(cmd.args[0], 1);
|
||||
_vm->goToNode(cmd.args[0], kTransitionFade);
|
||||
}
|
||||
|
||||
void Script::goToRoomNode(Context &c, const Opcode &cmd) {
|
||||
@ -1919,13 +1919,13 @@ void Script::goToRoomNode(Context &c, const Opcode &cmd) {
|
||||
_vm->_state->setLocationNextRoom(cmd.args[0]);
|
||||
_vm->_state->setLocationNextNode(cmd.args[1]);
|
||||
|
||||
_vm->goToNode(0, 1);
|
||||
_vm->goToNode(0, kTransitionFade);
|
||||
}
|
||||
|
||||
void Script::zipToNode(Context &c, const Opcode &cmd) {
|
||||
debugC(kDebugScript, "Opcode %d: Zip to node %d", cmd.op, cmd.args[0]);
|
||||
|
||||
_vm->goToNode(cmd.args[0], 3);
|
||||
_vm->goToNode(cmd.args[0], kTransitionZip);
|
||||
}
|
||||
|
||||
void Script::zipToRoomNode(Context &c, const Opcode &cmd) {
|
||||
@ -1934,7 +1934,7 @@ void Script::zipToRoomNode(Context &c, const Opcode &cmd) {
|
||||
_vm->_state->setLocationNextRoom(cmd.args[0]);
|
||||
_vm->_state->setLocationNextNode(cmd.args[1]);
|
||||
|
||||
_vm->goToNode(0, 3);
|
||||
_vm->goToNode(0, kTransitionZip);
|
||||
}
|
||||
|
||||
void Script::reloadNode(Context &c, const Opcode &cmd) {
|
||||
|
@ -204,6 +204,8 @@ GameState::GameState(Myst3Engine *vm):
|
||||
|
||||
VAR(185, CameraMoveSpeed, false)
|
||||
|
||||
VAR(187, TransitionSound, false)
|
||||
VAR(188, TransitionSoundVolume, false)
|
||||
VAR(189, LocationNextNode, false)
|
||||
VAR(190, LocationNextRoom, false)
|
||||
VAR(191, LocationNextAge, false)
|
||||
|
@ -176,6 +176,9 @@ public:
|
||||
|
||||
DECLARE_VAR(185, CameraMoveSpeed)
|
||||
|
||||
DECLARE_VAR(187, TransitionSound)
|
||||
DECLARE_VAR(188, TransitionSoundVolume)
|
||||
|
||||
DECLARE_VAR(189, LocationNextNode)
|
||||
DECLARE_VAR(190, LocationNextRoom)
|
||||
DECLARE_VAR(191, LocationNextAge)
|
||||
|
206
engines/myst3/transition.cpp
Normal file
206
engines/myst3/transition.cpp
Normal file
@ -0,0 +1,206 @@
|
||||
/* 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 "common/config-manager.h"
|
||||
|
||||
#include "engines/myst3/transition.h"
|
||||
#include "engines/myst3/sound.h"
|
||||
#include "engines/myst3/state.h"
|
||||
|
||||
#include "graphics/colormasks.h"
|
||||
|
||||
namespace Myst3 {
|
||||
|
||||
Transition *Transition::initialize(Myst3Engine *vm, TransitionType type) {
|
||||
return new Transition(vm, type);
|
||||
}
|
||||
|
||||
Transition::Transition(Myst3Engine *vm, TransitionType type) :
|
||||
_vm(vm),
|
||||
_type(type),
|
||||
_sourceScreenshot(nullptr) {
|
||||
|
||||
// Capture a screenshot of the source node
|
||||
if (type != kTransitionNone && computeDuration() != 0) {
|
||||
_sourceScreenshot = _vm->_gfx->getScreenshot();
|
||||
}
|
||||
}
|
||||
|
||||
Transition::~Transition() {
|
||||
if (_sourceScreenshot) {
|
||||
_sourceScreenshot->free();
|
||||
delete _sourceScreenshot;
|
||||
}
|
||||
}
|
||||
|
||||
int Transition::computeDuration() {
|
||||
int durationFrames = 30 * (100 - ConfMan.getInt("transition_speed")) / 100;
|
||||
if (_type == kTransitionZip) {
|
||||
durationFrames >>= 1;
|
||||
}
|
||||
return durationFrames;
|
||||
}
|
||||
|
||||
void Transition::playSound() {
|
||||
if (_vm->_state->getTransitionSound()) {
|
||||
_vm->_sound->playEffect(_vm->_state->getTransitionSound(),
|
||||
_vm->_state->getTransitionSoundVolume());
|
||||
}
|
||||
_vm->_state->setTransitionSound(0);
|
||||
}
|
||||
|
||||
void Transition::draw() {
|
||||
// Play the transition sound
|
||||
playSound();
|
||||
|
||||
// Got any transition to draw?
|
||||
if (!_sourceScreenshot) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Capture a screenshot of the destination node
|
||||
_vm->drawFrame(true);
|
||||
Graphics::Surface *target = _vm->_gfx->getScreenshot();
|
||||
|
||||
// Create the temporary surface and texture for the transition
|
||||
Graphics::Surface *frame = new Graphics::Surface();
|
||||
frame->create(target->w, target->h, target->format);
|
||||
Common::Rect frameRect = Common::Rect(frame->w, frame->h);
|
||||
|
||||
Texture *frameTexture = _vm->_gfx->createTexture(frame);
|
||||
|
||||
// Compute the start and end frames for the animation
|
||||
int durationFrames = computeDuration();
|
||||
int startFrame = _vm->_state->getFrameCount();
|
||||
uint endFrame = startFrame + durationFrames;
|
||||
|
||||
// Draw each step until completion
|
||||
int completion = 0;
|
||||
while (_vm->_state->getFrameCount() <= endFrame || completion < 100) {
|
||||
completion = CLIP<int>(100 * (_vm->_state->getFrameCount() - startFrame) / durationFrames, 0, 100);
|
||||
|
||||
uint32 *targetPtr = (uint32 *)target->getPixels();
|
||||
uint32 *sourcePtr = (uint32 *)_sourceScreenshot->getPixels();
|
||||
uint32 *framePtr = (uint32 *)frame->getPixels();
|
||||
drawStep(targetPtr, target->pitch, sourcePtr, _sourceScreenshot->pitch, framePtr, frame->pitch, frame->h, completion);
|
||||
|
||||
frameTexture->update(frame);
|
||||
_vm->_gfx->drawTexturedRect2D(frameRect, frameRect, frameTexture);
|
||||
|
||||
g_system->updateScreen();
|
||||
g_system->delayMillis(10);
|
||||
_vm->_state->updateFrameCounters();
|
||||
}
|
||||
|
||||
_vm->_gfx->freeTexture(frameTexture);
|
||||
|
||||
frame->free();
|
||||
delete frame;
|
||||
|
||||
target->free();
|
||||
delete target;
|
||||
}
|
||||
|
||||
void Transition::drawStep(uint32 *target, uint targetPitch, uint32 *source, uint sourcePitch, uint32 *destination, uint destinationPitch, uint destinationHeight, uint completion) {
|
||||
switch (_type) {
|
||||
case kTransitionNone:
|
||||
break;
|
||||
|
||||
case kTransitionFade:
|
||||
case kTransitionZip: {
|
||||
|
||||
for (uint y = 0; y < destinationHeight; y++) {
|
||||
uint32 *sourcePtr = source + (destinationHeight - y - 1) * (sourcePitch / 4);
|
||||
uint32 *targetPtr = target + (destinationHeight - y - 1) * (targetPitch / 4);
|
||||
uint32 *destinationPtr = destination;
|
||||
|
||||
for (uint x = 0; x < 640; x++) {
|
||||
byte sourceR, sourceG, sourceB;
|
||||
byte targetR, targetG, targetB;
|
||||
byte destR, destG, destB;
|
||||
|
||||
Graphics::colorToRGB< Graphics::ColorMasks<8888> >(*sourcePtr++, sourceR, sourceG, sourceB);
|
||||
Graphics::colorToRGB< Graphics::ColorMasks<8888> >(*targetPtr++, targetR, targetG, targetB);
|
||||
|
||||
// TODO: optimize ?
|
||||
destR = sourceR * (100 - completion) / 100 + targetR * completion / 100;
|
||||
destG = sourceG * (100 - completion) / 100 + targetG * completion / 100;
|
||||
destB = sourceB * (100 - completion) / 100 + targetB * completion / 100;
|
||||
|
||||
*destinationPtr++ = Graphics::RGBToColor< Graphics::ColorMasks<8888> >(destR, destG, destB);
|
||||
}
|
||||
|
||||
destination += (destinationPitch / 4);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kTransitionLeftToRight: {
|
||||
uint transitionX = (640 * 100 - 640 * completion) / 100;
|
||||
for (uint y = 0; y < destinationHeight; y++) {
|
||||
uint32 *sourcePtr = source + (destinationHeight - y - 1) * (sourcePitch / 4);
|
||||
uint32 *destinationPtr = destination;
|
||||
|
||||
for (uint x = 0; x < transitionX; x++) {
|
||||
*destinationPtr = *sourcePtr;
|
||||
destinationPtr++;
|
||||
sourcePtr++;
|
||||
}
|
||||
|
||||
uint32 *targetPtr = target + (destinationHeight - y - 1) * (targetPitch / 4) + transitionX;
|
||||
for (uint x = transitionX; x < 640; x++) {
|
||||
*destinationPtr = *targetPtr;
|
||||
destinationPtr++;
|
||||
targetPtr++;
|
||||
}
|
||||
|
||||
destination += (destinationPitch / 4);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case kTransitionRightToLeft: {
|
||||
uint transitionX = 640 * completion / 100;
|
||||
for (uint y = 0; y < destinationHeight; y++) {
|
||||
uint32 *targetPtr = target + (destinationHeight - y - 1) * (targetPitch / 4);
|
||||
uint32 *destinationPtr = destination;
|
||||
|
||||
for (uint x = 0; x < transitionX; x++) {
|
||||
*destinationPtr = *targetPtr;
|
||||
destinationPtr++;
|
||||
targetPtr++;
|
||||
}
|
||||
|
||||
uint32 *sourcePtr = source + (destinationHeight - y - 1) * (sourcePitch / 4) + transitionX;
|
||||
for (uint x = transitionX; x < 640; x++) {
|
||||
*destinationPtr = *sourcePtr;
|
||||
destinationPtr++;
|
||||
sourcePtr++;
|
||||
}
|
||||
|
||||
destination += (destinationPitch / 4);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /* namespace Myst3 */
|
51
engines/myst3/transition.h
Normal file
51
engines/myst3/transition.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* 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 TRANSITION_H_
|
||||
#define TRANSITION_H_
|
||||
|
||||
#include "engines/myst3/myst3.h"
|
||||
|
||||
namespace Myst3 {
|
||||
|
||||
class Transition {
|
||||
public:
|
||||
static Transition *initialize(Myst3Engine *vm, TransitionType type);
|
||||
virtual ~Transition();
|
||||
|
||||
void draw();
|
||||
|
||||
private:
|
||||
Transition(Myst3Engine *vm, TransitionType type);
|
||||
void drawStep(uint32 *target, uint targetPitch, uint32 *source, uint sourcePitch, uint32 *destination, uint destinationPitch, uint destinationHeight, uint completion);
|
||||
int computeDuration();
|
||||
void playSound();
|
||||
|
||||
Myst3Engine *_vm;
|
||||
TransitionType _type;
|
||||
|
||||
Graphics::Surface *_sourceScreenshot;
|
||||
|
||||
};
|
||||
|
||||
} /* namespace Myst3 */
|
||||
#endif /* TRANSITION_H_ */
|
Loading…
Reference in New Issue
Block a user