Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9e284be109 | |||
| c7c489fde5 | |||
| 1f7f5314a3 | |||
| 1f2cbc4c31 | |||
| 183d89ceaf | |||
| 0be3d6cd77 | |||
| 4613bfd072 | |||
| 585e5e1167 | |||
| 30408393e7 | |||
| e9c8cc9aea | |||
| 03b2989130 | |||
| e9c2872187 | |||
| b9ad5293bf | |||
| e4b2df21bc | |||
| 970faad32d | |||
| 0fb517f282 | |||
| 9fefa903bd | |||
| 3f8984b69f | |||
| 9ea1305c27 | |||
| 7c7c3b37ff | |||
| 792e537f2b |
@@ -9,13 +9,17 @@ LDFLAGS := -Llib -L/usr/lib -L/usr/local/lib
|
|||||||
|
|
||||||
SRCS := $(wildcard src/*.cpp)
|
SRCS := $(wildcard src/*.cpp)
|
||||||
OBJECTS := $(patsubst src/%.cpp,build/%.o, $(SRCS))
|
OBJECTS := $(patsubst src/%.cpp,build/%.o, $(SRCS))
|
||||||
|
DEPENDS := $(patsubst src/%.cpp,build/%.d, $(SRCS))
|
||||||
|
|
||||||
viseq: $(OBJECTS)
|
viseq: $(OBJECTS)
|
||||||
$(CXX) $(OBJECTS) -o $@ $(LDFLAGS) $(LDLIBS)
|
$(CXX) $(OBJECTS) -o $@ $(LDFLAGS) $(LDLIBS)
|
||||||
|
|
||||||
$(OBJECTS): build/%.o : src/%.cpp
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#$(OBJECTS): build/%.o : src/%.cpp
|
||||||
|
build/%.o: src/%.cpp Makefile
|
||||||
@mkdir -p build
|
@mkdir -p build
|
||||||
$(CXX) -c $< -o $@ $(CXXFLAGS) $(CXXINC)
|
$(CXX) -c $< -o $@ $(CXXFLAGS) $(CXXINC) -MMD -MP
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f build/*
|
rm -f build/*
|
||||||
|
|||||||
@@ -0,0 +1,122 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="512"
|
||||||
|
height="512"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
inkscape:export-filename="blocker_closed.png"
|
||||||
|
inkscape:export-xdpi="24"
|
||||||
|
inkscape:export-ydpi="24"
|
||||||
|
inkscape:version="1.4.4 (dcaf3e7d9e, 2026-05-05)"
|
||||||
|
sodipodi:docname="block.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:zoom="1.1398148"
|
||||||
|
inkscape:cx="87.294883"
|
||||||
|
inkscape:cy="268.026"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1414"
|
||||||
|
inkscape:window-x="2560"
|
||||||
|
inkscape:window-y="1106"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="g5">
|
||||||
|
<sodipodi:guide
|
||||||
|
position="0,256"
|
||||||
|
orientation="0,1"
|
||||||
|
id="guide1"
|
||||||
|
inkscape:locked="false"
|
||||||
|
inkscape:label=""
|
||||||
|
inkscape:color="rgb(0,134,229)" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="256,256"
|
||||||
|
orientation="1,0"
|
||||||
|
id="guide2"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs1" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Blocker Open"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
style="display:none">
|
||||||
|
<rect
|
||||||
|
style="fill:#b4d273;fill-opacity:1;fill-rule:evenodd;stroke-width:0.742756"
|
||||||
|
id="rect1"
|
||||||
|
width="282.46313"
|
||||||
|
height="512"
|
||||||
|
x="114.76843"
|
||||||
|
y="0"
|
||||||
|
ry="141.23157" />
|
||||||
|
<rect
|
||||||
|
style="fill:#d6d6d6;fill-opacity:1;fill-rule:evenodd;stroke-width:0.950718"
|
||||||
|
id="rect2"
|
||||||
|
width="379.43814"
|
||||||
|
height="45.092152"
|
||||||
|
x="-445.71906"
|
||||||
|
y="233.45392"
|
||||||
|
transform="rotate(-90)" />
|
||||||
|
<circle
|
||||||
|
style="fill:#d6d6d6;fill-opacity:1"
|
||||||
|
id="path1"
|
||||||
|
cx="255.99994"
|
||||||
|
cy="106.15759"
|
||||||
|
r="56.149471" />
|
||||||
|
<circle
|
||||||
|
style="fill:#d6d6d6;fill-opacity:1"
|
||||||
|
id="path1-0"
|
||||||
|
cx="256"
|
||||||
|
cy="407.41348"
|
||||||
|
r="56.149471" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
inkscape:label="Blocker Closed"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="g5"
|
||||||
|
transform="rotate(-90,256,256)">
|
||||||
|
<rect
|
||||||
|
style="fill:#c35355;fill-opacity:1;fill-rule:evenodd;stroke-width:0.742756"
|
||||||
|
id="rect3"
|
||||||
|
width="282.46313"
|
||||||
|
height="512"
|
||||||
|
x="114.76843"
|
||||||
|
y="0"
|
||||||
|
ry="141.23157" />
|
||||||
|
<rect
|
||||||
|
style="fill:#d6d6d6;fill-opacity:1;fill-rule:evenodd;stroke-width:0.950718"
|
||||||
|
id="rect4"
|
||||||
|
width="379.43814"
|
||||||
|
height="45.092152"
|
||||||
|
x="-445.71906"
|
||||||
|
y="233.45392"
|
||||||
|
transform="rotate(-90)" />
|
||||||
|
<circle
|
||||||
|
style="fill:#d6d6d6;fill-opacity:1"
|
||||||
|
id="circle4"
|
||||||
|
cx="255.99994"
|
||||||
|
cy="106.15759"
|
||||||
|
r="56.149471" />
|
||||||
|
<circle
|
||||||
|
style="fill:#d6d6d6;fill-opacity:1"
|
||||||
|
id="circle5"
|
||||||
|
cx="256"
|
||||||
|
cy="407.41348"
|
||||||
|
r="56.149471" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.2 KiB |
@@ -0,0 +1,81 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="512"
|
||||||
|
height="512"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
inkscape:export-filename="round-delete.png"
|
||||||
|
inkscape:export-xdpi="24"
|
||||||
|
inkscape:export-ydpi="24"
|
||||||
|
inkscape:version="1.4.4 (dcaf3e7d9e, 2026-05-05)"
|
||||||
|
sodipodi:docname="textures.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:zoom="1.1398148"
|
||||||
|
inkscape:cx="87.73355"
|
||||||
|
inkscape:cy="268.026"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1414"
|
||||||
|
inkscape:window-x="2560"
|
||||||
|
inkscape:window-y="1106"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1">
|
||||||
|
<sodipodi:guide
|
||||||
|
position="0,256"
|
||||||
|
orientation="0,1"
|
||||||
|
id="guide1"
|
||||||
|
inkscape:locked="false"
|
||||||
|
inkscape:label=""
|
||||||
|
inkscape:color="rgb(0,134,229)" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="256,256"
|
||||||
|
orientation="1,0"
|
||||||
|
id="guide2"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs1" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<circle
|
||||||
|
style="fill:#c35355;fill-opacity:1"
|
||||||
|
id="path2"
|
||||||
|
cx="256"
|
||||||
|
cy="256"
|
||||||
|
r="256" />
|
||||||
|
<rect
|
||||||
|
style="fill:#d6d6d6;fill-opacity:1;fill-rule:evenodd"
|
||||||
|
id="rect2"
|
||||||
|
width="419.79556"
|
||||||
|
height="45.092152"
|
||||||
|
x="-571.93646"
|
||||||
|
y="-22.546076"
|
||||||
|
transform="rotate(-135)" />
|
||||||
|
<rect
|
||||||
|
style="fill:#d6d6d6;fill-opacity:1;fill-rule:evenodd"
|
||||||
|
id="rect2-0"
|
||||||
|
width="419.79556"
|
||||||
|
height="45.092152"
|
||||||
|
x="-209.89778"
|
||||||
|
y="339.49261"
|
||||||
|
transform="rotate(-45)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -0,0 +1,96 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="512"
|
||||||
|
height="512"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
inkscape:export-filename="textures/split.png"
|
||||||
|
inkscape:export-xdpi="24"
|
||||||
|
inkscape:export-ydpi="24"
|
||||||
|
inkscape:version="1.4.4 (dcaf3e7d9e, 2026-05-05)"
|
||||||
|
sodipodi:docname="split.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:zoom="0.80597077"
|
||||||
|
inkscape:cx="-42.805522"
|
||||||
|
inkscape:cy="129.65731"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1414"
|
||||||
|
inkscape:window-x="2560"
|
||||||
|
inkscape:window-y="1106"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1">
|
||||||
|
<sodipodi:guide
|
||||||
|
position="0,256"
|
||||||
|
orientation="0,1"
|
||||||
|
id="guide1"
|
||||||
|
inkscape:locked="false"
|
||||||
|
inkscape:label=""
|
||||||
|
inkscape:color="rgb(0,134,229)" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="256,256"
|
||||||
|
orientation="1,0"
|
||||||
|
id="guide2"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs1" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<rect
|
||||||
|
style="fill:#b4d273;fill-opacity:1;fill-rule:evenodd;stroke-width:0.742756"
|
||||||
|
id="rect1"
|
||||||
|
width="282.46313"
|
||||||
|
height="512"
|
||||||
|
x="-1027.9529"
|
||||||
|
y="0"
|
||||||
|
ry="141.23157" />
|
||||||
|
<circle
|
||||||
|
style="fill:#b4d273;fill-opacity:1"
|
||||||
|
id="path2"
|
||||||
|
cx="256"
|
||||||
|
cy="256"
|
||||||
|
r="256" />
|
||||||
|
<circle
|
||||||
|
style="fill:#d6d6d6;fill-opacity:1;stroke-width:0.832073"
|
||||||
|
id="path2-7"
|
||||||
|
cx="256"
|
||||||
|
cy="256"
|
||||||
|
r="213.01056" />
|
||||||
|
<rect
|
||||||
|
style="fill:#b4d273;fill-opacity:1;fill-rule:evenodd"
|
||||||
|
id="rect2"
|
||||||
|
width="45.621445"
|
||||||
|
height="300.92609"
|
||||||
|
x="233.18927"
|
||||||
|
y="105.53696"
|
||||||
|
ry="22.810722" />
|
||||||
|
<rect
|
||||||
|
style="fill:#b4d273;fill-opacity:1;fill-rule:evenodd"
|
||||||
|
id="rect2-6"
|
||||||
|
width="45.621445"
|
||||||
|
height="300.92609"
|
||||||
|
x="233.18927"
|
||||||
|
y="-406.46304"
|
||||||
|
ry="22.810722"
|
||||||
|
transform="rotate(90)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.6 KiB |
@@ -0,0 +1,81 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="512"
|
||||||
|
height="512"
|
||||||
|
viewBox="0 0 512 512"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
inkscape:export-filename="round-delete.png"
|
||||||
|
inkscape:export-xdpi="24"
|
||||||
|
inkscape:export-ydpi="24"
|
||||||
|
inkscape:version="1.4.4 (dcaf3e7d9e, 2026-05-05)"
|
||||||
|
sodipodi:docname="textures.svg"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="namedview1"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#000000"
|
||||||
|
borderopacity="0.25"
|
||||||
|
inkscape:showpageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pagecheckerboard="0"
|
||||||
|
inkscape:deskcolor="#d1d1d1"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:zoom="1.1398148"
|
||||||
|
inkscape:cx="87.73355"
|
||||||
|
inkscape:cy="268.026"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1414"
|
||||||
|
inkscape:window-x="2560"
|
||||||
|
inkscape:window-y="1106"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1">
|
||||||
|
<sodipodi:guide
|
||||||
|
position="0,256"
|
||||||
|
orientation="0,1"
|
||||||
|
id="guide1"
|
||||||
|
inkscape:locked="false"
|
||||||
|
inkscape:label=""
|
||||||
|
inkscape:color="rgb(0,134,229)" />
|
||||||
|
<sodipodi:guide
|
||||||
|
position="256,256"
|
||||||
|
orientation="1,0"
|
||||||
|
id="guide2"
|
||||||
|
inkscape:locked="false" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs1" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<circle
|
||||||
|
style="fill:#c35355;fill-opacity:1"
|
||||||
|
id="path2"
|
||||||
|
cx="256"
|
||||||
|
cy="256"
|
||||||
|
r="256" />
|
||||||
|
<rect
|
||||||
|
style="fill:#d6d6d6;fill-opacity:1;fill-rule:evenodd"
|
||||||
|
id="rect2"
|
||||||
|
width="419.79556"
|
||||||
|
height="45.092152"
|
||||||
|
x="-571.93646"
|
||||||
|
y="-22.546076"
|
||||||
|
transform="rotate(-135)" />
|
||||||
|
<rect
|
||||||
|
style="fill:#d6d6d6;fill-opacity:1;fill-rule:evenodd"
|
||||||
|
id="rect2-0"
|
||||||
|
width="419.79556"
|
||||||
|
height="45.092152"
|
||||||
|
x="-209.89778"
|
||||||
|
y="339.49261"
|
||||||
|
transform="rotate(-45)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 29 KiB |
@@ -1,5 +1,6 @@
|
|||||||
#include "app-manager.h"
|
#include "app-manager.h"
|
||||||
|
|
||||||
|
#include "datatypes.h"
|
||||||
#include "interaction-manager.h"
|
#include "interaction-manager.h"
|
||||||
#include "nlohmann/json.hpp"
|
#include "nlohmann/json.hpp"
|
||||||
#include "graph-manager.h"
|
#include "graph-manager.h"
|
||||||
@@ -10,6 +11,7 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <raylib.h>
|
||||||
|
|
||||||
namespace VISEQ::APP{
|
namespace VISEQ::APP{
|
||||||
void AppManager::init(){
|
void AppManager::init(){
|
||||||
@@ -19,6 +21,25 @@ namespace VISEQ::APP{
|
|||||||
canvas->camera.zoom = 1.0f;
|
canvas->camera.zoom = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AppManager::loadTextures(){
|
||||||
|
TEXTURES::tex_connector = LoadTexture("resources/textures/connector.png");
|
||||||
|
TEXTURES::tex_connector_hover = LoadTexture("resources/textures/connector_hover.png");
|
||||||
|
TEXTURES::tex_connector_pressed = LoadTexture("resources/textures/connector_pressed.png");
|
||||||
|
TEXTURES::tex_connector_connected = LoadTexture("resources/textures/connector_connected.png");
|
||||||
|
TEXTURES::tex_delete = LoadTexture("resources/textures/delete.png");
|
||||||
|
TEXTURES::tex_split = LoadTexture("resources/textures/split.png");
|
||||||
|
TEXTURES::tex_blocker_open = LoadTexture("resources/textures/blocker_open.png");
|
||||||
|
TEXTURES::tex_blocker_closed= LoadTexture("resources/textures/blocker_closed.png");
|
||||||
|
TEXTURES::tex_delete_hover = LoadTexture("resources/textures/delete_hover.png");
|
||||||
|
TEXTURES::tex_split_hover = LoadTexture("resources/textures/split_hover.png");
|
||||||
|
TEXTURES::tex_blocker_open_hover = LoadTexture("resources/textures/blocker_open_hover.png");
|
||||||
|
TEXTURES::tex_blocker_closed_hover = LoadTexture("resources/textures/blocker_closed_hover.png");
|
||||||
|
TEXTURES::tex_delete_pressed = LoadTexture("resources/textures/delete_pressed.png");
|
||||||
|
TEXTURES::tex_split_pressed = LoadTexture("resources/textures/split_pressed.png");
|
||||||
|
TEXTURES::tex_blocker_open_pressed = LoadTexture("resources/textures/blocker_open_pressed.png");
|
||||||
|
TEXTURES::tex_blocker_closed_pressed = LoadTexture("resources/textures/blocker_closed_pressed.png");
|
||||||
|
}
|
||||||
|
|
||||||
void AppManager::close(){
|
void AppManager::close(){
|
||||||
std::ofstream file("state.json");
|
std::ofstream file("state.json");
|
||||||
file << json(*this);
|
file << json(*this);
|
||||||
@@ -154,8 +175,8 @@ namespace VISEQ::APP{
|
|||||||
canvas->drawStart();
|
canvas->drawStart();
|
||||||
canvas->draw();
|
canvas->draw();
|
||||||
|
|
||||||
gm->drawNodes(SCREEN_MOUSE, canvas->camera);
|
|
||||||
gm->drawEdges(SCREEN_MOUSE, canvas->camera);
|
gm->drawEdges(SCREEN_MOUSE, canvas->camera);
|
||||||
|
gm->drawNodes(SCREEN_MOUSE, canvas->camera);
|
||||||
sm->drawSignals(SCREEN_MOUSE, canvas->camera);
|
sm->drawSignals(SCREEN_MOUSE, canvas->camera);
|
||||||
|
|
||||||
im.draw();
|
im.draw();
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ namespace VISEQ::APP {
|
|||||||
UI::AppUI ui;
|
UI::AppUI ui;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
void loadTextures();
|
||||||
void close();
|
void close();
|
||||||
void startSignals();
|
void startSignals();
|
||||||
void loadState();
|
void loadState();
|
||||||
|
|||||||
@@ -12,6 +12,45 @@ inline bool ViButton(Vec2Df mp, float x, float y, float radius, Color 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 ViTexButton(Vec2Df mp, Vec2Df position, float rotation, float radius, Texture2D tex, Texture2D tex_hover, Texture2D tex_pressed, Color color){
|
||||||
|
float scale = (radius*2.0f) / (float)tex.width;
|
||||||
|
Vec2Df start_position = position - Vec2Df((tex.width*scale) / 2.0f, (tex.height*scale) / 2.0f);
|
||||||
|
Vec2Df center_pos = start_position.rotateAround(position, rotation);
|
||||||
|
bool hover = Vector2Distance(mp, position) < radius;
|
||||||
|
bool pressed = hover && IsMouseButtonPressed(MOUSE_BUTTON_LEFT);
|
||||||
|
|
||||||
|
if(!hover && !pressed) DrawTexturePro(tex, Rectangle(0.0, 0.0, tex.width, tex.height), Rectangle(center_pos.x, center_pos.y, tex.width*scale, tex.height*scale), Vec2Df(0.0f,tex.height*scale/2.0f), rotation, color);
|
||||||
|
if(hover) DrawTexturePro(tex_hover, Rectangle(0.0, 0.0, tex.width, tex.height), Rectangle(center_pos.x, center_pos.y, tex.width*scale, tex.height*scale), Vec2Df(0.0f,tex.height*scale/2.0f), rotation, color);
|
||||||
|
if(pressed) DrawTexturePro(tex_pressed, Rectangle(0.0, 0.0, tex.width, tex.height), Rectangle(center_pos.x, center_pos.y, tex.width*scale, tex.height*scale), Vec2Df(0.0f,tex.height*scale/2.0f), rotation, color);
|
||||||
|
|
||||||
|
return pressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ViTexButton(Vec2Df mp, Vec2Df position, float rotation, float radius, Texture2D tex, Texture2D tex_hover, Color color){
|
||||||
|
float scale = (radius*2.0f) / (float)tex.width;
|
||||||
|
Vec2Df start_position = position - Vec2Df((tex.width*scale) / 2.0f, (tex.height*scale) / 2.0f);
|
||||||
|
Vec2Df center_pos = start_position.rotateAround(position, rotation);
|
||||||
|
bool hover = Vector2Distance(mp, position) < radius;
|
||||||
|
bool pressed = hover && IsMouseButtonPressed(MOUSE_BUTTON_LEFT);
|
||||||
|
|
||||||
|
if(!hover) DrawTexturePro(tex, Rectangle(0.0, 0.0, tex.width, tex.height), Rectangle(center_pos.x, center_pos.y, tex.width*scale, tex.height*scale), Vec2Df(0.0f,tex.height*scale/2.0f), rotation, color);
|
||||||
|
if(hover) DrawTexturePro(tex_hover, Rectangle(0.0, 0.0, tex.width, tex.height), Rectangle(center_pos.x, center_pos.y, tex.width*scale, tex.height*scale), Vec2Df(0.0f,tex.height*scale/2.0f), rotation, color);
|
||||||
|
|
||||||
|
return pressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ViTexButton(Vec2Df mp, Vec2Df position, float rotation, float radius, Texture2D tex, Color color){
|
||||||
|
float scale = (radius*2.0f) / (float)tex.width;
|
||||||
|
Vec2Df start_position = position - Vec2Df((tex.width*scale) / 2.0f, (tex.height*scale) / 2.0f);
|
||||||
|
Vec2Df center_pos = start_position.rotateAround(position, rotation);
|
||||||
|
bool hover = Vector2Distance(mp, position) < radius;
|
||||||
|
bool pressed = hover && IsMouseButtonPressed(MOUSE_BUTTON_LEFT);
|
||||||
|
|
||||||
|
DrawTexturePro(tex, Rectangle(0.0, 0.0, tex.width, tex.height), Rectangle(center_pos.x, center_pos.y, tex.width*scale, tex.height*scale), Vec2Df(0.0f,tex.height*scale/2.0f), rotation, color);
|
||||||
|
|
||||||
|
return pressed;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool ViButton(Vec2Df mp, Vec2Df position, float radius, Color color){
|
inline bool ViButton(Vec2Df mp, Vec2Df position, float radius, Color color){
|
||||||
return ViButton(mp, position.x, position.y, radius, color);
|
return ViButton(mp, position.x, position.y, radius, color);
|
||||||
}
|
}
|
||||||
@@ -30,7 +69,12 @@ inline bool ViSegButton(Vec2Df mp, float x, float y, float start_angle, float en
|
|||||||
|
|
||||||
inline void DrawCenteredText(std::string text, Vec2Df position, float text_size, Color color){
|
inline void DrawCenteredText(std::string text, Vec2Df position, float text_size, Color color){
|
||||||
float offset = MeasureText(text.c_str(), text_size);
|
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);
|
//DrawText(text.c_str(), position.x-offset/2.0f, position.y-text_size/2.0f, text_size, color);
|
||||||
|
DrawTextEx(VISEQ::APP::inter, text.c_str(), Vec2Df(position.x-offset/2.0f, position.y-(float)text_size/2.0f+1), text_size, 2.0f, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void DrawText(std::string text, Vec2Df position, float text_size, Color color){
|
||||||
|
DrawText(text.c_str(), position.x, position.y-text_size/2.0f, text_size, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace VISEQ::APP::UI{
|
namespace VISEQ::APP::UI{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
//#include "interaction-event.h"
|
//#include "interaction-event.h"
|
||||||
|
#include "interaction-event.h"
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
#include "draggable.h"
|
#include "draggable.h"
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
@@ -59,8 +60,9 @@ namespace VISEQ::APP::CANVAS {
|
|||||||
if(state->mouse_right.down) {
|
if(state->mouse_right.down) {
|
||||||
camera.target = Vector2Add(camera.target, camera_delta);
|
camera.target = Vector2Add(camera.target, camera_delta);
|
||||||
}
|
}
|
||||||
|
if(clicked()) state->pushEvent({getPtr(), APP::Interaction::DESELECT});
|
||||||
|
|
||||||
if(hovering() && clicked()) state->pushEvent({getPtr(), APP::Interaction::PICKUP});
|
if(hovering() && held() && !pickedUp()) state->pushEvent({getPtr(), APP::Interaction::PICKUP});
|
||||||
if(pickedUp()) state->pushEvent({getPtr(), APP::Interaction::DRAG});
|
if(pickedUp()) state->pushEvent({getPtr(), APP::Interaction::DRAG});
|
||||||
if(picked_up && released()) state->pushEvent({getPtr(), APP::Interaction::PUTDOWN});
|
if(picked_up && released()) state->pushEvent({getPtr(), APP::Interaction::PUTDOWN});
|
||||||
|
|
||||||
|
|||||||
@@ -82,14 +82,14 @@ namespace VISEQ::GRAPH::NODES {
|
|||||||
|
|
||||||
void ConfigNode::update() {
|
void ConfigNode::update() {
|
||||||
Node::update();
|
Node::update();
|
||||||
mode = state->node_mode;
|
//mode = state->node_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigNode::interact(){
|
void ConfigNode::interact(){
|
||||||
float wheel = GetMouseWheelMove();
|
float wheel = GetMouseWheelMove();
|
||||||
|
|
||||||
if(KEYS_DOWN.ctrl && !KEYS_DOWN.alt){
|
if(KEYS_DOWN.ctrl && !KEYS_DOWN.alt){
|
||||||
switch(state->node_mode){
|
switch(mode){
|
||||||
case 0:{
|
case 0:{
|
||||||
midiNote.note += KEYS_DOWN.shift ? ((wheel > 0) - (wheel < 0)) * 12 : wheel;
|
midiNote.note += KEYS_DOWN.shift ? ((wheel > 0) - (wheel < 0)) * 12 : wheel;
|
||||||
break;}
|
break;}
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
#include "connector.h"
|
||||||
|
|
||||||
|
#include "helper.h"
|
||||||
|
#include "node.h"
|
||||||
|
#include "raymath.h"
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
#include "button.h"
|
||||||
|
#include <execution>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
|
namespace VISEQ::GRAPH {
|
||||||
|
GraphItemType Connector::getType() {
|
||||||
|
return GraphItemType::CONNECTOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Connector> Connector::getPtr(){
|
||||||
|
return shared_from_this();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Connector::hovering() {
|
||||||
|
return partner.expired() && CheckCollisionPointCircle(SCREEN_MOUSE, position, radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connector::setParent(std::shared_ptr<GraphItem> _parent){
|
||||||
|
parent = _parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connector::setPosition(Vec2Df pos) {
|
||||||
|
center_position = pos;
|
||||||
|
parent_position = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connector::setOrbit(float r) {
|
||||||
|
orbit = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connector::update() {
|
||||||
|
if(hovering()) state->pushEvent({getPtr(), APP::Interaction::HOVER});
|
||||||
|
if(hovering() && held() && !pickedUp()) state->pushEvent({getPtr(), APP::Interaction::PICKUP});
|
||||||
|
if(pickedUp()) state->pushEvent({getPtr(), APP::Interaction::DRAG});
|
||||||
|
if(picked_up && released()) state->pushEvent({getPtr(), APP::Interaction::PUTDOWN});
|
||||||
|
if(connected) {
|
||||||
|
state->pushEvent({getPtr(), APP::Interaction::CONNECT});
|
||||||
|
connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(partner.expired()) {
|
||||||
|
position = center_position.orbitAlongVector(SCREEN_MOUSE, orbit);
|
||||||
|
position_text = center_position.orbitAlongVector(SCREEN_MOUSE, orbit+10);
|
||||||
|
}
|
||||||
|
if(!partner.expired()) {
|
||||||
|
position = center_position.orbitAlongVector(partner.lock()->position, orbit);
|
||||||
|
position_text = center_position.orbitAlongVector(partner.lock()->position, orbit+10);
|
||||||
|
}
|
||||||
|
if(new_partner) {
|
||||||
|
new_partner = false;
|
||||||
|
state->pushEvent({getPtr(), APP::Interaction::CONNECT});
|
||||||
|
}
|
||||||
|
//parent_position = std::dynamic_pointer_cast<NODES::Node>(parent.lock())->position;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connector::draw() {
|
||||||
|
BASE::Connectable::draw();
|
||||||
|
float opacity = Clamp((400.0f - Clamp(position.dist(SCREEN_MOUSE), 0.0f, 400.0f)) / 400.0f, 0.0f, 1.0f);
|
||||||
|
float rotation = 0.0f;
|
||||||
|
|
||||||
|
if(partner.expired()) rotation = HELPER::GetRotation(parent_position, SCREEN_MOUSE) + 90.0f;
|
||||||
|
|
||||||
|
if(!partner.expired()) {
|
||||||
|
rotation = HELPER::GetRotation(parent_position, partner.lock()->position) + 90.0f;
|
||||||
|
opacity = 1.0f;
|
||||||
|
}
|
||||||
|
if(connecting) opacity = 1.0f;
|
||||||
|
|
||||||
|
if(partner.expired() && !connecting) ViTexButton(SCREEN_MOUSE, position, rotation, 8.0f,
|
||||||
|
TEXTURES::tex_connector, TEXTURES::tex_connector_hover, TEXTURES::tex_connector_pressed,
|
||||||
|
ColorLerp(Fade(VS_COLOR_WHITE, .0f), Fade(VS_COLOR_WHITE, 1.0f), opacity));
|
||||||
|
|
||||||
|
if(!partner.expired() || connecting) ViTexButton(SCREEN_MOUSE, position, rotation, 8.0f,
|
||||||
|
TEXTURES::tex_connector_connected, TEXTURES::tex_connector_hover,
|
||||||
|
ColorLerp(Fade(VS_COLOR_WHITE, .0f), Fade(VS_COLOR_WHITE, 1.0f), opacity));
|
||||||
|
|
||||||
|
//int partner_id = -1;
|
||||||
|
//if(!partner.expired()) partner_id = std::dynamic_pointer_cast<Connector>(partner.lock())->id;
|
||||||
|
//DrawTextPro(GetFontDefault(), std::format("{} {}", id, partner_id).c_str(), position_text, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK);
|
||||||
|
//DrawText(std::format("{}", id), position + Vec2Df(100.0f,100.0f), 8.0f, Color(255, 0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,12 +3,10 @@
|
|||||||
#include "connectable.h"
|
#include "connectable.h"
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
#include "graph-item.h"
|
#include "graph-item.h"
|
||||||
//#include "interaction-event.h"
|
|
||||||
#include "raymath.h"
|
|
||||||
#include "state.h"
|
|
||||||
#include "vmath.h"
|
#include "vmath.h"
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <raylib.h>
|
||||||
|
|
||||||
namespace VISEQ::GRAPH {
|
namespace VISEQ::GRAPH {
|
||||||
class Connector : public BASE::Connectable, public GraphItem, public std::enable_shared_from_this<Connector> {
|
class Connector : public BASE::Connectable, public GraphItem, public std::enable_shared_from_this<Connector> {
|
||||||
@@ -18,6 +16,8 @@ namespace VISEQ::GRAPH {
|
|||||||
Connector(std::shared_ptr<GraphItem> parent, Vec2Df center_position, float orbit) : orbit(orbit) {
|
Connector(std::shared_ptr<GraphItem> parent, Vec2Df center_position, float orbit) : orbit(orbit) {
|
||||||
setPosition(center_position);
|
setPosition(center_position);
|
||||||
setParent(parent);
|
setParent(parent);
|
||||||
|
_id++;
|
||||||
|
id = _id;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::weak_ptr<GraphItem> parent;
|
std::weak_ptr<GraphItem> parent;
|
||||||
@@ -27,58 +27,20 @@ namespace VISEQ::GRAPH {
|
|||||||
float radius = 8.0f;
|
float radius = 8.0f;
|
||||||
float orbit = 20.0f;
|
float orbit = 20.0f;
|
||||||
Vec2Df center_position;
|
Vec2Df center_position;
|
||||||
|
Vec2Df parent_position;
|
||||||
|
Vec2Df position_text;
|
||||||
|
inline static int _id = 0;
|
||||||
|
int id = 0;
|
||||||
|
|
||||||
|
GraphItemType getType() override;
|
||||||
|
|
||||||
GraphItemType getType() override{
|
std::shared_ptr<Connector> getPtr();
|
||||||
return GraphItemType::CONNECTOR;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Connector> getPtr(){
|
|
||||||
return shared_from_this();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool hovering() override {
|
virtual bool hovering() override;
|
||||||
return partner.expired() && CheckCollisionPointCircle(SCREEN_MOUSE, position, radius);
|
void setParent(std::shared_ptr<GraphItem> _parent);
|
||||||
}
|
void setPosition(Vec2Df pos) override;
|
||||||
|
void setOrbit(float r);
|
||||||
void setParent(std::shared_ptr<GraphItem> _parent){
|
void update() override;
|
||||||
parent = _parent;
|
void draw() override;
|
||||||
}
|
|
||||||
|
|
||||||
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});
|
|
||||||
if(hovering() && clicked()) state->pushEvent({getPtr(), APP::Interaction::PICKUP});
|
|
||||||
if(pickedUp()) state->pushEvent({getPtr(), APP::Interaction::DRAG});
|
|
||||||
if(picked_up && released()) state->pushEvent({getPtr(), APP::Interaction::PUTDOWN});
|
|
||||||
if(connected) {
|
|
||||||
state->pushEvent({getPtr(), APP::Interaction::CONNECT});
|
|
||||||
connected = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw() override {
|
|
||||||
BASE::Connectable::draw();
|
|
||||||
float opacity = 150.0f - Clamp(position.dist(SCREEN_MOUSE), 0.0f, 150.0f);
|
|
||||||
|
|
||||||
if(hovering()){
|
|
||||||
DrawCircle(position.x, position.y, 8.0f, (Color){108, 203, 237, 255});
|
|
||||||
} else {
|
|
||||||
DrawCircle(position.x, position.y, 8.0f, (Color){108, 153, 187, (unsigned char)opacity});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#define VS_COLOR_PURPLE (Color){158, 134, 200, 255}
|
#define VS_COLOR_PURPLE (Color){158, 134, 200, 255}
|
||||||
#define VS_COLOR_PINK (Color){176, 82, 121, 255}
|
#define VS_COLOR_PINK (Color){176, 82, 121, 255}
|
||||||
#define VS_COLOR_BLUE (Color){108, 153, 187, 255}
|
#define VS_COLOR_BLUE (Color){108, 153, 187, 255}
|
||||||
|
#define VS_COLOR_LIGHTBLUE (Color){143, 206, 255, 255}
|
||||||
|
|
||||||
#define VS_COLOR_RED (Color){195, 83, 85, 255}
|
#define VS_COLOR_RED (Color){195, 83, 85, 255}
|
||||||
#define VS_COLOR_BROWN (Color){84, 75, 61, 255}
|
#define VS_COLOR_BROWN (Color){84, 75, 61, 255}
|
||||||
@@ -22,13 +23,36 @@
|
|||||||
|
|
||||||
#include "nlohmann/json.hpp"
|
#include "nlohmann/json.hpp"
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
#include <raylib.h>
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "libremidi/libremidi.hpp"
|
#include "libremidi/libremidi.hpp"
|
||||||
|
|
||||||
#define RANGE_FILTER(L) std::ranges::views::filter(L)
|
#define RANGE_FILTER(L) std::ranges::views::filter(L)
|
||||||
|
|
||||||
|
namespace VISEQ::APP{
|
||||||
|
inline Font inter;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace VISEQ::TEXTURES {
|
||||||
|
inline Texture2D tex_connector;
|
||||||
|
inline Texture2D tex_connector_hover;
|
||||||
|
inline Texture2D tex_connector_pressed;
|
||||||
|
inline Texture2D tex_connector_connected;
|
||||||
|
inline Texture2D tex_delete;
|
||||||
|
inline Texture2D tex_split;
|
||||||
|
inline Texture2D tex_blocker_open;
|
||||||
|
inline Texture2D tex_blocker_closed;
|
||||||
|
inline Texture2D tex_delete_hover;
|
||||||
|
inline Texture2D tex_split_hover;
|
||||||
|
inline Texture2D tex_blocker_open_hover;
|
||||||
|
inline Texture2D tex_blocker_closed_hover;
|
||||||
|
inline Texture2D tex_delete_pressed;
|
||||||
|
inline Texture2D tex_split_pressed;
|
||||||
|
inline Texture2D tex_blocker_open_pressed;
|
||||||
|
inline Texture2D tex_blocker_closed_pressed;
|
||||||
|
}
|
||||||
|
|
||||||
namespace VISEQ::GRAPH::NODES {
|
namespace VISEQ::GRAPH::NODES {
|
||||||
enum Distribution {GEOMETRIC, ROUNDROBIN, RANDOM};
|
enum Distribution {GEOMETRIC, ROUNDROBIN, RANDOM};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,33 +9,49 @@ namespace VISEQ::BASE {
|
|||||||
return is_hovering && !hovering();
|
return is_hovering && !hovering();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Draggable::pickedUp() {
|
bool Draggable::clicked() {
|
||||||
|
if(hovering() && IsMouseButtonPressed(MOUSE_BUTTON_LEFT)){
|
||||||
|
last_tp = std::chrono::high_resolution_clock::now();
|
||||||
|
}
|
||||||
|
std::chrono::duration<double, std::micro> diff = std::chrono::high_resolution_clock::now() - last_tp;
|
||||||
|
if(released() && diff.count() < 100000){
|
||||||
|
std::cout << "draggable clicked" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Draggable::pickedUp() {
|
||||||
return held() && picked_up;
|
return held() && picked_up;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draggable::pickUp() {
|
void Draggable::pickUp() {
|
||||||
picked_up = true;
|
std::chrono::duration<double, std::micro> diff = std::chrono::high_resolution_clock::now() - last_tp;
|
||||||
|
if(held() && diff.count() > 100000){
|
||||||
|
std::cout << "draggable pickedUp" << std::endl;
|
||||||
|
picked_up = true;
|
||||||
|
}
|
||||||
drag_offset = position - SCREEN_MOUSE;
|
drag_offset = position - SCREEN_MOUSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draggable::pickUp(Vec2Df selection_origin) {
|
void Draggable::pickUp(Vec2Df selection_origin) {
|
||||||
picked_up = true;
|
picked_up = true;
|
||||||
drag_offset = position - selection_origin;
|
drag_offset = position - selection_origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draggable::drag(Vec2Df new_position) {
|
void Draggable::drag(Vec2Df new_position) {
|
||||||
position = new_position;
|
position = new_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draggable::putDown() {
|
void Draggable::putDown() {
|
||||||
picked_up = false;
|
picked_up = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Draggable::select() {
|
bool Draggable::select() {
|
||||||
return CheckCollisionPointRec(position, state->selection);
|
return CheckCollisionPointRec(position, state->selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draggable::deselect() {
|
void Draggable::deselect() {
|
||||||
selected = false;
|
selected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "selectable.h"
|
#include "selectable.h"
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
#include "vmath.h"
|
#include "vmath.h"
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
namespace VISEQ::BASE {
|
namespace VISEQ::BASE {
|
||||||
class Draggable : public Movable, public Selectable{
|
class Draggable : public Movable, public Selectable{
|
||||||
@@ -19,8 +20,11 @@ namespace VISEQ::BASE {
|
|||||||
|
|
||||||
bool picked_up = false;
|
bool picked_up = false;
|
||||||
|
|
||||||
|
std::chrono::time_point<std::chrono::high_resolution_clock> last_tp;
|
||||||
|
|
||||||
virtual bool entered() override;
|
virtual bool entered() override;
|
||||||
virtual bool exited() override;
|
virtual bool exited() override;
|
||||||
|
virtual bool clicked() override;
|
||||||
virtual bool pickedUp();
|
virtual bool pickedUp();
|
||||||
virtual void pickUp() override;
|
virtual void pickUp() override;
|
||||||
virtual void pickUp(Vec2Df selection_origin) override;
|
virtual void pickUp(Vec2Df selection_origin) override;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace VISEQ::GRAPH::EDGES {
|
|||||||
float speed = 0;
|
float speed = 0;
|
||||||
float bpm = 120.0f;
|
float bpm = 120.0f;
|
||||||
|
|
||||||
float connector_offset = 8.0f;
|
float connector_offset = 2.0f;
|
||||||
float switches_offset = 25.0f;
|
float switches_offset = 25.0f;
|
||||||
|
|
||||||
virtual bool GActive();
|
virtual bool GActive();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "config-node.h"
|
#include "config-node.h"
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
|
#include "helper.h"
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
#include "vmath.h"
|
#include "vmath.h"
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
@@ -52,7 +53,7 @@ namespace VISEQ::GRAPH{
|
|||||||
void GraphManager::addNode(SPTR_Node node){
|
void GraphManager::addNode(SPTR_Node node){
|
||||||
std::cout << "added node " << node->id << std::endl;
|
std::cout << "added node " << node->id << std::endl;
|
||||||
nodes.insert(nodes.end(), node);
|
nodes.insert(nodes.end(), node);
|
||||||
node->update();
|
nodes.back()->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphManager::addConnection(WPTR_Node from, WPTR_Node to){
|
void GraphManager::addConnection(WPTR_Node from, WPTR_Node to){
|
||||||
@@ -63,10 +64,19 @@ namespace VISEQ::GRAPH{
|
|||||||
edges.back()->edgeType = et;
|
edges.back()->edgeType = et;
|
||||||
edges.back()->start = from;
|
edges.back()->start = from;
|
||||||
edges.back()->end = to;
|
edges.back()->end = to;
|
||||||
|
|
||||||
|
from.lock()->update();
|
||||||
|
to.lock()->update();
|
||||||
|
|
||||||
|
from.lock()->connectors.back()->partner = to.lock()->getConnector();
|
||||||
|
to.lock()->connectors.back()->partner = from.lock()->getConnector();
|
||||||
|
|
||||||
edges.back()->start_conn = from.lock()->connectors.back();
|
edges.back()->start_conn = from.lock()->connectors.back();
|
||||||
edges.back()->end_conn = to.lock()->connectors.back();
|
edges.back()->end_conn = to.lock()->connectors.back();
|
||||||
|
|
||||||
from.lock()->connections.push_back(edges.back());
|
from.lock()->connections.push_back(edges.back());
|
||||||
to.lock()->connections.push_back(edges.back());
|
to.lock()->connections.push_back(edges.back());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,6 +90,7 @@ namespace VISEQ::GRAPH{
|
|||||||
if(!KEYS_DOWN.shift) selected_nodes.clear();
|
if(!KEYS_DOWN.shift) selected_nodes.clear();
|
||||||
selected_nodes.insert(selected_nodes.end(), temp_nodes.begin(), temp_nodes.end());
|
selected_nodes.insert(selected_nodes.end(), temp_nodes.begin(), temp_nodes.end());
|
||||||
std::for_each(selected_nodes.begin(), selected_nodes.end(), [](WPTR_Node n){n.lock()->selected = true;});
|
std::for_each(selected_nodes.begin(), selected_nodes.end(), [](WPTR_Node n){n.lock()->selected = true;});
|
||||||
|
std::cout << "selected " << selected_nodes.size() << " nodes" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphManager::deselect(){
|
void GraphManager::deselect(){
|
||||||
@@ -147,6 +158,12 @@ namespace VISEQ::GRAPH{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GraphManager::cycleModeOfSelectedNodes(bool direction){
|
||||||
|
for(auto n: selected_nodes){
|
||||||
|
n->cycleMode(direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GraphManager::reset(){
|
void GraphManager::reset(){
|
||||||
counter.clear();
|
counter.clear();
|
||||||
}
|
}
|
||||||
@@ -191,10 +208,15 @@ namespace VISEQ::GRAPH{
|
|||||||
return edges.back();
|
return edges.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
WPTR_Node GraphManager::next(WPTR_Node current, WPTR_Node last){
|
VEC_WPTR_Edge GraphManager::getPassableConnections(WPTR_Node node){
|
||||||
VEC_WPTR_Edge possible_connections = current.lock()->connections | RANGE_FILTER([current](WPTR_Edge c){
|
VEC_WPTR_Edge passable_connections = node.lock()->connections | RANGE_FILTER([node](WPTR_Edge c){
|
||||||
return (c.lock()->getEdgeType() == EdgeType::MIDIEDGE) && ((c.lock()->start.lock() == current.lock() && c.lock()->pass_forward) || (c.lock()->end.lock() == current.lock() && c.lock()->pass_backward));
|
return (c.lock()->getEdgeType() == EdgeType::MIDIEDGE) && ((c.lock()->start.lock() == node.lock() && c.lock()->pass_forward) || (c.lock()->end.lock() == node.lock() && c.lock()->pass_backward));
|
||||||
}) | std::ranges::to<VEC_WPTR_Edge>();
|
}) | std::ranges::to<VEC_WPTR_Edge>();
|
||||||
|
return passable_connections;
|
||||||
|
}
|
||||||
|
|
||||||
|
WPTR_Node GraphManager::next(WPTR_Node current, WPTR_Node last){
|
||||||
|
VEC_WPTR_Edge possible_connections = getPassableConnections(current);
|
||||||
|
|
||||||
if(possible_connections.empty()) return SPTR_Node(nullptr);
|
if(possible_connections.empty()) return SPTR_Node(nullptr);
|
||||||
|
|
||||||
@@ -347,41 +369,41 @@ namespace VISEQ::GRAPH{
|
|||||||
float v1_v2_distance = v1_position.dist(&v2_position);
|
float v1_v2_distance = v1_position.dist(&v2_position);
|
||||||
|
|
||||||
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;
|
||||||
Vec2Df from_to_handle = c->start.lock()->position - ((c->start.lock()->position - c->end.lock()->position)).norm() * (c->start.lock()->radius + c->switches_offset);
|
float from_radius = c->start.lock()->radius;
|
||||||
Vec2Df to_from_handle = c->end.lock()->position - ((c->end.lock()->position - c->start.lock()->position)).norm() * (c->end.lock()->radius + c->switches_offset);
|
float to_radius = c->end.lock()->radius;
|
||||||
Vec2Df middle_handle = c->end.lock()->position - ((c->end.lock()->position - c->start.lock()->position))*0.4f;
|
|
||||||
Vec2Df middle_handle_2 = c->end.lock()->position - ((c->end.lock()->position - c->start.lock()->position))*0.6f;
|
Vec2Df from_to_handle = c->start.lock()->position - ((c->start.lock()->position - c->end.lock()->position)).norm() * (from_radius + 35.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);
|
Vec2Df to_from_handle = c->end.lock()->position - ((c->end.lock()->position - c->start.lock()->position)).norm() * (to_radius + 35.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);
|
//Vec2Df middle_handle_2 = c->end.lock()->position - ((c->end.lock()->position - c->start.lock()->position)).norm()*65.0f;
|
||||||
|
//Vec2Df middle_handle = c->start.lock()->position - ((c->start.lock()->position - c->end.lock()->position)).norm()*65.0f;
|
||||||
|
Vec2Df center_handle = c->end.lock()->position - ((c->end.lock()->position - c->start.lock()->position))*0.5f;
|
||||||
|
|
||||||
|
Vec2Df delete_position = center_handle + (c->start.lock()->position - c->end.lock()->position).norm().orth() * 12.0f;
|
||||||
|
Vec2Df split_position = center_handle - (c->start.lock()->position - c->end.lock()->position).norm().orth() * 12.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(center_handle.dist(mouse_pos), 0.0f, 130.0f);
|
||||||
unsigned char opacity_from = 250.0f - Clamp(from_to_handle.dist(mouse_pos), 0.0f, 220.0f);
|
//unsigned char opacity_from = 250.0f - Clamp(from_to_handle.dist(mouse_pos), 0.0f, 220.0f);
|
||||||
unsigned char opacity_to = 250.0f - Clamp(to_from_handle.dist(mouse_pos), 0.0f, 220.0f);
|
//unsigned char opacity_to = 250.0f - Clamp(to_from_handle.dist(mouse_pos), 0.0f, 220.0f);
|
||||||
|
|
||||||
float midi_gate_v1 = 0.0f;
|
float opacity_normalized = Clamp((float)opacity / 255.0f, .0f, 1.0f);
|
||||||
float midi_gate_v2 = 0.0f;
|
//float opacity_from_normalized = Clamp((float)opacity_from / 255.0f, .0f, 1.0f);
|
||||||
|
//float opacity_to_normalized = Clamp((float)opacity_to / 255.0f, .0f, 1.0f);
|
||||||
|
|
||||||
if(c->start.lock()->getNodeType() == NodeType::MIDINODE){
|
|
||||||
midi_gate_v1 = Clamp((4.f / 1000.f) * std::dynamic_pointer_cast<MidiNode>(c->start.lock())->getNotes().gate, 1.f, 4.f);
|
|
||||||
}
|
|
||||||
if(c->end.lock()->getNodeType() == NodeType::MIDINODE){
|
|
||||||
midi_gate_v2 = Clamp((4.f / 1000.f) * std::dynamic_pointer_cast<MidiNode>(c->end.lock())->getNotes().gate, 1.f, 4.f);
|
|
||||||
}
|
|
||||||
// Line with small connector circles
|
// Line with small connector circles
|
||||||
if(c->end.lock()->getNodeType() == NodeType::MIDINODE && c->start.lock()->getNodeType() == NodeType::MIDINODE){
|
if(c->end.lock()->getNodeType() == NodeType::MIDINODE && c->start.lock()->getNodeType() == NodeType::MIDINODE){
|
||||||
|
|
||||||
Color col = {229, 181, 103, 255};
|
Color col = {229, 181, 103, 255};
|
||||||
if(c->GActive()) col = {108, 153, 187, 255};
|
if(c->GActive()) col = {108, 153, 187, 255};
|
||||||
DrawLine(v1_position.x, v1_position.y, v2_position.x, v2_position.y, col);
|
DrawLine(v1_position.x, v1_position.y, v2_position.x, v2_position.y, col);
|
||||||
{
|
if(state->draw_edge_lengths){
|
||||||
float d = c->start.lock()->position.dist(c->end.lock()->position);
|
float d = c->start.lock()->position.dist(c->end.lock()->position);
|
||||||
std::string frac = MIDI::Fractions.at(std::clamp<int>(round(d/60) - 1, 0, 31));
|
std::string frac = MIDI::Fractions.at(std::clamp<int>(round(d/60) - 1, 0, 31));
|
||||||
Vector2 text_length = MeasureTextEx(GetFontDefault(), std::format("{:.1f}",d).c_str(), 10.0f, 2.0f);
|
Vector2 text_length = MeasureTextEx(GetFontDefault(), std::format("{:.1f}",d).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);
|
||||||
|
|
||||||
Vec2Df middle_handle = c->start.lock()->position + (c->end.lock()->position - c->start.lock()->position) * ((d - text_length.x)*0.5f)/d;
|
Vec2Df middle_handle = c->start.lock()->position + (c->end.lock()->position - c->start.lock()->position) * ((d - text_length.x)*0.35f)/d;
|
||||||
Vec2Df middle_handle_frac = c->start.lock()->position + (c->end.lock()->position - c->start.lock()->position) * ((d - text_length_frac.x)*0.5f)/d;
|
Vec2Df middle_handle_frac = c->start.lock()->position + (c->end.lock()->position - c->start.lock()->position) * ((d - text_length_frac.x)*0.35f)/d;
|
||||||
Vec2Df text_position = middle_handle + (c->start.lock()->position - c->end.lock()->position).norm().orth() * 12.0f;
|
Vec2Df text_position = middle_handle + (c->start.lock()->position - c->end.lock()->position).norm().orth() * 12.0f;
|
||||||
Vec2Df text_position_frac = middle_handle_frac - (c->start.lock()->position - c->end.lock()->position).norm().orth() * 4.0f;
|
Vec2Df text_position_frac = middle_handle_frac - (c->start.lock()->position - c->end.lock()->position).norm().orth() * 4.0f;
|
||||||
|
|
||||||
@@ -389,38 +411,34 @@ namespace VISEQ::GRAPH{
|
|||||||
DrawTextPro(GetFontDefault(), std::format("{:.1f}",d).c_str(), text_position, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK);
|
DrawTextPro(GetFontDefault(), std::format("{:.1f}",d).c_str(), text_position, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK);
|
||||||
if( (int)d % 60 == 0) DrawTextPro(GetFontDefault(), frac.c_str(), text_position_frac, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK);
|
if( (int)d % 60 == 0) DrawTextPro(GetFontDefault(), frac.c_str(), text_position_frac, (Vector2){0,0}, rotation, 10.0f, 2.0f, VS_COLOR_PINK);
|
||||||
}
|
}
|
||||||
if(midi_gate_v1 == 4.0f) col = VS_COLOR_RED;
|
|
||||||
DrawCircle(v1_position.x, v1_position.y, midi_gate_v1, col);
|
|
||||||
|
|
||||||
col = {229, 181, 103, 255};
|
|
||||||
if(midi_gate_v2 == 4.0f) col = VS_COLOR_RED;
|
|
||||||
DrawCircle(v2_position.x, v2_position.y, midi_gate_v2, col);
|
|
||||||
|
|
||||||
if(!c->start.lock()->picked_up && !c->end.lock()->picked_up){
|
if(!c->start.lock()->picked_up && !c->end.lock()->picked_up){
|
||||||
// On/Off switches on both sides
|
// On/Off switches on both sides
|
||||||
if(ViButton(mouse_pos, from_to_handle.x, from_to_handle.y, 8.0f, c->pass_forward ? (Color){120, 210, 115, opacity_from} : (Color){232, 50, 32, opacity_from} )) c->pass_forward = !c->pass_forward;
|
|
||||||
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(ViTexButton(mouse_pos, from_to_handle, HELPER::GetRotation(from_to_handle, to_from_handle) + 90.0f, 8.0f,
|
||||||
Vec2Df block_point1 = (v1_position - v2_position).norm().orth()*4.0f + from_to_handle;
|
c->pass_forward ? TEXTURES::tex_blocker_open : TEXTURES::tex_blocker_closed,
|
||||||
Vec2Df block_point2 = (v1_position - v2_position).norm().orth()*-4.0f + from_to_handle;
|
c->pass_forward ? TEXTURES::tex_blocker_open_hover : TEXTURES::tex_blocker_closed_hover,
|
||||||
DrawLineEx(block_point1, block_point2, 2.0f, (Color){232,232,232,opacity_from});
|
c->pass_forward ? TEXTURES::tex_blocker_open_pressed : TEXTURES::tex_blocker_closed_pressed,
|
||||||
}
|
ColorLerp(Fade(VS_COLOR_WHITE, .0f), Fade(VS_COLOR_WHITE, 1.0f), 1.0))) c->pass_forward = !c->pass_forward;
|
||||||
|
|
||||||
if(!c->pass_backward){
|
if(ViTexButton(mouse_pos, to_from_handle, HELPER::GetRotation(to_from_handle, from_to_handle) + 90.0f, 8.0f,
|
||||||
Vec2Df block_point1 = (v1_position - v2_position).norm().orth()*4.0f + to_from_handle;
|
c->pass_backward ? TEXTURES::tex_blocker_open : TEXTURES::tex_blocker_closed,
|
||||||
Vec2Df block_point2 = (v1_position - v2_position).norm().orth()*-4.0f + to_from_handle;
|
c->pass_backward ? TEXTURES::tex_blocker_open_hover : TEXTURES::tex_blocker_closed_hover,
|
||||||
DrawLineEx(block_point1, block_point2, 2.0f, (Color){232,232,232,opacity_to});
|
c->pass_backward ? TEXTURES::tex_blocker_open_pressed : TEXTURES::tex_blocker_closed_pressed,
|
||||||
}
|
ColorLerp(Fade(VS_COLOR_WHITE, .0f), Fade(VS_COLOR_WHITE, 1.0f), 1.0))) c->pass_backward = !c->pass_backward;
|
||||||
|
|
||||||
if(ViButton(mouse_pos, flip_handle_2.x, flip_handle_2.y, 8.0f, (Color){232, 125, 62, opacity} )) splitEdge(c);
|
if(ViTexButton(mouse_pos, split_position, HELPER::GetRotation(from_to_handle, to_from_handle) + 90.0f, 8.0f,
|
||||||
|
TEXTURES::tex_split, TEXTURES::tex_split_hover, TEXTURES::tex_split_pressed, ColorLerp(Fade(VS_COLOR_WHITE, .0f), Fade(VS_COLOR_WHITE, 1.0f), opacity_normalized) )) splitEdge(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(c->start.lock()->getNodeType() == NodeType::CONFIGNODE || c->end.lock()->getNodeType() == NodeType::CONFIGNODE){
|
if(c->start.lock()->getNodeType() == NodeType::CONFIGNODE || c->end.lock()->getNodeType() == NodeType::CONFIGNODE){
|
||||||
DrawLine(v1_position.x, v1_position.y, v2_position.x, v2_position.y, VS_COLOR_BLUE);
|
DrawLine(v1_position.x, v1_position.y, v2_position.x, v2_position.y, VS_COLOR_BLUE);
|
||||||
}
|
}
|
||||||
|
if(IsWindowReady()){
|
||||||
if(ViButton(mouse_pos, flip_handle.x, flip_handle.y, 8.0f, (Color){232, 50, 32, opacity} )) removeEdge(c);
|
if(ViTexButton(mouse_pos, delete_position, HELPER::GetRotation(from_to_handle, to_from_handle), 8.0f,
|
||||||
|
TEXTURES::tex_delete, TEXTURES::tex_delete_hover, TEXTURES::tex_delete_pressed,
|
||||||
|
ColorLerp(Fade(VS_COLOR_WHITE, .0f), Fade(VS_COLOR_WHITE, 1.0f), opacity_normalized) )) removeEdge(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ namespace VISEQ::GRAPH {
|
|||||||
SPTR_Node copyNode(SPTR_Node n, Vec2Df position);
|
SPTR_Node copyNode(SPTR_Node n, Vec2Df position);
|
||||||
SPTR_Node copyNode(std::shared_ptr<MidiNode> n, Vec2Df position);
|
SPTR_Node copyNode(std::shared_ptr<MidiNode> n, Vec2Df position);
|
||||||
void setNodeMode(int mode);
|
void setNodeMode(int mode);
|
||||||
|
void cycleModeOfSelectedNodes(bool direction);
|
||||||
void reset();
|
void reset();
|
||||||
WPTR_Node getNode(int i);
|
WPTR_Node getNode(int i);
|
||||||
WPTR_Node getFirstNode();
|
WPTR_Node getFirstNode();
|
||||||
@@ -66,6 +67,7 @@ namespace VISEQ::GRAPH {
|
|||||||
SPTR_Node getClosestNode(Vec2Df position);
|
SPTR_Node getClosestNode(Vec2Df position);
|
||||||
VEC_WPTR_Node getNodesByID(int _id);
|
VEC_WPTR_Node getNodesByID(int _id);
|
||||||
WPTR_Edge lastEdge();
|
WPTR_Edge lastEdge();
|
||||||
|
VEC_WPTR_Edge getPassableConnections(WPTR_Node node);
|
||||||
WPTR_Node next(WPTR_Node current, WPTR_Node last);
|
WPTR_Node next(WPTR_Node current, WPTR_Node last);
|
||||||
void splitEdge(SPTR_Edge edge);
|
void splitEdge(SPTR_Edge edge);
|
||||||
void splitEdges();
|
void splitEdges();
|
||||||
|
|||||||
@@ -15,4 +15,8 @@ namespace VISEQ::HELPER{
|
|||||||
float rotation = Vector2Angle((Vector2){1,0}, (end - start)) * RAD2DEG;
|
float rotation = Vector2Angle((Vector2){1,0}, (end - start)) * RAD2DEG;
|
||||||
DrawTextPro(GetFontDefault(), text.c_str(), text_position, (Vector2){0,0}, rotation, size, 2.0f, col);
|
DrawTextPro(GetFontDefault(), text.c_str(), text_position, (Vector2){0,0}, rotation, size, 2.0f, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline float GetRotation(Vec2Df start, Vec2Df end){
|
||||||
|
return Vector2Angle((Vector2){1,0}, (end - start)) * RAD2DEG;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace VISEQ::BASE {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Interactable() {}
|
virtual ~Interactable() {}
|
||||||
|
|
||||||
bool is_hovering = false;
|
bool is_hovering = false;
|
||||||
|
|
||||||
int z_index = 0;
|
int z_index = 0;
|
||||||
|
|||||||
@@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
#include "connector.h"
|
#include "connector.h"
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
|
#include "interaction-event.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <ostream>
|
||||||
|
#include <ranges>
|
||||||
|
|
||||||
namespace VISEQ::INTERACTION{
|
namespace VISEQ::INTERACTION{
|
||||||
|
|
||||||
@@ -26,19 +29,22 @@ namespace VISEQ::INTERACTION{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!KEYS_DOWN.shift && IsKeyPressed(KEY_TAB)) {
|
if(!KEYS_DOWN.shift && IsKeyPressed(KEY_TAB)) {
|
||||||
state->node_mode = (state->node_mode + 1) % 7;
|
gm->cycleModeOfSelectedNodes(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(KEYS_DOWN.shift && IsKeyPressed(KEY_TAB)) {
|
if(KEYS_DOWN.shift && IsKeyPressed(KEY_TAB)) {
|
||||||
state->node_mode -= state->node_mode > 0 ? 1 : -6;
|
gm->cycleModeOfSelectedNodes(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!KEYS_DOWN.ctrl && IsKeyPressed(KEY_V)){
|
||||||
|
state->draw_edge_lengths = !state->draw_edge_lengths;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void InteractionManager::draw(){
|
void InteractionManager::draw(){
|
||||||
doInteraction();
|
doInteraction();
|
||||||
scaleSelection();
|
scaleSelection();
|
||||||
if(!gm->getSelection().empty()){
|
if(gm->getSelection().size() > 1){
|
||||||
DrawRectangleRoundedLines(state->bounding_box, 0.1f, 3, VS_COLOR_LIGHTGREY);
|
DrawRectangleRoundedLines(state->bounding_box, 0.1f, 3, VS_COLOR_LIGHTGREY);
|
||||||
scale_handle->draw();
|
scale_handle->draw();
|
||||||
}
|
}
|
||||||
@@ -130,16 +136,37 @@ namespace VISEQ::INTERACTION{
|
|||||||
bool exit = false;
|
bool exit = false;
|
||||||
bool once = false;
|
bool once = false;
|
||||||
bool connect_once = false;
|
bool connect_once = false;
|
||||||
|
bool blocking = false;
|
||||||
|
|
||||||
|
//std::cout << state->mouse_z << std::endl;
|
||||||
|
|
||||||
state->mouse_z = canvas->z_index;
|
state->mouse_z = canvas->z_index;
|
||||||
|
|
||||||
for(auto e : state->event_queue){
|
//auto sorted_queue = state->event_queue
|
||||||
|
|
||||||
|
auto nodes_queue = state->event_queue | RANGE_FILTER([](APP::InteractionEvent e) { return e.item->getType() == GraphItemType::NODE; }) | std::ranges::to<std::deque<APP::InteractionEvent>>();
|
||||||
|
auto connector_queue = state->event_queue | RANGE_FILTER([](APP::InteractionEvent e) { return e.item->getType() == GraphItemType::CONNECTOR; }) | std::ranges::to<std::deque<APP::InteractionEvent>>();
|
||||||
|
auto canvas_queue = state->event_queue | RANGE_FILTER([](APP::InteractionEvent e) { return e.item->getType() == GraphItemType::CANVAS; }) | std::ranges::to<std::deque<APP::InteractionEvent>>();
|
||||||
|
|
||||||
|
std::sort(nodes_queue.begin(), nodes_queue.end(), [](APP::InteractionEvent a, APP::InteractionEvent b){return a.item->z_index > b.item->z_index;});
|
||||||
|
|
||||||
|
std::deque<APP::InteractionEvent> state_queue;
|
||||||
|
state_queue.append_range(nodes_queue);
|
||||||
|
state_queue.append_range(connector_queue);
|
||||||
|
state_queue.append_range(canvas_queue);
|
||||||
|
|
||||||
|
state->event_queue.clear();
|
||||||
|
|
||||||
|
std::cout << state_queue.size() << std::endl;
|
||||||
|
|
||||||
|
for(auto e : state_queue){
|
||||||
if(!connect_once && e.action == APP::Interaction::CONNECT){
|
if(!connect_once && e.action == APP::Interaction::CONNECT){
|
||||||
|
blocking = true;
|
||||||
APP::InteractionEvent partner;
|
APP::InteractionEvent partner;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for(auto ei : state->event_queue){
|
for(auto ei : state->event_queue){
|
||||||
if(ei.action == APP::Interaction::HOVER && ei.item->getType() == GraphItemType::CONNECTOR) {
|
if(ei.action == APP::Interaction::HOVER && ei.item->getType() == GraphItemType::CONNECTOR) {
|
||||||
std::cout << "YEAH" << std::endl;
|
//std::cout << "YEAH" << std::endl;
|
||||||
partner = ei;
|
partner = ei;
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
@@ -149,8 +176,8 @@ namespace VISEQ::INTERACTION{
|
|||||||
auto connector = std::dynamic_pointer_cast<Connector>(e.item);
|
auto connector = std::dynamic_pointer_cast<Connector>(e.item);
|
||||||
if(found && partner != e){
|
if(found && partner != e){
|
||||||
auto connector_to = std::dynamic_pointer_cast<Connector>(partner.item);
|
auto connector_to = std::dynamic_pointer_cast<Connector>(partner.item);
|
||||||
connector->partner = connector_to;
|
//connector->partner = connector_to;
|
||||||
connector_to->partner = connector;
|
//connector_to->partner = connector;
|
||||||
gm->addConnection(std::dynamic_pointer_cast<Node>(connector->parent.lock()), std::dynamic_pointer_cast<Node>(connector_to->parent.lock()));
|
gm->addConnection(std::dynamic_pointer_cast<Node>(connector->parent.lock()), std::dynamic_pointer_cast<Node>(connector_to->parent.lock()));
|
||||||
} else if (partner != e){
|
} else if (partner != e){
|
||||||
if(KEYS_DOWN.alt){
|
if(KEYS_DOWN.alt){
|
||||||
@@ -163,12 +190,16 @@ namespace VISEQ::INTERACTION{
|
|||||||
connect_once = true;
|
connect_once = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if(e.item->getType() == GraphItemType::NODE){
|
||||||
|
if(e.action == APP::Interaction::DRAG) blocking = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while(state->event_queue.size() > 0 && !exit){
|
while(state_queue.size() > 0 && !exit){
|
||||||
auto e = state->event_queue.front();
|
auto e = state_queue.front();
|
||||||
if(e.action == APP::Interaction::CLICK){
|
if(e.action == APP::Interaction::CLICK){
|
||||||
gm->addToSelection();
|
gm->addToSelection();
|
||||||
|
std::cout << "click" << std::endl;
|
||||||
}
|
}
|
||||||
if(e.action == APP::Interaction::RIGHTCLICK){
|
if(e.action == APP::Interaction::RIGHTCLICK){
|
||||||
gm->addToSelection();
|
gm->addToSelection();
|
||||||
@@ -180,19 +211,10 @@ namespace VISEQ::INTERACTION{
|
|||||||
state->mouse_z = e.item->z_index;
|
state->mouse_z = e.item->z_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(e.item->getType() == GraphItemType::CANVAS) {
|
|
||||||
if(e.action == APP::Interaction::SELECT) {
|
|
||||||
gm->select();
|
|
||||||
canvas->clearSelectionRect();
|
|
||||||
}
|
|
||||||
if(e.action == APP::Interaction::DESELECT) {
|
|
||||||
gm->deselect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!once && e.item->getType() == GraphItemType::NODE){
|
if(!once && e.item->getType() == GraphItemType::NODE){
|
||||||
auto node = std::dynamic_pointer_cast<Node>(e.item);
|
auto node = std::dynamic_pointer_cast<Node>(e.item);
|
||||||
if(e.action == APP::Interaction::PICKUP) {
|
if(!blocking && e.action == APP::Interaction::PICKUP) {
|
||||||
|
std::cout << "node pickup" << std::endl;
|
||||||
node->pickUp();
|
node->pickUp();
|
||||||
if(node->selected){
|
if(node->selected){
|
||||||
for(auto s : gm->getSelection()){
|
for(auto s : gm->getSelection()){
|
||||||
@@ -202,6 +224,8 @@ namespace VISEQ::INTERACTION{
|
|||||||
once = true;
|
once = true;
|
||||||
}
|
}
|
||||||
if(e.action == APP::Interaction::DRAG) {
|
if(e.action == APP::Interaction::DRAG) {
|
||||||
|
blocking = true;
|
||||||
|
std::cout << "node drag" << std::endl;
|
||||||
if(KEYS_DOWN.ctrl) node->drag(MOD_MOUSE);
|
if(KEYS_DOWN.ctrl) node->drag(MOD_MOUSE);
|
||||||
else if(KEYS_DOWN.shift) {
|
else if(KEYS_DOWN.shift) {
|
||||||
snapPolar(node);
|
snapPolar(node);
|
||||||
@@ -213,9 +237,9 @@ namespace VISEQ::INTERACTION{
|
|||||||
s->drag(MOD_MOUSE + s->drag_offset);
|
s->drag(MOD_MOUSE + s->drag_offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
once = true;
|
|
||||||
}
|
}
|
||||||
if(e.action == APP::Interaction::PUTDOWN) {
|
if(e.action == APP::Interaction::PUTDOWN) {
|
||||||
|
std::cout << "node putdown" << std::endl;
|
||||||
node->putDown();
|
node->putDown();
|
||||||
if(node->selected){
|
if(node->selected){
|
||||||
for(auto s : gm->getSelection()){
|
for(auto s : gm->getSelection()){
|
||||||
@@ -224,6 +248,19 @@ namespace VISEQ::INTERACTION{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!blocking && !once && e.item->getType() == GraphItemType::CANVAS) {
|
||||||
|
if(e.action == APP::Interaction::SELECT) {
|
||||||
|
std::cout << "canvas select" << std::endl;
|
||||||
|
gm->select();
|
||||||
|
canvas->clearSelectionRect();
|
||||||
|
}
|
||||||
|
if(e.action == APP::Interaction::DESELECT) {
|
||||||
|
std::cout << "canvas deselect" << std::endl;
|
||||||
|
gm->deselect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(exit) break;
|
if(exit) break;
|
||||||
|
|
||||||
if(!once && (e.item->getType() == GraphItemType::CONNECTOR || e.item->getType() == GraphItemType::CANVAS || e.item->getType() == GraphItemType::HANDLE)) {
|
if(!once && (e.item->getType() == GraphItemType::CONNECTOR || e.item->getType() == GraphItemType::CANVAS || e.item->getType() == GraphItemType::HANDLE)) {
|
||||||
@@ -250,8 +287,8 @@ namespace VISEQ::INTERACTION{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state->event_queue.pop_front();
|
state_queue.pop_front();
|
||||||
}
|
}
|
||||||
state->event_queue.clear();
|
state_queue.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ namespace VISEQ::INTERACTION{
|
|||||||
|
|
||||||
virtual void update() override {
|
virtual void update() override {
|
||||||
if(hovering()) state->pushEvent({getPtr(), APP::Interaction::HOVER});
|
if(hovering()) state->pushEvent({getPtr(), APP::Interaction::HOVER});
|
||||||
if(hovering() && clicked()) state->pushEvent({getPtr(), APP::Interaction::PICKUP});
|
if(hovering() && held() && !pickedUp()) state->pushEvent({getPtr(), APP::Interaction::PICKUP});
|
||||||
if(pickedUp()) state->pushEvent({getPtr(), APP::Interaction::DRAG});
|
if(pickedUp()) state->pushEvent({getPtr(), APP::Interaction::DRAG});
|
||||||
if(picked_up && released()) state->pushEvent({getPtr(), APP::Interaction::PUTDOWN});
|
if(picked_up && released()) state->pushEvent({getPtr(), APP::Interaction::PUTDOWN});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ int main(){
|
|||||||
|
|
||||||
app.init();
|
app.init();
|
||||||
app.ui.init();
|
app.ui.init();
|
||||||
|
|
||||||
|
app.loadTextures();
|
||||||
|
|
||||||
app.loadState();
|
app.loadState();
|
||||||
|
|
||||||
@@ -58,7 +60,7 @@ int main(){
|
|||||||
|
|
||||||
while(!WindowShouldClose()){
|
while(!WindowShouldClose()){
|
||||||
app.update();
|
app.update();
|
||||||
app.draw();
|
if(IsWindowReady()) app.draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
app.close();
|
app.close();
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
#include "config-node.h"
|
#include "config-node.h"
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
#include "edge.h"
|
#include "edge.h"
|
||||||
#include "node-handle.h"
|
#include "interaction-event.h"
|
||||||
|
#include "midi.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
@@ -14,40 +15,10 @@
|
|||||||
namespace VISEQ::GRAPH::NODES {
|
namespace VISEQ::GRAPH::NODES {
|
||||||
|
|
||||||
void MidiNode::init(){
|
void MidiNode::init(){
|
||||||
float orbit_1 = radius + 25.0f;
|
|
||||||
float orbit_2 = orbit_1 + 20.0f;
|
|
||||||
float orbit_3 = orbit_2 + 20.0f;
|
|
||||||
float orbit_4 = orbit_3 + 20.0f;
|
|
||||||
float orbit_5 = orbit_4 + 30.0f;
|
|
||||||
|
|
||||||
midiNote.note = 64;
|
midiNote.note = 64;
|
||||||
midiNote.channel = 1;
|
midiNote.channel = 1;
|
||||||
midiNote.gate = 250;
|
midiNote.gate = 250;
|
||||||
midiNote.velocity = 64;
|
midiNote.velocity = 64;
|
||||||
|
|
||||||
midiHandles[NOTE].emplace_back(std::make_shared<NodeHandle<int>>(midiNote.note, position, VS_COLOR_GREEN, "NOTE", orbit_5, 12));
|
|
||||||
midiHandles[NOTE].emplace_back(std::make_shared<NodeHandle<int>>(midiNote.channel, position, VS_COLOR_PINK, "CHANNEL", orbit_1, 16, 1, 16, 40, 150));
|
|
||||||
midiHandles[NOTE].emplace_back(std::make_shared<NodeHandle<int>>(midiNote.gate, position, VS_COLOR_RED, "GATE", orbit_3, 30, 10, 30000, 40, 300));
|
|
||||||
midiHandles[NOTE].back()->logScale = true;
|
|
||||||
midiHandles[NOTE].emplace_back(std::make_shared<NodeHandle<int>>(midiNote.velocity, position, VS_COLOR_PURPLE, "VELOCITY", orbit_4, 32));
|
|
||||||
|
|
||||||
midiHandles[CC].emplace_back(std::make_shared<NodeHandle<int>>(midiCC.control, position, VS_COLOR_SUN, "CONTROL", orbit_3, 32));
|
|
||||||
midiHandles[CC].emplace_back(std::make_shared<NodeHandle<int>>(midiCC.channel, position, VS_COLOR_PINK, "CHANNEL", orbit_1, 1, 1, 16, 40, 150));
|
|
||||||
midiHandles[CC].emplace_back(std::make_shared<NodeHandle<int>>(midiCC.value, position, VS_COLOR_GREEN, "VALUE", orbit_4, 32));
|
|
||||||
|
|
||||||
midiHandles[PC].emplace_back(std::make_shared<NodeHandle<int>>(midiPC.program, position, VS_COLOR_SUN, "PROGRAM", orbit_3, 32));
|
|
||||||
midiHandles[PC].emplace_back(std::make_shared<NodeHandle<int>>(midiPC.channel, position, VS_COLOR_PINK, "CHANNEL", orbit_1, 1, 1, 16, 40, 150));
|
|
||||||
midiHandles[PC].emplace_back(std::make_shared<NodeHandle<int>>(midiPC.value, position, VS_COLOR_GREEN, "VALUE", orbit_4, 32));
|
|
||||||
|
|
||||||
midiHandles[PB].emplace_back(std::make_shared<NodeHandle<int>>(midiPitchBend.channel, position, VS_COLOR_PINK, "CHANNEL", orbit_1, 1, 1, 16, 40, 150));
|
|
||||||
midiHandles[PB].emplace_back(std::make_shared<NodeHandle<int>>(midiPitchBend.value, position, VS_COLOR_GREEN, "VALUE", orbit_3, 256, -8192, 8192, 40, 300));
|
|
||||||
|
|
||||||
midiHandles[AT].emplace_back(std::make_shared<NodeHandle<int>>(midiAftertouch.channel, position, VS_COLOR_PINK, "CHANNEL", orbit_1, 1, 1, 16, 40, 150));
|
|
||||||
midiHandles[AT].emplace_back(std::make_shared<NodeHandle<int>>(midiAftertouch.value, position, VS_COLOR_GREEN, "VALUE", orbit_3, 32));
|
|
||||||
|
|
||||||
midiHandles[PP].emplace_back(std::make_shared<NodeHandle<int>>(midiPolyPressure.channel, position, VS_COLOR_PINK, "CHANNEL", orbit_1, 1, 1, 16, 40, 150));
|
|
||||||
midiHandles[PP].emplace_back(std::make_shared<NodeHandle<int>>(midiPolyPressure.value, position, VS_COLOR_GREEN, "VALUE", orbit_4, 32));
|
|
||||||
midiHandles[PP].emplace_back(std::make_shared<NodeHandle<int>>(midiPolyPressure.note, position, VS_COLOR_SUN, "NOTE", orbit_5, 12));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<MidiNode> MidiNode::getPtr(){
|
std::shared_ptr<MidiNode> MidiNode::getPtr(){
|
||||||
@@ -134,40 +105,49 @@ namespace VISEQ::GRAPH::NODES {
|
|||||||
|
|
||||||
void MidiNode::update() {
|
void MidiNode::update() {
|
||||||
Node::update();
|
Node::update();
|
||||||
mode = state->node_mode;
|
|
||||||
for(auto mh : midiHandles[NOTE]){
|
|
||||||
mh->update(position);
|
|
||||||
}
|
|
||||||
for(auto mh : midiHandles[CC]){
|
|
||||||
mh->update(position);
|
|
||||||
}
|
|
||||||
for(auto mh : midiHandles[PC]){
|
|
||||||
mh->update(position);
|
|
||||||
}
|
|
||||||
for(auto mh : midiHandles[PB]){
|
|
||||||
mh->update(position);
|
|
||||||
}
|
|
||||||
for(auto mh : midiHandles[AT]){
|
|
||||||
mh->update(position);
|
|
||||||
}
|
|
||||||
for(auto mh : midiHandles[PP]){
|
|
||||||
mh->update(position);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MidiNode::modMidiNote(int incr){
|
void MidiNode::modMidiChannel(int incr){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void MidiNode::modMidiNoteValue(int incr){
|
||||||
midiNote.note += incr;
|
midiNote.note += incr;
|
||||||
if(midiNote.note < 0 ) midiNote.note = VISEQ::MIDI::Notes.size()-1;
|
if(midiNote.note < 0 ) midiNote.note = VISEQ::MIDI::Notes.size()-1;
|
||||||
if(midiNote.note >= (int)VISEQ::MIDI::Notes.size()) midiNote.note = 0;
|
if(midiNote.note >= (int)VISEQ::MIDI::Notes.size()) midiNote.note = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MidiNode::modMidiCC(int incr){
|
void MidiNode::modMidiNoteVelocity(int incr){
|
||||||
|
midiNote.velocity += incr;
|
||||||
|
if(midiNote.velocity < 0 ) midiNote.velocity = 127;
|
||||||
|
if(midiNote.velocity > 127 ) midiNote.velocity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MidiNode::modMidiNoteGate(int incr){
|
||||||
|
midiNote.gate += incr;
|
||||||
|
if(midiNote.gate < 0 ) midiNote.gate = 0;
|
||||||
|
if(midiNote.gate > 20000) midiNote.gate = 20000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MidiNode::modMidiCCValue(int incr){
|
||||||
|
midiCC.value += incr;
|
||||||
|
if(midiCC.value < 0 ) midiCC.value = 127;
|
||||||
|
if(midiCC.value > 127 ) midiCC.value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MidiNode::modMidiCCControl(int incr){
|
||||||
midiCC.control += incr;
|
midiCC.control += incr;
|
||||||
if(midiCC.control < 0 ) midiCC.control = 127;
|
if(midiCC.control < 0 ) midiCC.control = 127;
|
||||||
if(midiCC.control > 127 ) midiCC.control = 0;
|
if(midiCC.control > 127 ) midiCC.control = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MidiNode::modMidiPC(int incr){
|
void MidiNode::modMidiPCValue(int incr){
|
||||||
|
midiPC.value += incr;
|
||||||
|
if(midiPC.value < 0 ) midiPC.value = 127;
|
||||||
|
if(midiPC.value > 127 ) midiPC.value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MidiNode::modMidiPCProgram(int incr){
|
||||||
midiPC.program += incr;
|
midiPC.program += incr;
|
||||||
if(midiPC.program < 0 ) midiPC.program = 127;
|
if(midiPC.program < 0 ) midiPC.program = 127;
|
||||||
if(midiPC.program > 127 ) midiPC.program = 0;
|
if(midiPC.program > 127 ) midiPC.program = 0;
|
||||||
@@ -185,88 +165,73 @@ namespace VISEQ::GRAPH::NODES {
|
|||||||
if(midiAftertouch.value > 127 ) midiAftertouch.value = 127;
|
if(midiAftertouch.value > 127 ) midiAftertouch.value = 127;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MidiNode::modMidiPolyPressure(int incr){
|
void MidiNode::modMidiPolyPressureValue(int incr){
|
||||||
midiPolyPressure.value += incr;
|
midiPolyPressure.value += incr;
|
||||||
if(midiPolyPressure.value < 0 ) midiPolyPressure.value = 0;
|
if(midiPolyPressure.value < 0 ) midiPolyPressure.value = 0;
|
||||||
if(midiPolyPressure.value > 127 ) midiPolyPressure.value = 127;
|
if(midiPolyPressure.value > 16383 ) midiPolyPressure.value = 16383;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MidiNode::modMidiPolyPressureNote(int incr){
|
||||||
|
midiPolyPressure.note += incr;
|
||||||
|
if(midiPolyPressure.note < 0 ) midiPolyPressure.note = VISEQ::MIDI::Notes.size()-1;
|
||||||
|
if(midiPolyPressure.note >= (int)VISEQ::MIDI::Notes.size()) midiPolyPressure.note = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MidiNode::interact(){
|
void MidiNode::interact(){
|
||||||
float wheel = GetMouseWheelMove();
|
float wheel = GetMouseWheelMove();
|
||||||
|
|
||||||
|
switch(mode){
|
||||||
|
case NOTE:{
|
||||||
|
if(state->isModChain(APP::CTRL)) modMidiNoteValue(wheel);
|
||||||
|
if(state->isModChain(APP::CTRL, APP::SHIFT)) modMidiNoteValue(wheel*12);
|
||||||
|
if(state->isModChain(APP::CTRL, APP::ALT)) modMidiNoteValue(wheel*12);
|
||||||
|
if(state->isModChain(APP::CTRL, APP::SHIFT, APP::ALT)) modMidiNoteValue(wheel*24);
|
||||||
|
if(state->isModChain(APP::CTRL, APP::ALT, APP::SHIFT)) modMidiNoteValue(wheel*24);
|
||||||
|
|
||||||
if(KEYS_DOWN.ctrl && !KEYS_DOWN.alt){
|
if(state->isModChain(APP::SHIFT)) modMidiNoteVelocity(wheel);
|
||||||
switch(state->node_mode){
|
if(state->isModChain(APP::SHIFT, APP::CTRL)) modMidiNoteVelocity(wheel*16);
|
||||||
case 0:{
|
if(state->isModChain(APP::SHIFT, APP::ALT)) modMidiNoteVelocity(wheel*16);
|
||||||
modMidiNote(wheel);
|
if(state->isModChain(APP::SHIFT, APP::CTRL, APP::ALT)) modMidiNoteVelocity(wheel*32);
|
||||||
break;}
|
if(state->isModChain(APP::SHIFT, APP::ALT, APP::CTRL)) modMidiNoteVelocity(wheel*32);
|
||||||
case 1:{
|
|
||||||
modMidiCC(wheel);
|
if(state->isModChain(APP::ALT)) modMidiNoteGate(wheel*100);
|
||||||
break;}
|
if(state->isModChain(APP::ALT, APP::CTRL)) modMidiNoteGate(wheel*1000);
|
||||||
case 2:{
|
if(state->isModChain(APP::ALT, APP::SHIFT)) modMidiNoteGate(wheel*10);
|
||||||
modMidiPC(wheel);
|
if(state->isModChain(APP::ALT, APP::SHIFT, APP::CTRL)) modMidiNoteGate(wheel);
|
||||||
break;}
|
break;}
|
||||||
case 3:{
|
case CC:{
|
||||||
modMidiPitchBend(wheel);
|
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && !KEYS_DOWN.alt) modMidiCCValue(wheel);
|
||||||
break;}
|
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && !KEYS_DOWN.alt) modMidiCCControl(wheel);
|
||||||
case 4:{
|
break;}
|
||||||
modMidiAftertouch(wheel);
|
case PC:{
|
||||||
break;}
|
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && !KEYS_DOWN.alt) modMidiPCValue(wheel);
|
||||||
case 5:{
|
break;}
|
||||||
modMidiPolyPressure(wheel);
|
case PB:{
|
||||||
break;}
|
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPitchBend(wheel*64);
|
||||||
};
|
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPitchBend(wheel*2048);
|
||||||
} else if(KEYS_DOWN.shift && !KEYS_DOWN.alt) {
|
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPitchBend(wheel*256);
|
||||||
midiNote.velocity += wheel;
|
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPitchBend(wheel);
|
||||||
if(midiNote.velocity < 0 ) midiNote.velocity = 127;
|
break;}
|
||||||
if(midiNote.velocity > 127 ) midiNote.velocity = 0;
|
case AT:{
|
||||||
} else if(KEYS_DOWN.alt) {
|
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiAftertouch(wheel*10);
|
||||||
switch(state->node_mode){
|
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiAftertouch(wheel*100);
|
||||||
case 0:{
|
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiAftertouch(wheel);
|
||||||
float incr = (float)wheel * (KEYS_DOWN.shift ? 100.0f : KEYS_DOWN.ctrl ? 1000.0f : 10.0f);
|
break;}
|
||||||
midiNote.gate += incr;
|
case PP:{
|
||||||
if(midiNote.gate < 0 ) midiNote.gate = 0;
|
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && !KEYS_DOWN.alt) modMidiPolyPressureNote(wheel);
|
||||||
break;}
|
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && !KEYS_DOWN.alt) modMidiPolyPressureNote(wheel*10);
|
||||||
case 1:{
|
|
||||||
midiCC.value += wheel;
|
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPolyPressureValue(wheel*64);
|
||||||
if(midiCC.value < 0 ) midiCC.value = 0;
|
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPolyPressureValue(wheel*2048);
|
||||||
if(midiCC.value > 127 ) midiCC.value = 127;
|
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPolyPressureValue(wheel*256);
|
||||||
break;}
|
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) modMidiPolyPressureValue(wheel);
|
||||||
case 2:{
|
break;}
|
||||||
midiPC.value += wheel;
|
};
|
||||||
if(midiPC.value < 0 ) midiPC.value = 0;
|
|
||||||
if(midiPC.value > 127 ) midiPC.value = 127;
|
|
||||||
break;}
|
|
||||||
case 3:{
|
|
||||||
float incr = (float)wheel * (KEYS_DOWN.shift ? 100.0f : KEYS_DOWN.ctrl ? 1000.0f : 10.0f);
|
|
||||||
midiPitchBend.value += incr;
|
|
||||||
if(midiPitchBend.value < 0 ) midiPitchBend.value = 0;
|
|
||||||
if(midiPitchBend.value > 16383 ) midiPitchBend.value = 16383;
|
|
||||||
break;}
|
|
||||||
case 4:{
|
|
||||||
float incr = (float)wheel * (KEYS_DOWN.shift ? 100.0f : KEYS_DOWN.ctrl ? 1000.0f : 10.0f);
|
|
||||||
midiAftertouch.value += incr;
|
|
||||||
if(midiAftertouch.value < 0 ) midiAftertouch.value = 0;
|
|
||||||
if(midiAftertouch.value > 127 ) midiAftertouch.value = 127;
|
|
||||||
break;}
|
|
||||||
case 5:{
|
|
||||||
float incr = (float)wheel * (KEYS_DOWN.shift ? 100.0f : KEYS_DOWN.ctrl ? 1000.0f : 10.0f);
|
|
||||||
midiPolyPressure.value += incr;
|
|
||||||
if(midiPolyPressure.value < 0 ) midiPolyPressure.value = 0;
|
|
||||||
if(midiPolyPressure.value > 127 ) midiPolyPressure.value = 127;
|
|
||||||
break;}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MidiNode::draw(Vec2Df mouse, Camera2D cam) {
|
void MidiNode::draw(Vec2Df mouse, Camera2D cam) {
|
||||||
Node::draw();
|
Node::draw();
|
||||||
|
|
||||||
for(int i = 0; i < 6; ++i){
|
|
||||||
for(auto mh : midiHandles[(Handles)i]){
|
|
||||||
mh->lock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hovering() || selected) interact();
|
if(hovering() || selected) interact();
|
||||||
|
|
||||||
last = time;
|
last = time;
|
||||||
@@ -277,61 +242,124 @@ namespace VISEQ::GRAPH::NODES {
|
|||||||
} else {
|
} else {
|
||||||
fade -= (time - last)*1000.0f;
|
fade -= (time - last)*1000.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch((Handles)mode){
|
||||||
|
case NOTE:{
|
||||||
|
radius = (float)midiNote.velocity * 0.2f + 15.0f;
|
||||||
|
break;}
|
||||||
|
case CC:{
|
||||||
|
radius = (float)midiCC.value * 0.2f + 15.0f;
|
||||||
|
break;}
|
||||||
|
case PC:{
|
||||||
|
radius = (float)midiPC.value * 0.2f + 15.0f;
|
||||||
|
break;}
|
||||||
|
case PB:{
|
||||||
|
radius = (float)midiPitchBend.value * 0.002f + 15.0f;
|
||||||
|
break;}
|
||||||
|
case AT:{
|
||||||
|
radius = (float)midiAftertouch.value * 0.002f + 15.0f;
|
||||||
|
break;}
|
||||||
|
case PP:{
|
||||||
|
radius = (float)midiPolyPressure.value * 0.002f + 15.0f;
|
||||||
|
break;}
|
||||||
|
}
|
||||||
|
|
||||||
DrawRing(position, radius, radius + 4, 0, 360, 24, (Color){60, 60, 60, 255});
|
DrawRing(position, radius, radius + 4, 0, 360, 24, VS_COLOR_DARKGREY);
|
||||||
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.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});
|
if(!selected) DrawCircleLinesV(position, radius + 4, VS_COLOR_GREY);
|
||||||
|
|
||||||
float trigger_alpha = (1.f / getNotes().gate) * fade;
|
float trigger_alpha = (1.f / getNotes().gate) * fade;
|
||||||
|
|
||||||
if(!picked_up && !selected && !in_selection_rect && !hovering()) DrawCircle(position.x, position.y, radius, ColorLerp(state->mode_color, VS_COLOR_RED, trigger_alpha));
|
DrawCircle(position.x, position.y, radius, ColorLerp(state->settings.mode_colors[mode], VS_COLOR_RED, trigger_alpha));
|
||||||
if(picked_up || in_selection_rect || hovering()) DrawCircle(position.x, position.y, radius, (Color){108, 153, 187, 255});
|
if(hovering()) DrawCircleLinesV(position, radius + 4, VS_COLOR_PINK);
|
||||||
if(selected) DrawCircle(position.x, position.y, radius, (Color){255, 153, 187, 255});
|
if(picked_up || (in_selection_rect && MOUSE_LEFT.down) || selected) DrawCircleLinesV(position, radius + 4, VS_COLOR_LIGHTBLUE);
|
||||||
|
//if(selected) DrawCircle(position.x, position.y, radius, (Color){255, 153, 187, 255});
|
||||||
|
|
||||||
if(distributionMode == Distribution::RANDOM) DrawCircle(position.x, position.y, radius/2.0f, VS_COLOR_PINK);
|
if(distributionMode == Distribution::RANDOM) DrawCircle(position.x, position.y, radius/2.0f, VS_COLOR_PINK);
|
||||||
if(distributionMode == Distribution::ROUNDROBIN) DrawCircle(position.x, position.y, radius/2.0f, VS_COLOR_YELLOW);
|
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(selected) DrawCircleLinesV(position, radius+8, (Color){158, 255, 210, 255});
|
||||||
bool modified = false;
|
|
||||||
if(selected && mode >= 0 && mode < 6){
|
VMATH::Vec2D<float> desc_position = position + VMATH::Vec2D<float>(radius + 7.0f, radius + 7.0f);
|
||||||
for(auto mh : midiHandles[(Handles)mode]){
|
switch(mode){
|
||||||
mh->unlock();
|
case NOTE:{
|
||||||
mh->draw();
|
if(state->isModChainStart(APP::CTRL) || state->modifier_chain.size() == 0) DrawCenteredText(MIDI::Notes[getNotes().note], position, 14, VS_COLOR_DARKGREY);
|
||||||
std::string text = "";
|
if(state->isModChainStart(APP::SHIFT)) DrawCenteredText(std::format("{}", getNotes().velocity), position, 12, VS_COLOR_DARKGREY);
|
||||||
if(mh->hovering() || mh->picked_up){
|
|
||||||
text = std::format("{}", mh->assignedValueRef);
|
if(state->isModChain(APP::ALT)) DrawCenteredText(std::format("{:.1f}s", (float)getNotes().gate / 1000.f), position, 12, VS_COLOR_DARKGREY);
|
||||||
if(mh->name == "NOTE") text = MIDI::Notes[mh->assignedValueRef];
|
if(state->isModChainStart(APP::ALT, APP::CTRL)) DrawCenteredText(std::format("{:.2f}s", (float)getNotes().gate / 1000.f), position, 12, VS_COLOR_DARKGREY);
|
||||||
if(mh->name == "GATE") text = std::format("{:.2f}", mh->assignedValueRef / 1000.0f);
|
if(state->isModChain(APP::ALT, APP::SHIFT)) DrawCenteredText(std::format("{:.2f}s", (float)getNotes().gate / 1000.f), position, 12, VS_COLOR_DARKGREY);
|
||||||
if(mh->name == "VALUE" && (Handles)mode == PB) text = std::format("{}", round(((float)mh->assignedValueRef / 8192.0f) * 100));
|
if(state->isModChain(APP::ALT, APP::SHIFT, APP::CTRL)) DrawCenteredText(std::format("{:.3f}s", (float)getNotes().gate / 1000.f), position, 12, VS_COLOR_DARKGREY);
|
||||||
DrawCenteredText(text, position, 12, WHITE);
|
|
||||||
modified = true;
|
if(selected || hovering()){
|
||||||
}
|
if(state->isModChain(APP::CTRL)) DrawText("NOTE +1", desc_position, 8, VS_COLOR_WHITE);
|
||||||
}
|
if(state->isModChain(APP::CTRL, APP::SHIFT)) DrawText("NOTE +12", desc_position, 8, VS_COLOR_WHITE);
|
||||||
}
|
if(state->isModChain(APP::CTRL, APP::ALT)) DrawText("NOTE +12", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
if(state->isModChain(APP::CTRL, APP::SHIFT, APP::ALT)) DrawText("NOTE +24", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
if(state->isModChain(APP::CTRL, APP::ALT, APP::SHIFT)) DrawText("NOTE +24", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
|
||||||
if(!modified){
|
if(state->isModChain(APP::SHIFT)) DrawText("VELOCITY +1", desc_position, 8, VS_COLOR_WHITE);
|
||||||
switch((Handles)mode){
|
if(state->isModChain(APP::SHIFT, APP::CTRL)) DrawText("VELOCITY +16", desc_position, 8, VS_COLOR_WHITE);
|
||||||
case NOTE:{
|
if(state->isModChain(APP::SHIFT, APP::ALT)) DrawText("VELOCITY +16", desc_position, 8, VS_COLOR_WHITE);
|
||||||
DrawCenteredText(MIDI::Notes[getNotes().note], position, 12, WHITE);
|
if(state->isModChain(APP::SHIFT, APP::CTRL, APP::ALT)) DrawText("VELOCITY +32", desc_position, 8, VS_COLOR_WHITE);
|
||||||
break;}
|
if(state->isModChain(APP::SHIFT, APP::ALT, APP::CTRL)) DrawText("VELOCITY +32", desc_position, 8, VS_COLOR_WHITE);
|
||||||
case CC:{
|
|
||||||
DrawCenteredText(std::format("{}", getCC().value), position, 12, WHITE);
|
if(state->isModChain(APP::ALT)) DrawText("GATE 0.1s", desc_position, 8, VS_COLOR_WHITE);
|
||||||
break;}
|
if(state->isModChainStart(APP::ALT, APP::CTRL)) DrawText("GATE 1.0s", desc_position, 8, VS_COLOR_WHITE);
|
||||||
case PC:{
|
if(state->isModChain(APP::ALT, APP::SHIFT)) DrawText("GATE 0.01s", desc_position, 8, VS_COLOR_WHITE);
|
||||||
DrawCenteredText(std::format("{}", getPC().value), position, 12, WHITE);
|
if(state->isModChain(APP::ALT, APP::SHIFT, APP::CTRL)) DrawText("GATE 0.001s", desc_position, 8, VS_COLOR_WHITE);
|
||||||
break;}
|
}
|
||||||
case PB:{
|
break;}
|
||||||
DrawCenteredText(std::format("{}", round(((float)getPitchBend().value / 8192.0f) * 100)), position, 12, WHITE);
|
case CC:{
|
||||||
break;}
|
if(!KEYS_DOWN.shift) DrawCenteredText(std::format("{}", getCC().value), position, 12, VS_COLOR_DARKGREY);
|
||||||
case AT:{
|
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && !KEYS_DOWN.alt) DrawCenteredText(std::format("{}", getCC().control), position, 12, VS_COLOR_WHITE);
|
||||||
DrawCenteredText(std::format("{}", getAftertouch().value), position, 12, WHITE);
|
if(selected){
|
||||||
break;}
|
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && !KEYS_DOWN.alt) DrawText("CC", desc_position, 8, VS_COLOR_WHITE);
|
||||||
case PP:{
|
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && !KEYS_DOWN.alt) DrawText("VALUE", desc_position, 8, VS_COLOR_WHITE);
|
||||||
DrawCenteredText(std::format("{}", getPolyPressure().value), position, 12, WHITE);
|
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && !KEYS_DOWN.alt) DrawText("CONTROL", desc_position, 8, VS_COLOR_WHITE);
|
||||||
break;}
|
}
|
||||||
}
|
break;}
|
||||||
|
case PC:{
|
||||||
}
|
if(!KEYS_DOWN.shift) DrawCenteredText(std::format("{}", getPC().value), position, 12, VS_COLOR_DARKGREY);
|
||||||
|
if(selected){
|
||||||
|
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && !KEYS_DOWN.alt) DrawText("PROGRAM CHANGE", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && !KEYS_DOWN.alt) DrawText("PROGRAM", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
}
|
||||||
|
break;}
|
||||||
|
case PB:{
|
||||||
|
DrawCenteredText(std::format("{}", getPitchBend().value), position, 10, VS_COLOR_DARKGREY);
|
||||||
|
if(selected){
|
||||||
|
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && !KEYS_DOWN.alt) DrawText("PITCHBEND", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("64", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("2048", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("256", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("1", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
}
|
||||||
|
break;}
|
||||||
|
case AT:{
|
||||||
|
DrawCenteredText(std::format("{}", getAftertouch().value), position, 12, VS_COLOR_DARKGREY);
|
||||||
|
if(selected){
|
||||||
|
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && !KEYS_DOWN.alt) DrawText("AFTERTOUCH", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("10", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("100", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("1", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
}
|
||||||
|
break;}
|
||||||
|
case PP:{
|
||||||
|
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && !KEYS_DOWN.alt) DrawCenteredText(MIDI::Notes[getPolyPressure().note], position, 12, VS_COLOR_DARKGREY);
|
||||||
|
|
||||||
|
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawCenteredText(std::format("{}", getPolyPressure().value), position, 12, VS_COLOR_DARKGREY);
|
||||||
|
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawCenteredText(std::format("{}", getPolyPressure().value), position, 12, VS_COLOR_DARKGREY);
|
||||||
|
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) DrawCenteredText(std::format("{}", getPolyPressure().value), position, 12, VS_COLOR_DARKGREY);
|
||||||
|
if(selected){
|
||||||
|
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && !KEYS_DOWN.alt) DrawText("POLYPRESSURE", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
if(!KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("64", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
if(KEYS_DOWN.ctrl && !KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("2048", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
if(!KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("256", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
if(KEYS_DOWN.ctrl && KEYS_DOWN.shift && KEYS_DOWN.alt) DrawText("1", desc_position, 8, VS_COLOR_WHITE);
|
||||||
|
}
|
||||||
|
break;}
|
||||||
|
};
|
||||||
|
|
||||||
if(highlighted) DrawCircleLinesV(position, radius+2, (Color){255, 0, 0, 200});
|
if(highlighted) DrawCircleLinesV(position, radius+2, (Color){255, 0, 0, 200});
|
||||||
}
|
}
|
||||||
@@ -340,15 +368,6 @@ namespace VISEQ::GRAPH::NODES {
|
|||||||
std::vector<int> conns;
|
std::vector<int> conns;
|
||||||
std::ranges::transform(N.connections.begin(), N.connections.end(), std::back_inserter(conns), [](VISEQ::GRAPH::EDGES::SPTR_Edge e){ return e->id;});
|
std::ranges::transform(N.connections.begin(), N.connections.end(), std::back_inserter(conns), [](VISEQ::GRAPH::EDGES::SPTR_Edge e){ return e->id;});
|
||||||
|
|
||||||
std::vector<std::vector<Vec2Df>> handles;
|
|
||||||
|
|
||||||
for(auto i : N.midiHandles){
|
|
||||||
handles.emplace_back();
|
|
||||||
for(auto n : i.second){
|
|
||||||
handles.at(i.first).push_back(n->position);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
j = json{
|
j = json{
|
||||||
{"id", N.id},
|
{"id", N.id},
|
||||||
{"position", N.position},
|
{"position", N.position},
|
||||||
@@ -360,7 +379,6 @@ namespace VISEQ::GRAPH::NODES {
|
|||||||
{"midiPitchBend", N.midiPitchBend},
|
{"midiPitchBend", N.midiPitchBend},
|
||||||
{"midiAftertouch", N.midiAftertouch},
|
{"midiAftertouch", N.midiAftertouch},
|
||||||
{"midiPolyPressure", N.midiPolyPressure},
|
{"midiPolyPressure", N.midiPolyPressure},
|
||||||
{"handles", handles},
|
|
||||||
{"connections",conns}};
|
{"connections",conns}};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -378,20 +396,6 @@ namespace VISEQ::GRAPH::NODES {
|
|||||||
j.at("midiPitchBend").get_to(N.midiPitchBend);
|
j.at("midiPitchBend").get_to(N.midiPitchBend);
|
||||||
j.at("midiAftertouch").get_to(N.midiAftertouch);
|
j.at("midiAftertouch").get_to(N.midiAftertouch);
|
||||||
j.at("midiPolyPressure").get_to(N.midiPolyPressure);
|
j.at("midiPolyPressure").get_to(N.midiPolyPressure);
|
||||||
|
|
||||||
std::vector<std::vector<Vec2Df>> handles;
|
|
||||||
|
|
||||||
j.at("handles").get_to(handles);
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
for(auto n : handles){
|
|
||||||
int j = 0;
|
|
||||||
for(auto nn : n){
|
|
||||||
N.midiHandles[(Handles)i][j]->position = nn;
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void to_json(json& j, const std::shared_ptr<MidiNode>& N){
|
void to_json(json& j, const std::shared_ptr<MidiNode>& N){
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ namespace VISEQ::GRAPH::NODES {
|
|||||||
MIDI::MidiAftertouch midiAftertouch;
|
MIDI::MidiAftertouch midiAftertouch;
|
||||||
MIDI::MidiPolyPressure midiPolyPressure;
|
MIDI::MidiPolyPressure midiPolyPressure;
|
||||||
|
|
||||||
std::map<Handles, std::vector<std::shared_ptr<NodeHandle<int>>>> midiHandles;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct NodeMidiOut{
|
struct NodeMidiOut{
|
||||||
@@ -48,6 +46,8 @@ namespace VISEQ::GRAPH::NODES {
|
|||||||
bool send_cc = false;
|
bool send_cc = false;
|
||||||
bool send_pc = false;
|
bool send_pc = false;
|
||||||
bool send_pitch_bend = false;
|
bool send_pitch_bend = false;
|
||||||
|
bool send_aftertouch = false;
|
||||||
|
bool send_polypressure = false;
|
||||||
|
|
||||||
int midi_out = -1;
|
int midi_out = -1;
|
||||||
|
|
||||||
@@ -77,12 +77,18 @@ namespace VISEQ::GRAPH::NODES {
|
|||||||
MIDI::MidiPolyPressure getPolyPressure() const ;
|
MIDI::MidiPolyPressure getPolyPressure() const ;
|
||||||
std::vector<std::weak_ptr<ConfigNode>> getConnectedConfigNodes() const ;
|
std::vector<std::weak_ptr<ConfigNode>> getConnectedConfigNodes() const ;
|
||||||
void update() override ;
|
void update() override ;
|
||||||
void modMidiNote(int incr);
|
void modMidiChannel(int incr);
|
||||||
void modMidiCC(int incr);
|
void modMidiNoteValue(int incr);
|
||||||
void modMidiPC(int incr);
|
void modMidiNoteVelocity(int incr);
|
||||||
|
void modMidiNoteGate(int incr);
|
||||||
|
void modMidiCCValue(int incr);
|
||||||
|
void modMidiCCControl(int incr);
|
||||||
|
void modMidiPCValue(int incr);
|
||||||
|
void modMidiPCProgram(int incr);
|
||||||
void modMidiPitchBend(int incr);
|
void modMidiPitchBend(int incr);
|
||||||
void modMidiAftertouch(int incr);
|
void modMidiAftertouch(int incr);
|
||||||
void modMidiPolyPressure(int incr);
|
void modMidiPolyPressureValue(int incr);
|
||||||
|
void modMidiPolyPressureNote(int incr);
|
||||||
void interact();
|
void interact();
|
||||||
void draw(Vec2Df mouse, Camera2D cam) override ;
|
void draw(Vec2Df mouse, Camera2D cam) override ;
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <libremidi/message.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
@@ -61,12 +62,10 @@ namespace VISEQ::MIDI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Midi::note(int midi_out, int channel, int note, int velocity, int gate){
|
void Midi::note(int midi_out, int channel, int note, int velocity, int gate){
|
||||||
std::cout << "note on " << midi_out << " " << midi_outs.contains(midi_out) << std::endl;
|
|
||||||
if(midi_outs.contains(midi_out)){
|
if(midi_outs.contains(midi_out)){
|
||||||
if(midi_outs[midi_out]->is_port_open()){
|
if(midi_outs[midi_out]->is_port_open()){
|
||||||
midi_outs[midi_out]->send_message(libremidi::channel_events::note_on(channel, note, velocity));
|
midi_outs[midi_out]->send_message(libremidi::channel_events::note_on(channel, note, velocity));
|
||||||
notes.emplace_back(midi_out, channel, note, velocity, GetTime(), gate);
|
notes.emplace_back(midi_out, channel, note, velocity, GetTime(), gate);
|
||||||
std::cout << "note on " << midi_out << std::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,6 +78,14 @@ namespace VISEQ::MIDI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Midi::pc(int midi_out, int channel, int value){
|
||||||
|
if(midi_outs.contains(midi_out)){
|
||||||
|
if(midi_outs[midi_out]->is_port_open()){
|
||||||
|
midi_outs[midi_out]->send_message(libremidi::channel_events::program_change(channel, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Midi::pitch_bend(int midi_out, int channel, int pitch_value){
|
void Midi::pitch_bend(int midi_out, int channel, int pitch_value){
|
||||||
if(midi_outs.contains(midi_out)){
|
if(midi_outs.contains(midi_out)){
|
||||||
if(midi_outs[midi_out]->is_port_open()){
|
if(midi_outs[midi_out]->is_port_open()){
|
||||||
@@ -86,6 +93,22 @@ namespace VISEQ::MIDI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Midi::aftertouch(int midi_out, int channel, int aftertouch_value){
|
||||||
|
if(midi_outs.contains(midi_out)){
|
||||||
|
if(midi_outs[midi_out]->is_port_open()){
|
||||||
|
midi_outs[midi_out]->send_message(libremidi::channel_events::aftertouch(channel, aftertouch_value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Midi::polypressure(int midi_out, int channel, int note, int polypressure_value){
|
||||||
|
if(midi_outs.contains(midi_out)){
|
||||||
|
if(midi_outs[midi_out]->is_port_open()){
|
||||||
|
midi_outs[midi_out]->send_message(libremidi::channel_events::poly_pressure(channel, note, polypressure_value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Midi::all_notes_off(){
|
void Midi::all_notes_off(){
|
||||||
for(auto &n : notes){
|
for(auto &n : notes){
|
||||||
|
|||||||
@@ -50,7 +50,10 @@ namespace VISEQ::MIDI {
|
|||||||
void close_midi_out(VirtualMidiOutPort *out_port);
|
void close_midi_out(VirtualMidiOutPort *out_port);
|
||||||
void note(int midi_out, int channel, int note, int velocity, int gate);
|
void note(int midi_out, int channel, int note, int velocity, int gate);
|
||||||
void cc(int midi_out, int channel, int cc, int value);
|
void cc(int midi_out, int channel, int cc, int value);
|
||||||
|
void pc(int midi_out, int channel, int value);
|
||||||
void pitch_bend(int midi_out, int channel, int pitch_value);
|
void pitch_bend(int midi_out, int channel, int pitch_value);
|
||||||
|
void aftertouch(int midi_out, int channel, int aftertouch_value);
|
||||||
|
void polypressure(int midi_out, int channel, int note, int polypressure_value);
|
||||||
void all_notes_off();
|
void all_notes_off();
|
||||||
void update();
|
void update();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -85,14 +85,14 @@ namespace VISEQ::GRAPH::NODES {
|
|||||||
|
|
||||||
void ModNode::update() {
|
void ModNode::update() {
|
||||||
Node::update();
|
Node::update();
|
||||||
mode = state->node_mode;
|
//mode = state->node_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModNode::interact(){
|
void ModNode::interact(){
|
||||||
float wheel = GetMouseWheelMove();
|
float wheel = GetMouseWheelMove();
|
||||||
|
|
||||||
if(KEYS_DOWN.ctrl && !KEYS_DOWN.alt){
|
if(KEYS_DOWN.ctrl && !KEYS_DOWN.alt){
|
||||||
switch(state->node_mode){
|
switch(mode){
|
||||||
case 0:{
|
case 0:{
|
||||||
midiNote.note += KEYS_DOWN.shift ? ((wheel > 0) - (wheel < 0)) * 12 : wheel;
|
midiNote.note += KEYS_DOWN.shift ? ((wheel > 0) - (wheel < 0)) * 12 : wheel;
|
||||||
break;}
|
break;}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "connector.h"
|
#include "connector.h"
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
|
#include "interaction-event.h"
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
#include "vmath.h"
|
#include "vmath.h"
|
||||||
|
|
||||||
@@ -47,9 +48,16 @@ namespace VISEQ::GRAPH::NODES {
|
|||||||
|
|
||||||
void Node::update() {
|
void Node::update() {
|
||||||
if(hovering()) state->pushEvent({getPtr(), APP::Interaction::HOVER});
|
if(hovering()) state->pushEvent({getPtr(), APP::Interaction::HOVER});
|
||||||
if(hovering() && clicked()) state->pushEvent({getPtr(), APP::Interaction::PICKUP});
|
|
||||||
|
if(clicked()) {
|
||||||
|
selected = true;
|
||||||
|
state->pushEvent({getPtr(), APP::Interaction::CLICK});
|
||||||
|
}
|
||||||
|
if(hovering() && held() && !pickedUp()) state->pushEvent({getPtr(), APP::Interaction::PICKUP});
|
||||||
|
|
||||||
if(pickedUp()) state->pushEvent({getPtr(), APP::Interaction::DRAG});
|
if(pickedUp()) state->pushEvent({getPtr(), APP::Interaction::DRAG});
|
||||||
if(picked_up && released()) state->pushEvent({getPtr(), APP::Interaction::PUTDOWN});
|
if(picked_up && released()) state->pushEvent({getPtr(), APP::Interaction::PUTDOWN});
|
||||||
|
|
||||||
if(hovering() && MOUSE_RIGHT.clicked) {
|
if(hovering() && MOUSE_RIGHT.clicked) {
|
||||||
selected = true;
|
selected = true;
|
||||||
config = true;
|
config = true;
|
||||||
@@ -63,6 +71,16 @@ namespace VISEQ::GRAPH::NODES {
|
|||||||
c->update();
|
c->update();
|
||||||
}
|
}
|
||||||
if(free_connectors == 0) addConnector();
|
if(free_connectors == 0) addConnector();
|
||||||
|
in_selection_rect = CheckCollisionPointRec(position, state->selection);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::weak_ptr<Connector> Node::getConnector(){
|
||||||
|
for(auto c : connectors){
|
||||||
|
if(c->partner.expired()) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return connectors.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::draw(Vec2Df mp, Camera2D cam) {}
|
void Node::draw(Vec2Df mp, Camera2D cam) {}
|
||||||
@@ -73,6 +91,14 @@ namespace VISEQ::GRAPH::NODES {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Node::cycleMode(bool direction){
|
||||||
|
if(direction){
|
||||||
|
mode = (mode + 1) % 6;
|
||||||
|
} else {
|
||||||
|
mode -= mode > 0 ? 1 : -5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void to_json(json& j, const Node& N){
|
void to_json(json& j, const Node& N){
|
||||||
if(N.getNodeType() == NodeType::MIDINODE){
|
if(N.getNodeType() == NodeType::MIDINODE){
|
||||||
j = dynamic_cast<const MidiNode&>(N);
|
j = dynamic_cast<const MidiNode&>(N);
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ namespace VISEQ::GRAPH::NODES {
|
|||||||
std::shared_ptr<Node> getPtr();
|
std::shared_ptr<Node> getPtr();
|
||||||
virtual bool hovering() override;
|
virtual bool hovering() override;
|
||||||
void addConnector();
|
void addConnector();
|
||||||
|
std::weak_ptr<Connector> getConnector();
|
||||||
void removeConnector(std::weak_ptr<Connector> connector);
|
void removeConnector(std::weak_ptr<Connector> connector);
|
||||||
virtual NodeType getNodeType() const;
|
virtual NodeType getNodeType() const;
|
||||||
void deselect() override;
|
void deselect() override;
|
||||||
@@ -52,6 +53,7 @@ namespace VISEQ::GRAPH::NODES {
|
|||||||
void update() override;
|
void update() override;
|
||||||
void draw(Vec2Df mp, Camera2D cam) override;
|
void draw(Vec2Df mp, Camera2D cam) override;
|
||||||
void draw() override;
|
void draw() override;
|
||||||
|
virtual void cycleMode(bool direction);
|
||||||
|
|
||||||
friend void to_json(json& j, const Node& N);
|
friend void to_json(json& j, const Node& N);
|
||||||
friend void from_json(const json& j, Node& N);
|
friend void from_json(const json& j, Node& N);
|
||||||
|
|||||||
@@ -9,13 +9,14 @@ namespace VISEQ::BASE {
|
|||||||
Selectable() {}
|
Selectable() {}
|
||||||
|
|
||||||
bool in_selection_rect = false;
|
bool in_selection_rect = false;
|
||||||
bool selected = false;
|
bool selected = false;
|
||||||
|
|
||||||
bool copied = false;
|
bool copied = false;
|
||||||
bool highlighted = false;
|
bool highlighted = false;
|
||||||
bool erase = false;
|
bool erase = false;
|
||||||
Vec2Df selection_offset;
|
Vec2Df selection_offset;
|
||||||
|
|
||||||
|
void update();
|
||||||
virtual bool clicked() override;
|
virtual bool clicked() override;
|
||||||
|
|
||||||
virtual bool select() = 0;
|
virtual bool select() = 0;
|
||||||
|
|||||||
@@ -86,24 +86,27 @@ namespace VISEQ::SIGNAL {
|
|||||||
auto last = std::chrono::high_resolution_clock::now();
|
auto last = std::chrono::high_resolution_clock::now();
|
||||||
while(loop){
|
while(loop){
|
||||||
std::chrono::duration<double, std::micro> diff = std::chrono::high_resolution_clock::now() - last;
|
std::chrono::duration<double, std::micro> diff = std::chrono::high_resolution_clock::now() - last;
|
||||||
if((int)diff.count() >= 250){
|
if((int)diff.count() >= 100){
|
||||||
mutex->lock();
|
mutex->lock();
|
||||||
if(play){
|
if(play){
|
||||||
for(auto& s : signals){
|
for(auto& s : signals){
|
||||||
s->direction = (s->next.lock()->position - s->position).norm();
|
s->direction = (s->next.lock()->position - s->position).norm();
|
||||||
s->update(diff.count());
|
s->update(diff.count());
|
||||||
if(s->position.dist(s->next.lock()->position) < 0.6f) {
|
if(round(s->position.dist(s->next.lock()->position)) == 0) {
|
||||||
WPTR_Node next_node = gm->next(s->next, s->last);
|
WPTR_Node next_node = gm->next(s->next, s->last);
|
||||||
s->next.lock()->trigger();
|
s->next.lock()->trigger();
|
||||||
|
|
||||||
if(next_node.lock() != s->next.lock() && !next_node.expired() && s->next.lock()->getNodeType() == NodeType::MIDINODE) {
|
if(next_node.lock() != s->next.lock() && !next_node.expired() && s->next.lock()->getNodeType() == NodeType::MIDINODE) {
|
||||||
auto midinode = std::dynamic_pointer_cast<MidiNode>(s->next.lock());
|
auto midinode = std::dynamic_pointer_cast<MidiNode>(s->next.lock());
|
||||||
for(auto &m : midinode->selected_midi_outs){
|
for(auto &m : midinode->selected_midi_outs){
|
||||||
std::cout << m.second.name << " " << m.second.i << " " << m.second.enabled << std::endl;
|
|
||||||
if(m.second.enabled) {
|
if(m.second.enabled) {
|
||||||
|
std::cout << std::chrono::high_resolution_clock::now() << " : " << diff.count() << " " << m.second.name << " " << m.second.i << " " << m.second.enabled << std::endl;
|
||||||
if(midinode->send_note) midi.note(m.second.i, midinode->getNotes().channel, (int)Clamp(midinode->getNotes().note + s->midi_note_offset, 0, 127), midinode->getNotes().velocity, midinode->getNotes().gate);
|
if(midinode->send_note) midi.note(m.second.i, midinode->getNotes().channel, (int)Clamp(midinode->getNotes().note + s->midi_note_offset, 0, 127), midinode->getNotes().velocity, midinode->getNotes().gate);
|
||||||
if(midinode->send_cc) midi.cc(m.second.i, midinode->getCC().channel, midinode->getCC().control, (int)Clamp(midinode->getCC().value + s->midi_cc_offset, 0, 127));
|
if(midinode->send_cc) midi.cc(m.second.i, midinode->getCC().channel, midinode->getCC().control, (int)Clamp(midinode->getCC().value + s->midi_cc_offset, 0, 127));
|
||||||
|
if(midinode->send_pc) midi.pc(m.second.i, midinode->getPC().channel, midinode->getPC().value);
|
||||||
if(midinode->send_pitch_bend) midi.pitch_bend(m.second.i, midinode->getPitchBend().channel, midinode->getPitchBend().value);
|
if(midinode->send_pitch_bend) midi.pitch_bend(m.second.i, midinode->getPitchBend().channel, midinode->getPitchBend().value);
|
||||||
|
if(midinode->send_aftertouch) midi.aftertouch(m.second.i, midinode->getAftertouch().channel, midinode->getAftertouch().value);
|
||||||
|
if(midinode->send_polypressure) midi.polypressure(m.second.i, midinode->getPolyPressure().channel, midinode->getPolyPressure().note, midinode->getPolyPressure().value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s->last = s->next;
|
s->last = s->next;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "raylib.h"
|
#include "raylib.h"
|
||||||
#include "vmath.h"
|
#include "vmath.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
namespace VISEQ::APP{
|
namespace VISEQ::APP{
|
||||||
|
|
||||||
@@ -54,6 +55,29 @@ namespace VISEQ::APP{
|
|||||||
keys_released.shift = IsKeyReleased(KEY_LEFT_SHIFT) || IsKeyReleased(KEY_RIGHT_SHIFT);
|
keys_released.shift = IsKeyReleased(KEY_LEFT_SHIFT) || IsKeyReleased(KEY_RIGHT_SHIFT);
|
||||||
keys_released.alt = IsKeyReleased(KEY_LEFT_ALT) || IsKeyReleased(KEY_RIGHT_ALT);
|
keys_released.alt = IsKeyReleased(KEY_LEFT_ALT) || IsKeyReleased(KEY_RIGHT_ALT);
|
||||||
|
|
||||||
|
int n_modifier = keys_down.alt + keys_down.ctrl + keys_down.shift;
|
||||||
|
|
||||||
|
if(modifier_chain.size() < n_modifier){
|
||||||
|
ModifierKeyNames modKey = keys_pressed.ctrl ? CTRL : keys_pressed.shift ? SHIFT : ALT;
|
||||||
|
modifier_chain.push_back(modKey);
|
||||||
|
//std::cout << modifier_chain.size() << " " << modKey << std::endl;
|
||||||
|
for(ModifierKeyNames n : modifier_chain){
|
||||||
|
std::cout << n << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(modifier_chain.size() > n_modifier){
|
||||||
|
ModifierKeyNames modKey = keys_released.ctrl ? CTRL : keys_released.shift ? SHIFT : ALT;
|
||||||
|
auto it = std::remove(modifier_chain.begin(), modifier_chain.end(), modKey);
|
||||||
|
modifier_chain.erase(it);
|
||||||
|
//std::cout << modifier_chain.size() << " " << modKey << std::endl;
|
||||||
|
for(ModifierKeyNames n : modifier_chain){
|
||||||
|
std::cout << n << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
screen_mouse = {round(mouse_pos.x), round(mouse_pos.y)};
|
screen_mouse = {round(mouse_pos.x), round(mouse_pos.y)};
|
||||||
raw_mouse = {GetMousePosition().x, GetMousePosition().y};
|
raw_mouse = {GetMousePosition().x, GetMousePosition().y};
|
||||||
mod_mouse = {round(mouse_pos.x), round(mouse_pos.y)};
|
mod_mouse = {round(mouse_pos.x), round(mouse_pos.y)};
|
||||||
@@ -73,4 +97,30 @@ namespace VISEQ::APP{
|
|||||||
}
|
}
|
||||||
return State::instance;
|
return State::instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool State::isModChainEmpty(){
|
||||||
|
return modifier_chain.size() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool State::isModChainStart(ModifierKeyNames first){
|
||||||
|
if(modifier_chain.size() < 1) return false;
|
||||||
|
return std::equal(modifier_chain.begin(), modifier_chain.begin() + 1, std::vector<ModifierKeyNames>{first}.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool State::isModChainStart(ModifierKeyNames first, ModifierKeyNames second){
|
||||||
|
if(modifier_chain.size() < 2) return false;
|
||||||
|
return std::equal(modifier_chain.begin(), modifier_chain.begin() + 2, std::vector<ModifierKeyNames>{first, second}.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool State::isModChain(ModifierKeyNames first){
|
||||||
|
return modifier_chain == std::vector<ModifierKeyNames>{first};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool State::isModChain(ModifierKeyNames first, ModifierKeyNames second){
|
||||||
|
return modifier_chain == std::vector<ModifierKeyNames>{first, second};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool State::isModChain(ModifierKeyNames first, ModifierKeyNames second, ModifierKeyNames third){
|
||||||
|
return modifier_chain == std::vector<ModifierKeyNames>{first, second, third};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ namespace VISEQ::APP{
|
|||||||
bool alt = false;
|
bool alt = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ModifierKeyNames {CTRL, SHIFT, ALT};
|
||||||
|
|
||||||
class State{
|
class State{
|
||||||
public:
|
public:
|
||||||
State(){}
|
State(){}
|
||||||
@@ -66,6 +68,7 @@ namespace VISEQ::APP{
|
|||||||
|
|
||||||
int node_mode = 0;
|
int node_mode = 0;
|
||||||
bool context_menu = false;
|
bool context_menu = false;
|
||||||
|
bool draw_edge_lengths = false;
|
||||||
|
|
||||||
bool hovering = false;
|
bool hovering = false;
|
||||||
|
|
||||||
@@ -79,6 +82,8 @@ namespace VISEQ::APP{
|
|||||||
ModifierKeys keys_pressed;
|
ModifierKeys keys_pressed;
|
||||||
ModifierKeys keys_released;
|
ModifierKeys keys_released;
|
||||||
|
|
||||||
|
std::vector<ModifierKeyNames> modifier_chain;
|
||||||
|
|
||||||
Rectangle selection;
|
Rectangle selection;
|
||||||
Rectangle bounding_box;
|
Rectangle bounding_box;
|
||||||
|
|
||||||
@@ -96,6 +101,13 @@ namespace VISEQ::APP{
|
|||||||
static std::shared_ptr<State> get();
|
static std::shared_ptr<State> get();
|
||||||
|
|
||||||
std::deque<InteractionEvent> event_queue;
|
std::deque<InteractionEvent> event_queue;
|
||||||
|
|
||||||
|
bool isModChainEmpty();
|
||||||
|
bool isModChainStart(ModifierKeyNames first);
|
||||||
|
bool isModChainStart(ModifierKeyNames first, ModifierKeyNames second);
|
||||||
|
bool isModChain(ModifierKeyNames first);
|
||||||
|
bool isModChain(ModifierKeyNames first, ModifierKeyNames second);
|
||||||
|
bool isModChain(ModifierKeyNames first, ModifierKeyNames second, ModifierKeyNames third);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "raygui/raygui.h"
|
#include "raygui/raygui.h"
|
||||||
|
|
||||||
#include "datatypes.h"
|
#include "datatypes.h"
|
||||||
|
#include "vmath.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
@@ -14,6 +15,7 @@
|
|||||||
namespace VISEQ::APP::UI{
|
namespace VISEQ::APP::UI{
|
||||||
void AppUI::init(){
|
void AppUI::init(){
|
||||||
GuiLoadStyleDark();
|
GuiLoadStyleDark();
|
||||||
|
inter = LoadFontEx("resources/fonts/Inter_28pt-Bold.ttf", 96, 0, 250);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppUI::drawSideBar(){
|
void AppUI::drawSideBar(){
|
||||||
@@ -77,9 +79,11 @@ namespace VISEQ::APP::UI{
|
|||||||
s->multiplier = state->settings.bpm / 120.0f;
|
s->multiplier = state->settings.bpm / 120.0f;
|
||||||
float signal_bpm = round(state->settings.bpm * s->multiplier * (s->speed / state->settings.speed));
|
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(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;
|
||||||
|
|
||||||
|
GuiLabel((Rectangle){175, (float)s_signal+70 + signal_configs*20, 40, 20}, std::format("{}",signal_bpm).c_str());
|
||||||
|
|
||||||
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/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;
|
//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);
|
GuiToggle((Rectangle){240, (float)s_signal+70 + signal_configs*20, 20, 20},"P", &s->run);
|
||||||
s->speed = s_speed;
|
s->speed = s_speed;
|
||||||
signal_configs++;
|
signal_configs++;
|
||||||
@@ -93,19 +97,20 @@ namespace VISEQ::APP::UI{
|
|||||||
DrawText(std::format("{}", gm->getNodesSize()).c_str(), 20, state->settings.height - 70, 15, VS_COLOR_WHITE);
|
DrawText(std::format("{}", gm->getNodesSize()).c_str(), 20, state->settings.height - 70, 15, VS_COLOR_WHITE);
|
||||||
DrawFPS(20, state->settings.height - 30);
|
DrawFPS(20, state->settings.height - 30);
|
||||||
|
|
||||||
std::string shorts[6] = {"NT","CC","PC","PB","AT","PP"};
|
// std::string shorts[6] = {"NT","CC","PC","PB","AT","PP"};
|
||||||
for(int i = 0; i < 6; ++i){
|
// for(int i = 0; i < 6; ++i){
|
||||||
Color col = state->settings.mode_colors[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};
|
// 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});
|
// 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);
|
// DrawCircleV(pos, 30.0f, col);
|
||||||
DrawCenteredText(shorts[i], pos, 20, WHITE);
|
// DrawCenteredText(shorts[i], pos, 20, WHITE);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppUI::DrawCenteredText(std::string text, Vec2Df position, int size, Color color){
|
void AppUI::DrawCenteredText(std::string text, Vec2Df position, int size, Color color){
|
||||||
float offset = MeasureText(text.c_str(), size);
|
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 );
|
//DrawText(text.c_str(), position.x-offset/2.0f, position.y-(float)size/2.0f+1, size, color );
|
||||||
|
DrawTextEx(inter, text.c_str(), Vec2Df(position.x-offset/2.0f, position.y-(float)size/2.0f+1), size, 2.0f, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppUI::drawContextMenu(Camera2D camera){
|
void AppUI::drawContextMenu(Camera2D camera){
|
||||||
@@ -138,13 +143,20 @@ namespace VISEQ::APP::UI{
|
|||||||
int y_channel = y_midi + 30 + i*20;
|
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 + 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 + 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);
|
GuiCheckBox((Rectangle){np.x + 160, np.y + y_channel, 20, 20}, "PITCH-B", &mn->send_pitch_bend);
|
||||||
|
|
||||||
|
int y_send_bools = y_channel + 30;
|
||||||
|
GuiCheckBox((Rectangle){np.x + 20, np.y + y_send_bools, 20, 20}, "PC", &mn->send_pc);
|
||||||
|
GuiCheckBox((Rectangle){np.x + 90, np.y + y_send_bools, 20, 20}, "AT", &mn->send_aftertouch);
|
||||||
|
GuiCheckBox((Rectangle){np.x + 160, np.y + y_send_bools, 20, 20}, "POLY-P", &mn->send_polypressure);
|
||||||
|
|
||||||
int y_cc_note = y_channel + 120;
|
int y_cc_note = y_send_bools + 120;
|
||||||
|
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);
|
||||||
|
|
||||||
|
/*
|
||||||
switch(state->node_mode){
|
switch(state->node_mode){
|
||||||
case 0:{
|
case 0:{
|
||||||
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);
|
|
||||||
|
|
||||||
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note , 100, 20}, "NOTE");
|
GuiLabel((Rectangle){np.x + 20, np.y + y_cc_note , 100, 20}, "NOTE");
|
||||||
float v = mn->midiNote.note;
|
float v = mn->midiNote.note;
|
||||||
@@ -194,7 +206,7 @@ namespace VISEQ::APP::UI{
|
|||||||
GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 30, 220, 20}, "", "", &v, 0, 16383);
|
GuiSlider((Rectangle){np.x + 20, np.y + y_cc_note + 30, 220, 20}, "", "", &v, 0, 16383);
|
||||||
mn->midiPitchBend.value = round(v);
|
mn->midiPitchBend.value = round(v);
|
||||||
break;}
|
break;}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,14 @@ namespace VISEQ::VMATH{
|
|||||||
return Vec2D(-y, x);
|
return Vec2D(-y, x);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Vec2D rotate(float deg){
|
||||||
|
return Vec2D(cos(deg*DEG2RAD) * x, sin(deg*DEG2RAD) * y);
|
||||||
|
};
|
||||||
|
|
||||||
|
Vec2D rotateAround(Vec2D<T> v, float deg){
|
||||||
|
return Vec2D(cos(deg*DEG2RAD) * (x - v.x), sin(deg*DEG2RAD) * (y-v.y)) + v;
|
||||||
|
};
|
||||||
|
|
||||||
Vec2D norm() { return *this / length();};
|
Vec2D norm() { return *this / length();};
|
||||||
|
|
||||||
Vec2D center(Vec2D v){
|
Vec2D center(Vec2D v){
|
||||||
@@ -166,7 +174,7 @@ namespace VISEQ::VMATH{
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Vec2D<T> polarToCartesian(T r, T q) {
|
Vec2D<T> polarToCartesian(T r, T q) {
|
||||||
return Vec2D<T>{r * cos(q), r * sin(q)};
|
return Vec2D<T>{r * (T)cos(q), r * (T)sin(q)};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||