Skip to content

Commit 852949f

Browse files
authored
Merge pull request #3411 from shun-iwasawa/g/periodic_random
New Expression Function: Periodic Random
2 parents 14aa7ae + e2f9352 commit 852949f

File tree

1 file changed

+107
-6
lines changed

1 file changed

+107
-6
lines changed

toonz/sources/common/expressions/tgrammar.cpp

Lines changed: 107 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,8 @@ class CycleNode final : public CalculatorNode {
267267

268268
//-------------------------------------------------------------------
269269

270-
class RandomNode final : public CalculatorNode {
270+
class RandomNode : public CalculatorNode {
271+
protected:
271272
std::unique_ptr<CalculatorNode> m_seed, m_min, m_max, m_arg;
272273

273274
public:
@@ -312,6 +313,48 @@ class RandomNode final : public CalculatorNode {
312313
}
313314
};
314315

316+
//-------------------------------------------------------------------
317+
318+
class PeriodicRandomNode final : public RandomNode {
319+
std::unique_ptr<CalculatorNode> m_period;
320+
321+
public:
322+
PeriodicRandomNode(Calculator *calc) : RandomNode(calc), m_period() {}
323+
324+
void setPeriod(CalculatorNode *arg) {
325+
assert(m_period.get() == 0);
326+
m_period.reset(arg);
327+
}
328+
329+
double compute(double vars[3]) const override {
330+
double s = (m_seed.get() != 0) ? m_seed->compute(vars) : 0;
331+
double period = m_period->compute(vars);
332+
if (period == 0) period = 1;
333+
double f = m_arg->compute(vars);
334+
335+
double f0 = period * std::floor(f / period);
336+
double f1 = period * (std::floor(f / period) + 1);
337+
double ratio = (f - f0) / (f1 - f0);
338+
339+
double r0 = RandomManager::instance()->getValue(s, fabs(f0));
340+
double r1 = RandomManager::instance()->getValue(s, fabs(f1));
341+
double r = (1 - ratio) * r0 + ratio * r1;
342+
343+
if (m_min.get() == 0)
344+
if (m_max.get() == 0)
345+
return r;
346+
else
347+
return m_max->compute(vars) * r;
348+
else
349+
return (1 - r) * m_min->compute(vars) + r * m_max->compute(vars);
350+
}
351+
352+
void accept(CalculatorNodeVisitor &visitor) override {
353+
RandomNode::accept(visitor);
354+
if (m_period.get()) m_period->accept(visitor);
355+
}
356+
};
357+
315358
//===================================================================
316359
// Patterns
317360
//-------------------------------------------------------------------
@@ -538,7 +581,8 @@ class QuestionTernaryPattern final : public Pattern {
538581
bool matchToken(const std::vector<Token> &previousTokens,
539582
const Token &token) const override {
540583
int i = (int)previousTokens.size();
541-
return ((i == 1 && token.getText() == "?") || (i == 3 && token.getText() == ":"));
584+
return ((i == 1 && token.getText() == "?") ||
585+
(i == 3 && token.getText() == ":"));
542586
}
543587
bool isFinished(const std::vector<Token> &previousTokens,
544588
const Token &token) const override {
@@ -648,7 +692,7 @@ class FunctionPattern : public Pattern {
648692
const Token &token) const override {
649693
if (previousTokens.empty()) return false;
650694
return ((m_minArgCount == 0 && previousTokens.size() == 1 &&
651-
token.getText() != "(") ||
695+
token.getText() != "(") ||
652696
(previousTokens.back().getText() == ")"));
653697
}
654698
TokenType getTokenType(const std::vector<Token> &previousTokens,
@@ -692,11 +736,11 @@ class FunctionPattern : public Pattern {
692736
while (k > 0) nodes[--k] = popNode(stack);
693737
} else {
694738
while (k > 1) nodes[--k] = popNode(stack);
695-
nodes[0] = new VariableNode(calc, CalculatorNode::FRAME);
739+
nodes[0] = new VariableNode(calc, CalculatorNode::FRAME);
696740
}
697741

698742
// add default values
699-
for (int i = 0; i < m; i++)
743+
for (int i = 0; i < m; i++)
700744
nodes[n - m + i] = new NumberNode(calc, m_optionalArgDefaults[i]);
701745
}
702746
};
@@ -843,6 +887,36 @@ class RandomPattern final : public FunctionPattern {
843887
}
844888
};
845889

890+
//-------------------------------------------------------------------
891+
892+
class PeriodicRandomPattern final : public FunctionPattern {
893+
bool m_seed;
894+
895+
public:
896+
PeriodicRandomPattern(std::string functionName, bool seed,
897+
std::string description)
898+
: FunctionPattern(functionName, seed ? 2 : 1), m_seed(seed) {
899+
allowImplicitArg(true);
900+
addOptionalArg(0);
901+
addOptionalArg(0);
902+
setDescription(description);
903+
}
904+
void createNode(Calculator *calc, std::vector<CalculatorNode *> &stack,
905+
const std::vector<Token> &tokens) const override {
906+
int n = ((int)tokens.size() - 1) / 2;
907+
n--;
908+
if (m_seed) n--;
909+
PeriodicRandomNode *randomNode = new PeriodicRandomNode(calc);
910+
if (n > 0) {
911+
randomNode->setMax(popNode(stack));
912+
if (n > 1) randomNode->setMin(popNode(stack));
913+
}
914+
if (m_seed) randomNode->setSeed(popNode(stack));
915+
randomNode->setPeriod(popNode(stack));
916+
stack.push_back(randomNode);
917+
}
918+
};
919+
846920
//===================================================================
847921

848922
class PatternTable {
@@ -1085,7 +1159,7 @@ class Saw {
10851159
double operator()(double x, double length, double height) const {
10861160
if (length <= 0.0) return 0.0;
10871161
if (height <= 0.0) height = length;
1088-
double q = x / length;
1162+
double q = x / length;
10891163
return height * (q - floor(q));
10901164
}
10911165
};
@@ -1224,6 +1298,33 @@ Grammar::Grammar() : m_imp(new Imp()) {
12241298
"0,max)\nrnd_s(seed,min,max)\n" +
12251299
rnd_s_desc));
12261300

1301+
const std::string rnd_p_desc =
1302+
rnd_desc + "; values are interpolated in periodic intervals";
1303+
addPattern(new PeriodicRandomPattern(
1304+
"random_p", false,
1305+
"random_p(period) = random_p(period,0,1)\nrandom_p(period,max) = "
1306+
"random_p(period,0,max)\nrandom_p(period,min,max)\n" +
1307+
rnd_p_desc));
1308+
addPattern(new PeriodicRandomPattern(
1309+
"rnd_p", false,
1310+
"rnd_p(period) = rnd_p(period,0,1)\nrnd_p(period,max) = "
1311+
"rnd_p(period,0,max)\nrnd_p(period,min,max)\n" +
1312+
rnd_p_desc));
1313+
const std::string rnd_ps_desc =
1314+
rnd_s_desc + "; values are interpolated in periodic intervals";
1315+
addPattern(new PeriodicRandomPattern(
1316+
"random_ps", true,
1317+
"random_ps(period,seed) = random_ps(period,seed, "
1318+
"0,1)\nrandom_ps(period,seed,max) = random_ps(period,seed, "
1319+
"0,max)\nrandom_ps(period,seed,min,max)\n" +
1320+
rnd_ps_desc));
1321+
addPattern(new PeriodicRandomPattern(
1322+
"rnd_ps", true,
1323+
"rnd_ps(period,seed) = rnd_ps(period,seed, "
1324+
"0,1)\nrnd_ps(period,seed,max) = rnd_ps(period,seed, "
1325+
"0,max)\nrnd_ps(period,seed,min,max)\n" +
1326+
rnd_ps_desc));
1327+
12271328
addPattern(new CyclePattern("cycle"));
12281329
}
12291330

0 commit comments

Comments
 (0)