diff --git a/src/ObjWriting/Cache/AbstractCacheWriter.cpp b/src/ObjWriting/Cache/AbstractCacheWriter.cpp new file mode 100644 index 00000000..872968ef --- /dev/null +++ b/src/ObjWriting/Cache/AbstractCacheWriter.cpp @@ -0,0 +1,42 @@ +#include "AbstractCacheWriter.h" + +using namespace cache; + +AbstractCacheWriter::AbstractCacheWriter(std::ostream& stream) + : m_stream(stream) +{ +} + +void AbstractCacheWriter::Write(const void* data, const size_t dataSize) const +{ + m_stream.write(static_cast(data), dataSize); +} + +void AbstractCacheWriter::WriteString(const char* str) const +{ + if (!str) + return; + + const auto len = strnlen(str, 0xFFFF); + Write(&len, sizeof(len)); + Write(str, len); +} + +void AbstractCacheWriter::WriteBool(const bool value) const +{ + m_stream << (value ? '\x01' : '\x00'); +} + +void AbstractCacheWriter::WriteFalse() const +{ + WriteBool(false); +} + +void AbstractCacheWriter::WriteTrue() const +{ + WriteBool(true); +} + +void AbstractCacheWriter::WriteFileDependency(const std::string& dependencyName, uint64_t timestamp) const {} + +void AbstractCacheWriter::WriteGdtDependency(const std::string& dependencyName, uint32_t crc32) const {} diff --git a/src/ObjWriting/Cache/AbstractCacheWriter.h b/src/ObjWriting/Cache/AbstractCacheWriter.h new file mode 100644 index 00000000..a3029106 --- /dev/null +++ b/src/ObjWriting/Cache/AbstractCacheWriter.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +namespace cache +{ + class AbstractCacheWriter + { + protected: + explicit AbstractCacheWriter(std::ostream& stream); + + void WriteFileDependency(const std::string& dependencyName, uint64_t timestamp) const; + void WriteGdtDependency(const std::string& dependencyName, uint32_t crc32) const; + + void Write(const void* data, size_t dataSize) const; + void WriteString(const char* str) const; + + void WriteBool(bool value) const; + void WriteTrue() const; + void WriteFalse() const; + + std::ostream& m_stream; + }; +} // namespace cache diff --git a/src/ObjWriting/Game/IW4/Cache/MenuCacheWriter.cpp b/src/ObjWriting/Game/IW4/Cache/MenuCacheWriter.cpp new file mode 100644 index 00000000..477d9ae1 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Cache/MenuCacheWriter.cpp @@ -0,0 +1,263 @@ +#include "MenuCacheWriter.h" + +using namespace IW4; + +MenuCacheWriter::MenuCacheWriter(std::ostream& stream) + : AbstractCacheWriter(stream) +{ +} + +void MenuCacheWriter::WriteItemKeyHandler(const ItemKeyHandler& itemKeyHandler) const +{ + Write(&itemKeyHandler, sizeof(ItemKeyHandler)); + + if (itemKeyHandler.action) + WriteMenuEventHandlerSet(*itemKeyHandler.action); + + if (itemKeyHandler.next) + WriteItemKeyHandler(*itemKeyHandler.next); +} + +void MenuCacheWriter::WriteStatement(const Statement_s& statement) const +{ + Write(&statement, sizeof(Statement_s)); + + if (statement.entries && statement.numEntries > 0) + { + Write(statement.entries, sizeof(expressionEntry) * statement.numEntries); + + for (auto i = 0; i < statement.numEntries; i++) + { + const auto& entry = statement.entries[i]; + if (entry.type == EET_OPERAND) + { + if (entry.data.operand.dataType == VAL_STRING) + { + WriteString(entry.data.operand.internals.stringVal.string); + } + else if (entry.data.operand.dataType == VAL_FUNCTION) + { + if (entry.data.operand.internals.function) + WriteStatement(*entry.data.operand.internals.function); + } + } + } + } + + // supportingData +} + +void MenuCacheWriter::WriteMenuEventHandler(const MenuEventHandler& menuEventHandler) const +{ + Write(&menuEventHandler, sizeof(MenuEventHandler)); + + switch (menuEventHandler.eventType) + { + case EVENT_UNCONDITIONAL: + WriteString(menuEventHandler.eventData.unconditionalScript); + break; + + case EVENT_IF: + if (menuEventHandler.eventData.conditionalScript) + { + if (menuEventHandler.eventData.conditionalScript->eventHandlerSet) + { + WriteTrue(); + WriteMenuEventHandlerSet(*menuEventHandler.eventData.conditionalScript->eventHandlerSet); + } + else + WriteFalse(); + + if (menuEventHandler.eventData.conditionalScript->eventExpression) + { + WriteTrue(); + WriteStatement(*menuEventHandler.eventData.conditionalScript->eventExpression); + } + else + WriteFalse(); + } + break; + + case EVENT_ELSE: + if (menuEventHandler.eventData.elseScript) + WriteMenuEventHandlerSet(*menuEventHandler.eventData.elseScript); + break; + + case EVENT_SET_LOCAL_VAR_BOOL: + case EVENT_SET_LOCAL_VAR_FLOAT: + case EVENT_SET_LOCAL_VAR_INT: + case EVENT_SET_LOCAL_VAR_STRING: + if (menuEventHandler.eventData.setLocalVarData) + { + WriteBool(menuEventHandler.eventData.setLocalVarData->localVarName != nullptr); + WriteString(menuEventHandler.eventData.setLocalVarData->localVarName); + + if (menuEventHandler.eventData.setLocalVarData->expression) + { + WriteTrue(); + WriteStatement(*menuEventHandler.eventData.setLocalVarData->expression); + } + else + WriteFalse(); + } + break; + + default: + break; + } +} + +void MenuCacheWriter::WriteMenuEventHandlerSet(const MenuEventHandlerSet& menuEventHandlerSet) const +{ + Write(&menuEventHandlerSet, sizeof(MenuEventHandlerSet)); + + if (menuEventHandlerSet.eventHandlers) + { + for (auto i = 0; i < menuEventHandlerSet.eventHandlerCount; i++) + { + if (menuEventHandlerSet.eventHandlers[i]) + { + WriteTrue(); + WriteMenuEventHandler(*menuEventHandlerSet.eventHandlers[i]); + } + else + WriteFalse(); + } + } +} + +void MenuCacheWriter::WriteWindowDef(const windowDef_t& windowDef) const +{ + WriteString(windowDef.name); + + WriteString(windowDef.group); + + // background +} + +void MenuCacheWriter::WriteItem(const itemDef_s& item) const +{ + Write(&item, sizeof(item)); + + WriteWindowDef(item.window); + + WriteString(item.text); + + if (item.mouseEnterText) + WriteMenuEventHandlerSet(*item.mouseEnterText); + + if (item.mouseExitText) + WriteMenuEventHandlerSet(*item.mouseExitText); + + if (item.mouseEnter) + WriteMenuEventHandlerSet(*item.mouseEnter); + + if (item.mouseExit) + WriteMenuEventHandlerSet(*item.mouseExit); + + if (item.action) + WriteMenuEventHandlerSet(*item.action); + + if (item.accept) + WriteMenuEventHandlerSet(*item.accept); + + if (item.onFocus) + WriteMenuEventHandlerSet(*item.onFocus); + + if (item.leaveFocus) + WriteMenuEventHandlerSet(*item.leaveFocus); + + WriteString(item.dvar); + + WriteString(item.dvarTest); + + if (item.onKey) + WriteItemKeyHandler(*item.onKey); + + WriteString(item.enableDvar); + + WriteString(item.localVar); + + // focusSound + + // itemDefData + + // floatExpressions + + if (item.visibleExp) + WriteStatement(*item.visibleExp); + + if (item.disabledExp) + WriteStatement(*item.disabledExp); + + if (item.textExp) + WriteStatement(*item.textExp); + + if (item.materialExp) + WriteStatement(*item.materialExp); +} + +void MenuCacheWriter::WriteMenu(const menuDef_t& menu) const +{ + Write(&menu, sizeof(menu)); + + // expressionData + + WriteWindowDef(menu.window); + + WriteString(menu.font); + + if (menu.onOpen) + WriteMenuEventHandlerSet(*menu.onOpen); + + if (menu.onClose) + WriteMenuEventHandlerSet(*menu.onClose); + + if (menu.onCloseRequest) + WriteMenuEventHandlerSet(*menu.onCloseRequest); + + if (menu.onESC) + WriteMenuEventHandlerSet(*menu.onESC); + + if (menu.onKey) + WriteItemKeyHandler(*menu.onKey); + + if (menu.visibleExp) + WriteStatement(*menu.visibleExp); + + WriteString(menu.allowedBinding); + + WriteString(menu.soundName); + + if (menu.rectXExp) + WriteStatement(*menu.rectXExp); + + if (menu.rectYExp) + WriteStatement(*menu.rectYExp); + + if (menu.rectWExp) + WriteStatement(*menu.rectWExp); + + if (menu.rectHExp) + WriteStatement(*menu.rectHExp); + + if (menu.openSoundExp) + WriteStatement(*menu.openSoundExp); + + if (menu.closeSoundExp) + WriteStatement(*menu.closeSoundExp); + + if (menu.items) + { + for (auto i = 0; i < menu.itemCount; i++) + { + if (menu.items[i]) + { + WriteTrue(); + WriteItem(*menu.items[i]); + } + else + WriteFalse(); + } + } +} diff --git a/src/ObjWriting/Game/IW4/Cache/MenuCacheWriter.h b/src/ObjWriting/Game/IW4/Cache/MenuCacheWriter.h new file mode 100644 index 00000000..141534d0 --- /dev/null +++ b/src/ObjWriting/Game/IW4/Cache/MenuCacheWriter.h @@ -0,0 +1,25 @@ +#pragma once + +#include "Cache/AbstractCacheWriter.h" +#include "Game/IW4/IW4.h" + +#include + +namespace IW4 +{ + class MenuCacheWriter : public cache::AbstractCacheWriter + { + public: + explicit MenuCacheWriter(std::ostream& stream); + + void WriteStatement(const Statement_s& statement) const; + void WriteItemKeyHandler(const ItemKeyHandler& itemKeyHandler) const; + void WriteMenuEventHandler(const MenuEventHandler& menuEventHandler) const; + void WriteMenuEventHandlerSet(const MenuEventHandlerSet& menuEventHandlerSet) const; + + void WriteWindowDef(const windowDef_t& windowDef) const; + + void WriteItem(const itemDef_s& item) const; + void WriteMenu(const menuDef_t& menu) const; + }; +} // namespace IW4 diff --git a/src/ZoneLoading/Game/IW4/ContentLoaderIW4.cpp b/src/ZoneLoading/Game/IW4/ContentLoaderIW4.cpp index 209edc7e..7e560bac 100644 --- a/src/ZoneLoading/Game/IW4/ContentLoaderIW4.cpp +++ b/src/ZoneLoading/Game/IW4/ContentLoaderIW4.cpp @@ -39,6 +39,7 @@ #include "Loading/Exception/UnsupportedAssetTypeException.h" #include +#include using namespace IW4;