MTROPOLIS: Add keyboard messenger modifier loader and merge some messenger functionality

This commit is contained in:
elasota 2022-04-10 01:04:05 -04:00 committed by Eugene Sandulenko
parent 257ce80381
commit a888c537fa
5 changed files with 195 additions and 29 deletions

View File

@ -526,6 +526,24 @@ DataReadErrorCode IfMessengerModifier::load(DataReader &reader) {
return kDataReadErrorNone;
}
DataReadErrorCode KeyboardMessengerModifier::load(DataReader &reader) {
if (_revision != 0x3eb)
return kDataReadErrorReadFailed;
if (!modHeader.load(reader) || !reader.readU32(messageFlagsAndKeyStates) || !reader.readU16(unknown2)
|| !reader.readU16(keyModifiers) || !reader.readU8(keycode) || !reader.readBytes(unknown4)
|| !message.load(reader) || !reader.readU16(unknown7) || !reader.readU32(destination)
|| !reader.readBytes(unknown9) || !reader.readU16(with) || !reader.readBytes(unknown11)
|| !reader.readU32(withSourceGUID) || !reader.readBytes(unknown13) || !reader.readU8(withSourceLength)
|| !reader.readU8(unknown14))
return kDataReadErrorReadFailed;
if (withSourceLength > 0 && !reader.readNonTerminatedStr(withSource, withSourceLength))
return kDataReadErrorReadFailed;
return kDataReadErrorNone;
}
DataReadErrorCode BooleanVariableModifier::load(DataReader &reader) {
if (_revision != 0x3e8)
return kDataReadErrorUnsupportedRevision;
@ -658,6 +676,9 @@ DataReadErrorCode loadDataObject(const PlugInModifierRegistry &registry, DataRea
case DataObjectTypes::kPlugInModifier:
dataObject = new PlugInModifier();
break;
case DataObjectTypes::kKeyboardMessengerModifier:
dataObject = new KeyboardMessengerModifier();
break;
default:
warning("Unrecognized data object type %x", static_cast<int>(type));
break;

View File

@ -103,7 +103,7 @@ enum DataObjectType {
kSetModifier = 0x2df, // NYI
kCollisionDetectionMessengerMOdifier = 0x2ee, // NYI
kBoundaryDetectionMessengerModifier = 0x2f8, // NYI
kKeyboardMessengerModifier = 0x302, // NYI
kKeyboardMessengerModifier = 0x302,
kTextStyleModifier = 0x32a, // NYI
kGraphicModifier = 0x334, // NYI
kImageEffectModifier = 0x384, // NYI
@ -456,6 +456,63 @@ protected:
DataReadErrorCode load(DataReader &reader) override;
};
struct KeyboardMessengerModifier : public DataObject {
enum KeyStateFlags {
kOnDown = 0x10000000,
kOnUp = 0x4000000,
kOnRepeat = 0x8000000,
kKeyStateMask = (kOnDown | kOnUp | kOnRepeat),
};
enum KeyModifiers {
kControl = 0x1000,
kCommand = 0x0100,
kOption = 0x0800,
};
enum KeyCodes {
kAny = 0x00,
kHome = 0x01,
kEnter = 0x03,
kEnd = 0x04,
kHelp = 0x05,
kBackspace = 0x08,
kTab = 0x09,
kPageUp = 0x0b,
kPageDown = 0x0c,
kReturn = 0x0d,
kEscape = 0x1b,
kArrowLeft = 0x1c,
kArrowRight = 0x1d,
kArrowUp = 0x1e,
kArrowDown = 0x1f,
kDelete = 0x7f,
};
TypicalModifierHeader modHeader;
uint32 messageFlagsAndKeyStates;
uint16 unknown2;
uint16 keyModifiers;
uint8 keycode;
uint8 unknown4[7];
Event message;
uint16 unknown7;
uint32 destination;
uint8 unknown9[10];
uint16 with;
uint8 unknown11[4];
uint32 withSourceGUID;
uint8 unknown13[36];
uint8 withSourceLength;
uint8 unknown14;
Common::String withSource;
protected:
DataReadErrorCode load(DataReader &reader) override;
};
struct BooleanVariableModifier final : public DataObject {
TypicalModifierHeader modHeader;
uint8_t value;

View File

@ -67,6 +67,8 @@ IModifierFactory *getModifierFactoryForDataObjectType(const Data::DataObjectType
return ModifierFactory<MiniscriptModifier, Data::MiniscriptModifier>::getInstance();
case Data::DataObjectTypes::kIfMessengerModifier:
return ModifierFactory<IfMessengerModifier, Data::IfMessengerModifier>::getInstance();
case Data::DataObjectTypes::kKeyboardMessengerModifier:
return ModifierFactory<KeyboardMessengerModifier, Data::KeyboardMessengerModifier>::getInstance();
case Data::DataObjectTypes::kMessengerModifier:
return ModifierFactory<MessengerModifier, Data::MessengerModifier>::getInstance();
case Data::DataObjectTypes::kBooleanVariableModifier:

View File

@ -27,14 +27,6 @@
namespace MTropolis {
static MessageFlags translateMessengerFlags(uint32 messengerFlags) {
MessageFlags messageFlags;
messageFlags.relay = ((messengerFlags & 0x20000000) == 0);
messageFlags.cascade = ((messengerFlags & 0x40000000) == 0);
messageFlags.immediate = ((messengerFlags & 0x80000000) == 0);
return messageFlags;
}
bool BehaviorModifier::load(ModifierLoaderContext &context, const Data::BehaviorModifier &data) {
if (data.numChildren > 0) {
ChildLoaderContext loaderContext;
@ -75,17 +67,31 @@ bool MiniscriptModifier::load(ModifierLoaderContext &context, const Data::Minisc
return true;
}
MessengerSendSpec::MessengerSendSpec() : withType(kMessageWithNothing), withSourceGUID(0), destination(0) {
}
bool MessengerSendSpec::load(const Data::Event& dataEvent, uint32 dataMessageFlags, uint16 dataWith, uint32 dataWithSourceGUID, uint32 dataDestination) {
messageFlags.relay = ((dataMessageFlags & 0x20000000) == 0);
messageFlags.cascade = ((dataMessageFlags & 0x40000000) == 0);
messageFlags.immediate = ((dataMessageFlags & 0x80000000) == 0);
if (!this->send.load(dataEvent))
return false;
this->destination = dataDestination;
this->withSourceGUID = dataWithSourceGUID;
this->withType = static_cast<MessageWithType>(dataWith);
return true;
}
bool MessengerModifier::load(ModifierLoaderContext &context, const Data::MessengerModifier &data) {
_guid = data.modHeader.guid;
_name = data.modHeader.name;
if (!_when.load(data.when) || !_send.load(data.send))
if (!_when.load(data.when) || !_sendSpec.load(data.send, data.messageFlags, data.with, data.withSourceGUID, data.destination))
return false;
_messageFlags = translateMessengerFlags(data.messageFlags);
_messageWithType = static_cast<MessageWithType>(data.with);
_messageDestination = data.destination;
return true;
}
@ -93,13 +99,9 @@ bool IfMessengerModifier::load(ModifierLoaderContext &context, const Data::IfMes
_guid = data.modHeader.guid;
_name = data.modHeader.name;
if (!_when.load(data.when) || !_send.load(data.send))
if (!_when.load(data.when) || !_sendSpec.load(data.send, data.messageFlags, data.with, data.withSourceGUID, data.destination))
return false;
_messageFlags = translateMessengerFlags(data.messageFlags);
_messageWithType = static_cast<MessageWithType>(data.with);
_messageDestination = data.destination;
_program = MiniscriptParser::parse(data.program);
if (!_program)
return false;
@ -107,6 +109,49 @@ bool IfMessengerModifier::load(ModifierLoaderContext &context, const Data::IfMes
return true;
}
bool KeyboardMessengerModifier::load(ModifierLoaderContext &context, const Data::KeyboardMessengerModifier &data) {
_guid = data.modHeader.guid;
_name = data.modHeader.name;
_onDown = ((data.messageFlagsAndKeyStates & Data::KeyboardMessengerModifier::kOnDown) != 0);
_onUp = ((data.messageFlagsAndKeyStates & Data::KeyboardMessengerModifier::kOnUp) != 0);
_onRepeat = ((data.messageFlagsAndKeyStates & Data::KeyboardMessengerModifier::kOnRepeat) != 0);
_keyModControl = ((data.keyModifiers & Data::KeyboardMessengerModifier::kControl) != 0);
_keyModCommand = ((data.keyModifiers & Data::KeyboardMessengerModifier::kCommand) != 0);
_keyModOption = ((data.keyModifiers & Data::KeyboardMessengerModifier::kOption) != 0);
switch (data.keycode) {
case KeyCodeType::kAny:
case KeyCodeType::kHome:
case KeyCodeType::kEnter:
case KeyCodeType::kEnd:
case KeyCodeType::kHelp:
case KeyCodeType::kBackspace:
case KeyCodeType::kTab:
case KeyCodeType::kPageUp:
case KeyCodeType::kPageDown:
case KeyCodeType::kReturn:
case KeyCodeType::kEscape:
case KeyCodeType::kArrowLeft:
case KeyCodeType::kArrowRight:
case KeyCodeType::kArrowUp:
case KeyCodeType::kArrowDown:
case KeyCodeType::kDelete:
_keyCodeType = static_cast<KeyCodeType>(data.keycode);
_macRomanChar = 0;
break;
default:
_keyCodeType = kMacRomanChar;
_macRomanChar = data.keycode;
break;
}
if (!_sendSpec.load(data.message, data.messageFlagsAndKeyStates, data.with, data.withSourceGUID, data.destination))
return false;
return true;
}
bool BooleanVariableModifier::load(ModifierLoaderContext &context, const Data::BooleanVariableModifier &data) {
_guid = data.modHeader.guid;
_name = data.modHeader.name;

View File

@ -53,17 +53,24 @@ private:
Common::SharedPtr<MiniscriptProgram> _program;
};
struct MessengerSendSpec {
MessengerSendSpec();
bool load(const Data::Event &dataEvent, uint32 dataMessageFlags, uint16 dataWith, uint32 dataWithSourceGUID, uint32 dataDestination);
Event send;
MessageFlags messageFlags;
MessageWithType withType;
uint32 withSourceGUID;
uint32 destination; // May be a MessageDestination or GUID
};
class MessengerModifier : public Modifier {
public:
bool load(ModifierLoaderContext &context, const Data::MessengerModifier &data);
private:
Event _when;
Event _send;
MessageFlags _messageFlags;
MessageWithType _messageWithType;
uint32 _messageDestination; // May be a MessageDestination or GUID
MessengerSendSpec _sendSpec;
};
class IfMessengerModifier : public Modifier {
@ -72,14 +79,48 @@ public:
private:
Event _when;
Event _send;
MessageFlags _messageFlags;
MessageWithType _messageWithType;
uint32 _messageDestination; // May be a MessageDestination or GUID
MessengerSendSpec _sendSpec;
Common::SharedPtr<MiniscriptProgram> _program;
};
class KeyboardMessengerModifier : public Modifier {
public:
bool load(ModifierLoaderContext &context, const Data::KeyboardMessengerModifier &data);
private:
Event _send;
enum KeyCodeType {
kAny = 0x00,
kHome = 0x01,
kEnter = 0x03,
kEnd = 0x04,
kHelp = 0x05,
kBackspace = 0x08,
kTab = 0x09,
kPageUp = 0x0b,
kPageDown = 0x0c,
kReturn = 0x0d,
kEscape = 0x1b,
kArrowLeft = 0x1c,
kArrowRight = 0x1d,
kArrowUp = 0x1e,
kArrowDown = 0x1f,
kDelete = 0x7f,
kMacRomanChar = 0xff,
};
bool _onDown : 1;
bool _onUp : 1;
bool _onRepeat : 1;
bool _keyModControl : 1;
bool _keyModCommand : 1;
bool _keyModOption : 1;
KeyCodeType _keyCodeType;
uint8_t _macRomanChar;
MessengerSendSpec _sendSpec;
};
class BooleanVariableModifier : public Modifier {
public: