Browse Source

Add -p for creating screenshots of every module.

tags/v1.0.0
Andrew Belt 5 years ago
parent
commit
e9ac9eb677
6 changed files with 82 additions and 12 deletions
  1. +1
    -1
      dep/Makefile
  2. +3
    -0
      helper.py
  3. +2
    -0
      include/window.hpp
  4. +3
    -0
      src/dep.cpp
  5. +13
    -6
      src/main.cpp
  6. +60
    -5
      src/window.cpp

+ 1
- 1
dep/Makefile View File

@@ -160,7 +160,7 @@ $(rtaudio):
$(MAKE) -C rtaudio/build $(MAKE) -C rtaudio/build
$(MAKE) -C rtaudio/build install $(MAKE) -C rtaudio/build install


$(nanovg): $(wildcard nanovg/src/*.h)
$(nanovg): $(wildcard nanovg/src/*.h) nanovg/example/stb_image_write.h
cp $^ include/ cp $^ include/


$(nanosvg): $(wildcard nanosvg/src/*.h) $(nanosvg): $(wildcard nanosvg/src/*.h)


+ 3
- 0
helper.py View File

@@ -134,6 +134,9 @@ Plugin *pluginInstance;
void init(Plugin *p) { void init(Plugin *p) {
pluginInstance = p; pluginInstance = p;


// Add modules here, e.g.
// p->addModel(modelMyModule);

// Any other plugin initialization may go here. // Any other plugin initialization may go here.
// As an alternative, consider lazy-loading assets and lookup tables when your module is created to reduce startup times of Rack. // As an alternative, consider lazy-loading assets and lookup tables when your module is created to reduce startup times of Rack.
} }


+ 2
- 0
include/window.hpp View File

@@ -98,6 +98,8 @@ struct Window {
Window(); Window();
~Window(); ~Window();
void run(); void run();
/** Takes a screenshot of each module */
void screenshot();
void close(); void close();
void cursorLock(); void cursorLock();
void cursorUnlock(); void cursorUnlock();


+ 3
- 0
src/dep.cpp View File

@@ -21,3 +21,6 @@
#define NANOSVG_IMPLEMENTATION #define NANOSVG_IMPLEMENTATION
#define NANOSVG_ALL_COLOR_KEYWORDS #define NANOSVG_ALL_COLOR_KEYWORDS
#include <nanosvg.h> #include <nanosvg.h>

#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h>

+ 13
- 6
src/main.cpp View File

@@ -57,11 +57,12 @@ int main(int argc, char *argv[]) {
#endif #endif


std::string patchPath; std::string patchPath;
bool screenshot = false;


// Parse command line arguments // Parse command line arguments
int c; int c;
opterr = 0; opterr = 0;
while ((c = getopt(argc, argv, "ds:u:")) != -1) {
while ((c = getopt(argc, argv, "dhps:u:")) != -1) {
switch (c) { switch (c) {
case 'd': { case 'd': {
settings::devMode = true; settings::devMode = true;
@@ -69,6 +70,9 @@ int main(int argc, char *argv[]) {
case 'h': { case 'h': {
settings::headless = true; settings::headless = true;
} break; } break;
case 'p': {
screenshot = true;
} break;
case 's': { case 's': {
asset::systemDir = optarg; asset::systemDir = optarg;
} break; } break;
@@ -154,15 +158,18 @@ int main(int argc, char *argv[]) {
INFO("Starting engine"); INFO("Starting engine");
APP->engine->start(); APP->engine->start();


if (!settings::headless) {
if (settings::headless) {
// TEMP Prove that the app doesn't crash
std::this_thread::sleep_for(std::chrono::seconds(2));
}
else if (screenshot) {
APP->window->screenshot();
}
else {
INFO("Running window"); INFO("Running window");
APP->window->run(); APP->window->run();
INFO("Stopped window"); INFO("Stopped window");
} }
else {
// TEMP Prove that the app doesn't crash
std::this_thread::sleep_for(std::chrono::seconds(2));
}
INFO("Stopping engine"); INFO("Stopping engine");
APP->engine->stop(); APP->engine->stop();




+ 60
- 5
src/window.cpp View File

@@ -7,17 +7,20 @@
#include "app.hpp" #include "app.hpp"
#include "patch.hpp" #include "patch.hpp"
#include "settings.hpp" #include "settings.hpp"
#include "plugin.hpp" // used in Window::screenshot
#include "system.hpp" // used in Window::screenshot


#include <map> #include <map>
#include <queue> #include <queue>
#include <thread> #include <thread>


#if defined ARCH_MAC #if defined ARCH_MAC
// For CGAssociateMouseAndMouseCursorPosition
#include <ApplicationServices/ApplicationServices.h>
// For CGAssociateMouseAndMouseCursorPosition
#include <ApplicationServices/ApplicationServices.h>
#endif #endif


#include <osdialog.h> #include <osdialog.h>
#include <stb_image_write.h>




namespace rack { namespace rack {
@@ -271,6 +274,9 @@ Window::Window() {
osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, "Could not initialize NanoVG. Does your graphics card support OpenGL 2.0 or greater? If so, make sure you have the latest graphics drivers installed."); osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, "Could not initialize NanoVG. Does your graphics card support OpenGL 2.0 or greater? If so, make sure you have the latest graphics drivers installed.");
exit(1); exit(1);
} }

// Load default Blendish font
uiFont = loadFont(asset::system("res/fonts/DejaVuSans.ttf"));
} }


Window::~Window() { Window::~Window() {
@@ -300,10 +306,8 @@ Window::~Window() {
} }


void Window::run() { void Window::run() {
uiFont = APP->window->loadFont(asset::system("res/fonts/DejaVuSans.ttf"));

frame = 0; frame = 0;
while(!glfwWindowShouldClose(win)) {
while (!glfwWindowShouldClose(win)) {
frameTimeStart = glfwGetTime(); frameTimeStart = glfwGetTime();


// Make event handlers and step() have a clean nanovg context // Make event handlers and step() have a clean nanovg context
@@ -399,6 +403,57 @@ void Window::run() {
} }
} }


void Window::screenshot() {
// Iterate plugins and create directories
std::string screenshotsDir = asset::user("screenshots");
system::createDirectory(screenshotsDir);
for (plugin::Plugin *p : plugin::plugins) {
std::string dir = screenshotsDir + "/" + p->slug;
system::createDirectory(dir);
for (plugin::Model *model : p->models) {
std::string filename = dir + "/" + model->slug + ".png";
// Skip model if screenshot already exists
if (system::isFile(filename))
continue;
INFO("Screenshotting %s %s to %s", p->slug.c_str(), model->slug.c_str(), filename.c_str());

// Create widgets
app::ModuleWidget *mw = model->createModuleWidgetNull();
widget::FramebufferWidget *fb = new widget::FramebufferWidget;
fb->addChild(mw);
float zoom = 2.f;
fb->scale = math::Vec(zoom, zoom);

// Draw to framebuffer
frameTimeStart = glfwGetTime();
fb->step();
nvgluBindFramebuffer(fb->fb);

// Read pixels
int width, height;
nvgImageSize(vg, fb->getImageHandle(), &width, &height);
uint8_t data[height * width * 4];
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);

// Flip image vertically
for (int y = 0; y < height / 2; y++) {
int flipY = height - y - 1;
uint8_t tmp[width * 4];
memcpy(tmp, &data[y * width * 4], width * 4);
memcpy(&data[y * width * 4], &data[flipY * width * 4], width * 4);
memcpy(&data[flipY * width * 4], tmp, width * 4);
}

// Write pixels to PNG
stbi_write_png(filename.c_str(), width, height, 4, data, width * 4);

// Cleanup
nvgluBindFramebuffer(NULL);
delete fb;
}
}
}

void Window::close() { void Window::close() {
glfwSetWindowShouldClose(win, GLFW_TRUE); glfwSetWindowShouldClose(win, GLFW_TRUE);
} }


Loading…
Cancel
Save