| @@ -17,6 +17,7 @@ namespace rack { | |||||
| extern GLFWwindow *gWindow; | extern GLFWwindow *gWindow; | ||||
| extern NVGcontext *gVg; | extern NVGcontext *gVg; | ||||
| extern NVGcontext *gFramebufferVg; | |||||
| extern std::shared_ptr<Font> gGuiFont; | extern std::shared_ptr<Font> gGuiFont; | ||||
| extern float gPixelRatio; | extern float gPixelRatio; | ||||
| extern bool gAllowCursorLock; | extern bool gAllowCursorLock; | ||||
| @@ -228,7 +228,6 @@ struct FramebufferWidget : virtual Widget { | |||||
| FramebufferWidget(); | FramebufferWidget(); | ||||
| ~FramebufferWidget(); | ~FramebufferWidget(); | ||||
| void step() override; | |||||
| void draw(NVGcontext *vg) override; | void draw(NVGcontext *vg) override; | ||||
| int getImageHandle(); | int getImageHandle(); | ||||
| }; | }; | ||||
| @@ -31,7 +31,7 @@ RackScene::RackScene() { | |||||
| scrollWidget = new RackScrollWidget(); | scrollWidget = new RackScrollWidget(); | ||||
| { | { | ||||
| zoomWidget = new ZoomWidget(); | zoomWidget = new ZoomWidget(); | ||||
| zoomWidget->zoom = 1.0; | |||||
| zoomWidget->zoom = 0.5; | |||||
| { | { | ||||
| assert(!gRackWidget); | assert(!gRackWidget); | ||||
| gRackWidget = new RackWidget(); | gRackWidget = new RackWidget(); | ||||
| @@ -404,6 +404,9 @@ struct AddManufacturerMenuItem : MenuItem { | |||||
| for (Model *model : models) { | for (Model *model : models) { | ||||
| AddModuleMenuItem *item = new AddModuleMenuItem(); | AddModuleMenuItem *item = new AddModuleMenuItem(); | ||||
| item->text = model->name; | item->text = model->name; | ||||
| // item->rightText = model->plugin->slug; | |||||
| // if (!model->plugin->version.empty()) | |||||
| // item->rightText += " v" + model->plugin->version; | |||||
| item->model = model; | item->model = model; | ||||
| item->modulePos = modulePos; | item->modulePos = modulePos; | ||||
| menu->pushChild(item); | menu->pushChild(item); | ||||
| @@ -29,6 +29,7 @@ namespace rack { | |||||
| GLFWwindow *gWindow = NULL; | GLFWwindow *gWindow = NULL; | ||||
| NVGcontext *gVg = NULL; | NVGcontext *gVg = NULL; | ||||
| NVGcontext *gFramebufferVg = NULL; | |||||
| std::shared_ptr<Font> gGuiFont; | std::shared_ptr<Font> gGuiFont; | ||||
| float gPixelRatio = 0.0; | float gPixelRatio = 0.0; | ||||
| bool gAllowCursorLock = true; | bool gAllowCursorLock = true; | ||||
| @@ -220,15 +221,15 @@ void renderGui() { | |||||
| gPixelRatio = (float)width / windowWidth; | gPixelRatio = (float)width / windowWidth; | ||||
| // Update and render | // Update and render | ||||
| glViewport(0, 0, width, height); | |||||
| glClearColor(0.0, 0.0, 0.0, 1.0); | |||||
| glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | |||||
| nvgBeginFrame(gVg, width, height, gPixelRatio); | nvgBeginFrame(gVg, width, height, gPixelRatio); | ||||
| nvgReset(gVg); | nvgReset(gVg); | ||||
| nvgScale(gVg, gPixelRatio, gPixelRatio); | nvgScale(gVg, gPixelRatio, gPixelRatio); | ||||
| gScene->draw(gVg); | gScene->draw(gVg); | ||||
| glViewport(0, 0, width, height); | |||||
| glClearColor(0.0, 0.0, 0.0, 1.0); | |||||
| glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | |||||
| nvgEndFrame(gVg); | nvgEndFrame(gVg); | ||||
| glfwSwapBuffers(gWindow); | glfwSwapBuffers(gWindow); | ||||
| } | } | ||||
| @@ -288,6 +289,9 @@ void guiInit() { | |||||
| // gVg = nvgCreateGL3(NVG_ANTIALIAS); | // gVg = nvgCreateGL3(NVG_ANTIALIAS); | ||||
| assert(gVg); | assert(gVg); | ||||
| gFramebufferVg = nvgCreateGL2(NVG_ANTIALIAS); | |||||
| assert(gFramebufferVg); | |||||
| // Set up Blendish | // Set up Blendish | ||||
| gGuiFont = Font::load(assetGlobal("res/DejaVuSans.ttf")); | gGuiFont = Font::load(assetGlobal("res/DejaVuSans.ttf")); | ||||
| bndSetFont(gGuiFont->handle); | bndSetFont(gGuiFont->handle); | ||||
| @@ -298,6 +302,7 @@ void guiDestroy() { | |||||
| gGuiFont.reset(); | gGuiFont.reset(); | ||||
| nvgDeleteGL2(gVg); | nvgDeleteGL2(gVg); | ||||
| // nvgDeleteGL3(gVg); | // nvgDeleteGL3(gVg); | ||||
| nvgDeleteGL2(gFramebufferVg); | |||||
| glfwDestroyWindow(gWindow); | glfwDestroyWindow(gWindow); | ||||
| glfwTerminate(); | glfwTerminate(); | ||||
| } | } | ||||
| @@ -32,11 +32,7 @@ FramebufferWidget::~FramebufferWidget() { | |||||
| delete internal; | delete internal; | ||||
| } | } | ||||
| void FramebufferWidget::step() { | |||||
| // Step children before rendering | |||||
| Widget::step(); | |||||
| // Render the scene to the framebuffer if dirty | |||||
| void FramebufferWidget::draw(NVGcontext *vg) { | |||||
| if (dirty) { | if (dirty) { | ||||
| internal->box.pos = Vec(0, 0); | internal->box.pos = Vec(0, 0); | ||||
| internal->box.size = box.size; | internal->box.size = box.size; | ||||
| @@ -50,6 +46,7 @@ void FramebufferWidget::step() { | |||||
| // Delete old one first to free up GPU memory | // Delete old one first to free up GPU memory | ||||
| internal->setFramebuffer(NULL); | internal->setFramebuffer(NULL); | ||||
| // Create a framebuffer from the main nanovg context. We will draw to this in the secondary nanovg context. | |||||
| NVGLUframebuffer *fb = nvgluCreateFramebuffer(gVg, fbSize.x, fbSize.y, NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY); | NVGLUframebuffer *fb = nvgluCreateFramebuffer(gVg, fbSize.x, fbSize.y, NVG_IMAGE_REPEATX | NVG_IMAGE_REPEATY); | ||||
| if (!fb) | if (!fb) | ||||
| return; | return; | ||||
| @@ -59,36 +56,19 @@ void FramebufferWidget::step() { | |||||
| glViewport(0.0, 0.0, fbSize.x, fbSize.y); | glViewport(0.0, 0.0, fbSize.x, fbSize.y); | ||||
| glClearColor(0.0, 0.0, 0.0, 0.0); | glClearColor(0.0, 0.0, 0.0, 0.0); | ||||
| glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); | ||||
| nvgBeginFrame(gVg, fbSize.x, fbSize.y, gPixelRatio * oversample); | |||||
| nvgScale(gVg, gPixelRatio * oversample, gPixelRatio * oversample); | |||||
| Widget::draw(gVg); | |||||
| nvgBeginFrame(gFramebufferVg, fbSize.x, fbSize.y, gPixelRatio * oversample); | |||||
| nvgEndFrame(gVg); | |||||
| nvgScale(gFramebufferVg, gPixelRatio * oversample, gPixelRatio * oversample); | |||||
| Widget::draw(gFramebufferVg); | |||||
| nvgEndFrame(gFramebufferVg); | |||||
| nvgluBindFramebuffer(NULL); | nvgluBindFramebuffer(NULL); | ||||
| dirty = false; | dirty = false; | ||||
| } | } | ||||
| } | |||||
| void FramebufferWidget::draw(NVGcontext *vg) { | |||||
| // { | |||||
| // float xform[6]; | |||||
| // nvgCurrentTransform(vg, xform); | |||||
| // printf("%f %f %f %f %f %f\n", xform[0], xform[1], xform[2], xform[3], xform[4], xform[5]); | |||||
| // nvgSave(vg); | |||||
| // nvgResetTransform(vg); | |||||
| // nvgTranslate(vg, xform[5], xform[6]); | |||||
| // nvgBeginPath(vg); | |||||
| // nvgRect(vg, 0, 0, 50, 50); | |||||
| // nvgFillColor(vg, nvgRGBf(1.0, 0.0, 0.0)); | |||||
| // nvgFill(vg); | |||||
| // nvgRestore(vg); | |||||
| // } | |||||
| if (!internal->fb) { | if (!internal->fb) { | ||||
| // Bypass framebuffer cache entirely | |||||
| // Widget::draw(vg); | |||||
| return; | return; | ||||
| } | } | ||||
| @@ -102,6 +82,22 @@ void FramebufferWidget::draw(NVGcontext *vg) { | |||||
| // For debugging bounding box of framebuffer image | // For debugging bounding box of framebuffer image | ||||
| // nvgFillColor(vg, nvgRGBA(255, 0, 0, 64)); | // nvgFillColor(vg, nvgRGBA(255, 0, 0, 64)); | ||||
| // nvgFill(vg); | // nvgFill(vg); | ||||
| { | |||||
| float xform[6]; | |||||
| nvgCurrentTransform(vg, xform); | |||||
| // printf("%f %f %f %f; %f %f\n", xform[0], xform[1], xform[2], xform[3], xform[4], xform[5]); | |||||
| nvgSave(vg); | |||||
| nvgResetTransform(vg); | |||||
| nvgTranslate(vg, xform[4], xform[5]); | |||||
| nvgScale(vg, xform[0], xform[3]); | |||||
| nvgBeginPath(vg); | |||||
| nvgRect(vg, 0, 0, internal->box.size.x, internal->box.size.y); | |||||
| nvgStrokeWidth(vg, 2.0); | |||||
| nvgStrokeColor(vg, nvgRGBf(1.0, 0.0, 0.0)); | |||||
| nvgStroke(vg); | |||||
| nvgRestore(vg); | |||||
| } | |||||
| } | } | ||||
| int FramebufferWidget::getImageHandle() { | int FramebufferWidget::getImageHandle() { | ||||