From ddf9e640b12f2aee8e9c50aed4934121959dad1b Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 9 Dec 2024 01:40:13 +0100 Subject: [PATCH] Good working protoype with config nodes and a experimental channel setting ui. --- src/button.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++ src/config-node.h | 2 +- src/connector.h | 13 ++++++---- src/datatypes.h | 2 +- src/midi-node.h | 50 ++++++++++++++++++++++++++++++++------ src/node.h | 1 + src/vmath.h | 8 +++++++ 7 files changed, 123 insertions(+), 14 deletions(-) diff --git a/src/button.h b/src/button.h index 5967067..39faada 100644 --- a/src/button.h +++ b/src/button.h @@ -1,15 +1,76 @@ #pragma once +#include "datatypes.h" +#include "interactable.h" #include "vmath.h" #include "raylib.h" #include "raymath.h" +#include "state.h" inline bool ViButton(Vec2Df mp, float x, float y, float radius, Color color){ DrawCircle(x,y,radius, color); return (Vector2Distance(mp, (Vector2){x,y}) < radius && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)); } +inline bool ViButton(Vec2Df mp, Vec2Df position, float radius, Color color){ + return ViButton(mp, position.x, position.y, radius, color); +} + +inline bool ViButtonText(Vec2Df mp, Vec2Df position, float radius, Color color, std::string text, float text_size, Color text_color){ + float offset = MeasureText(text.c_str(), text_size); + DrawCircle(position.x, position.y, radius, color); + DrawText(text.c_str(), position.x-offset/2.0f, position.y - text_size/2, text_size, text_color); + return (Vector2Distance(mp, position) < radius && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)); +} + inline bool ViSegButton(Vec2Df mp, float x, float y, float start_angle, float end_angle, float radius, Color color){ DrawCircleSector((Vector2){x,y},radius, start_angle, end_angle, 5, color); return (Vector2Distance(mp, (Vector2){x,y}) < radius && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)); } + +inline void DrawCenteredText(std::string text, Vec2Df position, float text_size, Color color){ + float offset = MeasureText(text.c_str(), text_size); + DrawText(text.c_str(), position.x-offset/2.0f, position.y-text_size/2.0f, text_size, color); +} + +namespace VISEQ::APP::UI{ + + class Button : public BASE::Interactable{ + public: + Button() {} + Button(Vec2Df position, Color color) : color(color), position(position) {} + Color color = VS_COLOR_YELLOW; + Color hover_color = VS_COLOR_SUN; + Vec2Df position = {0,0}; + std::string text = ""; + Color text_color = VS_COLOR_BROWN; + float text_size = 10; + virtual void draw() = 0; + virtual GRAPH::GraphItemType getType() override {return GRAPH::GraphItemType::VS_BUTTON;} + }; + + class ButtonRound : public Button{ + public: + ButtonRound() {} + ButtonRound(Vec2Df position, float radius, Color color) : Button(position, color), radius(radius){} + + std::shared_ptr state = APP::State::get(); + + float radius = 0.0f; + virtual bool hovering() override { + return CheckCollisionPointCircle(SCREEN_MOUSE, position, radius); + } + + virtual void pickUp() override {} + virtual void pickUp(Vec2Df position) override {} + virtual void drag(Vec2Df position) override {} + virtual void putDown() override {} + + virtual void draw() override { + float offset = MeasureText(text.c_str(), text_size); + if(!hovering()) DrawCircle(position.x, position.y, radius, color); + else DrawCircle(position.x, position.y, radius, hover_color); + if(text != "") DrawText(text.c_str(), position.x-offset/2.0f, position.y - text_size/2, text_size, text_color); + } + }; +} diff --git a/src/config-node.h b/src/config-node.h index d7a9f0d..207529f 100644 --- a/src/config-node.h +++ b/src/config-node.h @@ -181,7 +181,7 @@ namespace VISEQ::GRAPH::NODES { } if(highlighted) DrawCircleLinesV(position, radius+2, (Color){255, 0, 0, 200}); - DrawText(std::format("{}", id).c_str(), position.x + 20.0f, position.y + 20.0f, 10, WHITE); + //DrawText(std::format("{}", id).c_str(), position.x + 20.0f, position.y + 20.0f, 10, WHITE); } friend void to_json(json& j, const ConfigNode& N){ diff --git a/src/connector.h b/src/connector.h index f9673b7..da77833 100644 --- a/src/connector.h +++ b/src/connector.h @@ -24,8 +24,8 @@ namespace VISEQ::GRAPH { bool passable = false; - float radius = 5.0f; - float orbit = 14.0f; + float radius = 8.0f; + float orbit = 20.0f; Vec2Df center_position; GraphItemType getType() override{ @@ -47,6 +47,9 @@ namespace VISEQ::GRAPH { void setPosition(Vec2Df pos) override { center_position = pos; } + void setOrbit(float r) { + orbit = r; + } void update() override { if(hovering()) state->pushEvent({getPtr(), APP::Interaction::HOVER}); @@ -57,9 +60,9 @@ namespace VISEQ::GRAPH { state->pushEvent({getPtr(), APP::Interaction::CONNECT}); connected = false; } - - if(partner.expired()) position = center_position - ((center_position - SCREEN_MOUSE)).norm() * (radius + orbit); - if(!partner.expired()) position = center_position - ((center_position - partner.lock()->position)).norm() * (radius + orbit); + + if(partner.expired()) position = center_position.orbitAlongVector(SCREEN_MOUSE, orbit); + if(!partner.expired()) position = center_position .orbitAlongVector(partner.lock()->position, orbit); if(new_partner) { new_partner = false; state->pushEvent({getPtr(), APP::Interaction::CONNECT}); diff --git a/src/datatypes.h b/src/datatypes.h index 9e0ab7c..e9bbc3e 100644 --- a/src/datatypes.h +++ b/src/datatypes.h @@ -33,7 +33,7 @@ namespace VISEQ::GRAPH::NODES { namespace VISEQ::GRAPH{ - enum GraphItemType {NODE, EDGE, CONNECTOR, CANVAS, HANDLE}; + enum GraphItemType {NODE, EDGE, CONNECTOR, CANVAS, HANDLE, VS_BUTTON}; enum NodeType {OSCNODE, MIDINODE, CONFIGNODE}; enum EdgeType {MIDIEDGE, CONFIGEDGE}; } diff --git a/src/midi-node.h b/src/midi-node.h index eb46cc0..fc7e204 100644 --- a/src/midi-node.h +++ b/src/midi-node.h @@ -1,13 +1,15 @@ #pragma once +#include "button.h" #include "config-node.h" #include "datatypes.h" #include "edge.h" #include "node.h" +#include "raylib.h" #include "raymath.h" +#include "state.h" #include - -#define RADIUS 14.0f +#include namespace VISEQ::APP::UI{ class AppUI; @@ -25,6 +27,8 @@ namespace VISEQ::GRAPH::NODES { MIDI::MidiAftertouch midiAftertouch; MIDI::MidiPolyPressure midiPolyPressure; MIDI::MidiPC midiPC; + + std::vector channelButtons; public: @@ -34,8 +38,8 @@ namespace VISEQ::GRAPH::NODES { bool enabled; }; - MidiNode() {std::cout << "MidiNode Constructor std" << std::endl;} - MidiNode(Vec2Df position) : Node(position) {} + MidiNode() {init();} + MidiNode(Vec2Df position) : Node(position) {init();} NodeType nodeType = NodeType::MIDINODE; @@ -57,6 +61,14 @@ namespace VISEQ::GRAPH::NODES { float fade = 0; float time = 0; float last = 0; + + void init(){ + channelButtons.clear(); + for(int i = 0; i < 16; ++i){ + channelButtons.emplace_back(position, 4.0f, VS_COLOR_YELLOW); + channelButtons.back().hover_color = VS_COLOR_PINK; + } + } std::shared_ptr getPtr(){ return std::static_pointer_cast(shared_from_this()); @@ -203,6 +215,12 @@ namespace VISEQ::GRAPH::NODES { void draw(Vec2Df mouse, Camera2D cam) override { Node::draw(); + if(hovering()) { + radius += radius < 25 ? 2 : 0; + } else { + radius -= radius > 15 ? 2 : 0; + } + if(hovering() || selected) interact(); last = time; @@ -214,8 +232,8 @@ namespace VISEQ::GRAPH::NODES { fade -= (time - last)*1000.0f; } - DrawRing(position, radius, radius+4, 0, 360, 24, (Color){60, 60, 60, 255}); - DrawRing(position, radius, radius+4, 0.0f - 90.0f, (360.0f/127.0f) * getNotes().velocity - 90.0f, 24, (Color){158, 134, 200, 255}); + DrawRing(position, radius, radius + 4, 0, 360, 24, (Color){60, 60, 60, 255}); + DrawRing(position, radius, radius + 4, 0.0f - 90.0f, (360.0f/127.0f) * getNotes().velocity - 90.0f, 24, (Color){158, 134, 200, 255}); DrawCircleLinesV(position, radius + 4, (Color){100, 100, 100, 255}); float midi_gate_map = round((255.f / getNotes().gate) * fade); @@ -241,6 +259,24 @@ namespace VISEQ::GRAPH::NODES { if(distributionMode == Distribution::ROUNDROBIN) DrawCircle(position.x, position.y, radius/2.0f, VS_COLOR_YELLOW); if(selected) DrawCircleLinesV(position, radius+8, (Color){158, 255, 210, 255}); + + if(hovering()){ + for(int i = 0; i < 16; ++i){ + channelButtons.at(i).position = position.orbitAtAngle(21.0, DEG2RAD * (360.0f/16.0f)*i); + Color col = VS_COLOR_YELLOW; + if(mode == 0 && midiNote.channel == i) col = VS_COLOR_PINK; + if(mode == 1 && midiCC.channel == i) col = VS_COLOR_PINK; + if(mode == 2 && midiPitchBend.channel == i) col = VS_COLOR_PINK; + channelButtons.at(i).color = col; + channelButtons.at(i).draw(); + if(channelButtons.at(i).hovering()) DrawCenteredText(std::format("{}", i+1), position + (Vec2Df){0,10.0f}, 8, VS_COLOR_WHITE); + if(channelButtons.at(i).clicked()) { + if(mode == 0) midiNote.channel = i; + if(mode == 1) midiCC.channel = i; + if(mode == 2) midiPitchBend.channel = i; + } + } + } if(KEYS_DOWN.alt){ float value = 0; @@ -280,7 +316,7 @@ namespace VISEQ::GRAPH::NODES { } if(highlighted) DrawCircleLinesV(position, radius+2, (Color){255, 0, 0, 200}); - DrawText(std::format("{}", id).c_str(), position.x + 20.0f, position.y + 20.0f, 10, WHITE); + //DrawText(std::format("{}", id).c_str(), position.x + 20.0f, position.y + 20.0f, 10, WHITE); } friend void to_json(json& j, const MidiNode& N){ diff --git a/src/node.h b/src/node.h index 83c3b0f..70308db 100644 --- a/src/node.h +++ b/src/node.h @@ -88,6 +88,7 @@ namespace VISEQ::GRAPH::NODES { for(auto c : connectors){ if(c->partner.expired()) free_connectors++; c->setPosition(position); + c->setOrbit(radius + 8.0f); c->update(); } if(free_connectors == 0) addConnector(); diff --git a/src/vmath.h b/src/vmath.h index c2723d0..cf62831 100644 --- a/src/vmath.h +++ b/src/vmath.h @@ -61,6 +61,14 @@ namespace VISEQ::VMATH{ return Vec2D{x,y} - (Vec2D{x,y} - v)*0.5f; } + Vec2D orbitAlongVector(Vec2D d, float r){ + return Vec2D{x,y} - ((Vec2D{x,y} - d)).norm() * r; + } + + Vec2D orbitAtAngle(float r, float angle){ + return {x + sin(angle) * r, y + cos(angle) * r}; + } + Vec2D& operator=(const Vec2D& vec){ if (this == &vec){ return *this;