d
This commit is contained in:
parent
035f031195
commit
d639ee8b9b
4 changed files with 335 additions and 223 deletions
|
@ -319,109 +319,6 @@ namespace K::PlugboardNodes {
|
||||||
.fetch = { FetchAbsoluteValue }
|
.fetch = { FetchAbsoluteValue }
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr 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) {
|
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);
|
auto *e = std::any_cast<InterpolationExtra>(&n.extra);
|
||||||
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes);
|
f32 x = GetNodeInputArg<PlugboardGraph::T_Float>(s, n, 0, show_nodes);
|
||||||
|
|
346
Keishiki/UI.cpp
346
Keishiki/UI.cpp
|
@ -253,7 +253,7 @@ namespace K::UI {
|
||||||
ImGui::TextUnformatted(n.node->in[in].name.c_str());
|
ImGui::TextUnformatted(n.node->in[in].name.c_str());
|
||||||
|
|
||||||
// Update link info
|
// Update link info
|
||||||
std::visit([&socket_link_pos, &dragging_on_socket, &source, &link_pos, &style](auto&& arg) {
|
std::visit([&socket_link_pos, &dragging_on_socket, &source, &link_pos](auto&& arg) {
|
||||||
using T = std::decay_t<decltype(arg)>;
|
using T = std::decay_t<decltype(arg)>;
|
||||||
if constexpr (std::is_same_v<T, PlugboardGraph::ConnectInfo>) {
|
if constexpr (std::is_same_v<T, PlugboardGraph::ConnectInfo>) {
|
||||||
if (ImGui::IsItemActive())
|
if (ImGui::IsItemActive())
|
||||||
|
@ -408,6 +408,8 @@ namespace K::UI {
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
static bool show_curve_editor = false;
|
||||||
|
|
||||||
if (ImGui::Shortcut(ImGuiKey_Space))
|
if (ImGui::Shortcut(ImGuiKey_Space))
|
||||||
TogglePlay();
|
TogglePlay();
|
||||||
|
|
||||||
|
@ -446,7 +448,7 @@ namespace K::UI {
|
||||||
AddTransformLayer(s, name);
|
AddTransformLayer(s, name);
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetNextItemWidth(-100.0f);
|
ImGui::SetNextItemWidth(250.0f);
|
||||||
ImGui::InputText("##LayerName", &name);
|
ImGui::InputText("##LayerName", &name);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::BeginDisabled(no_selection);
|
ImGui::BeginDisabled(no_selection);
|
||||||
|
@ -474,6 +476,10 @@ namespace K::UI {
|
||||||
}
|
}
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::Checkbox("Chain Editor", &show_curve_editor);
|
||||||
|
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
ImGuiStyle style = ImGui::GetStyle();
|
ImGuiStyle style = ImGui::GetStyle();
|
||||||
ImVec2 avail = ImGui::GetContentRegionAvail();
|
ImVec2 avail = ImGui::GetContentRegionAvail();
|
||||||
|
@ -553,13 +559,19 @@ namespace K::UI {
|
||||||
view_left_old = view_left,
|
view_left_old = view_left,
|
||||||
view_right = 1.0f,
|
view_right = 1.0f,
|
||||||
view_right_old = view_right;
|
view_right_old = view_right;
|
||||||
f32 view_amt, mouse_tl_x;
|
f32 view_amt = view_right - view_left, mouse_tl_x;
|
||||||
|
f32 fr_step;
|
||||||
|
|
||||||
// Mouse Handlers
|
// Mouse Handlers
|
||||||
// Drag playhead/pan
|
// Drag playhead/pan
|
||||||
|
static bool tl_clear_selection_request = false;
|
||||||
|
bool tl_clear_selection_request_this_frame = tl_clear_selection_request;
|
||||||
auto draw_tl_bg_drag_area = [&view_width, &style, &view_amt, &s, &mouse_tl_x](f32 h = 0.0f) {
|
auto draw_tl_bg_drag_area = [&view_width, &style, &view_amt, &s, &mouse_tl_x](f32 h = 0.0f) {
|
||||||
static f32 pan_x, view_left_old, view_right_old;
|
static f32 pan_x, view_left_old, view_right_old;
|
||||||
ImGui::InvisibleButton("##TL_BG", ImVec2{ view_width + style.CellPadding.x * 2, h == 0.0f ? row_height + style.CellPadding.y : h});
|
ImGui::InvisibleButton("##TL_BG", ImVec2{ view_width + style.CellPadding.x * 2, h == 0.0f ? row_height + style.CellPadding.y : h});
|
||||||
|
if (ImGui::IsItemClicked()) {
|
||||||
|
tl_clear_selection_request = true;
|
||||||
|
}
|
||||||
if (ImGui::IsItemActive()) {
|
if (ImGui::IsItemActive()) {
|
||||||
s.current_frame = TimelineScreenViewToFrame(view_left, view_amt, view_width, std::clamp(mouse_tl_x, 0.0f, view_width), s.frame_max);
|
s.current_frame = TimelineScreenViewToFrame(view_left, view_amt, view_width, std::clamp(mouse_tl_x, 0.0f, view_width), s.frame_max);
|
||||||
}
|
}
|
||||||
|
@ -602,6 +614,7 @@ namespace K::UI {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr static f32 knob_width = 8.0f;
|
||||||
if (ImGui::BeginTable("Layers", 5, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY)) {
|
if (ImGui::BeginTable("Layers", 5, ImGuiTableFlags_BordersInner | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY)) {
|
||||||
ImGui::TableSetupScrollFreeze(0, 1); // Make top row always visible
|
ImGui::TableSetupScrollFreeze(0, 1); // Make top row always visible
|
||||||
ImGui::TableSetupColumn("#", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_IndentDisable);
|
ImGui::TableSetupColumn("#", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_IndentDisable);
|
||||||
|
@ -626,15 +639,14 @@ namespace K::UI {
|
||||||
ImGui::TableSetColumnIndex(4);
|
ImGui::TableSetColumnIndex(4);
|
||||||
|
|
||||||
auto *window = ImGui::GetCurrentWindow();
|
auto *window = ImGui::GetCurrentWindow();
|
||||||
const static f32 knob_width = 8.0f;
|
|
||||||
tl_init_pos = ImGui::GetCursorScreenPos();
|
tl_init_pos = ImGui::GetCursorScreenPos();
|
||||||
view_width = ImGui::GetColumnWidth() - 10.0f,
|
view_width = ImGui::GetColumnWidth() - 10.0f,
|
||||||
tl_width = view_width - knob_width,
|
tl_width = view_width - knob_width,
|
||||||
view_height = ImGui::TableGetHeaderRowHeight(),
|
view_height = ImGui::TableGetHeaderRowHeight(),
|
||||||
control_left = tl_init_pos.x,
|
control_left = tl_init_pos.x,
|
||||||
control_right = tl_init_pos.x + view_width;
|
control_right = tl_init_pos.x + view_width;
|
||||||
view_amt = view_right - view_left;
|
|
||||||
mouse_tl_x = io.MousePos.x - tl_init_pos.x;
|
mouse_tl_x = io.MousePos.x - tl_init_pos.x;
|
||||||
|
fr_step = 1.0f / static_cast<f32>(s.frame_max + 1) * view_width / view_amt;
|
||||||
|
|
||||||
ImGui::SetCursorScreenPos({tl_init_pos.x - knob_width / 2.0f + view_width * view_left, tl_init_pos.y});
|
ImGui::SetCursorScreenPos({tl_init_pos.x - knob_width / 2.0f + view_width * view_left, tl_init_pos.y});
|
||||||
ImGui::InvisibleButton("##TL_L", ImVec2{knob_width, view_height});
|
ImGui::InvisibleButton("##TL_L", ImVec2{knob_width, view_height});
|
||||||
|
@ -645,7 +657,7 @@ namespace K::UI {
|
||||||
view_left_old = view_left;
|
view_left_old = view_left;
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemActive()) {
|
if (ImGui::IsItemActive()) {
|
||||||
view_left = std::clamp(view_left_old + ImGui::GetMouseDragDelta().x / tl_width * view_amt, 0.0f, view_right - 2.0f / static_cast<f32>(s.frame_max));
|
view_left = std::clamp(view_left_old + ImGui::GetMouseDragDelta().x / tl_width, 0.0f, view_right - 2.0f / static_cast<f32>(s.frame_max));
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
@ -658,7 +670,7 @@ namespace K::UI {
|
||||||
view_right_old = view_right;
|
view_right_old = view_right;
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemActive()) {
|
if (ImGui::IsItemActive()) {
|
||||||
view_left = std::clamp(view_left_old + ImGui::GetMouseDragDelta().x / tl_width * view_amt, 0.0f, 1.0f - view_amt);
|
view_left = std::clamp(view_left_old + ImGui::GetMouseDragDelta().x / tl_width, 0.0f, 1.0f - view_amt);
|
||||||
view_right = view_left + view_amt;
|
view_right = view_left + view_amt;
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
@ -670,7 +682,7 @@ namespace K::UI {
|
||||||
view_right_old = view_right;
|
view_right_old = view_right;
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemActive()) {
|
if (ImGui::IsItemActive()) {
|
||||||
view_right = std::clamp(view_right_old + ImGui::GetMouseDragDelta().x / tl_width * view_amt, view_left + 2.0f / static_cast<f32>(s.frame_max), 1.0f);
|
view_right = std::clamp(view_right_old + ImGui::GetMouseDragDelta().x / tl_width, view_left + 2.0f / static_cast<f32>(s.frame_max), 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
window->DrawList->AddRect({tl_init_pos.x - knob_width / 2.0f, tl_init_pos.y}, {tl_init_pos.x + knob_width / 2.0f, tl_init_pos.y + view_height},
|
window->DrawList->AddRect({tl_init_pos.x - knob_width / 2.0f, tl_init_pos.y}, {tl_init_pos.x + knob_width / 2.0f, tl_init_pos.y + view_height},
|
||||||
|
@ -678,45 +690,15 @@ namespace K::UI {
|
||||||
window->DrawList->AddRect({tl_init_pos.x + view_width - knob_width / 2.0f, tl_init_pos.y},
|
window->DrawList->AddRect({tl_init_pos.x + view_width - knob_width / 2.0f, tl_init_pos.y},
|
||||||
{tl_init_pos.x + view_width + knob_width / 2.0f, tl_init_pos.y + view_height}, 0x22FFFFFF);
|
{tl_init_pos.x + view_width + knob_width / 2.0f, tl_init_pos.y + view_height}, 0x22FFFFFF);
|
||||||
window->DrawList->AddRectFilled({tl_init_pos.x + view_width * view_left - knob_width / 2.0f, tl_init_pos.y},
|
window->DrawList->AddRectFilled({tl_init_pos.x + view_width * view_left - knob_width / 2.0f, tl_init_pos.y},
|
||||||
{tl_init_pos.x + view_width * view_left + knob_width / 2.0f, tl_init_pos.y + view_height},
|
{tl_init_pos.x + view_width * view_left + knob_width / 2.0f, tl_init_pos.y + view_height},
|
||||||
0xAAFFFFFF, 2.0f);
|
0xAAFFFFFF, 2.0f);
|
||||||
window->DrawList->AddRectFilled({tl_init_pos.x + view_width * view_right - knob_width / 2.0f, tl_init_pos.y},
|
window->DrawList->AddRectFilled({tl_init_pos.x + view_width * view_right - knob_width / 2.0f, tl_init_pos.y},
|
||||||
{tl_init_pos.x + view_width * view_right + knob_width / 2.0f, tl_init_pos.y + view_height},
|
{tl_init_pos.x + view_width * view_right + knob_width / 2.0f, tl_init_pos.y + view_height},
|
||||||
0xAAFFFFFF, 2.0f);
|
0xAAFFFFFF, 2.0f);
|
||||||
window->DrawList->AddRectFilled(
|
window->DrawList->AddRectFilled(
|
||||||
{tl_init_pos.x + view_width * view_left, tl_init_pos.y + view_height * .2f},
|
{tl_init_pos.x + view_width * view_left, tl_init_pos.y + view_height * .2f},
|
||||||
{tl_init_pos.x + view_width * view_right, tl_init_pos.y + view_height * .8f}, 0x33FFFFFF, 2.0f);
|
{tl_init_pos.x + view_width * view_right, tl_init_pos.y + view_height * .8f}, 0x33FFFFFF, 2.0f);
|
||||||
|
|
||||||
// Playhead
|
|
||||||
window->DrawList->AddLine({tl_init_pos.x + view_width * static_cast<f32>(s.current_frame) /
|
|
||||||
static_cast<f32>(s.frame_max + 1), tl_init_pos.y},
|
|
||||||
{tl_init_pos.x + view_width * static_cast<f32>(s.current_frame) /
|
|
||||||
static_cast<f32>(s.frame_max + 1),
|
|
||||||
tl_init_pos.y + view_height}, 0xFF3333FF, 2.0f);
|
|
||||||
|
|
||||||
ImGui::SetCursorScreenPos(tl_init_pos - style.CellPadding);
|
|
||||||
ImGui::InvisibleButton("##TL_BG", ImVec2{ view_width + style.CellPadding.x * 2, row_height + style.CellPadding.y});
|
|
||||||
|
|
||||||
// Frame Grid
|
|
||||||
static f32 frame_grid_min_width = 20.0f;
|
|
||||||
f32 fr_step = 1.0f / static_cast<f32>(s.frame_max + 1) * view_width / view_amt,
|
|
||||||
grid_step =
|
|
||||||
fr_step >= frame_grid_min_width ? fr_step : std::ceil(frame_grid_min_width / fr_step) * fr_step;
|
|
||||||
for (f32 fr = TimelineFrameToScreenView(view_left, view_amt, view_width,
|
|
||||||
std::ceil(view_left * static_cast<f32>(s.frame_max + 1)),
|
|
||||||
s.frame_max) + tl_init_pos.x;
|
|
||||||
fr < tl_init_pos.x + view_width; fr += grid_step)
|
|
||||||
window->DrawList->AddLine({fr, tl_init_pos.y + row_height},
|
|
||||||
{fr, ImGui::GetWindowSize().y + tl_init_pos.y}, 0x11FFFFFF, 1.0f);
|
|
||||||
|
|
||||||
if (TimelineFrameInView(view_left, view_right, s.current_frame, s.frame_max)) {
|
|
||||||
f32 fr = TimelineFrameToScreenView(view_left, view_amt, view_width, s.current_frame, s.frame_max) +
|
|
||||||
tl_init_pos.x;
|
|
||||||
window->DrawList->AddLine(
|
|
||||||
{fr, tl_init_pos.y + row_height},
|
|
||||||
{fr, ImGui::GetWindowSize().y + tl_init_pos.y}, 0x773333FF, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::PopStyleVar(3);
|
ImGui::PopStyleVar(3);
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::TableHeader("");
|
ImGui::TableHeader("");
|
||||||
|
@ -726,7 +708,7 @@ namespace K::UI {
|
||||||
i32 move_from = -1, move_to = -1;
|
i32 move_from = -1, move_to = -1;
|
||||||
bool after{};
|
bool after{};
|
||||||
|
|
||||||
// KF dragging controls
|
// KF controls
|
||||||
static bool started_dragging = false, dragging = false;
|
static bool started_dragging = false, dragging = false;
|
||||||
if (started_dragging) {
|
if (started_dragging) {
|
||||||
dragging = true;
|
dragging = true;
|
||||||
|
@ -828,26 +810,29 @@ namespace K::UI {
|
||||||
|
|
||||||
const static f32 layer_bound_width = 5.0f;
|
const static f32 layer_bound_width = 5.0f;
|
||||||
i32 l_in = TimelineFrameInView(view_left, view_right, current_layer.in, s.frame_max), l_out = TimelineFrameInView(view_left, view_right, current_layer.out, s.frame_max);
|
i32 l_in = TimelineFrameInView(view_left, view_right, current_layer.in, s.frame_max), l_out = TimelineFrameInView(view_left, view_right, current_layer.out, s.frame_max);
|
||||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + TimelineFrameToScreenView(view_left, view_amt, view_width, current_layer.in, s.frame_max));
|
f32 in_pos = TimelineFrameToScreenView(view_left, view_amt, view_width, current_layer.in, s.frame_max),
|
||||||
|
out_pos = TimelineFrameToScreenView(view_left, view_amt, view_width, current_layer.out, s.frame_max);
|
||||||
if (l_in) {
|
if (l_in) {
|
||||||
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + in_pos);
|
||||||
static f32 l_in_old;
|
static f32 l_in_old;
|
||||||
ImGui::PushStyleColor(ImGuiCol_Button, 0xFF666666);
|
ImGui::PushStyleColor(ImGuiCol_Button, 0xFF666666);
|
||||||
ImGui::Button("##Layer_L", {layer_bound_width, view_height});
|
ImGui::Button("##Layer_L", {layer_bound_width, view_height});
|
||||||
if (ImGui::IsItemClicked()) {
|
if (ImGui::IsItemClicked()) {
|
||||||
l_in_old = TimelineFrameToScreenView(view_left, view_amt, view_width, current_layer.in, s.frame_max);
|
l_in_old = in_pos;
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
|
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemActive()) {
|
if (ImGui::IsItemActive()) {
|
||||||
current_layer.in = std::min(TimelineScreenViewToFrame(view_left, view_amt, view_width, std::clamp(ImGui::GetMouseDragDelta().x + l_in_old, 0.0f, view_width), s.frame_max), current_layer.out);
|
current_layer.in = std::min(TimelineScreenViewToFrame(view_left, view_amt, view_width,
|
||||||
|
std::clamp(ImGui::GetMouseDragDelta().x + l_in_old, 0.0f, view_width), s.frame_max), current_layer.out);
|
||||||
}
|
}
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
ImGui::SameLine(0.0f, 0.0f);
|
ImGui::SameLine(0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
f32 in_pos = TimelineFrameToScreenView(view_left, view_amt, view_width, current_layer.in, s.frame_max);
|
|
||||||
ImGui::PushID(0);
|
ImGui::PushID(0);
|
||||||
ImGui::Button(current_layer.name.c_str(), {std::min(TimelineFrameToScreenView(view_left, view_amt, view_width, current_layer.out, s.frame_max) + fr_step, view_width) - in_pos - layer_bound_width * static_cast<f32>(l_in + l_out), view_height});
|
ImGui::Button(current_layer.name.c_str(),
|
||||||
|
{std::min(out_pos + fr_step, view_width) - static_cast<f32>(l_in) * in_pos - layer_bound_width * static_cast<f32>(l_in + l_out), view_height});
|
||||||
static u32 in_old, out_old;
|
static u32 in_old, out_old;
|
||||||
if (ImGui::IsItemClicked()) {
|
if (ImGui::IsItemClicked()) {
|
||||||
in_old = current_layer.in;
|
in_old = current_layer.in;
|
||||||
|
@ -866,7 +851,7 @@ namespace K::UI {
|
||||||
ImGui::PushStyleColor(ImGuiCol_Button, 0xFF666666);
|
ImGui::PushStyleColor(ImGuiCol_Button, 0xFF666666);
|
||||||
ImGui::Button("##Layer_R", {layer_bound_width, view_height});
|
ImGui::Button("##Layer_R", {layer_bound_width, view_height});
|
||||||
if (ImGui::IsItemClicked()) {
|
if (ImGui::IsItemClicked()) {
|
||||||
r_out_old = TimelineFrameToScreenView(view_left, view_amt, view_width, current_layer.out, s.frame_max);
|
r_out_old = out_pos;
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
|
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
|
||||||
|
@ -1016,6 +1001,10 @@ namespace K::UI {
|
||||||
ImGui::TableSetColumnIndex(2);
|
ImGui::TableSetColumnIndex(2);
|
||||||
|
|
||||||
auto& [chain, chain_copy] = *std::any_cast<PlugboardNodes::ChainExtra>(&info.p->extra);
|
auto& [chain, chain_copy] = *std::any_cast<PlugboardNodes::ChainExtra>(&info.p->extra);
|
||||||
|
|
||||||
|
if (tl_clear_selection_request)
|
||||||
|
chain.selected.clear();
|
||||||
|
|
||||||
bool m_empty = chain.segments.empty(), m_has_before = !m_empty && chain.segments.begin()->frame >= s.current_frame;
|
bool m_empty = chain.segments.empty(), m_has_before = !m_empty && chain.segments.begin()->frame >= s.current_frame;
|
||||||
|
|
||||||
ImGui::BeginDisabled(m_empty || m_has_before);
|
ImGui::BeginDisabled(m_empty || m_has_before);
|
||||||
|
@ -1032,7 +1021,7 @@ namespace K::UI {
|
||||||
|
|
||||||
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));
|
PlugboardGraph::Eval(s, info));
|
||||||
if (ImGui::DragFloat("##value", &v)) {
|
if (ImGui::DragFloat("##value", &v, 0.005f)) {
|
||||||
auto l = std::lower_bound(chain.segments.begin(), chain.segments.end(), s.current_frame,
|
auto l = std::lower_bound(chain.segments.begin(), chain.segments.end(), s.current_frame,
|
||||||
[](const PlugboardNodes::ChainSegment& a, i32 b) { return a.frame < b; });
|
[](const PlugboardNodes::ChainSegment& a, i32 b) { return a.frame < b; });
|
||||||
if (l != chain.segments.end() && l->frame == static_cast<i32>(s.current_frame))
|
if (l != chain.segments.end() && l->frame == static_cast<i32>(s.current_frame))
|
||||||
|
@ -1070,9 +1059,6 @@ namespace K::UI {
|
||||||
chain.selected.clear();
|
chain.selected.clear();
|
||||||
key_loop_target = &chain_copy;
|
key_loop_target = &chain_copy;
|
||||||
}
|
}
|
||||||
if (ImGui::IsWindowHovered() && ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !io.KeyCtrl) {
|
|
||||||
chain.selected.clear();
|
|
||||||
}
|
|
||||||
for (u32 ii = 0; ii < key_loop_target->segments.size(); ii++) {
|
for (u32 ii = 0; ii < key_loop_target->segments.size(); ii++) {
|
||||||
const auto& [k, val, segment] = (key_loop_target->segments)[ii];
|
const auto& [k, val, segment] = (key_loop_target->segments)[ii];
|
||||||
ImGui::PushID(k);
|
ImGui::PushID(k);
|
||||||
|
@ -1121,6 +1107,8 @@ namespace K::UI {
|
||||||
started_dragging = true; // setup dragging & start on next frame
|
started_dragging = true; // setup dragging & start on next frame
|
||||||
|
|
||||||
if (!is_sel || ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
|
if (!is_sel || ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
|
||||||
|
if (!io.KeyCtrl)
|
||||||
|
chain.selected.clear();
|
||||||
chain.selected.push_back(ii);
|
chain.selected.push_back(ii);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1164,6 +1152,8 @@ namespace K::UI {
|
||||||
|
|
||||||
if (started_dragging && dragging)
|
if (started_dragging && dragging)
|
||||||
started_dragging = false;
|
started_dragging = false;
|
||||||
|
if (tl_clear_selection_request_this_frame && tl_clear_selection_request)
|
||||||
|
tl_clear_selection_request = false;
|
||||||
|
|
||||||
tl_end_begin = {tl_init_pos.x, ImGui::GetCursorScreenPos().y};
|
tl_end_begin = {tl_init_pos.x, ImGui::GetCursorScreenPos().y};
|
||||||
|
|
||||||
|
@ -1209,12 +1199,107 @@ namespace K::UI {
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
||||||
ImGui::SetCursorScreenPos(tl_end_begin);
|
ImGui::SetCursorScreenPos(tl_end_begin);
|
||||||
if (ImGui::BeginChild("TL Overlay")) {
|
if (ImGui::BeginChild("TL Bottom Unfilled Drag Overlay")) {
|
||||||
draw_tl_bg_drag_area(ImGui::GetContentRegionAvail().y);
|
draw_tl_bg_drag_area(ImGui::GetContentRegionAvail().y);
|
||||||
tl_scroll_zoom();
|
tl_scroll_zoom();
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
||||||
|
ImVec2 tl_grid_cursor_pos = {tl_init_pos.x, tl_init_pos.y + row_height};
|
||||||
|
if (show_curve_editor) {
|
||||||
|
ImGui::SetCursorScreenPos(tl_grid_cursor_pos);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ChildBg, 0xFF111111);
|
||||||
|
if (ImGui::BeginChild("Curve Editor", ImGui::GetContentRegionAvail())) {
|
||||||
|
draw_tl_bg_drag_area(ImGui::GetContentRegionAvail().y);
|
||||||
|
tl_scroll_zoom();
|
||||||
|
ImGui::SetCursorScreenPos(tl_grid_cursor_pos);
|
||||||
|
|
||||||
|
ImPlot::PushStyleVar(ImPlotStyleVar_PlotPadding, {0.0f, 0.0f});
|
||||||
|
ImPlot::PushStyleVar(ImPlotStyleVar_FitPadding, {.1f, .1f});
|
||||||
|
ImPlot::PushStyleColor(ImPlotCol_FrameBg, 0);
|
||||||
|
ImPlot::PushStyleColor(ImPlotCol_PlotBg, 0);
|
||||||
|
ImPlot::PushStyleColor(ImPlotCol_PlotBorder, 0);
|
||||||
|
if (ImPlot::BeginPlot("uniform", {view_width, ImGui::GetContentRegionAvail().y}, 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; };
|
||||||
|
// struct PlotInfo info {
|
||||||
|
// .begin = view_left * static_cast<f32>(s.frame_max + 1),
|
||||||
|
// .end = view_right * static_cast<f32>(s.frame_max + 1),
|
||||||
|
// .samples = 200,
|
||||||
|
// .s = s,
|
||||||
|
// .connected_v = std::get<1>(connected_v)
|
||||||
|
// };
|
||||||
|
// ImPlot::SetupAxisLimits(ImAxis_X1, info.begin, info.end, ImGuiCond_Always);
|
||||||
|
// ImPlot::SetupFinish();
|
||||||
|
// ImPlot::PlotLineG("v", [](int idx, void* user_data) -> ImPlotPoint {
|
||||||
|
// PlotInfo i = *(PlotInfo*)user_data;
|
||||||
|
// f32 x = i.begin + (i.end - i.begin) * static_cast<f32>(idx) / static_cast<f32>(i.samples);
|
||||||
|
// CompState ss = i.s;
|
||||||
|
// ss.current_frame = static_cast<u64>(std::round(x));
|
||||||
|
// bool 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);
|
||||||
|
static float xs1[100], ys1[100];
|
||||||
|
for (int i = 0; i < 100; ++i) {
|
||||||
|
xs1[i] = i * 0.01f;
|
||||||
|
ys1[i] = xs1[i] + 0.1f * ((float)rand() / (float)RAND_MAX);
|
||||||
|
}
|
||||||
|
static float xs2[50], ys2[50];
|
||||||
|
for (int i = 0; i < 50; i++) {
|
||||||
|
xs2[i] = 0.25f + 0.2f * ((float)rand() / (float)RAND_MAX);
|
||||||
|
ys2[i] = 0.75f + 0.2f * ((float)rand() / (float)RAND_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImPlot::PlotScatter("Data 1", xs1, ys1, 100);
|
||||||
|
ImPlot::PushStyleVar(ImPlotStyleVar_FillAlpha, 0.25f);
|
||||||
|
ImPlot::SetNextMarkerStyle(ImPlotMarker_Square, 6, ImPlot::GetColormapColor(1), IMPLOT_AUTO, ImPlot::GetColormapColor(1));
|
||||||
|
ImPlot::PlotScatter("Data 2", xs2, ys2, 50);
|
||||||
|
ImPlot::PopStyleVar();
|
||||||
|
|
||||||
|
ImPlot::EndPlot();
|
||||||
|
}
|
||||||
|
ImPlot::PopStyleColor(3);
|
||||||
|
ImPlot::PopStyleVar(2);
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SetCursorScreenPos(tl_grid_cursor_pos);
|
||||||
|
if (ImGui::BeginChild("TL Grid Overlay", ImGui::GetContentRegionAvail(), ImGuiChildFlags_None, ImGuiWindowFlags_NoInputs)) {
|
||||||
|
// Playhead
|
||||||
|
auto window = ImGui::GetCurrentWindow();
|
||||||
|
window->DrawList->AddLine({tl_init_pos.x + view_width * static_cast<f32>(s.current_frame) /
|
||||||
|
static_cast<f32>(s.frame_max + 1), tl_init_pos.y},
|
||||||
|
{tl_init_pos.x + view_width * static_cast<f32>(s.current_frame) /
|
||||||
|
static_cast<f32>(s.frame_max + 1),
|
||||||
|
tl_init_pos.y + view_height}, 0xFF3333FF, 2.0f);
|
||||||
|
|
||||||
|
ImGui::SetCursorScreenPos(tl_init_pos - style.CellPadding);
|
||||||
|
ImGui::InvisibleButton("##TL_BG", ImVec2{ view_width + style.CellPadding.x * 2, row_height + style.CellPadding.y});
|
||||||
|
|
||||||
|
// Frame Grid
|
||||||
|
static f32 frame_grid_min_width = 20.0f;
|
||||||
|
f32 grid_step =
|
||||||
|
fr_step >= frame_grid_min_width ? fr_step : std::ceil(frame_grid_min_width / fr_step) * fr_step;
|
||||||
|
for (f32 fr = TimelineFrameToScreenView(view_left, view_amt, view_width,
|
||||||
|
std::ceil(view_left * static_cast<f32>(s.frame_max + 1)),
|
||||||
|
s.frame_max) + tl_init_pos.x;
|
||||||
|
fr < tl_init_pos.x + view_width; fr += grid_step)
|
||||||
|
window->DrawList->AddLine({fr, tl_init_pos.y + row_height},
|
||||||
|
{fr, ImGui::GetWindowSize().y + tl_init_pos.y}, 0x11FFFFFF, 1.0f);
|
||||||
|
|
||||||
|
if (TimelineFrameInView(view_left, view_right, s.current_frame, s.frame_max)) {
|
||||||
|
f32 fr = TimelineFrameToScreenView(view_left, view_amt, view_width, s.current_frame, s.frame_max) +
|
||||||
|
tl_init_pos.x;
|
||||||
|
window->DrawList->AddLine(
|
||||||
|
{fr, tl_init_pos.y + row_height},
|
||||||
|
{fr, ImGui::GetWindowSize().y + tl_init_pos.y}, 0x773333FF, 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndChild();
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
@ -1337,70 +1422,11 @@ namespace K::UI {
|
||||||
if (ImGui::Begin("Interpolation", &draw_interpolation, ImGuiWindowFlags_NoScrollbar)) {
|
if (ImGui::Begin("Interpolation", &draw_interpolation, ImGuiWindowFlags_NoScrollbar)) {
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
|
||||||
|
static PlugboardNodes::K_Interpolation type_current = PlugboardNodes::K_I_CubicBezier;
|
||||||
|
|
||||||
static const ImVec2 p1 { 0.0f, 0.0f}, p4 {1.0f, 1.0f};
|
static const ImVec2 p1 { 0.0f, 0.0f}, p4 {1.0f, 1.0f};
|
||||||
static ImVec2 p2 { 1.0f, 0.0f }, p3 { 0.0f, 1.0f }, p2_old = p2, p3_old = p3;
|
static ImVec2 p2 { 1.0f, 0.0f }, p3 { 0.0f, 1.0f }, p2_old = p2, p3_old = p3;
|
||||||
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, {10.0f, 10.0f});
|
|
||||||
f32 y_max = std::max(std::max(p2.y, p3.y), p4.y),
|
|
||||||
y_min = std::min(std::min(p1.y, p2.y), p3.y),
|
|
||||||
y_range = y_max - y_min;
|
|
||||||
|
|
||||||
f32 w_window = ImGui::GetContentRegionAvail().x;
|
|
||||||
if (ImGui::BeginChild("Canvas", {w_window, w_window}, ImGuiChildFlags_Border, ImGuiWindowFlags_NoScrollbar)) {
|
|
||||||
f32 w = ImGui::GetContentRegionAvail().x;
|
|
||||||
ImVec2 pos = ImGui::GetCursorScreenPos();
|
|
||||||
auto *dl = ImGui::GetWindowDrawList();
|
|
||||||
ImVec2 tp1 = pos + ImVec2{p1.x * w, ((1.0f - p1.y) - (1.0f - y_max)) * w / y_range},
|
|
||||||
tp4 = pos + ImVec2{p4.x * w, ((1.0f - p4.y) - (1.0f - y_max)) * w / y_range},
|
|
||||||
tp2 = pos + ImVec2{p2.x * w, ((1.0f - p2.y) - (1.0f - y_max)) * w / y_range},
|
|
||||||
tp3 = pos + ImVec2{p3.x * w, ((1.0f - p3.y) - (1.0f - y_max)) * w / y_range};
|
|
||||||
dl->AddBezierCubic(tp1, tp2, tp3, tp4, 0xFFFFFFFF, 2.0f);
|
|
||||||
dl->AddLine(tp1, tp2, 0xAAFFFFFF, 1.5f);
|
|
||||||
dl->AddLine(tp3, tp4, 0xAAFFFFFF, 1.5f);
|
|
||||||
dl->AddLine(tp1, {tp1.x + w, tp1.y}, 0x44FFFFFF, 2.0f);
|
|
||||||
dl->AddLine(tp4, {tp4.x - w, tp4.y}, 0x44FFFFFF, 2.0f);
|
|
||||||
dl->AddText(tp1 + ImVec2{10.0f, -20.0f}, 0xFFFFFFFF, "0.0");
|
|
||||||
dl->AddText(tp4 + ImVec2{-30.0f, 10.0f}, 0xFFFFFFFF, "1.0");
|
|
||||||
|
|
||||||
f32 x = std::clamp((io.MousePos.x - pos.x) / w, 0.0f, 1.0f);
|
|
||||||
f32 y = Graphics::InjectingCubicBezierFromX(p2.x, p2.y, p3.x, p3.y, x);
|
|
||||||
dl->AddLine(pos + ImVec2{0, ((1.0f - y) - (1.0f - y_max)) * w / y_range}, pos + ImVec2{w, ((1.0f - y) - (1.0f - y_max)) * w / y_range}, 0xBB5555FF, 1.0f);
|
|
||||||
dl->AddLine(pos + ImVec2{x * w, 0.0f}, pos + ImVec2{x * w, w}, 0x44FF5555, 1.0f);
|
|
||||||
|
|
||||||
ImGui::SetCursorScreenPos({tp1.x, ((1.0f - y) - (1.0f - y_max)) * w / y_range + pos.y});
|
|
||||||
ImGui::Text("%.2f, %.2f", x, y);
|
|
||||||
|
|
||||||
ImGui::SetCursorPos(ImVec2{0.0f, 20.0f});
|
|
||||||
ImGui::Text("%.2f", y_max);
|
|
||||||
|
|
||||||
ImGui::SetCursorPos(ImVec2{w * .8f, w - 15.0f,});
|
|
||||||
ImGui::Text("%.2f", y_min);
|
|
||||||
|
|
||||||
ImVec2 size = {15.0f, 15.0f};
|
|
||||||
ImGui::SetCursorScreenPos(tp2 - size / 2.0f);
|
|
||||||
ImVec2 off = io.MousePos - io.MouseClickedPos[0];
|
|
||||||
ImGui::Button("##P2", size);
|
|
||||||
if (ImGui::IsItemClicked()) {
|
|
||||||
p2_old = p2;
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemActive()) {
|
|
||||||
p2 = p2_old + ImVec2{off.x / w, off.y / -w * y_range};
|
|
||||||
p2.x = std::clamp(p2.x, 0.0f, 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::SetCursorScreenPos(tp3 - size / 2.0f);
|
|
||||||
ImGui::Button("##P3", size);
|
|
||||||
if (ImGui::IsItemClicked()) {
|
|
||||||
p3_old = p3;
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemActive()) {
|
|
||||||
p3 = p3_old + ImVec2{off.x / w, off.y / -w * y_range};
|
|
||||||
p3.x = std::clamp(p3.x, 0.0f, 1.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::PopStyleVar(1);
|
|
||||||
ImGui::EndChild();
|
|
||||||
|
|
||||||
if (ImGui::Button("Apply"))
|
if (ImGui::Button("Apply"))
|
||||||
for (auto& layer : s.layers)
|
for (auto& layer : s.layers)
|
||||||
for (auto& u : layer.track.uniforms)
|
for (auto& u : layer.track.uniforms)
|
||||||
|
@ -1409,11 +1435,97 @@ namespace K::UI {
|
||||||
for (auto it = chain.segments.begin(); it != chain.segments.end(); it++) {
|
for (auto it = chain.segments.begin(); it != chain.segments.end(); it++) {
|
||||||
auto nit = std::next(it);
|
auto nit = std::next(it);
|
||||||
if (nit != chain.segments.end() && std::find(chain.selected.begin(), chain.selected.end(), std::distance(chain.segments.begin(), it)) != chain.selected.end() &&
|
if (nit != chain.segments.end() && std::find(chain.selected.begin(), chain.selected.end(), std::distance(chain.segments.begin(), it)) != chain.selected.end() &&
|
||||||
std::find(chain.selected.begin(), chain.selected.end(), std::distance(chain.segments.begin(), nit)) != chain.selected.end()) {
|
std::find(chain.selected.begin(), chain.selected.end(), std::distance(chain.segments.begin(), nit)) != chain.selected.end()) {
|
||||||
it->interp = {PlugboardNodes::K_I_CubicBezier, {p2.x, p2.y, p3.x, p3.y}};
|
it->interp = {type_current, {p2.x, p2.y, p3.x, p3.y}};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
|
||||||
|
ImGui::Combo("##Type", (i32*)&type_current, PlugboardNodes::K_Interpolation_Names, PlugboardNodes::K_I_Count);
|
||||||
|
|
||||||
|
f32 w_window = std::min(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y);
|
||||||
|
if (type_current == PlugboardNodes::K_I_CubicBezier) {
|
||||||
|
f32 y_max = std::max(std::max(p2.y, p3.y), p4.y),
|
||||||
|
y_min = std::min(std::min(p1.y, p2.y), p3.y),
|
||||||
|
y_range = y_max - y_min;
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, {10.0f, 10.0f});
|
||||||
|
if (ImGui::BeginChild("Canvas", {w_window, w_window}, ImGuiChildFlags_Border, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse)) {
|
||||||
|
f32 w = ImGui::GetContentRegionAvail().x;
|
||||||
|
ImVec2 pos = ImGui::GetCursorScreenPos();
|
||||||
|
auto *dl = ImGui::GetWindowDrawList();
|
||||||
|
ImVec2 tp1 = pos + ImVec2{p1.x * w, ((1.0f - p1.y) - (1.0f - y_max)) * w / y_range},
|
||||||
|
tp4 = pos + ImVec2{p4.x * w, ((1.0f - p4.y) - (1.0f - y_max)) * w / y_range},
|
||||||
|
tp2 = pos + ImVec2{p2.x * w, ((1.0f - p2.y) - (1.0f - y_max)) * w / y_range},
|
||||||
|
tp3 = pos + ImVec2{p3.x * w, ((1.0f - p3.y) - (1.0f - y_max)) * w / y_range};
|
||||||
|
dl->AddBezierCubic(tp1, tp2, tp3, tp4, 0xFFFFFFFF, 2.0f);
|
||||||
|
dl->AddLine(tp1, tp2, 0xAAFFFFFF, 1.5f);
|
||||||
|
dl->AddLine(tp3, tp4, 0xAAFFFFFF, 1.5f);
|
||||||
|
dl->AddLine(tp1, {tp1.x + w, tp1.y}, 0x44FFFFFF, 2.0f);
|
||||||
|
dl->AddLine(tp4, {tp4.x - w, tp4.y}, 0x44FFFFFF, 2.0f);
|
||||||
|
dl->AddText(tp1 + ImVec2{10.0f, -20.0f}, 0xFFFFFFFF, "0.0");
|
||||||
|
dl->AddText(tp4 + ImVec2{-30.0f, 10.0f}, 0xFFFFFFFF, "1.0");
|
||||||
|
|
||||||
|
f32 x = std::clamp((io.MousePos.x - pos.x) / w, 0.0f, 1.0f);
|
||||||
|
f32 y = Graphics::InjectingCubicBezierFromX(p2.x, p2.y, p3.x, p3.y, x);
|
||||||
|
dl->AddLine(pos + ImVec2{0, ((1.0f - y) - (1.0f - y_max)) * w / y_range}, pos + ImVec2{w, ((1.0f - y) - (1.0f - y_max)) * w / y_range}, 0xBB5555FF, 1.0f);
|
||||||
|
dl->AddLine(pos + ImVec2{x * w, 0.0f}, pos + ImVec2{x * w, w}, 0x44FF5555, 1.0f);
|
||||||
|
|
||||||
|
ImGui::SetCursorScreenPos({tp1.x, ((1.0f - y) - (1.0f - y_max)) * w / y_range + pos.y});
|
||||||
|
ImGui::Text("%.2f, %.2f", x, y);
|
||||||
|
|
||||||
|
ImGui::SetCursorPos(ImVec2{0.0f, 20.0f});
|
||||||
|
ImGui::Text("%.2f", y_max);
|
||||||
|
|
||||||
|
ImGui::SetCursorPos(ImVec2{w * .8f, w - 15.0f,});
|
||||||
|
ImGui::Text("%.2f", y_min);
|
||||||
|
|
||||||
|
ImVec2 size = {15.0f, 15.0f};
|
||||||
|
ImGui::SetCursorScreenPos(tp2 - size / 2.0f);
|
||||||
|
ImVec2 off = io.MousePos - io.MouseClickedPos[0];
|
||||||
|
ImGui::Button("##P2", size);
|
||||||
|
if (ImGui::IsItemClicked()) {
|
||||||
|
p2_old = p2;
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemActive()) {
|
||||||
|
p2 = p2_old + ImVec2{off.x / w, off.y / -w * y_range};
|
||||||
|
p2.x = std::clamp(p2.x, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SetCursorScreenPos(tp3 - size / 2.0f);
|
||||||
|
ImGui::Button("##P3", size);
|
||||||
|
if (ImGui::IsItemClicked()) {
|
||||||
|
p3_old = p3;
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemActive()) {
|
||||||
|
p3 = p3_old + ImVec2{off.x / w, off.y / -w * y_range};
|
||||||
|
p3.x = std::clamp(p3.x, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::PopStyleVar(1);
|
||||||
|
ImGui::EndChild();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ImPlot::PushStyleVar(ImPlotStyleVar_PlotPadding, {0.0f, 0.0f});
|
||||||
|
ImPlot::PushStyleVar(ImPlotStyleVar_FitPadding, {.1f, .1f});
|
||||||
|
ImPlot::PushStyleColor(ImPlotCol_FrameBg, 0);
|
||||||
|
ImPlot::PushStyleColor(ImPlotCol_PlotBg, 0);
|
||||||
|
ImPlot::PushStyleColor(ImPlotCol_PlotBorder, 0);
|
||||||
|
if (ImPlot::BeginPlot("uniform", {w_window, w_window}, ImPlotFlags_CanvasOnly | ImPlotFlags_NoInputs)) {
|
||||||
|
ImPlot::SetupAxis(ImAxis_X1, "time", ImPlotAxisFlags_NoLabel | ImPlotAxisFlags_NoHighlight | ImPlotAxisFlags_AutoFit);
|
||||||
|
ImPlot::SetupAxis(ImAxis_Y1, "val", ImPlotAxisFlags_Opposite | ImPlotAxisFlags_NoLabel | ImPlotAxisFlags_NoHighlight | ImPlotAxisFlags_AutoFit);
|
||||||
|
ImPlot::SetupFinish();
|
||||||
|
constexpr static u32 samples = 100;
|
||||||
|
ImPlot::PlotLineG("v", [](i32 idx, void* user_data) {
|
||||||
|
f32 t = static_cast<f32>(idx) / static_cast<f32>(samples);
|
||||||
|
return ImPlotPoint{t, PlugboardNodes::EvalInterpolation(t, {.interp = type_current})};
|
||||||
|
}, nullptr, samples);
|
||||||
|
ImPlot::EndPlot();
|
||||||
|
}
|
||||||
|
ImPlot::PopStyleColor(3);
|
||||||
|
ImPlot::PopStyleVar(2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,109 @@ namespace K::PlugboardNodes {
|
||||||
f32 v[4];
|
f32 v[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr 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 {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern PlugboardGraph::Node Interpolation;
|
extern PlugboardGraph::Node Interpolation;
|
||||||
|
|
||||||
struct ChainSegment {
|
struct ChainSegment {
|
||||||
|
|
6
TODO.md
6
TODO.md
|
@ -1,11 +1,10 @@
|
||||||
# NOW
|
# NOW
|
||||||
## UI
|
## UI
|
||||||
- Undo's
|
|
||||||
- Once this is done we can move the plugboard loop detection/chain finding out of the eval loop
|
|
||||||
- Keys
|
- Keys
|
||||||
- selection in comp panel
|
|
||||||
- deletion
|
- deletion
|
||||||
- copy & paste
|
- copy & paste
|
||||||
|
- Undo's
|
||||||
|
- Once this is done we can move the plugboard loop detection/chain finding out of the eval loop
|
||||||
- Graph editor
|
- Graph editor
|
||||||
- Node groups
|
- Node groups
|
||||||
- Simple export
|
- Simple export
|
||||||
|
@ -37,6 +36,7 @@
|
||||||
## Compositor
|
## Compositor
|
||||||
- Simple 3D engine
|
- Simple 3D engine
|
||||||
- Flat sets and flat maps pending compiler support
|
- Flat sets and flat maps pending compiler support
|
||||||
|
- Random Idea: Array-eval nodes
|
||||||
|
|
||||||
## UI
|
## UI
|
||||||
- Adapt nodes for shader graph -- code editor will be fine for now
|
- Adapt nodes for shader graph -- code editor will be fine for now
|
||||||
|
|
Loading…
Add table
Reference in a new issue