Files
viseq/src/ui.h
T

213 lines
9.5 KiB
C++
Raw Normal View History

2024-10-25 16:41:37 +02:00
#pragma once
#include "state.h"
#include "midi-node.h"
2024-10-30 14:55:24 +01:00
#include "raylib.h"
2024-10-25 16:41:37 +02:00
#include "raygui/raygui.h"
#include "raygui/dark/style_dark.h"
#include "datatypes.h"
2024-10-30 14:55:24 +01:00
#include "graph-manager.h"
2024-10-25 16:41:37 +02:00
#include "signal-manager.h"
2024-10-30 14:55:24 +01:00
#include <memory>
2024-10-25 16:41:37 +02:00
#include <ranges>
2024-11-03 03:48:49 +01:00
namespace VISEQ::APP::UI{
class AppUI{
public:
AppUI() {}
AppUI(std::shared_ptr<SIGNAL::SignalManager> sm, std::shared_ptr<GraphManager> gm) : gm(gm), sm(sm) {}
2024-11-14 00:55:09 +01:00
std::shared_ptr<State> state = State::get();
2024-11-03 03:48:49 +01:00
std::shared_ptr<GraphManager> gm;
std::shared_ptr<SIGNAL::SignalManager> sm;
2024-11-03 03:48:49 +01:00
bool bpm_spinner_edit_mode = false;
2024-11-03 03:48:49 +01:00
void init(){
GuiLoadStyleDark();
2024-10-29 00:50:39 +01:00
}
2024-10-25 16:41:37 +02:00
2024-11-03 03:48:49 +01:00
void drawSideBar(){
GuiPanel((Rectangle){-1,-30,380,(float)state->settings.height + 31}, "");
2024-11-03 03:48:49 +01:00
const int s_controls = 25;
//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 + 45;
GuiLabel((Rectangle){20, (float)s_bpm, 120, 20}, "TIMING");
2024-11-14 00:55:09 +01:00
GuiLabel((Rectangle){200, (float)s_bpm, 40, 20}, std::format("{}",state->settings.bpm).c_str());
int _bpm = state->settings.bpm;
// GuiSlider((Rectangle){20, (float)s_bpm + 25, 240, 20}, "", "", &_bpm, 1, 300);
if(GuiSpinner((Rectangle){20, (float)s_bpm + 25, 240, 20}, "", &_bpm, 1, 300, bpm_spinner_edit_mode)) bpm_spinner_edit_mode = !bpm_spinner_edit_mode;
2024-11-14 00:55:09 +01:00
state->settings.bpm = _bpm;
2024-11-03 03:48:49 +01:00
int s_midi = s_bpm + 75;
GuiLabel((Rectangle){20, (float)s_midi, 240, 20}, "MIDI OUT");
if(GuiButton((Rectangle){200, (float)s_midi, 60, 20}, "RELOAD")) sm->midi.enumerate();
int i = 0;
for(auto& mo : sm->midi.midi_out_ports){
GuiCheckBox((Rectangle){20, (float)s_midi + 25 + i*20.0f, 20, 20}, mo.port.port_name.substr(0,32).c_str(), &mo.enabled);
i++;
}
if(GuiButton((Rectangle){20, (float)s_midi + 45 + i*20.0f, 240, 20}, "ENABLE FOR ALL")) {
for(auto &midis : sm->midi.midi_out_ports){
if(midis.enabled){
gm->setMidiPortForAll(midis.number, true);
2024-10-25 16:41:37 +02:00
}
}
}
2024-11-03 03:48:49 +01:00
int s_signal = s_midi + 100 + i*20;
GuiLabel((Rectangle){20, (float)s_signal, 240, 20}, "SIGNALS");
if(GuiButton((Rectangle){20, (float)s_signal + 35, 240, 20}, "ADD RANDOM SIGNAL")){
std::shared_ptr<Node> ni = gm->getRandomNode();
sm->addSignalAtNode(ni);
}
2024-10-25 16:41:37 +02:00
2024-11-03 03:48:49 +01:00
int signal_configs = 0;
for(auto &s : sm->signals){
if(GuiButton((Rectangle){20,(float)s_signal+70 + signal_configs*20, 20, 20},"X")) sm->removeSignal(s);
2024-11-03 03:48:49 +01:00
DrawCircle(55, s_signal+80 + signal_configs*20, 6.0F, s->color);
2024-11-07 00:01:54 +01:00
int s_speed = round(s->speed);
2024-11-14 00:55:09 +01:00
s->multiplier = state->settings.bpm / 120.0f;
float signal_bpm = round(state->settings.bpm * s->multiplier * (s->speed / state->settings.speed));
if(GuiSpinner((Rectangle){70, (float)s_signal+70 + signal_configs*20, 100, 20}, "", &s_speed, 1, 16 * state->settings.grid * 4, s->ui_edit_speed)) s->ui_edit_speed = !s->ui_edit_speed;
if(GuiButton((Rectangle){200,(float)s_signal+70 + signal_configs*20, 30, 20}, "1/2")) s_speed = state->settings.speed / 2;
//if(GuiButton((Rectangle){200,(float)s_signal+70 + signal_configs*20, 30, 20},"1/4")) s_speed = state->settings.speed / 4;
GuiLabel((Rectangle){195, (float)s_signal+70 + signal_configs*20, 30, 20}, std::format("{}",signal_bpm).c_str());
GuiToggle((Rectangle){240, (float)s_signal+70 + signal_configs*20, 20, 20},"P", &s->run);
s->speed = s_speed;
2024-11-03 03:48:49 +01:00
signal_configs++;
2024-10-25 16:41:37 +02:00
}
2024-11-03 03:48:49 +01:00
int s_nodes = s_signal + 70 + signal_configs*20;
GuiLabel((Rectangle){20, (float)s_nodes + 30, 240, 20}, "NODES");
if(GuiButton((Rectangle){20, (float)s_nodes + 60, 240, 20}, "ADD RANDOM NODE")){
gm->createMidiNode(Vec2Df{200.0f, 200.0f});
2024-11-03 03:48:49 +01:00
}
DrawText(std::format("{}", gm->getNodesSize()).c_str(), 20, state->settings.height - 70, 15, VS_COLOR_WHITE);
2024-11-14 00:55:09 +01:00
DrawFPS(20, state->settings.height - 30);
std::string shorts[6] = {"NT","CC","PC","PB","AT","PP"};
for(int i = 0; i < 6; ++i){
Color col = state->settings.mode_colors[i];
Vec2Df pos = {state->settings.width - (6.0f*75.0f) + i*75.0f, state->settings.height - 75.0f};
DrawRing(pos, 30.0f, 34.0f, 0.0f, 360.0f, 24, state->node_mode == i ? VS_COLOR_WHITE : (Color){0,0,0,0});
DrawCircleV(pos, 30.0f, col);
DrawCenteredText(shorts[i], pos, 20, WHITE);
}
2024-11-05 00:51:25 +01:00
}
2024-11-07 00:56:33 +01:00
void DrawCenteredText(std::string text, Vec2Df position, int size, Color color){
float offset = MeasureText(text.c_str(), size);
DrawText(text.c_str(), position.x-offset/2.0f, position.y-(float)size/2.0f+1, size, color );
2024-11-03 03:48:49 +01:00
}
2024-12-05 23:39:01 +01:00
void drawContextMenu(Camera2D camera){
for(auto n : gm->getSelection() | std::views::filter([](std::shared_ptr<Node> n){ return n->config; })){
Vector2 np = GetWorldToScreen2D((Vector2){n->position.x, n->position.y}, camera);
2024-11-06 02:28:37 +01:00
2024-12-05 23:39:01 +01:00
state->context_menu = !GuiWindowBox((Rectangle){np.x + 10, np.y + 10, 240, 440}, "config");
n->config = state->context_menu;
2024-10-25 16:41:37 +02:00
2024-11-03 03:48:49 +01:00
int option = n->distributionMode;
GuiToggleGroup((Rectangle){ np.x + 20, np.y + 40, 73, 20 }, "GEO;RR;RAND", &option);
n->distributionMode = (Distribution)option;
2024-11-06 02:28:37 +01:00
2024-11-03 03:48:49 +01:00
GuiLabel((Rectangle){np.x + 20, np.y + 65, 220, 20}, "SIGNALS");
if(GuiButton((Rectangle){np.x + 20, np.y + 90, 220, 20}, "ADD SIGNAL")){
sm->addSignalAtNode(n);
}
2024-11-03 03:48:49 +01:00
int y_midi = 120;
GuiLabel((Rectangle){np.x + 20, np.y + y_midi, 220, 20}, "MIDI OUT");
int i = 0;
if(n->getNodeType() == NodeType::MIDINODE){
std::shared_ptr<MidiNode> mn = std::dynamic_pointer_cast<MidiNode>(n);
for(auto& mo : mn->midi_outs){
GuiCheckBox((Rectangle){np.x + 20, np.y + y_midi + 20 + i*20.0f, 20, 20}, mo.second.name.c_str(), &mo.second.enabled);
i++;
}
2024-11-06 02:28:37 +01:00
2024-11-03 03:48:49 +01:00
int y_channel = y_midi + 30 + i*20;
GuiCheckBox((Rectangle){np.x + 20, np.y + y_channel, 20, 20}, "NOTE", &mn->send_note);
GuiCheckBox((Rectangle){np.x + 90, np.y + y_channel, 20, 20}, "CC", &mn->send_cc);
GuiCheckBox((Rectangle){np.x + 160, np.y + y_channel, 20, 20}, "PITCH", &mn->send_pitch_bend);
2024-11-06 02:28:37 +01:00
2024-11-03 03:48:49 +01:00
int y_cc_note = y_channel + 120;
switch(state->node_mode){
2024-11-03 03:48:49 +01:00
case 0:{
2024-11-06 02:28:37 +01:00
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note - 75, 220, 20}, "NOTE CHANNEL");
GuiToggleGroup((Rectangle){np.x + 20, np.y + y_cc_note - 50, 25, 20}, "1;2;3;4;5;6;7;8\n9;10;11;12;13;14;15;16", &mn->midiNote.channel);
2024-11-06 02:28:37 +01:00
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note , 100, 20}, "NOTE");
float v = mn->midiNote.note;
2024-11-06 02:28:37 +01:00
GuiLabel((Rectangle){np.x + 210, np.y + y_cc_note , 20, 20}, MIDI::Notes[(int)round(v)].c_str());
GuiLabel((Rectangle){np.x + 160, np.y + y_cc_note , 40, 20}, std::format("{}",mn->midiNote.note).c_str());
2024-11-06 02:28:37 +01:00
GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 30, 220, 20}, "", "", &v, 0, 127);
mn->midiNote.note = round(v);
2024-11-06 02:28:37 +01:00
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note + 60, 100, 20}, "VELOCITY");
v = mn->midiNote.velocity;
GuiLabel((Rectangle){np.x + 210, np.y + y_cc_note + 60, 20, 20}, std::format("{}",mn->midiNote.velocity).c_str());
2024-11-06 02:28:37 +01:00
GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 90, 220, 20}, "", "", &v, 0, 127);
mn->midiNote.velocity = round(v);
2024-11-06 02:28:37 +01:00
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note + 120, 100, 20}, "GATE");
v = mn->midiNote.gate;
GuiLabel((Rectangle){np.x + 210, np.y + y_cc_note + 120, 20, 20}, std::format("{}",(float)mn->midiNote.gate/1000.0f).c_str());
2024-11-06 02:28:37 +01:00
GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 150, 220, 20}, "", "", &v, 0, 30000);
mn->midiNote.gate= round(v);
2024-11-06 02:28:37 +01:00
break;}
2024-11-03 03:48:49 +01:00
case 1:
2024-11-06 02:28:37 +01:00
{
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note - 75, 220, 20}, "CC CHANNEL");
GuiToggleGroup((Rectangle){np.x + 20, np.y + y_cc_note - 50, 25, 20}, "1;2;3;4;5;6;7;8\n9;10;11;12;13;14;15;16", &mn->midiCC.channel);
2024-11-06 02:28:37 +01:00
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note , 100, 20}, "CC");
float v = mn->midiCC.control;
GuiLabel((Rectangle){np.x + 160, np.y + y_cc_note , 40, 20}, std::format("{}",mn->midiCC.control).c_str());
2024-11-06 02:28:37 +01:00
GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 30, 220, 20}, "", "", &v, 0, 127);
mn->midiCC.control = round(v);
2024-11-06 02:28:37 +01:00
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note + 60, 100, 20}, "CC VALUE");
v = mn->midiCC.value;
GuiLabel((Rectangle){np.x + 210, np.y + y_cc_note + 60, 20, 20}, std::format("{}",mn->midiCC.value).c_str());
2024-11-06 02:28:37 +01:00
GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 90, 220, 20}, "", "", &v, 0, 127);
mn->midiCC.value = round(v);
2024-11-06 02:28:37 +01:00
break;}
2024-11-03 03:48:49 +01:00
case 2:
2024-11-06 02:28:37 +01:00
{
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note - 75, 220, 20}, "PITCH BEND CHANNEL");
GuiToggleGroup((Rectangle){np.x + 20, np.y + y_cc_note - 50, 25, 20}, "1;2;3;4;5;6;7;8\n9;10;11;12;13;14;15;16", &mn->midiPitchBend.channel);
2024-11-06 02:28:37 +01:00
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note , 100, 20}, "CC");
float v = mn->midiPitchBend.value;
GuiLabel((Rectangle){np.x + 160, np.y + y_cc_note , 40, 20}, std::format("{}",mn->midiPitchBend.value).c_str());
2024-11-06 02:28:37 +01:00
GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 30, 220, 20}, "", "", &v, 0, 16383);
mn->midiPitchBend.value = round(v);
2024-11-06 02:28:37 +01:00
break;}
2024-11-03 03:48:49 +01:00
}
}
}
2024-10-25 16:41:37 +02:00
}
void draw(Vec2Df mouse_pos, Camera2D camera){
2024-11-03 03:48:49 +01:00
drawSideBar();
2024-12-05 23:39:01 +01:00
if(state->context_menu) drawContextMenu(camera);
2024-11-03 03:48:49 +01:00
}
2024-10-25 16:41:37 +02:00
2024-11-03 03:48:49 +01:00
};
}