temp solution for loops and chains
This commit is contained in:
parent
4b6296c697
commit
e51e684875
9 changed files with 708 additions and 657 deletions
|
@ -20,13 +20,13 @@ namespace {
|
|||
namespace K {
|
||||
K::AppState app_state;
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchCompFrame(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchCompFrame(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes = nullptr) {
|
||||
return PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type{static_cast<i32>(s.current_frame)};
|
||||
}
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchCompTime(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchCompTime(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes = nullptr) {
|
||||
return PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type{static_cast<f32>(s.current_frame) / s.fps};
|
||||
}
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchAppTicks(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchAppTicks(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes = nullptr) {
|
||||
return PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type{ static_cast<f32>(SDL_GetTicks64()) };
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,30 @@
|
|||
#include <PlugboardGraph.h>
|
||||
#include <PlugboardNodes.h>
|
||||
|
||||
namespace K::PlugboardGraph {
|
||||
void NodeInstance::connect(u32 input_index, NodeInstance *to, u32 to_out_index) {
|
||||
inputs_fed[input_index] = ConnectInfo{to, to_out_index};
|
||||
to->outputs_going[to_out_index].push_back({this, input_index});
|
||||
}
|
||||
|
||||
void NodeInstance::disconnect(u32 input_index) {
|
||||
std::visit([this](auto&& arg){
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<T, ConnectInfo>) {
|
||||
for (auto it = arg.p->outputs_going[arg.index].begin();
|
||||
it != arg.p->outputs_going[arg.index].end(); it++) {
|
||||
if (it->p == this) {
|
||||
arg.p->outputs_going[arg.index].erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, T_Map<Type::T_Count>::type>)
|
||||
;
|
||||
}, inputs_fed[input_index]);
|
||||
inputs_fed[input_index] = expand_type(node->in[input_index].type);
|
||||
}
|
||||
|
||||
String VarToString(const T_Map<T_Count>::type& var) {
|
||||
return std::visit([](auto&& arg) -> String {
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
|
@ -24,8 +48,18 @@ namespace K::PlugboardGraph {
|
|||
return table[i];
|
||||
}
|
||||
|
||||
T_Map<T_Count>::type Eval(const CompState& s, const ConnectInfo& info) {
|
||||
return info.p->node->fetch[info.index](s, *info.p);
|
||||
T_Map<T_Count>::type Eval(const CompState& s, const ConnectInfo& info, Vector<ConnectInfo> *show_nodes) {
|
||||
auto p = *info.p;
|
||||
auto n = p.node;
|
||||
if (show_nodes != nullptr) {
|
||||
if (std::find(show_nodes->begin(), show_nodes->end(), info) != show_nodes->end()) {
|
||||
Log("Failure to evaluate plugboard tree: loop detected!");
|
||||
return {}; // tree contains cycle -- abort
|
||||
}
|
||||
if (n == &PlugboardNodes::Chain)
|
||||
show_nodes->push_back(info);
|
||||
}
|
||||
return n->fetch[info.index](s, p, show_nodes);
|
||||
}
|
||||
|
||||
NodeInstance MakeInstance(Node& n) {
|
||||
|
|
490
Keishiki/PlugboardNodes.cpp
Normal file
490
Keishiki/PlugboardNodes.cpp
Normal file
|
@ -0,0 +1,490 @@
|
|||
#include <PlugboardNodes.h>
|
||||
|
||||
namespace K::PlugboardNodes {
|
||||
std::array<PlugboardGraph::Node*, 20> Nodes = std::to_array<PlugboardGraph::Node*>({
|
||||
&Add,
|
||||
&Subtract,
|
||||
&Multiply,
|
||||
&Divide,
|
||||
&Negate,
|
||||
|
||||
&NaturalLogarithm,
|
||||
&SquareRoot,
|
||||
&Power,
|
||||
|
||||
&AbsoluteValue,
|
||||
&Sign,
|
||||
&Minimum,
|
||||
&Maximum,
|
||||
|
||||
&Sin,
|
||||
&Cos,
|
||||
&Tan,
|
||||
&Arcsin,
|
||||
&Arccos,
|
||||
&Arctan,
|
||||
&Atan2,
|
||||
|
||||
&Interpolation
|
||||
});
|
||||
|
||||
const char *K_Interpolation_Names[] = {
|
||||
"Cubic Bezier",
|
||||
"In Constant",
|
||||
"Out Constant",
|
||||
"Linear",
|
||||
"Step",
|
||||
"Smooth Step",
|
||||
"In Quadratic",
|
||||
"Out Quadratic",
|
||||
"In Out Quadratic",
|
||||
"Out In Quadratic",
|
||||
"In Cubic",
|
||||
"Out Cubic",
|
||||
"In Out Cubic",
|
||||
"Out In Cubic",
|
||||
"In Quartic",
|
||||
"Out Quartic",
|
||||
"In Out Quartic",
|
||||
"Out In Quartic",
|
||||
"In Quintic",
|
||||
"Out Quintic",
|
||||
"In Out Quintic",
|
||||
"Out In Quintic",
|
||||
"In Sine",
|
||||
"Out Sine",
|
||||
"In Out Sine",
|
||||
"Out In Sine",
|
||||
"In Exponential",
|
||||
"Out Exponential",
|
||||
"In Out Exponential",
|
||||
"Out In Exponential",
|
||||
"In Circular",
|
||||
"Out Circular",
|
||||
"In Out Circular",
|
||||
"Out In Circular",
|
||||
"In Elastic",
|
||||
"Out Elastic",
|
||||
"In Out Elastic",
|
||||
"Out In Elastic",
|
||||
"In Back",
|
||||
"Out Back",
|
||||
"In Out Back",
|
||||
"Out In Back",
|
||||
"In Bounce",
|
||||
"Out Bounce",
|
||||
"In Out Bounce",
|
||||
"Out In Bounce",
|
||||
"Invalid"
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchAdd(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes),
|
||||
y = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 1, show_nodes);
|
||||
return x + y;
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Add = {
|
||||
.name = "Add",
|
||||
.in = { {"a", PlugboardGraph::T_Float }, {"b", PlugboardGraph::T_Float } },
|
||||
.out = { { "a+b", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchAdd }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchNegate(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes);
|
||||
return -x;
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Negate = {
|
||||
.name = "Negate",
|
||||
.in = { {"a", PlugboardGraph::T_Float } },
|
||||
.out = { { "-a", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchNegate }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchSubtract(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes),
|
||||
y = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 1, show_nodes);
|
||||
return x-y;
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Subtract = {
|
||||
.name = "Subtract",
|
||||
.in = { {"a", PlugboardGraph::T_Float }, {"b", PlugboardGraph::T_Float } },
|
||||
.out = { { "a-b", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchSubtract }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchMultiply(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes),
|
||||
y = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 1, show_nodes);
|
||||
return x*y;
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Multiply = {
|
||||
.name = "Multiply",
|
||||
.in = { {"a", PlugboardGraph::T_Float }, {"b", PlugboardGraph::T_Float } },
|
||||
.out = { { "a*b", PlugboardGraph::T_Float } },
|
||||
.fetch = {FetchMultiply }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchDivide(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes),
|
||||
y = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 1, show_nodes);
|
||||
return x/y;
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Divide = {
|
||||
.name = "Divide",
|
||||
.in = { {"a", PlugboardGraph::T_Float }, {"b", PlugboardGraph::T_Float } },
|
||||
.out = { { "a/b", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchDivide }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchSign(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes);
|
||||
return std::signbit(x) ? -1.0f : 1.0f;
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Sign = {
|
||||
.name = "Sign",
|
||||
.in = { {"a", PlugboardGraph::T_Float } },
|
||||
.out = { { "sgn(a)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchSign }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchSin(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes);
|
||||
return std::sin(x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Sin = {
|
||||
.name = "Sin",
|
||||
.in = { {"a (rad)", PlugboardGraph::T_Float } },
|
||||
.out = { { "sin(a)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchSin }
|
||||
};
|
||||
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchCos(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes);
|
||||
return std::cos(x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Cos = {
|
||||
.name = "Cos",
|
||||
.in = { {"a (rad)", PlugboardGraph::T_Float } },
|
||||
.out = { { "cos(a)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchCos }
|
||||
};
|
||||
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchTan(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes);
|
||||
return std::tan(x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Tan = {
|
||||
.name = "Tan",
|
||||
.in = { {"a (rad)", PlugboardGraph::T_Float } },
|
||||
.out = { { "tan(a)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchTan }
|
||||
};
|
||||
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchArcsin(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes);
|
||||
return std::asin(x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Arcsin = {
|
||||
.name = "Arcsin",
|
||||
.in = { {"a", PlugboardGraph::T_Float } },
|
||||
.out = { { "arcsin(a) (rad)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchArcsin }
|
||||
};
|
||||
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchArccos(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes);
|
||||
return std::acos(x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Arccos = {
|
||||
.name = "Arccos",
|
||||
.in = { {"a", PlugboardGraph::T_Float } },
|
||||
.out = { { "arccos(a) (rad)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchArccos }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchArctan(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes);
|
||||
return std::atan(x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Arctan = {
|
||||
.name = "Arctan",
|
||||
.in = { {"a", PlugboardGraph::T_Float } },
|
||||
.out = { { "arctan(a) (rad)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchArctan }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchAtan2(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 y = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes),
|
||||
x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 1, show_nodes);
|
||||
return std::atan2(y, x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Atan2 = {
|
||||
.name = "Atan2",
|
||||
.in = { {"y", PlugboardGraph::T_Float }, {"x", PlugboardGraph::T_Float } },
|
||||
.out = { { "atan2(y, x) (rad)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchAtan2 }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchMinimum(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 y = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes),
|
||||
x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 1, show_nodes);
|
||||
return std::min(y, x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Minimum = {
|
||||
.name = "Minimum",
|
||||
.in = { {"a", PlugboardGraph::T_Float }, {"b", PlugboardGraph::T_Float } },
|
||||
.out = { { "min(a, b)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchMinimum }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchMaximum(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 y = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes),
|
||||
x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 1, show_nodes);
|
||||
return std::max(y, x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Maximum = {
|
||||
.name = "Maximum",
|
||||
.in = { {"a", PlugboardGraph::T_Float }, {"b", PlugboardGraph::T_Float } },
|
||||
.out = { { "max(a, b)", PlugboardGraph::T_Float } },
|
||||
.fetch = {FetchMaximum }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchPower(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes),
|
||||
y = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 1, show_nodes);
|
||||
return std::pow(x, y);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Power = {
|
||||
.name = "Power",
|
||||
.in = { {"a", PlugboardGraph::T_Float }, {"b", PlugboardGraph::T_Float } },
|
||||
.out = { { "a^b", PlugboardGraph::T_Float } },
|
||||
.fetch = {FetchPower }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchSquareRoot(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes);
|
||||
return std::sqrt(x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node SquareRoot = {
|
||||
.name = "Square Root",
|
||||
.in = { {"a", PlugboardGraph::T_Float } },
|
||||
.out = { { "sqrt(a)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchSquareRoot }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchNaturalLogarithm(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes);
|
||||
return std::log(x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node NaturalLogarithm = {
|
||||
.name = "Natural Logarithm",
|
||||
.in = { {"a", PlugboardGraph::T_Float } },
|
||||
.out = { { "log(a)", PlugboardGraph::T_Float } },
|
||||
.fetch = {FetchNaturalLogarithm }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchAbsoluteValue(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes);
|
||||
return std::log(x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node AbsoluteValue = {
|
||||
.name = "Absolute Value",
|
||||
.in = { {"a", PlugboardGraph::T_Float } },
|
||||
.out = { { "|a|", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchAbsoluteValue }
|
||||
};
|
||||
|
||||
f32 EvalInterpolation(f32 x, const InterpolationExtra& extra) {
|
||||
switch (extra.interp) {
|
||||
case K_I_InConstant:
|
||||
return 0.0f;
|
||||
case K_I_OutConstant:
|
||||
return 1.0f;
|
||||
case K_I_Linear:
|
||||
return x;
|
||||
case K_I_Step:
|
||||
return bx::getEaseFunc(bx::Easing::Step)(x);
|
||||
case K_I_SmoothStep:
|
||||
return bx::getEaseFunc(bx::Easing::SmoothStep)(x);
|
||||
case K_I_InQuadratic:
|
||||
return bx::getEaseFunc(bx::Easing::InQuad)(x);
|
||||
case K_I_OutQuadratic:
|
||||
return bx::getEaseFunc(bx::Easing::OutQuad)(x);
|
||||
case K_I_InOutQuadratic:
|
||||
return bx::getEaseFunc(bx::Easing::InOutQuad)(x);
|
||||
case K_I_OutInQuadratic:
|
||||
return bx::getEaseFunc(bx::Easing::OutInQuad)(x);
|
||||
case K_I_InCubic:
|
||||
return bx::getEaseFunc(bx::Easing::InCubic)(x);
|
||||
case K_I_OutCubic:
|
||||
return bx::getEaseFunc(bx::Easing::OutCubic)(x);
|
||||
case K_I_InOutCubic:
|
||||
return bx::getEaseFunc(bx::Easing::InOutCubic)(x);
|
||||
case K_I_OutInCubic:
|
||||
return bx::getEaseFunc(bx::Easing::OutInCubic)(x);
|
||||
case K_I_InQuartic:
|
||||
return bx::getEaseFunc(bx::Easing::InQuart)(x);
|
||||
case K_I_OutQuartic:
|
||||
return bx::getEaseFunc(bx::Easing::OutQuart)(x);
|
||||
case K_I_InOutQuartic:
|
||||
return bx::getEaseFunc(bx::Easing::InOutQuart)(x);
|
||||
case K_I_OutInQuartic:
|
||||
return bx::getEaseFunc(bx::Easing::OutInQuart)(x);
|
||||
case K_I_InQuintic:
|
||||
return bx::getEaseFunc(bx::Easing::InQuint)(x);
|
||||
case K_I_OutQuintic:
|
||||
return bx::getEaseFunc(bx::Easing::OutInQuint)(x);
|
||||
case K_I_InOutQuintic:
|
||||
return bx::getEaseFunc(bx::Easing::InOutQuint)(x);
|
||||
case K_I_OutInQuintic:
|
||||
return bx::getEaseFunc(bx::Easing::OutInQuint)(x);
|
||||
case K_I_InSine:
|
||||
return bx::getEaseFunc(bx::Easing::InSine)(x);
|
||||
case K_I_OutSine:
|
||||
return bx::getEaseFunc(bx::Easing::OutSine)(x);
|
||||
case K_I_InOutSine:
|
||||
return bx::getEaseFunc(bx::Easing::InOutSine)(x);
|
||||
case K_I_OutInSine:
|
||||
return bx::getEaseFunc(bx::Easing::OutInSine)(x);
|
||||
case K_I_InExponential:
|
||||
return bx::getEaseFunc(bx::Easing::InExpo)(x);
|
||||
case K_I_OutExponential:
|
||||
return bx::getEaseFunc(bx::Easing::OutExpo)(x);
|
||||
case K_I_InOutExponential:
|
||||
return bx::getEaseFunc(bx::Easing::InOutExpo)(x);
|
||||
case K_I_OutInExponential:
|
||||
return bx::getEaseFunc(bx::Easing::OutInExpo)(x);
|
||||
case K_I_InCircular:
|
||||
return bx::getEaseFunc(bx::Easing::InCirc)(x);
|
||||
case K_I_OutCircular:
|
||||
return bx::getEaseFunc(bx::Easing::OutCirc)(x);
|
||||
case K_I_InOutCircular:
|
||||
return bx::getEaseFunc(bx::Easing::InOutCirc)(x);
|
||||
case K_I_OutInCircular:
|
||||
return bx::getEaseFunc(bx::Easing::OutInCirc)(x);
|
||||
case K_I_InElastic:
|
||||
return bx::getEaseFunc(bx::Easing::InElastic)(x);
|
||||
case K_I_OutElastic:
|
||||
return bx::getEaseFunc(bx::Easing::OutElastic)(x);
|
||||
case K_I_InOutElastic:
|
||||
return bx::getEaseFunc(bx::Easing::InOutElastic)(x);
|
||||
case K_I_OutInElastic:
|
||||
return bx::getEaseFunc(bx::Easing::OutInElastic)(x);
|
||||
case K_I_InBack:
|
||||
return bx::getEaseFunc(bx::Easing::InBack)(x);
|
||||
case K_I_OutBack:
|
||||
return bx::getEaseFunc(bx::Easing::OutBack)(x);
|
||||
case K_I_InOutBack:
|
||||
return bx::getEaseFunc(bx::Easing::InOutBack)(x);
|
||||
case K_I_OutInBack:
|
||||
return bx::getEaseFunc(bx::Easing::OutInBack)(x);
|
||||
case K_I_InBounce:
|
||||
return bx::getEaseFunc(bx::Easing::InBounce)(x);
|
||||
case K_I_OutBounce:
|
||||
return bx::getEaseFunc(bx::Easing::OutBounce)(x);
|
||||
case K_I_InOutBounce:
|
||||
return bx::getEaseFunc(bx::Easing::InOutBounce)(x);
|
||||
case K_I_OutInBounce:
|
||||
return bx::getEaseFunc(bx::Easing::OutInBounce)(x);
|
||||
case K_I_CubicBezier: {
|
||||
f32 p2x = extra.v[0], p2y = extra.v[1], p3x = extra.v[2], p3y = extra.v[3];
|
||||
f32 a = 0.0f, b = p2x, c = p3x, d = 1.0f;
|
||||
f64 t = Graphics::GetCubicUniqueReal(-a+3.0f*b-3.0f*c+d, 3.0f*a-6.0f*b+3.0f*c, -3.0f*a+3.0f*b,a-x);
|
||||
return static_cast<f32>(Graphics::CubicBezier(0.0f, p2y, p3y, 1.0f, t));
|
||||
}
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchInterpolation(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
auto *e = std::any_cast<InterpolationExtra>(&n.extra);
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes);
|
||||
return EvalInterpolation(x, *e);
|
||||
}
|
||||
|
||||
void DrawInterpolation(PlugboardGraph::NodeInstance& n) {
|
||||
auto *v = std::any_cast<InterpolationExtra>(&n.extra);
|
||||
ImGui::SetNextItemWidth(-FLT_MIN);
|
||||
if (ImGui::BeginCombo("##Interp", K_Interpolation_Names[v->interp], ImGuiComboFlags_None)) {
|
||||
for (u32 i = 0; i < K_Interpolation::K_I_Count; i++) {
|
||||
const bool is_selected = (v->interp == i);
|
||||
if (ImGui::Selectable(K_Interpolation_Names[i], is_selected))
|
||||
v->interp = static_cast<K_Interpolation>(i);
|
||||
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
|
||||
void SetUpInterpolation(PlugboardGraph::NodeInstance& n) {
|
||||
n.extra = InterpolationExtra{};
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Interpolation = {
|
||||
.name = "Interpolation",
|
||||
.in = { {"t", PlugboardGraph::T_Float } },
|
||||
.out = { { "Value", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchInterpolation },
|
||||
.special_draw = DrawInterpolation,
|
||||
.extra_setup = SetUpInterpolation
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchChain(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
u32 frame = GetNodeInputArg<PlugboardGraph::T_Int>(s, n, 0, show_nodes);
|
||||
|
||||
auto *v = std::any_cast<std::map<u32, ChainSegment>>(&n.extra);
|
||||
if (v->empty())
|
||||
return 0.0f;
|
||||
if (frame <= v->begin()->first)
|
||||
return v->begin()->second.value;
|
||||
if (frame >= v->rbegin()->first)
|
||||
return v->rbegin()->second.value;
|
||||
|
||||
auto nit = v->upper_bound(frame), it = std::prev(nit);
|
||||
u32 x1 = it->first, x2 = nit->first;
|
||||
f32 t = static_cast<f32>(frame - x1) / static_cast<f32>(x2 - x1);
|
||||
f32 normalized_val = EvalInterpolation(t, it->second.interp);
|
||||
|
||||
return it->second.value + normalized_val * (nit->second.value - it->second.value);
|
||||
}
|
||||
|
||||
void SetUpChain(PlugboardGraph::NodeInstance& n) {
|
||||
n.extra = std::map<u32, ChainSegment>{};
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Chain = {
|
||||
.name = "Chain",
|
||||
.in = { {"In", PlugboardGraph::T_Int } },
|
||||
.out = { { "Out", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchChain },
|
||||
.special_draw = nullptr,
|
||||
.extra_setup = SetUpChain
|
||||
};
|
||||
}
|
224
Keishiki/UI.cpp
224
Keishiki/UI.cpp
|
@ -332,10 +332,10 @@ namespace K::UI {
|
|||
}
|
||||
|
||||
if (ImGui::Begin("Viewport", &draw_viewport)) {
|
||||
if (ImGui::Shortcut(ImGuiKey_Space)) {
|
||||
if (ImGui::Shortcut(ImGuiKey_Space))
|
||||
TogglePlay();
|
||||
}
|
||||
|
||||
// Perform rendering
|
||||
u32 view_count = 0, layers_done = 0;
|
||||
bgfx::setViewFrameBuffer(Graphics::K_VIEW_COMP_COMPOSITE + view_count, composite_fb[0]); // the other fb will be cleared in composite
|
||||
bgfx::setViewClear(Graphics::K_VIEW_COMP_COMPOSITE + view_count, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH | BGFX_CLEAR_STENCIL, 0x00000000);
|
||||
|
@ -973,7 +973,8 @@ namespace K::UI {
|
|||
CompState ss = i.s;
|
||||
ss.current_frame = static_cast<u64>(std::round(x));
|
||||
bool good;
|
||||
return {x, std::get<PlugboardGraph::T_Map<PlugboardGraph::T_Float>::type>(PlugboardGraph::ConvertValue(PlugboardGraph::Eval(ss, i.connected_v), PlugboardGraph::T_Float, good))};
|
||||
Vector<PlugboardGraph::ConnectInfo> info;
|
||||
return {x, std::get<PlugboardGraph::T_Map<PlugboardGraph::T_Float>::type>(PlugboardGraph::ConvertValue(PlugboardGraph::Eval(ss, i.connected_v, &info), PlugboardGraph::T_Float, good))};
|
||||
}, &info, info.samples);
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
|
@ -984,116 +985,130 @@ namespace K::UI {
|
|||
|
||||
draw_tl_bg_drag_area();
|
||||
|
||||
if (uniform_open && (connected_v.index() == 1) && std::get<1>(connected_v).p->node == &PlugboardNodes::Chain) {
|
||||
ImGui::TableNextRow(ImGuiTableRowFlags_None, row_height);
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
ImGui::Indent();
|
||||
ImGui::TreeNodeEx(std::get<1>(connected_v).p->node->name.c_str(),
|
||||
ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_FramePadding);
|
||||
ImGui::TableSetColumnIndex(2);
|
||||
auto *m = std::any_cast<std::map<u32, PlugboardNodes::ChainSegment>>(&std::get<1>(connected_v).p->extra);
|
||||
bool m_empty = m->empty();
|
||||
ImGui::BeginDisabled(m_empty || m->begin()->first >= s.current_frame);
|
||||
if (ImGui::Button("<")) {
|
||||
auto it = std::prev(m->upper_bound(s.current_frame));
|
||||
s.current_frame = (it->first == s.current_frame ? std::prev(it) : it)->first;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::EndDisabled();
|
||||
f32 v = std::get<PlugboardGraph::T_Map<PlugboardGraph::T_Float>::type>(PlugboardGraph::Eval(s, std::get<1>(connected_v))), copy = v;
|
||||
ImGui::DragFloat("##value", &v);
|
||||
ImGui::SameLine();
|
||||
if (v != copy) {
|
||||
auto l = m->lower_bound(s.current_frame);
|
||||
auto interp = l == m->end() ? PlugboardNodes::K_I_Linear : l->second.interp.interp;
|
||||
m->insert_or_assign(s.current_frame, PlugboardNodes::ChainSegment{
|
||||
.value = v,
|
||||
.interp = {
|
||||
.interp = interp
|
||||
}
|
||||
});
|
||||
}
|
||||
ImGui::BeginDisabled(m_empty || m->rbegin()->first <= s.current_frame);
|
||||
if (ImGui::Button(">")) {
|
||||
s.current_frame = m->upper_bound(s.current_frame)->first;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::TableSetColumnIndex(3);
|
||||
ImGui::Text("%lu", m->size());
|
||||
ImGui::TableSetColumnIndex(4);
|
||||
ImVec2 begin_tl = ImGui::GetCursorScreenPos();
|
||||
if (uniform_open && connected_v.index() == 1) {
|
||||
for (auto info: u.show_nodes) {
|
||||
ImGui::TableNextRow(ImGuiTableRowFlags_None, row_height);
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
ImGui::TableSetColumnIndex(1);
|
||||
ImGui::Indent();
|
||||
ImGui::TreeNodeEx(info.p->node->name.c_str(),
|
||||
ImGuiTreeNodeFlags_SpanFullWidth |
|
||||
ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Leaf |
|
||||
ImGuiTreeNodeFlags_FramePadding);
|
||||
ImGui::TableSetColumnIndex(2);
|
||||
auto *m = std::any_cast<std::map<u32, PlugboardNodes::ChainSegment>>(
|
||||
&info.p->extra);
|
||||
bool m_empty = m->empty();
|
||||
ImGui::BeginDisabled(m_empty || m->begin()->first >= s.current_frame);
|
||||
if (ImGui::Button("<")) {
|
||||
auto it = std::prev(m->upper_bound(s.current_frame));
|
||||
s.current_frame = (it->first == s.current_frame ? std::prev(it) : it)->first;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::EndDisabled();
|
||||
f32 v = std::get<PlugboardGraph::T_Map<PlugboardGraph::T_Float>::type>(
|
||||
PlugboardGraph::Eval(s, info)), copy = v;
|
||||
ImGui::DragFloat("##value", &v);
|
||||
ImGui::SameLine();
|
||||
if (v != copy) {
|
||||
auto l = m->lower_bound(s.current_frame);
|
||||
auto interp = l == m->end() ? PlugboardNodes::K_I_Linear : l->second.interp.interp;
|
||||
m->insert_or_assign(s.current_frame, PlugboardNodes::ChainSegment{
|
||||
.value = v,
|
||||
.interp = {
|
||||
.interp = interp
|
||||
}
|
||||
});
|
||||
}
|
||||
ImGui::BeginDisabled(m_empty || m->rbegin()->first <= s.current_frame);
|
||||
if (ImGui::Button(">")) {
|
||||
s.current_frame = m->upper_bound(s.current_frame)->first;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::TableSetColumnIndex(3);
|
||||
ImGui::Text("%lu", m->size());
|
||||
ImGui::TableSetColumnIndex(4);
|
||||
ImVec2 begin_tl = ImGui::GetCursorScreenPos();
|
||||
|
||||
static std::map<u32, PlugboardNodes::ChainSegment> m_copy{};
|
||||
static u32 dragging{};
|
||||
static decltype(m) drag_m = nullptr;
|
||||
static i64 drag_og = -1;
|
||||
if (drag_m != m || drag_og == -1) { // premature optimization is the root of good performance !!
|
||||
f32 *last_val = nullptr;
|
||||
u32 last_x = 0;
|
||||
for (auto& [k, segment] : *m) {
|
||||
ImGui::PushID(k);
|
||||
if (last_val != nullptr && *last_val != segment.value) {
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + row_height / 2.5f);
|
||||
static std::map<u32, PlugboardNodes::ChainSegment> m_copy{};
|
||||
static u32 dragging{};
|
||||
static decltype(m) drag_m = nullptr;
|
||||
static i64 drag_og = -1;
|
||||
if (drag_m != m ||
|
||||
drag_og == -1) { // premature optimization is the root of good performance !!
|
||||
f32 *last_val = nullptr;
|
||||
u32 last_x = 0;
|
||||
for (auto &[k, segment]: *m) {
|
||||
ImGui::PushID(k);
|
||||
ImGui::Button("##strip", {TimelineFrameToScreenView(view_left, view_amt, view_width, k, s.frame_max) - TimelineFrameToScreenView(view_left, view_amt, view_width, last_x, s.frame_max), row_height * .2f});
|
||||
if (last_val != nullptr && *last_val != segment.value) {
|
||||
ImGui::SameLine(0.0f, 0.0f);
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + row_height / 2.5f);
|
||||
ImGui::PushID(k);
|
||||
ImGui::Button("##strip",
|
||||
{TimelineFrameToScreenView(view_left, view_amt, view_width, k,
|
||||
s.frame_max) -
|
||||
TimelineFrameToScreenView(view_left, view_amt, view_width,
|
||||
last_x, s.frame_max),
|
||||
row_height * .2f});
|
||||
ImGui::PopID();
|
||||
}
|
||||
last_val = &segment.value;
|
||||
last_x = k;
|
||||
|
||||
ImGui::SetCursorScreenPos(
|
||||
{TimelineFrameToScreenView(view_left, view_amt, view_width, k,
|
||||
s.frame_max) + begin_tl.x - 2.5f,
|
||||
begin_tl.y});
|
||||
bool d;
|
||||
ImGui::Button("k", {0.0f, row_height * .8f});
|
||||
if (ImGui::IsItemClicked()) {
|
||||
m_copy = *m;
|
||||
drag_og = k;
|
||||
drag_m = m;
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
last_val = &segment.value;
|
||||
last_x = k;
|
||||
|
||||
ImGui::SetCursorScreenPos(
|
||||
{TimelineFrameToScreenView(view_left, view_amt, view_width, k,
|
||||
s.frame_max) + begin_tl.x - 2.5f, begin_tl.y});
|
||||
bool d;
|
||||
ImGui::Button("k", {0.0f, row_height * .8f});
|
||||
if (ImGui::IsItemClicked()) {
|
||||
m_copy = *m;
|
||||
drag_og = k;
|
||||
drag_m = m;
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
else {
|
||||
m->clear();
|
||||
for (auto& [k, segment] : m_copy) {
|
||||
ImGui::PushID(k);
|
||||
if (drag_og != k) {
|
||||
if (TimelineFrameInView(view_left, view_right, k, s.frame_max)) {
|
||||
} else {
|
||||
m->clear();
|
||||
for (auto &[k, segment]: m_copy) {
|
||||
ImGui::PushID(k);
|
||||
if (drag_og != k) {
|
||||
if (TimelineFrameInView(view_left, view_right, k, s.frame_max)) {
|
||||
ImGui::SetCursorScreenPos(
|
||||
{TimelineFrameToScreenView(view_left, view_amt, view_width, k,
|
||||
s.frame_max) + begin_tl.x - 2.5f,
|
||||
begin_tl.y});
|
||||
ImGui::Button("k", {0.0f, row_height * .8f});
|
||||
m->emplace(k, segment);
|
||||
}
|
||||
} else {
|
||||
ImGui::SetCursorScreenPos(
|
||||
{TimelineFrameToScreenView(view_left, view_amt, view_width, k,
|
||||
s.frame_max) + begin_tl.x - 2.5f, begin_tl.y});
|
||||
{TimelineFrameToScreenView(view_left, view_amt, view_width,
|
||||
dragging,
|
||||
s.frame_max) + begin_tl.x - 2.5f,
|
||||
begin_tl.y});
|
||||
ImGui::Button("k", {0.0f, row_height * .8f});
|
||||
m->emplace(k, segment);
|
||||
if (ImGui::IsItemActive()) {
|
||||
dragging = TimelineScreenViewToFrame(view_left, view_amt, view_width,
|
||||
std::clamp(ImGui::GetMousePos().x -
|
||||
tl_init_pos.x, 0.0f,
|
||||
view_width),
|
||||
s.frame_max);
|
||||
m->emplace(dragging, segment);
|
||||
}
|
||||
if (drag_og == k && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
|
||||
m->emplace(dragging, segment);
|
||||
drag_og = -1;
|
||||
drag_m = nullptr;
|
||||
}
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
else {
|
||||
ImGui::SetCursorScreenPos(
|
||||
{TimelineFrameToScreenView(view_left, view_amt, view_width, dragging,
|
||||
s.frame_max) + begin_tl.x - 2.5f, begin_tl.y});
|
||||
ImGui::Button("k", {0.0f, row_height * .8f});
|
||||
if (ImGui::IsItemActive()) {
|
||||
dragging = TimelineScreenViewToFrame(view_left, view_amt, view_width,
|
||||
std::clamp(ImGui::GetMousePos().x -
|
||||
tl_init_pos.x, 0.0f,
|
||||
view_width), s.frame_max);
|
||||
m->emplace(dragging, segment);
|
||||
}
|
||||
if (drag_og == k && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
|
||||
m->emplace(dragging, segment);
|
||||
drag_og = -1;
|
||||
drag_m = nullptr;
|
||||
}
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::SetCursorScreenPos(begin_tl);
|
||||
draw_tl_bg_drag_area();
|
||||
}
|
||||
ImGui::SetCursorScreenPos(begin_tl);
|
||||
draw_tl_bg_drag_area();
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
j++;
|
||||
}
|
||||
|
@ -1117,7 +1132,6 @@ namespace K::UI {
|
|||
if (move_from != -1 && move_to != -1) {
|
||||
if (no_selection)
|
||||
std::swap(s.layers[move_to], s.layers[move_from]);
|
||||
|
||||
else {
|
||||
const u32 n = s.selected.size();
|
||||
u32 inserted = 0;
|
||||
|
@ -1399,10 +1413,8 @@ namespace K::UI {
|
|||
ImGui::DockSpaceOverViewport(0, ImGui::GetMainViewport(), ImGuiDockNodeFlags_PassthruCentralNode);
|
||||
|
||||
ImGui::ShowDemoWindow();
|
||||
// static ImGuiStyle& style = ImGui::GetStyle();
|
||||
// style.GrabRounding = style.FrameRounding = 5.0f;
|
||||
MainMenuBar(s);
|
||||
if (draw_viewport) Viewport(s);
|
||||
if (draw_viewport) Viewport(s); // Must go before comp!
|
||||
if (draw_layer) Layer(s);
|
||||
if (draw_comp) Composition(s);
|
||||
if (draw_interpolation) Interpolation(s);
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace K {
|
|||
}
|
||||
|
||||
void VisualTrack::GetFrame(const CompState& s, u32 view_id, bgfx::FrameBufferHandle fb, u32 w, u32 h, f32 proj[16],
|
||||
f32 view[16], f32 transform[16]) const {
|
||||
f32 view[16], f32 transform[16]) {
|
||||
bgfx::setViewMode(view_id, bgfx::ViewMode::Sequential);
|
||||
bgfx::setViewClear(view_id, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH | BGFX_CLEAR_STENCIL);
|
||||
bgfx::setViewFrameBuffer(view_id, fb);
|
||||
|
@ -55,7 +55,8 @@ namespace K {
|
|||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<T, PlugboardGraph::ConnectInfo>) {
|
||||
bool good;
|
||||
val_target = PlugboardValToShader(PlugboardGraph::ConvertValue(PlugboardGraph::Eval(s, arg),
|
||||
u.show_nodes.clear();
|
||||
val_target = PlugboardValToShader(PlugboardGraph::ConvertValue(PlugboardGraph::Eval(s, arg, &u.show_nodes),
|
||||
static_cast<PlugboardGraph::Type>(u.val.index()), // todo DANGEROUS !!
|
||||
good));
|
||||
}
|
||||
|
|
|
@ -62,17 +62,6 @@ namespace K::PlugboardGraph {
|
|||
};
|
||||
|
||||
struct NodeInstance;
|
||||
struct Node {
|
||||
String name; // will likely get SSO for most stuff
|
||||
|
||||
Vector<Socket> in;
|
||||
Vector<Socket> out;
|
||||
|
||||
Vector<T_Map<T_Count>::type(*)(const CompState&, const NodeInstance&)> fetch; // todo investigate how you might wanna jit this instead of evaluating a tree for each output at runtime esp. when a project is set for rendering
|
||||
void (*special_draw)(NodeInstance&);
|
||||
void (*extra_setup)(NodeInstance&);
|
||||
};
|
||||
|
||||
|
||||
struct ConnectInfo {
|
||||
NodeInstance *p; // NOTE: so NodeInstances must be stored in a list, otherwise vector realloc leads to UAF
|
||||
|
@ -80,6 +69,19 @@ namespace K::PlugboardGraph {
|
|||
auto operator<=>(const ConnectInfo&) const = default; // too-modern c++ black magic ?
|
||||
};
|
||||
|
||||
struct Node {
|
||||
String name; // will likely get SSO for most stuff
|
||||
|
||||
Vector<Socket> in;
|
||||
Vector<Socket> out;
|
||||
|
||||
Vector<T_Map<T_Count>::type(*)(const CompState&, const NodeInstance&, Vector<ConnectInfo>*)> fetch; // todo investigate how you might wanna jit this instead of evaluating a tree for each output at runtime esp. when a project is set for rendering
|
||||
void (*special_draw)(NodeInstance&);
|
||||
void (*extra_setup)(NodeInstance&);
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct ConnectInfoHasher {
|
||||
std::size_t operator()(const ConnectInfo& k) const
|
||||
{
|
||||
|
@ -97,28 +99,8 @@ namespace K::PlugboardGraph {
|
|||
|
||||
std::any extra;
|
||||
|
||||
void connect(u32 input_index, NodeInstance *to, u32 to_out_index) {
|
||||
inputs_fed[input_index] = ConnectInfo{to, to_out_index};
|
||||
to->outputs_going[to_out_index].push_back({this, input_index});
|
||||
}
|
||||
|
||||
void disconnect(u32 input_index) {
|
||||
std::visit([this](auto&& arg){
|
||||
using T = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<T, ConnectInfo>) {
|
||||
for (auto it = arg.p->outputs_going[arg.index].begin();
|
||||
it != arg.p->outputs_going[arg.index].end(); it++) {
|
||||
if (it->p == this) {
|
||||
arg.p->outputs_going[arg.index].erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, T_Map<Type::T_Count>::type>)
|
||||
;
|
||||
}, inputs_fed[input_index]);
|
||||
inputs_fed[input_index] = expand_type(node->in[input_index].type);
|
||||
}
|
||||
void connect(u32 input_index, NodeInstance *to, u32 to_out_index);
|
||||
void disconnect(u32 input_index);
|
||||
};
|
||||
|
||||
|
||||
|
@ -126,7 +108,7 @@ namespace K::PlugboardGraph {
|
|||
|
||||
T_Map<T_Count>::type ConvertValue(const T_Map<T_Count>::type& v, Type target, bool& good);
|
||||
|
||||
T_Map<T_Count>::type Eval(const CompState& s, const ConnectInfo& info);
|
||||
T_Map<T_Count>::type Eval(const CompState& s, const ConnectInfo& info, Vector<ConnectInfo> *show_nodes = nullptr);
|
||||
|
||||
struct LinksFromSource {
|
||||
ImVec2 source;
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
|
||||
namespace {
|
||||
template <K::PlugboardGraph::Type type>
|
||||
typename K::PlugboardGraph::T_Map<type>::type GetNodeInputArg(const K::CompState& s, const K::PlugboardGraph::NodeInstance& n, u32 index) {
|
||||
typename K::PlugboardGraph::T_Map<type>::type GetNodeInputArg(const K::CompState& s, const K::PlugboardGraph::NodeInstance& n, u32 index, K::Vector<K::PlugboardGraph::ConnectInfo> *show_nodes) {
|
||||
bool good;
|
||||
typename K::PlugboardGraph::T_Map<type>::type v = std::get<typename K::PlugboardGraph::T_Map<type>::type>(K::PlugboardGraph::ConvertValue(std::visit([&s](auto&& arg) {
|
||||
typename K::PlugboardGraph::T_Map<type>::type v = std::get<typename K::PlugboardGraph::T_Map<type>::type>(K::PlugboardGraph::ConvertValue(std::visit([&show_nodes, &s](auto&& arg) {
|
||||
using U = std::decay_t<decltype(arg)>;
|
||||
if constexpr (std::is_same_v<U, K::PlugboardGraph::ConnectInfo>)
|
||||
return K::PlugboardGraph::Eval(s, arg);
|
||||
return K::PlugboardGraph::Eval(s, arg, show_nodes);
|
||||
else
|
||||
return arg;
|
||||
}, n.inputs_fed[index]), type, good));
|
||||
|
@ -25,245 +25,25 @@ namespace {
|
|||
}
|
||||
|
||||
namespace K::PlugboardNodes {
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchAdd(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0),
|
||||
y = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 1);
|
||||
return x + y;
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Add = {
|
||||
.name = "Add",
|
||||
.in = { {"a", PlugboardGraph::T_Float }, {"b", PlugboardGraph::T_Float } },
|
||||
.out = { { "a+b", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchAdd }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchNegate(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0);
|
||||
return -x;
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Negate = {
|
||||
.name = "Negate",
|
||||
.in = { {"a", PlugboardGraph::T_Float } },
|
||||
.out = { { "-a", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchNegate }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchSubtract(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0),
|
||||
y = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 1);
|
||||
return x-y;
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Subtract = {
|
||||
.name = "Subtract",
|
||||
.in = { {"a", PlugboardGraph::T_Float }, {"b", PlugboardGraph::T_Float } },
|
||||
.out = { { "a-b", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchSubtract }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchMultiply(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0),
|
||||
y = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 1);
|
||||
return x*y;
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Multiply = {
|
||||
.name = "Multiply",
|
||||
.in = { {"a", PlugboardGraph::T_Float }, {"b", PlugboardGraph::T_Float } },
|
||||
.out = { { "a*b", PlugboardGraph::T_Float } },
|
||||
.fetch = {FetchMultiply }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchDivide(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0),
|
||||
y = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 1);
|
||||
return x/y;
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Divide = {
|
||||
.name = "Divide",
|
||||
.in = { {"a", PlugboardGraph::T_Float }, {"b", PlugboardGraph::T_Float } },
|
||||
.out = { { "a/b", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchDivide }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchSign(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0);
|
||||
return std::signbit(x) ? -1.0f : 1.0f;
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Sign = {
|
||||
.name = "Sign",
|
||||
.in = { {"a", PlugboardGraph::T_Float } },
|
||||
.out = { { "sgn(a)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchSign }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchSin(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0);
|
||||
return std::sin(x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Sin = {
|
||||
.name = "Sin",
|
||||
.in = { {"a (rad)", PlugboardGraph::T_Float } },
|
||||
.out = { { "sin(a)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchSin }
|
||||
};
|
||||
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchCos(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0);
|
||||
return std::cos(x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Cos = {
|
||||
.name = "Cos",
|
||||
.in = { {"a (rad)", PlugboardGraph::T_Float } },
|
||||
.out = { { "cos(a)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchCos }
|
||||
};
|
||||
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchTan(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0);
|
||||
return std::tan(x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Tan = {
|
||||
.name = "Tan",
|
||||
.in = { {"a (rad)", PlugboardGraph::T_Float } },
|
||||
.out = { { "tan(a)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchTan }
|
||||
};
|
||||
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchArcsin(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0);
|
||||
return std::asin(x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Arcsin = {
|
||||
.name = "Arcsin",
|
||||
.in = { {"a", PlugboardGraph::T_Float } },
|
||||
.out = { { "arcsin(a) (rad)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchArcsin }
|
||||
};
|
||||
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchArccos(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0);
|
||||
return std::acos(x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Arccos = {
|
||||
.name = "Arccos",
|
||||
.in = { {"a", PlugboardGraph::T_Float } },
|
||||
.out = { { "arccos(a) (rad)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchArccos }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchArctan(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0);
|
||||
return std::atan(x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Arctan = {
|
||||
.name = "Arctan",
|
||||
.in = { {"a", PlugboardGraph::T_Float } },
|
||||
.out = { { "arctan(a) (rad)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchArctan }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchAtan2(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 y = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0),
|
||||
x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 1);
|
||||
return std::atan2(y, x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Atan2 = {
|
||||
.name = "Atan2",
|
||||
.in = { {"y", PlugboardGraph::T_Float }, {"x", PlugboardGraph::T_Float } },
|
||||
.out = { { "atan2(y, x) (rad)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchAtan2 }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchMinimum(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 y = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0),
|
||||
x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 1);
|
||||
return std::min(y, x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Minimum = {
|
||||
.name = "Minimum",
|
||||
.in = { {"a", PlugboardGraph::T_Float }, {"b", PlugboardGraph::T_Float } },
|
||||
.out = { { "min(a, b)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchMinimum }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchMaximum(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 y = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0),
|
||||
x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 1);
|
||||
return std::max(y, x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Maximum = {
|
||||
.name = "Maximum",
|
||||
.in = { {"a", PlugboardGraph::T_Float }, {"b", PlugboardGraph::T_Float } },
|
||||
.out = { { "max(a, b)", PlugboardGraph::T_Float } },
|
||||
.fetch = {FetchMaximum }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchPower(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0),
|
||||
y = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 1);
|
||||
return std::pow(x, y);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Power = {
|
||||
.name = "Power",
|
||||
.in = { {"a", PlugboardGraph::T_Float }, {"b", PlugboardGraph::T_Float } },
|
||||
.out = { { "a^b", PlugboardGraph::T_Float } },
|
||||
.fetch = {FetchPower }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchSquareRoot(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0);
|
||||
return std::sqrt(x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node SquareRoot = {
|
||||
.name = "Square Root",
|
||||
.in = { {"a", PlugboardGraph::T_Float } },
|
||||
.out = { { "sqrt(a)", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchSquareRoot }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchNaturalLogarithm(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0);
|
||||
return std::log(x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node NaturalLogarithm = {
|
||||
.name = "Natural Logarithm",
|
||||
.in = { {"a", PlugboardGraph::T_Float } },
|
||||
.out = { { "log(a)", PlugboardGraph::T_Float } },
|
||||
.fetch = {FetchNaturalLogarithm }
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchAbsoluteValue(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0);
|
||||
return std::log(x);
|
||||
}
|
||||
|
||||
PlugboardGraph::Node AbsoluteValue = {
|
||||
.name = "Absolute Value",
|
||||
.in = { {"a", PlugboardGraph::T_Float } },
|
||||
.out = { { "|a|", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchAbsoluteValue }
|
||||
};
|
||||
extern PlugboardGraph::Node Add;
|
||||
extern PlugboardGraph::Node Negate;
|
||||
extern PlugboardGraph::Node Subtract;
|
||||
extern PlugboardGraph::Node Multiply;
|
||||
extern PlugboardGraph::Node Divide;
|
||||
extern PlugboardGraph::Node Sign;
|
||||
extern PlugboardGraph::Node Sin;
|
||||
extern PlugboardGraph::Node Cos;
|
||||
extern PlugboardGraph::Node Tan;
|
||||
extern PlugboardGraph::Node Arcsin;
|
||||
extern PlugboardGraph::Node Arccos;
|
||||
extern PlugboardGraph::Node Arctan;
|
||||
extern PlugboardGraph::Node Atan2;
|
||||
extern PlugboardGraph::Node Minimum;
|
||||
extern PlugboardGraph::Node Maximum;
|
||||
extern PlugboardGraph::Node Power;
|
||||
extern PlugboardGraph::Node SquareRoot;
|
||||
extern PlugboardGraph::Node NaturalLogarithm;
|
||||
extern PlugboardGraph::Node AbsoluteValue;
|
||||
|
||||
enum K_Interpolation {
|
||||
K_I_CubicBezier,
|
||||
|
@ -315,261 +95,21 @@ namespace K::PlugboardNodes {
|
|||
K_I_Count
|
||||
};
|
||||
|
||||
|
||||
const char *K_Interpolation_Names[] {
|
||||
"Cubic Bezier",
|
||||
"In Constant",
|
||||
"Out Constant",
|
||||
"Linear",
|
||||
"Step",
|
||||
"Smooth Step",
|
||||
"In Quadratic",
|
||||
"Out Quadratic",
|
||||
"In Out Quadratic",
|
||||
"Out In Quadratic",
|
||||
"In Cubic",
|
||||
"Out Cubic",
|
||||
"In Out Cubic",
|
||||
"Out In Cubic",
|
||||
"In Quartic",
|
||||
"Out Quartic",
|
||||
"In Out Quartic",
|
||||
"Out In Quartic",
|
||||
"In Quintic",
|
||||
"Out Quintic",
|
||||
"In Out Quintic",
|
||||
"Out In Quintic",
|
||||
"In Sine",
|
||||
"Out Sine",
|
||||
"In Out Sine",
|
||||
"Out In Sine",
|
||||
"In Exponential",
|
||||
"Out Exponential",
|
||||
"In Out Exponential",
|
||||
"Out In Exponential",
|
||||
"In Circular",
|
||||
"Out Circular",
|
||||
"In Out Circular",
|
||||
"Out In Circular",
|
||||
"In Elastic",
|
||||
"Out Elastic",
|
||||
"In Out Elastic",
|
||||
"Out In Elastic",
|
||||
"In Back",
|
||||
"Out Back",
|
||||
"In Out Back",
|
||||
"Out In Back",
|
||||
"In Bounce",
|
||||
"Out Bounce",
|
||||
"In Out Bounce",
|
||||
"Out In Bounce",
|
||||
"Invalid"
|
||||
};
|
||||
extern const char *K_Interpolation_Names[];
|
||||
|
||||
struct InterpolationExtra {
|
||||
K_Interpolation interp;
|
||||
f32 v[4];
|
||||
};
|
||||
|
||||
f32 EvalInterpolation(f32 x, const InterpolationExtra& extra) {
|
||||
switch (extra.interp) {
|
||||
case K_I_InConstant:
|
||||
return 0.0f;
|
||||
case K_I_OutConstant:
|
||||
return 1.0f;
|
||||
case K_I_Linear:
|
||||
return x;
|
||||
case K_I_Step:
|
||||
return bx::getEaseFunc(bx::Easing::Step)(x);
|
||||
case K_I_SmoothStep:
|
||||
return bx::getEaseFunc(bx::Easing::SmoothStep)(x);
|
||||
case K_I_InQuadratic:
|
||||
return bx::getEaseFunc(bx::Easing::InQuad)(x);
|
||||
case K_I_OutQuadratic:
|
||||
return bx::getEaseFunc(bx::Easing::OutQuad)(x);
|
||||
case K_I_InOutQuadratic:
|
||||
return bx::getEaseFunc(bx::Easing::InOutQuad)(x);
|
||||
case K_I_OutInQuadratic:
|
||||
return bx::getEaseFunc(bx::Easing::OutInQuad)(x);
|
||||
case K_I_InCubic:
|
||||
return bx::getEaseFunc(bx::Easing::InCubic)(x);
|
||||
case K_I_OutCubic:
|
||||
return bx::getEaseFunc(bx::Easing::OutCubic)(x);
|
||||
case K_I_InOutCubic:
|
||||
return bx::getEaseFunc(bx::Easing::InOutCubic)(x);
|
||||
case K_I_OutInCubic:
|
||||
return bx::getEaseFunc(bx::Easing::OutInCubic)(x);
|
||||
case K_I_InQuartic:
|
||||
return bx::getEaseFunc(bx::Easing::InQuart)(x);
|
||||
case K_I_OutQuartic:
|
||||
return bx::getEaseFunc(bx::Easing::OutQuart)(x);
|
||||
case K_I_InOutQuartic:
|
||||
return bx::getEaseFunc(bx::Easing::InOutQuart)(x);
|
||||
case K_I_OutInQuartic:
|
||||
return bx::getEaseFunc(bx::Easing::OutInQuart)(x);
|
||||
case K_I_InQuintic:
|
||||
return bx::getEaseFunc(bx::Easing::InQuint)(x);
|
||||
case K_I_OutQuintic:
|
||||
return bx::getEaseFunc(bx::Easing::OutInQuint)(x);
|
||||
case K_I_InOutQuintic:
|
||||
return bx::getEaseFunc(bx::Easing::InOutQuint)(x);
|
||||
case K_I_OutInQuintic:
|
||||
return bx::getEaseFunc(bx::Easing::OutInQuint)(x);
|
||||
case K_I_InSine:
|
||||
return bx::getEaseFunc(bx::Easing::InSine)(x);
|
||||
case K_I_OutSine:
|
||||
return bx::getEaseFunc(bx::Easing::OutSine)(x);
|
||||
case K_I_InOutSine:
|
||||
return bx::getEaseFunc(bx::Easing::InOutSine)(x);
|
||||
case K_I_OutInSine:
|
||||
return bx::getEaseFunc(bx::Easing::OutInSine)(x);
|
||||
case K_I_InExponential:
|
||||
return bx::getEaseFunc(bx::Easing::InExpo)(x);
|
||||
case K_I_OutExponential:
|
||||
return bx::getEaseFunc(bx::Easing::OutExpo)(x);
|
||||
case K_I_InOutExponential:
|
||||
return bx::getEaseFunc(bx::Easing::InOutExpo)(x);
|
||||
case K_I_OutInExponential:
|
||||
return bx::getEaseFunc(bx::Easing::OutInExpo)(x);
|
||||
case K_I_InCircular:
|
||||
return bx::getEaseFunc(bx::Easing::InCirc)(x);
|
||||
case K_I_OutCircular:
|
||||
return bx::getEaseFunc(bx::Easing::OutCirc)(x);
|
||||
case K_I_InOutCircular:
|
||||
return bx::getEaseFunc(bx::Easing::InOutCirc)(x);
|
||||
case K_I_OutInCircular:
|
||||
return bx::getEaseFunc(bx::Easing::OutInCirc)(x);
|
||||
case K_I_InElastic:
|
||||
return bx::getEaseFunc(bx::Easing::InElastic)(x);
|
||||
case K_I_OutElastic:
|
||||
return bx::getEaseFunc(bx::Easing::OutElastic)(x);
|
||||
case K_I_InOutElastic:
|
||||
return bx::getEaseFunc(bx::Easing::InOutElastic)(x);
|
||||
case K_I_OutInElastic:
|
||||
return bx::getEaseFunc(bx::Easing::OutInElastic)(x);
|
||||
case K_I_InBack:
|
||||
return bx::getEaseFunc(bx::Easing::InBack)(x);
|
||||
case K_I_OutBack:
|
||||
return bx::getEaseFunc(bx::Easing::OutBack)(x);
|
||||
case K_I_InOutBack:
|
||||
return bx::getEaseFunc(bx::Easing::InOutBack)(x);
|
||||
case K_I_OutInBack:
|
||||
return bx::getEaseFunc(bx::Easing::OutInBack)(x);
|
||||
case K_I_InBounce:
|
||||
return bx::getEaseFunc(bx::Easing::InBounce)(x);
|
||||
case K_I_OutBounce:
|
||||
return bx::getEaseFunc(bx::Easing::OutBounce)(x);
|
||||
case K_I_InOutBounce:
|
||||
return bx::getEaseFunc(bx::Easing::InOutBounce)(x);
|
||||
case K_I_OutInBounce:
|
||||
return bx::getEaseFunc(bx::Easing::OutInBounce)(x);
|
||||
case K_I_CubicBezier: {
|
||||
f32 p2x = extra.v[0], p2y = extra.v[1], p3x = extra.v[2], p3y = extra.v[3];
|
||||
f32 a = 0.0f, b = p2x, c = p3x, d = 1.0f;
|
||||
f64 t = Graphics::GetCubicUniqueReal(-a+3.0f*b-3.0f*c+d, 3.0f*a-6.0f*b+3.0f*c, -3.0f*a+3.0f*b,a-x);
|
||||
return static_cast<f32>(Graphics::CubicBezier(0.0f, p2y, p3y, 1.0f, t));
|
||||
}
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchInterpolation(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
auto *e = std::any_cast<InterpolationExtra>(&n.extra);
|
||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0);
|
||||
return EvalInterpolation(x, *e);
|
||||
}
|
||||
|
||||
void DrawInterpolation(PlugboardGraph::NodeInstance& n) {
|
||||
auto *v = std::any_cast<InterpolationExtra>(&n.extra);
|
||||
ImGui::SetNextItemWidth(-FLT_MIN);
|
||||
if (ImGui::BeginCombo("##Interp", K_Interpolation_Names[v->interp], ImGuiComboFlags_None)) {
|
||||
for (u32 i = 0; i < K_Interpolation::K_I_Count; i++) {
|
||||
const bool is_selected = (v->interp == i);
|
||||
if (ImGui::Selectable(K_Interpolation_Names[i], is_selected))
|
||||
v->interp = static_cast<K_Interpolation>(i);
|
||||
|
||||
if (is_selected)
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
}
|
||||
|
||||
void SetUpInterpolation(PlugboardGraph::NodeInstance& n) {
|
||||
n.extra = InterpolationExtra{};
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Interpolation = {
|
||||
.name = "Interpolation",
|
||||
.in = { {"t", PlugboardGraph::T_Float } },
|
||||
.out = { { "Value", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchInterpolation },
|
||||
.special_draw = DrawInterpolation,
|
||||
.extra_setup = SetUpInterpolation
|
||||
};
|
||||
extern PlugboardGraph::Node Interpolation;
|
||||
|
||||
struct ChainSegment {
|
||||
f32 value;
|
||||
InterpolationExtra interp;
|
||||
};
|
||||
|
||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchChain(const CompState& s, const PlugboardGraph::NodeInstance& n) {
|
||||
u32 frame = GetNodeInputArg<PlugboardGraph::T_Int>(s, n, 0);
|
||||
extern PlugboardGraph::Node Chain;
|
||||
|
||||
auto *v = std::any_cast<std::map<u32, ChainSegment>>(&n.extra);
|
||||
if (v->empty())
|
||||
return 0.0f;
|
||||
if (frame <= v->begin()->first)
|
||||
return v->begin()->second.value;
|
||||
if (frame >= v->rbegin()->first)
|
||||
return v->rbegin()->second.value;
|
||||
|
||||
auto nit = v->upper_bound(frame), it = std::prev(nit);
|
||||
u32 x1 = it->first, x2 = nit->first;
|
||||
f32 t = static_cast<f32>(frame - x1) / static_cast<f32>(x2 - x1);
|
||||
f32 normalized_val = EvalInterpolation(t, it->second.interp);
|
||||
|
||||
return it->second.value + normalized_val * (nit->second.value - it->second.value);
|
||||
}
|
||||
|
||||
void SetUpChain(PlugboardGraph::NodeInstance& n) {
|
||||
n.extra = std::map<u32, ChainSegment>{};
|
||||
}
|
||||
|
||||
PlugboardGraph::Node Chain = {
|
||||
.name = "Chain",
|
||||
.in = { {"In", PlugboardGraph::T_Int } },
|
||||
.out = { { "Out", PlugboardGraph::T_Float } },
|
||||
.fetch = { FetchChain },
|
||||
.special_draw = nullptr,
|
||||
.extra_setup = SetUpChain
|
||||
};
|
||||
|
||||
auto Nodes = std::to_array<PlugboardGraph::Node*>({
|
||||
&Add,
|
||||
&Subtract,
|
||||
&Multiply,
|
||||
&Divide,
|
||||
&Negate,
|
||||
|
||||
&NaturalLogarithm,
|
||||
&SquareRoot,
|
||||
&Power,
|
||||
|
||||
&AbsoluteValue,
|
||||
&Sign,
|
||||
&Minimum,
|
||||
&Maximum,
|
||||
|
||||
&Sin,
|
||||
&Cos,
|
||||
&Tan,
|
||||
&Arcsin,
|
||||
&Arccos,
|
||||
&Arctan,
|
||||
&Atan2,
|
||||
|
||||
&Interpolation
|
||||
});
|
||||
extern std::array<PlugboardGraph::Node*, 20> Nodes;
|
||||
}
|
||||
|
|
|
@ -8,24 +8,12 @@
|
|||
#include "PlugboardGraph.h"
|
||||
|
||||
namespace K {
|
||||
/*
|
||||
template <typename T>
|
||||
struct Varying {
|
||||
static_assert(std::is_arithmetic<T>::value);
|
||||
u64 begin = 0, duration = 0;
|
||||
std::function<T(f64)> interp;
|
||||
|
||||
T get(u64 current_time) const {
|
||||
return interp(std::fmin(1.0f, std::fmax(0.0f, current_time - begin)) / static_cast<f64>(duration));
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
||||
struct Uniform {
|
||||
String name;
|
||||
bgfx::UniformHandle handle;
|
||||
ShaderGraph::T_Map<ShaderGraph::T_Count>::type val;
|
||||
PlugboardGraph::ConnectInfo connection;
|
||||
Vector<PlugboardGraph::ConnectInfo> show_nodes;
|
||||
};
|
||||
|
||||
struct Sampler {
|
||||
|
@ -45,7 +33,7 @@ namespace K {
|
|||
Vector<Uniform> uniforms;
|
||||
Vector<Sampler> samplers;
|
||||
void GetFrame(const CompState& s, u32 view_id, bgfx::FrameBufferHandle fb, u32 w, u32 h, f32 proj[16],
|
||||
f32 view[16], f32 transform[16]) const;
|
||||
f32 view[16], f32 transform[16]);
|
||||
static void ExposeUniform(CompState& s, Uniform& uu);
|
||||
void ExposeUniform(CompState& s, u32 i);
|
||||
static void HideUniform(CompState& s, Uniform& uu);
|
||||
|
|
24
TODO.md
24
TODO.md
|
@ -1,10 +1,14 @@
|
|||
# NOW
|
||||
## UI
|
||||
- Key selection in comp panel
|
||||
- Graph editor
|
||||
- Node loop detection (separate DFS (extra work) or be smart in recursion)
|
||||
- detect time-sensitive nodes in tree and display on timeline
|
||||
- Undo's
|
||||
- Once this is done we can move the plugboard loop detection/chain finding out of the eval loop
|
||||
- Keys
|
||||
- selection in comp panel
|
||||
- deletion
|
||||
- copy&paste
|
||||
- Graph editor
|
||||
- Node groups
|
||||
- Simple export
|
||||
|
||||
## Compositor
|
||||
- Video!
|
||||
|
@ -15,18 +19,18 @@
|
|||
- Data models
|
||||
- Dump and read back state, (de)serialization!!!
|
||||
- Pre-compose/Layer Groups (jokes -- can be completely UI side)
|
||||
- Resource
|
||||
- Deletion
|
||||
- Motion blur
|
||||
- Non-negotiable - Text (idea: index-based evaluation in plugboard)
|
||||
- Non-negotiable - Shapes (idea: embed glisp :mmtroll:, need to inquire -- still a lot of friction for simple shapes if we don't also get the glisp gizmos)
|
||||
- Non-negotiable - External data driving (csv, json or something else?) -- use a node to select source
|
||||
|
||||
## Chores
|
||||
- Node groups
|
||||
- Text (idea: index-based evaluation in plugboard)
|
||||
- Shapes (idea: embed glisp :mmtroll:, need to inquire -- still a lot of friction for simple shapes if we don't also get the glisp gizmos)
|
||||
- External data driving (csv, json or something else?) -- use a node to select source
|
||||
|
||||
# Later
|
||||
## IO
|
||||
- File dialogues pending SDL3
|
||||
- https://wiki.libsdl.org/SDL3/CategoryDialog
|
||||
- Clipboard pending SDL3
|
||||
- OIIO output for more than PNG's
|
||||
- don't care about video export -- leave it for ffmpeg
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue