json serialization beginnings, but still much to do

This commit is contained in:
Sebastian
2024-11-02 15:52:16 +01:00
parent 70d0a186a4
commit 522e9d456a
17 changed files with 25274 additions and 224 deletions
File diff suppressed because it is too large Load Diff
+176
View File
@@ -0,0 +1,176 @@
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
#include <cstdint> // int64_t, uint64_t
#include <map> // map
#include <memory> // allocator
#include <string> // string
#include <vector> // vector
// #include <nlohmann/detail/abi_macros.hpp>
// __ _____ _____ _____
// __| | __| | | | JSON for Modern C++
// | | |__ | | | | | | version 3.11.3
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
//
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
// SPDX-License-Identifier: MIT
// This file contains all macro definitions affecting or depending on the ABI
#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
#if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
#if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3
#warning "Already included a different version of the library!"
#endif
#endif
#endif
#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum)
#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum)
#ifndef JSON_DIAGNOSTICS
#define JSON_DIAGNOSTICS 0
#endif
#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
#endif
#if JSON_DIAGNOSTICS
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
#else
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
#endif
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
#else
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
#endif
#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
#endif
// Construct the namespace ABI tags component
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
#define NLOHMANN_JSON_ABI_TAGS \
NLOHMANN_JSON_ABI_TAGS_CONCAT( \
NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
// Construct the namespace version component
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
_v ## major ## _ ## minor ## _ ## patch
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
#define NLOHMANN_JSON_NAMESPACE_VERSION
#else
#define NLOHMANN_JSON_NAMESPACE_VERSION \
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
NLOHMANN_JSON_VERSION_MINOR, \
NLOHMANN_JSON_VERSION_PATCH)
#endif
// Combine namespace components
#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
#ifndef NLOHMANN_JSON_NAMESPACE
#define NLOHMANN_JSON_NAMESPACE \
nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
NLOHMANN_JSON_ABI_TAGS, \
NLOHMANN_JSON_NAMESPACE_VERSION)
#endif
#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
namespace nlohmann \
{ \
inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
NLOHMANN_JSON_ABI_TAGS, \
NLOHMANN_JSON_NAMESPACE_VERSION) \
{
#endif
#ifndef NLOHMANN_JSON_NAMESPACE_END
#define NLOHMANN_JSON_NAMESPACE_END \
} /* namespace (inline namespace) NOLINT(readability/namespace) */ \
} // namespace nlohmann
#endif
/*!
@brief namespace for Niels Lohmann
@see https://github.com/nlohmann
@since version 1.0.0
*/
NLOHMANN_JSON_NAMESPACE_BEGIN
/*!
@brief default JSONSerializer template argument
This serializer ignores the template arguments and uses ADL
([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
for serialization.
*/
template<typename T = void, typename SFINAE = void>
struct adl_serializer;
/// a class to store JSON values
/// @sa https://json.nlohmann.me/api/basic_json/
template<template<typename U, typename V, typename... Args> class ObjectType =
std::map,
template<typename U, typename... Args> class ArrayType = std::vector,
class StringType = std::string, class BooleanType = bool,
class NumberIntegerType = std::int64_t,
class NumberUnsignedType = std::uint64_t,
class NumberFloatType = double,
template<typename U> class AllocatorType = std::allocator,
template<typename T, typename SFINAE = void> class JSONSerializer =
adl_serializer,
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
class CustomBaseClass = void>
class basic_json;
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
/// @sa https://json.nlohmann.me/api/json_pointer/
template<typename RefStringType>
class json_pointer;
/*!
@brief default specialization
@sa https://json.nlohmann.me/api/json/
*/
using json = basic_json<>;
/// @brief a minimal map-like container that preserves insertion order
/// @sa https://json.nlohmann.me/api/ordered_map/
template<class Key, class T, class IgnoredLess, class Allocator>
struct ordered_map;
/// @brief specialization that maintains the insertion order of object keys
/// @sa https://json.nlohmann.me/api/ordered_json/
using ordered_json = basic_json<nlohmann::ordered_map>;
NLOHMANN_JSON_NAMESPACE_END
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
+2 -2
View File
@@ -4,12 +4,12 @@
#include "raylib.h" #include "raylib.h"
#include "raymath.h" #include "raymath.h"
inline bool ViButton(Vec2D<float> mp, float x, float y, float radius, Color color){ inline bool ViButton(Vec2Df mp, float x, float y, float radius, Color color){
DrawCircle(x,y,radius, color); DrawCircle(x,y,radius, color);
return (Vector2Distance(mp, (Vector2){x,y}) < radius && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)); return (Vector2Distance(mp, (Vector2){x,y}) < radius && IsMouseButtonPressed(MOUSE_BUTTON_LEFT));
} }
inline bool ViSegButton(Vec2D<float> mp, float x, float y, float start_angle, float end_angle, float radius, Color color){ 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); DrawCircleSector((Vector2){x,y},radius, start_angle, end_angle, 5, color);
return (Vector2Distance(mp, (Vector2){x,y}) < radius && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)); return (Vector2Distance(mp, (Vector2){x,y}) < radius && IsMouseButtonPressed(MOUSE_BUTTON_LEFT));
} }
+31 -134
View File
@@ -18,10 +18,14 @@
#define VS_COLOR_BROWN (Color){84, 75, 61, 255} #define VS_COLOR_BROWN (Color){84, 75, 61, 255}
#define VS_COLOR_SUN (Color){214, 170, 21, 255} #define VS_COLOR_SUN (Color){214, 170, 21, 255}
#include "vmath.h"
#include "nlohmann/json.hpp"
using json = nlohmann::json;
#include <cmath> #include <cmath>
#include <math.h> #include <math.h>
#include "libremidi/libremidi.hpp" #include "libremidi/libremidi.hpp"
#include "raylib.h"
enum Distribution {GEOMETRIC, ROUNDROBIN, RANDOM}; enum Distribution {GEOMETRIC, ROUNDROBIN, RANDOM};
@@ -45,146 +49,36 @@ typedef std::vector<SPTR_Node> VEC_SPTR_Node;
typedef std::vector<SPTR_Edge> VEC_SPTR_Edge; typedef std::vector<SPTR_Edge> VEC_SPTR_Edge;
typedef std::vector<SPTR_Signal> VEC_SPTR_Signal; typedef std::vector<SPTR_Signal> VEC_SPTR_Signal;
using Vec2Df = VMath::Vec2D<float>;
// 2D Vectors namespace nlohmann {
template <typename T> template <typename T>
class Vec2D{ struct adl_serializer<std::shared_ptr<T>> {
public: static void to_json(json& j, const std::shared_ptr<T>& opt){
if (opt)
Vec2D() {}; {
Vec2D(T x, T y) : x(x), y(y) {} j = *opt;
T x = 0; }
T y = 0; else
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));}; j = nullptr;
}
T length() { return (T)sqrt(pow(x, 2) + pow(y, 2));};
T angle(Vec2D v){
T angle = atan2(v.y, v.x) - atan2(y,x);
if(angle > M_PI) angle -= M_PI_2;
if(angle < -M_PI) angle += M_PI_2;
return angle;
//return acos(dot(v));
};
T angleDeg(Vec2D v){
return angle(v) * 180 / M_PI;
};
T dot(Vec2D &v){
return (x*v.x) + (y*v.y);
};
T dot(Vec2D v){
return (x*v.x) + (y*v.y);
};
operator Vector2() const {
return (Vector2){x,y};
} }
Vec2D orth(Vec2D &v){ static void from_json(const json& j, std::shared_ptr<T>& opt){
return Vec2D(-v.y, v.x); if (j.is_null())
{
opt = nullptr;
}
else
{
opt.reset(new T(j.get<T>()));
//opt = j.get<T>();
}
}
}; };
Vec2D orth(){
return Vec2D(-y, x);
};
Vec2D norm() { return *this / length();};
Vec2D center(Vec2D v){
return Vec2D<T>{x,y} - (Vec2D<T>{x,y} - v)*0.5f;
} }
Vec2D& operator=(const Vec2D& vec){
if (this == &vec){
return *this;
}
x = vec.x;
y = vec.y;
return *this;
};
Vec2D& operator+=(const Vec2D& vec){
this->x += vec.x;
this->y += vec.y;
return *this;
};
Vec2D& operator-=(const Vec2D& vec){
this->x -= vec.x;
this->y -= vec.y;
return *this;
};
Vec2D& operator*=(const Vec2D& vec){
this->x *= vec.x;
this->y *= vec.y;
return *this;
};
Vec2D& operator/=(const Vec2D& vec){
this->x /= vec.x;
this->y /= vec.y;
return *this;
};
Vec2D& operator*=(T scalar){
this->x *= scalar;
this->y *= scalar;
return *this;
};
Vec2D& operator/=(T scalar){
this->x /= scalar;
this->y /= scalar;
return *this;
};
};
template<typename T>
Vec2D<T> operator+(const Vec2D<T> left, const Vec2D<T> right){
return Vec2D<T>(left.x + right.x, left.y + right.y);
};
template<typename T>
Vec2D<T> operator-(const Vec2D<T> left, const Vec2D<T> right){
return Vec2D<T>(left.x - right.x, left.y - right.y);
};
template<typename T>
Vec2D<T> operator*(const Vec2D<T> left, const Vec2D<T> right){
return Vec2D<T>(left.x * right.x, left.y * right.y);
};
template<typename T>
Vec2D<T> operator/(const Vec2D<T> left, const Vec2D<T> right){
return Vec2D<T>(left.x / right.x, left.y / right.y);
};
template<typename T>
Vec2D<T> operator/(const Vec2D<T> left, T scalar){
return Vec2D<T>(left.x / scalar, left.y / scalar);
};
template<typename T>
Vec2D<T> operator*(const Vec2D<T> left, T scalar){
return Vec2D<T>(left.x * scalar, left.y * scalar);
};
template<typename T>
Vec2D<T> cartesianToPolar(T x, T y) {
return Vec2D<T>{sqrt(x * x + y * y), atan(y / x)}; // r,theta
}
template<typename T>
Vec2D<T> polarToCartesian(T r, T q) {
return Vec2D<T>{r * cos(q), r * sin(q)};
}
// App Settings // App Settings
struct AppSettings{ struct AppSettings{
@@ -217,6 +111,9 @@ struct MidiOut{
int number; int number;
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(MidiOut, number)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(MidiOutPort, number, enabled)
namespace MIDI{ namespace MIDI{
inline std::vector<std::string> Fractions = {"1/32","1/16","3/32","1/8","5/32","3/16","7/32","1/4","9/32","5/16","11/32","3/8","13/32","7/16","15/32","1/2","17/32","9/16","19/32","5/8","21/32","11/16","23/32","3/4","25/32","13/16","27/32","7/8","29/32","15/16","31/32","1/1"}; inline std::vector<std::string> Fractions = {"1/32","1/16","3/32","1/8","5/32","3/16","7/32","1/4","9/32","5/16","11/32","3/8","13/32","7/16","15/32","1/2","17/32","9/16","19/32","5/8","21/32","11/16","23/32","3/4","25/32","13/16","27/32","7/8","29/32","15/16","31/32","1/1"};
inline std::vector<std::string> Notes = { inline std::vector<std::string> Notes = {
+3 -1
View File
@@ -28,7 +28,9 @@ class Edge : public GraphItem{
return start == origin ? end : start; return start == origin ? end : start;
} }
void draw(Vec2D<float> mouse_pos, Camera2D cam) { void draw(Vec2Df mouse_pos, Camera2D cam) {
} }
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Edge, id, start, end, pass_forward, pass_backward)
+10 -2
View File
@@ -8,11 +8,19 @@
class GraphItem{ class GraphItem{
public: public:
GraphItem() {static int _id; id=_id++;}
std::vector<std::shared_ptr<GraphItem>> neighbors; std::vector<std::shared_ptr<GraphItem>> neighbors;
int id = 0;
GraphItemType graphItemType; GraphItemType graphItemType;
virtual void draw(Vec2D<float> mouse, Camera2D cam) = 0; virtual void draw(Vec2Df mouse, Camera2D cam) {};
virtual GraphItemType getType() {return graphItemType;} virtual GraphItemType getType() {return graphItemType;}
virtual ~GraphItem() = default; virtual ~GraphItem() = default;
/*void to_json(json& j, const GraphItem& G){*/
/* j = json{{"id",id},{"graphItemType",graphItemType},{"neighbors",neighbors}};*/
/*}*/
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(GraphItem, id, graphItemType, neighbors)
+50 -28
View File
@@ -5,8 +5,9 @@
#include "raylib.h" #include "raylib.h"
#include "raymath.h" #include "raymath.h"
#include "nlohmann/json.hpp"
#include "button.h" #include "button.h"
#include "graph-item.h"
#include "midi-node.h" #include "midi-node.h"
#include "node.h" #include "node.h"
#include "edge.h" #include "edge.h"
@@ -21,6 +22,8 @@
#include <ranges> #include <ranges>
#include <vector> #include <vector>
using json = nlohmann::json;
class GraphManager{ class GraphManager{
public: public:
@@ -35,6 +38,14 @@ class GraphManager{
std::map<SPTR_Node, int> counter; std::map<SPTR_Node, int> counter;
/*void to_json(json& j, const GraphManager& G){*/
/* j = json{{"nodes", G.nodes}, {"edges", G.edges}};*/
/*}*/
/**/
/*void from_json(const json& j, GraphManager& G){*/
/**/
/*}*/
SPTR_Node getRandomNode(){ SPTR_Node getRandomNode(){
VEC_SPTR_GraphItem o; VEC_SPTR_GraphItem o;
std::ranges::sample(nodes, std::back_inserter(o), 1, std::mt19937{std::random_device{}()}); std::ranges::sample(nodes, std::back_inserter(o), 1, std::mt19937{std::random_device{}()});
@@ -47,7 +58,7 @@ class GraphManager{
return std::dynamic_pointer_cast<Edge>(o.front()); return std::dynamic_pointer_cast<Edge>(o.front());
} }
void copyNodes(VEC_SPTR_Node _nodes, Vec2D<float> position){ void copyNodes(VEC_SPTR_Node _nodes, Vec2Df position){
for(auto n: _nodes){ for(auto n: _nodes){
nodes.insert(nodes.end(), std::make_shared<Node>(*n)); nodes.insert(nodes.end(), std::make_shared<Node>(*n));
nodes.back()->setPosition(position + nodes.back()->drag_offset); nodes.back()->setPosition(position + nodes.back()->drag_offset);
@@ -55,7 +66,7 @@ class GraphManager{
} }
} }
void copyNodes(std::vector<std::shared_ptr<MidiNode>> _nodes, Vec2D<float> position){ void copyNodes(std::vector<std::shared_ptr<MidiNode>> _nodes, Vec2Df position){
for(auto n: _nodes){ for(auto n: _nodes){
nodes.insert(nodes.end(), std::make_shared<MidiNode>(*n)); nodes.insert(nodes.end(), std::make_shared<MidiNode>(*n));
nodes.back()->setPosition(position + nodes.back()->drag_offset); nodes.back()->setPosition(position + nodes.back()->drag_offset);
@@ -63,21 +74,21 @@ class GraphManager{
} }
} }
SPTR_Node copyNode(SPTR_Node n, Vec2D<float> position){ SPTR_Node copyNode(SPTR_Node n, Vec2Df position){
std::cout << "copy basenode" << std::endl; std::cout << "copy basenode" << std::endl;
nodes.insert(nodes.end(), std::make_shared<Node>(*n)); nodes.insert(nodes.end(), std::make_shared<Node>(*n));
nodes.back()->setPosition(position); nodes.back()->setPosition(position);
return nodes.back(); return nodes.back();
} }
SPTR_Node copyNode(std::shared_ptr<MidiNode> n, Vec2D<float> position){ SPTR_Node copyNode(std::shared_ptr<MidiNode> n, Vec2Df position){
std::cout << "copy midinode" << std::endl; std::cout << "copy midinode" << std::endl;
nodes.insert(nodes.end(), std::make_shared<MidiNode>(*n)); nodes.insert(nodes.end(), std::make_shared<MidiNode>(*n));
nodes.back()->setPosition(position); nodes.back()->setPosition(position);
return nodes.back(); return nodes.back();
} }
SPTR_Node addMidiNode(Vec2D<float> position){ SPTR_Node addMidiNode(Vec2Df position){
nodes.emplace_back(std::make_shared<MidiNode>(position)); nodes.emplace_back(std::make_shared<MidiNode>(position));
return nodes.back(); return nodes.back();
} }
@@ -102,7 +113,7 @@ class GraphManager{
int return_path = 0; int return_path = 0;
float angle = -1; float angle = -1;
if(current->distributionMode == Distribution::GEOMETRIC){ if(current->distributionMode == Distribution::GEOMETRIC){
Vec2D<float> coming_from = (current->position - last->position).norm(); Vec2Df coming_from = (current->position - last->position).norm();
int i = 0; int i = 0;
for(auto n : possible_connections){ for(auto n : possible_connections){
SPTR_Node next_node = n->getNextNode(current); SPTR_Node next_node = n->getNextNode(current);
@@ -148,7 +159,7 @@ class GraphManager{
void splitEdges(){ void splitEdges(){
for(auto s : split_edges){ for(auto s : split_edges){
Vec2D<float> center = s->end->position.center(s->start->position); Vec2Df center = s->end->position.center(s->start->position);
SPTR_Node cn = addMidiNode(center); SPTR_Node cn = addMidiNode(center);
addConnection(s->start, cn); addConnection(s->start, cn);
addConnection(cn, s->end); addConnection(cn, s->end);
@@ -170,12 +181,12 @@ class GraphManager{
remove_edges.clear(); remove_edges.clear();
} }
void drawEdges(Vec2D<float> mouse_pos, Camera2D cam){ void drawEdges(Vec2Df mouse_pos, Camera2D cam){
if(!remove_edges.empty()) removeEdges(); if(!remove_edges.empty()) removeEdges();
if(!split_edges.empty()) splitEdges(); if(!split_edges.empty()) splitEdges();
for(auto c : edges){ for(auto c : edges){
Vec2D<float> v1_position = c->start->position - ((c->start->position - c->end->position)).norm() * (c->start->radius + c->connector_offset); Vec2Df v1_position = c->start->position - ((c->start->position - c->end->position)).norm() * (c->start->radius + c->connector_offset);
Vec2D<float> v2_position = c->end->position - ((c->end->position - c->start->position)).norm() * (c->end->radius + c->connector_offset); Vec2Df v2_position = c->end->position - ((c->end->position - c->start->position)).norm() * (c->end->radius + c->connector_offset);
float v1_v2_distance = v1_position.dist(&v2_position); float v1_v2_distance = v1_position.dist(&v2_position);
float midi_gate_v1 = Clamp((4.f / 1000.f) * c->start->GGate(), 1.f, 4.f); float midi_gate_v1 = Clamp((4.f / 1000.f) * c->start->GGate(), 1.f, 4.f);
@@ -194,12 +205,12 @@ class GraphManager{
DrawCircle(v2_position.x, v2_position.y, midi_gate_v2, col); DrawCircle(v2_position.x, v2_position.y, midi_gate_v2, col);
if(v1_v2_distance < 100) c->switches_offset = v1_v2_distance/2.3f; if(v1_v2_distance < 100) c->switches_offset = v1_v2_distance/2.3f;
Vec2D<float> from_to_handle = c->start->position - ((c->start->position - c->end->position)).norm() * (c->start->radius + c->switches_offset); Vec2Df from_to_handle = c->start->position - ((c->start->position - c->end->position)).norm() * (c->start->radius + c->switches_offset);
Vec2D<float> to_from_handle = c->end->position - ((c->end->position - c->start->position)).norm() * (c->end->radius + c->switches_offset); Vec2Df to_from_handle = c->end->position - ((c->end->position - c->start->position)).norm() * (c->end->radius + c->switches_offset);
Vec2D<float> middle_handle = c->end->position - ((c->end->position - c->start->position))*0.4f; Vec2Df middle_handle = c->end->position - ((c->end->position - c->start->position))*0.4f;
Vec2D<float> middle_handle_2 = c->end->position - ((c->end->position - c->start->position))*0.6f; Vec2Df middle_handle_2 = c->end->position - ((c->end->position - c->start->position))*0.6f;
Vec2D<float> flip_handle = middle_handle + (v1_position - v2_position).norm().orth() * (v1_v2_distance < 120.0f ? Clamp((120.0f - v1_v2_distance)*0.2, 0.f, 20.f) : 1.0f); Vec2Df flip_handle = middle_handle + (v1_position - v2_position).norm().orth() * (v1_v2_distance < 120.0f ? Clamp((120.0f - v1_v2_distance)*0.2, 0.f, 20.f) : 1.0f);
Vec2D<float> flip_handle_2 = middle_handle_2 + (v1_position - v2_position).norm().orth() * (v1_v2_distance < 120.0f ? Clamp((120.0f - v1_v2_distance)*-0.2, -20.f, 0.f) : 1.0f); Vec2Df flip_handle_2 = middle_handle_2 + (v1_position - v2_position).norm().orth() * (v1_v2_distance < 120.0f ? Clamp((120.0f - v1_v2_distance)*-0.2, -20.f, 0.f) : 1.0f);
// Dynamic opacity by distance to mouse // Dynamic opacity by distance to mouse
unsigned char opacity = 150.0f - Clamp(middle_handle.dist(mouse_pos), 0.0f, 150.0f); unsigned char opacity = 150.0f - Clamp(middle_handle.dist(mouse_pos), 0.0f, 150.0f);
@@ -212,14 +223,14 @@ class GraphManager{
if(ViButton(mouse_pos, to_from_handle.x, to_from_handle.y, 8.0f, c->pass_backward ? (Color){120, 210, 115, opacity_to} : (Color){232, 50, 32, opacity_to} )) c->pass_backward = !c->pass_backward; if(ViButton(mouse_pos, to_from_handle.x, to_from_handle.y, 8.0f, c->pass_backward ? (Color){120, 210, 115, opacity_to} : (Color){232, 50, 32, opacity_to} )) c->pass_backward = !c->pass_backward;
if(!c->pass_forward){ if(!c->pass_forward){
Vec2D<float> block_point1 = (v1_position - v2_position).norm().orth()*4.0f + from_to_handle; Vec2Df block_point1 = (v1_position - v2_position).norm().orth()*4.0f + from_to_handle;
Vec2D<float> block_point2 = (v1_position - v2_position).norm().orth()*-4.0f + from_to_handle; Vec2Df block_point2 = (v1_position - v2_position).norm().orth()*-4.0f + from_to_handle;
DrawLineEx(block_point1, block_point2, 2.0f, (Color){232,232,232,opacity_from}); DrawLineEx(block_point1, block_point2, 2.0f, (Color){232,232,232,opacity_from});
} }
if(!c->pass_backward){ if(!c->pass_backward){
Vec2D<float> block_point1 = (v1_position - v2_position).norm().orth()*4.0f + to_from_handle; Vec2Df block_point1 = (v1_position - v2_position).norm().orth()*4.0f + to_from_handle;
Vec2D<float> block_point2 = (v1_position - v2_position).norm().orth()*-4.0f + to_from_handle; Vec2Df block_point2 = (v1_position - v2_position).norm().orth()*-4.0f + to_from_handle;
DrawLineEx(block_point1, block_point2, 2.0f, (Color){232,232,232,opacity_to}); DrawLineEx(block_point1, block_point2, 2.0f, (Color){232,232,232,opacity_to});
} }
@@ -229,7 +240,7 @@ class GraphManager{
} }
} }
void drawNodes(Vec2D<float> mouse_pos, Camera2D camera){ void drawNodes(Vec2Df mouse_pos, Camera2D camera){
auto neighbors = nodes | RANGE_FILTER([](SPTR_Node n){ return !n->dragging && !n->selected;}) | std::ranges::to<VEC_SPTR_Node>(); auto neighbors = nodes | RANGE_FILTER([](SPTR_Node n){ return !n->dragging && !n->selected;}) | std::ranges::to<VEC_SPTR_Node>();
float min_d = 480; float min_d = 480;
for(auto n : nodes){ for(auto n : nodes){
@@ -247,16 +258,16 @@ class GraphManager{
Vector2 text_length = MeasureTextEx(GetFontDefault(), std::format("{:.1f}",dn).c_str(), 10.0f, 2.0f); Vector2 text_length = MeasureTextEx(GetFontDefault(), std::format("{:.1f}",dn).c_str(), 10.0f, 2.0f);
Vector2 text_length_frac = MeasureTextEx(GetFontDefault(), frac.c_str(), 10.0f, 2.0f); Vector2 text_length_frac = MeasureTextEx(GetFontDefault(), frac.c_str(), 10.0f, 2.0f);
Vec2D<float> middle_handle = nb->position + (n->position - nb->position) * ((dn - text_length.x)*0.5f)/dn; Vec2Df middle_handle = nb->position + (n->position - nb->position) * ((dn - text_length.x)*0.5f)/dn;
Vec2D<float> middle_handle_frac = nb->position + (n->position - nb->position) * ((dn - text_length_frac.x)*0.5f)/dn; Vec2Df middle_handle_frac = nb->position + (n->position - nb->position) * ((dn - text_length_frac.x)*0.5f)/dn;
Vec2D<float> text_position = middle_handle + (nb->position - n->position).norm().orth() * 12.0f; Vec2Df text_position = middle_handle + (nb->position - n->position).norm().orth() * 12.0f;
Vec2D<float> text_position_frac = middle_handle_frac - (nb->position - n->position).norm().orth() * 4.0f; Vec2Df text_position_frac = middle_handle_frac - (nb->position - n->position).norm().orth() * 4.0f;
float rotation = Vector2Angle((Vector2){1,0}, (n->position - nb->position)) * RAD2DEG; float rotation = Vector2Angle((Vector2){1,0}, (n->position - nb->position)) * RAD2DEG;
DrawTextPro(GetFontDefault(), std::format("{:.1f}",dn).c_str(), text_position, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK); DrawTextPro(GetFontDefault(), std::format("{:.1f}",dn).c_str(), text_position, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK);
if(nb == neighbors.front() && IsKeyDown(KEY_LEFT_SHIFT)) DrawTextPro(GetFontDefault(), frac.c_str(), text_position_frac, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK); if(nb == neighbors.front() && IsKeyDown(KEY_LEFT_SHIFT)) DrawTextPro(GetFontDefault(), frac.c_str(), text_position_frac, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK);
Vec2D<float> n_position = n->position - ((n->position - nb->position)).norm() * 20.0f; Vec2Df n_position = n->position - ((n->position - nb->position)).norm() * 20.0f;
Vec2D<float> nb_position = nb->position - ((nb->position - n->position)).norm() * 20.0f; Vec2Df nb_position = nb->position - ((nb->position - n->position)).norm() * 20.0f;
DrawLineV(n_position, nb_position, VS_COLOR_PINK); DrawLineV(n_position, nb_position, VS_COLOR_PINK);
} }
@@ -269,3 +280,14 @@ class GraphManager{
}; };
inline void to_json(json& j, const Node& N) {
std::vector<int> conns;
std::ranges::transform(N.connections.begin(), N.connections.end(), std::back_inserter(conns), [](SPTR_Edge e){ return e->id;});
j = json{{"neighbor", N.neighbor}, {"nodeType", N.nodeType}, {"distributionMode", N.distributionMode}, {"connections", conns}};
}
inline void from_json(const json& j, Node& N) {
}
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(GraphManager, nodes, edges)
+27 -25
View File
@@ -6,28 +6,30 @@
* *
*/ */
#include "midi-node.h"
#include <algorithm>
#include <iterator>
#include <memory>
#include <vector>
#define RAYGUI_IMPLEMENTATION #define RAYGUI_IMPLEMENTATION
#include "datatypes.h"
#include <ranges>
#include <raylib.h> #include <raylib.h>
#include <raymath.h> #include <raymath.h>
#include "state-manager.h"
#include "datatypes.h"
#include "midi-node.h"
#include "nlohmann/json.hpp"
#include <cstdlib> #include <cstdlib>
#include <stdio.h> #include <stdio.h>
#include <cmath> #include <cmath>
#include <ranges>
#include <algorithm>
#include <iterator>
#include <memory>
#include "state-manager.h" using json = nlohmann::json;
AppState app; AppState app;
Vec2D<float> mouse_pos; Vec2Df mouse_pos;
Vec2D<float> drag_start; Vec2Df drag_start;
Camera2D camera = { {0} }; Camera2D camera = { {0} };
@@ -71,17 +73,17 @@ int main(){
camera.zoom = 1.0f; camera.zoom = 1.0f;
for(int i = 0; i < 4; ++i){ for(int i = 0; i < 4; ++i){
app.gm.addMidiNode(Vec2D<float>{(float)i * app.settings.grid*4 + 7 * app.settings.grid, 2 * app.settings.grid*4}); app.gm.addMidiNode(Vec2Df{(float)i * app.settings.grid*4 + 7 * app.settings.grid, 2 * app.settings.grid*4});
} }
for(int i = 3; i >= 0; --i){ for(int i = 3; i >= 0; --i){
app.gm.addMidiNode(Vec2D<float>{(float)i * app.settings.grid*4 + 7 * app.settings.grid, 3 * app.settings.grid*4}); app.gm.addMidiNode(Vec2Df{(float)i * app.settings.grid*4 + 7 * app.settings.grid, 3 * app.settings.grid*4});
} }
for(int i = 0; i < 8; ++i){ for(int i = 0; i < 8; ++i){
app.gm.addConnection(app.gm.nodes[i], app.gm.nodes[(i+1) % 8]); app.gm.addConnection(app.gm.nodes[i], app.gm.nodes[(i+1) % 8]);
} }
std::cout << app.gm.nodes[0]->getNodeType() << std::endl; std::cout << std::setw(2) << json(app.gm) << std::endl;
app.sm.addSignalAtNode(app.gm.nodes.front()); app.sm.addSignalAtNode(app.gm.nodes.front());
app.sm.startSignalThread(); app.sm.startSignalThread();
@@ -89,7 +91,7 @@ int main(){
enum InteractionState {HOVER_CANVAS, HOVER_NODE, HOVER_CONNECTOR, DRAG_NODE, CONNECT_NODE, DRAW_SELECTION, DELETE_SELECTED_NODES, COPY_SELECTED_NODES, PASTE_SELECTED_NODES}; enum InteractionState {HOVER_CANVAS, HOVER_NODE, HOVER_CONNECTOR, DRAG_NODE, CONNECT_NODE, DRAW_SELECTION, DELETE_SELECTED_NODES, COPY_SELECTED_NODES, PASTE_SELECTED_NODES};
InteractionState istate = HOVER_CANVAS; InteractionState istate = HOVER_CANVAS;
Vec2D<float> select_start; Vec2Df select_start;
Rectangle selection; Rectangle selection;
VEC_SPTR_Node copied_nodes; VEC_SPTR_Node copied_nodes;
@@ -103,8 +105,8 @@ int main(){
app.settings.speed = (app.settings.grid * 16.0f) * (app.settings.bpm / 120.f); app.settings.speed = (app.settings.grid * 16.0f) * (app.settings.bpm / 120.f);
Vector2 mp = GetScreenToWorld2D(GetMousePosition(), camera); Vector2 mp = GetScreenToWorld2D(GetMousePosition(), camera);
Vec2D<float> mouse_pos = {(float)mp.x, (float)mp.y}; Vec2Df mouse_pos = {(float)mp.x, (float)mp.y};
Vec2D<float> cam_pos = {camera.offset.x, camera.offset.y}; Vec2Df cam_pos = {camera.offset.x, camera.offset.y};
bool mouse_down = IsMouseButtonDown(MOUSE_BUTTON_LEFT); bool mouse_down = IsMouseButtonDown(MOUSE_BUTTON_LEFT);
bool mouse_clicked = IsMouseButtonPressed(MOUSE_BUTTON_LEFT); bool mouse_clicked = IsMouseButtonPressed(MOUSE_BUTTON_LEFT);
@@ -114,8 +116,8 @@ int main(){
bool mouse_right_clicked = IsMouseButtonPressed(MOUSE_BUTTON_RIGHT); bool mouse_right_clicked = IsMouseButtonPressed(MOUSE_BUTTON_RIGHT);
bool mouse_right_released = IsMouseButtonReleased(MOUSE_BUTTON_RIGHT); bool mouse_right_released = IsMouseButtonReleased(MOUSE_BUTTON_RIGHT);
Vec2D<float> mouse_delta = {GetMouseDelta().x, GetMouseDelta().y}; Vec2Df mouse_delta = {GetMouseDelta().x, GetMouseDelta().y};
Vec2D<float> delta = mouse_delta * (-1.0f/camera.zoom); Vec2Df delta = mouse_delta * (-1.0f/camera.zoom);
auto dragging_nodes = app.gm.nodes | RANGE_FILTER([](SPTR_Node n) { return n->dragging;}); auto dragging_nodes = app.gm.nodes | RANGE_FILTER([](SPTR_Node n) { return n->dragging;});
auto connecting_nodes = app.gm.nodes | RANGE_FILTER([](SPTR_Node n) { return n->connecting;}); auto connecting_nodes = app.gm.nodes | RANGE_FILTER([](SPTR_Node n) { return n->connecting;});
@@ -163,8 +165,8 @@ int main(){
select_start = mouse_pos; select_start = mouse_pos;
} }
if(mouse_down){ if(mouse_down){
Vec2D<float> select1 = {mouse_pos.x > select_start.x ? select_start.x : mouse_pos.x, mouse_pos.y > select_start.y ? select_start.y : mouse_pos.y}; Vec2Df select1 = {mouse_pos.x > select_start.x ? select_start.x : mouse_pos.x, mouse_pos.y > select_start.y ? select_start.y : mouse_pos.y};
Vec2D<float> select2 = {mouse_pos.x > select_start.x ? mouse_pos.x - select_start.x : select_start.x - mouse_pos.x, mouse_pos.y > select_start.y ? mouse_pos.y - select_start.y : select_start.y - mouse_pos.y}; Vec2Df select2 = {mouse_pos.x > select_start.x ? mouse_pos.x - select_start.x : select_start.x - mouse_pos.x, mouse_pos.y > select_start.y ? mouse_pos.y - select_start.y : select_start.y - mouse_pos.y};
DrawRectangleLines(select1.x, select1.y, select2.x, select2.y, (Color){150,150,150,150}); DrawRectangleLines(select1.x, select1.y, select2.x, select2.y, (Color){150,150,150,150});
selection = (Rectangle){select1.x, select1.y, select2.x, select2.y}; selection = (Rectangle){select1.x, select1.y, select2.x, select2.y};
@@ -219,9 +221,9 @@ int main(){
} else if(IsKeyDown(KEY_LEFT_SHIFT)){ } else if(IsKeyDown(KEY_LEFT_SHIFT)){
float steps = round((dragNode->neighbor->position.dist(mouse_pos)) / app.settings.grid) * app.settings.grid; float steps = round((dragNode->neighbor->position.dist(mouse_pos)) / app.settings.grid) * app.settings.grid;
float pol_r = steps; float pol_r = steps;
float pol_theta = Vector2Angle(Vec2D<float>{1,0},(mouse_pos - dragNode->neighbor->position)); float pol_theta = Vector2Angle(Vec2Df{1,0},(mouse_pos - dragNode->neighbor->position));
Vec2D<float> polar = polarToCartesian(pol_r, pol_theta); Vec2Df polar = VMath::polarToCartesian(pol_r, pol_theta);
dragNode->position = dragNode->neighbor->position + polar; dragNode->position = dragNode->neighbor->position + polar;
} else { } else {
dragNode->position = mouse_pos + dragNode->drag_offset; dragNode->position = mouse_pos + dragNode->drag_offset;
@@ -254,7 +256,7 @@ int main(){
} }
case InteractionState::CONNECT_NODE: case InteractionState::CONNECT_NODE:
{ {
Vec2D<float> connector_position = connecting_nodes.front()->position - ((connecting_nodes.front()->position - mouse_pos)).norm() * (connecting_nodes.front()->radius + 14.0f); Vec2Df connector_position = connecting_nodes.front()->position - ((connecting_nodes.front()->position - mouse_pos)).norm() * (connecting_nodes.front()->radius + 14.0f);
if(connecting_nodes.front()->connecting && mouse_down){ if(connecting_nodes.front()->connecting && mouse_down){
DrawLine(connector_position.x, connector_position.y, mouse_pos.x, mouse_pos.y, (Color){229, 181, 103, 255}); DrawLine(connector_position.x, connector_position.y, mouse_pos.x, mouse_pos.y, (Color){229, 181, 103, 255});
@@ -312,7 +314,7 @@ int main(){
if(!hovering_nodes.empty() && hovering_nodes.front()->getNodeType() == NodeType::MIDINODE) { if(!hovering_nodes.empty() && hovering_nodes.front()->getNodeType() == NodeType::MIDINODE) {
VEC_SPTR_Node modify_nodes; VEC_SPTR_Node modify_nodes;
std::copy_if(selected_nodes.begin(), selected_nodes.end(), std::back_inserter(modify_nodes), [](SPTR_Node n){ return n->getNodeType() == NodeType::MIDINODE;}); std::copy_if(selected_nodes.begin(), selected_nodes.end(), std::back_inserter(modify_nodes), [](SPTR_Node n){ return n->getNodeType() == NodeType::MIDINODE;});
std::copy_if(hovering_nodes.begin(), hovering_nodes.end(), std::back_inserter(modify_nodes), [modify_nodes](SPTR_Node n){ return n->getNodeType() == NodeType::MIDINODE && !std::ranges::contains(modify_nodes, n);}); if(selected_nodes.empty()) std::copy_if(hovering_nodes.begin(), hovering_nodes.end(), std::back_inserter(modify_nodes), [modify_nodes](SPTR_Node n){ return n->getNodeType() == NodeType::MIDINODE && !std::ranges::contains(modify_nodes, n);});
for(auto n : modify_nodes){ for(auto n : modify_nodes){
std::shared_ptr<MidiNode> midiNode = std::dynamic_pointer_cast<MidiNode>(n); std::shared_ptr<MidiNode> midiNode = std::dynamic_pointer_cast<MidiNode>(n);
+8 -4
View File
@@ -5,7 +5,7 @@
#include "raymath.h" #include "raymath.h"
#include <map> #include <map>
#define R 14.0f #define RADIUS 14.0f
struct NodeMidiOut{ struct NodeMidiOut{
int i; int i;
@@ -13,12 +13,14 @@ struct NodeMidiOut{
bool enabled; bool enabled;
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(NodeMidiOut, i, name, enabled)
class MidiNode : public Node{ class MidiNode : public Node{
public: public:
MidiNode() {} MidiNode() {}
MidiNode(Vec2D<float> position) : Node(position) {} MidiNode(Vec2Df position) : Node(position) {}
NodeType nodeType = NodeType::MIDINODE; NodeType nodeType = NodeType::MIDINODE;
@@ -81,7 +83,7 @@ class MidiNode : public Node{
return midi_gate; return midi_gate;
} }
void draw(Vec2D<float> mouse, Camera2D cam) override { void draw(Vec2Df mouse, Camera2D cam) override {
last = time; last = time;
time = GetTime(); time = GetTime();
if(time - start >= (float)midi_gate / 1000.0f){ if(time - start >= (float)midi_gate / 1000.0f){
@@ -155,7 +157,7 @@ class MidiNode : public Node{
} }
} }
Vec2D<float> connector = position - ((position - mouse)).norm() * (radius + R); Vec2Df connector = position - ((position - mouse)).norm() * (radius + RADIUS);
float opacity = 150.0f - Clamp(position.dist(mouse), 0.0f, 150.0f); float opacity = 150.0f - Clamp(position.dist(mouse), 0.0f, 150.0f);
if(hover_connect){ if(hover_connect){
@@ -166,3 +168,5 @@ class MidiNode : public Node{
if(highlighted) DrawCircleLinesV(position, radius+2, (Color){255, 0, 0, 200}); if(highlighted) DrawCircleLinesV(position, radius+2, (Color){255, 0, 0, 200});
} }
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(MidiNode, id, nodeType, send_note, send_cc, send_pc, send_pitch_bend, midi_outs, mode, midi_note_channel, midi_note, midi_velocity, midi_gate, midi_cc_channel, midi_cc, midi_cc_value, midi_pc_channel, midi_pc, midi_pc_value, midi_pitch_bend_channel, midi_pitch_bend)
-2
View File
@@ -127,5 +127,3 @@ class Midi {
} }
} }
}; };
+14 -7
View File
@@ -2,21 +2,22 @@
#include "datatypes.h" #include "datatypes.h"
class Movable{ class Movable{
public: public:
Movable() {} Movable() {}
virtual ~Movable() {} virtual ~Movable() {}
Movable(Vec2D<float> p, Vec2D<float> d, float s) : speed(s), position(p), direction(d) {} Movable(Vec2Df p, Vec2Df d, float s) : speed(s), position(p), direction(d) {}
Movable(Vec2D<float> p, float s) : speed(s), position(p) {} Movable(Vec2Df p, float s) : speed(s), position(p) {}
float speed = 1.0f; float speed = 1.0f;
Vec2D<float> position; Vec2Df position;
Vec2D<float> direction; Vec2Df direction;
Vec2D<float> drag_offset; Vec2Df drag_offset;
bool in_rect = false; bool in_rect = false;
@@ -31,8 +32,14 @@ class Movable{
bool erase = false; bool erase = false;
virtual void setPosition(Vec2D<float> _position) {position = _position;} virtual void setPosition(Vec2Df _position) {position = _position;}
virtual Vec2D<float> getPosition() {return position;}; virtual Vec2Df getPosition() {return position;};
virtual void update(double frametime) {}; virtual void update(double frametime) {};
virtual void update() {}; virtual void update() {};
/*virtual void to_json(json& j, const Movable& M){*/
/* j = json{{"position", M.position}, {"direction", M.direction}, {"speed", M.speed}};*/
/*}*/
}; };
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Movable, position, direction, speed)
+12 -4
View File
@@ -2,7 +2,8 @@
#include <raylib.h> #include <raylib.h>
#include "edge.h" #include "nlohmann/json.hpp"
#include "datatypes.h" #include "datatypes.h"
#include "graph-item.h" #include "graph-item.h"
#include "moveable.h" #include "moveable.h"
@@ -11,8 +12,8 @@ class Node : public Movable, public GraphItem{
public: public:
Node() {} Node() {}
Node(float x, float y) : Movable(Vec2D<float>(x, y), 0.0f) {} Node(float x, float y) : Movable(Vec2Df(x, y), 0.0f) {}
Node(Vec2D<float> p) : Movable(p, 0.0f) {} Node(Vec2Df p) : Movable(p, 0.0f) {}
NodeType nodeType; NodeType nodeType;
@@ -31,5 +32,12 @@ class Node : public Movable, public GraphItem{
virtual int GGate() {return 0;}; virtual int GGate() {return 0;};
virtual int GActive() {return 0;}; virtual int GActive() {return 0;};
virtual void trigger() {}; virtual void trigger() {};
void draw(Vec2D<float> mouse_pos, Camera2D cam) {} void draw(Vec2Df mouse_pos, Camera2D cam) override {}
}; };
/*inline void to_json(json& j, const std::shared_ptr<Node>& N){*/
/* j = json{{"id", N->id}, {"nodeType",N->nodeType}};*/
/*}*/
//NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Node, nodeType, neighbor, connections, distributionMode)
//NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Node, id, nodeType, distributionMode)
+3 -3
View File
@@ -41,7 +41,7 @@ class SignalManager{
void reset(){ void reset(){
for(auto &s : signals){ for(auto &s : signals){
s->position = s->start->position + Vec2D<float>{0.1, 0.1}; s->position = s->start->position + Vec2Df{0.1, 0.1};
s->next = s->start; s->next = s->start;
s->last = s->start; s->last = s->start;
} }
@@ -59,7 +59,7 @@ class SignalManager{
void addSignalAtNode(SPTR_Node node){ void addSignalAtNode(SPTR_Node node){
Color c = {(unsigned char)(20 + (rand() % 200)), 100, (unsigned char)(20 + (int)(rand() % 200)), 200}; Color c = {(unsigned char)(20 + (rand() % 200)), 100, (unsigned char)(20 + (int)(rand() % 200)), 200};
signals.emplace_back(std::make_shared<Signal>(node->position + Vec2D<float>{0.5f, 0.5f}, 8.0f, 0, c)); // position + 1 or else it does not render. why? no idea! signals.emplace_back(std::make_shared<Signal>(node->position + Vec2Df{0.5f, 0.5f}, 8.0f, 0, c)); // position + 1 or else it does not render. why? no idea!
signals.back()->next = node; signals.back()->next = node;
signals.back()->last = node; signals.back()->last = node;
signals.back()->start = node; signals.back()->start = node;
@@ -105,7 +105,7 @@ class SignalManager{
} }
} }
void drawSignals(Vec2D<float> mouse_pos, Camera2D camera){ void drawSignals(Vec2Df mouse_pos, Camera2D camera){
for(auto s : signals){ for(auto s : signals){
mutex->lock(); mutex->lock();
s->draw(mouse_pos, camera); s->draw(mouse_pos, camera);
+2 -2
View File
@@ -9,7 +9,7 @@ class Signal : public Movable{
public: public:
Signal(); Signal();
Signal(Vec2D<float> position, float r, float _speed, Color color) : Movable(position, Vec2D<float>(0,0), _speed), radius(r), color(color) {} Signal(Vec2Df position, float r, float _speed, Color color) : Movable(position, Vec2Df(0,0), _speed), radius(r), color(color) {}
SPTR_Node next; SPTR_Node next;
SPTR_Node last; SPTR_Node last;
@@ -32,7 +32,7 @@ class Signal : public Movable{
position += direction.norm() * speed * multiplier * (float)t_delta / 1000000.0f; position += direction.norm() * speed * multiplier * (float)t_delta / 1000000.0f;
} }
void draw(Vec2D<float> mouse, Camera2D cam) { void draw(Vec2Df mouse, Camera2D cam) {
DrawCircle(position.x, position.y, radius, color); DrawCircle(position.x, position.y, radius, color);
} }
}; };
+3 -3
View File
@@ -45,7 +45,7 @@ class AppState{
} }
} }
void copyNodesAndConnections(VEC_SPTR_Node nodes, Vec2D<float> position){ void copyNodesAndConnections(VEC_SPTR_Node nodes, Vec2Df position){
VEC_SPTR_Edge copy_connections; VEC_SPTR_Edge copy_connections;
for(auto n : nodes){ for(auto n : nodes){
@@ -129,7 +129,7 @@ class AppState{
std::erase_if(gm.nodes, [nodes](SPTR_Node n){ return std::ranges::contains(nodes, n);}); std::erase_if(gm.nodes, [nodes](SPTR_Node n){ return std::ranges::contains(nodes, n);});
} }
void draw(Vec2D<float> mouse_pos, Camera2D camera){ void draw(Vec2Df mouse_pos, Camera2D camera){
mutex.lock(); mutex.lock();
updateMidiPorts(); updateMidiPorts();
mutex.unlock(); mutex.unlock();
@@ -138,7 +138,7 @@ class AppState{
sm.drawSignals(mouse_pos, camera); sm.drawSignals(mouse_pos, camera);
} }
void drawUI(Vec2D<float> *mouse_pos, Camera2D *camera){ void drawUI(Vec2Df *mouse_pos, Camera2D *camera){
mutex.lock(); mutex.lock();
ui.draw(mouse_pos, camera); ui.draw(mouse_pos, camera);
mutex.unlock(); mutex.unlock();
+2 -2
View File
@@ -83,7 +83,7 @@ class AppUI{
int s_nodes = s_signal + 70 + signal_configs*20; int s_nodes = s_signal + 70 + signal_configs*20;
GuiLabel((Rectangle){20, (float)s_nodes + 30, 240, 20}, "NODES"); GuiLabel((Rectangle){20, (float)s_nodes + 30, 240, 20}, "NODES");
if(GuiButton((Rectangle){20, (float)s_nodes + 60, 240, 20}, "ADD RANDOM NODE")){ if(GuiButton((Rectangle){20, (float)s_nodes + 60, 240, 20}, "ADD RANDOM NODE")){
gm->addMidiNode(Vec2D<float>{200.0f, 200.0f}); gm->addMidiNode(Vec2Df{200.0f, 200.0f});
} }
DrawText(std::format("{}", gm->nodes.size()).c_str(), 20, settings->height - 70, 15, VS_COLOR_WHITE); DrawText(std::format("{}", gm->nodes.size()).c_str(), 20, settings->height - 70, 15, VS_COLOR_WHITE);
DrawFPS(20, settings->height - 30); DrawFPS(20, settings->height - 30);
@@ -179,7 +179,7 @@ class AppUI{
} }
} }
void draw(Vec2D<float> *mouse_pos, Camera2D *camera){ void draw(Vec2Df *mouse_pos, Camera2D *camera){
drawSideBar(); drawSideBar();
drawPerNodeConfig(camera); drawPerNodeConfig(camera);
} }
+160
View File
@@ -0,0 +1,160 @@
#pragma once
#include "raylib.h"
#include <cmath>
#include "nlohmann/json.hpp"
using json = nlohmann::json;
namespace VMath{
template<typename T>
class Vec2D{
public:
Vec2D() {};
Vec2D(T x, T y) : x(x), y(y) {}
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));};
T angle(Vec2D v){
T angle = atan2(v.y, v.x) - atan2(y,x);
if(angle > M_PI) angle -= M_PI_2;
if(angle < -M_PI) angle += M_PI_2;
return angle;
//return acos(dot(v));
};
T angleDeg(Vec2D v){
return angle(v) * 180 / M_PI;
};
T dot(Vec2D &v){
return (x*v.x) + (y*v.y);
};
T dot(Vec2D v){
return (x*v.x) + (y*v.y);
};
operator Vector2() const {
return (Vector2){x,y};
}
Vec2D orth(Vec2D &v){
return Vec2D(-v.y, v.x);
};
Vec2D orth(){
return Vec2D(-y, x);
};
Vec2D norm() { return *this / length();};
Vec2D center(Vec2D v){
return Vec2D<T>{x,y} - (Vec2D<T>{x,y} - v)*0.5f;
}
Vec2D& operator=(const Vec2D& vec){
if (this == &vec){
return *this;
}
x = vec.x;
y = vec.y;
return *this;
};
Vec2D& operator+=(const Vec2D& vec){
this->x += vec.x;
this->y += vec.y;
return *this;
};
Vec2D& operator-=(const Vec2D& vec){
this->x -= vec.x;
this->y -= vec.y;
return *this;
};
Vec2D& operator*=(const Vec2D& vec){
this->x *= vec.x;
this->y *= vec.y;
return *this;
};
Vec2D& operator/=(const Vec2D& vec){
this->x /= vec.x;
this->y /= vec.y;
return *this;
};
Vec2D& operator*=(T scalar){
this->x *= scalar;
this->y *= scalar;
return *this;
};
Vec2D& operator/=(T scalar){
this->x /= scalar;
this->y /= scalar;
return *this;
};
};
template<typename T>
void to_json(json& j, const Vec2D<T> V){
j = json{{"x",V.x},{"y",V.y}};
}
template<typename T>
void from_json(const json& j, Vec2D<T> V){
j.at("x").get_to(V.x);
j.at("y").get_to(V.y);
}
template<typename T>
Vec2D<T> operator+(const Vec2D<T> left, const Vec2D<T> right){
return Vec2D<T>(left.x + right.x, left.y + right.y);
};
template<typename T>
Vec2D<T> operator-(const Vec2D<T> left, const Vec2D<T> right){
return Vec2D<T>(left.x - right.x, left.y - right.y);
};
template<typename T>
Vec2D<T> operator*(const Vec2D<T> left, const Vec2D<T> right){
return Vec2D<T>(left.x * right.x, left.y * right.y);
};
template<typename T>
Vec2D<T> operator/(const Vec2D<T> left, const Vec2D<T> right){
return Vec2D<T>(left.x / right.x, left.y / right.y);
};
template<typename T>
Vec2D<T> operator/(const Vec2D<T> left, T scalar){
return Vec2D<T>(left.x / scalar, left.y / scalar);
};
template<typename T>
Vec2D<T> operator*(const Vec2D<T> left, T scalar){
return Vec2D<T>(left.x * scalar, left.y * scalar);
};
template<typename T>
Vec2D<T> cartesianToPolar(T x, T y) {
return Vec2D<T>{sqrt(x * x + y * y), atan(y / x)}; // r,theta
}
template<typename T>
Vec2D<T> polarToCartesian(T r, T q) {
return Vec2D<T>{r * cos(q), r * sin(q)};
}
}