/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* 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 3 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, see .
*
*/
#ifndef MTROPOLIS_PLUGIN_STANDARD_H
#define MTROPOLIS_PLUGIN_STANDARD_H
#include "mtropolis/modifiers.h"
#include "mtropolis/modifier_factory.h"
#include "mtropolis/runtime.h"
#include "mtropolis/plugin/standard_data.h"
namespace MTropolis {
class Runtime;
namespace Standard {
class StandardPlugIn;
class CursorModifier : public Modifier {
public:
CursorModifier();
bool load(const PlugInModifierLoaderContext &context, const Data::Standard::CursorModifier &data);
bool respondsToEvent(const Event &evt) const override;
VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr &msg) override;
void disable(Runtime *runtime) override;
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "Cursor Modifier"; }
SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
#endif
private:
Common::SharedPtr shallowClone() const override;
const char *getDefaultName() const override;
Event _applyWhen;
Event _removeWhen;
uint32 _cursorID;
};
// This appears to be basically a duplicate of scene transition modifier, except unlike that,
// its parameters are controllable via script, and the duration scaling appears to be different
// (probably 600000 max rate instead of 6000000)
class STransCtModifier : public Modifier {
public:
static const int32 kMaxDuration = 600000;
STransCtModifier();
bool load(const PlugInModifierLoaderContext &context, const Data::Standard::STransCtModifier &data);
bool respondsToEvent(const Event &evt) const override;
VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr &msg) override;
void disable(Runtime *runtime) override;
bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &result, const Common::String &attrib) override;
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "STransCt Scene Transition Modifier"; }
SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
#endif
private:
Common::SharedPtr shallowClone() const override;
const char *getDefaultName() const override;
MiniscriptInstructionOutcome scriptSetRate(MiniscriptThread *thread, const DynamicValue &value);
MiniscriptInstructionOutcome scriptSetSteps(MiniscriptThread *thread, const DynamicValue &value);
Event _enableWhen;
Event _disableWhen;
int32 _transitionType;
int32 _transitionDirection;
int32 _steps;
int32 _duration;
bool _fullScreen;
};
class MediaCueMessengerModifier : public Modifier, public IMediaCueModifier {
public:
MediaCueMessengerModifier();
~MediaCueMessengerModifier();
bool load(const PlugInModifierLoaderContext &context, const Data::Standard::MediaCueMessengerModifier &data);
bool respondsToEvent(const Event &evt) const override;
VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr &msg) override;
void disable(Runtime *runtime) override;
Modifier *getMediaCueModifier() override;
Common::WeakPtr getMediaCueTriggerSource() const override;
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "Media Cue Modifier"; }
SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
#endif
private:
enum CueSourceType {
kCueSourceInteger,
kCueSourceIntegerRange,
kCueSourceVariableReference,
kCueSourceLabel,
kCueSourceString,
kCueSourceInvalid = -1,
};
union CueSourceUnion {
CueSourceUnion();
~CueSourceUnion();
int32 asInt;
IntRange asIntRange;
uint32 asVarRefGUID;
Label asLabel;
uint64 asUnset;
Common::String asString;
template
void construct(const T &value);
template
void destruct();
};
MediaCueMessengerModifier(const MediaCueMessengerModifier &other);
void destructCueSource();
Common::SharedPtr shallowClone() const override;
const char *getDefaultName() const override;
void linkInternalReferences(ObjectLinkingScope *scope) override;
void visitInternalReferences(IStructuralReferenceVisitor *visitor) override;
CueSourceType _cueSourceType;
CueSourceUnion _cueSource;
Common::WeakPtr _cueSourceModifier;
Event _enableWhen;
Event _disableWhen;
MediaCueState _mediaCue;
bool _isActive;
};
class ObjectReferenceVariableModifier : public VariableModifier {
public:
ObjectReferenceVariableModifier();
bool load(const PlugInModifierLoaderContext &context, const Data::Standard::ObjectReferenceVariableModifier &data);
bool varSetValue(MiniscriptThread *thread, const DynamicValue &value) override;
void varGetValue(DynamicValue &dest) const override;
bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &result, const Common::String &attrib) override;
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "Object Reference Variable Modifier"; }
SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
void debugInspect(IDebugInspectionReport *report) const override;
#endif
private:
struct ObjectWriteInterface {
static MiniscriptInstructionOutcome write(MiniscriptThread *thread, const DynamicValue &dest, void *objectRef, uintptr ptrOrOffset);
static MiniscriptInstructionOutcome refAttrib(MiniscriptThread *thread, DynamicValueWriteProxy &proxy, void *objectRef, uintptr ptrOrOffset, const Common::String &attrib);
static MiniscriptInstructionOutcome refAttribIndexed(MiniscriptThread *thread, DynamicValueWriteProxy &proxy, void *objectRef, uintptr ptrOrOffset, const Common::String &attrib, const DynamicValue &index);
};
Common::SharedPtr shallowClone() const override;
const char *getDefaultName() const override;
MiniscriptInstructionOutcome scriptSetPath(MiniscriptThread *thread, const DynamicValue &value);
MiniscriptInstructionOutcome scriptSetObject(MiniscriptThread *thread, const DynamicValue &value);
MiniscriptInstructionOutcome scriptObjectRefAttrib(MiniscriptThread *thread, DynamicValueWriteProxy &proxy, const Common::String &attrib);
MiniscriptInstructionOutcome scriptObjectRefAttribIndexed(MiniscriptThread *thread, DynamicValueWriteProxy &proxy, const Common::String &attrib, const DynamicValue &index);
void resolve(Runtime *runtime);
void resolveRelativePath(Runtime *runtime, RuntimeObject *obj, const Common::String &path, size_t startPos);
void resolveAbsolutePath(Runtime *runtime);
static bool computeObjectPath(RuntimeObject *obj, Common::String &outPath);
static RuntimeObject *getObjectParent(RuntimeObject *obj);
Event _setToSourceParentWhen;
};
class ObjectReferenceVariableStorage : public VariableStorage {
public:
friend class ObjectReferenceVariableModifier;
ObjectReferenceVariableStorage();
Common::SharedPtr getSaveLoad(Runtime *runtime) override;
Common::SharedPtr clone() const override;
private:
class SaveLoad : public ModifierSaveLoad {
public:
explicit SaveLoad(ObjectReferenceVariableStorage *storage);
private:
void commitLoad() const override;
void saveInternal(Common::WriteStream *stream) const override;
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
ObjectReferenceVariableStorage *_storage;
Common::String _objectPath;
};
Common::String _fullPath;
Common::String _objectPath;
mutable ObjectReference _object;
};
class ListVariableStorage : public VariableStorage {
public:
friend class ListVariableModifier;
ListVariableStorage();
Common::SharedPtr getSaveLoad(Runtime *runtime) override;
Common::SharedPtr clone() const override;
private:
class SaveLoad : public ModifierSaveLoad {
public:
explicit SaveLoad(ListVariableStorage *storage);
private:
void commitLoad() const override;
void saveInternal(Common::WriteStream *stream) const override;
bool loadInternal(Common::ReadStream *stream, uint32 saveFileVersion) override;
static void recursiveWriteList(DynamicList *list, Common::WriteStream *stream);
static Common::SharedPtr recursiveReadList(Common::ReadStream *stream);
ListVariableStorage *_storage;
Common::SharedPtr _list;
};
Common::SharedPtr _list;
DynamicValueTypes::DynamicValueType _preferredContentType;
};
class ListVariableModifier : public VariableModifier {
public:
ListVariableModifier();
bool load(const PlugInModifierLoaderContext &context, const Data::Standard::ListVariableModifier &data);
bool varSetValue(MiniscriptThread *thread, const DynamicValue &value) override;
void varGetValue(DynamicValue &dest) const override;
bool isListVariable() const override;
bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
bool readAttributeIndexed(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib, const DynamicValue &index) override;
MiniscriptInstructionOutcome writeRefAttribute(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib) override;
MiniscriptInstructionOutcome writeRefAttributeIndexed(MiniscriptThread *thread, DynamicValueWriteProxy &writeProxy, const Common::String &attrib, const DynamicValue &index) override;
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "List Variable Modifier"; }
SupportStatus debugGetSupportStatus() const override { return kSupportStatusDone; }
void debugInspect(IDebugInspectionReport *report) const override;
#endif
private:
MiniscriptInstructionOutcome scriptSetCount(MiniscriptThread *thread, const DynamicValue &value);
Common::SharedPtr shallowClone() const override;
const char *getDefaultName() const override;
};
class SysInfoModifier : public Modifier {
public:
bool load(const PlugInModifierLoaderContext &context, const Data::Standard::SysInfoModifier &data);
bool readAttribute(MiniscriptThread *thread, DynamicValue &result, const Common::String &attrib) override;
void disable(Runtime *runtime) override {}
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "System Info Modifier"; }
#endif
private:
Common::SharedPtr shallowClone() const override;
const char *getDefaultName() const override;
};
struct StandardPlugInHacks {
StandardPlugInHacks();
// If list mod values are illegible, just ignore them and flag it as garbled.
// Necessary to load object 00788ab9 (olL437Check) in Obsidian, which is supposed to be a list of
// 4 lists that are 3-size each, in the persistent data, but actually contains 4 identical values
// that appear to be garbage.
bool allowGarbledListModData;
};
class PanningModifier : public Modifier {
public:
PanningModifier();
~PanningModifier();
bool load(const PlugInModifierLoaderContext &context, const Data::Standard::PanningModifier &data);
bool respondsToEvent(const Event &evt) const override;
VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr &msg) override;
void disable(Runtime *runtime) override;
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "Panning Modifier"; }
void debugInspect(IDebugInspectionReport *report) const override;
#endif
private:
Common::SharedPtr shallowClone() const override;
const char *getDefaultName() const override;
};
class FadeModifier : public Modifier {
public:
FadeModifier();
~FadeModifier();
bool load(const PlugInModifierLoaderContext &context, const Data::Standard::FadeModifier &data);
void disable(Runtime *runtime) override;
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "Fade Modifier"; }
#endif
private:
Common::SharedPtr shallowClone() const override;
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 &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 shallowClone() const override;
const char *getDefaultName() const override;
Event _executeWhen;
Common::String _filePath;
};
class NavigateModifier : public Modifier {
public:
NavigateModifier();
~NavigateModifier();
bool load(const PlugInModifierLoaderContext &context, const Data::Standard::NavigateModifier &data);
bool respondsToEvent(const Event &evt) const override;
VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr &msg) override;
void disable(Runtime *runtime) override;
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "Navigate Modifier"; }
void debugInspect(IDebugInspectionReport *report) const override;
#endif
private:
Common::SharedPtr shallowClone() const override;
const char *getDefaultName() const override;
};
class OpenTitleModifier : public Modifier {
public:
OpenTitleModifier();
~OpenTitleModifier();
bool load(const PlugInModifierLoaderContext &context, const Data::Standard::OpenTitleModifier &data);
bool respondsToEvent(const Event &evt) const override;
VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr &msg) override;
void disable(Runtime *runtime) override;
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "Open Title Modifier"; }
void debugInspect(IDebugInspectionReport *report) const override;
#endif
private:
Common::SharedPtr shallowClone() const override;
const char *getDefaultName() const override;
Event _executeWhen;
Common::String _pathOrUrl;
bool _addToReturnList;
};
class OpenAppModifier : public Modifier {
public:
OpenAppModifier();
~OpenAppModifier();
bool load(const PlugInModifierLoaderContext &context, const Data::Standard::OpenAppModifier &data);
bool respondsToEvent(const Event &evt) const override;
VThreadState consumeMessage(Runtime *runtime, const Common::SharedPtr &msg) override;
void disable(Runtime *runtime) override;
#ifdef MTROPOLIS_DEBUG_ENABLE
const char *debugGetTypeName() const override { return "Open App Modifier"; }
void debugInspect(IDebugInspectionReport *report) const override;
#endif
private:
Common::SharedPtr shallowClone() const override;
const char *getDefaultName() const override;
Event _executeWhen;
Common::String _pathOrUrl;
bool _addToReturnList;
};
class StandardPlugIn : public MTropolis::PlugIn {
public:
StandardPlugIn();
~StandardPlugIn();
void registerModifiers(IPlugInModifierRegistrar *registrar) const override;
const StandardPlugInHacks &getHacks() const;
StandardPlugInHacks &getHacks();
private:
PlugInModifierFactory _cursorModifierFactory;
PlugInModifierFactory _sTransCtModifierFactory;
PlugInModifierFactory _mediaCueModifierFactory;
PlugInModifierFactory _objRefVarModifierFactory;
PlugInModifierFactory _listVarModifierFactory;
PlugInModifierFactory _sysInfoModifierFactory;
PlugInModifierFactory _panningModifierFactory;
PlugInModifierFactory _fadeModifierFactory;
PlugInModifierFactory _printModifierFactory;
PlugInModifierFactory _navigateModifierFactory;
PlugInModifierFactory _openTitleModifierFactory;
PlugInModifierFactory _openAppModifierFactory;
StandardPlugInHacks _hacks;
};
} // End of namespace Standard
} // End of namespace MTropolis
#endif