From 06cb6d831931fa8499d6610568f7927b0a6461c7 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 28 Oct 2024 02:07:47 +0100 Subject: [PATCH] distance to closest node displayed, timing problems with midi notes being sent 1 to 3ms too early, or too late --- include/raygui/dark/README.md | 27 ------------------ include/raygui/dark/style_dark.h | 48 ++++++++++++++++---------------- src/datatypes.h | 1 + src/main.cpp | 4 +-- src/midi.h | 4 +-- src/moveable.h | 1 + src/node-manager.h | 16 +++++++++++ src/signal-manager.h | 16 +++++++---- src/signal.h | 2 +- src/state-manager.h | 6 ++-- src/ui.h | 13 +++++---- 11 files changed, 68 insertions(+), 70 deletions(-) delete mode 100644 include/raygui/dark/README.md diff --git a/include/raygui/dark/README.md b/include/raygui/dark/README.md deleted file mode 100644 index c3595fc..0000000 --- a/include/raygui/dark/README.md +++ /dev/null @@ -1,27 +0,0 @@ -## style: dark - -Classical dark style with an extra high-def colour touch! Elegant and professional, perfect for the expensive tools! - -![dark style table](style_dark.png) - -## style: provided files - -Several options are provided to add the style to a `raygui` application, choose the one that better fits the project. - -| file name | description | -| :-------- | :---------- | -| `style_dark.rgs` | Binary style file (raygui 4.0), font data compressed (recs, glyphs) | -| `style_dark.txt.rgs` | Text style file, no font data, requires external font provided | -| `style_dark.old.rgs` | Binary style file (raygui 3.x), font data uncompressed (recs, glyphs) | -| `style_dark.h` | Embeddable style as code file, self-contained, includes font data | -| `style_dark.png` | Style table image, contains `rGSf` chunk with binary `rgs` file data | - -## screenshot - -![dark style screen](screenshot.png) - -## about font - -"Pixel Operator" font by de Jayvee Enaguas. - -CC0 1.0 Universal, downloaded from dafont.com: [pixel-operator](https://www.dafont.com/pixel-operator.font) diff --git a/include/raygui/dark/style_dark.h b/include/raygui/dark/style_dark.h index 4047da4..674b125 100644 --- a/include/raygui/dark/style_dark.h +++ b/include/raygui/dark/style_dark.h @@ -7,7 +7,7 @@ // more info and bugs-report: github.com/raysan5/raygui // // feedback and support: ray[at]raylibtech.com // // // -// Copyright (c) 2020-2023 raylib technologies (@raylibtech) // +// Copyright (c) 2020-2024 raylib technologies (@raylibtech) // // // ////////////////////////////////////////////////////////////////////////////////// @@ -15,29 +15,29 @@ // Custom style name: Dark static const GuiStyleProp darkStyleProps[DARK_STYLE_PROPS_COUNT] = { - { 0, 0, (long)0x878787ff }, // DEFAULT_BORDER_COLOR_NORMAL - { 0, 1, (long)0x2c2c2cff }, // DEFAULT_BASE_COLOR_NORMAL - { 0, 2, (long)0xc3c3c3ff }, // DEFAULT_TEXT_COLOR_NORMAL - { 0, 3, (long)0xe1e1e1ff }, // DEFAULT_BORDER_COLOR_FOCUSED - { 0, 4, (long)0x848484ff }, // DEFAULT_BASE_COLOR_FOCUSED - { 0, 5, (long)0x181818ff }, // DEFAULT_TEXT_COLOR_FOCUSED - { 0, 6, (long)0x000000ff }, // DEFAULT_BORDER_COLOR_PRESSED - { 0, 7, (long)0xefefefff }, // DEFAULT_BASE_COLOR_PRESSED - { 0, 8, (long)0x202020ff }, // DEFAULT_TEXT_COLOR_PRESSED - { 0, 9, (long)0x6a6a6aff }, // DEFAULT_BORDER_COLOR_DISABLED - { 0, 10, (long)0x818181ff }, // DEFAULT_BASE_COLOR_DISABLED - { 0, 11, (long)0x606060ff }, // DEFAULT_TEXT_COLOR_DISABLED - { 0, 16, (long)0x00000010 }, // DEFAULT_TEXT_SIZE - { 0, 17, (long)0x00000000 }, // DEFAULT_TEXT_SPACING - { 0, 18, (long)0x9d9d9dff }, // DEFAULT_LINE_COLOR - { 0, 19, (long)0x3c3c3cff }, // DEFAULT_BACKGROUND_COLOR - { 0, 20, (long)0x00000018 }, // DEFAULT_TEXT_LINE_SPACING - { 1, 5, (long)0xf7f7f7ff }, // LABEL_TEXT_COLOR_FOCUSED - { 1, 8, (long)0x898989ff }, // LABEL_TEXT_COLOR_PRESSED - { 4, 5, (long)0xb0b0b0ff }, // SLIDER_TEXT_COLOR_FOCUSED - { 5, 5, (long)0x848484ff }, // PROGRESSBAR_TEXT_COLOR_FOCUSED - { 9, 5, (long)0xf5f5f5ff }, // TEXTBOX_TEXT_COLOR_FOCUSED - { 10, 5, (long)0xf6f6f6ff }, // VALUEBOX_TEXT_COLOR_FOCUSED + { 0, 0, 0x878787ff }, // DEFAULT_BORDER_COLOR_NORMAL + { 0, 1, 0x2c2c2cff }, // DEFAULT_BASE_COLOR_NORMAL + { 0, 2, 0xc3c3c3ff }, // DEFAULT_TEXT_COLOR_NORMAL + { 0, 3, 0xe1e1e1ff }, // DEFAULT_BORDER_COLOR_FOCUSED + { 0, 4, 0x848484ff }, // DEFAULT_BASE_COLOR_FOCUSED + { 0, 5, 0x181818ff }, // DEFAULT_TEXT_COLOR_FOCUSED + { 0, 6, 0x000000ff }, // DEFAULT_BORDER_COLOR_PRESSED + { 0, 7, 0xefefefff }, // DEFAULT_BASE_COLOR_PRESSED + { 0, 8, 0x202020ff }, // DEFAULT_TEXT_COLOR_PRESSED + { 0, 9, 0x6a6a6aff }, // DEFAULT_BORDER_COLOR_DISABLED + { 0, 10, 0x818181ff }, // DEFAULT_BASE_COLOR_DISABLED + { 0, 11, 0x606060ff }, // DEFAULT_TEXT_COLOR_DISABLED + { 0, 16, 0x00000010 }, // DEFAULT_TEXT_SIZE + { 0, 17, 0x00000000 }, // DEFAULT_TEXT_SPACING + { 0, 18, 0x9d9d9dff }, // DEFAULT_LINE_COLOR + { 0, 19, 0x3c3c3cff }, // DEFAULT_BACKGROUND_COLOR + { 0, 20, 0x00000018 }, // DEFAULT_TEXT_LINE_SPACING + { 1, 5, 0xf7f7f7ff }, // LABEL_TEXT_COLOR_FOCUSED + { 1, 8, 0x898989ff }, // LABEL_TEXT_COLOR_PRESSED + { 4, 5, 0xb0b0b0ff }, // SLIDER_TEXT_COLOR_FOCUSED + { 5, 5, 0x848484ff }, // PROGRESSBAR_TEXT_COLOR_FOCUSED + { 9, 5, 0xf5f5f5ff }, // TEXTBOX_TEXT_COLOR_FOCUSED + { 10, 5, 0xf6f6f6ff }, // VALUEBOX_TEXT_COLOR_FOCUSED }; // WARNING: This style uses a custom font: "PixelOperator.ttf" (size: 16, spacing: 0) diff --git a/src/datatypes.h b/src/datatypes.h index cd7f97a..0a31ca7 100644 --- a/src/datatypes.h +++ b/src/datatypes.h @@ -38,6 +38,7 @@ class Vec2D{ T x = 0; T y = 0; T dist(Vec2D* v) { return sqrt(pow((v->x - x), 2) + pow((v->y - y), 2));}; + T dist(Vec2D v) { return sqrt(pow((v.x - x), 2) + pow((v.y - y), 2));}; T length() { return (T)sqrt(pow(x, 2) + pow(y, 2));}; diff --git a/src/main.cpp b/src/main.cpp index 1eaffe0..04060ee 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -66,8 +66,8 @@ int main(){ app.settings.speed = (app.settings.grid * 8.0f) * (app.settings.bpm / 120.f); - app.settings.width = monitor_width; - app.settings.height = monitor_height; + app.settings.width = monitor_width - 300; + app.settings.height = monitor_height - 300; SetTargetFPS(app.settings.fps); diff --git a/src/midi.h b/src/midi.h index 98d5063..a681742 100644 --- a/src/midi.h +++ b/src/midi.h @@ -76,7 +76,7 @@ class Midi { } void note(int midi_out, int channel, int note, int velocity, int gate){ - if(!midi_outs.empty()){ + if(midi_outs.contains(midi_out)){ if(midi_outs[midi_out]->is_port_open()){ midi_outs[midi_out]->send_message(libremidi::channel_events::note_on(channel, note, velocity)); notes.emplace_back(midi_out, channel, note, velocity, GetTime(), gate); @@ -88,7 +88,7 @@ class Midi { float time = GetTime(); for(auto &n : notes){ if(time - n.start >= (float)n.gate / 1000.0f){ - midi_outs[n.midi_out]->send_message(libremidi::channel_events::note_off(n.channel, n.note, n.velocity)); + if(midi_outs.contains(n.midi_out) && midi_outs[n.midi_out]->is_port_open()) midi_outs[n.midi_out]->send_message(libremidi::channel_events::note_off(n.channel, n.note, n.velocity)); n.erase = true; } } diff --git a/src/moveable.h b/src/moveable.h index de03511..54e6c7d 100644 --- a/src/moveable.h +++ b/src/moveable.h @@ -18,6 +18,7 @@ class Movable{ Vec2D direction; virtual void update(int fps) {}; + virtual void update(double frametime) {}; virtual void update() {}; virtual void draw(Vec2D *mouse, Camera2D *cam) {}; diff --git a/src/node-manager.h b/src/node-manager.h index 6f15282..73ed002 100644 --- a/src/node-manager.h +++ b/src/node-manager.h @@ -1,6 +1,9 @@ #pragma once +#include "datatypes.h" #include "node.h" +#include "raylib.h" +#include "raymath.h" #include #include #include @@ -57,7 +60,20 @@ class NodeManager{ } void drawNodes(Vec2D *mouse_pos, Camera2D *camera){ + auto flat_nodes = nodes | std::ranges::views::values | std::ranges::to>(); for(auto& n : nodes | std::ranges::views::values ){ + if(n.dragging){ + std::sort(flat_nodes.begin(), flat_nodes.end(), [n](Node na, Node nb){ return na.position.dist(n.position) < nb.position.dist(n.position);}); + float d = flat_nodes.at(1).position.dist(n.position); + if(d > 0 && d < 240) { + Vector2 text_length = MeasureTextEx(GetFontDefault(), std::format("{:.1f}",d).c_str(), 10.0f, 2.0f); + Vec2D middle_handle = flat_nodes.at(1).position + (n.position - flat_nodes.at(1).position) * ((d - text_length.x)*0.5f)/d; + Vec2D text_position = middle_handle + (flat_nodes.at(1).position - n.position).norm().orth() * 12.0f; + float rotation = Vector2Angle((Vector2){1,0}, (n.position - flat_nodes.at(1).position)) * RAD2DEG; + DrawTextPro(GetFontDefault(), std::format("{:.1f}",d).c_str(), text_position, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK); + DrawLineV(n.position, flat_nodes.at(1).position, VS_COLOR_PINK); + } + } n.draw(mouse_pos, camera); } } diff --git a/src/signal-manager.h b/src/signal-manager.h index 00d79e3..65d4635 100644 --- a/src/signal-manager.h +++ b/src/signal-manager.h @@ -71,22 +71,24 @@ class SignalManager{ } void updateSignals(){ - auto last = std::chrono::steady_clock::now(); + auto last = std::chrono::high_resolution_clock::now(); while(loop){ - std::chrono::duration diff = std::chrono::steady_clock::now() - last; - if(diff.count() > 500){ + std::chrono::duration diff = std::chrono::high_resolution_clock::now() - last; + if((int)diff.count() >= 250){ mutex->lock(); if(play){ for(auto& s : signals){ s.direction = (nm->nodes[s.next].position - s.position).norm(); s.update(diff.count()); - if(s.position.dist(&nm->nodes[s.next].position) < 1.0f) { + if(s.position.dist(&nm->nodes[s.next].position) < 0.6f) { int n = cm->next(s.next, s.last); nm->nodes[s.next].trigger(); if(n != s.next && n != -1) { for(auto &m : nm->nodes[s.next].midi_outs){ - if(m.second.enabled) midi.note(m.second.i, nm->nodes[s.next].midi_channel, nm->nodes[s.next].midi_note, nm->nodes[s.next].midi_velocity, nm->nodes[s.next].midi_gate); + if(m.second.enabled) { + midi.note(m.second.i, nm->nodes[s.next].midi_channel, nm->nodes[s.next].midi_note, nm->nodes[s.next].midi_velocity, nm->nodes[s.next].midi_gate); + } } s.last = s.next; s.next = n; @@ -96,14 +98,16 @@ class SignalManager{ } midi.update(); mutex->unlock(); - last = std::chrono::steady_clock::now(); + last = std::chrono::high_resolution_clock::now(); } } } void drawSignals(Vec2D *mouse_pos, Camera2D *camera){ for(auto& s : signals){ + mutex->lock(); s.draw(mouse_pos, camera); + mutex->unlock(); } } diff --git a/src/signal.h b/src/signal.h index 8758720..1d02219 100644 --- a/src/signal.h +++ b/src/signal.h @@ -28,7 +28,7 @@ class Signal : public Movable{ Color color; - void update(int t_delta){ + void update(double t_delta){ // 120px / 16th = 1920px / whole note // whole note = 2s at 120bpm // 960px / s diff --git a/src/state-manager.h b/src/state-manager.h index 9829122..419af13 100644 --- a/src/state-manager.h +++ b/src/state-manager.h @@ -53,7 +53,9 @@ class AppState{ for(auto &n : copy_nodes_ids){ int old_id = n; int new_id = nm.copyNode(n, position + nm.nodes[n].drag_offset); - + nm.nodes[new_id].copied = false; + nm.nodes[new_id].selected = true; + for(auto &c : copy_connections){ if(c.v1 == old_id) c.v1 = new_id; if(c.v2 == old_id) c.v2 = new_id; @@ -121,10 +123,10 @@ class AppState{ void draw(Vec2D *mouse_pos, Camera2D *camera){ mutex.lock(); updateMidiPorts(); + mutex.unlock(); nm.drawNodes(mouse_pos, camera); cm.drawConnections(mouse_pos, camera); sm.drawSignals(mouse_pos, camera); - mutex.unlock(); } void drawUI(Vec2D *mouse_pos, Camera2D *camera){ diff --git a/src/ui.h b/src/ui.h index 55942b8..bf1799a 100644 --- a/src/ui.h +++ b/src/ui.h @@ -27,12 +27,13 @@ class AppUI{ void drawSideBar(){ - GuiWindowBox((Rectangle){0,0,280,(float)settings->height}, "config"); + GuiPanel((Rectangle){-1,-30,280,(float)settings->height + 31}, ""); { - const int s_controls = 55; - if(GuiButton((Rectangle){20, (float)s_controls, 60, 30}, "PLAY")) sm->play ? sm->pause() : sm->start(); - if(GuiButton((Rectangle){100, (float)s_controls, 60, 30}, "STOP")) sm->stop(); - if(GuiButton((Rectangle){180, (float)s_controls, 60, 30}, "RESET")) sm->reset(); + const int s_controls = 20; + //GuiSetStyle(BUTTON, STATE_FOCUSED, 0xFF0000FF); + if(GuiButton((Rectangle){20, (float)s_controls, 80, 30}, "PLAY")) sm->play ? sm->pause() : sm->start(); + if(GuiButton((Rectangle){120, (float)s_controls, 60, 30}, "STOP")) sm->stop(); + if(GuiButton((Rectangle){200, (float)s_controls, 60, 30}, "RESET")) sm->reset(); const int s_bpm = s_controls + 35; GuiLabel((Rectangle){20, (float)s_bpm, 120, 20}, "TIMING"); @@ -83,7 +84,7 @@ class AppUI{ if(GuiButton((Rectangle){20, (float)s_nodes + 60, 240, 20}, "ADD RANDOM NODE")){ nm->addNode(200.0f, 200.0f); } - + DrawText(std::format("{}", nm->nodes.size()).c_str(), 20, settings->height - 70, 15, VS_COLOR_WHITE); DrawFPS(20, settings->height - 30); } }