mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2025-04-20 16:15:43 +00:00
Make use of custom functions when converting menus
This commit is contained in:
parent
338de302d9
commit
7188b0946d
@ -1105,9 +1105,9 @@ namespace IW4
|
|||||||
VAL_INT = 0x0,
|
VAL_INT = 0x0,
|
||||||
VAL_FLOAT = 0x1,
|
VAL_FLOAT = 0x1,
|
||||||
VAL_STRING = 0x2,
|
VAL_STRING = 0x2,
|
||||||
NUM_INTERNAL_DATATYPES = 0x3,
|
|
||||||
VAL_FUNCTION = 0x3,
|
VAL_FUNCTION = 0x3,
|
||||||
NUM_DATATYPES = 0x4,
|
|
||||||
|
NUM_DATATYPES,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Operand
|
struct Operand
|
||||||
|
@ -2315,6 +2315,8 @@ namespace IW5
|
|||||||
EXP_FUNC_STATIC_DVAR_BOOL,
|
EXP_FUNC_STATIC_DVAR_BOOL,
|
||||||
EXP_FUNC_STATIC_DVAR_FLOAT,
|
EXP_FUNC_STATIC_DVAR_FLOAT,
|
||||||
EXP_FUNC_STATIC_DVAR_STRING,
|
EXP_FUNC_STATIC_DVAR_STRING,
|
||||||
|
|
||||||
|
EXP_FUNC_DYN_START
|
||||||
};
|
};
|
||||||
|
|
||||||
enum expressionEntryType : int
|
enum expressionEntryType : int
|
||||||
|
@ -37,6 +37,7 @@ public:
|
|||||||
return dynamic_cast<T*>(foundEntry->second.get());
|
return dynamic_cast<T*>(foundEntry->second.get());
|
||||||
|
|
||||||
auto newState = std::make_unique<T>();
|
auto newState = std::make_unique<T>();
|
||||||
|
newState->SetZone(m_zone);
|
||||||
auto* newStatePtr = newState.get();
|
auto* newStatePtr = newState.get();
|
||||||
m_zone_asset_loader_states.emplace(std::make_pair<std::type_index, std::unique_ptr<IZoneAssetLoaderState>>(typeid(T), std::move(newState)));
|
m_zone_asset_loader_states.emplace(std::make_pair<std::type_index, std::unique_ptr<IZoneAssetLoaderState>>(typeid(T), std::move(newState)));
|
||||||
return newStatePtr;
|
return newStatePtr;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "Zone/Zone.h"
|
||||||
|
|
||||||
class IZoneAssetLoaderState
|
class IZoneAssetLoaderState
|
||||||
{
|
{
|
||||||
@ -11,4 +12,9 @@ public:
|
|||||||
IZoneAssetLoaderState(IZoneAssetLoaderState&& other) noexcept = default;
|
IZoneAssetLoaderState(IZoneAssetLoaderState&& other) noexcept = default;
|
||||||
IZoneAssetLoaderState& operator=(const IZoneAssetLoaderState& other) = default;
|
IZoneAssetLoaderState& operator=(const IZoneAssetLoaderState& other) = default;
|
||||||
IZoneAssetLoaderState& operator=(IZoneAssetLoaderState&& other) noexcept = default;
|
IZoneAssetLoaderState& operator=(IZoneAssetLoaderState&& other) noexcept = default;
|
||||||
};
|
|
||||||
|
virtual void SetZone(Zone* zone)
|
||||||
|
{
|
||||||
|
// Do nothing by default
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -29,7 +29,7 @@ bool AssetLoaderMenuList::ShouldLoadMenuFile(const std::string& menuFilePath, me
|
|||||||
const auto alreadyLoadedFile = zoneState->m_loaded_files.find(menuFilePath);
|
const auto alreadyLoadedFile = zoneState->m_loaded_files.find(menuFilePath);
|
||||||
if (alreadyLoadedFile == zoneState->m_loaded_files.end())
|
if (alreadyLoadedFile == zoneState->m_loaded_files.end())
|
||||||
{
|
{
|
||||||
zoneState->m_loaded_files.emplace(menuFilePath);
|
zoneState->AddLoadedFile(menuFilePath);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,10 +50,10 @@ void AssetLoaderMenuList::AddMenuFilesToLoadToQueue(std::deque<std::string>& que
|
|||||||
void AssetLoaderMenuList::AddResultsToZoneState(menu::ParsingResult* parsingResult, menu::MenuAssetZoneState* zoneState)
|
void AssetLoaderMenuList::AddResultsToZoneState(menu::ParsingResult* parsingResult, menu::MenuAssetZoneState* zoneState)
|
||||||
{
|
{
|
||||||
for (auto& function : parsingResult->m_functions)
|
for (auto& function : parsingResult->m_functions)
|
||||||
zoneState->m_functions.emplace_back(std::move(function));
|
zoneState->AddFunction(std::move(function));
|
||||||
|
|
||||||
for (auto& menu : parsingResult->m_menus)
|
for (auto& menu : parsingResult->m_menus)
|
||||||
zoneState->m_menus.emplace_back(std::move(menu));
|
zoneState->AddMenu(std::move(menu));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AssetLoaderMenuList::ProcessParsedResults(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, menu::ParsingResult* parsingResult,
|
bool AssetLoaderMenuList::ProcessParsedResults(const std::string& assetName, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager, menu::ParsingResult* parsingResult,
|
||||||
|
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 <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "MenuConversionZoneStateIW4.h"
|
||||||
#include "Game/IW4/MenuConstantsIW4.h"
|
#include "Game/IW4/MenuConstantsIW4.h"
|
||||||
#include "Game/T5/T5_Assets.h"
|
|
||||||
#include "Utils/ClassUtils.h"
|
#include "Utils/ClassUtils.h"
|
||||||
#include "Menu/AbstractMenuConverter.h"
|
#include "Menu/AbstractMenuConverter.h"
|
||||||
|
#include "Parsing/Menu/MenuAssetZoneState.h"
|
||||||
#include "Parsing/Menu/Domain/EventHandler/CommonEventHandlerCondition.h"
|
#include "Parsing/Menu/Domain/EventHandler/CommonEventHandlerCondition.h"
|
||||||
#include "Parsing/Menu/Domain/EventHandler/CommonEventHandlerScript.h"
|
#include "Parsing/Menu/Domain/EventHandler/CommonEventHandlerScript.h"
|
||||||
#include "Parsing/Menu/Domain/EventHandler/CommonEventHandlerSetLocalVar.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/SimpleExpressionBinaryOperation.h"
|
||||||
#include "Parsing/Simple/Expression/SimpleExpressionConditionalOperator.h"
|
#include "Parsing/Simple/Expression/SimpleExpressionConditionalOperator.h"
|
||||||
#include "Parsing/Simple/Expression/SimpleExpressionUnaryOperation.h"
|
#include "Parsing/Simple/Expression/SimpleExpressionUnaryOperation.h"
|
||||||
@ -22,6 +24,9 @@ namespace IW4
|
|||||||
{
|
{
|
||||||
class MenuConverterImpl : public AbstractMenuConverter
|
class MenuConverterImpl : public AbstractMenuConverter
|
||||||
{
|
{
|
||||||
|
MenuConversionZoneState* m_conversion_zone_state;
|
||||||
|
MenuAssetZoneState* m_parsing_zone_state;
|
||||||
|
|
||||||
static void ApplyMenuDefaults(menuDef_t* menu)
|
static void ApplyMenuDefaults(menuDef_t* menu)
|
||||||
{
|
{
|
||||||
memset(menu, 0, sizeof(menuDef_t));
|
memset(menu, 0, sizeof(menuDef_t));
|
||||||
@ -90,39 +95,16 @@ namespace IW4
|
|||||||
return static_cast<Material*>(materialDependency->m_ptr);
|
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{};
|
expressionEntry functionEntry{};
|
||||||
functionEntry.type = EET_OPERATOR;
|
functionEntry.type = EET_OPERATOR;
|
||||||
functionEntry.data.op = foundMapping->second;
|
functionEntry.data.op = static_cast<int>(functionCall->m_function_index);
|
||||||
entries.emplace_back(functionEntry);
|
entries.emplace_back(functionEntry);
|
||||||
|
|
||||||
auto firstArg = true;
|
auto firstArg = true;
|
||||||
for(const auto& arg : functionCall->m_args)
|
for (const auto& arg : functionCall->m_args)
|
||||||
{
|
{
|
||||||
if (!firstArg)
|
if (!firstArg)
|
||||||
{
|
{
|
||||||
@ -134,7 +116,7 @@ namespace IW4
|
|||||||
else
|
else
|
||||||
firstArg = false;
|
firstArg = false;
|
||||||
|
|
||||||
ConvertExpressionEntry(entries, arg.get(), menu, item);
|
ConvertExpressionEntry(gameStatement, entries, arg.get(), menu, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
expressionEntry parenRight{};
|
expressionEntry parenRight{};
|
||||||
@ -143,6 +125,33 @@ namespace IW4
|
|||||||
entries.emplace_back(parenRight);
|
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)]
|
constexpr static expressionOperatorType_e UNARY_OPERATION_MAPPING[static_cast<unsigned>(SimpleUnaryOperationId::COUNT)]
|
||||||
{
|
{
|
||||||
OP_NOT,
|
OP_NOT,
|
||||||
@ -150,7 +159,7 @@ namespace IW4
|
|||||||
OP_SUBTRACT
|
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
|
const CommonItemDef* item) const
|
||||||
{
|
{
|
||||||
assert(static_cast<unsigned>(unaryOperation->m_operation_type->m_id) < static_cast<unsigned>(SimpleUnaryOperationId::COUNT));
|
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;
|
parenLeft.data.op = OP_LEFTPAREN;
|
||||||
entries.emplace_back(parenLeft);
|
entries.emplace_back(parenLeft);
|
||||||
|
|
||||||
ConvertExpressionEntry(entries, unaryOperation->m_operand.get(), menu, item);
|
ConvertExpressionEntry(gameStatement, entries, unaryOperation->m_operand.get(), menu, item);
|
||||||
|
|
||||||
expressionEntry parenRight{};
|
expressionEntry parenRight{};
|
||||||
parenRight.type = EET_OPERATOR;
|
parenRight.type = EET_OPERATOR;
|
||||||
@ -174,7 +183,7 @@ namespace IW4
|
|||||||
entries.emplace_back(parenRight);
|
entries.emplace_back(parenRight);
|
||||||
}
|
}
|
||||||
else
|
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)]
|
constexpr static expressionOperatorType_e BINARY_OPERATION_MAPPING[static_cast<unsigned>(SimpleBinaryOperationId::COUNT)]
|
||||||
@ -198,7 +207,7 @@ namespace IW4
|
|||||||
OP_OR
|
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
|
const CommonItemDef* item) const
|
||||||
{
|
{
|
||||||
if (binaryOperation->Operand1NeedsParenthesis())
|
if (binaryOperation->Operand1NeedsParenthesis())
|
||||||
@ -208,7 +217,7 @@ namespace IW4
|
|||||||
parenLeft.data.op = OP_LEFTPAREN;
|
parenLeft.data.op = OP_LEFTPAREN;
|
||||||
entries.emplace_back(parenLeft);
|
entries.emplace_back(parenLeft);
|
||||||
|
|
||||||
ConvertExpressionEntry(entries, binaryOperation->m_operand1.get(), menu, item);
|
ConvertExpressionEntry(gameStatement, entries, binaryOperation->m_operand1.get(), menu, item);
|
||||||
|
|
||||||
expressionEntry parenRight{};
|
expressionEntry parenRight{};
|
||||||
parenRight.type = EET_OPERATOR;
|
parenRight.type = EET_OPERATOR;
|
||||||
@ -216,7 +225,7 @@ namespace IW4
|
|||||||
entries.emplace_back(parenRight);
|
entries.emplace_back(parenRight);
|
||||||
}
|
}
|
||||||
else
|
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));
|
assert(static_cast<unsigned>(binaryOperation->m_operation_type->m_id) < static_cast<unsigned>(SimpleBinaryOperationId::COUNT));
|
||||||
expressionEntry operation{};
|
expressionEntry operation{};
|
||||||
@ -231,7 +240,7 @@ namespace IW4
|
|||||||
parenLeft.data.op = OP_LEFTPAREN;
|
parenLeft.data.op = OP_LEFTPAREN;
|
||||||
entries.emplace_back(parenLeft);
|
entries.emplace_back(parenLeft);
|
||||||
|
|
||||||
ConvertExpressionEntry(entries, binaryOperation->m_operand2.get(), menu, item);
|
ConvertExpressionEntry(gameStatement, entries, binaryOperation->m_operand2.get(), menu, item);
|
||||||
|
|
||||||
expressionEntry parenRight{};
|
expressionEntry parenRight{};
|
||||||
parenRight.type = EET_OPERATOR;
|
parenRight.type = EET_OPERATOR;
|
||||||
@ -239,7 +248,7 @@ namespace IW4
|
|||||||
entries.emplace_back(parenRight);
|
entries.emplace_back(parenRight);
|
||||||
}
|
}
|
||||||
else
|
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
|
void ConvertExpressionEntryExpressionValue(std::vector<expressionEntry>& entries, const SimpleExpressionValue* expressionValue) const
|
||||||
@ -266,7 +275,7 @@ namespace IW4
|
|||||||
entries.emplace_back(entry);
|
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())
|
if (!m_disable_optimizations && expression->IsStatic())
|
||||||
{
|
{
|
||||||
@ -279,15 +288,19 @@ namespace IW4
|
|||||||
}
|
}
|
||||||
else if (const auto* binaryOperation = dynamic_cast<const SimpleExpressionBinaryOperation*>(expression))
|
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))
|
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))
|
else if (dynamic_cast<const SimpleExpressionConditionalOperator*>(expression))
|
||||||
{
|
{
|
||||||
@ -308,10 +321,11 @@ namespace IW4
|
|||||||
auto* statement = m_memory->Create<Statement_s>();
|
auto* statement = m_memory->Create<Statement_s>();
|
||||||
statement->lastResult = Operand{};
|
statement->lastResult = Operand{};
|
||||||
statement->lastExecuteTime = 0;
|
statement->lastExecuteTime = 0;
|
||||||
|
statement->supportingData = nullptr; // Supporting data is set upon using it
|
||||||
|
|
||||||
std::vector<expressionEntry> expressionEntries;
|
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()));
|
auto* outputExpressionEntries = static_cast<expressionEntry*>(m_memory->Alloc(sizeof(expressionEntry) * expressionEntries.size()));
|
||||||
memcpy(outputExpressionEntries, expressionEntries.data(), sizeof(expressionEntry) * expressionEntries.size());
|
memcpy(outputExpressionEntries, expressionEntries.data(), sizeof(expressionEntry) * expressionEntries.size());
|
||||||
@ -319,9 +333,6 @@ namespace IW4
|
|||||||
statement->entries = outputExpressionEntries;
|
statement->entries = outputExpressionEntries;
|
||||||
statement->numEntries = static_cast<int>(expressionEntries.size());
|
statement->numEntries = static_cast<int>(expressionEntries.size());
|
||||||
|
|
||||||
// TODO: Add supporting data
|
|
||||||
statement->supportingData = nullptr;
|
|
||||||
|
|
||||||
return statement;
|
return statement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -646,8 +657,12 @@ namespace IW4
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
MenuConverterImpl(const bool disableOptimizations, ISearchPath* searchPath, MemoryManager* memory, IAssetLoadingManager* manager)
|
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
|
_NODISCARD menuDef_t* ConvertMenu(const CommonMenuDef& commonMenu) const
|
||||||
@ -697,6 +712,7 @@ namespace IW4
|
|||||||
menu->onESC = ConvertEventHandlerSet(commonMenu.m_on_esc.get(), &commonMenu);
|
menu->onESC = ConvertEventHandlerSet(commonMenu.m_on_esc.get(), &commonMenu);
|
||||||
menu->onKey = ConvertKeyHandler(commonMenu.m_key_handlers, &commonMenu);
|
menu->onKey = ConvertKeyHandler(commonMenu.m_key_handlers, &commonMenu);
|
||||||
menu->items = ConvertMenuItems(commonMenu);
|
menu->items = ConvertMenuItems(commonMenu);
|
||||||
|
menu->expressionData = m_conversion_zone_state->m_supporting_data;
|
||||||
|
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
#include "CommonExpressionBaseFunctionCall.h"
|
||||||
|
|
||||||
|
using namespace menu;
|
||||||
|
|
||||||
|
CommonExpressionBaseFunctionCall::CommonExpressionBaseFunctionCall(std::string functionName, size_t functionIndex)
|
||||||
|
: m_function_name(std::move(functionName)),
|
||||||
|
m_function_index(functionIndex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommonExpressionBaseFunctionCall::Equals(const ISimpleExpression* other) const
|
||||||
|
{
|
||||||
|
const auto otherFunctionCall = dynamic_cast<const CommonExpressionBaseFunctionCall*>(other);
|
||||||
|
|
||||||
|
if (!otherFunctionCall
|
||||||
|
|| m_function_name != otherFunctionCall->m_function_name
|
||||||
|
|| m_function_index != otherFunctionCall->m_function_index
|
||||||
|
|| m_args.size() != otherFunctionCall->m_args.size())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i = 0u; i < m_args.size(); i++)
|
||||||
|
{
|
||||||
|
const auto* arg = m_args[i].get();
|
||||||
|
const auto* otherArg = otherFunctionCall->m_args[i].get();
|
||||||
|
|
||||||
|
if (!arg->Equals(otherArg))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommonExpressionBaseFunctionCall::IsStatic() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleExpressionValue CommonExpressionBaseFunctionCall::Evaluate() const
|
||||||
|
{
|
||||||
|
return SimpleExpressionValue(0);
|
||||||
|
}
|
@ -5,13 +5,14 @@
|
|||||||
|
|
||||||
namespace menu
|
namespace menu
|
||||||
{
|
{
|
||||||
class CommonExpressionFunctionCall final : public ISimpleExpression
|
class CommonExpressionBaseFunctionCall final : public ISimpleExpression
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string m_function_name;
|
std::string m_function_name;
|
||||||
|
size_t m_function_index;
|
||||||
std::vector<std::unique_ptr<ISimpleExpression>> m_args;
|
std::vector<std::unique_ptr<ISimpleExpression>> m_args;
|
||||||
|
|
||||||
explicit CommonExpressionFunctionCall(std::string functionName);
|
CommonExpressionBaseFunctionCall(std::string functionName, size_t functionIndex);
|
||||||
|
|
||||||
_NODISCARD bool Equals(const ISimpleExpression* other) const override;
|
_NODISCARD bool Equals(const ISimpleExpression* other) const override;
|
||||||
_NODISCARD bool IsStatic() const override;
|
_NODISCARD bool IsStatic() const override;
|
@ -0,0 +1,24 @@
|
|||||||
|
#include "CommonExpressionCustomFunctionCall.h"
|
||||||
|
|
||||||
|
using namespace menu;
|
||||||
|
|
||||||
|
CommonExpressionCustomFunctionCall::CommonExpressionCustomFunctionCall(std::string functionName)
|
||||||
|
: m_function_name(std::move(functionName))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommonExpressionCustomFunctionCall::Equals(const ISimpleExpression* other) const
|
||||||
|
{
|
||||||
|
const auto otherFunctionCall = dynamic_cast<const CommonExpressionCustomFunctionCall*>(other);
|
||||||
|
return otherFunctionCall && m_function_name == otherFunctionCall->m_function_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommonExpressionCustomFunctionCall::IsStatic() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleExpressionValue CommonExpressionCustomFunctionCall::Evaluate() const
|
||||||
|
{
|
||||||
|
return SimpleExpressionValue(0);
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Parsing/Simple/Expression/ISimpleExpression.h"
|
||||||
|
|
||||||
|
namespace menu
|
||||||
|
{
|
||||||
|
class CommonExpressionCustomFunctionCall final : public ISimpleExpression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::string m_function_name;
|
||||||
|
|
||||||
|
explicit CommonExpressionCustomFunctionCall(std::string functionName);
|
||||||
|
|
||||||
|
_NODISCARD bool Equals(const ISimpleExpression* other) const override;
|
||||||
|
_NODISCARD bool IsStatic() const override;
|
||||||
|
_NODISCARD SimpleExpressionValue Evaluate() const override;
|
||||||
|
};
|
||||||
|
}
|
@ -1,41 +0,0 @@
|
|||||||
#include "CommonExpressionFunctionCall.h"
|
|
||||||
|
|
||||||
using namespace menu;
|
|
||||||
|
|
||||||
CommonExpressionFunctionCall::CommonExpressionFunctionCall(std::string functionName)
|
|
||||||
: m_function_name(std::move(functionName))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CommonExpressionFunctionCall::Equals(const ISimpleExpression* other) const
|
|
||||||
{
|
|
||||||
const auto otherFunctionCall = dynamic_cast<const CommonExpressionFunctionCall*>(other);
|
|
||||||
|
|
||||||
if (!otherFunctionCall
|
|
||||||
|| m_function_name != otherFunctionCall->m_function_name
|
|
||||||
|| m_args.size() != otherFunctionCall->m_args.size())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto i = 0u; i < m_args.size(); i++)
|
|
||||||
{
|
|
||||||
const auto* arg = m_args[i].get();
|
|
||||||
const auto* otherArg = otherFunctionCall->m_args[i].get();
|
|
||||||
|
|
||||||
if (!arg->Equals(otherArg))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CommonExpressionFunctionCall::IsStatic() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleExpressionValue CommonExpressionFunctionCall::Evaluate() const
|
|
||||||
{
|
|
||||||
return SimpleExpressionValue(0);
|
|
||||||
}
|
|
@ -1,7 +1,12 @@
|
|||||||
#include "MenuExpressionMatchers.h"
|
#include "MenuExpressionMatchers.h"
|
||||||
|
|
||||||
#include "MenuMatcherFactory.h"
|
#include "MenuMatcherFactory.h"
|
||||||
#include "Parsing/Menu/Domain/Expression/CommonExpressionFunctionCall.h"
|
#include "Game/IW4/IW4.h"
|
||||||
|
#include "Game/IW5/IW5.h"
|
||||||
|
#include "Game/IW4/MenuConstantsIW4.h"
|
||||||
|
#include "Game/IW5/MenuConstantsIW5.h"
|
||||||
|
#include "Parsing/Menu/Domain/Expression/CommonExpressionBaseFunctionCall.h"
|
||||||
|
#include "Parsing/Menu/Domain/Expression/CommonExpressionCustomFunctionCall.h"
|
||||||
|
|
||||||
using namespace menu;
|
using namespace menu;
|
||||||
|
|
||||||
@ -10,9 +15,14 @@ static constexpr int TAG_EXPRESSION_FUNCTION_CALL_END = SimpleExpressionMatchers
|
|||||||
|
|
||||||
static constexpr int CAPTURE_FUNCTION_NAME = SimpleExpressionMatchers::CAPTURE_OFFSET_EXPRESSION_EXT + 1;
|
static constexpr int CAPTURE_FUNCTION_NAME = SimpleExpressionMatchers::CAPTURE_OFFSET_EXPRESSION_EXT + 1;
|
||||||
|
|
||||||
|
MenuExpressionMatchers::MenuExpressionMatchers(const MenuFileParserState* state)
|
||||||
|
: SimpleExpressionMatchers(true, true, true, true, true),
|
||||||
|
m_state(state)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
MenuExpressionMatchers::MenuExpressionMatchers()
|
MenuExpressionMatchers::MenuExpressionMatchers()
|
||||||
: SimpleExpressionMatchers(true, true, true, true, true)
|
: MenuExpressionMatchers(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,17 +46,73 @@ std::unique_ptr<SimpleExpressionMatchers::matcher_t> MenuExpressionMatchers::Par
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::map<std::string, size_t>& MenuExpressionMatchers::GetBaseFunctionMapForFeatureLevel(const FeatureLevel featureLevel)
|
||||||
|
{
|
||||||
|
if(featureLevel == FeatureLevel::IW4)
|
||||||
|
{
|
||||||
|
static std::map<std::string, size_t> iw4FunctionMap;
|
||||||
|
static bool iw4FunctionMapInitialized = false;
|
||||||
|
|
||||||
|
if(!iw4FunctionMapInitialized)
|
||||||
|
{
|
||||||
|
for(size_t i = IW4::expressionFunction_e::EXP_FUNC_DYN_START; i < std::extent_v<decltype(IW4::g_expFunctionNames)>; i++)
|
||||||
|
iw4FunctionMap.emplace(std::make_pair(IW4::g_expFunctionNames[i], i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return iw4FunctionMap;
|
||||||
|
}
|
||||||
|
if(featureLevel == FeatureLevel::IW5)
|
||||||
|
{
|
||||||
|
static std::map<std::string, size_t> iw5FunctionMap;
|
||||||
|
static bool iw5FunctionMapInitialized = false;
|
||||||
|
|
||||||
|
if(!iw5FunctionMapInitialized)
|
||||||
|
{
|
||||||
|
for(size_t i = IW5::expressionFunction_e::EXP_FUNC_DYN_START; i < std::extent_v<decltype(IW5::g_expFunctionNames)>; i++)
|
||||||
|
iw5FunctionMap.emplace(std::make_pair(IW5::g_expFunctionNames[i], i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return iw5FunctionMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(false);
|
||||||
|
throw ParsingException(TokenPos(), "Feature level has no functions registered!!");
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<ISimpleExpression> MenuExpressionMatchers::ProcessOperandExtension(SequenceResult<SimpleParserValue>& result) const
|
std::unique_ptr<ISimpleExpression> MenuExpressionMatchers::ProcessOperandExtension(SequenceResult<SimpleParserValue>& result) const
|
||||||
{
|
{
|
||||||
|
assert(m_state);
|
||||||
|
if(m_state == nullptr)
|
||||||
|
throw ParsingException(TokenPos(), "No state when processing menu operand extension!!");
|
||||||
|
|
||||||
if (result.PeekAndRemoveIfTag(TAG_EXPRESSION_FUNCTION_CALL) != TAG_EXPRESSION_FUNCTION_CALL)
|
if (result.PeekAndRemoveIfTag(TAG_EXPRESSION_FUNCTION_CALL) != TAG_EXPRESSION_FUNCTION_CALL)
|
||||||
throw ParsingException(TokenPos(), "Menu Operand Extension must be function call");
|
throw ParsingException(TokenPos(), "Menu Operand Extension must be function call");
|
||||||
|
|
||||||
auto functionCall = std::make_unique<CommonExpressionFunctionCall>(result.NextCapture(CAPTURE_FUNCTION_NAME).IdentifierValue());
|
const auto& functionCallToken = result.NextCapture(CAPTURE_FUNCTION_NAME);
|
||||||
|
auto functionCallName = functionCallToken.IdentifierValue();
|
||||||
|
|
||||||
while (result.PeekAndRemoveIfTag(TAG_EXPRESSION_FUNCTION_CALL_END) != TAG_EXPRESSION_FUNCTION_CALL_END)
|
const auto& baseFunctionMap = GetBaseFunctionMapForFeatureLevel(m_state->m_feature_level);
|
||||||
|
const auto foundBaseFunction = baseFunctionMap.find(functionCallName);
|
||||||
|
if(foundBaseFunction != baseFunctionMap.end())
|
||||||
{
|
{
|
||||||
functionCall->m_args.emplace_back(ProcessExpression(result));
|
auto functionCall = std::make_unique<CommonExpressionBaseFunctionCall>(std::move(functionCallName), foundBaseFunction->second);
|
||||||
|
while (result.PeekAndRemoveIfTag(TAG_EXPRESSION_FUNCTION_CALL_END) != TAG_EXPRESSION_FUNCTION_CALL_END)
|
||||||
|
{
|
||||||
|
functionCall->m_args.emplace_back(ProcessExpression(result));
|
||||||
|
}
|
||||||
|
return std::move(functionCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::move(functionCall);
|
const auto foundCustomFunction = m_state->m_functions_by_name.find(functionCallName);
|
||||||
}
|
if(foundCustomFunction != m_state->m_functions_by_name.end())
|
||||||
|
{
|
||||||
|
auto functionCall = std::make_unique<CommonExpressionCustomFunctionCall>(std::move(functionCallName));
|
||||||
|
|
||||||
|
if(result.PeekAndRemoveIfTag(TAG_EXPRESSION_FUNCTION_CALL_END) != TAG_EXPRESSION_FUNCTION_CALL_END)
|
||||||
|
throw ParsingException(functionCallToken.GetPos(), "Custom functions cannot be called with arguments");
|
||||||
|
|
||||||
|
return std::move(functionCall);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw ParsingException(functionCallToken.GetPos(), "Unknown function");
|
||||||
|
}
|
||||||
|
@ -2,14 +2,20 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include "Parsing/Menu/MenuFileParserState.h"
|
||||||
#include "Parsing/Simple/Expression/SimpleExpressionMatchers.h"
|
#include "Parsing/Simple/Expression/SimpleExpressionMatchers.h"
|
||||||
|
|
||||||
namespace menu
|
namespace menu
|
||||||
{
|
{
|
||||||
class MenuExpressionMatchers final : public SimpleExpressionMatchers
|
class MenuExpressionMatchers final : public SimpleExpressionMatchers
|
||||||
{
|
{
|
||||||
|
const MenuFileParserState* m_state;
|
||||||
|
|
||||||
|
static const std::map<std::string, size_t>& GetBaseFunctionMapForFeatureLevel(FeatureLevel featureLevel);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MenuExpressionMatchers();
|
MenuExpressionMatchers();
|
||||||
|
explicit MenuExpressionMatchers(const MenuFileParserState* state);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::unique_ptr<matcher_t> ParseOperandExtension(const supplier_t* labelSupplier) const override;
|
std::unique_ptr<matcher_t> ParseOperandExtension(const supplier_t* labelSupplier) const override;
|
||||||
|
@ -101,7 +101,7 @@ std::string& MenuMatcherFactory::TokenTextValue(const SimpleParserValue& value)
|
|||||||
return value.StringValue();
|
return value.StringValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
int MenuMatcherFactory::TokenIntExpressionValue(SequenceResult<SimpleParserValue>& result)
|
int MenuMatcherFactory::TokenIntExpressionValue(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result)
|
||||||
{
|
{
|
||||||
const auto nextTag = result.PeekTag();
|
const auto nextTag = result.PeekTag();
|
||||||
|
|
||||||
@ -115,7 +115,7 @@ int MenuMatcherFactory::TokenIntExpressionValue(SequenceResult<SimpleParserValue
|
|||||||
if (nextTag == TAG_EXPRESSION)
|
if (nextTag == TAG_EXPRESSION)
|
||||||
{
|
{
|
||||||
result.NextTag();
|
result.NextTag();
|
||||||
const auto expression = MenuExpressionMatchers().ProcessExpression(result);
|
const auto expression = MenuExpressionMatchers(state).ProcessExpression(result);
|
||||||
|
|
||||||
if (!expression || !expression->IsStatic())
|
if (!expression || !expression->IsStatic())
|
||||||
throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), "Not a valid static expression");
|
throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), "Not a valid static expression");
|
||||||
@ -131,7 +131,7 @@ int MenuMatcherFactory::TokenIntExpressionValue(SequenceResult<SimpleParserValue
|
|||||||
throw ParsingException(TokenPos(), "TokenIntExpressionValue must be expression or int");
|
throw ParsingException(TokenPos(), "TokenIntExpressionValue must be expression or int");
|
||||||
}
|
}
|
||||||
|
|
||||||
double MenuMatcherFactory::TokenNumericExpressionValue(SequenceResult<SimpleParserValue>& result)
|
double MenuMatcherFactory::TokenNumericExpressionValue(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result)
|
||||||
{
|
{
|
||||||
const auto nextTag = result.PeekTag();
|
const auto nextTag = result.PeekTag();
|
||||||
|
|
||||||
@ -145,7 +145,7 @@ double MenuMatcherFactory::TokenNumericExpressionValue(SequenceResult<SimplePars
|
|||||||
if (nextTag == TAG_EXPRESSION)
|
if (nextTag == TAG_EXPRESSION)
|
||||||
{
|
{
|
||||||
result.NextTag();
|
result.NextTag();
|
||||||
const auto expression = MenuExpressionMatchers().ProcessExpression(result);
|
const auto expression = MenuExpressionMatchers(state).ProcessExpression(result);
|
||||||
|
|
||||||
if (!expression || !expression->IsStatic())
|
if (!expression || !expression->IsStatic())
|
||||||
throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), "Not a valid static expression");
|
throw ParsingException(result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), "Not a valid static expression");
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "Parsing/Sequence/SequenceResult.h"
|
#include "Parsing/Sequence/SequenceResult.h"
|
||||||
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
|
#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h"
|
||||||
|
#include "Parsing/Menu/MenuFileParserState.h"
|
||||||
|
|
||||||
namespace menu
|
namespace menu
|
||||||
{
|
{
|
||||||
@ -30,7 +31,7 @@ namespace menu
|
|||||||
_NODISCARD static double TokenNumericFloatingPointValue(const SimpleParserValue& value);
|
_NODISCARD static double TokenNumericFloatingPointValue(const SimpleParserValue& value);
|
||||||
_NODISCARD static std::string& TokenTextValue(const SimpleParserValue& value);
|
_NODISCARD static std::string& TokenTextValue(const SimpleParserValue& value);
|
||||||
|
|
||||||
_NODISCARD static int TokenIntExpressionValue(SequenceResult<SimpleParserValue>& result);
|
_NODISCARD static int TokenIntExpressionValue(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result);
|
||||||
_NODISCARD static double TokenNumericExpressionValue(SequenceResult<SimpleParserValue>& result);
|
_NODISCARD static double TokenNumericExpressionValue(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
19
src/ObjLoading/Parsing/Menu/MenuAssetZoneState.cpp
Normal file
19
src/ObjLoading/Parsing/Menu/MenuAssetZoneState.cpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#include "MenuAssetZoneState.h"
|
||||||
|
|
||||||
|
using namespace menu;
|
||||||
|
|
||||||
|
void MenuAssetZoneState::AddLoadedFile(std::string loadedFileName)
|
||||||
|
{
|
||||||
|
m_loaded_files.emplace(std::move(loadedFileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuAssetZoneState::AddFunction(std::unique_ptr<CommonFunctionDef> function)
|
||||||
|
{
|
||||||
|
m_functions_by_name.emplace(std::make_pair(function->m_name, function.get()));
|
||||||
|
m_functions.emplace_back(std::move(function));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MenuAssetZoneState::AddMenu(std::unique_ptr<CommonMenuDef> menu)
|
||||||
|
{
|
||||||
|
m_menus.emplace_back(std::move(menu));
|
||||||
|
}
|
@ -16,6 +16,12 @@ namespace menu
|
|||||||
std::vector<std::unique_ptr<CommonFunctionDef>> m_functions;
|
std::vector<std::unique_ptr<CommonFunctionDef>> m_functions;
|
||||||
std::vector<std::unique_ptr<CommonMenuDef>> m_menus;
|
std::vector<std::unique_ptr<CommonMenuDef>> m_menus;
|
||||||
|
|
||||||
|
std::map<std::string, CommonFunctionDef*> m_functions_by_name;
|
||||||
|
|
||||||
MenuAssetZoneState() = default;
|
MenuAssetZoneState() = default;
|
||||||
|
|
||||||
|
void AddLoadedFile(std::string loadedFileName);
|
||||||
|
void AddFunction(std::unique_ptr<CommonFunctionDef> function);
|
||||||
|
void AddMenu(std::unique_ptr<CommonMenuDef> menu);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -582,7 +582,7 @@ namespace menu::event_handler_set_scope_sequences
|
|||||||
protected:
|
protected:
|
||||||
void ProcessMatch(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result) const override
|
void ProcessMatch(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result) const override
|
||||||
{
|
{
|
||||||
const MenuExpressionMatchers expressionMatchers;
|
const MenuExpressionMatchers expressionMatchers(state);
|
||||||
|
|
||||||
const auto typeTag = static_cast<SetLocalVarType>(result.NextTag());
|
const auto typeTag = static_cast<SetLocalVarType>(result.NextTag());
|
||||||
const auto& varNameToken = result.NextCapture(CAPTURE_VAR_NAME);
|
const auto& varNameToken = result.NextCapture(CAPTURE_VAR_NAME);
|
||||||
@ -623,7 +623,7 @@ namespace menu::event_handler_set_scope_sequences
|
|||||||
protected:
|
protected:
|
||||||
void ProcessMatch(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result) const override
|
void ProcessMatch(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result) const override
|
||||||
{
|
{
|
||||||
const MenuExpressionMatchers expressionMatchers;
|
const MenuExpressionMatchers expressionMatchers(state);
|
||||||
auto expression = expressionMatchers.ProcessExpression(result);
|
auto expression = expressionMatchers.ProcessExpression(result);
|
||||||
|
|
||||||
if (!expression)
|
if (!expression)
|
||||||
@ -668,7 +668,7 @@ namespace menu::event_handler_set_scope_sequences
|
|||||||
protected:
|
protected:
|
||||||
void ProcessMatch(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result) const override
|
void ProcessMatch(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result) const override
|
||||||
{
|
{
|
||||||
const MenuExpressionMatchers expressionMatchers;
|
const MenuExpressionMatchers expressionMatchers(state);
|
||||||
auto expression = expressionMatchers.ProcessExpression(result);
|
auto expression = expressionMatchers.ProcessExpression(result);
|
||||||
|
|
||||||
if (!expression)
|
if (!expression)
|
||||||
@ -708,9 +708,7 @@ namespace menu::event_handler_set_scope_sequences
|
|||||||
{
|
{
|
||||||
const ScriptMatcherFactory create(this);
|
const ScriptMatcherFactory create(this);
|
||||||
const MenuExpressionMatchers expressionMatchers;
|
const MenuExpressionMatchers expressionMatchers;
|
||||||
|
|
||||||
AddLabeledMatchers(expressionMatchers.Expression(this), MenuExpressionMatchers::LABEL_EXPRESSION);
|
|
||||||
|
|
||||||
AddMatchers({
|
AddMatchers({
|
||||||
create.Char('}'),
|
create.Char('}'),
|
||||||
create.Keyword("else").Capture(CAPTURE_KEYWORD),
|
create.Keyword("else").Capture(CAPTURE_KEYWORD),
|
||||||
|
@ -22,10 +22,10 @@ GenericColorPropertySequence::GenericColorPropertySequence(std::string keywordNa
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
double GenericColorPropertySequence::ReadColorValue(SequenceResult<SimpleParserValue>& result)
|
double GenericColorPropertySequence::ReadColorValue(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result)
|
||||||
{
|
{
|
||||||
if (result.PeekAndRemoveIfTag(TAG_COLOR) == TAG_COLOR)
|
if (result.PeekAndRemoveIfTag(TAG_COLOR) == TAG_COLOR)
|
||||||
return MenuMatcherFactory::TokenNumericExpressionValue(result);
|
return MenuMatcherFactory::TokenNumericExpressionValue(state, result);
|
||||||
|
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
@ -35,10 +35,10 @@ void GenericColorPropertySequence::ProcessMatch(MenuFileParserState* state, Sequ
|
|||||||
if (m_set_callback)
|
if (m_set_callback)
|
||||||
{
|
{
|
||||||
CommonColor color{};
|
CommonColor color{};
|
||||||
color.r = ReadColorValue(result);
|
color.r = ReadColorValue(state, result);
|
||||||
color.g = ReadColorValue(result);
|
color.g = ReadColorValue(state, result);
|
||||||
color.b = ReadColorValue(result);
|
color.b = ReadColorValue(state, result);
|
||||||
color.a = ReadColorValue(result);
|
color.a = ReadColorValue(state, result);
|
||||||
|
|
||||||
m_set_callback(state, result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), color);
|
m_set_callback(state, result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), color);
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ namespace menu
|
|||||||
|
|
||||||
const callback_t m_set_callback;
|
const callback_t m_set_callback;
|
||||||
|
|
||||||
static double ReadColorValue(SequenceResult<SimpleParserValue>& result);
|
static double ReadColorValue(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void ProcessMatch(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result) const override;
|
void ProcessMatch(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result) const override;
|
||||||
|
@ -65,7 +65,7 @@ void GenericExpressionPropertySequence::ProcessMatch(MenuFileParserState* state,
|
|||||||
{
|
{
|
||||||
if (m_set_callback)
|
if (m_set_callback)
|
||||||
{
|
{
|
||||||
const MenuExpressionMatchers expressionMatchers;
|
const MenuExpressionMatchers expressionMatchers(state);
|
||||||
auto expression = expressionMatchers.ProcessExpression(result);
|
auto expression = expressionMatchers.ProcessExpression(result);
|
||||||
m_set_callback(state, result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(expression));
|
m_set_callback(state, result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), std::move(expression));
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ void GenericFloatingPointPropertySequence::ProcessMatch(MenuFileParserState* sta
|
|||||||
{
|
{
|
||||||
if (m_set_callback)
|
if (m_set_callback)
|
||||||
{
|
{
|
||||||
const auto value = MenuMatcherFactory::TokenNumericExpressionValue(result);
|
const auto value = MenuMatcherFactory::TokenNumericExpressionValue(state, result);
|
||||||
m_set_callback(state, result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), value);
|
m_set_callback(state, result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ void GenericIntPropertySequence::ProcessMatch(MenuFileParserState* state, Sequen
|
|||||||
{
|
{
|
||||||
if (m_set_callback)
|
if (m_set_callback)
|
||||||
{
|
{
|
||||||
const auto value = MenuMatcherFactory::TokenIntExpressionValue(result);
|
const auto value = MenuMatcherFactory::TokenIntExpressionValue(state, result);
|
||||||
m_set_callback(state, result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), value);
|
m_set_callback(state, result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos(), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,10 +188,10 @@ namespace menu::item_scope_sequences
|
|||||||
{
|
{
|
||||||
assert(state->m_current_item);
|
assert(state->m_current_item);
|
||||||
|
|
||||||
const auto x = MenuMatcherFactory::TokenNumericExpressionValue(result);
|
const auto x = MenuMatcherFactory::TokenNumericExpressionValue(state, result);
|
||||||
const auto y = MenuMatcherFactory::TokenNumericExpressionValue(result);
|
const auto y = MenuMatcherFactory::TokenNumericExpressionValue(state, result);
|
||||||
const auto w = MenuMatcherFactory::TokenNumericExpressionValue(result);
|
const auto w = MenuMatcherFactory::TokenNumericExpressionValue(state, result);
|
||||||
const auto h = MenuMatcherFactory::TokenNumericExpressionValue(result);
|
const auto h = MenuMatcherFactory::TokenNumericExpressionValue(state, result);
|
||||||
CommonRect rect
|
CommonRect rect
|
||||||
{
|
{
|
||||||
x,
|
x,
|
||||||
@ -231,8 +231,8 @@ namespace menu::item_scope_sequences
|
|||||||
{
|
{
|
||||||
assert(state->m_current_item);
|
assert(state->m_current_item);
|
||||||
|
|
||||||
state->m_current_item->m_rect.x = MenuMatcherFactory::TokenNumericExpressionValue(result);
|
state->m_current_item->m_rect.x = MenuMatcherFactory::TokenNumericExpressionValue(state, result);
|
||||||
state->m_current_item->m_rect.y = MenuMatcherFactory::TokenNumericExpressionValue(result);
|
state->m_current_item->m_rect.y = MenuMatcherFactory::TokenNumericExpressionValue(state, result);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -261,9 +261,9 @@ namespace menu::item_scope_sequences
|
|||||||
{
|
{
|
||||||
assert(state->m_current_item);
|
assert(state->m_current_item);
|
||||||
|
|
||||||
state->m_current_item->m_fx_letter_time = MenuMatcherFactory::TokenIntExpressionValue(result);
|
state->m_current_item->m_fx_letter_time = MenuMatcherFactory::TokenIntExpressionValue(state, result);
|
||||||
state->m_current_item->m_fx_decay_start_time = MenuMatcherFactory::TokenIntExpressionValue(result);
|
state->m_current_item->m_fx_decay_start_time = MenuMatcherFactory::TokenIntExpressionValue(state, result);
|
||||||
state->m_current_item->m_fx_decay_duration = MenuMatcherFactory::TokenIntExpressionValue(result);
|
state->m_current_item->m_fx_decay_duration = MenuMatcherFactory::TokenIntExpressionValue(state, result);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -341,9 +341,9 @@ namespace menu::item_scope_sequences
|
|||||||
|
|
||||||
ItemScopeOperations::EnsureHasEditFieldFeatures(*state->m_current_item, result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos());
|
ItemScopeOperations::EnsureHasEditFieldFeatures(*state->m_current_item, result.NextCapture(CAPTURE_FIRST_TOKEN).GetPos());
|
||||||
state->m_current_item->m_dvar = MenuMatcherFactory::TokenTextValue(result.NextCapture(CAPTURE_DVAR_NAME));
|
state->m_current_item->m_dvar = MenuMatcherFactory::TokenTextValue(result.NextCapture(CAPTURE_DVAR_NAME));
|
||||||
state->m_current_item->m_edit_field_features->m_def_val = MenuMatcherFactory::TokenNumericExpressionValue(result);
|
state->m_current_item->m_edit_field_features->m_def_val = MenuMatcherFactory::TokenNumericExpressionValue(state, result);
|
||||||
state->m_current_item->m_edit_field_features->m_min_val = MenuMatcherFactory::TokenNumericExpressionValue(result);
|
state->m_current_item->m_edit_field_features->m_min_val = MenuMatcherFactory::TokenNumericExpressionValue(state, result);
|
||||||
state->m_current_item->m_edit_field_features->m_max_val = MenuMatcherFactory::TokenNumericExpressionValue(result);
|
state->m_current_item->m_edit_field_features->m_max_val = MenuMatcherFactory::TokenNumericExpressionValue(state, result);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -422,7 +422,7 @@ namespace menu::item_scope_sequences
|
|||||||
while (result.HasNextCapture(CAPTURE_STEP_NAME))
|
while (result.HasNextCapture(CAPTURE_STEP_NAME))
|
||||||
{
|
{
|
||||||
multiValueFeatures->m_step_names.emplace_back(MenuMatcherFactory::TokenTextValue(result.NextCapture(CAPTURE_STEP_NAME)));
|
multiValueFeatures->m_step_names.emplace_back(MenuMatcherFactory::TokenTextValue(result.NextCapture(CAPTURE_STEP_NAME)));
|
||||||
multiValueFeatures->m_double_values.emplace_back(MenuMatcherFactory::TokenNumericExpressionValue(result));
|
multiValueFeatures->m_double_values.emplace_back(MenuMatcherFactory::TokenNumericExpressionValue(state, result));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -124,10 +124,10 @@ namespace menu::menu_scope_sequences
|
|||||||
{
|
{
|
||||||
assert(state->m_current_menu);
|
assert(state->m_current_menu);
|
||||||
|
|
||||||
const auto x = MenuMatcherFactory::TokenNumericExpressionValue(result);
|
const auto x = MenuMatcherFactory::TokenNumericExpressionValue(state, result);
|
||||||
const auto y = MenuMatcherFactory::TokenNumericExpressionValue(result);
|
const auto y = MenuMatcherFactory::TokenNumericExpressionValue(state, result);
|
||||||
const auto w = MenuMatcherFactory::TokenNumericExpressionValue(result);
|
const auto w = MenuMatcherFactory::TokenNumericExpressionValue(state, result);
|
||||||
const auto h = MenuMatcherFactory::TokenNumericExpressionValue(result);
|
const auto h = MenuMatcherFactory::TokenNumericExpressionValue(state, result);
|
||||||
CommonRect rect
|
CommonRect rect
|
||||||
{
|
{
|
||||||
x,
|
x,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user