-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathCmd.cpp
88 lines (71 loc) · 2.46 KB
/
Cmd.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include "Cmd.h"
#include "DrawStrategy.hpp"
#include "Rule.h"
#include "Turtle.h"
void Command::evaluateExpressions(const Context& /*context*/) const
{}
void Command::forwardExecuteTo(const Command &command, RunState &target, int depth) const {
command.executeOn(target, depth);
}
RotateCommand::RotateCommand(std::unique_ptr<Parsenode> _a) :
_angleExpression(std::move(_a)) {
}
void RotateCommand::executeOn(RunState& target, int /* unused */) const {
target._drawStrategy.rotate(_angle);
}
void RotateCommand::evaluateExpressions(const Context& context) const{
_angle = _angleExpression->eval(context);
}
void FlipCommand::executeOn(RunState& target, int /* unused */) const
{
target._drawStrategy.flip();
}
void PushCommand::executeOn(RunState& target, int /* unused */) const
{
target._drawStrategy.push();
}
void PopCommand::executeOn(RunState& target, int /* unused */) const
{
target._drawStrategy.pop();
}
RuleCommand::RuleCommand(std::string_view ruleName,
bool isReversed, bool isFlipped, ParsenodePtr scaleExpression) :
_ruleName(ruleName), _isReversed(isReversed), _isFlipped(isFlipped),
_scaleExpression(std::move(scaleExpression)) {
}
void RuleCommand::run(std::string_view startrule,const Ruletable &_rules, DrawStrategy & drawStrategy, int depth) {
RunState rr{_rules,drawStrategy};
RuleCommand(startrule,false,false).executeOn(rr , depth);
}
template <typename Func>
void forwardOrBackwards(bool backwards,const Commands &c, Func f)
{
if(backwards)
for(auto i = c.rbegin(); i != c.rend(); ++i)
f(i);
else
for(auto i = c.begin(); i != c.end(); ++i)
f(i);
}
void RuleCommand::executeOn(RunState& target, int depth) const
{
const auto & rule = target._rules.at(_ruleName);
if (depth == 0) {
target._drawStrategy.draw(rule,_isFlipped,_atScale);
return;
}
auto oldScale = target._drawStrategy.getScale();
target._drawStrategy.scaleby(_atScale*rule.getLocalScale());
if (_isFlipped)
target._drawStrategy.flip();
target._backwards ^= _isReversed; //NOLINT
forwardOrBackwards(target._backwards, rule.getCommands(), [&](auto i){
forwardExecuteTo(**i,target,depth-1);});
target._backwards ^= _isReversed; //NOLINT
if (_isFlipped)
target._drawStrategy.flip();
target._drawStrategy.setScale(oldScale);
}
void RuleCommand::evaluateExpressions(const Context& context) const {
_atScale = _scaleExpression->eval(context);
}