mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-06-09 22:38:06 -05:00
Make use of custom functions when converting menus
This commit is contained in:
114
src/ObjLoading/Game/IW4/Menu/MenuConversionZoneStateIW4.cpp
Normal file
114
src/ObjLoading/Game/IW4/Menu/MenuConversionZoneStateIW4.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
#include "MenuConversionZoneStateIW4.h"
|
||||
|
||||
using namespace IW4;
|
||||
|
||||
MenuConversionZoneState::MenuConversionZoneState()
|
||||
: m_zone(nullptr),
|
||||
m_supporting_data(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void MenuConversionZoneState::SetZone(Zone* zone)
|
||||
{
|
||||
auto* memory = zone->GetMemory();
|
||||
|
||||
m_zone = zone;
|
||||
m_supporting_data = memory->Create<ExpressionSupportingData>();
|
||||
memset(m_supporting_data, 0, sizeof(ExpressionSupportingData));
|
||||
}
|
||||
|
||||
Statement_s* MenuConversionZoneState::FindFunction(const std::string& functionName)
|
||||
{
|
||||
const auto foundFunction = m_function_by_name.find(functionName);
|
||||
|
||||
if (foundFunction != m_function_by_name.end())
|
||||
return foundFunction->second;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Statement_s* MenuConversionZoneState::AddFunction(const std::string& functionName, Statement_s* function)
|
||||
{
|
||||
m_functions.push_back(function);
|
||||
m_function_by_name.emplace(std::make_pair(functionName, function));
|
||||
|
||||
return function;
|
||||
}
|
||||
|
||||
size_t MenuConversionZoneState::AddStaticDvar(const std::string& dvarName)
|
||||
{
|
||||
const auto foundDvar = m_dvars_by_name.find(dvarName);
|
||||
|
||||
if (foundDvar != m_dvars_by_name.end())
|
||||
return foundDvar->second;
|
||||
|
||||
auto* memory = m_zone->GetMemory();
|
||||
auto* staticDvar = static_cast<StaticDvar*>(memory->Alloc(sizeof(StaticDvar)));
|
||||
|
||||
staticDvar->dvarName = memory->Dup(dvarName.c_str());
|
||||
staticDvar->dvar = nullptr;
|
||||
|
||||
const auto staticDvarIndex = m_static_dvars.size();
|
||||
m_static_dvars.push_back(staticDvar);
|
||||
m_dvars_by_name.emplace(std::make_pair(dvarName, staticDvarIndex));
|
||||
|
||||
return staticDvarIndex;
|
||||
}
|
||||
|
||||
const char* MenuConversionZoneState::AddString(const std::string& str)
|
||||
{
|
||||
const auto foundString = m_strings_by_value.find(str);
|
||||
|
||||
if (foundString != m_strings_by_value.end())
|
||||
return foundString->second;
|
||||
|
||||
auto* memory = m_zone->GetMemory();
|
||||
const auto* strDuped = memory->Dup(str.c_str());
|
||||
|
||||
m_strings.push_back(strDuped);
|
||||
m_strings_by_value.emplace(std::make_pair(str, strDuped));
|
||||
|
||||
return strDuped;
|
||||
}
|
||||
|
||||
void MenuConversionZoneState::FinalizeSupportingData() const
|
||||
{
|
||||
auto* memory = m_zone->GetMemory();
|
||||
|
||||
m_supporting_data->uifunctions.totalFunctions = static_cast<int>(m_functions.size());
|
||||
m_supporting_data->staticDvarList.numStaticDvars = static_cast<int>(m_static_dvars.size());
|
||||
m_supporting_data->uiStrings.totalStrings = static_cast<int>(m_strings.size());
|
||||
|
||||
if (m_supporting_data->uifunctions.functions)
|
||||
memory->Free(m_supporting_data->uifunctions.functions);
|
||||
|
||||
if (m_supporting_data->staticDvarList.staticDvars)
|
||||
memory->Free(m_supporting_data->staticDvarList.staticDvars);
|
||||
|
||||
if (m_supporting_data->uiStrings.strings)
|
||||
memory->Free(m_supporting_data->uiStrings.strings);
|
||||
|
||||
if (!m_functions.empty())
|
||||
{
|
||||
m_supporting_data->uifunctions.functions = static_cast<Statement_s**>(memory->Alloc(sizeof(void*) * m_functions.size()));
|
||||
memcpy(m_supporting_data->uifunctions.functions, &m_functions[0], sizeof(void*) * m_functions.size());
|
||||
}
|
||||
else
|
||||
m_supporting_data->uifunctions.functions = nullptr;
|
||||
|
||||
if (!m_static_dvars.empty())
|
||||
{
|
||||
m_supporting_data->staticDvarList.staticDvars = static_cast<StaticDvar**>(memory->Alloc(sizeof(void*) * m_static_dvars.size()));
|
||||
memcpy(m_supporting_data->staticDvarList.staticDvars, &m_static_dvars[0], sizeof(void*) * m_static_dvars.size());
|
||||
}
|
||||
else
|
||||
m_supporting_data->staticDvarList.staticDvars = nullptr;
|
||||
|
||||
if (!m_strings.empty())
|
||||
{
|
||||
m_supporting_data->uiStrings.strings = static_cast<const char**>(memory->Alloc(sizeof(void*) * m_strings.size()));
|
||||
memcpy(m_supporting_data->uiStrings.strings, &m_strings[0], sizeof(void*) * m_strings.size());
|
||||
}
|
||||
else
|
||||
m_supporting_data->uiStrings.strings = nullptr;
|
||||
}
|
36
src/ObjLoading/Game/IW4/Menu/MenuConversionZoneStateIW4.h
Normal file
36
src/ObjLoading/Game/IW4/Menu/MenuConversionZoneStateIW4.h
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "AssetLoading/IZoneAssetLoaderState.h"
|
||||
#include "Game/IW4/IW4.h"
|
||||
|
||||
namespace IW4
|
||||
{
|
||||
class MenuConversionZoneState final : public IZoneAssetLoaderState
|
||||
{
|
||||
Zone* m_zone;
|
||||
std::vector<Statement_s*> m_functions;
|
||||
std::map<std::string, Statement_s*> m_function_by_name;
|
||||
|
||||
std::vector<StaticDvar*> m_static_dvars;
|
||||
std::map<std::string, size_t> m_dvars_by_name;
|
||||
|
||||
std::vector<const char*> m_strings;
|
||||
std::map<std::string, const char*> m_strings_by_value;
|
||||
|
||||
public:
|
||||
ExpressionSupportingData* m_supporting_data;
|
||||
|
||||
MenuConversionZoneState();
|
||||
void SetZone(Zone* zone) override;
|
||||
|
||||
Statement_s* FindFunction(const std::string& functionName);
|
||||
|
||||
Statement_s* AddFunction(const std::string& functionName, Statement_s* function);
|
||||
size_t AddStaticDvar(const std::string& dvarName);
|
||||
const char* AddString(const std::string& str);
|
||||
|
||||
void FinalizeSupportingData() const;
|
||||
};
|
||||
}
|
@ -3,14 +3,16 @@
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include "MenuConversionZoneStateIW4.h"
|
||||
#include "Game/IW4/MenuConstantsIW4.h"
|
||||
#include "Game/T5/T5_Assets.h"
|
||||
#include "Utils/ClassUtils.h"
|
||||
#include "Menu/AbstractMenuConverter.h"
|
||||
#include "Parsing/Menu/MenuAssetZoneState.h"
|
||||
#include "Parsing/Menu/Domain/EventHandler/CommonEventHandlerCondition.h"
|
||||
#include "Parsing/Menu/Domain/EventHandler/CommonEventHandlerScript.h"
|
||||
#include "Parsing/Menu/Domain/EventHandler/CommonEventHandlerSetLocalVar.h"
|
||||
#include "Parsing/Menu/Domain/Expression/CommonExpressionFunctionCall.h"
|
||||
#include "Parsing/Menu/Domain/Expression/CommonExpressionBaseFunctionCall.h"
|
||||
#include "Parsing/Menu/Domain/Expression/CommonExpressionCustomFunctionCall.h"
|
||||
#include "Parsing/Simple/Expression/SimpleExpressionBinaryOperation.h"
|
||||
#include "Parsing/Simple/Expression/SimpleExpressionConditionalOperator.h"
|
||||
#include "Parsing/Simple/Expression/SimpleExpressionUnaryOperation.h"
|
||||
@ -22,6 +24,9 @@ namespace IW4
|
||||
{
|
||||
class MenuConverterImpl : public AbstractMenuConverter
|
||||
{
|
||||
MenuConversionZoneState* m_conversion_zone_state;
|
||||
MenuAssetZoneState* m_parsing_zone_state;
|
||||
|
||||
static void ApplyMenuDefaults(menuDef_t* menu)
|
||||
{
|
||||
memset(menu, 0, sizeof(menuDef_t));
|
||||
@ -90,39 +95,16 @@ namespace IW4
|
||||
return static_cast<Material*>(materialDependency->m_ptr);
|
||||
}
|
||||
|
||||
static const std::map<std::string, int>& GetFunctionMap()
|
||||
void ConvertExpressionEntryBaseFunctionCall(Statement_s* gameStatement, std::vector<expressionEntry>& entries, const CommonExpressionBaseFunctionCall* functionCall, const CommonMenuDef* menu,
|
||||
const CommonItemDef* item) const
|
||||
{
|
||||
static std::map<std::string, int> mappings;
|
||||
static bool initialized = false;
|
||||
|
||||
if(!initialized)
|
||||
{
|
||||
for(size_t i = EXP_FUNC_DYN_START; i < std::extent_v<decltype(g_expFunctionNames)>; i++)
|
||||
{
|
||||
mappings[g_expFunctionNames[i]] = static_cast<int>(i);
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
return mappings;
|
||||
}
|
||||
|
||||
void ConvertExpressionEntryFunctionCall(std::vector<expressionEntry>& entries, const CommonExpressionFunctionCall* functionCall, const CommonMenuDef* menu,
|
||||
const CommonItemDef* item) const
|
||||
{
|
||||
const auto& functionMappings = GetFunctionMap();
|
||||
|
||||
const auto foundMapping = functionMappings.find(functionCall->m_function_name);
|
||||
if (foundMapping == functionMappings.end())
|
||||
throw MenuConversionException("Could not find function \"" + functionCall->m_function_name + "\"", menu, item);
|
||||
|
||||
expressionEntry functionEntry{};
|
||||
functionEntry.type = EET_OPERATOR;
|
||||
functionEntry.data.op = foundMapping->second;
|
||||
functionEntry.data.op = static_cast<int>(functionCall->m_function_index);
|
||||
entries.emplace_back(functionEntry);
|
||||
|
||||
auto firstArg = true;
|
||||
for(const auto& arg : functionCall->m_args)
|
||||
for (const auto& arg : functionCall->m_args)
|
||||
{
|
||||
if (!firstArg)
|
||||
{
|
||||
@ -134,7 +116,7 @@ namespace IW4
|
||||
else
|
||||
firstArg = false;
|
||||
|
||||
ConvertExpressionEntry(entries, arg.get(), menu, item);
|
||||
ConvertExpressionEntry(gameStatement, entries, arg.get(), menu, item);
|
||||
}
|
||||
|
||||
expressionEntry parenRight{};
|
||||
@ -143,6 +125,33 @@ namespace IW4
|
||||
entries.emplace_back(parenRight);
|
||||
}
|
||||
|
||||
void ConvertExpressionEntryCustomFunctionCall(Statement_s* gameStatement, std::vector<expressionEntry>& entries, const CommonExpressionCustomFunctionCall* functionCall, const CommonMenuDef* menu,
|
||||
const CommonItemDef* item) const
|
||||
{
|
||||
Statement_s* functionStatement = m_conversion_zone_state->FindFunction(functionCall->m_function_name);
|
||||
|
||||
if (functionStatement == nullptr)
|
||||
{
|
||||
// Function was not converted yet: Convert it now
|
||||
const auto foundCommonFunction = m_parsing_zone_state->m_functions_by_name.find(functionCall->m_function_name);
|
||||
|
||||
if (foundCommonFunction == m_parsing_zone_state->m_functions_by_name.end())
|
||||
throw MenuConversionException("Failed to find definition for custom function \"" + functionCall->m_function_name + "\"", menu, item);
|
||||
|
||||
functionStatement = ConvertExpression(foundCommonFunction->second->m_value.get(), menu, item);
|
||||
functionStatement = m_conversion_zone_state->AddFunction(foundCommonFunction->second->m_name, functionStatement);
|
||||
}
|
||||
|
||||
expressionEntry functionEntry{};
|
||||
functionEntry.type = EET_OPERATOR;
|
||||
functionEntry.data.operand.dataType = VAL_FUNCTION;
|
||||
functionEntry.data.operand.internals.function = functionStatement;
|
||||
entries.emplace_back(functionEntry);
|
||||
|
||||
// Statement uses custom function so it needs supporting data
|
||||
gameStatement->supportingData = m_conversion_zone_state->m_supporting_data;
|
||||
}
|
||||
|
||||
constexpr static expressionOperatorType_e UNARY_OPERATION_MAPPING[static_cast<unsigned>(SimpleUnaryOperationId::COUNT)]
|
||||
{
|
||||
OP_NOT,
|
||||
@ -150,7 +159,7 @@ namespace IW4
|
||||
OP_SUBTRACT
|
||||
};
|
||||
|
||||
void ConvertExpressionEntryUnaryOperation(std::vector<expressionEntry>& entries, const SimpleExpressionUnaryOperation* unaryOperation, const CommonMenuDef* menu,
|
||||
void ConvertExpressionEntryUnaryOperation(Statement_s* gameStatement, std::vector<expressionEntry>& entries, const SimpleExpressionUnaryOperation* unaryOperation, const CommonMenuDef* menu,
|
||||
const CommonItemDef* item) const
|
||||
{
|
||||
assert(static_cast<unsigned>(unaryOperation->m_operation_type->m_id) < static_cast<unsigned>(SimpleUnaryOperationId::COUNT));
|
||||
@ -166,7 +175,7 @@ namespace IW4
|
||||
parenLeft.data.op = OP_LEFTPAREN;
|
||||
entries.emplace_back(parenLeft);
|
||||
|
||||
ConvertExpressionEntry(entries, unaryOperation->m_operand.get(), menu, item);
|
||||
ConvertExpressionEntry(gameStatement, entries, unaryOperation->m_operand.get(), menu, item);
|
||||
|
||||
expressionEntry parenRight{};
|
||||
parenRight.type = EET_OPERATOR;
|
||||
@ -174,7 +183,7 @@ namespace IW4
|
||||
entries.emplace_back(parenRight);
|
||||
}
|
||||
else
|
||||
ConvertExpressionEntry(entries, unaryOperation->m_operand.get(), menu, item);
|
||||
ConvertExpressionEntry(gameStatement, entries, unaryOperation->m_operand.get(), menu, item);
|
||||
}
|
||||
|
||||
constexpr static expressionOperatorType_e BINARY_OPERATION_MAPPING[static_cast<unsigned>(SimpleBinaryOperationId::COUNT)]
|
||||
@ -198,7 +207,7 @@ namespace IW4
|
||||
OP_OR
|
||||
};
|
||||
|
||||
void ConvertExpressionEntryBinaryOperation(std::vector<expressionEntry>& entries, const SimpleExpressionBinaryOperation* binaryOperation, const CommonMenuDef* menu,
|
||||
void ConvertExpressionEntryBinaryOperation(Statement_s* gameStatement, std::vector<expressionEntry>& entries, const SimpleExpressionBinaryOperation* binaryOperation, const CommonMenuDef* menu,
|
||||
const CommonItemDef* item) const
|
||||
{
|
||||
if (binaryOperation->Operand1NeedsParenthesis())
|
||||
@ -208,7 +217,7 @@ namespace IW4
|
||||
parenLeft.data.op = OP_LEFTPAREN;
|
||||
entries.emplace_back(parenLeft);
|
||||
|
||||
ConvertExpressionEntry(entries, binaryOperation->m_operand1.get(), menu, item);
|
||||
ConvertExpressionEntry(gameStatement, entries, binaryOperation->m_operand1.get(), menu, item);
|
||||
|
||||
expressionEntry parenRight{};
|
||||
parenRight.type = EET_OPERATOR;
|
||||
@ -216,7 +225,7 @@ namespace IW4
|
||||
entries.emplace_back(parenRight);
|
||||
}
|
||||
else
|
||||
ConvertExpressionEntry(entries, binaryOperation->m_operand1.get(), menu, item);
|
||||
ConvertExpressionEntry(gameStatement, entries, binaryOperation->m_operand1.get(), menu, item);
|
||||
|
||||
assert(static_cast<unsigned>(binaryOperation->m_operation_type->m_id) < static_cast<unsigned>(SimpleBinaryOperationId::COUNT));
|
||||
expressionEntry operation{};
|
||||
@ -231,7 +240,7 @@ namespace IW4
|
||||
parenLeft.data.op = OP_LEFTPAREN;
|
||||
entries.emplace_back(parenLeft);
|
||||
|
||||
ConvertExpressionEntry(entries, binaryOperation->m_operand2.get(), menu, item);
|
||||
ConvertExpressionEntry(gameStatement, entries, binaryOperation->m_operand2.get(), menu, item);
|
||||
|
||||
expressionEntry parenRight{};
|
||||
parenRight.type = EET_OPERATOR;
|
||||
@ -239,7 +248,7 @@ namespace IW4
|
||||
entries.emplace_back(parenRight);
|
||||
}
|
||||
else
|
||||
ConvertExpressionEntry(entries, binaryOperation->m_operand2.get(), menu, item);
|
||||
ConvertExpressionEntry(gameStatement, entries, binaryOperation->m_operand2.get(), menu, item);
|
||||
}
|
||||
|
||||
void ConvertExpressionEntryExpressionValue(std::vector<expressionEntry>& entries, const SimpleExpressionValue* expressionValue) const
|
||||
@ -266,7 +275,7 @@ namespace IW4
|
||||
entries.emplace_back(entry);
|
||||
}
|
||||
|
||||
void ConvertExpressionEntry(std::vector<expressionEntry>& entries, const ISimpleExpression* expression, const CommonMenuDef* menu, const CommonItemDef* item) const
|
||||
void ConvertExpressionEntry(Statement_s* gameStatement, std::vector<expressionEntry>& entries, const ISimpleExpression* expression, const CommonMenuDef* menu, const CommonItemDef* item) const
|
||||
{
|
||||
if (!m_disable_optimizations && expression->IsStatic())
|
||||
{
|
||||
@ -279,15 +288,19 @@ namespace IW4
|
||||
}
|
||||
else if (const auto* binaryOperation = dynamic_cast<const SimpleExpressionBinaryOperation*>(expression))
|
||||
{
|
||||
ConvertExpressionEntryBinaryOperation(entries, binaryOperation, menu, item);
|
||||
ConvertExpressionEntryBinaryOperation(gameStatement, entries, binaryOperation, menu, item);
|
||||
}
|
||||
else if (const auto* unaryOperation = dynamic_cast<const SimpleExpressionUnaryOperation*>(expression))
|
||||
{
|
||||
ConvertExpressionEntryUnaryOperation(entries, unaryOperation, menu, item);
|
||||
ConvertExpressionEntryUnaryOperation(gameStatement, entries, unaryOperation, menu, item);
|
||||
}
|
||||
else if (const auto* functionCall = dynamic_cast<const CommonExpressionFunctionCall*>(expression))
|
||||
else if (const auto* baseFunctionCall = dynamic_cast<const CommonExpressionBaseFunctionCall*>(expression))
|
||||
{
|
||||
ConvertExpressionEntryFunctionCall(entries, functionCall, menu, item);
|
||||
ConvertExpressionEntryBaseFunctionCall(gameStatement, entries, baseFunctionCall, menu, item);
|
||||
}
|
||||
else if (const auto* customFunctionCall = dynamic_cast<const CommonExpressionCustomFunctionCall*>(expression))
|
||||
{
|
||||
ConvertExpressionEntryCustomFunctionCall(gameStatement, entries, customFunctionCall, menu, item);
|
||||
}
|
||||
else if (dynamic_cast<const SimpleExpressionConditionalOperator*>(expression))
|
||||
{
|
||||
@ -308,10 +321,11 @@ namespace IW4
|
||||
auto* statement = m_memory->Create<Statement_s>();
|
||||
statement->lastResult = Operand{};
|
||||
statement->lastExecuteTime = 0;
|
||||
statement->supportingData = nullptr; // Supporting data is set upon using it
|
||||
|
||||
std::vector<expressionEntry> expressionEntries;
|
||||
|
||||
ConvertExpressionEntry(expressionEntries, expression, menu, item);
|
||||
ConvertExpressionEntry(statement, expressionEntries, expression, menu, item);
|
||||
|
||||
auto* outputExpressionEntries = static_cast<expressionEntry*>(m_memory->Alloc(sizeof(expressionEntry) * expressionEntries.size()));
|
||||
memcpy(outputExpressionEntries, expressionEntries.data(), sizeof(expressionEntry) * expressionEntries.size());
|
||||
@ -319,9 +333,6 @@ namespace IW4
|
||||
statement->entries = outputExpressionEntries;
|
||||
statement->numEntries = static_cast<int>(expressionEntries.size());
|
||||
|
||||
// TODO: Add supporting data
|
||||
statement->supportingData = nullptr;
|
||||
|
||||
return statement;
|
||||
}
|
||||
|
||||
@ -646,8 +657,12 @@ namespace IW4
|
||||
|
||||
public:
|
||||
MenuConverterImpl(const bool disableOptimizations, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager)
|
||||
: AbstractMenuConverter(disableOptimizations, searchPath, memory, manager)
|
||||
: AbstractMenuConverter(disableOptimizations, searchPath, memory, manager),
|
||||
m_conversion_zone_state(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState<MenuConversionZoneState>()),
|
||||
m_parsing_zone_state(manager->GetAssetLoadingContext()->GetZoneAssetLoaderState<MenuAssetZoneState>())
|
||||
{
|
||||
assert(m_conversion_zone_state);
|
||||
assert(m_parsing_zone_state);
|
||||
}
|
||||
|
||||
_NODISCARD menuDef_t* ConvertMenu(const CommonMenuDef& commonMenu) const
|
||||
@ -697,6 +712,7 @@ namespace IW4
|
||||
menu->onESC = ConvertEventHandlerSet(commonMenu.m_on_esc.get(), &commonMenu);
|
||||
menu->onKey = ConvertKeyHandler(commonMenu.m_key_handlers, &commonMenu);
|
||||
menu->items = ConvertMenuItems(commonMenu);
|
||||
menu->expressionData = m_conversion_zone_state->m_supporting_data;
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
Reference in New Issue
Block a user