some curve editor fixes
This commit is contained in:
parent
cf0af93cac
commit
5ca9c91098
1 changed files with 216 additions and 159 deletions
375
Keishiki/UI.cpp
375
Keishiki/UI.cpp
|
@ -871,9 +871,11 @@ namespace K::UI {
|
||||||
std::erase(s.selected, i);
|
std::erase(s.selected, i);
|
||||||
else
|
else
|
||||||
s.selected.push_back(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.push_back(i);
|
s.selected.push_back(i);
|
||||||
|
@ -929,81 +931,99 @@ namespace K::UI {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timeline
|
// Timeline
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
ImGui::TableSetColumnIndex(4);
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{});
|
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, ImVec2{});
|
|
||||||
|
|
||||||
ImGui::TableNextColumn();
|
|
||||||
|
|
||||||
f32 init_y = ImGui::GetCursorScreenPos().y;
|
f32 init_y = ImGui::GetCursorScreenPos().y;
|
||||||
|
if (!show_curve_editor) {
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{});
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, ImVec2{});
|
||||||
|
|
||||||
const static f32 layer_bound_width = 5.0f;
|
const static f32 layer_bound_width = 5.0f;
|
||||||
const bool l_le_right_extr = static_cast<f32>(current_layer.in) / static_cast<f32>(s.frame_max + 1) <= view_right,
|
const bool l_le_right_extr =
|
||||||
l_in = l_le_right_extr && static_cast<f32>(current_layer.in) / static_cast<f32>(s.frame_max + 1) >= view_left,
|
static_cast<f32>(current_layer.in) / static_cast<f32>(s.frame_max + 1) <= view_right,
|
||||||
l_ge_left_extr = static_cast<f32>(current_layer.out) / static_cast<f32>(s.frame_max + 1) >= view_left,
|
l_in = l_le_right_extr &&
|
||||||
l_out = l_ge_left_extr && static_cast<f32>(current_layer.out) / static_cast<f32>(s.frame_max + 1) <= view_right;
|
static_cast<f32>(current_layer.in) / static_cast<f32>(s.frame_max + 1) >= view_left,
|
||||||
f32 in_pos = TimelineFrameToScreenView(view_left, view_amt, view_width, current_layer.in, s.frame_max),
|
l_ge_left_extr =
|
||||||
out_pos = TimelineFrameToScreenView(view_left, view_amt, view_width, current_layer.out, s.frame_max);
|
static_cast<f32>(current_layer.out) / static_cast<f32>(s.frame_max + 1) >= view_left,
|
||||||
ImGui::PushID(0);
|
l_out = l_ge_left_extr &&
|
||||||
if (l_in) {
|
static_cast<f32>(current_layer.out) / static_cast<f32>(s.frame_max + 1) <=
|
||||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + in_pos);
|
view_right;
|
||||||
static f32 l_in_old;
|
f32 in_pos = TimelineFrameToScreenView(view_left, view_amt, view_width, current_layer.in,
|
||||||
ImGui::PushStyleColor(ImGuiCol_Button, 0xFF666666);
|
s.frame_max),
|
||||||
ImGui::Button("##Layer_L", {layer_bound_width, view_height});
|
out_pos = TimelineFrameToScreenView(view_left, view_amt, view_width, current_layer.out,
|
||||||
if (ImGui::IsItemClicked()) {
|
s.frame_max);
|
||||||
l_in_old = in_pos;
|
ImGui::PushID(0);
|
||||||
|
if (l_in) {
|
||||||
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + in_pos);
|
||||||
|
static f32 l_in_old;
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Button, 0xFF666666);
|
||||||
|
ImGui::Button("##Layer_L", {layer_bound_width, view_height});
|
||||||
|
if (ImGui::IsItemClicked()) {
|
||||||
|
l_in_old = in_pos;
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
ImGui::SameLine(0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered()) {
|
if (l_le_right_extr && l_ge_left_extr) {
|
||||||
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
|
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;
|
||||||
|
if (ImGui::IsItemClicked()) {
|
||||||
|
in_old = current_layer.in;
|
||||||
|
out_old = current_layer.out;
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemActive()) {
|
||||||
|
i32 off = static_cast<i32>(std::trunc(ImGui::GetMouseDragDelta().x / fr_step));
|
||||||
|
off = std::max(-static_cast<i32>(in_old), off);
|
||||||
|
current_layer.in = in_old + off;
|
||||||
|
current_layer.out = out_old + off;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemActive()) {
|
if (l_out) {
|
||||||
current_layer.in = std::min(TimelineScreenViewToFrame(view_left, view_amt, view_width,
|
static f32 r_out_old;
|
||||||
std::clamp(ImGui::GetMouseDragDelta().x + l_in_old, 0.0f, view_width), s.frame_max), current_layer.out);
|
ImGui::SameLine(0.0f, 0.0f);
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Button, 0xFF666666);
|
||||||
|
ImGui::Button("##Layer_R", {layer_bound_width, view_height});
|
||||||
|
if (ImGui::IsItemClicked()) {
|
||||||
|
r_out_old = out_pos;
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
|
||||||
|
}
|
||||||
|
if (ImGui::IsItemActive()) {
|
||||||
|
current_layer.out = std::max(TimelineScreenViewToFrame(view_left, view_amt, view_width,
|
||||||
|
std::clamp(
|
||||||
|
ImGui::GetMouseDragDelta().x +
|
||||||
|
r_out_old, 0.0f, view_width),
|
||||||
|
s.frame_max), current_layer.in);
|
||||||
|
}
|
||||||
|
ImGui::PopStyleColor();
|
||||||
}
|
}
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopID();
|
||||||
ImGui::SameLine(0.0f, 0.0f);
|
|
||||||
}
|
|
||||||
if (l_le_right_extr && l_ge_left_extr) {
|
|
||||||
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;
|
|
||||||
if (ImGui::IsItemClicked()) {
|
|
||||||
in_old = current_layer.in;
|
|
||||||
out_old = current_layer.out;
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemActive()) {
|
|
||||||
i32 off = static_cast<i32>(std::trunc(ImGui::GetMouseDragDelta().x / fr_step));
|
|
||||||
off = std::max(-static_cast<i32>(in_old), off);
|
|
||||||
current_layer.in = in_old + off;
|
|
||||||
current_layer.out = out_old + off;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (l_out) {
|
|
||||||
static f32 r_out_old;
|
|
||||||
ImGui::SameLine(0.0f, 0.0f);
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Button, 0xFF666666);
|
|
||||||
ImGui::Button("##Layer_R", {layer_bound_width, view_height});
|
|
||||||
if (ImGui::IsItemClicked()) {
|
|
||||||
r_out_old = out_pos;
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemHovered()) {
|
|
||||||
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
|
|
||||||
}
|
|
||||||
if (ImGui::IsItemActive()) {
|
|
||||||
current_layer.out = std::max(TimelineScreenViewToFrame(view_left, view_amt, view_width, std::clamp(ImGui::GetMouseDragDelta().x + r_out_old, 0.0f, view_width), s.frame_max), current_layer.in);
|
|
||||||
}
|
|
||||||
ImGui::PopStyleColor();
|
|
||||||
}
|
|
||||||
ImGui::PopID();
|
|
||||||
|
|
||||||
ImGui::SetCursorScreenPos(ImVec2{tl_init_pos.x, init_y} - style.CellPadding);
|
ImGui::SetCursorScreenPos(ImVec2{tl_init_pos.x, init_y} - style.CellPadding);
|
||||||
ImGui::InvisibleButton("##TL_BG", ImVec2{ view_width + style.CellPadding.x * 2, row_height + style.CellPadding.y});
|
ImGui::InvisibleButton("##TL_BG", ImVec2{view_width + style.CellPadding.x * 2,
|
||||||
if (ImGui::IsItemActive()) {
|
row_height + style.CellPadding.y});
|
||||||
s.current_frame = TimelineScreenViewToFrame(view_left, view_amt, view_width, std::clamp(mouse_tl_x, 0.0f, view_width), s.frame_max);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::PopStyleVar(3);
|
ImGui::PopStyleVar(3);
|
||||||
|
}
|
||||||
|
|
||||||
if (layer_open) {
|
if (layer_open) {
|
||||||
i32 j = 0;
|
i32 j = 0;
|
||||||
|
@ -1046,7 +1066,7 @@ namespace K::UI {
|
||||||
else if (ImGui::IsItemActive()) {
|
else if (ImGui::IsItemActive()) {
|
||||||
if (ImGui::IsKeyPressed(ImGuiKey_LeftShift)) {
|
if (ImGui::IsKeyPressed(ImGuiKey_LeftShift)) {
|
||||||
auto& c = s.plugboard.nodes.Store(Plugboard::Chain{});
|
auto& c = s.plugboard.nodes.Store(Plugboard::Chain{});
|
||||||
c.extra.chain.segments.emplace_back(s.current_frame, std::get<Plugboard::T_Map<Plugboard::T_Float>::type>(arg));
|
c.extra.chain.segments.emplace_back(s.current_frame, std::get<Plugboard::T_Map<Plugboard::T_Float>::type>(arg), Plugboard::InterpolationExtra(Plugboard::K_I_Linear));
|
||||||
c.extra.chain.selected.push_back(0);
|
c.extra.chain.selected.push_back(0);
|
||||||
Plugboard::Connect(u.connection.p, u.connection.index, &c, 0);
|
Plugboard::Connect(u.connection.p, u.connection.index, &c, 0);
|
||||||
Plugboard::Connect(&c, 0, &s.plugboard.in_instance, 0);
|
Plugboard::Connect(&c, 0, &s.plugboard.in_instance, 0);
|
||||||
|
@ -1078,46 +1098,57 @@ namespace K::UI {
|
||||||
|
|
||||||
ImGui::TableSetColumnIndex(3);
|
ImGui::TableSetColumnIndex(3);
|
||||||
ImGui::TableSetColumnIndex(4);
|
ImGui::TableSetColumnIndex(4);
|
||||||
auto p = ImGui::GetCursorScreenPos(); // restored later
|
if (!show_curve_editor) {
|
||||||
|
auto p = ImGui::GetCursorScreenPos(); // restored later
|
||||||
|
|
||||||
// plot uniform if connected
|
// plot uniform if connected
|
||||||
ImPlot::PushStyleVar(ImPlotStyleVar_PlotPadding, {0.0f, 0.0f});
|
ImPlot::PushStyleVar(ImPlotStyleVar_PlotPadding, {0.0f, 0.0f});
|
||||||
ImPlot::PushStyleVar(ImPlotStyleVar_FitPadding, {.1f, .1f});
|
ImPlot::PushStyleVar(ImPlotStyleVar_FitPadding, {.1f, .1f});
|
||||||
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}, ImPlotFlags_CanvasOnly | ImPlotFlags_NoFrame | ImPlotFlags_NoInputs)) {
|
if (connected_v.index() == 1 && ImPlot::BeginPlot("uniform", {view_width, row_height},
|
||||||
ImPlot::SetupAxis(ImAxis_X1, "time", ImPlotAxisFlags_NoDecorations | ImPlotAxisFlags_NoHighlight);
|
ImPlotFlags_CanvasOnly |
|
||||||
ImPlot::SetupAxis(ImAxis_Y1, "val", ImPlotAxisFlags_NoDecorations | ImPlotAxisFlags_NoHighlight | ImPlotAxisFlags_AutoFit);
|
ImPlotFlags_NoFrame |
|
||||||
struct PlotInfo info {
|
ImPlotFlags_NoInputs)) {
|
||||||
.begin = view_left * static_cast<f32>(s.frame_max + 1),
|
ImPlot::SetupAxis(ImAxis_X1, "time",
|
||||||
.end = view_right * static_cast<f32>(s.frame_max + 1),
|
ImPlotAxisFlags_NoDecorations | ImPlotAxisFlags_NoHighlight);
|
||||||
.samples = 100,
|
ImPlot::SetupAxis(ImAxis_Y1, "val",
|
||||||
.s = s,
|
ImPlotAxisFlags_NoDecorations | ImPlotAxisFlags_NoHighlight |
|
||||||
.connected_v = std::get<1>(connected_v)
|
ImPlotAxisFlags_AutoFit);
|
||||||
};
|
struct PlotInfo info{
|
||||||
ImPlot::SetupAxisLimits(ImAxis_X1, info.begin, info.end, ImGuiCond_Always);
|
.begin = view_left * static_cast<f32>(s.frame_max + 1),
|
||||||
ImPlot::SetupFinish();
|
.end = view_right * static_cast<f32>(s.frame_max + 1),
|
||||||
ImPlot::PlotLineG("v", [](int idx, void* user_data) -> ImPlotPoint {
|
.samples = 100,
|
||||||
PlotInfo i = *(PlotInfo*)user_data;
|
.s = s,
|
||||||
f32 x = i.begin + (i.end - i.begin) * static_cast<f32>(idx) / static_cast<f32>(i.samples);
|
.connected_v = std::get<1>(connected_v)
|
||||||
CompositionState ss = i.s;
|
};
|
||||||
ss.current_frame = static_cast<u64>(std::round(x));
|
ImPlot::SetupAxisLimits(ImAxis_X1, info.begin, info.end, ImGuiCond_Always);
|
||||||
bool good;
|
ImPlot::SetupFinish();
|
||||||
Vector<Plugboard::ConnectInfo> info;
|
ImPlot::PlotLineG("v", [](int idx, void *user_data) -> ImPlotPoint {
|
||||||
return {x, std::get<Plugboard::T_Map<Plugboard::T_Float>::type>(Plugboard::ConvertValue(Plugboard::Eval(ss, i.connected_v), Plugboard::T_Float, good))};
|
PlotInfo i = *(PlotInfo *) user_data;
|
||||||
|
f32 x = i.begin +
|
||||||
|
(i.end - i.begin) * static_cast<f32>(idx) / static_cast<f32>(i.samples);
|
||||||
|
CompositionState ss = i.s;
|
||||||
|
ss.current_frame = static_cast<u64>(std::round(x));
|
||||||
|
bool good;
|
||||||
|
Vector<Plugboard::ConnectInfo> info;
|
||||||
|
return {x, std::get<Plugboard::T_Map<Plugboard::T_Float>::type>(
|
||||||
|
Plugboard::ConvertValue(Plugboard::Eval(ss, i.connected_v),
|
||||||
|
Plugboard::T_Float, good))};
|
||||||
}, &info, info.samples);
|
}, &info, info.samples);
|
||||||
ImPlot::EndPlot();
|
ImPlot::EndPlot();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ImGui::TextUnformatted("Constant");
|
ImGui::TextUnformatted("Constant");
|
||||||
}
|
}
|
||||||
ImPlot::PopStyleColor(3);
|
ImPlot::PopStyleColor(3);
|
||||||
ImPlot::PopStyleVar(2);
|
ImPlot::PopStyleVar(2);
|
||||||
|
|
||||||
ImGui::SetCursorScreenPos(p);
|
ImGui::SetCursorScreenPos(p);
|
||||||
|
|
||||||
tl_bg_handler();
|
tl_bg_handler();
|
||||||
|
}
|
||||||
|
|
||||||
if (uniform_open && connected_v.index() == 1) {
|
if (uniform_open && connected_v.index() == 1) {
|
||||||
for (const auto& info: s.plugboard.show_nodes[u.connection.index]) {
|
for (const auto& info: s.plugboard.show_nodes[u.connection.index]) {
|
||||||
|
@ -1142,9 +1173,6 @@ namespace K::UI {
|
||||||
|
|
||||||
auto& [chain, chain_copy] = std::get<Plugboard::Chain*>(info.p)->extra;
|
auto& [chain, chain_copy] = std::get<Plugboard::Chain*>(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);
|
||||||
|
@ -1190,57 +1218,73 @@ namespace K::UI {
|
||||||
ImGui::TableSetColumnIndex(3);
|
ImGui::TableSetColumnIndex(3);
|
||||||
ImGui::Text("%lu", chain.segments.size());
|
ImGui::Text("%lu", chain.segments.size());
|
||||||
ImGui::TableSetColumnIndex(4);
|
ImGui::TableSetColumnIndex(4);
|
||||||
ImVec2 begin_tl = ImGui::GetCursorScreenPos();
|
if (!show_curve_editor) {
|
||||||
|
ImVec2 begin_tl = ImGui::GetCursorScreenPos();
|
||||||
|
|
||||||
if (started_dragging)
|
if (started_dragging)
|
||||||
chain_copy = chain;
|
chain_copy = chain;
|
||||||
|
|
||||||
auto key_loop_target = &chain;
|
auto key_loop_target = &chain;
|
||||||
if (dragging) {
|
if (dragging) {
|
||||||
chain.segments.clear();
|
chain.segments.clear();
|
||||||
chain.selected.clear();
|
chain.selected.clear();
|
||||||
key_loop_target = &chain_copy;
|
key_loop_target = &chain_copy;
|
||||||
}
|
|
||||||
for (u32 ii = 0; ii < key_loop_target->segments.size(); ii++) {
|
|
||||||
const auto& [k, val, segment] = (key_loop_target->segments)[ii];
|
|
||||||
ImGui::PushID(k);
|
|
||||||
|
|
||||||
auto sel_it = std::ranges::find(key_loop_target->selected, ii);
|
|
||||||
bool is_sel = sel_it != key_loop_target->selected.end();
|
|
||||||
|
|
||||||
i32 frame = k;
|
|
||||||
if (dragging && is_sel) {
|
|
||||||
frame += static_cast<i32>(ImGui::GetMouseDragDelta().x / tl_width * view_amt *
|
|
||||||
static_cast<f32>(s.frame_max + 1));
|
|
||||||
}
|
}
|
||||||
ImVec2 draw_pos = {TimelineFrameToScreenView(view_left, view_amt, view_width, frame,
|
for (u32 ii = 0; ii < key_loop_target->segments.size(); ii++) {
|
||||||
s.frame_max) + begin_tl.x - kf_tab_width / 2.0f,
|
const auto &[k, val, segment] = (key_loop_target->segments)[ii];
|
||||||
begin_tl.y};
|
ImGui::PushID(k);
|
||||||
|
|
||||||
ImGui::SetCursorScreenPos(draw_pos);
|
auto sel_it = std::ranges::find(key_loop_target->selected, ii);
|
||||||
|
bool is_sel = sel_it != key_loop_target->selected.end();
|
||||||
|
|
||||||
ImGui::Button(is_sel ? "s" : "k", {kf_tab_width, row_height * .8f});
|
i32 frame = k;
|
||||||
|
if (dragging && is_sel) {
|
||||||
|
frame += static_cast<i32>(ImGui::GetMouseDragDelta().x / tl_width *
|
||||||
|
view_amt *
|
||||||
|
static_cast<f32>(s.frame_max + 1));
|
||||||
|
}
|
||||||
|
ImVec2 draw_pos = {
|
||||||
|
TimelineFrameToScreenView(view_left, view_amt, view_width, frame,
|
||||||
|
s.frame_max) + begin_tl.x -
|
||||||
|
kf_tab_width / 2.0f,
|
||||||
|
begin_tl.y};
|
||||||
|
|
||||||
kf_drag_btn_handler(key_loop_target, dragging, chain, frame, is_sel,
|
ImGui::SetCursorScreenPos(draw_pos);
|
||||||
sel_it, segment, val, ii, started_dragging, {draw_pos.x + kf_tab_width / 2.0f, draw_pos.y});
|
|
||||||
|
|
||||||
ImGui::PopID();
|
ImGui::Button(is_sel ? "s" : "k", {kf_tab_width, row_height * .8f});
|
||||||
}
|
|
||||||
for (auto it = chain.segments.begin(); it != chain.segments.end(); it++) {
|
kf_drag_btn_handler(key_loop_target, dragging, chain, frame, is_sel,
|
||||||
auto nit = std::next(it);
|
sel_it, segment, val, ii, started_dragging,
|
||||||
if (nit != chain.segments.end() && it->value != nit->value) {
|
{draw_pos.x + kf_tab_width / 2.0f, draw_pos.y});
|
||||||
window->DrawList->AddRectFilled({TimelineFrameToScreenView(view_left, view_amt, view_width, it->frame,
|
|
||||||
s.frame_max) + begin_tl.x + kf_tab_width / 2.0f,
|
ImGui::PopID();
|
||||||
begin_tl.y + row_height / 2.0f - 2.0f}, {TimelineFrameToScreenView(view_left, view_amt, view_width, nit->frame,
|
}
|
||||||
s.frame_max) + begin_tl.x - kf_tab_width / 2.0f,
|
for (auto it = chain.segments.begin(); it != chain.segments.end(); it++) {
|
||||||
begin_tl.y + row_height / 2.0f + 2.0f},
|
auto nit = std::next(it);
|
||||||
std::ranges::find(chain.selected, std::distance(chain.segments.begin(), it)) != chain.selected.end() &&
|
if (nit != chain.segments.end() && it->value != nit->value) {
|
||||||
std::ranges::find(chain.selected, std::distance(chain.segments.begin(), nit)) != chain.selected.end() ? 0x88FFAAAA : 0x44AAAAAA);
|
window->DrawList->AddRectFilled(
|
||||||
|
{TimelineFrameToScreenView(view_left, view_amt, view_width,
|
||||||
|
it->frame,
|
||||||
|
s.frame_max) + begin_tl.x +
|
||||||
|
kf_tab_width / 2.0f,
|
||||||
|
begin_tl.y + row_height / 2.0f - 2.0f},
|
||||||
|
{TimelineFrameToScreenView(view_left, view_amt, view_width,
|
||||||
|
nit->frame,
|
||||||
|
s.frame_max) + begin_tl.x -
|
||||||
|
kf_tab_width / 2.0f,
|
||||||
|
begin_tl.y + row_height / 2.0f + 2.0f},
|
||||||
|
std::ranges::find(chain.selected,
|
||||||
|
std::distance(chain.segments.begin(), it)) !=
|
||||||
|
chain.selected.end() &&
|
||||||
|
std::ranges::find(chain.selected,
|
||||||
|
std::distance(chain.segments.begin(), nit)) !=
|
||||||
|
chain.selected.end() ? 0x88FFAAAA : 0x44AAAAAA);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::SetCursorScreenPos(begin_tl);
|
ImGui::SetCursorScreenPos(begin_tl);
|
||||||
tl_bg_handler();
|
tl_bg_handler();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
|
@ -1266,8 +1310,6 @@ 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};
|
||||||
|
|
||||||
|
@ -1330,7 +1372,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 (ImPlot::BeginPlot("uniform", {view_width, ImGui::GetContentRegionAvail().y}, ImPlotFlags_CanvasOnly | ImPlotFlags_NoFrame | ImPlotFlags_NoInputs)) {
|
if (ImPlot::BeginPlot("uniform", {view_width, ImGui::GetContentRegionAvail().y}, ImPlotFlags_NoTitle | ImPlotFlags_NoMenus | ImPlotFlags_NoBoxSelect | ImPlotFlags_NoMouseText | ImPlotFlags_NoFrame | ImPlotFlags_NoInputs)) {
|
||||||
static bool started_dragging = false, dragging = false;
|
static bool started_dragging = false, dragging = false;
|
||||||
|
|
||||||
ImPlot::SetupAxis(ImAxis_X1, "time", ImPlotAxisFlags_NoHighlight | ImPlotAxisFlags_NoLabel | ImPlotAxisFlags_NoGridLines);
|
ImPlot::SetupAxis(ImAxis_X1, "time", ImPlotAxisFlags_NoHighlight | ImPlotAxisFlags_NoLabel | ImPlotAxisFlags_NoGridLines);
|
||||||
|
@ -1354,6 +1396,7 @@ namespace K::UI {
|
||||||
if (!std::holds_alternative<Plugboard::Chain*>(n))
|
if (!std::holds_alternative<Plugboard::Chain*>(n))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
ImGui::PushID(&n);
|
||||||
auto& [chain, chain_copy] = std::get<Plugboard::Chain*>(n)->extra;
|
auto& [chain, chain_copy] = std::get<Plugboard::Chain*>(n)->extra;
|
||||||
Plugboard::ConnectInfo i {n, 0}; // it's a chain -- 0 is out
|
Plugboard::ConnectInfo i {n, 0}; // it's a chain -- 0 is out
|
||||||
|
|
||||||
|
@ -1391,7 +1434,11 @@ namespace K::UI {
|
||||||
f64 x = frame, y = v;
|
f64 x = frame, y = v;
|
||||||
ImVec2 k_pos = ImPlot::PlotToPixels(x, y);
|
ImVec2 k_pos = ImPlot::PlotToPixels(x, y);
|
||||||
|
|
||||||
ImPlot::Annotation(x, y, {1.0f, 1.0f, 1.0f, 1.0f}, {15.0f, 0.0f}, true);
|
const bool is_last = ii + 1 == key_loop_target->segments.size();
|
||||||
|
if (is_last)
|
||||||
|
ImPlot::Annotation(x, y, {1.0f, 1.0f, 1.0f, 1.0f}, {15.0f, 0.0f}, true);
|
||||||
|
else
|
||||||
|
ImPlot::Annotation(x, y, {1.0f, 1.0f, 1.0f, 1.0f}, {15.0f, 0.0f}, true, "%.2f, %.2f, %s", x, y, Plugboard::K_Interpolation_Names[segment.interp]);
|
||||||
ImGui::SetCursorScreenPos(k_pos - ImVec2{10.0f / 2.0f, 10.0f / 2.0f});
|
ImGui::SetCursorScreenPos(k_pos - ImVec2{10.0f / 2.0f, 10.0f / 2.0f});
|
||||||
|
|
||||||
ImGui::PushStyleColor(ImGuiCol_Button, is_sel ? 0xFFFFFF88 : 0xFFAA7777);
|
ImGui::PushStyleColor(ImGuiCol_Button, is_sel ? 0xFFFFFF88 : 0xFFAA7777);
|
||||||
|
@ -1401,7 +1448,7 @@ namespace K::UI {
|
||||||
kf_drag_btn_handler(key_loop_target, dragging, chain, frame, is_sel,
|
kf_drag_btn_handler(key_loop_target, dragging, chain, frame, is_sel,
|
||||||
sel_it, segment, v, ii, started_dragging, k_pos);
|
sel_it, segment, v, ii, started_dragging, k_pos);
|
||||||
|
|
||||||
if (segment.interp == Plugboard::K_I_CubicBezier && ii + 1 < key_loop_target->segments.size()) {
|
if (segment.interp == Plugboard::K_I_CubicBezier && !is_last) {
|
||||||
const auto& [k_nxt, val_nxt, _] = (key_loop_target->segments)[ii + 1];
|
const auto& [k_nxt, val_nxt, _] = (key_loop_target->segments)[ii + 1];
|
||||||
i32 frame_nxt = k_nxt;
|
i32 frame_nxt = k_nxt;
|
||||||
f64 v_nxt = val_nxt;
|
f64 v_nxt = val_nxt;
|
||||||
|
@ -1451,10 +1498,10 @@ namespace K::UI {
|
||||||
f64 xs[2] = {static_cast<f64>(frame), p2x},
|
f64 xs[2] = {static_cast<f64>(frame), p2x},
|
||||||
ys[2] = {v, p2y};
|
ys[2] = {v, p2y};
|
||||||
|
|
||||||
ImPlot::PlotLine("cb tangent", xs, ys, 2);
|
ImPlot::PlotLine("###cb tangent", xs, ys, 2);
|
||||||
xs[0] = p3x; xs[1] = static_cast<f64>(frame_nxt);
|
xs[0] = p3x; xs[1] = static_cast<f64>(frame_nxt);
|
||||||
ys[0] = p3y; ys[1] = v_nxt;
|
ys[0] = p3y; ys[1] = v_nxt;
|
||||||
ImPlot::PlotLine("cb tangent", xs, ys, 2);
|
ImPlot::PlotLine("###cb tangent", xs, ys, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
|
@ -1467,7 +1514,7 @@ namespace K::UI {
|
||||||
.s = s,
|
.s = s,
|
||||||
.connected_v = i
|
.connected_v = i
|
||||||
};
|
};
|
||||||
ImPlot::PlotLineG("v", [](int idx, void *user_data) -> ImPlotPoint {
|
ImPlot::PlotLineG(s.plugboard.nodes.GetName(static_cast<Plugboard::K_P_Nodes>(n.index())), [](int idx, void *user_data) -> ImPlotPoint {
|
||||||
PlotInfo i = *(PlotInfo *) user_data;
|
PlotInfo i = *(PlotInfo *) user_data;
|
||||||
f32 x = i.begin + (i.end - i.begin) * static_cast<f32>(idx) / static_cast<f32>(i.samples);
|
f32 x = i.begin + (i.end - i.begin) * static_cast<f32>(idx) / static_cast<f32>(i.samples);
|
||||||
CompositionState ss = i.s;
|
CompositionState ss = i.s;
|
||||||
|
@ -1478,6 +1525,7 @@ namespace K::UI {
|
||||||
Plugboard::ConvertValue(Plugboard::Eval(ss, i.connected_v),
|
Plugboard::ConvertValue(Plugboard::Eval(ss, i.connected_v),
|
||||||
Plugboard::T_Float, good))};
|
Plugboard::T_Float, good))};
|
||||||
}, &info, info.samples);
|
}, &info, info.samples);
|
||||||
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
ImPlot::EndPlot();
|
ImPlot::EndPlot();
|
||||||
|
|
||||||
|
@ -1554,6 +1602,15 @@ namespace K::UI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tl_clear_selection_request)
|
||||||
|
for (auto& p : s.plugboard.selected_nodes)
|
||||||
|
if (auto *n = std::get_if<Plugboard::Chain*>(&p)){
|
||||||
|
auto& [chain, _] = (*n)->extra;
|
||||||
|
chain.selected.clear();
|
||||||
|
}
|
||||||
|
if (tl_clear_selection_request_this_frame && tl_clear_selection_request)
|
||||||
|
tl_clear_selection_request = false;
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue