git.haldean.org qb / 647063e
everything's different Haldean Brown 4 months ago
16 changed file(s) with 201 addition(s) and 35 deletion(s). Raw diff Collapse all Expand all
0 ((c++-mode
1 . ((compile-command . "cmake --build build")
2 ))
3 )
0 ;;; Directory Local Variables
1 ;;; For more information see (info "(emacs) Directory Variables")
2
3 ((c++-mode . ((c-basic-offset . 2)
4 (compile-command . "cmake --build build"))))
4747 else()
4848 add_library(sokol STATIC sokol/sokol.c ${SOKOL_HEADERS})
4949 if (CMAKE_SYSTEM_NAME STREQUAL Linux)
50 target_link_libraries(sokol INTERFACE X11 Xi Xcursor GL dl m)
50 target_link_libraries(sokol INTERFACE X11 Xi Xcursor GL dl m asound)
5151 target_link_libraries(sokol PUBLIC Threads::Threads)
5252 endif()
5353 endif()
6969 colors.hpp
7070 cue.cpp
7171 cue.hpp
72 fonts.cpp
73 fonts.hpp
74 nodeui.cpp
75 nodeui.hpp
7276 qb.cpp
7377 qb.hpp
7478 qbshim.cpp
7579 qbshim.hpp
76 nodeui.cpp
77 nodeui.hpp
7880 task.cpp
7981 task.hpp
82 ui.cpp
83 ui.hpp
8084 AudioFile/AudioFile.h
8185 )
8286 if (MSVC)
Binary diff not shown
1010 case waveform: return "waveform";
1111 case playhead: return "playhead";
1212 case hit: return "track hit";
13 case ruler: return "time ruler";
14 case ruler_text: return "time ruler text";
1315 }
1416 return "unknown";
1517 }
1618
1719 void setdefault() {
18 colors[color::background] = IM_COL32(99, 0, 29, 255);
19 colors[color::waveform] = IM_COL32(255, 158, 0, 255);
20 colors[color::playhead] = IM_COL32(154, 0, 42, 255);
21 colors[color::hit] = IM_COL32(0, 255, 255, 255);
20 colors[color::background] = IM_COL32(5, 2, 3, 255);
21 colors[color::waveform] = IM_COL32(255, 45, 0, 255);
22 colors[color::playhead] = IM_COL32(255, 0, 128, 125);
23 colors[color::hit] = IM_COL32(255, 203, 0, 255);
24 colors[color::ruler] = IM_COL32(214, 14, 96, 255);
25 colors[color::ruler_text] = IM_COL32(255, 255, 255, 255);
26
27 ImVec4* colors = ImGui::GetStyle().Colors;
28 colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
29 colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
30 colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f);
31 colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
32 colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f);
33 colors[ImGuiCol_Border] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f);
34 colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
35 colors[ImGuiCol_FrameBg] = ImVec4(0.16f, 0.16f, 0.16f, 0.54f);
36 colors[ImGuiCol_FrameBgHovered] = ImVec4(0.30f, 0.30f, 0.30f, 0.40f);
37 colors[ImGuiCol_FrameBgActive] = ImVec4(1.00f, 0.00f, 0.16f, 1.00f);
38 colors[ImGuiCol_TitleBg] = ImVec4(0.04f, 0.04f, 0.04f, 1.00f);
39 colors[ImGuiCol_TitleBgActive] = ImVec4(1.00f, 0.00f, 0.16f, 1.00f);
40 colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f);
41 colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f);
42 colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f);
43 colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f);
44 colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
45 colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f);
46 colors[ImGuiCol_CheckMark] = ImVec4(1.00f, 0.00f, 0.16f, 1.00f);
47 colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 0.00f, 0.16f, 1.00f);
48 colors[ImGuiCol_SliderGrabActive] = ImVec4(1.00f, 0.00f, 0.16f, 1.00f);
49 colors[ImGuiCol_Button] = ImVec4(0.52f, 0.52f, 0.52f, 0.40f);
50 colors[ImGuiCol_ButtonHovered] = ImVec4(0.22f, 0.22f, 0.22f, 1.00f);
51 colors[ImGuiCol_ButtonActive] = ImVec4(1.00f, 0.00f, 0.16f, 1.00f);
52 colors[ImGuiCol_Header] = ImVec4(0.62f, 0.62f, 0.62f, 0.31f);
53 colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.45f, 0.80f);
54 colors[ImGuiCol_HeaderActive] = ImVec4(1.00f, 0.00f, 0.16f, 1.00f);
55 colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.43f, 0.43f, 0.50f);
56 colors[ImGuiCol_SeparatorHovered] = ImVec4(0.75f, 0.00f, 0.10f, 0.78f);
57 colors[ImGuiCol_SeparatorActive] = ImVec4(1.00f, 0.00f, 0.16f, 1.00f);
58 colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.24f);
59 colors[ImGuiCol_ResizeGripHovered] = ImVec4(1.00f, 1.00f, 1.00f, 0.67f);
60 colors[ImGuiCol_ResizeGripActive] = ImVec4(1.00f, 0.00f, 0.16f, 1.00f);
61 colors[ImGuiCol_Tab] = ImVec4(1.00f, 0.00f, 0.16f, 0.44f);
62 colors[ImGuiCol_TabHovered] = ImVec4(1.00f, 0.00f, 0.16f, 0.80f);
63 colors[ImGuiCol_TabActive] = ImVec4(1.00f, 0.00f, 0.16f, 1.00f);
64 colors[ImGuiCol_TabUnfocused] = ImVec4(0.17f, 0.10f, 0.15f, 0.97f);
65 colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.47f, 0.18f, 0.28f, 1.00f);
66 colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
67 colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
68 colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
69 colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
70 colors[ImGuiCol_TableHeaderBg] = ImVec4(0.19f, 0.19f, 0.20f, 1.00f);
71 colors[ImGuiCol_TableBorderStrong] = ImVec4(0.31f, 0.31f, 0.35f, 1.00f);
72 colors[ImGuiCol_TableBorderLight] = ImVec4(0.23f, 0.23f, 0.25f, 1.00f);
73 colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
74 colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.06f);
75 colors[ImGuiCol_TextSelectedBg] = ImVec4(1.00f, 0.00f, 0.16f, 1.00f);
76 colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
77 colors[ImGuiCol_NavHighlight] = ImVec4(1.00f, 0.00f, 0.16f, 1.00f);
78 colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
79 colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
80 colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
2281 }
2382
2483 void showeditor() {
66 waveform,
77 playhead,
88 hit,
9 ruler,
10 ruler_text,
911 ncolors
1012 };
1113
Binary diff not shown
0 #include "cimgui/imgui/imgui.h"
1 #include "sokol/sokol_gfx.h"
2
3 namespace qb {
4 void initfonts() {
5 ImGui::GetIO().Fonts->AddFontFromFileTTF("data/InputMono-Regular.ttf", 14);
6
7 unsigned char* font_pixels;
8 int font_width, font_height;
9 ImGui::GetIO().Fonts->GetTexDataAsRGBA32(
10 &font_pixels, &font_width, &font_height);
11
12 sg_image_desc img_desc;
13 memset(&img_desc, 0, sizeof(img_desc));
14 img_desc.width = font_width;
15 img_desc.height = font_height;
16 img_desc.pixel_format = SG_PIXELFORMAT_RGBA8;
17 img_desc.wrap_u = SG_WRAP_CLAMP_TO_EDGE;
18 img_desc.wrap_v = SG_WRAP_CLAMP_TO_EDGE;
19 img_desc.min_filter = SG_FILTER_LINEAR;
20 img_desc.mag_filter = SG_FILTER_LINEAR;
21 img_desc.data.subimage[0][0].ptr = font_pixels;
22 img_desc.data.subimage[0][0].size =
23 (size_t)(font_width * font_height) * sizeof(uint32_t);
24 img_desc.label = "input-serif-12";
25 sg_image img = sg_make_image(&img_desc);
26 ImGui::GetIO().Fonts->TexID = (ImTextureID)(uintptr_t) img.id;
27 }
28 }
0 namespace qb {
1 void initfonts();
2 }
2323 stm_setup();
2424 simgui_setup(&(simgui_desc_t){
2525 .max_vertices = 524288,
26 .no_default_font = true,
2627 });
2728
2829 // initial clear color
2930 state.pass_action = (sg_pass_action) {
30 .colors[0] = { .action = SG_ACTION_CLEAR, .value = { 0.04f, 0.02f, 0.045f, 1.0 } }
31 .colors[0] = { .action = SG_ACTION_CLEAR, .value = { 0.0f, 0.0f, 0.0f, 1.0 } }
3132 };
3233 state.context = qb_init();
3334 }
106106 std::lower_bound(track.hits.begin(),
107107 track.hits.end(),
108108 (int) ctx->playhead());
109 if (iter != track.hits.end() && iter != track.hits.begin()) {
109 if (iter != track.hits.begin() && !track.hits.empty()) {
110110 hitdist = (float) (ctx->playhead() - *std::prev(iter));
111111 }
112112 }
22 #include "audionode.hpp"
33 #include "colors.hpp"
44 #include "cue.hpp"
5 #include "fonts.hpp"
56 #include "nodeui.hpp"
67 #include "task.hpp"
8 #include "ui.hpp"
79
810 #include "sokol/sokol_app.h"
911 #include "sokol/sokol_audio.h"
2022 }
2123
2224 context::context() {
25 qb::initfonts();
26
2327 _nodes.push_back(std::make_shared<qb::audio_node>(this, "test/coc-mono.wav"));
2428
2529 auto cuenode = std::make_shared<qb::cue_node>(this, "test/cues.txt");
4145 ImGui::GetIO().KeyRepeatRate = 1.0f / _framerate;
4246 }
4347
44 int context::frame2pixel(double frame) {
48 int context::frame2pixel(double frame) const {
4549 const double off = frame - _playhead;
4650 const double ndc = off / (double)_visrad;
4751 const int px = (int) round(_width * (ndc + 1) / 2.0);
5963
6064 ImGui::SetNextWindowPos(ImVec2(0, 0));
6165 ImGui::SetNextWindowSize(ImVec2((float) _width, (float) _height));
62 ImGui::PushStyleColor(ImGuiCol_WindowBg, qb::theme::colors[qb::theme::background]);
66 ImGui::PushStyleColor(
67 ImGuiCol_WindowBg,
68 qb::theme::colors[qb::theme::background]);
6369 ImGui::Begin("MainWindow", nullptr,
6470 ImGuiWindowFlags_NoDecoration);
71
72 qb::draw_ruler(*this);
73 qb::draw_playhead(*this);
6574
6675 double minframe = 0;
6776 double maxframe = 0;
103112 _playhead = clamp((double)_playhead + framedist, minframe, maxframe);
104113 _visrad = clamp((double)_visrad + zoomdist, 3.0, maxframe - minframe);
105114 }
106 if (ImGui::IsMouseDragging(ImGuiMouseButton_Left)) {
107 const ImVec2 delta = ImGui::GetMouseDragDelta(ImGuiMouseButton_Left);
108
109 }
110
111 // draw _playhead
112 {
113 ImDrawList * const drawlist = ImGui::GetWindowDrawList();
114 const float f0x = (float) frame2pixel(_playhead);
115 const float f1x = (float) frame2pixel(_playhead + 1);
116 if (f1x > 0 && f1x != f0x) {
117 drawlist->AddRectFilled(ImVec2(f0x, 0.0), ImVec2(f1x, (float) _height),
118 qb::theme::colors[qb::theme::color::playhead]);
119 } else {
120 drawlist->AddLine(ImVec2(f0x, 0), ImVec2(f0x, (float) _height),
121 qb::theme::colors[qb::theme::color::playhead]);
122 }
123 }
124115
125116 for (const auto &n : _nodes) {
126117 draw_node(n);
127118 }
119
128120 ImGui::End();
129121 ImGui::PopStyleColor();
130122
6060 context &operator=(const context &) = delete;
6161 context &operator=(context &&) = delete;
6262
63 // get/set the playback framerate (not the UI frame rate!)
6364 int framerate() const { return _framerate; }
6465 void framerate(int fr) { _framerate = fr; }
6566
67 // visible radius around playhead
6668 double visrad() const { return _visrad; }
69 // location of the playhead (in playback frames)
6770 double playhead() const { return _playhead; }
71
72 // for ui animations, incremented (with wraparound) on every UI frame.
6873 uint32_t spinstep() const { return _spinstep; }
74
75 // width and height of the qb window
6976 int width() const { return _width; }
7077 int height() const { return _height; }
7178
79 // draws a frame at the given width and height
7280 void frame(int width, int height);
81
82 // kills the event loop
7383 void shutdown();
7484
75 int frame2pixel(double frame);
85 // translates a playback frame to a UI x-coordinate
86 int frame2pixel(double frame) const;
7687
7788 private:
7889 void initaudio();
8596 int _width = 0;
8697 int _height = 0;
8798
88 // for ui animations
8999 uint32_t _spinstep = 0;
90100
91101 bool _audioinit = false;
11 #define SOKOL_IMPL
22 #define SOKOL_IMGUI_IMPL
33 #define SOKOL_AUDIO_IMPL
4 #define SOKOL_LOG
45 #if defined(_WIN32)
56 #define SOKOL_D3D11
67 #elif defined(__EMSCRIPTEN__)
66 {
77
88 using task = std::function<void(void)>;
9
910 struct taskpool {
1011 static taskpool& get();
12
13 // submit a task that is executed once on a separate thread
1114 void submit_async(const task &t);
15
16 // submit a task that is executed at the end of the current frame, in the
17 // main thread.
1218 void submit_frame(const task &t);
19
20 // execute all frame tasks (only should be called from the main thread)
1321 void frame();
1422
1523 private:
0 #include "ui.hpp"
1
2 #include "colors.hpp"
3
4 #include "cimgui/imgui/imgui.h"
5
6 namespace qb {
7 void draw_playhead(const qb::context &ctx)
8 {
9 ImDrawList * const drawlist = ImGui::GetWindowDrawList();
10 const float f0x = (float) ctx.frame2pixel(ctx.playhead());
11 const float f1x = (float) ctx.frame2pixel(ctx.playhead() + 1);
12 if (f1x > 0 && f1x != f0x) {
13 drawlist->AddRectFilled(
14 ImVec2(f0x, 0.0), ImVec2(f1x, (float) ctx.height()),
15 qb::theme::colors[qb::theme::color::playhead]);
16 } else {
17 drawlist->AddLine(
18 ImVec2(f0x, 0), ImVec2(f0x, (float) ctx.height()),
19 qb::theme::colors[qb::theme::color::playhead]);
20 }
21 }
22
23 static constexpr float ruler_height = 16;
24
25 void draw_ruler(const qb::context &ctx)
26 {
27 ImDrawList * const drawlist = ImGui::GetWindowDrawList();
28 const float playheadx = (float) ctx.frame2pixel(ctx.playhead() + 1);
29 /*
30 drawlist->AddRectFilled(
31 ImVec2(0, 0), ImVec2(ctx.width(), ruler_height),
32 qb::theme::colors[qb::theme::color::ruler]);
33 */
34
35 char buf[32] = {};
36 snprintf(buf, 32, "%.0f", ctx.playhead());
37 drawlist->AddText(
38 ImGui::GetIO().Fonts->Fonts[0],
39 ruler_height,
40 ImVec2(playheadx, 30),
41 qb::theme::color::ruler,
42 "hello!");
43 }
44 }
0 #ifndef qb_ui_hpp
1 #define qb_ui_hpp
2
3 #include "qb.hpp"
4
5 namespace qb {
6 void draw_playhead(const qb::context &ctx);
7 void draw_ruler(const qb::context &ctx);
8 }
9
10 #endif