@@ -30,9 +30,6 @@ CFLAGS += -DNOC_FILE_DIALOG_OSX | |||||
CXXFLAGS += -DAPPLE -stdlib=libc++ -I$(HOME)/local/include | CXXFLAGS += -DAPPLE -stdlib=libc++ -I$(HOME)/local/include | ||||
LDFLAGS += -stdlib=libc++ -L$(HOME)/local/lib -lpthread -lglew -lglfw3 -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo -ldl -ljansson -lportaudio -lportmidi -lsamplerate | LDFLAGS += -stdlib=libc++ -L$(HOME)/local/lib -lpthread -lglew -lglfw3 -framework Cocoa -framework OpenGL -framework IOKit -framework CoreVideo -ldl -ljansson -lportaudio -lportmidi -lsamplerate | ||||
TARGET = Rack | TARGET = Rack | ||||
Rack.app: $(TARGET) | |||||
./bundle.sh | |||||
endif | endif | ||||
# Windows | # Windows | ||||
@@ -52,41 +49,13 @@ LDFLAGS += \ | |||||
-L$(HOME)/pkg/portaudio-r1891-build/lib/x64/ReleaseMinDependency -lportaudio_x64 \ | -L$(HOME)/pkg/portaudio-r1891-build/lib/x64/ReleaseMinDependency -lportaudio_x64 \ | ||||
-Wl,--export-all-symbols,--out-implib,libRack.a -mwindows | -Wl,--export-all-symbols,--out-implib,libRack.a -mwindows | ||||
TARGET = Rack.exe | TARGET = Rack.exe | ||||
# OBJECTS = Rack.res | |||||
%.res: %.rc | |||||
windres $^ -O coff -o $@ | |||||
endif | |||||
OBJECTS = Rack.res | |||||
all: $(TARGET) | all: $(TARGET) | ||||
dist: $(TARGET) | |||||
# Rack | |||||
mkdir -p dist/Rack | |||||
cp LICENSE* dist/Rack/ | |||||
ifeq ($(ARCH), linux) | |||||
cp Rack dist/Rack/ | |||||
endif | |||||
ifeq ($(ARCH), apple) | |||||
./bundle.sh | |||||
cp -R Rack.app dist/Rack/ | |||||
endif | |||||
ifeq ($(ARCH), windows) | |||||
cp Rack.exe dist/Rack/ | |||||
./copy_dlls.sh | |||||
cp *.dll dist/Rack/ | |||||
%.res: %.rc | |||||
windres $^ -O coff -o $@ | |||||
endif | endif | ||||
cp -R res dist/Rack/ | |||||
mkdir -p dist/Rack/plugins | |||||
# Fundamental | |||||
$(MAKE) -C plugins/Fundamental dist | |||||
cp -R plugins/Fundamental/dist/Fundamental dist/Rack/plugins/ | |||||
# zip | |||||
cd dist && zip -5 -r Rack.zip Rack | |||||
clean: | |||||
rm -rfv build $(TARGET) dist | |||||
include Makefile.inc | include Makefile.inc |
@@ -0,0 +1 @@ | |||||
GLFW_ICON ICON res/icon.ico |
@@ -0,0 +1,97 @@ | |||||
#pragma once | |||||
#include "scene.hpp" | |||||
namespace rack { | |||||
//////////////////// | |||||
// knobs | |||||
//////////////////// | |||||
struct KnobDavies1900h : SpriteKnob { | |||||
KnobDavies1900h() { | |||||
box.size = Vec(36, 36); | |||||
spriteOffset = Vec(-8, -8); | |||||
spriteSize = Vec(64, 64); | |||||
minIndex = 44; | |||||
maxIndex = -46; | |||||
spriteCount = 120; | |||||
} | |||||
}; | |||||
struct KnobDavies1900hWhite : KnobDavies1900h { | |||||
KnobDavies1900hWhite() { | |||||
spriteImage = Image::load("res/ComponentLibrary/Davies1900hWhite.png"); | |||||
} | |||||
}; | |||||
struct KnobDavies1900hBlack : KnobDavies1900h { | |||||
KnobDavies1900hBlack() { | |||||
spriteImage = Image::load("res/ComponentLibrary/Davies1900hBlack.png"); | |||||
} | |||||
}; | |||||
struct KnobDavies1900hRed : KnobDavies1900h { | |||||
KnobDavies1900hRed() { | |||||
spriteImage = Image::load("res/ComponentLibrary/Davies1900hRed.png"); | |||||
} | |||||
}; | |||||
//////////////////// | |||||
// ports | |||||
//////////////////// | |||||
struct PJ301M : SpriteWidget { | |||||
PJ301M() { | |||||
box.size = Vec(24, 24); | |||||
spriteOffset = Vec(-10, -10); | |||||
spriteSize = Vec(48, 48); | |||||
spriteImage = Image::load("res/ComponentLibrary/PJ301M.png"); | |||||
} | |||||
}; | |||||
struct InputPortPJ301M : InputPort, PJ301M {}; | |||||
struct OutputPortPJ301M: OutputPort, PJ301M {}; | |||||
struct PJ3410 : SpriteWidget { | |||||
PJ3410() { | |||||
box.size = Vec(31, 31); | |||||
spriteOffset = Vec(-9, -9); | |||||
spriteSize = Vec(54, 54); | |||||
spriteImage = Image::load("res/ComponentLibrary/PJ3410.png"); | |||||
} | |||||
}; | |||||
struct InputPortPJ3410 : InputPort, PJ3410 {}; | |||||
struct OutputPortPJ3410: OutputPort, PJ3410 {}; | |||||
struct CL1362 : SpriteWidget { | |||||
CL1362() { | |||||
box.size = Vec(33, 29); | |||||
spriteOffset = Vec(-10, -10); | |||||
spriteSize = Vec(57, 54); | |||||
spriteImage = Image::load("res/ComponentLibrary/CL1362.png"); | |||||
} | |||||
}; | |||||
struct InputPortCL1362 : InputPort, CL1362 {}; | |||||
struct OutputPortCL1362 : OutputPort, CL1362 {}; | |||||
//////////////////// | |||||
// panels | |||||
//////////////////// | |||||
struct LightPanel : Panel { | |||||
LightPanel() { | |||||
backgroundColor = nvgRGB(0xe8, 0xe8, 0xe8); | |||||
borderColor = nvgRGB(0xac, 0xac, 0xac); | |||||
} | |||||
}; | |||||
struct DarkPanel : Panel { | |||||
DarkPanel() { | |||||
backgroundColor = nvgRGB(0x0f, 0x0f, 0x0f); | |||||
borderColor = nvgRGB(0x5e, 0x5e, 0x5e); | |||||
} | |||||
}; | |||||
} // namespace rack |
@@ -13,5 +13,7 @@ void guiCursorUnlock(); | |||||
const char *guiSaveDialog(const char *filters, const char *filename); | const char *guiSaveDialog(const char *filters, const char *filename); | ||||
const char *guiOpenDialog(const char *filters, const char *filename); | const char *guiOpenDialog(const char *filters, const char *filename); | ||||
// TODO This should probably go in another file, like resources.hpp? | |||||
void drawSVG(NVGcontext *vg, NSVGimage *svg); | |||||
} // namespace rack | } // namespace rack |
@@ -2,6 +2,7 @@ | |||||
#include "plugin.hpp" | #include "plugin.hpp" | ||||
#include "engine.hpp" | #include "engine.hpp" | ||||
#include "gui.hpp" | #include "gui.hpp" | ||||
#include "components.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -11,14 +12,6 @@ namespace rack { | |||||
// helpers | // helpers | ||||
//////////////////// | //////////////////// | ||||
inline | |||||
Plugin *createPlugin(std::string slug, std::string name) { | |||||
Plugin *plugin = new Plugin(); | |||||
plugin->slug = slug; | |||||
plugin->name = name; | |||||
return plugin; | |||||
} | |||||
template <class TModuleWidget> | template <class TModuleWidget> | ||||
Model *createModel(Plugin *plugin, std::string slug, std::string name) { | Model *createModel(Plugin *plugin, std::string slug, std::string name) { | ||||
struct TModel : Model { | struct TModel : Model { | ||||
@@ -93,8 +93,9 @@ struct RackWidget : OpaqueWidget { | |||||
void onMouseDown(int button); | void onMouseDown(int button); | ||||
}; | }; | ||||
struct ModulePanel : TransparentWidget { | |||||
struct Panel : TransparentWidget { | |||||
NVGcolor backgroundColor; | NVGcolor backgroundColor; | ||||
NVGcolor borderColor; | |||||
std::shared_ptr<Image> backgroundImage; | std::shared_ptr<Image> backgroundImage; | ||||
void draw(NVGcontext *vg); | void draw(NVGcontext *vg); | ||||
}; | }; | ||||
@@ -109,7 +110,7 @@ struct Light : TransparentWidget, SpriteWidget { | |||||
}; | }; | ||||
// If you don't add these to your ModuleWidget, it will fall out of the RackWidget | // If you don't add these to your ModuleWidget, it will fall out of the RackWidget | ||||
struct Screw : TransparentWidget, SpriteWidget { | |||||
struct Screw : TransparentWidget { | |||||
Screw(); | Screw(); | ||||
}; | }; | ||||
@@ -123,14 +124,17 @@ struct ParamWidget : OpaqueWidget, QuantityWidget { | |||||
void onChange(); | void onChange(); | ||||
}; | }; | ||||
struct Knob : ParamWidget, SpriteWidget { | |||||
int minIndex, maxIndex, spriteCount; | |||||
void step(); | |||||
struct Knob : ParamWidget { | |||||
void onDragStart(); | void onDragStart(); | ||||
void onDragMove(Vec mouseRel); | void onDragMove(Vec mouseRel); | ||||
void onDragEnd(); | void onDragEnd(); | ||||
}; | }; | ||||
struct SpriteKnob : Knob, SpriteWidget { | |||||
int minIndex, maxIndex, spriteCount; | |||||
void step(); | |||||
}; | |||||
struct Switch : ParamWidget, SpriteWidget { | struct Switch : ParamWidget, SpriteWidget { | ||||
}; | }; | ||||
@@ -212,47 +216,9 @@ struct RackScene : Scene { | |||||
RackScene(); | RackScene(); | ||||
void step(); | void step(); | ||||
void draw(NVGcontext *vg); | |||||
}; | }; | ||||
//////////////////// | |||||
// Component Library | |||||
//////////////////// | |||||
struct PJ301M : SpriteWidget { | |||||
PJ301M() { | |||||
box.size = Vec(24, 24); | |||||
spriteOffset = Vec(-10, -10); | |||||
spriteSize = Vec(48, 48); | |||||
spriteImage = Image::load("res/ComponentLibrary/PJ301M.png"); | |||||
} | |||||
}; | |||||
struct InputPortPJ301M : InputPort, PJ301M {}; | |||||
struct OutputPortPJ301M: OutputPort, PJ301M {}; | |||||
struct PJ3410 : SpriteWidget { | |||||
PJ3410() { | |||||
box.size = Vec(31, 31); | |||||
spriteOffset = Vec(-9, -9); | |||||
spriteSize = Vec(54, 54); | |||||
spriteImage = Image::load("res/ComponentLibrary/PJ3410.png"); | |||||
} | |||||
}; | |||||
struct InputPortPJ3410 : InputPort, PJ3410 {}; | |||||
struct OutputPortPJ3410: OutputPort, PJ3410 {}; | |||||
struct CL1362 : SpriteWidget { | |||||
CL1362() { | |||||
box.size = Vec(33, 29); | |||||
spriteOffset = Vec(-10, -10); | |||||
spriteSize = Vec(57, 54); | |||||
spriteImage = Image::load("res/ComponentLibrary/CL1362.png"); | |||||
} | |||||
}; | |||||
struct InputPortCL1362 : InputPort, CL1362 {}; | |||||
struct OutputPortCL1362 : OutputPort, CL1362 {}; | |||||
//////////////////// | //////////////////// | ||||
// globals | // globals | ||||
//////////////////// | //////////////////// | ||||
@@ -35,7 +35,7 @@ struct Image { | |||||
}; | }; | ||||
struct SVG { | struct SVG { | ||||
NSVGimage *image; | |||||
NSVGimage *handle; | |||||
SVG(const std::string &filename); | SVG(const std::string &filename); | ||||
~SVG(); | ~SVG(); | ||||
static std::shared_ptr<SVG> load(const std::string &filename); | static std::shared_ptr<SVG> load(const std::string &filename); | ||||
@@ -46,7 +46,7 @@ struct AudioInterface : Module { | |||||
SampleRateConverter<2> outputSrc; | SampleRateConverter<2> outputSrc; | ||||
// in rack's sample rate | // in rack's sample rate | ||||
DoubleRingBuffer<Frame<2>, 32> inputBuffer; | |||||
DoubleRingBuffer<Frame<2>, 16> inputBuffer; | |||||
DoubleRingBuffer<Frame<2>, (1<<15)> outputBuffer; | DoubleRingBuffer<Frame<2>, (1<<15)> outputBuffer; | ||||
// in device's sample rate | // in device's sample rate | ||||
DoubleRingBuffer<Frame<2>, (1<<15)> inputSrcBuffer; | DoubleRingBuffer<Frame<2>, (1<<15)> inputSrcBuffer; | ||||
@@ -121,7 +121,7 @@ void AudioInterface::step() { | |||||
err = Pa_ReadStream(stream, (float*) buf, blockSize); | err = Pa_ReadStream(stream, (float*) buf, blockSize); | ||||
if (err) { | if (err) { | ||||
// Ignore buffer underflows | // Ignore buffer underflows | ||||
if (err != paInputOverflowed) { | |||||
if (err == paInputOverflowed) { | |||||
fprintf(stderr, "Audio input buffer underflow\n"); | fprintf(stderr, "Audio input buffer underflow\n"); | ||||
} | } | ||||
} | } | ||||
@@ -143,7 +143,7 @@ void AudioInterface::step() { | |||||
inputSrcBuffer.startIncr(blockSize); | inputSrcBuffer.startIncr(blockSize); | ||||
if (err) { | if (err) { | ||||
// Ignore buffer underflows | // Ignore buffer underflows | ||||
if (err != paOutputUnderflowed) { | |||||
if (err == paOutputUnderflowed) { | |||||
fprintf(stderr, "Audio output buffer underflow\n"); | fprintf(stderr, "Audio output buffer underflow\n"); | ||||
} | } | ||||
} | } | ||||
@@ -308,7 +308,8 @@ struct SampleRateChoice : ChoiceButton { | |||||
menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | ||||
const float sampleRates[6] = {44100, 48000, 88200, 96000, 176400, 192000}; | const float sampleRates[6] = {44100, 48000, 88200, 96000, 176400, 192000}; | ||||
for (int i = 0; i < 6; i++) { | |||||
int sampleRatesLen = sizeof(sampleRates) / sizeof(sampleRates[0]); | |||||
for (int i = 0; i < sampleRatesLen; i++) { | |||||
SampleRateItem *item = new SampleRateItem(); | SampleRateItem *item = new SampleRateItem(); | ||||
item->audioInterface = audioInterface; | item->audioInterface = audioInterface; | ||||
item->sampleRate = sampleRates[i]; | item->sampleRate = sampleRates[i]; | ||||
@@ -340,8 +341,9 @@ struct BlockSizeChoice : ChoiceButton { | |||||
Menu *menu = new Menu(); | Menu *menu = new Menu(); | ||||
menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | menu->box.pos = getAbsolutePos().plus(Vec(0, box.size.y)); | ||||
const int blockSizes[6] = {128, 256, 512, 1024, 2048, 4096}; | |||||
for (int i = 0; i < 6; i++) { | |||||
const int blockSizes[] = {64, 128, 256, 512, 1024, 2048, 4096}; | |||||
int blockSizesLen = sizeof(blockSizes) / sizeof(blockSizes[0]); | |||||
for (int i = 0; i < blockSizesLen; i++) { | |||||
BlockSizeItem *item = new BlockSizeItem(); | BlockSizeItem *item = new BlockSizeItem(); | ||||
item->audioInterface = audioInterface; | item->audioInterface = audioInterface; | ||||
item->blockSize = blockSizes[i]; | item->blockSize = blockSizes[i]; | ||||
@@ -362,24 +364,14 @@ AudioInterfaceWidget::AudioInterfaceWidget() : ModuleWidget(new AudioInterface() | |||||
box.size = Vec(15*8, 380); | box.size = Vec(15*8, 380); | ||||
{ | { | ||||
ModulePanel *panel = new ModulePanel(); | |||||
Panel *panel = new LightPanel(); | |||||
panel->box.size = box.size; | panel->box.size = box.size; | ||||
panel->backgroundColor = nvgRGBf(0.90, 0.90, 0.90); | |||||
// panel->imageFilename = ""; | |||||
addChild(panel); | addChild(panel); | ||||
} | } | ||||
float margin = 5; | float margin = 5; | ||||
float yPos = margin; | float yPos = margin; | ||||
{ | |||||
Label *label = new Label(); | |||||
label->box.pos = Vec(margin, yPos); | |||||
label->text = "Audio Interface"; | |||||
addChild(label); | |||||
yPos += label->box.size.y + margin; | |||||
} | |||||
{ | { | ||||
Label *label = new Label(); | Label *label = new Label(); | ||||
label->box.pos = Vec(margin, yPos); | label->box.pos = Vec(margin, yPos); | ||||
@@ -225,10 +225,8 @@ MidiInterfaceWidget::MidiInterfaceWidget() : ModuleWidget(new MidiInterface()) { | |||||
box.size = Vec(15*8, 380); | box.size = Vec(15*8, 380); | ||||
{ | { | ||||
ModulePanel *panel = new ModulePanel(); | |||||
Panel *panel = new LightPanel(); | |||||
panel->box.size = box.size; | panel->box.size = box.size; | ||||
panel->backgroundColor = nvgRGBf(0.90, 0.90, 0.90); | |||||
// panel->imageFilename = ""; | |||||
addChild(panel); | addChild(panel); | ||||
} | } | ||||
@@ -1,9 +1,6 @@ | |||||
#include "core.hpp" | #include "core.hpp" | ||||
using namespace rack; | |||||
struct CorePlugin : Plugin { | struct CorePlugin : Plugin { | ||||
CorePlugin() { | CorePlugin() { | ||||
slug = "Core"; | slug = "Core"; | ||||
@@ -129,9 +129,9 @@ static void engineRun() { | |||||
} | } | ||||
} | } | ||||
auto end = std::chrono::high_resolution_clock::now(); | auto end = std::chrono::high_resolution_clock::now(); | ||||
auto duration = std::chrono::nanoseconds((long) (0.9 * 1e9 * stepSize / gSampleRate)) - (end - start); | |||||
auto duration = std::chrono::nanoseconds((long) (0.5 * 1e9 * stepSize / gSampleRate)) - (end - start); | |||||
// Avoid pegging the CPU at 100% when there are no "blocking" modules like AudioInterface, but still step audio at a reasonable rate | // Avoid pegging the CPU at 100% when there are no "blocking" modules like AudioInterface, but still step audio at a reasonable rate | ||||
std::this_thread::sleep_for(duration); | |||||
// std::this_thread::sleep_for(duration); | |||||
} | } | ||||
} | } | ||||
@@ -314,8 +314,8 @@ std::shared_ptr<Image> Image::load(const std::string &filename) { | |||||
//////////////////// | //////////////////// | ||||
SVG::SVG(const std::string &filename) { | SVG::SVG(const std::string &filename) { | ||||
image = nsvgParseFromFile(filename.c_str(), "px", 96.0); | |||||
if (image) { | |||||
handle = nsvgParseFromFile(filename.c_str(), "px", 96.0); | |||||
if (handle) { | |||||
fprintf(stderr, "Loaded SVG %s\n", filename.c_str()); | fprintf(stderr, "Loaded SVG %s\n", filename.c_str()); | ||||
} | } | ||||
else { | else { | ||||
@@ -324,7 +324,7 @@ SVG::SVG(const std::string &filename) { | |||||
} | } | ||||
SVG::~SVG() { | SVG::~SVG() { | ||||
nsvgDelete(image); | |||||
nsvgDelete(handle); | |||||
} | } | ||||
std::shared_ptr<SVG> SVG::load(const std::string &filename) { | std::shared_ptr<SVG> SVG::load(const std::string &filename) { | ||||
@@ -336,4 +336,83 @@ std::shared_ptr<SVG> SVG::load(const std::string &filename) { | |||||
} | } | ||||
//////////////////// | |||||
// drawSVG | |||||
//////////////////// | |||||
NVGcolor getNVGColor(int color) { | |||||
return nvgRGBA((color >> 0) & 0xff, (color >> 8) & 0xff, (color >> 16) & 0xff, (color >> 24) & 0xff); | |||||
// return nvgRGBA((color >> 24) & 0xff, (color >> 16) & 0xff, (color >> 8) & 0xff, (color) & 0xff); | |||||
} | |||||
void drawSVG(NVGcontext *vg, NSVGimage *svg) { | |||||
for (NSVGshape *shape = svg->shapes; shape; shape = shape->next) { | |||||
// printf(" new shape: id \"%s\", fillrule %d\n", shape->id, shape->fillRule); | |||||
if (!(shape->flags & NSVG_FLAGS_VISIBLE)) | |||||
continue; | |||||
nvgSave(vg); | |||||
nvgGlobalAlpha(vg, shape->opacity); | |||||
nvgStrokeWidth(vg, shape->strokeWidth); | |||||
// strokeDashOffset, strokeDashArray, strokeDashCount not supported | |||||
// strokeLineJoin, strokeLineCap not supported | |||||
// Build path | |||||
nvgBeginPath(vg); | |||||
for (NSVGpath *path = shape->paths; path; path = path->next) { | |||||
// printf(" new path: %d points, %s\n", path->npts, path->closed ? "closed" : "notclosed"); | |||||
nvgMoveTo(vg, path->pts[0], path->pts[1]); | |||||
for (int i = 1; i < path->npts; i += 3) { | |||||
float *p = &path->pts[2*i]; | |||||
nvgBezierTo(vg, p[0], p[1], p[2], p[3], p[4], p[5]); | |||||
// nvgLineTo(vg, p[4], p[5]); | |||||
} | |||||
if (path->closed) | |||||
nvgClosePath(vg); | |||||
if (path->next) | |||||
nvgPathWinding(vg, NVG_HOLE); | |||||
} | |||||
// Fill shape | |||||
if (shape->fill.type) { | |||||
switch (shape->fill.type) { | |||||
case NSVG_PAINT_COLOR: { | |||||
NVGcolor color = getNVGColor(shape->fill.color); | |||||
nvgFillColor(vg, color); | |||||
// printf(" fill color (%f %f %f %f)\n", color.r, color.g, color.b, color.a); | |||||
} break; | |||||
case NSVG_PAINT_LINEAR_GRADIENT: { | |||||
NSVGgradient *g = shape->fill.gradient; | |||||
// printf(" lin grad: %f\t%f\n", g->fx, g->fy); | |||||
} break; | |||||
} | |||||
nvgFill(vg); | |||||
} | |||||
// Stroke shape | |||||
if (shape->stroke.type) { | |||||
switch (shape->stroke.type) { | |||||
case NSVG_PAINT_COLOR: { | |||||
NVGcolor color = getNVGColor(shape->stroke.color); | |||||
nvgFillColor(vg, color); | |||||
// printf(" stroke color (%f %f %f %f)\n", color.r, color.g, color.b, color.a); | |||||
} break; | |||||
case NSVG_PAINT_LINEAR_GRADIENT: { | |||||
NSVGgradient *g = shape->stroke.gradient; | |||||
// printf(" lin grad: %f\t%f\n", g->fx, g->fy); | |||||
} break; | |||||
} | |||||
nvgStroke(vg); | |||||
} | |||||
nvgRestore(vg); | |||||
} | |||||
} | |||||
} // namespace rack | } // namespace rack |
@@ -20,7 +20,7 @@ int main() { | |||||
assert(success); | assert(success); | ||||
CFRelease(bundleURL); | CFRelease(bundleURL); | ||||
chdir(dirname(path)); | |||||
// chdir(dirname(path)); | |||||
} | } | ||||
#endif | #endif | ||||
@@ -4,7 +4,7 @@ | |||||
namespace rack { | namespace rack { | ||||
std::string gApplicationName = "VCV Rack"; | std::string gApplicationName = "VCV Rack"; | ||||
std::string gApplicationVersion = "v0.1.0 alpha"; | |||||
std::string gApplicationVersion = "v0.2.0 alpha"; | |||||
RackWidget *gRackWidget = NULL; | RackWidget *gRackWidget = NULL; | ||||
@@ -7,10 +7,6 @@ namespace rack { | |||||
#define KNOB_SENSITIVITY 0.001 | #define KNOB_SENSITIVITY 0.001 | ||||
void Knob::step() { | |||||
index = eucmod((int) roundf(mapf(value, minValue, maxValue, minIndex, maxIndex)), spriteCount); | |||||
} | |||||
void Knob::onDragStart() { | void Knob::onDragStart() { | ||||
guiCursorLock(); | guiCursorLock(); | ||||
} | } | ||||
@@ -3,10 +3,9 @@ | |||||
namespace rack { | namespace rack { | ||||
void ModulePanel::draw(NVGcontext *vg) { | |||||
void Panel::draw(NVGcontext *vg) { | |||||
nvgBeginPath(vg); | nvgBeginPath(vg); | ||||
nvgRect(vg, box.pos.x, box.pos.y, box.size.x, box.size.y); | nvgRect(vg, box.pos.x, box.pos.y, box.size.x, box.size.y); | ||||
NVGpaint paint; | |||||
// Background color | // Background color | ||||
nvgFillColor(vg, backgroundColor); | nvgFillColor(vg, backgroundColor); | ||||
@@ -16,10 +15,15 @@ void ModulePanel::draw(NVGcontext *vg) { | |||||
if (backgroundImage) { | if (backgroundImage) { | ||||
int width, height; | int width, height; | ||||
nvgImageSize(vg, backgroundImage->handle, &width, &height); | nvgImageSize(vg, backgroundImage->handle, &width, &height); | ||||
paint = nvgImagePattern(vg, box.pos.x, box.pos.y, width, height, 0.0, backgroundImage->handle, 1.0); | |||||
NVGpaint paint = nvgImagePattern(vg, box.pos.x, box.pos.y, width, height, 0.0, backgroundImage->handle, 1.0); | |||||
nvgFillPaint(vg, paint); | nvgFillPaint(vg, paint); | ||||
nvgFill(vg); | nvgFill(vg); | ||||
} | } | ||||
// Border color | |||||
nvgStrokeColor(vg, borderColor); | |||||
nvgStrokeWidth(vg, 0.5); | |||||
nvgStroke(vg); | |||||
} | } | ||||
} // namespace rack | } // namespace rack |
@@ -1,4 +1,5 @@ | |||||
#include "scene.hpp" | #include "scene.hpp" | ||||
#include "gui.hpp" | |||||
namespace rack { | namespace rack { | ||||
@@ -24,5 +25,23 @@ void RackScene::step() { | |||||
Scene::step(); | Scene::step(); | ||||
} | } | ||||
void RackScene::draw(NVGcontext *vg) { | |||||
Scene::draw(vg); | |||||
// // Draw custom stuff here | |||||
// static std::shared_ptr<SVG> svg; | |||||
// if (!svg) | |||||
// svg = SVG::load("res/ComponentLibrary/CL1362.svg"); | |||||
// for (float y = 0.0; y < 1000.0; y += 200.0) | |||||
// for (float x = 0.0; x < 1000.0; x += 200.0) { | |||||
// nvgSave(vg); | |||||
// nvgTranslate(vg, x, y); | |||||
// drawSVG(vg, svg->handle); | |||||
// nvgRestore(vg); | |||||
// } | |||||
} | |||||
} // namespace rack | } // namespace rack |
@@ -288,23 +288,18 @@ void RackWidget::step() { | |||||
} | } | ||||
void RackWidget::draw(NVGcontext *vg) { | void RackWidget::draw(NVGcontext *vg) { | ||||
// Draw background | |||||
nvgBeginPath(vg); | nvgBeginPath(vg); | ||||
nvgRect(vg, box.pos.x, box.pos.y, box.size.x, box.size.y); | nvgRect(vg, box.pos.x, box.pos.y, box.size.x, box.size.y); | ||||
NVGpaint paint; | |||||
{ | |||||
// int imageId = loadImage("res/background.png"); | |||||
// int imageWidth, imageHeight; | |||||
// nvgImageSize(vg, imageId, &imageWidth, &imageHeight); | |||||
// paint = nvgImagePattern(vg, box.pos.x, box.pos.y, imageWidth, imageHeight, 0.0, imageId, 1.0); | |||||
// nvgFillPaint(vg, paint); | |||||
nvgFillColor(vg, nvgRGBf(0.25, 0.25, 0.25)); | |||||
nvgFill(vg); | |||||
} | |||||
// Background color | |||||
nvgFillColor(vg, nvgRGBf(0.2, 0.2, 0.2)); | |||||
nvgFill(vg); | |||||
// Rails image | |||||
{ | { | ||||
int imageWidth, imageHeight; | int imageWidth, imageHeight; | ||||
nvgImageSize(vg, railsImage->handle, &imageWidth, &imageHeight); | nvgImageSize(vg, railsImage->handle, &imageWidth, &imageHeight); | ||||
paint = nvgImagePattern(vg, box.pos.x, box.pos.y, imageWidth, imageHeight, 0.0, railsImage->handle, 1.0); | |||||
NVGpaint paint = nvgImagePattern(vg, box.pos.x, box.pos.y, imageWidth, imageHeight, 0.0, railsImage->handle, 1.0); | |||||
nvgFillPaint(vg, paint); | nvgFillPaint(vg, paint); | ||||
nvgFill(vg); | nvgFill(vg); | ||||
} | } | ||||
@@ -4,12 +4,12 @@ | |||||
namespace rack { | namespace rack { | ||||
Screw::Screw() { | Screw::Screw() { | ||||
box.size = Vec(15, 15); | |||||
spriteOffset = Vec(-7, -7); | |||||
spriteSize = Vec(29, 29); | |||||
spriteImage = Image::load("res/screw.png"); | |||||
// box.size = Vec(15, 15); | |||||
// spriteOffset = Vec(-7, -7); | |||||
// spriteSize = Vec(29, 29); | |||||
// spriteImage = Image::load("res/screw.png"); | |||||
index = randomu32() % 5; | |||||
// index = randomu32() % 5; | |||||
} | } | ||||
@@ -0,0 +1,10 @@ | |||||
#include "scene.hpp" | |||||
namespace rack { | |||||
void SpriteKnob::step() { | |||||
index = eucmod((int) roundf(mapf(value, minValue, maxValue, minIndex, maxIndex)), spriteCount); | |||||
} | |||||
} // namespace rack |
@@ -4,10 +4,28 @@ | |||||
namespace rack { | namespace rack { | ||||
void drawWire(NVGcontext *vg, Vec pos1, Vec pos2, float tension, NVGcolor color, float opacity) { | |||||
NVGcolor colorShadow = nvgRGBAf(0, 0, 0, 0.08); | |||||
static void drawPlug(NVGcontext *vg, Vec pos, NVGcolor color) { | |||||
NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5); | NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5); | ||||
nvgBeginPath(vg); | |||||
nvgCircle(vg, pos.x, pos.y, 10.5); | |||||
nvgFillColor(vg, colorOutline); | |||||
nvgFill(vg); | |||||
nvgBeginPath(vg); | |||||
nvgCircle(vg, pos.x, pos.y, 9.5); | |||||
nvgFillColor(vg, color); | |||||
nvgFill(vg); | |||||
nvgBeginPath(vg); | |||||
nvgCircle(vg, pos.x, pos.y, 5.5); | |||||
nvgFillColor(vg, nvgRGBf(0.0, 0.0, 0.0)); | |||||
nvgFill(vg); | |||||
} | |||||
static void drawWire(NVGcontext *vg, Vec pos1, Vec pos2, NVGcolor color, float tension, float opacity) { | |||||
NVGcolor colorShadow = nvgRGBAf(0, 0, 0, 0.08); | |||||
NVGcolor colorOutline = nvgLerpRGBA(color, nvgRGBf(0.0, 0.0, 0.0), 0.5); | |||||
// Wire | // Wire | ||||
if (opacity > 0.0) { | if (opacity > 0.0) { | ||||
@@ -35,68 +53,36 @@ void drawWire(NVGcontext *vg, Vec pos1, Vec pos2, float tension, NVGcolor color, | |||||
nvgMoveTo(vg, pos1.x, pos1.y); | nvgMoveTo(vg, pos1.x, pos1.y); | ||||
nvgQuadTo(vg, pos3.x, pos3.y, pos2.x, pos2.y); | nvgQuadTo(vg, pos3.x, pos3.y, pos2.x, pos2.y); | ||||
nvgStrokeColor(vg, colorOutline); | nvgStrokeColor(vg, colorOutline); | ||||
nvgStrokeWidth(vg, 6); | |||||
nvgStrokeWidth(vg, 5); | |||||
nvgStroke(vg); | nvgStroke(vg); | ||||
// Wire solid | // Wire solid | ||||
nvgStrokeColor(vg, color); | nvgStrokeColor(vg, color); | ||||
nvgStrokeWidth(vg, 4); | |||||
nvgStrokeWidth(vg, 3); | |||||
nvgStroke(vg); | nvgStroke(vg); | ||||
nvgRestore(vg); | nvgRestore(vg); | ||||
} | } | ||||
// First plug | |||||
nvgBeginPath(vg); | |||||
nvgCircle(vg, pos1.x, pos1.y, 21/2.0); | |||||
nvgFillColor(vg, colorOutline); | |||||
nvgFill(vg); | |||||
nvgBeginPath(vg); | |||||
nvgCircle(vg, pos1.x, pos1.y, 19/2.0); | |||||
nvgFillColor(vg, color); | |||||
nvgFill(vg); | |||||
nvgBeginPath(vg); | |||||
nvgCircle(vg, pos1.x, pos1.y, 11/2.0); | |||||
nvgFillColor(vg, nvgRGBf(0.0, 0.0, 0.0)); | |||||
nvgFill(vg); | |||||
// Second plug | |||||
nvgBeginPath(vg); | |||||
nvgCircle(vg, pos2.x, pos2.y, 21/2.0); | |||||
nvgFillColor(vg, colorOutline); | |||||
nvgFill(vg); | |||||
nvgBeginPath(vg); | |||||
nvgCircle(vg, pos2.x, pos2.y, 19/2.0); | |||||
nvgFillColor(vg, color); | |||||
nvgFill(vg); | |||||
nvgBeginPath(vg); | |||||
nvgCircle(vg, pos2.x, pos2.y, 11/2.0); | |||||
nvgFillColor(vg, nvgRGBf(0.0, 0.0, 0.0)); | |||||
nvgFill(vg); | |||||
} | } | ||||
static NVGcolor wireColors[8] = { | static NVGcolor wireColors[8] = { | ||||
nvgRGB(0x50, 0x50, 0x50), | |||||
nvgRGB(0xac, 0x41, 0x42), | |||||
nvgRGB(0x90, 0xa9, 0x59), | |||||
nvgRGB(0xf4, 0xbf, 0x75), | |||||
nvgRGB(0x6a, 0x9f, 0xb5), | |||||
nvgRGB(0xaa, 0x75, 0x9f), | |||||
nvgRGB(0x75, 0xb5, 0xaa), | |||||
nvgRGB(0xf5, 0xf5, 0xf5), | |||||
nvgRGB(0xc9, 0xb7, 0x0e), // yellow | |||||
nvgRGB(0xc9, 0x18, 0x47), // red | |||||
nvgRGB(0x0c, 0x8e, 0x15), // green | |||||
nvgRGB(0x09, 0x86, 0xad), // blue | |||||
nvgRGB(0x44, 0x44, 0x44), // black | |||||
nvgRGB(0x66, 0x66, 0x66), // gray | |||||
nvgRGB(0x88, 0x88, 0x88), // light gray | |||||
nvgRGB(0xaa, 0xaa, 0xaa), // white | |||||
}; | }; | ||||
static int wireColorId = 1; | |||||
static int nextWireColorId = 1; | |||||
WireWidget::WireWidget() { | WireWidget::WireWidget() { | ||||
wireColorId = (wireColorId + 1) % 8; | |||||
color = wireColors[wireColorId]; | |||||
color = wireColors[nextWireColorId]; | |||||
nextWireColorId = (nextWireColorId + 1) % 8; | |||||
} | } | ||||
WireWidget::~WireWidget() { | WireWidget::~WireWidget() { | ||||
@@ -152,8 +138,11 @@ void WireWidget::draw(NVGcontext *vg) { | |||||
outputPos = outputPos.minus(absolutePos); | outputPos = outputPos.minus(absolutePos); | ||||
inputPos = inputPos.minus(absolutePos); | inputPos = inputPos.minus(absolutePos); | ||||
drawWire(vg, outputPos, inputPos, tension, color, opacity); | |||||
drawWire(vg, outputPos, inputPos, color, tension, opacity); | |||||
drawPlug(vg, outputPos, color); | |||||
drawPlug(vg, inputPos, color); | |||||
} | } | ||||
} // namespace rack | } // namespace rack |