Browse Source

Added Scene::createMenu(), renamed arch macros to ARCH_*

tags/v0.3.0
Andrew Belt 8 years ago
parent
commit
de5c9ca2af
12 changed files with 110 additions and 115 deletions
  1. +2
    -2
      Makefile
  2. +2
    -1
      Makefile-plugin.inc
  3. +3
    -4
      Makefile.inc
  4. +0
    -1
      include/app.hpp
  5. +1
    -0
      include/widgets.hpp
  6. +41
    -46
      src/app/ModuleWidget.cpp
  7. +2
    -2
      src/app/ParamWidget.cpp
  8. +0
    -1
      src/app/RackScene.cpp
  9. +22
    -28
      src/app/RackWidget.cpp
  10. +2
    -2
      src/main.cpp
  11. +23
    -28
      src/plugin.cpp
  12. +12
    -0
      src/widgets/Scene.cpp

+ 2
- 2
Makefile View File

@@ -1,7 +1,7 @@
ARCH ?= lin ARCH ?= lin
FLAGS = -g -Wall -O2 -msse -mfpmath=sse -ffast-math -fno-finite-math-only \
FLAGS += -g -Wall -O3 -march=core2 -ffast-math \
-I./ext -I./include -I./ext -I./include
CXXFLAGS = -fno-exceptions
CXXFLAGS += -std=c++11 -fno-exceptions


SOURCES = $(wildcard src/*.cpp src/*/*.cpp) \ SOURCES = $(wildcard src/*.cpp src/*/*.cpp) \
ext/nanovg/src/nanovg.c ext/nanovg/src/nanovg.c


+ 2
- 1
Makefile-plugin.inc View File

@@ -1,8 +1,9 @@
ARCH ?= lin ARCH ?= lin




FLAGS += -fPIC -g -Wall -O3 -msse -mfpmath=sse -ffast-math \
FLAGS += -fPIC -g -Wall -O3 -march=core2 -ffast-math \
-I../../include -I../../include
CXXFLAGS += -std=c++11 -fno-exceptions
LDFLAGS += LDFLAGS +=






+ 3
- 4
Makefile.inc View File

@@ -1,17 +1,16 @@
FLAGS += -MMD FLAGS += -MMD
CXXFLAGS += -std=c++11




ifeq ($(ARCH), lin) ifeq ($(ARCH), lin)
CC ?= gcc CC ?= gcc
CXX ?= g++ CXX ?= g++
FLAGS += -DLINUX
FLAGS += -DARCH_LIN
endif endif


ifeq ($(ARCH), mac) ifeq ($(ARCH), mac)
CC ?= clang CC ?= clang
CXX ?= clang++ CXX ?= clang++
FLAGS += -DAPPLE
FLAGS += -DARCH_MAC
CXXFLAGS += -stdlib=libc++ CXXFLAGS += -stdlib=libc++
LDFLAGS += -stdlib=libc++ LDFLAGS += -stdlib=libc++
endif endif
@@ -19,7 +18,7 @@ endif
ifeq ($(ARCH), win) ifeq ($(ARCH), win)
CC ?= x86_64-w64-mingw32-gcc CC ?= x86_64-w64-mingw32-gcc
CXX ?= x86_64-w64-mingw32-g++ CXX ?= x86_64-w64-mingw32-g++
FLAGS += -DWINDOWS -D_USE_MATH_DEFINES
FLAGS += -DARCH_WIN -D_USE_MATH_DEFINES
endif endif






+ 0
- 1
include/app.hpp View File

