diff --git a/raw/iw4/statemaps/wip_particle_cloud.sm b/raw/iw4/statemaps/wip_particle_cloud.sm index 9d5f729f..184d784f 100644 --- a/raw/iw4/statemaps/wip_particle_cloud.sm +++ b/raw/iw4/statemaps/wip_particle_cloud.sm @@ -22,7 +22,7 @@ separateAlphaBlendFunc mtlBlendOp == Disable: // Unused Disable, One, Zero; - mtlAlphaTest == Disable: // Used + mtlAlphaTest == Always: // Used Add, Zero, One; default: diff --git a/src/Common/StateMap/StateMapLayout.cpp b/src/Common/StateMap/StateMapLayout.cpp index 08e71b7d..1a0013fb 100644 --- a/src/Common/StateMap/StateMapLayout.cpp +++ b/src/Common/StateMap/StateMapLayout.cpp @@ -23,6 +23,9 @@ namespace state_map // Zero mask values must be last assert(value.m_state_bits_mask != 0 || i == var.m_values.size() - 1); + + // Must not have a value outside the var mask + assert((value.m_state_bits_mask & ~var.m_values_mask) == 0); } } @@ -68,9 +71,10 @@ StateMapLayoutVarValue::StateMapLayoutVarValue(std::string name, const size_t st { } -StateMapLayoutVar::StateMapLayoutVar(std::string name, const size_t stateBitsIndex, std::vector values) +StateMapLayoutVar::StateMapLayoutVar(std::string name, const size_t stateBitsIndex, const size_t valuesMask, std::vector values) : m_name(std::move(name)), m_state_bits_index(stateBitsIndex), + m_values_mask(valuesMask), m_values(std::move(values)) { } diff --git a/src/Common/StateMap/StateMapLayout.h b/src/Common/StateMap/StateMapLayout.h index 7c306cdb..12d0fdc0 100644 --- a/src/Common/StateMap/StateMapLayout.h +++ b/src/Common/StateMap/StateMapLayout.h @@ -36,10 +36,11 @@ namespace state_map class StateMapLayoutVar { public: - StateMapLayoutVar(std::string name, size_t stateBitsIndex, std::vector values); + StateMapLayoutVar(std::string name, size_t stateBitsIndex, size_t valuesMask, std::vector values); std::string m_name; size_t m_state_bits_index; + size_t m_values_mask; std::vector m_values; }; diff --git a/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h b/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h index fa40a1cf..093fc638 100644 --- a/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h +++ b/src/ObjCommon/Game/IW4/TechsetConstantsIW4.h @@ -651,7 +651,7 @@ namespace IW4 inline state_map::StateMapLayoutVars stateMapVarLayout({ { - "mtlAlphaTest", 0, { + "mtlAlphaTest", 0, GFXS0_ATEST_DISABLE | GFXS0_ATEST_MASK, { {"Always", GFXS0_ATEST_DISABLE}, {"GE128", GFXS0_ATEST_GE_128}, {"GT0", GFXS0_ATEST_GT_0}, @@ -659,7 +659,7 @@ namespace IW4 } }, { - "mtlBlendOp", 0, { + "mtlBlendOp", 0, GFXS0_BLENDOP_RGB_MASK, { {"Add", GFXS_BLENDOP_ADD << GFXS0_BLENDOP_RGB_SHIFT}, {"Subtract", GFXS_BLENDOP_SUBTRACT << GFXS0_BLENDOP_RGB_SHIFT}, {"RevSubtract", GFXS_BLENDOP_REVSUBTRACT << GFXS0_BLENDOP_RGB_SHIFT}, @@ -669,7 +669,7 @@ namespace IW4 } }, { - "mtlSrcBlend", 0, { + "mtlSrcBlend", 0, GFXS0_SRCBLEND_RGB_MASK, { {"Zero", GFXS_BLEND_ZERO << GFXS0_SRCBLEND_RGB_SHIFT}, {"One", GFXS_BLEND_ONE << GFXS0_SRCBLEND_RGB_SHIFT}, {"SrcColor", GFXS_BLEND_SRCCOLOR << GFXS0_SRCBLEND_RGB_SHIFT}, @@ -683,7 +683,7 @@ namespace IW4 } }, { - "mtlDestBlend", 0, { + "mtlDestBlend", 0, GFXS0_DSTBLEND_RGB_MASK, { {"Zero", GFXS_BLEND_ZERO << GFXS0_DSTBLEND_RGB_SHIFT}, {"One", GFXS_BLEND_ONE << GFXS0_DSTBLEND_RGB_SHIFT}, {"SrcColor", GFXS_BLEND_SRCCOLOR << GFXS0_DSTBLEND_RGB_SHIFT}, @@ -697,7 +697,7 @@ namespace IW4 } }, { - "mtlBlendOpAlpha", 0, { + "mtlBlendOpAlpha", 0, GFXS0_BLENDOP_ALPHA_MASK, { {"Add", GFXS_BLENDOP_ADD << GFXS0_BLENDOP_ALPHA_SHIFT}, {"Subtract", GFXS_BLENDOP_SUBTRACT << GFXS0_BLENDOP_ALPHA_SHIFT}, {"RevSubtract", GFXS_BLENDOP_REVSUBTRACT << GFXS0_BLENDOP_ALPHA_SHIFT}, @@ -707,7 +707,7 @@ namespace IW4 } }, { - "mtlSrcBlendAlpha", 0, { + "mtlSrcBlendAlpha", 0, GFXS0_SRCBLEND_ALPHA_MASK, { {"Zero", GFXS_BLEND_ZERO << GFXS0_SRCBLEND_ALPHA_SHIFT}, {"One", GFXS_BLEND_ONE << GFXS0_SRCBLEND_ALPHA_SHIFT}, {"SrcColor", GFXS_BLEND_SRCCOLOR << GFXS0_SRCBLEND_ALPHA_SHIFT}, @@ -721,7 +721,7 @@ namespace IW4 } }, { - "mtlDestBlendAlpha", 0, { + "mtlDestBlendAlpha", 0, GFXS0_DSTBLEND_ALPHA_MASK, { {"Zero", GFXS_BLEND_ZERO << GFXS0_DSTBLEND_ALPHA_SHIFT}, {"One", GFXS_BLEND_ONE << GFXS0_DSTBLEND_ALPHA_SHIFT}, {"SrcColor", GFXS_BLEND_SRCCOLOR << GFXS0_DSTBLEND_ALPHA_SHIFT}, @@ -735,38 +735,38 @@ namespace IW4 } }, { - "mtlCullFace", 0, { + "mtlCullFace", 0, GFXS0_CULL_MASK, { {"None", GFXS0_CULL_NONE}, {"Back", GFXS0_CULL_BACK}, {"Front", GFXS0_CULL_FRONT}, } }, { - "mtlColorWriteRgb", 0, { + "mtlColorWriteRgb", 0, GFXS0_COLORWRITE_RGB, { {"Enable", GFXS0_COLORWRITE_RGB}, {"Disable", 0}, } }, { - "mtlColorWriteAlpha", 0, { + "mtlColorWriteAlpha", 0, GFXS0_COLORWRITE_ALPHA, { {"Enable", GFXS0_COLORWRITE_ALPHA}, {"Disable", 0}, } }, { - "mtlGammaWrite", 0, { + "mtlGammaWrite", 0, GFXS0_GAMMAWRITE, { {"Enable", GFXS0_GAMMAWRITE}, {"Disable", 0}, } }, { - "mtlWireframe", 0, { + "mtlWireframe", 0, GFXS0_POLYMODE_LINE, { {"Enable", GFXS0_POLYMODE_LINE}, {"Disable", 0}, } }, { - "mtlDepthTest", 1, { + "mtlDepthTest", 1, GFXS1_DEPTHTEST_DISABLE | GFXS1_DEPTHTEST_MASK, { {"Disable", GFXS1_DEPTHTEST_DISABLE}, {"Less", GFXS1_DEPTHTEST_LESS}, {"LessEqual", GFXS1_DEPTHTEST_LESSEQUAL}, @@ -775,13 +775,13 @@ namespace IW4 } }, { - "mtlDepthWrite", 1, { + "mtlDepthWrite", 1, GFXS1_DEPTHWRITE, { {"Enable", GFXS1_DEPTHWRITE}, {"Disable", 0}, } }, { - "mtlPolygonOffset", 1, { + "mtlPolygonOffset", 1, GFXS1_POLYGON_OFFSET_MASK, { {"1", GFXS1_POLYGON_OFFSET_1}, {"2", GFXS1_POLYGON_OFFSET_2}, {"shadowmap", GFXS1_POLYGON_OFFSET_SHADOWMAP}, @@ -789,14 +789,14 @@ namespace IW4 } }, { - "mtlStencil", 1, { + "mtlStencil", 1, GFXS1_STENCIL_FRONT_ENABLE | GFXS1_STENCIL_BACK_ENABLE, { {"OneSided", GFXS1_STENCIL_FRONT_ENABLE}, {"TwoSided", GFXS1_STENCIL_FRONT_ENABLE | GFXS1_STENCIL_BACK_ENABLE}, {"Disable", 0}, } }, { - "mtlStencilFuncFront", 1, { + "mtlStencilFuncFront", 1, GFXS1_STENCIL_FRONT_FUNC_MASK, { {"Less", GFXS_STENCILFUNC_LESS << GFXS1_STENCIL_FRONT_FUNC_SHIFT}, {"Equal", GFXS_STENCILFUNC_EQUAL << GFXS1_STENCIL_FRONT_FUNC_SHIFT}, {"LessEqual", GFXS_STENCILFUNC_LESSEQUAL << GFXS1_STENCIL_FRONT_FUNC_SHIFT}, @@ -808,7 +808,7 @@ namespace IW4 } }, { - "mtlStencilOpFrontPass", 1, { + "mtlStencilOpFrontPass", 1, GFXS1_STENCIL_FRONT_PASS_MASK, { {"Zero", GFXS_STENCILOP_ZERO << GFXS1_STENCIL_FRONT_PASS_SHIFT}, {"Replace", GFXS_STENCILOP_REPLACE << GFXS1_STENCIL_FRONT_PASS_SHIFT}, {"IncrSat", GFXS_STENCILOP_INCRSAT << GFXS1_STENCIL_FRONT_PASS_SHIFT}, @@ -820,7 +820,7 @@ namespace IW4 } }, { - "mtlStencilOpFrontFail", 1, { + "mtlStencilOpFrontFail", 1, GFXS1_STENCIL_FRONT_FAIL_MASK, { {"Zero", GFXS_STENCILOP_ZERO << GFXS1_STENCIL_FRONT_FAIL_SHIFT}, {"Replace", GFXS_STENCILOP_REPLACE << GFXS1_STENCIL_FRONT_FAIL_SHIFT}, {"IncrSat", GFXS_STENCILOP_INCRSAT << GFXS1_STENCIL_FRONT_FAIL_SHIFT}, @@ -832,7 +832,7 @@ namespace IW4 } }, { - "mtlStencilOpFrontZFail", 1, { + "mtlStencilOpFrontZFail", 1, GFXS1_STENCIL_FRONT_ZFAIL_MASK, { {"Zero", GFXS_STENCILOP_ZERO << GFXS1_STENCIL_FRONT_ZFAIL_SHIFT}, {"Replace", GFXS_STENCILOP_REPLACE << GFXS1_STENCIL_FRONT_ZFAIL_SHIFT}, {"IncrSat", GFXS_STENCILOP_INCRSAT << GFXS1_STENCIL_FRONT_ZFAIL_SHIFT}, @@ -844,7 +844,7 @@ namespace IW4 } }, { - "mtlStencilFuncBack", 1, { + "mtlStencilFuncBack", 1, GFXS1_STENCIL_BACK_FUNC_MASK, { {"Less", GFXS_STENCILFUNC_LESS << GFXS1_STENCIL_BACK_FUNC_SHIFT}, {"Equal", GFXS_STENCILFUNC_EQUAL << GFXS1_STENCIL_BACK_FUNC_SHIFT}, {"LessEqual", GFXS_STENCILFUNC_LESSEQUAL << GFXS1_STENCIL_BACK_FUNC_SHIFT}, @@ -856,7 +856,7 @@ namespace IW4 } }, { - "mtlStencilOpBackPass", 1, { + "mtlStencilOpBackPass", 1, GFXS1_STENCIL_BACK_PASS_MASK, { {"Zero", GFXS_STENCILOP_ZERO << GFXS1_STENCIL_BACK_PASS_SHIFT}, {"Replace", GFXS_STENCILOP_REPLACE << GFXS1_STENCIL_BACK_PASS_SHIFT}, {"IncrSat", GFXS_STENCILOP_INCRSAT << GFXS1_STENCIL_BACK_PASS_SHIFT}, @@ -868,7 +868,7 @@ namespace IW4 } }, { - "mtlStencilOpBackFail", 1, { + "mtlStencilOpBackFail", 1, GFXS1_STENCIL_BACK_FAIL_MASK, { {"Zero", GFXS_STENCILOP_ZERO << GFXS1_STENCIL_BACK_FAIL_SHIFT}, {"Replace", GFXS_STENCILOP_REPLACE << GFXS1_STENCIL_BACK_FAIL_SHIFT}, {"IncrSat", GFXS_STENCILOP_INCRSAT << GFXS1_STENCIL_BACK_FAIL_SHIFT}, @@ -880,7 +880,7 @@ namespace IW4 } }, { - "mtlStencilOpBackZFail", 1, { + "mtlStencilOpBackZFail", 1, GFXS1_STENCIL_BACK_ZFAIL_MASK, { {"Zero", GFXS_STENCILOP_ZERO << GFXS1_STENCIL_BACK_ZFAIL_SHIFT}, {"Replace", GFXS_STENCILOP_REPLACE << GFXS1_STENCIL_BACK_ZFAIL_SHIFT}, {"IncrSat", GFXS_STENCILOP_INCRSAT << GFXS1_STENCIL_BACK_ZFAIL_SHIFT}, diff --git a/src/ObjLoading/StateMap/Parsing/Matcher/StateMapExpressionMatchers.cpp b/src/ObjLoading/StateMap/Parsing/Matcher/StateMapExpressionMatchers.cpp deleted file mode 100644 index 70a9b81c..00000000 --- a/src/ObjLoading/StateMap/Parsing/Matcher/StateMapExpressionMatchers.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include "StateMapExpressionMatchers.h" - -#include "Parsing/Simple/Expression/SimpleExpressionScopeValue.h" -#include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" - -using namespace state_map; - -static constexpr int CAPTURE_VALUE = SimpleExpressionMatchers::CAPTURE_OFFSET_EXPRESSION_EXT + 1; - -StateMapExpressionMatchers::StateMapExpressionMatchers() - : StateMapExpressionMatchers(nullptr) -{ -} - -StateMapExpressionMatchers::StateMapExpressionMatchers(StateMapParserState* state) - : SimpleExpressionMatchers(false, false, false, false, true), - m_state(state) -{ -} - -std::unique_ptr StateMapExpressionMatchers::ParseOperandExtension(const supplier_t* labelSupplier) const -{ - const SimpleMatcherFactory create(labelSupplier); - - return create.Or({ - create.Identifier().Capture(CAPTURE_VALUE), - create.Integer().Capture(CAPTURE_VALUE), - }); -} - -std::unique_ptr StateMapExpressionMatchers::ProcessOperandExtension(SequenceResult& result) const -{ - assert(m_state); - - const auto& valueToken = result.NextCapture(CAPTURE_VALUE); - auto value = valueToken.m_type == SimpleParserValueType::IDENTIFIER ? valueToken.IdentifierValue() : std::to_string(valueToken.IntegerValue()); - - if (value.rfind("mtl", 0) == 0) - { - if (m_state->m_valid_vars.find(value) == m_state->m_valid_vars.end()) - throw ParsingException(valueToken.GetPos(), "Unknown variable"); - - return std::make_unique(value); - } - - if (m_state->m_valid_values.find(value) == m_state->m_valid_values.end()) - throw ParsingException(valueToken.GetPos(), "Unknown value"); - - return std::make_unique(value); -} diff --git a/src/ObjLoading/StateMap/Parsing/Matcher/StateMapExpressionMatchers.h b/src/ObjLoading/StateMap/Parsing/Matcher/StateMapExpressionMatchers.h deleted file mode 100644 index 5be3ea1e..00000000 --- a/src/ObjLoading/StateMap/Parsing/Matcher/StateMapExpressionMatchers.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include - -#include "Parsing/Simple/Expression/SimpleExpressionMatchers.h" -#include "StateMap/Parsing/StateMapParserState.h" - -namespace state_map -{ - class StateMapExpressionMatchers final : public SimpleExpressionMatchers - { - public: - StateMapExpressionMatchers(); - explicit StateMapExpressionMatchers(StateMapParserState* state); - - protected: - std::unique_ptr ParseOperandExtension(const supplier_t* labelSupplier) const override; - std::unique_ptr ProcessOperandExtension(SequenceResult& result) const override; - - private: - StateMapParserState* m_state; - }; -} diff --git a/src/ObjLoading/StateMap/Parsing/StateMapParser.cpp b/src/ObjLoading/StateMap/Parsing/StateMapParser.cpp index 406bfa97..1a920c72 100644 --- a/src/ObjLoading/StateMap/Parsing/StateMapParser.cpp +++ b/src/ObjLoading/StateMap/Parsing/StateMapParser.cpp @@ -1,6 +1,8 @@ #include "StateMapParser.h" -#include "Matcher/StateMapExpressionMatchers.h" +#include +#include + #include "Parsing/Simple/Matcher/SimpleMatcherFactory.h" using namespace state_map; @@ -64,18 +66,45 @@ namespace state_map class SequenceCondition final : public StateMapParser::sequence_t { static constexpr auto TAG_DEFAULT = 1; - static constexpr auto TAG_EXPRESSION = 2; + static constexpr auto TAG_CONDITION = 2; + static constexpr auto TAG_EQUALS_OPERATION = 3; + + static constexpr auto CAPTURE_OPERATOR = 1; + + static constexpr auto LABEL_CONDITION = 1; + static constexpr auto LABEL_EQUALS_OPERATION = 2; + static constexpr auto LABEL_CONDITION_OPERATOR = 3; public: SequenceCondition() { - AddLabeledMatchers(StateMapExpressionMatchers().Expression(this), StateMapExpressionMatchers::LABEL_EXPRESSION); const SimpleMatcherFactory create(this); + AddLabeledMatchers(create.Or({ + create.Identifier(), + create.Integer() + }).Capture(CAPTURE_OPERATOR), LABEL_CONDITION_OPERATOR); + + AddLabeledMatchers(create.And({ + create.True().Tag(TAG_EQUALS_OPERATION), + create.Label(LABEL_CONDITION_OPERATOR), + create.MultiChar(StateMapParser::MULTI_TOKEN_EQUALS), + create.Label(LABEL_CONDITION_OPERATOR) + }), LABEL_EQUALS_OPERATION); + + AddLabeledMatchers(create.And({ + create.True().Tag(TAG_CONDITION), + create.Label(LABEL_EQUALS_OPERATION), + create.OptionalLoop(create.And({ + create.MultiChar(StateMapParser::MULTI_TOKEN_AND), + create.Label(LABEL_EQUALS_OPERATION) + })) + }), LABEL_CONDITION); + AddMatchers({ create.Or({ create.Keyword("default").Tag(TAG_DEFAULT), - create.Label(StateMapExpressionMatchers::LABEL_EXPRESSION).Tag(TAG_EXPRESSION) + create.Label(LABEL_CONDITION) }), create.Char(':') }); @@ -94,11 +123,10 @@ namespace state_map state->m_definition->m_state_map_entries[state->m_current_entry_index].m_rules.emplace_back(std::move(newRule)); } - if (result.PeekAndRemoveIfTag(TAG_EXPRESSION) == TAG_EXPRESSION) + if (result.PeekAndRemoveIfTag(TAG_CONDITION) == TAG_CONDITION) { - auto expression = StateMapExpressionMatchers(state).ProcessExpression(result); - - state->m_current_rule->m_conditions.emplace_back(std::move(expression)); + auto condition = ProcessCondition(state, result); + state->m_current_rule->m_conditions.emplace_back(std::move(condition)); } else { @@ -108,6 +136,73 @@ namespace state_map entry.m_default_index = entry.m_rules.size() - 1; } } + + static StateMapCondition ProcessCondition(const StateMapParserState* state, SequenceResult& result) + { + StateMapCondition condition(state->m_layout.m_state_bits_count); + + while (result.PeekAndRemoveIfTag(TAG_EQUALS_OPERATION) == TAG_EQUALS_OPERATION) + { + std::array, 2> operatorToken + { + result.NextCapture(CAPTURE_OPERATOR), + result.NextCapture(CAPTURE_OPERATOR) + }; + + std::array operatorValue + { + ProcessOperator(operatorToken[0]), + ProcessOperator(operatorToken[1]) + }; + + const auto variableIndex = IsVariable(operatorValue[1]) ? 1 : 0; + const auto valueIndex = variableIndex == 0 ? 1 : 0; + + const auto& variable = GetVariable(state, operatorToken[variableIndex], operatorValue[variableIndex]); + const auto& value = GetValue(variable, operatorToken[valueIndex], operatorValue[valueIndex]); + + condition.m_masks_per_index[variable.m_state_bits_index] |= variable.m_values_mask; + condition.m_values_per_index[variable.m_state_bits_index] |= value.m_state_bits_mask; + } + + return condition; + } + + static std::string ProcessOperator(const SimpleParserValue& token) + { + return token.m_type == SimpleParserValueType::IDENTIFIER ? token.IdentifierValue() : std::to_string(token.IntegerValue()); + } + + static bool IsVariable(const std::string& _operator) + { + return _operator.rfind("mtl", 0) == 0; + } + + static const StateMapLayoutVar& GetVariable(const StateMapParserState* state, const SimpleParserValue& operatorToken, const std::string& operatorValue) + { + const auto& foundVariable = state->m_valid_vars.find(operatorValue); + if (foundVariable == state->m_valid_vars.end()) + throw ParsingException(operatorToken.GetPos(), "Unknown variable"); + + return state->m_layout.m_var_layout.m_vars[foundVariable->second]; + } + + static const StateMapLayoutVarValue& GetValue(const StateMapLayoutVar& variable, const SimpleParserValue& operatorToken, const std::string& operatorValue) + { + const auto matchingValue = std::find_if(variable.m_values.begin(), variable.m_values.end(), [&operatorValue](const StateMapLayoutVarValue& value) + { + return value.m_name == operatorValue; + }); + + if (matchingValue == variable.m_values.end()) + { + std::ostringstream ss; + ss << "Unknown value for variable \"" << variable.m_name << "\""; + throw ParsingException(operatorToken.GetPos(), ss.str()); + } + + return *matchingValue; + } }; class SequenceValue final : public StateMapParser::sequence_t diff --git a/src/ObjLoading/StateMap/Parsing/StateMapParser.h b/src/ObjLoading/StateMap/Parsing/StateMapParser.h index 9dc49043..64b06fb3 100644 --- a/src/ObjLoading/StateMap/Parsing/StateMapParser.h +++ b/src/ObjLoading/StateMap/Parsing/StateMapParser.h @@ -11,6 +11,10 @@ namespace state_map { class StateMapParser final : public AbstractParser { + public: + static constexpr auto MULTI_TOKEN_AND = 600; + static constexpr auto MULTI_TOKEN_EQUALS = 601; + protected: const std::vector& GetTestsForState() override; diff --git a/src/ObjLoading/StateMap/StateMapDefinition.cpp b/src/ObjLoading/StateMap/StateMapDefinition.cpp index e2cfc092..c1a79398 100644 --- a/src/ObjLoading/StateMap/StateMapDefinition.cpp +++ b/src/ObjLoading/StateMap/StateMapDefinition.cpp @@ -2,6 +2,12 @@ using namespace state_map; +StateMapCondition::StateMapCondition(const size_t entryCount) + : m_masks_per_index(entryCount), + m_values_per_index(entryCount) +{ +} + StateMapRule::StateMapRule() : m_value(0u), m_passthrough(false) diff --git a/src/ObjLoading/StateMap/StateMapDefinition.h b/src/ObjLoading/StateMap/StateMapDefinition.h index 4b691cbd..94c292bb 100644 --- a/src/ObjLoading/StateMap/StateMapDefinition.h +++ b/src/ObjLoading/StateMap/StateMapDefinition.h @@ -4,14 +4,21 @@ #include #include -#include "Parsing/Simple/Expression/ISimpleExpression.h" - namespace state_map { + class StateMapCondition + { + public: + std::vector m_masks_per_index; + std::vector m_values_per_index; + + explicit StateMapCondition(size_t entryCount); + }; + class StateMapRule { public: - std::vector> m_conditions; + std::vector m_conditions; size_t m_value; bool m_passthrough; diff --git a/src/ObjLoading/StateMap/StateMapHandler.cpp b/src/ObjLoading/StateMap/StateMapHandler.cpp index 7b56406e..20b885ea 100644 --- a/src/ObjLoading/StateMap/StateMapHandler.cpp +++ b/src/ObjLoading/StateMap/StateMapHandler.cpp @@ -6,21 +6,6 @@ using namespace state_map; -void StateMapVars::AddValue(std::string key, std::string value) -{ - m_vars.emplace(std::make_pair(std::move(key), std::move(value))); -} - -SimpleExpressionValue StateMapVars::ValueByName(const std::string& name) const -{ - const auto foundValue = m_vars.find(name); - - if (foundValue != m_vars.end()) - return SimpleExpressionValue(foundValue->second); - - return SimpleExpressionValue(0); -} - StateMapHandler::StateMapHandler(const StateMapLayout& stateMapLayout, const StateMapDefinition& stateMap) : m_state_map_layout(stateMapLayout), m_state_map(stateMap) @@ -32,19 +17,17 @@ void StateMapHandler::ApplyStateMap(const uint32_t* baseStateBits, uint32_t* out assert(baseStateBits != nullptr); assert(outStateBits != nullptr); - const auto vars = BuildVars(baseStateBits); - for (auto i = 0u; i < m_state_map_layout.m_state_bits_count; i++) outStateBits[i] = baseStateBits[i]; for (auto entryIndex = 0u; entryIndex < m_state_map.m_state_map_entries.size(); entryIndex++) { const auto& entry = m_state_map.m_state_map_entries[entryIndex]; - const auto matchingRule = std::find_if(entry.m_rules.begin(), entry.m_rules.end(), [&vars](const std::unique_ptr& rule) + const auto matchingRule = std::find_if(entry.m_rules.begin(), entry.m_rules.end(), [&baseStateBits](const std::unique_ptr& rule) { - const auto matchingCondition = std::find_if(rule->m_conditions.begin(), rule->m_conditions.end(), [&vars](std::unique_ptr& condition) + const auto matchingCondition = std::find_if(rule->m_conditions.begin(), rule->m_conditions.end(), [&baseStateBits](const StateMapCondition& condition) { - return condition->EvaluateNonStatic(&vars).IsTruthy(); + return ConditionIsTrue(condition, baseStateBits); }); return matchingCondition != rule->m_conditions.end(); @@ -57,27 +40,6 @@ void StateMapHandler::ApplyStateMap(const uint32_t* baseStateBits, uint32_t* out } } -StateMapVars StateMapHandler::BuildVars(const uint32_t* baseStateBits) const -{ - StateMapVars result; - - for (const auto& var : m_state_map_layout.m_var_layout.m_vars) - { - const auto baseStateBitField = baseStateBits[var.m_state_bits_index]; - const auto matchingValue = std::find_if(var.m_values.begin(), var.m_values.end(), [&baseStateBitField](const StateMapLayoutVarValue& value) - { - return (baseStateBitField & value.m_state_bits_mask) == value.m_state_bits_mask; - }); - - if (matchingValue != var.m_values.end()) - result.AddValue(var.m_name, matchingValue->m_name); - else - std::cerr << "Could not find base value for state map var \"" << var.m_name << "\"\n"; - } - - return result; -} - void StateMapHandler::ApplyRule(const StateMapLayoutEntry& entry, const StateMapRule& rule, uint32_t* outStateBits) { if (rule.m_passthrough) @@ -86,3 +48,15 @@ void StateMapHandler::ApplyRule(const StateMapLayoutEntry& entry, const StateMap outStateBits[entry.m_state_bits_index] &= ~entry.m_state_bits_mask; outStateBits[entry.m_state_bits_index] |= rule.m_value; } + +bool StateMapHandler::ConditionIsTrue(const StateMapCondition& condition, const uint32_t* stateBits) +{ + const auto stateBitCount = std::min(condition.m_masks_per_index.size(), condition.m_values_per_index.size()); + for (auto stateBitIndex = 0u; stateBitIndex < stateBitCount; stateBitIndex++) + { + if ((stateBits[stateBitIndex] & condition.m_masks_per_index[stateBitIndex]) != condition.m_values_per_index[stateBitIndex]) + return false; + } + + return true; +} diff --git a/src/ObjLoading/StateMap/StateMapHandler.h b/src/ObjLoading/StateMap/StateMapHandler.h index 7fe44933..4d1f7023 100644 --- a/src/ObjLoading/StateMap/StateMapHandler.h +++ b/src/ObjLoading/StateMap/StateMapHandler.h @@ -1,24 +1,12 @@ #pragma once #include -#include -#include "Utils/ClassUtils.h" #include "StateMap/StateMapDefinition.h" #include "StateMap/StateMapLayout.h" namespace state_map { - class StateMapVars final : public ISimpleExpressionScopeValues - { - public: - void AddValue(std::string key, std::string value); - _NODISCARD SimpleExpressionValue ValueByName(const std::string& name) const override; - - private: - std::unordered_map m_vars; - }; - class StateMapHandler { public: @@ -27,8 +15,8 @@ namespace state_map void ApplyStateMap(const uint32_t* baseStateBits, uint32_t* outStateBits) const; private: - StateMapVars BuildVars(const uint32_t* baseStateBits) const; static void ApplyRule(const StateMapLayoutEntry& entry, const StateMapRule& rule, uint32_t* outStateBits); + static bool ConditionIsTrue(const StateMapCondition& condition, const uint32_t* stateBits); const StateMapLayout& m_state_map_layout; const StateMapDefinition& m_state_map; diff --git a/src/ObjLoading/StateMap/StateMapReader.cpp b/src/ObjLoading/StateMap/StateMapReader.cpp index 5190350d..f20b2b1e 100644 --- a/src/ObjLoading/StateMap/StateMapReader.cpp +++ b/src/ObjLoading/StateMap/StateMapReader.cpp @@ -5,7 +5,6 @@ #include "Parsing/StateMapParser.h" #include "Parsing/Impl/CommentRemovingStreamProxy.h" #include "Parsing/Impl/ParserSingleInputStream.h" -#include "Parsing/Matcher/StateMapExpressionMatchers.h" using namespace state_map; @@ -51,7 +50,8 @@ std::unique_ptr StateMapReader::ReadStateMapDefinition() con lexerConfig.m_read_strings = false; lexerConfig.m_read_integer_numbers = true; lexerConfig.m_read_floating_point_numbers = false; - StateMapExpressionMatchers().ApplyTokensToLexerConfig(lexerConfig); + lexerConfig.m_multi_character_tokens.emplace_back(StateMapParser::MULTI_TOKEN_AND, "&&"); + lexerConfig.m_multi_character_tokens.emplace_back(StateMapParser::MULTI_TOKEN_EQUALS, "=="); const auto lexer = std::make_unique(m_comment_proxy.get(), std::move(lexerConfig)); const auto parser = std::make_unique(lexer.get(), m_state_map_name, m_state_map_layout);