distance to closest node displayed, timing problems with midi notes being sent 1 to 3ms too early, or too late
This commit is contained in:
@@ -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));};
|
||||
|
||||
|
||||
+2
-2
@@ -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);
|
||||
|
||||
|
||||
+2
-2
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ class Movable{
|
||||
Vec2D<float> direction;
|
||||
|
||||
virtual void update(int fps) {};
|
||||
virtual void update(double frametime) {};
|
||||
virtual void update() {};
|
||||
virtual void draw(Vec2D<float> *mouse, Camera2D *cam) {};
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "datatypes.h"
|
||||
#include "node.h"
|
||||
#include "raylib.h"
|
||||
#include "raymath.h"
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <random>
|
||||
@@ -57,7 +60,20 @@ class NodeManager{
|
||||
}
|
||||
|
||||
void drawNodes(Vec2D<float> *mouse_pos, Camera2D *camera){
|
||||
auto flat_nodes = nodes | std::ranges::views::values | std::ranges::to<std::vector<Node>>();
|
||||
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<float> middle_handle = flat_nodes.at(1).position + (n.position - flat_nodes.at(1).position) * ((d - text_length.x)*0.5f)/d;
|
||||
Vec2D<float> 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);
|
||||
}
|
||||
}
|
||||
|
||||
+10
-6
@@ -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<double, std::micro> diff = std::chrono::steady_clock::now() - last;
|
||||
if(diff.count() > 500){
|
||||
std::chrono::duration<double, std::micro> 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<float> *mouse_pos, Camera2D *camera){
|
||||
for(auto& s : signals){
|
||||
mutex->lock();
|
||||
s.draw(mouse_pos, camera);
|
||||
mutex->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+4
-2
@@ -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<float> *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<float> *mouse_pos, Camera2D *camera){
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user