@@ -289,7 +289,6 @@ struct RackScene : Scene {
extern std::string gApplicationName; extern std::string gApplicationName;
extern std::string gApplicationVersion; extern std::string gApplicationVersion;


extern Scene *gScene;
extern RackWidget *gRackWidget; extern RackWidget *gRackWidget;


void sceneInit(); void sceneInit();


+ 1
- 0
include/widgets.hpp View File

@@ -387,6 +387,7 @@ struct Tooltip : Widget {
struct Scene : OpaqueWidget { struct Scene : OpaqueWidget {
Widget *overlay = NULL; Widget *overlay = NULL;
void setOverlay(Widget *w); void setOverlay(Widget *w);
Menu *createMenu();
void step(); void step();
}; };




+ 41
- 46
src/app/ModuleWidget.cpp View File

@@ -40,40 +40,40 @@ void ModuleWidget::addParam(ParamWidget *param) {
} }


json_t *ModuleWidget::toJson() { json_t *ModuleWidget::toJson() {
json_t *root = json_object();
json_t *rootJ = json_object();


// plugin // plugin
json_object_set_new(root, "plugin", json_string(model->plugin->slug.c_str()));
json_object_set_new(rootJ, "plugin", json_string(model->plugin->slug.c_str()));
// model // model
json_object_set_new(root, "model", json_string(model->slug.c_str()));
json_object_set_new(rootJ, "model", json_string(model->slug.c_str()));
// pos // pos
json_t *pos = json_pack("[f, f]", (double) box.pos.x, (double) box.pos.y); json_t *pos = json_pack("[f, f]", (double) box.pos.x, (double) box.pos.y);
json_object_set_new(root, "pos", pos);
json_object_set_new(rootJ, "pos", pos);
// params // params
json_t *paramsJ = json_array(); json_t *paramsJ = json_array();
for (ParamWidget *paramWidget : params) { for (ParamWidget *paramWidget : params) {
json_t *paramJ = paramWidget->toJson(); json_t *paramJ = paramWidget->toJson();
json_array_append_new(paramsJ, paramJ); json_array_append_new(paramsJ, paramJ);
} }
json_object_set_new(root, "params", paramsJ);
json_object_set_new(rootJ, "params", paramsJ);
// data // data
json_t *dataJ = module ? module->toJsonData() : NULL; json_t *dataJ = module ? module->toJsonData() : NULL;
if (dataJ) { if (dataJ) {
json_object_set_new(root, "data", dataJ);
json_object_set_new(rootJ, "data", dataJ);
} }


return root;
return rootJ;
} }


void ModuleWidget::fromJson(json_t *root) {
void ModuleWidget::fromJson(json_t *rootJ) {
// pos // pos
json_t *pos = json_object_get(root, "pos");
json_t *pos = json_object_get(rootJ, "pos");
double x, y; double x, y;
json_unpack(pos, "[F, F]", &x, &y); json_unpack(pos, "[F, F]", &x, &y);
box.pos = Vec(x, y); box.pos = Vec(x, y);


// params // params
json_t *paramsJ = json_object_get(root, "params");
json_t *paramsJ = json_object_get(rootJ, "params");
size_t paramId; size_t paramId;
json_t *paramJ; json_t *paramJ;
json_array_foreach(paramsJ, paramId, paramJ) { json_array_foreach(paramsJ, paramId, paramJ) {
@@ -83,7 +83,7 @@ void ModuleWidget::fromJson(json_t *root) {
} }


// data // data
json_t *dataJ = json_object_get(root, "data");
json_t *dataJ = json_object_get(rootJ, "data");
if (dataJ && module) { if (dataJ && module) {
module->fromJsonData(dataJ); module->fromJsonData(dataJ);
} }
@@ -197,41 +197,36 @@ struct DeleteModuleMenuItem : MenuItem {


void ModuleWidget::onMouseDown(int button) { void ModuleWidget::onMouseDown(int button) {
if (button == 1) { if (button == 1) {
MenuOverlay *overlay = new MenuOverlay();
Menu *menu = new Menu();
menu->box.pos = gMousePos;
{
MenuLabel *menuLabel = new MenuLabel();
menuLabel->text = model->plugin->name + ": " + model->name;
menu->pushChild(menuLabel);

ResetParamsMenuItem *resetItem = new ResetParamsMenuItem();
resetItem->text = "Initialize";
resetItem->moduleWidget = this;
menu->pushChild(resetItem);

RandomizeParamsMenuItem *randomizeParams = new RandomizeParamsMenuItem();
randomizeParams->text = "Randomize";
randomizeParams->moduleWidget = this;
menu->pushChild(randomizeParams);

DisconnectPortsMenuItem *disconnectItem = new DisconnectPortsMenuItem();
disconnectItem->text = "Disconnect cables";
disconnectItem->moduleWidget = this;
menu->pushChild(disconnectItem);

CloneModuleMenuItem *cloneItem = new CloneModuleMenuItem();
cloneItem->text = "Clone";
cloneItem->moduleWidget = this;
menu->pushChild(cloneItem);

DeleteModuleMenuItem *deleteItem = new DeleteModuleMenuItem();
deleteItem->text = "Delete";
deleteItem->moduleWidget = this;
menu->pushChild(deleteItem);
}
overlay->addChild(menu);
gScene->setOverlay(overlay);
Menu *menu = gScene->createMenu();

MenuLabel *menuLabel = new MenuLabel();
menuLabel->text = model->plugin->name + ": " + model->name;
menu->pushChild(menuLabel);

ResetParamsMenuItem *resetItem = new ResetParamsMenuItem();
resetItem->text = "Initialize";
resetItem->moduleWidget = this;
menu->pushChild(resetItem);

RandomizeParamsMenuItem *randomizeParams = new RandomizeParamsMenuItem();
randomizeParams->text = "Randomize";
randomizeParams->moduleWidget = this;
menu->pushChild(randomizeParams);

DisconnectPortsMenuItem *disconnectItem = new DisconnectPortsMenuItem();
disconnectItem->text = "Disconnect cables";
disconnectItem->moduleWidget = this;
menu->pushChild(disconnectItem);

CloneModuleMenuItem *cloneItem = new CloneModuleMenuItem();
cloneItem->text = "Clone";
cloneItem->moduleWidget = this;
menu->pushChild(cloneItem);

DeleteModuleMenuItem *deleteItem = new DeleteModuleMenuItem();
deleteItem->text = "Delete";
deleteItem->moduleWidget = this;
menu->pushChild(deleteItem);
} }
} }




+ 2
- 2
src/app/ParamWidget.cpp View File

@@ -9,8 +9,8 @@ json_t *ParamWidget::toJson() {
return paramJ; return paramJ;
} }


void ParamWidget::fromJson(json_t *root) {
setValue(json_number_value(root));
void ParamWidget::fromJson(json_t *rootJ) {
setValue(json_number_value(rootJ));
} }


void ParamWidget::onMouseDown(int button) { void ParamWidget::onMouseDown(int button) {


+ 0
- 1
src/app/RackScene.cpp View File

@@ -30,5 +30,4 @@ void RackScene::draw(NVGcontext *vg) {
} }





} // namespace rack } // namespace rack

+ 22
- 28
src/app/RackWidget.cpp View File

@@ -33,10 +33,10 @@ void RackWidget::savePatch(std::string filename) {
if (!file) if (!file)
return; return;


json_t *root = toJson();
if (root) {
json_dumpf(root, file, JSON_INDENT(2));
json_decref(root);
json_t *rootJ = toJson();
if (rootJ) {
json_dumpf(rootJ, file, JSON_INDENT(2));
json_decref(rootJ);
} }


fclose(file); fclose(file);
@@ -49,11 +49,11 @@ void RackWidget::loadPatch(std::string filename) {
return; return;


json_error_t error; json_error_t error;
json_t *root = json_loadf(file, 0, &error);
if (root) {
json_t *rootJ = json_loadf(file, 0, &error);
if (rootJ) {
clear(); clear();
fromJson(root);
json_decref(root);
fromJson(rootJ);
json_decref(rootJ);
} }
else { else {
printf("JSON parsing error at %s %d:%d %s\n", error.source, error.line, error.column, error.text); printf("JSON parsing error at %s %d:%d %s\n", error.source, error.line, error.column, error.text);
@@ -64,19 +64,19 @@ void RackWidget::loadPatch(std::string filename) {


json_t *RackWidget::toJson() { json_t *RackWidget::toJson() {
// root // root
json_t *root = json_object();
json_t *rootJ = json_object();


// version // version
json_t *versionJ = json_string(gApplicationVersion.c_str()); json_t *versionJ = json_string(gApplicationVersion.c_str());
json_object_set_new(root, "version", versionJ);
json_object_set_new(rootJ, "version", versionJ);


// wireOpacity // wireOpacity
json_t *wireOpacityJ = json_real(dynamic_cast<RackScene*>(gScene)->toolbar->wireOpacitySlider->value); json_t *wireOpacityJ = json_real(dynamic_cast<RackScene*>(gScene)->toolbar->wireOpacitySlider->value);
json_object_set_new(root, "wireOpacity", wireOpacityJ);
json_object_set_new(rootJ, "wireOpacity", wireOpacityJ);


// wireTension // wireTension
json_t *wireTensionJ = json_real(dynamic_cast<RackScene*>(gScene)->toolbar->wireTensionSlider->value); json_t *wireTensionJ = json_real(dynamic_cast<RackScene*>(gScene)->toolbar->wireTensionSlider->value);
json_object_set_new(root, "wireTension", wireTensionJ);
json_object_set_new(rootJ, "wireTension", wireTensionJ);


// modules // modules
json_t *modulesJ = json_array(); json_t *modulesJ = json_array();
@@ -91,7 +91,7 @@ json_t *RackWidget::toJson() {
json_t *moduleJ = moduleWidget->toJson(); json_t *moduleJ = moduleWidget->toJson();
json_array_append_new(modulesJ, moduleJ); json_array_append_new(modulesJ, moduleJ);
} }
json_object_set_new(root, "modules", modulesJ);
json_object_set_new(rootJ, "modules", modulesJ);


// wires // wires
json_t *wires = json_array(); json_t *wires = json_array();
@@ -129,14 +129,14 @@ json_t *RackWidget::toJson() {
} }
json_array_append_new(wires, wire); json_array_append_new(wires, wire);
} }
json_object_set_new(root, "wires", wires);
json_object_set_new(rootJ, "wires", wires);


return root;
return rootJ;
} }


void RackWidget::fromJson(json_t *root) {
void RackWidget::fromJson(json_t *rootJ) {
// version // version
json_t *versionJ = json_object_get(root, "version");
json_t *versionJ = json_object_get(rootJ, "version");
if (versionJ) { if (versionJ) {
const char *version = json_string_value(versionJ); const char *version = json_string_value(versionJ);
if (gApplicationVersion != version) if (gApplicationVersion != version)
@@ -144,18 +144,18 @@ void RackWidget::fromJson(json_t *root) {
} }


// wireOpacity // wireOpacity
json_t *wireOpacityJ = json_object_get(root, "wireOpacity");
json_t *wireOpacityJ = json_object_get(rootJ, "wireOpacity");
if (wireOpacityJ) if (wireOpacityJ)
dynamic_cast<RackScene*>(gScene)->toolbar->wireOpacitySlider->value = json_number_value(wireOpacityJ); dynamic_cast<RackScene*>(gScene)->toolbar->wireOpacitySlider->value = json_number_value(wireOpacityJ);


// wireTension // wireTension
json_t *wireTensionJ = json_object_get(root, "wireTension");
json_t *wireTensionJ = json_object_get(rootJ, "wireTension");
if (wireTensionJ) if (wireTensionJ)
dynamic_cast<RackScene*>(gScene)->toolbar->wireTensionSlider->value = json_number_value(wireTensionJ); dynamic_cast<RackScene*>(gScene)->toolbar->wireTensionSlider->value = json_number_value(wireTensionJ);


// modules // modules
std::map<int, ModuleWidget*> moduleWidgets; std::map<int, ModuleWidget*> moduleWidgets;
json_t *modulesJ = json_object_get(root, "modules");
json_t *modulesJ = json_object_get(rootJ, "modules");
if (!modulesJ) return; if (!modulesJ) return;
size_t moduleId; size_t moduleId;
json_t *moduleJ; json_t *moduleJ;
@@ -193,7 +193,7 @@ void RackWidget::fromJson(json_t *root) {
} }


// wires // wires
json_t *wiresJ = json_object_get(root, "wires");
json_t *wiresJ = json_object_get(rootJ, "wires");
if (!wiresJ) return; if (!wiresJ) return;
size_t wireId; size_t wireId;
json_t *wireJ; json_t *wireJ;
@@ -320,12 +320,8 @@ struct AddModuleMenuItem : MenuItem {


void RackWidget::onMouseDown(int button) { void RackWidget::onMouseDown(int button) {
if (button == 1) { if (button == 1) {
// Get relative position of the click
Vec modulePos = gMousePos.minus(getAbsolutePos()); Vec modulePos = gMousePos.minus(getAbsolutePos());

MenuOverlay *overlay = new MenuOverlay();
Menu *menu = new Menu();
menu->box.pos = gMousePos;
Menu *menu = gScene->createMenu();


MenuLabel *menuLabel = new MenuLabel(); MenuLabel *menuLabel = new MenuLabel();
menuLabel->text = "Add Module"; menuLabel->text = "Add Module";
@@ -339,8 +335,6 @@ void RackWidget::onMouseDown(int button) {
menu->pushChild(item); menu->pushChild(item);
} }
} }
overlay->addChild(menu);
gScene->setOverlay(overlay);
} }
} }




+ 2
- 2
src/main.cpp View File

@@ -4,7 +4,7 @@
#include "plugin.hpp" #include "plugin.hpp"




#if defined(APPLE)
#if ARCH_MAC
#include <CoreFoundation/CoreFoundation.h> #include <CoreFoundation/CoreFoundation.h>
#include <unistd.h> // for chdir and access #include <unistd.h> // for chdir and access
#include <libgen.h> // for dirname #include <libgen.h> // for dirname
@@ -81,7 +81,7 @@ void fixCwd() {
using namespace rack; using namespace rack;


int main() { int main() {
#if defined(APPLE)
#if ARCH_MAC
fixCwd(); fixCwd();
#endif #endif




+ 23
- 28
src/plugin.cpp View File

@@ -12,7 +12,7 @@
#include <zip.h> #include <zip.h>
#include <jansson.h> #include <jansson.h>


#if defined(WINDOWS)
#if ARCH_WIN
#include <windows.h> #include <windows.h>
#include <shellapi.h> #include <shellapi.h>
#include <direct.h> #include <direct.h>
@@ -43,22 +43,22 @@ Plugin::~Plugin() {




static int loadPlugin(std::string slug) { static int loadPlugin(std::string slug) {
#if defined(LINUX)
#if ARCH_LIN
std::string path = "./plugins/" + slug + "/plugin.so"; std::string path = "./plugins/" + slug + "/plugin.so";
#elif defined(WINDOWS)
#elif ARCH_WIN
std::string path = "./plugins/" + slug + "/plugin.dll"; std::string path = "./plugins/" + slug + "/plugin.dll";
#elif defined(APPLE)
#elif ARCH_MAC
std::string path = "./plugins/" + slug + "/plugin.dylib"; std::string path = "./plugins/" + slug + "/plugin.dylib";
#endif #endif


// Load dynamic/shared library // Load dynamic/shared library
#if defined(WINDOWS)
#if ARCH_WIN
HINSTANCE handle = LoadLibrary(path.c_str()); HINSTANCE handle = LoadLibrary(path.c_str());
if (!handle) { if (!handle) {
fprintf(stderr, "Failed to load library %s\n", path.c_str()); fprintf(stderr, "Failed to load library %s\n", path.c_str());
return -1; return -1;
} }
#elif defined(LINUX) || defined(APPLE)
#elif ARCH_LIN || ARCH_MAC
void *handle = dlopen(path.c_str(), RTLD_NOW | RTLD_GLOBAL); void *handle = dlopen(path.c_str(), RTLD_NOW | RTLD_GLOBAL);
if (!handle) { if (!handle) {
fprintf(stderr, "Failed to load library %s: %s\n", path.c_str(), dlerror()); fprintf(stderr, "Failed to load library %s: %s\n", path.c_str(), dlerror());
@@ -69,9 +69,9 @@ static int loadPlugin(std::string slug) {
// Call plugin init() function // Call plugin init() function
typedef Plugin *(*InitCallback)(); typedef Plugin *(*InitCallback)();
InitCallback initCallback; InitCallback initCallback;
#if defined(WINDOWS)
#if ARCH_WIN
initCallback = (InitCallback) GetProcAddress(handle, "init"); initCallback = (InitCallback) GetProcAddress(handle, "init");
#elif defined(LINUX) || defined(APPLE)
#elif ARCH_LIN || ARCH_MAC
initCallback = (InitCallback) dlsym(handle, "init"); initCallback = (InitCallback) dlsym(handle, "init");
#endif #endif
if (!initCallback) { if (!initCallback) {
@@ -173,10 +173,8 @@ static void extract_zip(const char *dir, int zipfd) {
if (err) goto cleanup; if (err) goto cleanup;
int nameLen = strlen(zs.name); int nameLen = strlen(zs.name);


char path[MAXPATHLEN] = "\0";
strncat(path, dir, MAXPATHLEN);
strncat(path, "/", MAXPATHLEN);
strncat(path, zs.name, MAXPATHLEN);
char path[MAXPATHLEN];
snprintf(path, sizeof(path), "%s/%s", dir, zs.name);


if (zs.name[nameLen - 1] == '/') { if (zs.name[nameLen - 1] == '/') {
err = mkdir(path, 0755); err = mkdir(path, 0755);
@@ -213,15 +211,15 @@ cleanup:


void pluginOpenBrowser(std::string url) { void pluginOpenBrowser(std::string url) {
// shell injection is possible, so make sure the URL is trusted // shell injection is possible, so make sure the URL is trusted
#if defined(LINUX)
#if ARCH_LIN
std::string command = "xdg-open " + url; std::string command = "xdg-open " + url;
system(command.c_str()); system(command.c_str());
#endif #endif
#if defined(APPLE)
#if ARCH_MAC
std::string command = "open " + url; std::string command = "open " + url;
system(command.c_str()); system(command.c_str());
#endif #endif
#if defined(WINDOWS)
#if ARCH_WIN
ShellExecute(NULL, "open", url.c_str(), NULL, NULL, SW_SHOWNORMAL); ShellExecute(NULL, "open", url.c_str(), NULL, NULL, SW_SHOWNORMAL);
#endif #endif
} }
@@ -245,14 +243,14 @@ void pluginLogIn(std::string email, std::string password) {
if (res == CURLE_OK) { if (res == CURLE_OK) {
// Parse JSON response // Parse JSON response
json_error_t error; json_error_t error;
json_t *root = json_loads(resText.c_str(), 0, &error);
if (root) {
json_t *tokenJ = json_object_get(root, "token");
json_t *rootJ = json_loads(resText.c_str(), 0, &error);
if (rootJ) {
json_t *tokenJ = json_object_get(rootJ, "token");
if (tokenJ) { if (tokenJ) {
// Set the token, which logs the user in // Set the token, which logs the user in
token = json_string_value(tokenJ); token = json_string_value(tokenJ);
} }
json_decref(root);
json_decref(rootJ);
} }
} }
} }
@@ -287,11 +285,8 @@ static void pluginRefreshPlugin(json_t *pluginJ) {
downloadProgress = 0.0; downloadProgress = 0.0;


const char *dir = "plugins"; const char *dir = "plugins";
char path[MAXPATHLEN] = "\0";
strncat(path, dir, MAXPATHLEN);
strncat(path, "/", MAXPATHLEN);
strncat(path, slug.c_str(), MAXPATHLEN);
strncat(path, ".zip", MAXPATHLEN);
char path[MAXPATHLEN];
snprintf(path, sizeof(path), "%s/%s.zip", dir, slug.c_str());
int zip = open(path, O_RDWR | O_TRUNC | O_CREAT, 0644); int zip = open(path, O_RDWR | O_TRUNC | O_CREAT, 0644);
// Download zip // Download zip
download_file(zip, url.c_str()); download_file(zip, url.c_str());
@@ -329,9 +324,9 @@ void pluginRefresh() {
if (res == CURLE_OK) { if (res == CURLE_OK) {
// Parse JSON response // Parse JSON response
json_error_t error; json_error_t error;
json_t *root = json_loads(resText.c_str(), 0, &error);
if (root) {
json_t *pluginsJ = json_object_get(root, "plugins");
json_t *rootJ = json_loads(resText.c_str(), 0, &error);
if (rootJ) {
json_t *pluginsJ = json_object_get(rootJ, "plugins");
if (pluginsJ) { if (pluginsJ) {
// Iterate through each plugin object // Iterate through each plugin object
size_t index; size_t index;
@@ -340,7 +335,7 @@ void pluginRefresh() {
pluginRefreshPlugin(pluginJ); pluginRefreshPlugin(pluginJ);
} }
} }
json_decref(root);
json_decref(rootJ);
} }
} }




+ 12
- 0
src/widgets/Scene.cpp View File

@@ -16,6 +16,18 @@ void Scene::setOverlay(Widget *w) {
} }
} }


Menu *Scene::createMenu() {
// Get relative position of the click
MenuOverlay *overlay = new MenuOverlay();
Menu *menu = new Menu();
menu->box.pos = gMousePos;

overlay->addChild(menu);
gScene->setOverlay(overlay);

return menu;
}

void Scene::step() { void Scene::step() {
if (overlay) { if (overlay) {
overlay->box.size = box.size; overlay->box.size = box.size;


Loading…
Cancel
Save