/* 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