diff --git a/Keishiki/Graphics.cpp b/Keishiki/Graphics.cpp index 4b5365f..ef5bed8 100644 --- a/Keishiki/Graphics.cpp +++ b/Keishiki/Graphics.cpp @@ -374,41 +374,4 @@ namespace K::Graphics { bgfx::setState(BGFX_STATE_WRITE_RGB | BGFX_STATE_WRITE_A); 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); - } - } diff --git a/Keishiki/PlugboardGraph.cpp b/Keishiki/PlugboardGraph.cpp index 0d494a9..bff2617 100644 --- a/Keishiki/PlugboardGraph.cpp +++ b/Keishiki/PlugboardGraph.cpp @@ -25,7 +25,7 @@ namespace K::PlugboardGraph { inputs_fed[input_index] = expand_type(node->in[input_index].type); } - String VarToString(const T_Map::type& var) { + constexpr String VarToString(const T_Map::type& var) { return std::visit([](auto&& arg) -> String { using T = std::decay_t; if constexpr (std::is_same_v::type>) diff --git a/Keishiki/PlugboardNodes.cpp b/Keishiki/PlugboardNodes.cpp index c5ca9a7..30f40c8 100644 --- a/Keishiki/PlugboardNodes.cpp +++ b/Keishiki/PlugboardNodes.cpp @@ -318,7 +318,7 @@ namespace K::PlugboardNodes { .fetch = { FetchAbsoluteValue } }; - f32 EvalInterpolation(f32 x, const InterpolationExtra& extra) { + constexpr f32 EvalInterpolation(f32 x, const InterpolationExtra& extra) { switch (extra.interp) { case K_I_InConstant: return 0.0f; @@ -459,24 +459,28 @@ namespace K::PlugboardNodes { PlugboardGraph::T_Map::type FetchChain(const CompState& s, const PlugboardGraph::NodeInstance& n, Vector *show_nodes) { u32 frame = GetNodeInputArg(s, n, 0, show_nodes); - auto *v = std::any_cast>(&n.extra); + auto *v = std::any_cast>(&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; + if (v->back().frame <= frame) + return v->back().value; + if (v->front().frame >= frame) + return v->front().value; - auto nit = v->upper_bound(frame), it = std::prev(nit); - u32 x1 = it->first, x2 = nit->first; + auto nit = std::upper_bound(v->cbegin(), v->cend(), frame, + [](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(frame - x1) / static_cast(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) { - n.extra = std::map{}; + n.extra = Vector{}; } PlugboardGraph::Node Chain = { diff --git a/Keishiki/Resource.cpp b/Keishiki/Resource.cpp index 55389fc..58b98b0 100644 --- a/Keishiki/Resource.cpp +++ b/Keishiki/Resource.cpp @@ -43,6 +43,7 @@ namespace K::Resource { res.format, BGFX_TEXTURE_NONE | BGFX_SAMPLER_UVW_CLAMP, ref); + res.filename = file.filename(); auto [it, check] = resources.emplace(file, res); return &std::get>(it->second); } @@ -66,6 +67,7 @@ namespace K::Resource { const auto frag = shader_path / (shader_name + ".frag.bin"), vert = shader_path / (shader_name + ".vert.bin"); auto [iter, check] = resources.emplace(shader_name, Resource{ + .name = shader_name, .frag_last_updated = std::filesystem::last_write_time(frag), .pg = bgfx::createProgram(LoadShader(vert), LoadShader(frag), true) }); diff --git a/Keishiki/UI.cpp b/Keishiki/UI.cpp index cfdb901..f23298f 100644 --- a/Keishiki/UI.cpp +++ b/Keishiki/UI.cpp @@ -344,7 +344,7 @@ namespace K::UI { view_count++; 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; 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(); } - 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(frame) / static_cast(frame_max + 1); 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(frame) / static_cast(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(std::round((view / view_width * view_amt + view_left) * static_cast(frame_max + 1))), 0UL, frame_max); } @@ -406,9 +406,8 @@ namespace K::UI { ImGui::End(); return; } - if (ImGui::Shortcut(ImGuiKey_Space)) { + if (ImGui::Shortcut(ImGuiKey_Space)) TogglePlay(); - } static u32 node_current{}; if (ImGui::Button("Add")) { @@ -450,22 +449,22 @@ namespace K::UI { ImGui::SameLine(); ImGui::BeginDisabled(no_selection); 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; u32 deleted = 0, before_active = 0; const u32 sz = s.layers.size(); 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.erase(s.layers.begin() + i - deleted); - s.disabled.erase(i); + std::erase(s.disabled, i); if (static_cast(i) < s.active) before_active++; deleted++; } - else if (s.disabled.contains(i)) { - s.disabled.erase(i); - s.disabled.insert(i - deleted); + else if (std::find(s.disabled.begin(), s.disabled.end(), i) != s.disabled.end()) { + std::erase(s.disabled, i); + s.disabled.push_back(i - deleted); } } s.selected.clear(); @@ -729,7 +728,8 @@ namespace K::UI { bool after{}; for (u32 i = 0; i < s.layers.size(); 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(i)); ImGui::TableNextRow(ImGuiTableRowFlags_None, row_height); @@ -740,7 +740,7 @@ namespace K::UI { static auto base_flags = ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_AllowOverlap | ImGuiTreeNodeFlags_FramePadding; auto flags = base_flags; - if (s.selected.contains(i)) + if (selected) flags |= ImGuiTreeNodeFlags_Selected; ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, {0.0f, (row_height - ImGui::GetTextLineHeight()) / 2.0f}); @@ -748,15 +748,15 @@ namespace K::UI { if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen()) { if (io.KeyCtrl) { if (selected) - s.selected.erase(i); + std::erase(s.selected, i); else - s.selected.insert(i); + s.selected.push_back(i); } else if (io.KeyShift) { // TODO } else { s.selected.clear(); if (!selected) - s.selected.insert(i); + s.selected.push_back(i); } s.active = selected ? -1 : static_cast(i); } @@ -764,12 +764,12 @@ namespace K::UI { auto source_flags = ImGuiDragDropFlags_SourceNoDisableHover | ImGuiDragDropFlags_SourceNoHoldToOpenOthers; 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()); ImGui::SetDragDropPayload("K_COMP_REORDER", &i, sizeof(u32)); ImGui::EndDragDropSource(); } - if ((no_selection || !s.selected.contains(i)) && ImGui::BeginDragDropTarget()) { + if ((no_selection || !selected) && ImGui::BeginDragDropTarget()) { if (!no_selection) { after = ImGui::GetMousePos().y - ImGui::GetWindowPos().y > ImGui::GetCursorPosY() - row_height / 2.0f; @@ -803,9 +803,9 @@ namespace K::UI { ImGui::Checkbox("##Enable", &cp); if (cp == disabled) { if (disabled) - s.disabled.erase(i); + std::erase(s.disabled, i); else - s.disabled.insert(i); + s.disabled.push_back(i); } // Timeline @@ -954,7 +954,7 @@ namespace K::UI { ImPlot::PushStyleColor(ImPlotCol_FrameBg, 0); ImPlot::PushStyleColor(ImPlotCol_PlotBg, 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_Y1, "val", ImPlotAxisFlags_NoDecorations | ImPlotAxisFlags_NoHighlight | ImPlotAxisFlags_AutoFit); 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_FramePadding); ImGui::TableSetColumnIndex(2); - auto *m = std::any_cast>( - &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(); + auto *m = std::any_cast>(&info.p->extra); + bool m_empty = m->empty(), m_has_before = !m_empty && m->begin()->frame >= s.current_frame; + + ImGui::BeginDisabled(m_empty || m_has_before); + if (ImGui::Button("<")) + s.current_frame = std::prev(std::upper_bound(m->begin(), m->end(), s.current_frame, + [](u32 a, const PlugboardNodes::ChainSegment& b) { return a < b.frame; }))->frame; ImGui::EndDisabled(); + + ImGui::SameLine(); + f32 v = std::get::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; + auto l = std::lower_bound(m->begin(), m->end(), s.current_frame, + [](const PlugboardNodes::ChainSegment& a, u32 b) { return a.frame < b; }); + if (l != m->end() && l->frame == s.current_frame) + l->value = v; + else + m->emplace(l, s.current_frame, v, PlugboardNodes::InterpolationExtra{ + m_has_before ? std::prev(l)->interp.interp : PlugboardNodes::K_I_Linear + }); } + + ImGui::SameLine(); + + 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::TableSetColumnIndex(3); ImGui::Text("%lu", m->size()); ImGui::TableSetColumnIndex(4); ImVec2 begin_tl = ImGui::GetCursorScreenPos(); - static std::map m_copy{}; + static Vector 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); - 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; + bool not_dragging = drag_m != m || drag_og == -1; + if (!not_dragging) + m->clear(); + auto key_loop_target = not_dragging ? m : &m_copy; + for (auto& [k, val, segment]: *key_loop_target) { + ImGui::PushID(k); + + if (!not_dragging && drag_og == k) + ImGui::SetCursorScreenPos( + {TimelineFrameToScreenView(view_left, view_amt, view_width, + dragging, + s.frame_max) + begin_tl.x - 2.5f, + 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}); - 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)) { - 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, - dragging, - 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()) { dragging = TimelineScreenViewToFrame(view_left, view_amt, view_width, - std::clamp(ImGui::GetMousePos().x - - tl_init_pos.x, 0.0f, - view_width), + std::clamp(io.MousePos.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); + if (ImGui::IsMouseReleased(ImGuiMouseButton_Left)) { drag_og = -1; 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); draw_tl_bg_drag_area(); @@ -1148,7 +1133,7 @@ namespace K::UI { s.selected.clear(); 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); } ImGui::SameLine(); - ImGui::SetNextItemWidth(-80.0f); ImGui::InputText("##SamplerName", &name, ImGuiInputTextFlags_CallbackCharFilter, TextFilters::VariableName); if (ImGui::BeginTable("Samplers", 3, ImGuiTableFlags_Borders)) { @@ -1267,7 +1251,7 @@ namespace K::UI { ImGui::TableNextColumn(); ImGui::TextUnformatted(it->name.c_str()); ImGui::TableNextColumn(); - ImGui::Text("mmoker"); + ImGui::Text("%s", it->resource->filename.c_str()); ImGui::TableNextColumn(); if (ImGui::Button("X")) { bgfx::destroy(it->handle); diff --git a/Keishiki/include/Graphics.h b/Keishiki/include/Graphics.h index 9a987e7..8284e8a 100644 --- a/Keishiki/include/Graphics.h +++ b/Keishiki/include/Graphics.h @@ -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]); - f64 GetCubicUniqueReal(f64 a, f64 b, f64 c, f64 d); - f64 CubicBezier(f64 a, f64 b, f64 c, f64 d, f64 t); - f64 InjectingCubicBezierFromX(f64 p2x, f64 p2y, f64 p3x, f64 p3y, f64 x); + constexpr static 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.; + } + } + + 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); + } } diff --git a/Keishiki/include/Keishiki.h b/Keishiki/include/Keishiki.h index 0851b72..d98bde0 100644 --- a/Keishiki/include/Keishiki.h +++ b/Keishiki/include/Keishiki.h @@ -1,7 +1,5 @@ #pragma once #include "Common.h" -#include -#include #include "PlugboardGraph.h" #include "VisualTrack.h" #include @@ -30,8 +28,8 @@ namespace K { Vector layers; i32 active = -1; // index for layers - std::set selected; // indices for layers - std::unordered_set disabled; // indices for layers + Vector selected; // indices for layers + Vector disabled; // indices for layers PlugboardGraph::PlugboardGraph plugboard; }; diff --git a/Keishiki/include/PlugboardGraph.h b/Keishiki/include/PlugboardGraph.h index bc71755..b37b57e 100644 --- a/Keishiki/include/PlugboardGraph.h +++ b/Keishiki/include/PlugboardGraph.h @@ -52,7 +52,7 @@ namespace K::PlugboardGraph { template<> struct T_Map { using type = std::variant; }; - String VarToString(const T_Map::type& var); + constexpr String VarToString(const T_Map::type& var); T_Map::type expand_type(Type i); @@ -80,8 +80,6 @@ namespace K::PlugboardGraph { void (*extra_setup)(NodeInstance&); }; - - struct ConnectInfoHasher { std::size_t operator()(const ConnectInfo& k) const { diff --git a/Keishiki/include/PlugboardNodes.h b/Keishiki/include/PlugboardNodes.h index 436f89b..e68ca90 100644 --- a/Keishiki/include/PlugboardNodes.h +++ b/Keishiki/include/PlugboardNodes.h @@ -105,6 +105,7 @@ namespace K::PlugboardNodes { extern PlugboardGraph::Node Interpolation; struct ChainSegment { + u32 frame; f32 value; InterpolationExtra interp; }; diff --git a/Keishiki/include/Resource.h b/Keishiki/include/Resource.h index 78981fc..1b5c700 100644 --- a/Keishiki/include/Resource.h +++ b/Keishiki/include/Resource.h @@ -23,11 +23,13 @@ namespace K::Resource { template struct Resource { + std::filesystem::path filename; std::filesystem::file_time_type last_updated; }; template<> struct Resource { + std::filesystem::path filename; std::filesystem::file_time_type last_updated; bgfx::TextureHandle tex; u8 *buf; @@ -37,6 +39,7 @@ namespace K::Resource { template<> struct Resource { + std::filesystem::path filename; std::filesystem::file_time_type last_updated; u32 frames; Vector tex; @@ -46,16 +49,18 @@ namespace K::Resource { template<> struct Resource { + std::filesystem::path filename; std::filesystem::file_time_type last_updated; u32 frames; Vector tex; u32 h, w; bgfx::TextureFormat::Enum format; - String scratch_dir; + std::filesystem::path scratch_dir; }; template<> struct Resource { + String name; std::filesystem::file_time_type frag_last_updated; bgfx::ProgramHandle pg; }; diff --git a/TODO.md b/TODO.md index 4484f60..541a193 100644 --- a/TODO.md +++ b/TODO.md @@ -5,7 +5,7 @@ - Keys - selection in comp panel - deletion - - copy&paste + - copy & paste - Graph editor - Node groups - Simple export