diff --git a/Keishiki/Keishiki.cpp b/Keishiki/Keishiki.cpp index 50036e7..6897e97 100644 --- a/Keishiki/Keishiki.cpp +++ b/Keishiki/Keishiki.cpp @@ -14,8 +14,8 @@ namespace { SDL_Window *window; - u16 window_width = 2200; - u16 window_height = 1200; + u16 window_width = 1920; + u16 window_height = 1080; u64 init_time, last_time, current_time, delta_t; u32 frame; diff --git a/Keishiki/PlugboardGraph.cpp b/Keishiki/PlugboardGraph.cpp index cbb44b6..96b96b7 100644 --- a/Keishiki/PlugboardGraph.cpp +++ b/Keishiki/PlugboardGraph.cpp @@ -23,4 +23,126 @@ namespace K::PlugboardGraph { static T_Map::type table[] = {f32{}, i32{}, RGBA{}, XY{}, XYZ{}, String{}}; return table[i]; } + + T_Map::type Eval(const CompState& s, const ConnectInfo& info) { + Vector::type> pack; + for (u32 i = 0; i < info.p->inputs_fed.size(); i++) { + bool good; + auto val = ConvertValue(std::visit([&s](auto&& arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) + return Eval(s,arg); + else if constexpr (std::is_same_v::type>) + return arg; + }, info.p->inputs_fed[i]), info.p->node->in[i].type, good); + if (good) { + pack.push_back(val); + } + else return {}; // todo panic! + } + return info.p->node->fetch[info.index](s, pack); + } + + NodeInstance MakeInstance(Node& n) { + Vector::type, ConnectInfo>> inp; + Vector> out; + for (const auto& t : n.in) + inp.emplace_back(expand_type(t.type)); + for (auto t : n.out) + out.emplace_back(); + return { + .node = &n, + .inputs_fed = std::move(inp), + .outputs_going = std::move(out) + }; + } + + T_Map::type ConvertValue(const T_Map::type& v, Type target, bool& good) { + good = true; + return std::visit([&good, target](auto&& arg) -> T_Map::type { + using T = std::decay_t; + if constexpr (std::is_same_v::type>) { + switch (target) { + case T_Float: + return arg; + case T_Int: + return static_cast::type>(arg); + case T_RGBA: + return RGBA{ arg, arg, arg, arg }; + case T_XY: + return XY{ arg, arg }; + case T_XYZ: + return XYZ{ arg, arg, arg }; + case T_String: + return VarToString(arg); + case T_Count: + good = false; + return {}; + } + } + else if constexpr (std::is_same_v::type>) { + auto f = static_cast::type>(arg); + switch (target) { + case T_Float: + return f; + case T_Int: + return arg; + case T_RGBA: + return RGBA{ f, f, f, f }; + case T_XY: + return XY{ f, f }; + case T_XYZ: + return XYZ{ f, f, f }; + case T_String: + return VarToString(arg); + case T_Count: + good = false; + return {}; + } + } + else if constexpr (std::is_same_v::type>) { + switch (target) { + case T_RGBA: + return arg; + case T_String: + return VarToString(arg); + default: + good = false; + return {}; + } + } + else if constexpr (std::is_same_v::type>) { + switch (target) { + case T_XY: + return arg; + case T_String: + return VarToString(arg); + default: + good = false; + return {}; + } + } + else if constexpr (std::is_same_v::type>) { + switch (target) { + case T_XYZ: + return arg; + case T_String: + return VarToString(arg); + default: + good = false; + return {}; + } + } + else if constexpr (std::is_same_v::type>) { + switch (target) { + case T_String: + return arg; + default: + good = false; + return {}; + } + } + return {}; + }, v); + } } diff --git a/Keishiki/ShaderGraph.cpp b/Keishiki/ShaderGraph.cpp index fde00e2..54e5207 100644 --- a/Keishiki/ShaderGraph.cpp +++ b/Keishiki/ShaderGraph.cpp @@ -36,4 +36,9 @@ namespace K::ShaderGraph { if (RGBA_node->node->out_types[RGBA_node_out_index] != Type::T_RGBA) return {}; return BuildNode(*RGBA_node); } + + T_Map::type expand_type(Type i) { + static constexpr T_Map::type table[] = {f32{}, i32{}, RGBA{}, XY{}, XYZ{}}; + return table[i]; + } } diff --git a/Keishiki/UI.cpp b/Keishiki/UI.cpp index c1c4670..312495c 100644 --- a/Keishiki/UI.cpp +++ b/Keishiki/UI.cpp @@ -20,8 +20,7 @@ namespace { draw_comp = true, draw_interpolation = true, draw_properties = true, - draw_assets = true, - draw_color = true; + draw_assets = true; const f32 row_height = 20.0f; @@ -796,7 +795,7 @@ namespace K::UI { } ImGui::SetCursorScreenPos(nodes_begin); - if (ImGui::BeginChild("Overlay", {}, false, ImGuiWindowFlags_NoInputs)) { + if (ImGui::BeginChild("Overlay", {table_left - ImGui::GetWindowPos().x, 0.0f}, false, ImGuiWindowFlags_NoInputs)) { for (auto &[_, link]: s.plugboard.links_pos) for (auto &sink: link.sinks) ImGui::GetCurrentWindow()->DrawList->AddBezierCubic(link.source, @@ -827,8 +826,9 @@ namespace K::UI { void Shader(CompState& s) { if (ImGui::Begin("Shader", &draw_shader)) { if (s.active == -1) - ImGui::Text("No active layer."); + ImGui::TextUnformatted("No active layer."); else { + ImGui::Text("Editing Layer %u: %s", s.active, s.layers[s.active].name.c_str()); static i32 type_current = 0; static String name{}; if (ImGui::Button("Add Uniform") && !name.empty() && !isdigit(name[0]) && !(name[0] == 'f' && name.length() == 1)) { @@ -892,7 +892,6 @@ namespace K::UI { } ImGui::EndTable(); } - ImGui::Text("Editing Layer %u: %s", s.active, s.layers[s.active].name.c_str()); ImGui::InputTextMultiline("##source", &s.layers[s.active].track.shader, ImVec2(-FLT_MIN, ImGui::GetContentRegionAvail().y - 25.0f), ImGuiInputTextFlags_AllowTabInput); if (ImGui::Button("Submit Shader")) s.layers[s.active].track.compile(); @@ -902,8 +901,60 @@ namespace K::UI { } void Interpolation(CompState& s) { - if (ImGui::Begin("Interpolation", &draw_interpolation)) { + if (ImGui::Begin("Interpolation", &draw_interpolation, ImGuiWindowFlags_NoScrollbar)) { + ImGuiIO& io = ImGui::GetIO(); + 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; + + 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, 15.0f}, 0xFFFFFFFF, "1.0"); + + 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(); + + ImGui::Button("Apply"); } ImGui::End(); } @@ -922,13 +973,6 @@ namespace K::UI { ImGui::End(); } - void Color(CompState& s) { - if (ImGui::Begin("Color", &draw_color)) { - - } - ImGui::End(); - } - void Draw(u32 frame, CompState& s) { ImGui_ImplSDL2_NewFrame(); ImGui_Implbgfx_NewFrame(); @@ -946,7 +990,6 @@ namespace K::UI { if (draw_interpolation) Interpolation(s); if (draw_properties) Properties(s); if (draw_assets) Assets(s); - if (draw_color) Color(s); if (save_called && ready_frame == frame) { stbi_write_png("frame.png", static_cast(s.width), static_cast(s.height), 4, save_buffer, static_cast(s.width) * 4); diff --git a/Keishiki/include/Graphics.h b/Keishiki/include/Graphics.h index 9514533..05dff3f 100644 --- a/Keishiki/include/Graphics.h +++ b/Keishiki/include/Graphics.h @@ -114,7 +114,7 @@ namespace K::Graphics { "Hue", "Saturation", - "Color", + "Colour", "Luminosity", "Invalid" diff --git a/Keishiki/include/PlugboardGraph.h b/Keishiki/include/PlugboardGraph.h index 7ac05ff..c83bec0 100644 --- a/Keishiki/include/PlugboardGraph.h +++ b/Keishiki/include/PlugboardGraph.h @@ -118,127 +118,11 @@ namespace K::PlugboardGraph { }; - inline NodeInstance MakeInstance(Node& n) { - Vector::type, ConnectInfo>> inp; - Vector> out; - for (const auto& t : n.in) - inp.emplace_back(expand_type(t.type)); - for (auto t : n.out) - out.emplace_back(); - return { - .node = &n, - .inputs_fed = std::move(inp), - .outputs_going = std::move(out) - }; - } + NodeInstance MakeInstance(Node& n); - inline T_Map::type ConvertValue(const T_Map::type& v, Type target, bool& good) { - good = true; - return std::visit([&good, target](auto&& arg) -> T_Map::type { - using T = std::decay_t; - if constexpr (std::is_same_v::type>) { - switch (target) { - case T_Float: - return arg; - case T_Int: - return static_cast::type>(arg); - case T_RGBA: - return RGBA{ arg, arg, arg, arg }; - case T_XY: - return XY{ arg, arg }; - case T_XYZ: - return XYZ{ arg, arg, arg }; - case T_String: - return VarToString(arg); - case T_Count: - good = false; - return {}; - } - } - else if constexpr (std::is_same_v::type>) { - auto f = static_cast::type>(arg); - switch (target) { - case T_Float: - return f; - case T_Int: - return arg; - case T_RGBA: - return RGBA{ f, f, f, f }; - case T_XY: - return XY{ f, f }; - case T_XYZ: - return XYZ{ f, f, f }; - case T_String: - return VarToString(arg); - case T_Count: - good = false; - return {}; - } - } - else if constexpr (std::is_same_v::type>) { - switch (target) { - case T_RGBA: - return arg; - case T_String: - return VarToString(arg); - default: - good = false; - return {}; - } - } - else if constexpr (std::is_same_v::type>) { - switch (target) { - case T_XY: - return arg; - case T_String: - return VarToString(arg); - default: - good = false; - return {}; - } - } - else if constexpr (std::is_same_v::type>) { - switch (target) { - case T_XYZ: - return arg; - case T_String: - return VarToString(arg); - default: - good = false; - return {}; - } - } - else if constexpr (std::is_same_v::type>) { - switch (target) { - case T_String: - return arg; - default: - good = false; - return {}; - } - } - return {}; - }, v); - } + T_Map::type ConvertValue(const T_Map::type& v, Type target, bool& good); - inline T_Map::type Eval(const CompState& s, const ConnectInfo& info) { - Vector::type> pack; - for (u32 i = 0; i < info.p->inputs_fed.size(); i++) { - bool good; - auto val = ConvertValue(std::visit([&s](auto&& arg) { - using T = std::decay_t; - if constexpr (std::is_same_v) - return Eval(s,arg); - else if constexpr (std::is_same_v::type>) - return arg; - }, info.p->inputs_fed[i]), info.p->node->in[i].type, good); - if (good) { - pack.push_back(val); - } - else return {}; // todo panic! - } - return info.p->node->fetch[info.index](s, pack); - } + T_Map::type Eval(const CompState& s, const ConnectInfo& info); struct LinksFromSource { ImVec2 source; diff --git a/Keishiki/include/ShaderGraph.h b/Keishiki/include/ShaderGraph.h index 3127f3a..c13c309 100644 --- a/Keishiki/include/ShaderGraph.h +++ b/Keishiki/include/ShaderGraph.h @@ -46,10 +46,7 @@ namespace K::ShaderGraph { }; String VarToString(const T_Map::type& var); - inline T_Map::type expand_type(Type i) { - static constexpr T_Map::type table[] = {f32{}, i32{}, ShaderGraph::RGBA{}, ShaderGraph::XY{}, ShaderGraph::XYZ{}}; - return table[i]; - } + T_Map::type expand_type(Type i); struct Node; struct InSlot {