Add menu eventhandlerset sequences for if, elseif and else

This commit is contained in:
Jan 2021-11-14 12:46:02 +01:00
parent f760c517dd
commit 13589fd43c
3 changed files with 173 additions and 34 deletions

View File

@ -3,7 +3,13 @@
using namespace menu; using namespace menu;
MenuFileParserState::EventHandlerConditionState::EventHandlerConditionState(CommonEventHandlerCondition* condition) MenuFileParserState::EventHandlerConditionState::EventHandlerConditionState(CommonEventHandlerCondition* condition)
: EventHandlerConditionState(condition, false)
{
}
MenuFileParserState::EventHandlerConditionState::EventHandlerConditionState(CommonEventHandlerCondition* condition, const bool autoSkip)
: m_in_condition_elements(true), : m_in_condition_elements(true),
m_auto_skip(autoSkip),
m_condition(condition) m_condition(condition)
{ {
} }
@ -22,12 +28,12 @@ MenuFileParserState::MenuFileParserState(const FeatureLevel featureLevel)
MenuFileParserState::MenuFileParserState(const FeatureLevel featureLevel, const MenuAssetZoneState* zoneState) MenuFileParserState::MenuFileParserState(const FeatureLevel featureLevel, const MenuAssetZoneState* zoneState)
: MenuFileParserState(featureLevel) : MenuFileParserState(featureLevel)
{ {
for(const auto& function : zoneState->m_functions) for (const auto& function : zoneState->m_functions)
{ {
m_functions_by_name.emplace(std::make_pair(function->m_name, function.get())); m_functions_by_name.emplace(std::make_pair(function->m_name, function.get()));
} }
for(const auto& menu : zoneState->m_menus) for (const auto& menu : zoneState->m_menus)
{ {
m_menus_by_name.emplace(std::make_pair(menu->m_name, menu.get())); m_menus_by_name.emplace(std::make_pair(menu->m_name, menu.get()));
} }

View File

@ -22,9 +22,11 @@ namespace menu
{ {
public: public:
bool m_in_condition_elements; bool m_in_condition_elements;
bool m_auto_skip;
CommonEventHandlerCondition* m_condition; CommonEventHandlerCondition* m_condition;
explicit EventHandlerConditionState(CommonEventHandlerCondition* condition); explicit EventHandlerConditionState(CommonEventHandlerCondition* condition);
EventHandlerConditionState(CommonEventHandlerCondition* condition, bool autoSkip);
}; };
const FeatureLevel m_feature_level; const FeatureLevel m_feature_level;

View File

@ -130,26 +130,34 @@ namespace menu::event_handler_set_scope_sequences
state->m_current_nested_event_handler_set->m_elements.emplace_back(std::make_unique<CommonEventHandlerScript>(std::move(remainingScript))); state->m_current_nested_event_handler_set->m_elements.emplace_back(std::make_unique<CommonEventHandlerScript>(std::move(remainingScript)));
state->m_current_script.clear(); state->m_current_script.clear();
if (!state->m_condition_stack.empty()) bool conditionWasAutoSkip;
{
state->m_condition_stack.pop();
do
{
conditionWasAutoSkip = false;
if (!state->m_condition_stack.empty()) if (!state->m_condition_stack.empty())
{ {
const auto& newConditionState = state->m_condition_stack.top(); conditionWasAutoSkip = state->m_condition_stack.top().m_auto_skip;
if (newConditionState.m_in_condition_elements) state->m_condition_stack.pop();
state->m_current_nested_event_handler_set = newConditionState.m_condition->m_condition_elements.get();
if (!state->m_condition_stack.empty())
{
const auto& newConditionState = state->m_condition_stack.top();
if (newConditionState.m_in_condition_elements)
state->m_current_nested_event_handler_set = newConditionState.m_condition->m_condition_elements.get();
else
state->m_current_nested_event_handler_set = newConditionState.m_condition->m_else_elements.get();
}
else else
state->m_current_nested_event_handler_set = newConditionState.m_condition->m_else_elements.get(); state->m_current_nested_event_handler_set = state->m_current_event_handler_set;
} }
else else
state->m_current_nested_event_handler_set = state->m_current_event_handler_set; {
} state->m_current_event_handler_set = nullptr;
else state->m_current_nested_event_handler_set = nullptr;
{ }
state->m_current_event_handler_set = nullptr;
state->m_current_nested_event_handler_set = nullptr;
} }
while (conditionWasAutoSkip);
} }
}; };
@ -258,6 +266,34 @@ namespace menu::event_handler_set_scope_sequences
} }
}; };
class SequenceLerp final : public SequenceGenericScriptStatement
{
public:
explicit SequenceLerp()
{
const ScriptMatcherFactory create(this);
AddMatchers({
create.And({
create.ScriptKeyword("lerp"),
create.Or({
create.ScriptKeyword("scale"),
create.ScriptKeyword("alpha"),
create.ScriptKeyword("x"),
create.ScriptKeyword("y"),
}),
create.ScriptKeyword("from"),
create.ScriptNumeric(),
create.ScriptKeyword("to"),
create.ScriptNumeric(),
create.ScriptKeyword("over"),
create.ScriptNumeric()
}).Capture(CAPTURE_SCRIPT_TOKEN),
create.Optional(create.Char(';'))
});
}
};
class SequenceSetLocalVar final : public MenuFileParser::sequence_t class SequenceSetLocalVar final : public MenuFileParser::sequence_t
{ {
static constexpr auto TAG_BOOL = static_cast<int>(SetLocalVarType::BOOL); static constexpr auto TAG_BOOL = static_cast<int>(SetLocalVarType::BOOL);
@ -380,32 +416,124 @@ namespace menu::event_handler_set_scope_sequences
} }
}; };
class SequenceLerp final : public SequenceGenericScriptStatement class SequenceIf final : public MenuFileParser::sequence_t
{ {
static constexpr auto CAPTURE_KEYWORD = 1;
public: public:
explicit SequenceLerp() SequenceIf()
{ {
const ScriptMatcherFactory create(this); const ScriptMatcherFactory create(this);
AddLabeledMatchers(MenuCommonMatchers::Expression(this), MenuCommonMatchers::LABEL_EXPRESSION);
AddMatchers({ AddMatchers({
create.And({ create.Keyword("if").Capture(CAPTURE_KEYWORD),
create.ScriptKeyword("lerp"), create.Char('('),
create.Or({ create.Label(MenuCommonMatchers::LABEL_EXPRESSION),
create.ScriptKeyword("scale"), create.Char(')'),
create.ScriptKeyword("alpha"), create.Char('{')
create.ScriptKeyword("x"),
create.ScriptKeyword("y"),
}),
create.ScriptKeyword("from"),
create.ScriptNumeric(),
create.ScriptKeyword("to"),
create.ScriptNumeric(),
create.ScriptKeyword("over"),
create.ScriptNumeric()
}).Capture(CAPTURE_SCRIPT_TOKEN),
create.Optional(create.Char(';'))
}); });
} }
protected:
void ProcessMatch(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result) const override
{
auto expression = MenuCommonMatchers::ProcessExpression(state, result);
if (!expression)
throw ParsingException(result.NextCapture(CAPTURE_KEYWORD).GetPos(), "Could not parse expression");
auto newCondition = std::make_unique<CommonEventHandlerCondition>(std::move(expression), std::make_unique<CommonEventHandlerSet>(), nullptr);
auto* newConditionPtr = newCondition.get();
state->m_current_nested_event_handler_set->m_elements.emplace_back(std::move(newCondition));
state->m_condition_stack.emplace(newConditionPtr);
state->m_current_nested_event_handler_set = newConditionPtr->m_condition_elements.get();
}
};
class SequenceElseIf final : public MenuFileParser::sequence_t
{
static constexpr auto CAPTURE_KEYWORD = 1;
public:
SequenceElseIf()
{
const ScriptMatcherFactory create(this);
AddLabeledMatchers(MenuCommonMatchers::Expression(this), MenuCommonMatchers::LABEL_EXPRESSION);
AddMatchers({
create.Keyword("elseif").Capture(CAPTURE_KEYWORD),
create.Char('('),
create.Label(MenuCommonMatchers::LABEL_EXPRESSION),
create.Char(')'),
create.Char('{')
});
}
protected:
void ProcessMatch(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result) const override
{
auto expression = MenuCommonMatchers::ProcessExpression(state, result);
if (!expression)
throw ParsingException(result.NextCapture(CAPTURE_KEYWORD).GetPos(), "Could not parse expression");
if (state->m_condition_stack.empty())
throw ParsingException(result.NextCapture(CAPTURE_KEYWORD).GetPos(), "Not in an if statement");
auto& currentCondition = state->m_condition_stack.top();
assert(currentCondition.m_in_condition_elements == (currentCondition.m_condition->m_else_elements == nullptr));
if (!currentCondition.m_in_condition_elements)
throw ParsingException(result.NextCapture(CAPTURE_KEYWORD).GetPos(), "Cannot specify elseif after else");
currentCondition.m_in_condition_elements = false;
auto newCondition = std::make_unique<CommonEventHandlerCondition>(std::move(expression), std::make_unique<CommonEventHandlerSet>(), nullptr);
auto* newConditionPtr = newCondition.get();
currentCondition.m_condition->m_else_elements = std::make_unique<CommonEventHandlerSet>();
currentCondition.m_condition->m_else_elements->m_elements.emplace_back(std::move(newCondition));
state->m_condition_stack.emplace(newConditionPtr, true);
state->m_current_nested_event_handler_set = newConditionPtr->m_condition_elements.get();
}
};
class SequenceElse final : public MenuFileParser::sequence_t
{
static constexpr auto CAPTURE_KEYWORD = 1;
public:
SequenceElse()
{
const ScriptMatcherFactory create(this);
AddLabeledMatchers(MenuCommonMatchers::Expression(this), MenuCommonMatchers::LABEL_EXPRESSION);
AddMatchers({
create.Keyword("else").Capture(CAPTURE_KEYWORD),
create.Char('{')
});
}
protected:
void ProcessMatch(MenuFileParserState* state, SequenceResult<SimpleParserValue>& result) const override
{
if (state->m_condition_stack.empty())
throw ParsingException(result.NextCapture(CAPTURE_KEYWORD).GetPos(), "Not in an if statement");
auto& currentCondition = state->m_condition_stack.top();
assert(currentCondition.m_in_condition_elements == (currentCondition.m_condition->m_else_elements == nullptr));
if (!currentCondition.m_in_condition_elements)
throw ParsingException(result.NextCapture(CAPTURE_KEYWORD).GetPos(), "Cannot specify second else block");
currentCondition.m_in_condition_elements = false;
currentCondition.m_condition->m_else_elements = std::make_unique<CommonEventHandlerSet>();
state->m_current_nested_event_handler_set = currentCondition.m_condition->m_else_elements.get();
}
}; };
} }
@ -457,7 +585,7 @@ void EventHandlerSetScopeSequences::AddSequences(FeatureLevel featureLevel)
AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("respondOnDvarStringValue"), create.ScriptText(), create.ScriptText(), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("respondOnDvarStringValue"), create.ScriptText(), create.ScriptText(), create.ScriptText()}));
AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("respondOnDvarIntValue"), create.ScriptText(), create.ScriptInt(), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("respondOnDvarIntValue"), create.ScriptText(), create.ScriptInt(), create.ScriptText()}));
AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("respondOnDvarFloatValue"), create.ScriptText(), create.ScriptNumeric(), create.ScriptText()})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("respondOnDvarFloatValue"), create.ScriptText(), create.ScriptNumeric(), create.ScriptText()}));
AddSequence(std::make_unique<SequenceSetPlayerData>()); //AddSequence(std::make_unique<SequenceSetPlayerData>());
AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("setPlayerDataSp")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("setPlayerDataSp")}));
AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("updateMail")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("updateMail")}));
AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("openMail")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("openMail")}));
@ -481,4 +609,7 @@ void EventHandlerSetScopeSequences::AddSequences(FeatureLevel featureLevel)
AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("togglePlayerMute")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("togglePlayerMute")}));
AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("resolveError")})); AddSequence(SequenceGenericScriptStatement::Create({create.ScriptKeyword("resolveError")}));
AddSequence(std::make_unique<SequenceLerp>()); AddSequence(std::make_unique<SequenceLerp>());
AddSequence(std::make_unique<SequenceIf>());
AddSequence(std::make_unique<SequenceElseIf>());
AddSequence(std::make_unique<SequenceElse>());
} }