asdf
This commit is contained in:
parent
e51e684875
commit
a811f3287c
11 changed files with 153 additions and 165 deletions
|
@ -374,41 +374,4 @@ namespace K::Graphics {
|
||||||
bgfx::setState(BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A);
|
bgfx::setState(BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A);
|
||||||
bgfx::submit(view_id, composite_pg);
|
bgfx::submit(view_id, composite_pg);
|
||||||
}
|
}
|
||||||
|
|
||||||
f64 GetCubicUniqueReal(f64 a, f64 b, f64 c, f64 d) {
|
|
||||||
static constexpr auto accept = [](f64 t){ return 0.0 <= t && t <= 1.0; };
|
|
||||||
|
|
||||||
f64 a1 = b/a, a2 = c/a, a3 = d/a;
|
|
||||||
f64 Q = (a1 * a1 - 3.0 * a2) / 9.0,
|
|
||||||
R = (2.0 * a1 * a1 * a1 - 9.0 * a1 * a2 + 27.0 * a3) / 54.0,
|
|
||||||
Qcubed = Q * Q * Q,
|
|
||||||
D = Qcubed - R * R;
|
|
||||||
|
|
||||||
if (D >= 0) {
|
|
||||||
f64 theta = acos(R / sqrt(Qcubed));
|
|
||||||
f64 sqrtQ = sqrt(Q);
|
|
||||||
f64 r1 = -2.0 * sqrtQ * cos( theta / 3.0) - a1 / 3.0,
|
|
||||||
r2 = -2.0 * sqrtQ * cos((theta + 2.0 * std::numbers::pi) / 3.0) - a1 / 3.0,
|
|
||||||
r3 = -2.0 * sqrtQ * cos((theta + 4.0 * std::numbers::pi) / 3.0) - a1 / 3.0;
|
|
||||||
return accept(r1) ? r1 : (accept(r2) ? r2 : r3);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
f64 e = std::pow(std::sqrt(-D) + std::abs(R), 1.0 / 3.0);
|
|
||||||
if (R > 0.0)
|
|
||||||
e = -e;
|
|
||||||
return (e + Q / e) - a1 / 3.;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
f64 CubicBezier(f64 a, f64 b, f64 c, f64 d, f64 t) {
|
|
||||||
f64 t2 = t * t, t3 = t2 * t, mt = 1.0-t, mt2 = mt * mt, mt3 = mt2 * mt;
|
|
||||||
return a*mt3 + b*3.0*mt2*t + c*3.0*mt*t2 + d*t3;
|
|
||||||
}
|
|
||||||
f64 InjectingCubicBezierFromX(f64 p2x, f64 p2y, f64 p3x, f64 p3y, f64 x) {
|
|
||||||
f64 a = 0.0f, b = p2x,
|
|
||||||
c = p3x, d = 1.0;
|
|
||||||
|
|
||||||
f64 t = GetCubicUniqueReal(-a+3.0*b-3.0*c+d, 3.0*a-6.0*b+3.0*c, -3.0*a+3.0*b,a-x);
|
|
||||||
return CubicBezier(0.0, p2y, p3y, 1.0, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace K::PlugboardGraph {
|
||||||
inputs_fed[input_index] = expand_type(node->in[input_index].type);
|
inputs_fed[input_index] = expand_type(node->in[input_index].type);
|
||||||
}
|
}
|
||||||
|
|
||||||
String VarToString(const T_Map<T_Count>::type& var) {
|
constexpr String VarToString(const T_Map<T_Count>::type& var) {
|
||||||
return std::visit([](auto&& arg) -> String {
|
return std::visit([](auto&& arg) -> String {
|
||||||
using T = std::decay_t<decltype(arg)>;
|
using T = std::decay_t<decltype(arg)>;
|
||||||
if constexpr (std::is_same_v<T, T_Map<T_Float>::type>)
|
if constexpr (std::is_same_v<T, T_Map<T_Float>::type>)
|
||||||
|
|
|
@ -318,7 +318,7 @@ namespace K::PlugboardNodes {
|
||||||
.fetch = { FetchAbsoluteValue }
|
.fetch = { FetchAbsoluteValue }
|
||||||
};
|
};
|
||||||
|
|
||||||
f32 EvalInterpolation(f32 x, const InterpolationExtra& extra) {
|
constexpr f32 EvalInterpolation(f32 x, const InterpolationExtra& extra) {
|
||||||
switch (extra.interp) {
|
switch (extra.interp) {
|
||||||
case K_I_InConstant:
|
case K_I_InConstant:
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
@ -459,24 +459,28 @@ namespace K::PlugboardNodes {
|
||||||
PlugboardGraph::T_Map<PlugboardGraph::T_Count>::type FetchChain(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector<PlugboardGraph::ConnectInfo> *show_nodes) {
|
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);
|
u32 frame = GetNodeInputArg<PlugboardGraph::T_Int>(s, n, 0, show_nodes);
|
||||||
|
|
||||||
auto *v = std::any_cast<std::map<u32, ChainSegment>>(&n.extra);
|
auto *v = std::any_cast<Vector<ChainSegment>>(&n.extra);
|
||||||
if (v->empty())
|
if (v->empty())
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
if (frame <= v->begin()->first)
|
if (v->back().frame <= frame)
|
||||||
return v->begin()->second.value;
|
return v->back().value;
|
||||||
if (frame >= v->rbegin()->first)
|
if (v->front().frame >= frame)
|
||||||
return v->rbegin()->second.value;
|
return v->front().value;
|
||||||
|
|
||||||
auto nit = v->upper_bound(frame), it = std::prev(nit);
|
auto nit = std::upper_bound(v->cbegin(), v->cend(), frame,
|
||||||
u32 x1 = it->first, x2 = nit->first;
|
[](u32 a, const PlugboardNodes::ChainSegment& b) {
|
||||||
|
return a < b.frame;
|
||||||
|
}), it = std::prev(nit);
|
||||||
|
|
||||||
|
u32 x1 = it->frame, x2 = nit->frame;
|
||||||
f32 t = static_cast<f32>(frame - x1) / static_cast<f32>(x2 - x1);
|
f32 t = static_cast<f32>(frame - x1) / static_cast<f32>(x2 - x1);
|
||||||
f32 normalized_val = EvalInterpolation(t, it->second.interp);
|
f32 normalized_val = EvalInterpolation(t, it->interp);
|
||||||
|
|
||||||
return it->second.value + normalized_val * (nit->second.value - it->second.value);
|
return it->value + normalized_val * (nit->value - it->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetUpChain(PlugboardGraph::NodeInstance& n) {
|
void SetUpChain(PlugboardGraph::NodeInstance& n) {
|
||||||
n.extra = std::map<u32, ChainSegment>{};
|
n.extra = Vector<ChainSegment>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
PlugboardGraph::Node Chain = {
|
PlugboardGraph::Node Chain = {
|
||||||
|
|
|
@ -43,6 +43,7 @@ namespace K::Resource {
|
||||||
res.format,
|
res.format,
|
||||||
BGFX_TEXTURE_NONE | BGFX_SAMPLER_UVW_CLAMP,
|
BGFX_TEXTURE_NONE | BGFX_SAMPLER_UVW_CLAMP,
|
||||||
ref);
|
ref);
|
||||||
|
res.filename = file.filename();
|
||||||
auto [it, check] = resources.emplace(file, res);
|
auto [it, check] = resources.emplace(file, res);
|
||||||
return &std::get<Resource<K_R_Still>>(it->second);
|
return &std::get<Resource<K_R_Still>>(it->second);
|
||||||
}
|
}
|
||||||
|
@ -66,6 +67,7 @@ namespace K::Resource {
|
||||||
const auto frag = shader_path / (shader_name + ".frag.bin"),
|
const auto frag = shader_path / (shader_name + ".frag.bin"),
|
||||||
vert = shader_path / (shader_name + ".vert.bin");
|
vert = shader_path / (shader_name + ".vert.bin");
|
||||||
auto [iter, check] = resources.emplace(shader_name, Resource<K_R_ShaderProgram>{
|
auto [iter, check] = resources.emplace(shader_name, Resource<K_R_ShaderProgram>{
|
||||||
|
.name = shader_name,
|
||||||
.frag_last_updated = std::filesystem::last_write_time(frag),
|
.frag_last_updated = std::filesystem::last_write_time(frag),
|
||||||
.pg = bgfx::createProgram(LoadShader(vert), LoadShader(frag), true)
|
.pg = bgfx::createProgram(LoadShader(vert), LoadShader(frag), true)
|
||||||
});
|
});
|
||||||
|
|
178
Keishiki/UI.cpp
178
Keishiki/UI.cpp
|
@ -344,7 +344,7 @@ namespace K::UI {
|
||||||
view_count++;
|
view_count++;
|
||||||
|
|
||||||
for (u32 i = s.layers.size() - 1; i != u32(-1); i--) {
|
for (u32 i = s.layers.size() - 1; i != u32(-1); i--) {
|
||||||
if (s.disabled.contains(i)) continue;
|
if (std::find(s.disabled.begin(), s.disabled.end(), i) != s.disabled.end()) continue;
|
||||||
if (s.current_frame > s.layers[i].out || s.current_frame < s.layers[i].in) continue;
|
if (s.current_frame > s.layers[i].out || s.current_frame < s.layers[i].in) continue;
|
||||||
|
|
||||||
s.layers[i].track.GetFrame(s, Graphics::K_VIEW_COMP_COMPOSITE + view_count++, render_fb, s.width,
|
s.layers[i].track.GetFrame(s, Graphics::K_VIEW_COMP_COMPOSITE + view_count++, render_fb, s.width,
|
||||||
|
@ -388,16 +388,16 @@ namespace K::UI {
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool TimelineFrameInView(f32 view_left, f32 view_right, u64 frame, u64 frame_max) {
|
constexpr bool TimelineFrameInView(f32 view_left, f32 view_right, u64 frame, u64 frame_max) {
|
||||||
f32 p = static_cast<f32>(frame) / static_cast<f32>(frame_max + 1);
|
f32 p = static_cast<f32>(frame) / static_cast<f32>(frame_max + 1);
|
||||||
return p >= view_left && p < view_right;
|
return p >= view_left && p < view_right;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline f32 TimelineFrameToScreenView(f32 view_left, f32 view_amt, f32 view_width, u64 frame, u64 frame_max) {
|
constexpr f32 TimelineFrameToScreenView(f32 view_left, f32 view_amt, f32 view_width, u64 frame, u64 frame_max) {
|
||||||
return (static_cast<f32>(frame) / static_cast<f32>(frame_max + 1) - view_left) / view_amt * view_width;
|
return (static_cast<f32>(frame) / static_cast<f32>(frame_max + 1) - view_left) / view_amt * view_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline u64 TimelineScreenViewToFrame(f32 view_left, f32 view_amt, f32 view_width, f32 view, u64 frame_max) {
|
constexpr u64 TimelineScreenViewToFrame(f32 view_left, f32 view_amt, f32 view_width, f32 view, u64 frame_max) {
|
||||||
return std::clamp(static_cast<u64>(std::round((view / view_width * view_amt + view_left) * static_cast<f32>(frame_max + 1))), 0UL, frame_max);
|
return std::clamp(static_cast<u64>(std::round((view / view_width * view_amt + view_left) * static_cast<f32>(frame_max + 1))), 0UL, frame_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -406,9 +406,8 @@ namespace K::UI {
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ImGui::Shortcut(ImGuiKey_Space)) {
|
if (ImGui::Shortcut(ImGuiKey_Space))
|
||||||
TogglePlay();
|
TogglePlay();
|
||||||
}
|
|
||||||
|
|
||||||
static u32 node_current{};
|
static u32 node_current{};
|
||||||
if (ImGui::Button("Add")) {
|
if (ImGui::Button("Add")) {
|
||||||
|
@ -450,22 +449,22 @@ namespace K::UI {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::BeginDisabled(no_selection);
|
ImGui::BeginDisabled(no_selection);
|
||||||
if (ImGui::Button("Delete Layer")) { // todo unregister from plugboard beforehand
|
if (ImGui::Button("Delete Layer")) { // todo unregister from plugboard beforehand
|
||||||
if (s.selected.contains(s.active))
|
if (std::find(s.selected.begin(), s.selected.end(), s.active) != s.selected.end())
|
||||||
s.active = -1;
|
s.active = -1;
|
||||||
u32 deleted = 0, before_active = 0;
|
u32 deleted = 0, before_active = 0;
|
||||||
const u32 sz = s.layers.size();
|
const u32 sz = s.layers.size();
|
||||||
for (u32 i = 0; i < sz; i++) {
|
for (u32 i = 0; i < sz; i++) {
|
||||||
if (s.selected.contains(i)) {
|
if (std::find(s.selected.begin(), s.selected.end(), i) != s.selected.end()) {
|
||||||
s.layers[i - deleted].track.Clear();
|
s.layers[i - deleted].track.Clear();
|
||||||
s.layers.erase(s.layers.begin() + i - deleted);
|
s.layers.erase(s.layers.begin() + i - deleted);
|
||||||
s.disabled.erase(i);
|
std::erase(s.disabled, i);
|
||||||
if (static_cast<i32>(i) < s.active)
|
if (static_cast<i32>(i) < s.active)
|
||||||
before_active++;
|
before_active++;
|
||||||
deleted++;
|
deleted++;
|
||||||
}
|
}
|
||||||
else if (s.disabled.contains(i)) {
|
else if (std::find(s.disabled.begin(), s.disabled.end(), i) != s.disabled.end()) {
|
||||||
s.disabled.erase(i);
|
std::erase(s.disabled, i);
|
||||||
s.disabled.insert(i - deleted);
|
s.disabled.push_back(i - deleted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.selected.clear();
|
s.selected.clear();
|
||||||
|
@ -729,7 +728,8 @@ namespace K::UI {
|
||||||
bool after{};
|
bool after{};
|
||||||
for (u32 i = 0; i < s.layers.size(); i++) {
|
for (u32 i = 0; i < s.layers.size(); i++) {
|
||||||
auto& current_layer = s.layers[i];
|
auto& current_layer = s.layers[i];
|
||||||
const bool selected = s.selected.contains(i), disabled = s.disabled.contains(i);
|
const bool selected = std::find(s.selected.begin(), s.selected.end(), i) != s.selected.end(),
|
||||||
|
disabled = std::find(s.disabled.begin(), s.disabled.end(), i) != s.disabled.end();
|
||||||
ImGui::PushID(static_cast<i32>(i));
|
ImGui::PushID(static_cast<i32>(i));
|
||||||
ImGui::TableNextRow(ImGuiTableRowFlags_None, row_height);
|
ImGui::TableNextRow(ImGuiTableRowFlags_None, row_height);
|
||||||
|
|
||||||
|
@ -740,7 +740,7 @@ namespace K::UI {
|
||||||
static auto base_flags = ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_OpenOnArrow |
|
static auto base_flags = ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_OpenOnArrow |
|
||||||
ImGuiTreeNodeFlags_AllowOverlap | ImGuiTreeNodeFlags_FramePadding;
|
ImGuiTreeNodeFlags_AllowOverlap | ImGuiTreeNodeFlags_FramePadding;
|
||||||
auto flags = base_flags;
|
auto flags = base_flags;
|
||||||
if (s.selected.contains(i))
|
if (selected)
|
||||||
flags |= ImGuiTreeNodeFlags_Selected;
|
flags |= ImGuiTreeNodeFlags_Selected;
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,
|
||||||
{0.0f, (row_height - ImGui::GetTextLineHeight()) / 2.0f});
|
{0.0f, (row_height - ImGui::GetTextLineHeight()) / 2.0f});
|
||||||
|
@ -748,15 +748,15 @@ namespace K::UI {
|
||||||
if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen()) {
|
if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen()) {
|
||||||
if (io.KeyCtrl) {
|
if (io.KeyCtrl) {
|
||||||
if (selected)
|
if (selected)
|
||||||
s.selected.erase(i);
|
std::erase(s.selected, i);
|
||||||
else
|
else
|
||||||
s.selected.insert(i);
|
s.selected.push_back(i);
|
||||||
} else if (io.KeyShift) {
|
} else if (io.KeyShift) {
|
||||||
// TODO
|
// TODO
|
||||||
} else {
|
} else {
|
||||||
s.selected.clear();
|
s.selected.clear();
|
||||||
if (!selected)
|
if (!selected)
|
||||||
s.selected.insert(i);
|
s.selected.push_back(i);
|
||||||
}
|
}
|
||||||
s.active = selected ? -1 : static_cast<i32>(i);
|
s.active = selected ? -1 : static_cast<i32>(i);
|
||||||
}
|
}
|
||||||
|
@ -764,12 +764,12 @@ namespace K::UI {
|
||||||
auto source_flags =
|
auto source_flags =
|
||||||
ImGuiDragDropFlags_SourceNoDisableHover | ImGuiDragDropFlags_SourceNoHoldToOpenOthers;
|
ImGuiDragDropFlags_SourceNoDisableHover | ImGuiDragDropFlags_SourceNoHoldToOpenOthers;
|
||||||
if (!no_selection) source_flags |= ImGuiDragDropFlags_SourceNoPreviewTooltip;
|
if (!no_selection) source_flags |= ImGuiDragDropFlags_SourceNoPreviewTooltip;
|
||||||
if ((no_selection || s.selected.contains(i)) && ImGui::BeginDragDropSource(source_flags)) {
|
if ((no_selection || selected) && ImGui::BeginDragDropSource(source_flags)) {
|
||||||
if (s.selected.empty()) ImGui::Text("Swap with #%u %s", i, current_layer.name.c_str());
|
if (s.selected.empty()) ImGui::Text("Swap with #%u %s", i, current_layer.name.c_str());
|
||||||
ImGui::SetDragDropPayload("K_COMP_REORDER", &i, sizeof(u32));
|
ImGui::SetDragDropPayload("K_COMP_REORDER", &i, sizeof(u32));
|
||||||
ImGui::EndDragDropSource();
|
ImGui::EndDragDropSource();
|
||||||
}
|
}
|
||||||
if ((no_selection || !s.selected.contains(i)) && ImGui::BeginDragDropTarget()) {
|
if ((no_selection || !selected) && ImGui::BeginDragDropTarget()) {
|
||||||
if (!no_selection) {
|
if (!no_selection) {
|
||||||
after = ImGui::GetMousePos().y - ImGui::GetWindowPos().y >
|
after = ImGui::GetMousePos().y - ImGui::GetWindowPos().y >
|
||||||
ImGui::GetCursorPosY() - row_height / 2.0f;
|
ImGui::GetCursorPosY() - row_height / 2.0f;
|
||||||
|
@ -803,9 +803,9 @@ namespace K::UI {
|
||||||
ImGui::Checkbox("##Enable", &cp);
|
ImGui::Checkbox("##Enable", &cp);
|
||||||
if (cp == disabled) {
|
if (cp == disabled) {
|
||||||
if (disabled)
|
if (disabled)
|
||||||
s.disabled.erase(i);
|
std::erase(s.disabled, i);
|
||||||
else
|
else
|
||||||
s.disabled.insert(i);
|
s.disabled.push_back(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timeline
|
// Timeline
|
||||||
|
@ -954,7 +954,7 @@ namespace K::UI {
|
||||||
ImPlot::PushStyleColor(ImPlotCol_FrameBg, 0);
|
ImPlot::PushStyleColor(ImPlotCol_FrameBg, 0);
|
||||||
ImPlot::PushStyleColor(ImPlotCol_PlotBg, 0);
|
ImPlot::PushStyleColor(ImPlotCol_PlotBg, 0);
|
||||||
ImPlot::PushStyleColor(ImPlotCol_PlotBorder, 0);
|
ImPlot::PushStyleColor(ImPlotCol_PlotBorder, 0);
|
||||||
if (connected_v.index() == 1 && ImPlot::BeginPlot("uniform", {view_width, row_height * 2.0f}, ImPlotFlags_CanvasOnly | ImPlotFlags_NoFrame | ImPlotFlags_NoInputs)) {
|
if (connected_v.index() == 1 && ImPlot::BeginPlot("uniform", {view_width, row_height}, ImPlotFlags_CanvasOnly | ImPlotFlags_NoFrame | ImPlotFlags_NoInputs)) {
|
||||||
ImPlot::SetupAxis(ImAxis_X1, "time", ImPlotAxisFlags_NoDecorations | ImPlotAxisFlags_NoHighlight);
|
ImPlot::SetupAxis(ImAxis_X1, "time", ImPlotAxisFlags_NoDecorations | ImPlotAxisFlags_NoHighlight);
|
||||||
ImPlot::SetupAxis(ImAxis_Y1, "val", ImPlotAxisFlags_NoDecorations | ImPlotAxisFlags_NoHighlight | ImPlotAxisFlags_AutoFit);
|
ImPlot::SetupAxis(ImAxis_Y1, "val", ImPlotAxisFlags_NoDecorations | ImPlotAxisFlags_NoHighlight | ImPlotAxisFlags_AutoFit);
|
||||||
struct PlotInfo { f32 begin, end; i32 samples; const CompState &s; PlugboardGraph::ConnectInfo &connected_v; };
|
struct PlotInfo { f32 begin, end; i32 samples; const CompState &s; PlugboardGraph::ConnectInfo &connected_v; };
|
||||||
|
@ -996,114 +996,99 @@ namespace K::UI {
|
||||||
ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Leaf |
|
ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Leaf |
|
||||||
ImGuiTreeNodeFlags_FramePadding);
|
ImGuiTreeNodeFlags_FramePadding);
|
||||||
ImGui::TableSetColumnIndex(2);
|
ImGui::TableSetColumnIndex(2);
|
||||||
auto *m = std::any_cast<std::map<u32, PlugboardNodes::ChainSegment>>(
|
auto *m = std::any_cast<Vector<PlugboardNodes::ChainSegment>>(&info.p->extra);
|
||||||
&info.p->extra);
|
bool m_empty = m->empty(), m_has_before = !m_empty && m->begin()->frame >= s.current_frame;
|
||||||
bool m_empty = m->empty();
|
|
||||||
ImGui::BeginDisabled(m_empty || m->begin()->first >= s.current_frame);
|
ImGui::BeginDisabled(m_empty || m_has_before);
|
||||||
if (ImGui::Button("<")) {
|
if (ImGui::Button("<"))
|
||||||
auto it = std::prev(m->upper_bound(s.current_frame));
|
s.current_frame = std::prev(std::upper_bound(m->begin(), m->end(), s.current_frame,
|
||||||
s.current_frame = (it->first == s.current_frame ? std::prev(it) : it)->first;
|
[](u32 a, const PlugboardNodes::ChainSegment& b) { return a < b.frame; }))->frame;
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
f32 v = std::get<PlugboardGraph::T_Map<PlugboardGraph::T_Float>::type>(
|
f32 v = std::get<PlugboardGraph::T_Map<PlugboardGraph::T_Float>::type>(
|
||||||
PlugboardGraph::Eval(s, info)), copy = v;
|
PlugboardGraph::Eval(s, info)), copy = v;
|
||||||
ImGui::DragFloat("##value", &v);
|
ImGui::DragFloat("##value", &v);
|
||||||
ImGui::SameLine();
|
|
||||||
if (v != copy) {
|
if (v != copy) {
|
||||||
auto l = m->lower_bound(s.current_frame);
|
auto l = std::lower_bound(m->begin(), m->end(), s.current_frame,
|
||||||
auto interp = l == m->end() ? PlugboardNodes::K_I_Linear : l->second.interp.interp;
|
[](const PlugboardNodes::ChainSegment& a, u32 b) { return a.frame < b; });
|
||||||
m->insert_or_assign(s.current_frame, PlugboardNodes::ChainSegment{
|
if (l != m->end() && l->frame == s.current_frame)
|
||||||
.value = v,
|
l->value = v;
|
||||||
.interp = {
|
else
|
||||||
.interp = interp
|
m->emplace(l, s.current_frame, v, PlugboardNodes::InterpolationExtra{
|
||||||
}
|
m_has_before ? std::prev(l)->interp.interp : PlugboardNodes::K_I_Linear
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ImGui::BeginDisabled(m_empty || m->rbegin()->first <= s.current_frame);
|
|
||||||
if (ImGui::Button(">")) {
|
ImGui::SameLine();
|
||||||
s.current_frame = m->upper_bound(s.current_frame)->first;
|
|
||||||
}
|
ImGui::BeginDisabled(m_empty || m->back().frame <= s.current_frame);
|
||||||
|
if (ImGui::Button(">"))
|
||||||
|
s.current_frame = std::upper_bound(m->begin(), m->end(), s.current_frame,
|
||||||
|
[](u32 a, const PlugboardNodes::ChainSegment& b) { return a < b.frame; })->frame;
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(3);
|
ImGui::TableSetColumnIndex(3);
|
||||||
ImGui::Text("%lu", m->size());
|
ImGui::Text("%lu", m->size());
|
||||||
ImGui::TableSetColumnIndex(4);
|
ImGui::TableSetColumnIndex(4);
|
||||||
ImVec2 begin_tl = ImGui::GetCursorScreenPos();
|
ImVec2 begin_tl = ImGui::GetCursorScreenPos();
|
||||||
|
|
||||||
static std::map<u32, PlugboardNodes::ChainSegment> m_copy{};
|
static Vector<PlugboardNodes::ChainSegment> m_copy{};
|
||||||
static u32 dragging{};
|
static u32 dragging{};
|
||||||
static decltype(m) drag_m = nullptr;
|
static decltype(m) drag_m = nullptr;
|
||||||
static i64 drag_og = -1;
|
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);
|
|
||||||
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(
|
bool not_dragging = drag_m != m || drag_og == -1;
|
||||||
{TimelineFrameToScreenView(view_left, view_amt, view_width, k,
|
if (!not_dragging)
|
||||||
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();
|
m->clear();
|
||||||
for (auto &[k, segment]: m_copy) {
|
auto key_loop_target = not_dragging ? m : &m_copy;
|
||||||
|
for (auto& [k, val, segment]: *key_loop_target) {
|
||||||
ImGui::PushID(k);
|
ImGui::PushID(k);
|
||||||
if (drag_og != k) {
|
|
||||||
if (TimelineFrameInView(view_left, view_right, k, s.frame_max)) {
|
if (!not_dragging && drag_og == k)
|
||||||
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(
|
ImGui::SetCursorScreenPos(
|
||||||
{TimelineFrameToScreenView(view_left, view_amt, view_width,
|
{TimelineFrameToScreenView(view_left, view_amt, view_width,
|
||||||
dragging,
|
dragging,
|
||||||
s.frame_max) + begin_tl.x - 2.5f,
|
s.frame_max) + begin_tl.x - 2.5f,
|
||||||
begin_tl.y});
|
begin_tl.y});
|
||||||
|
else
|
||||||
|
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});
|
ImGui::Button("k", {0.0f, row_height * .8f});
|
||||||
|
if (!not_dragging) {
|
||||||
|
if (drag_og == k) {
|
||||||
|
m->emplace(std::lower_bound(m->begin(), m->end(), dragging,
|
||||||
|
[](const PlugboardNodes::ChainSegment& a, u32 b) {
|
||||||
|
return a.frame < b;
|
||||||
|
}), dragging, val, segment);
|
||||||
if (ImGui::IsItemActive()) {
|
if (ImGui::IsItemActive()) {
|
||||||
dragging = TimelineScreenViewToFrame(view_left, view_amt, view_width,
|
dragging = TimelineScreenViewToFrame(view_left, view_amt, view_width,
|
||||||
std::clamp(ImGui::GetMousePos().x -
|
std::clamp(io.MousePos.x -
|
||||||
tl_init_pos.x, 0.0f,
|
tl_init_pos.x, 0.0f,
|
||||||
view_width),
|
view_width),
|
||||||
s.frame_max);
|
s.frame_max);
|
||||||
m->emplace(dragging, segment);
|
|
||||||
}
|
}
|
||||||
if (drag_og == k && ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
|
if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) {
|
||||||
m->emplace(dragging, segment);
|
|
||||||
drag_og = -1;
|
drag_og = -1;
|
||||||
drag_m = nullptr;
|
drag_m = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::PopID();
|
else
|
||||||
|
m->emplace(std::lower_bound(m->begin(), m->end(), k,
|
||||||
|
[](const PlugboardNodes::ChainSegment& a, u32 b) {
|
||||||
|
return a.frame < b;
|
||||||
|
}), k, val, segment);
|
||||||
}
|
}
|
||||||
|
else if (ImGui::IsItemClicked()) {
|
||||||
|
m_copy = *m;
|
||||||
|
drag_og = k;
|
||||||
|
drag_m = m;
|
||||||
|
}
|
||||||
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
ImGui::SetCursorScreenPos(begin_tl);
|
ImGui::SetCursorScreenPos(begin_tl);
|
||||||
draw_tl_bg_drag_area();
|
draw_tl_bg_drag_area();
|
||||||
|
@ -1148,7 +1133,7 @@ namespace K::UI {
|
||||||
|
|
||||||
s.selected.clear();
|
s.selected.clear();
|
||||||
for (u32 j = 0; j < n; j++)
|
for (u32 j = 0; j < n; j++)
|
||||||
s.selected.insert(target - popped_before_target + j);
|
s.selected.push_back(target - popped_before_target + j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1252,7 +1237,6 @@ namespace K::UI {
|
||||||
s.layers[s.active].track.AddSampler(name);
|
s.layers[s.active].track.AddSampler(name);
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetNextItemWidth(-80.0f);
|
|
||||||
ImGui::InputText("##SamplerName", &name, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::VariableName);
|
ImGui::InputText("##SamplerName", &name, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::VariableName);
|
||||||
|
|
||||||
if (ImGui::BeginTable("Samplers", 3, ImGuiTableFlags_Borders)) {
|
if (ImGui::BeginTable("Samplers", 3, ImGuiTableFlags_Borders)) {
|
||||||
|
@ -1267,7 +1251,7 @@ namespace K::UI {
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::TextUnformatted(it->name.c_str());
|
ImGui::TextUnformatted(it->name.c_str());
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
ImGui::Text("mmoker");
|
ImGui::Text("%s", it->resource->filename.c_str());
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
if (ImGui::Button("X")) {
|
if (ImGui::Button("X")) {
|
||||||
bgfx::destroy(it->handle);
|
bgfx::destroy(it->handle);
|
||||||
|
|
|
@ -117,7 +117,40 @@ namespace K::Graphics {
|
||||||
|
|
||||||
void Composite(u32 view_id, bgfx::FrameBufferHandle fb, bgfx::TextureHandle composite, bgfx::TextureHandle from, Blending mode, u16 w, u16 h, f32 proj[16], f32 transform[16]);
|
void Composite(u32 view_id, bgfx::FrameBufferHandle fb, bgfx::TextureHandle composite, bgfx::TextureHandle from, Blending mode, u16 w, u16 h, f32 proj[16], f32 transform[16]);
|
||||||
|
|
||||||
f64 GetCubicUniqueReal(f64 a, f64 b, f64 c, f64 d);
|
constexpr static f64 GetCubicUniqueReal(f64 a, f64 b, f64 c, f64 d) {
|
||||||
f64 CubicBezier(f64 a, f64 b, f64 c, f64 d, f64 t);
|
static constexpr auto accept = [](f64 t){ return 0.0 <= t && t <= 1.0; };
|
||||||
f64 InjectingCubicBezierFromX(f64 p2x, f64 p2y, f64 p3x, f64 p3y, f64 x);
|
f64 a1 = b/a, a2 = c/a, a3 = d/a;
|
||||||
|
f64 Q = (a1 * a1 - 3.0 * a2) / 9.0,
|
||||||
|
R = (2.0 * a1 * a1 * a1 - 9.0 * a1 * a2 + 27.0 * a3) / 54.0,
|
||||||
|
Qcubed = Q * Q * Q,
|
||||||
|
D = Qcubed - R * R;
|
||||||
|
|
||||||
|
if (D >= 0) {
|
||||||
|
f64 theta = acos(R / sqrt(Qcubed));
|
||||||
|
f64 sqrtQ = sqrt(Q);
|
||||||
|
f64 r1 = -2.0 * sqrtQ * cos( theta / 3.0) - a1 / 3.0,
|
||||||
|
r2 = -2.0 * sqrtQ * cos((theta + 2.0 * std::numbers::pi) / 3.0) - a1 / 3.0,
|
||||||
|
r3 = -2.0 * sqrtQ * cos((theta + 4.0 * std::numbers::pi) / 3.0) - a1 / 3.0;
|
||||||
|
return accept(r1) ? r1 : (accept(r2) ? r2 : r3);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
f64 e = std::pow(std::sqrt(-D) + std::abs(R), 1.0 / 3.0);
|
||||||
|
if (R > 0.0)
|
||||||
|
e = -e;
|
||||||
|
return (e + Q / e) - a1 / 3.;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr static f64 CubicBezier(f64 a, f64 b, f64 c, f64 d, f64 t) {
|
||||||
|
f64 t2 = t * t, t3 = t2 * t, mt = 1.0-t, mt2 = mt * mt, mt3 = mt2 * mt;
|
||||||
|
return a*mt3 + b*3.0*mt2*t + c*3.0*mt*t2 + d*t3;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr static f64 InjectingCubicBezierFromX(f64 p2x, f64 p2y, f64 p3x, f64 p3y, f64 x) {
|
||||||
|
f64 a = 0.0f, b = p2x,
|
||||||
|
c = p3x, d = 1.0;
|
||||||
|
|
||||||
|
f64 t = GetCubicUniqueReal(-a+3.0*b-3.0*c+d, 3.0*a-6.0*b+3.0*c, -3.0*a+3.0*b,a-x);
|
||||||
|
return CubicBezier(0.0, p2y, p3y, 1.0, t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include <set>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include "PlugboardGraph.h"
|
#include "PlugboardGraph.h"
|
||||||
#include "VisualTrack.h"
|
#include "VisualTrack.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
@ -30,8 +28,8 @@ namespace K {
|
||||||
|
|
||||||
Vector<Layer> layers;
|
Vector<Layer> layers;
|
||||||
i32 active = -1; // index for layers
|
i32 active = -1; // index for layers
|
||||||
std::set<u32> selected; // indices for layers
|
Vector<u32> selected; // indices for layers
|
||||||
std::unordered_set<u32> disabled; // indices for layers
|
Vector<u32> disabled; // indices for layers
|
||||||
|
|
||||||
PlugboardGraph::PlugboardGraph plugboard;
|
PlugboardGraph::PlugboardGraph plugboard;
|
||||||
};
|
};
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace K::PlugboardGraph {
|
||||||
template<> struct T_Map<T_Count> {
|
template<> struct T_Map<T_Count> {
|
||||||
using type = std::variant<f32, i32, RGBA, XY, XYZ, String>;
|
using type = std::variant<f32, i32, RGBA, XY, XYZ, String>;
|
||||||
};
|
};
|
||||||
String VarToString(const T_Map<T_Count>::type& var);
|
constexpr String VarToString(const T_Map<T_Count>::type& var);
|
||||||
|
|
||||||
T_Map<T_Count>::type expand_type(Type i);
|
T_Map<T_Count>::type expand_type(Type i);
|
||||||
|
|
||||||
|
@ -80,8 +80,6 @@ namespace K::PlugboardGraph {
|
||||||
void (*extra_setup)(NodeInstance&);
|
void (*extra_setup)(NodeInstance&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct ConnectInfoHasher {
|
struct ConnectInfoHasher {
|
||||||
std::size_t operator()(const ConnectInfo& k) const
|
std::size_t operator()(const ConnectInfo& k) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -105,6 +105,7 @@ namespace K::PlugboardNodes {
|
||||||
extern PlugboardGraph::Node Interpolation;
|
extern PlugboardGraph::Node Interpolation;
|
||||||
|
|
||||||
struct ChainSegment {
|
struct ChainSegment {
|
||||||
|
u32 frame;
|
||||||
f32 value;
|
f32 value;
|
||||||
InterpolationExtra interp;
|
InterpolationExtra interp;
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,11 +23,13 @@ namespace K::Resource {
|
||||||
|
|
||||||
template <Type T>
|
template <Type T>
|
||||||
struct Resource {
|
struct Resource {
|
||||||
|
std::filesystem::path filename;
|
||||||
std::filesystem::file_time_type last_updated;
|
std::filesystem::file_time_type last_updated;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Resource<K_R_Still> {
|
struct Resource<K_R_Still> {
|
||||||
|
std::filesystem::path filename;
|
||||||
std::filesystem::file_time_type last_updated;
|
std::filesystem::file_time_type last_updated;
|
||||||
bgfx::TextureHandle tex;
|
bgfx::TextureHandle tex;
|
||||||
u8 *buf;
|
u8 *buf;
|
||||||
|
@ -37,6 +39,7 @@ namespace K::Resource {
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Resource<K_R_StillSequence> {
|
struct Resource<K_R_StillSequence> {
|
||||||
|
std::filesystem::path filename;
|
||||||
std::filesystem::file_time_type last_updated;
|
std::filesystem::file_time_type last_updated;
|
||||||
u32 frames;
|
u32 frames;
|
||||||
Vector<bgfx::TextureHandle> tex;
|
Vector<bgfx::TextureHandle> tex;
|
||||||
|
@ -46,16 +49,18 @@ namespace K::Resource {
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Resource<K_R_VideoAudio> {
|
struct Resource<K_R_VideoAudio> {
|
||||||
|
std::filesystem::path filename;
|
||||||
std::filesystem::file_time_type last_updated;
|
std::filesystem::file_time_type last_updated;
|
||||||
u32 frames;
|
u32 frames;
|
||||||
Vector<bgfx::TextureHandle> tex;
|
Vector<bgfx::TextureHandle> tex;
|
||||||
u32 h, w;
|
u32 h, w;
|
||||||
bgfx::TextureFormat::Enum format;
|
bgfx::TextureFormat::Enum format;
|
||||||
String scratch_dir;
|
std::filesystem::path scratch_dir;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct Resource<K_R_ShaderProgram> {
|
struct Resource<K_R_ShaderProgram> {
|
||||||
|
String name;
|
||||||
std::filesystem::file_time_type frag_last_updated;
|
std::filesystem::file_time_type frag_last_updated;
|
||||||
bgfx::ProgramHandle pg;
|
bgfx::ProgramHandle pg;
|
||||||
};
|
};
|
||||||
|
|
2
TODO.md
2
TODO.md
|
@ -5,7 +5,7 @@
|
||||||
- Keys
|
- Keys
|
||||||
- selection in comp panel
|
- selection in comp panel
|
||||||
- deletion
|
- deletion
|
||||||
- copy&paste
|
- copy & paste
|
||||||
- Graph editor
|
- Graph editor
|
||||||
- Node groups
|
- Node groups
|
||||||
- Simple export
|
- Simple export
|
||||||
|
|
Loading…
Add table
Reference in a new issue