MTROPOLIS: Move Print modifier from MTI to Standard

Although MTI had Print in its MTIKIT plugin, most of the content
from MTIKIT, including Print, is found in the EXTRAS and EXPRMNTL
plugins of many mtTropolis 1.1 titles.
This commit is contained in:
Michael 2024-08-14 23:52:48 +02:00 committed by Eric Lasota
parent 1d7b13c116
commit fb88427db6
8 changed files with 248 additions and 247 deletions

View File

@ -21,14 +21,6 @@
#include "common/file.h"
#include "common/random.h"
#include "common/translation.h"
#include "common/macresman.h"
#include "gui/dialog.h"
#include "gui/imagealbum-dialog.h"
#include "image/bmp.h"
#include "image/pict.h"
#include "mtropolis/plugin/mti.h"
#include "mtropolis/plugins.h"
@ -38,7 +30,6 @@
#include "video/mpegps_decoder.h"
#include "graphics/managed_surface.h"
#include "graphics/palette.h"
#include "common/file.h"
namespace MTropolis {
@ -413,191 +404,6 @@ const char *ShanghaiModifier::getDefaultName() const {
return "Shanghai Modifier"; // ???
}
class PrintModifierImageSupplier : public GUI::ImageAlbumImageSupplier {
public:
PrintModifierImageSupplier(const Common::String &inputPath, bool isMacVersion);
bool loadImageSlot(uint slot, const Graphics::Surface *&outSurface, bool &outHasPalette, Graphics::Palette &outPalette, GUI::ImageAlbumImageMetadata &outMetadata) override;
void releaseImageSlot(uint slot) override;
uint getNumSlots() const override;
Common::U32String getDefaultFileNameForSlot(uint slot) const override;
bool getFileFormatForImageSlot(uint slot, Common::FormatInfo::FormatID &outFormat) const override;
Common::SeekableReadStream *createReadStreamForSlot(uint slot) override;
private:
Common::String _path;
Common::SharedPtr<Image::ImageDecoder> _decoder;
bool _isMacVersion;
};
PrintModifierImageSupplier::PrintModifierImageSupplier(const Common::String &inputPath, bool isMacVersion) : _path(inputPath), _isMacVersion(isMacVersion) {
if (isMacVersion)
_decoder.reset(new Image::PICTDecoder());
else
_decoder.reset(new Image::BitmapDecoder());
}
bool PrintModifierImageSupplier::loadImageSlot(uint slot, const Graphics::Surface *&outSurface, bool &outHasPalette, Graphics::Palette &outPalette, GUI::ImageAlbumImageMetadata &outMetadata) {
Common::ScopedPtr<Common::SeekableReadStream> dataStream(createReadStreamForSlot(slot));
if (!dataStream)
return false;
if (!_decoder->loadStream(*dataStream)) {
warning("Failed to decode print file");
return false;
}
dataStream.reset();
outSurface = _decoder->getSurface();
outHasPalette = _decoder->hasPalette();
if (_decoder->hasPalette())
outPalette.set(_decoder->getPalette(), 0, _decoder->getPaletteColorCount());
outMetadata = GUI::ImageAlbumImageMetadata();
outMetadata._orientation = GUI::kImageAlbumImageOrientationLandscape;
outMetadata._viewTransformation = GUI::kImageAlbumViewTransformationRotate90CW;
return true;
}
void PrintModifierImageSupplier::releaseImageSlot(uint slot) {
_decoder->destroy();
}
uint PrintModifierImageSupplier::getNumSlots() const {
return 1;
}
Common::U32String PrintModifierImageSupplier::getDefaultFileNameForSlot(uint slot) const {
Common::String filename = _path;
size_t lastColonPos = filename.findLastOf(':');
if (lastColonPos != Common::String::npos)
filename = filename.substr(lastColonPos + 1);
size_t lastDotPos = filename.findLastOf('.');
if (lastDotPos != Common::String::npos)
filename = filename.substr(0, lastDotPos);
if (_isMacVersion)
filename += Common::U32String(".pict");
else
filename += Common::U32String(".bmp");
return filename.decode(Common::kASCII);
}
bool PrintModifierImageSupplier::getFileFormatForImageSlot(uint slot, Common::FormatInfo::FormatID &outFormat) const {
if (slot != 0)
return false;
if (_isMacVersion)
outFormat = Common::FormatInfo::kPICT;
else
outFormat = Common::FormatInfo::kBMP;
return true;
}
Common::SeekableReadStream *PrintModifierImageSupplier::createReadStreamForSlot(uint slot) {
if (slot != 0)
return nullptr;
size_t lastColonPos = _path.findLastOf(':');
Common::String filename;
if (lastColonPos == Common::String::npos)
filename = _path;
else
filename = _path.substr(lastColonPos + 1);
Common::Path path(Common::String("MPZ_MTI/") + filename);
if (_isMacVersion) {
// Color images have res fork data so we must load from the data fork
return Common::MacResManager::openFileOrDataFork(path);
} else {
// Win versions are just files
Common::File *f = new Common::File();
if (!f->open(path)) {
delete f;
return nullptr;
}
return f;
}
}
PrintModifier::PrintModifier() {
}
PrintModifier::~PrintModifier() {
}
bool PrintModifier::respondsToEvent(const Event &evt) const {
return _executeWhen.respondsTo(evt);
}
VThreadState PrintModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
if (_executeWhen.respondsTo(msg->getEvent())) {
PrintModifierImageSupplier imageSupplier(_filePath, runtime->getProject()->getPlatform() == kProjectPlatformMacintosh);
Common::ScopedPtr<GUI::Dialog> dialog(GUI::createImageAlbumDialog(_("Image Viewer"), &imageSupplier, 0));
dialog->runModal();
}
return kVThreadReturn;
}
void PrintModifier::disable(Runtime *runtime) {
}
MiniscriptInstructionOutcome PrintModifier::writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib) {
if (attrib == "showdialog") {
// This is only ever set to "false"
DynamicValueWriteDiscardHelper::create(writeProxy);
return kMiniscriptInstructionOutcomeContinue;
} else if (attrib == "filepath") {
DynamicValueWriteStringHelper::create(&_filePath, writeProxy);
return kMiniscriptInstructionOutcomeContinue;
}
return Modifier::writeRefAttribute(thread, writeProxy, attrib);
}
bool PrintModifier::load(const PlugInModifierLoaderContext &context, const Data::MTI::PrintModifier &data) {
if (data.executeWhen.type != Data::PlugInTypeTaggedValue::kEvent)
return false;
if (data.filePath.type != Data::PlugInTypeTaggedValue::kString)
return false;
_filePath = data.filePath.value.asString;
if (!_executeWhen.load(data.executeWhen.value.asEvent))
return false;
return true;
}
#ifdef MTROPOLIS_DEBUG_ENABLE
void PrintModifier::debugInspect(IDebugInspectionReport *report) const {
}
#endif
Common::SharedPtr<Modifier> PrintModifier::shallowClone() const {
return Common::SharedPtr<Modifier>(new PrintModifier(*this));
}
const char *PrintModifier::getDefaultName() const {
return "Print Modifier";
}
class MPEGVideoPlayer : public IPostEffect, public IPlayMediaSignalReceiver {
public:
explicit MPEGVideoPlayer(Runtime *runtime, const Common::SharedPtr<Video::VideoDecoder> &videoDecoder, IMPEGVideoCompletionNotifier *completionNotifier);
@ -777,12 +583,11 @@ void SampleModifier::stopPlaying() {
}
MTIPlugIn::MTIPlugIn()
: _shanghaiModifierFactory(this), _printModifierFactory(this), _sampleModifierFactory(this) {
: _shanghaiModifierFactory(this), _sampleModifierFactory(this) {
}
void MTIPlugIn::registerModifiers(IPlugInModifierRegistrar *registrar) const {
registrar->registerPlugInModifier("Shanghai", &_shanghaiModifierFactory);
registrar->registerPlugInModifier("Print", &_printModifierFactory);
registrar->registerPlugInModifier("Sample", &_sampleModifierFactory);
}

View File

@ -94,32 +94,6 @@ private:
int8 _tileAtCoordinate[kBoardSizeX][kBoardSizeY][kBoardSizeZ];
};
class PrintModifier : public Modifier {
public:
PrintModifier();
~PrintModifier();
bool respondsToEvent(const Event &evt) const override;
VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
void disable(Runtime *runtime) override;
MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib) override;
bool load(const PlugInModifierLoaderContext &context, const Data::MTI::PrintModifier &data);
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "Print Modifier"; }
void debugInspect(IDebugInspectionReport *report) const override;
#endif
private:
Common::SharedPtr<Modifier> shallowClone() const override;
const char *getDefaultName() const override;
Event _executeWhen;
Common::String _filePath;
};
class MPEGVideoPlayer;
class IMPEGVideoCompletionNotifier : IInterfaceBase {
@ -170,7 +144,6 @@ public:
private:
PlugInModifierFactory<ShanghaiModifier, Data::MTI::ShanghaiModifier> _shanghaiModifierFactory;
PlugInModifierFactory<PrintModifier, Data::MTI::PrintModifier> _printModifierFactory;
PlugInModifierFactory<SampleModifier, Data::MTI::SampleModifier> _sampleModifierFactory;
};

View File

@ -37,17 +37,6 @@ DataReadErrorCode ShanghaiModifier::load(PlugIn &plugIn, const PlugInModifier &p
return kDataReadErrorNone;
}
DataReadErrorCode PrintModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
if (prefix.plugInRevision != 0)
return kDataReadErrorUnsupportedRevision;
if (!executeWhen.load(reader) || !unknown1Bool.load(reader) || !unknown2Bool.load(reader) ||
!unknown3Bool.load(reader) || !filePath.load(reader) || !unknown4Bool.load(reader))
return kDataReadErrorReadFailed;
return kDataReadErrorNone;
}
DataReadErrorCode SampleModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
if (prefix.plugInRevision != 0)
return kDataReadErrorUnsupportedRevision;

View File

@ -41,18 +41,6 @@ protected:
DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
};
struct PrintModifier : public PlugInModifierData {
PlugInTypeTaggedValue executeWhen;
PlugInTypeTaggedValue unknown1Bool;
PlugInTypeTaggedValue unknown2Bool;
PlugInTypeTaggedValue unknown3Bool;
PlugInTypeTaggedValue filePath;
PlugInTypeTaggedValue unknown4Bool;
protected:
DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
};
struct SampleModifier : public PlugInModifierData {
PlugInTypeTaggedValue executeWhen;
PlugInTypeTaggedValue videoNumber;

View File

@ -22,6 +22,16 @@
#include "common/random.h"
#include "common/config-manager.h"
#include "common/file.h"
#include "common/macresman.h"
#include "common/translation.h"
#include "gui/dialog.h"
#include "gui/imagealbum-dialog.h"
#include "graphics/palette.h"
#include "image/bmp.h"
#include "image/pict.h"
#include "mtropolis/miniscript.h"
#include "mtropolis/plugin/standard.h"
@ -1523,6 +1533,191 @@ const char *FadeModifier::getDefaultName() const {
return "Fade Modifier"; // ???
}
class PrintModifierImageSupplier : public GUI::ImageAlbumImageSupplier {
public:
PrintModifierImageSupplier(const Common::String &inputPath, bool isMacVersion);
bool loadImageSlot(uint slot, const Graphics::Surface *&outSurface, bool &outHasPalette, Graphics::Palette &outPalette, GUI::ImageAlbumImageMetadata &outMetadata) override;
void releaseImageSlot(uint slot) override;
uint getNumSlots() const override;
Common::U32String getDefaultFileNameForSlot(uint slot) const override;
bool getFileFormatForImageSlot(uint slot, Common::FormatInfo::FormatID &outFormat) const override;
Common::SeekableReadStream *createReadStreamForSlot(uint slot) override;
private:
Common::String _path;
Common::SharedPtr<Image::ImageDecoder> _decoder;
bool _isMacVersion;
};
PrintModifierImageSupplier::PrintModifierImageSupplier(const Common::String &inputPath, bool isMacVersion) : _path(inputPath), _isMacVersion(isMacVersion) {
if (isMacVersion)
_decoder.reset(new Image::PICTDecoder());
else
_decoder.reset(new Image::BitmapDecoder());
}
bool PrintModifierImageSupplier::loadImageSlot(uint slot, const Graphics::Surface *&outSurface, bool &outHasPalette, Graphics::Palette &outPalette, GUI::ImageAlbumImageMetadata &outMetadata) {
Common::ScopedPtr<Common::SeekableReadStream> dataStream(createReadStreamForSlot(slot));
if (!dataStream)
return false;
if (!_decoder->loadStream(*dataStream)) {
warning("Failed to decode print file");
return false;
}
dataStream.reset();
outSurface = _decoder->getSurface();
outHasPalette = _decoder->hasPalette();
if (_decoder->hasPalette())
outPalette.set(_decoder->getPalette(), 0, _decoder->getPaletteColorCount());
outMetadata = GUI::ImageAlbumImageMetadata();
outMetadata._orientation = GUI::kImageAlbumImageOrientationLandscape;
outMetadata._viewTransformation = GUI::kImageAlbumViewTransformationRotate90CW;
return true;
}
void PrintModifierImageSupplier::releaseImageSlot(uint slot) {
_decoder->destroy();
}
uint PrintModifierImageSupplier::getNumSlots() const {
return 1;
}
Common::U32String PrintModifierImageSupplier::getDefaultFileNameForSlot(uint slot) const {
Common::String filename = _path;
size_t lastColonPos = filename.findLastOf(':');
if (lastColonPos != Common::String::npos)
filename = filename.substr(lastColonPos + 1);
size_t lastDotPos = filename.findLastOf('.');
if (lastDotPos != Common::String::npos)
filename = filename.substr(0, lastDotPos);
if (_isMacVersion)
filename += Common::U32String(".pict");
else
filename += Common::U32String(".bmp");
return filename.decode(Common::kASCII);
}
bool PrintModifierImageSupplier::getFileFormatForImageSlot(uint slot, Common::FormatInfo::FormatID &outFormat) const {
if (slot != 0)
return false;
if (_isMacVersion)
outFormat = Common::FormatInfo::kPICT;
else
outFormat = Common::FormatInfo::kBMP;
return true;
}
Common::SeekableReadStream *PrintModifierImageSupplier::createReadStreamForSlot(uint slot) {
if (slot != 0)
return nullptr;
size_t lastColonPos = _path.findLastOf(':');
Common::String filename;
if (lastColonPos == Common::String::npos)
filename = _path;
else
filename = _path.substr(lastColonPos + 1);
Common::Path path(Common::String("MPZ_MTI/") + filename);
if (_isMacVersion) {
// Color images have res fork data so we must load from the data fork
return Common::MacResManager::openFileOrDataFork(path);
} else {
// Win versions are just files
Common::File *f = new Common::File();
if (!f->open(path)) {
delete f;
return nullptr;
}
return f;
}
}
PrintModifier::PrintModifier() {
}
PrintModifier::~PrintModifier() {
}
bool PrintModifier::respondsToEvent(const Event &evt) const {
return _executeWhen.respondsTo(evt);
}
VThreadState PrintModifier::consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) {
if (_executeWhen.respondsTo(msg->getEvent())) {
PrintModifierImageSupplier imageSupplier(_filePath, runtime->getProject()->getPlatform() == kProjectPlatformMacintosh);
Common::ScopedPtr<GUI::Dialog> dialog(GUI::createImageAlbumDialog(_("Image Viewer"), &imageSupplier, 0));
dialog->runModal();
}
return kVThreadReturn;
}
void PrintModifier::disable(Runtime *runtime) {
}
MiniscriptInstructionOutcome PrintModifier::writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib) {
if (attrib == "showdialog") {
// This is only ever set to "false"
DynamicValueWriteDiscardHelper::create(writeProxy);
return kMiniscriptInstructionOutcomeContinue;
} else if (attrib == "filepath") {
DynamicValueWriteStringHelper::create(&_filePath, writeProxy);
return kMiniscriptInstructionOutcomeContinue;
}
return Modifier::writeRefAttribute(thread, writeProxy, attrib);
}
bool PrintModifier::load(const PlugInModifierLoaderContext &context, const Data::Standard::PrintModifier &data) {
if (data.executeWhen.type != Data::PlugInTypeTaggedValue::kEvent)
return false;
if (data.filePath.type != Data::PlugInTypeTaggedValue::kString)
return false;
_filePath = data.filePath.value.asString;
if (!_executeWhen.load(data.executeWhen.value.asEvent))
return false;
return true;
}
#ifdef MTROPOLIS_DEBUG_ENABLE
void PrintModifier::debugInspect(IDebugInspectionReport *report) const {
}
#endif
Common::SharedPtr<Modifier> PrintModifier::shallowClone() const {
return Common::SharedPtr<Modifier>(new PrintModifier(*this));
}
const char *PrintModifier::getDefaultName() const {
return "Print Modifier";
}
StandardPlugInHacks::StandardPlugInHacks() : allowGarbledListModData(false) {
}
@ -1534,7 +1729,8 @@ StandardPlugIn::StandardPlugIn()
, _listVarModifierFactory(this)
, _sysInfoModifierFactory(this)
, _panningModifierFactory(this)
, _fadeModifierFactory(this) {
, _fadeModifierFactory(this)
, _printModifierFactory(this) {
}
StandardPlugIn::~StandardPlugIn() {
@ -1547,6 +1743,7 @@ void StandardPlugIn::registerModifiers(IPlugInModifierRegistrar *registrar) cons
registrar->registerPlugInModifier("ObjRefP", &_objRefVarModifierFactory);
registrar->registerPlugInModifier("ListMod", &_listVarModifierFactory);
registrar->registerPlugInModifier("SysInfo", &_sysInfoModifierFactory);
registrar->registerPlugInModifier("Print", &_printModifierFactory);
registrar->registerPlugInModifier("panning", &_panningModifierFactory);
registrar->registerPlugInModifier("fade", &_fadeModifierFactory);

View File

@ -368,6 +368,31 @@ private:
const char *getDefaultName() const override;
};
class PrintModifier : public Modifier {
public:
PrintModifier();
~PrintModifier();
bool respondsToEvent(const Event &evt) const override;
VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr<MessageProperties> &msg) override;
void disable(Runtime *runtime) override;
MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib) override;
bool load(const PlugInModifierLoaderContext &context, const Data::Standard::PrintModifier &data);
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "Print Modifier"; }
void debugInspect(IDebugInspectionReport *report) const override;
#endif
private:
Common::SharedPtr<Modifier> shallowClone() const override;
const char *getDefaultName() const override;
Event _executeWhen;
Common::String _filePath;
};
class StandardPlugIn : public MTropolis::PlugIn {
public:
@ -388,6 +413,7 @@ private:
PlugInModifierFactory<SysInfoModifier, Data::Standard::SysInfoModifier> _sysInfoModifierFactory;
PlugInModifierFactory<PanningModifier, Data::Standard::PanningModifier> _panningModifierFactory;
PlugInModifierFactory<FadeModifier, Data::Standard::FadeModifier> _fadeModifierFactory;
PlugInModifierFactory<PrintModifier, Data::Standard::PrintModifier> _printModifierFactory;
StandardPlugInHacks _hacks;
};

View File

@ -198,6 +198,17 @@ DataReadErrorCode FadeModifier::load(PlugIn &plugIn, const PlugInModifier &prefi
return kDataReadErrorNone;
}
DataReadErrorCode PrintModifier::load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) {
if (prefix.plugInRevision != 0)
return kDataReadErrorUnsupportedRevision;
if (!executeWhen.load(reader) || !unknown1Bool.load(reader) || !unknown2Bool.load(reader) ||
!unknown3Bool.load(reader) || !filePath.load(reader) || !unknown4Bool.load(reader))
return kDataReadErrorReadFailed;
return kDataReadErrorNone;
}
} // End of namespace Standard
} // End of namespace Data

View File

@ -152,6 +152,18 @@ protected:
DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
};
struct PrintModifier : public PlugInModifierData {
PlugInTypeTaggedValue executeWhen;
PlugInTypeTaggedValue unknown1Bool;
PlugInTypeTaggedValue unknown2Bool;
PlugInTypeTaggedValue unknown3Bool;
PlugInTypeTaggedValue filePath;
PlugInTypeTaggedValue unknown4Bool;
protected:
DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
};
} // End of namespace Standard
} // End of namespace Data