From a2fad7d2faed9175d63dcc59a459103b376d2046 Mon Sep 17 00:00:00 2001 From: Weili Shi Date: Fri, 3 Nov 2017 11:51:06 -0400 Subject: [PATCH 01/23] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f8d3873..c881b71 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ void BaseAppSampleApp::prepareSettings(ci::app::App::Settings* settings) { SettingsManager::setInstance(myApp::MyAppSettingsManager::getInstance()); // Initialize the settings manager with the cinder app settings and the settings json - SettingsManager::getInstance()->setup(settings, ci::app::getAssetPath("appSettings.json"), [](SettingsManager * manager) { + SettingsManager::getInstance()->setup(settings, ci::app::getAssetPath("settings.json"), [](SettingsManager * manager) { // Optional: Override json defaults at runtime manager->mFullscreen = false; manager->mWindowSize = ivec2(1280, 720); From 44abcf79ffb2af6b70af41aa8799140832720099 Mon Sep 17 00:00:00 2001 From: Benjamin Bojko Date: Mon, 13 Nov 2017 14:27:32 -0500 Subject: [PATCH 02/23] Hide params w Shift+F1; Toggle cursor w C even when params are hidden --- src/bluecadet/core/BaseApp.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/bluecadet/core/BaseApp.cpp b/src/bluecadet/core/BaseApp.cpp index d8a4e52..7d56acc 100644 --- a/src/bluecadet/core/BaseApp.cpp +++ b/src/bluecadet/core/BaseApp.cpp @@ -141,7 +141,9 @@ void BaseApp::draw(const bool clear) { if (settings->mDrawStats) { mStats->drawScene(); } - settings->getParams()->draw(); + if (settings->getParams()->isVisible()) { + settings->getParams()->draw(); + } } } @@ -155,6 +157,10 @@ void BaseApp::keyDown(KeyEvent event) { case KeyEvent::KEY_q: quit(); break; + case KeyEvent::KEY_c: + SettingsManager::getInstance()->mShowMouse = !SettingsManager::getInstance()->mShowMouse; + SettingsManager::getInstance()->mShowMouse ? showCursor() : hideCursor(); + break; case KeyEvent::KEY_f: SettingsManager::getInstance()->mFullscreen = !isFullScreen(); setFullScreen(SettingsManager::getInstance()->mFullscreen); @@ -166,9 +172,14 @@ void BaseApp::keyDown(KeyEvent event) { SettingsManager::getInstance()->getParams()->maximize(); } else if (SettingsManager::getInstance()->getParams()->isMaximized()) { - SettingsManager::getInstance()->getParams()->minimize(); + if (event.isShiftDown()) { + SettingsManager::getInstance()->getParams()->hide(); + } else { + SettingsManager::getInstance()->getParams()->minimize(); + } } else { + SettingsManager::getInstance()->getParams()->show(); SettingsManager::getInstance()->getParams()->maximize(); } break; From a4d4739125d36b2c73230006ab31c560656bfd5b Mon Sep 17 00:00:00 2001 From: Benjamin Bojko Date: Mon, 13 Nov 2017 15:31:53 -0500 Subject: [PATCH 03/23] Consolidated and cleaned up settings json/mgr --- assets/settings.json | 72 +++++------ samples/ViewTypesSample/assets/settings.json | 72 +++++------ .../src/ViewTypesSampleApp.cpp | 11 +- src/bluecadet/core/BaseApp.cpp | 33 +++-- src/bluecadet/core/SettingsManager.cpp | 117 ++++++++---------- src/bluecadet/core/SettingsManager.h | 79 ++++++------ 6 files changed, 185 insertions(+), 199 deletions(-) diff --git a/assets/settings.json b/assets/settings.json index bab8f1e..fd0a208 100644 --- a/assets/settings.json +++ b/assets/settings.json @@ -1,37 +1,39 @@ { - "settings": { - "general": { - "consoleWindowEnabled": true, - "FPS": 60, - "appVersion": "alpha-1.0" - }, - "display": { - "width": 1920, - "height": 1080, - "columns": 1, - "rows": 1 - }, - "graphics": { - "verticalSync": true, - "fullscreen": true, - "borderless": false - }, - "debug": { - "debugMode": true, - "drawMinimap": true, - "drawTouches": false, - "minimizeParams": true, - "drawScreenLayout": false - }, - "touch": { - "mouse": true, - "tuio": true, - "native": true - }, - "analytics": { - "appName": "", - "trackingId": "", - "clientId": "" - } - } + "settings": { + "general": { + "console": true, + "version": "v1.0.0" + }, + "display": { + "size": {"x": 1920, "y": 1080}, + "columns": 1, + "rows": 1 + }, + "window": { + "fps": 60, + "vsync": true, + "fullscreen": true, + "borderless": false, + "size": {"x": 1280, "y": 720}, + "cameraOffset": {"x": 0, "y": 0}, + "clearColor": {"r": 0, "g": 0, "b": 0, "a": 1.0} + }, + "touch": { + "mouse": true, + "tuio": true, + "native": false + }, + "debug": { + "debugEnabled": true, + "showStats": false, + "showMinimap": false, + "showTouches": false, + "showScreenLayout": false, + "showCursor": true, + "minimizeParams": false, + "collapseParams": true, + "displayIdHotkeys": false, + "zoomToggleHotkey": true + } + } } diff --git a/samples/ViewTypesSample/assets/settings.json b/samples/ViewTypesSample/assets/settings.json index bab8f1e..fd0a208 100644 --- a/samples/ViewTypesSample/assets/settings.json +++ b/samples/ViewTypesSample/assets/settings.json @@ -1,37 +1,39 @@ { - "settings": { - "general": { - "consoleWindowEnabled": true, - "FPS": 60, - "appVersion": "alpha-1.0" - }, - "display": { - "width": 1920, - "height": 1080, - "columns": 1, - "rows": 1 - }, - "graphics": { - "verticalSync": true, - "fullscreen": true, - "borderless": false - }, - "debug": { - "debugMode": true, - "drawMinimap": true, - "drawTouches": false, - "minimizeParams": true, - "drawScreenLayout": false - }, - "touch": { - "mouse": true, - "tuio": true, - "native": true - }, - "analytics": { - "appName": "", - "trackingId": "", - "clientId": "" - } - } + "settings": { + "general": { + "console": true, + "version": "v1.0.0" + }, + "display": { + "size": {"x": 1920, "y": 1080}, + "columns": 1, + "rows": 1 + }, + "window": { + "fps": 60, + "vsync": true, + "fullscreen": true, + "borderless": false, + "size": {"x": 1280, "y": 720}, + "cameraOffset": {"x": 0, "y": 0}, + "clearColor": {"r": 0, "g": 0, "b": 0, "a": 1.0} + }, + "touch": { + "mouse": true, + "tuio": true, + "native": false + }, + "debug": { + "debugEnabled": true, + "showStats": false, + "showMinimap": false, + "showTouches": false, + "showScreenLayout": false, + "showCursor": true, + "minimizeParams": false, + "collapseParams": true, + "displayIdHotkeys": false, + "zoomToggleHotkey": true + } + } } diff --git a/samples/ViewTypesSample/src/ViewTypesSampleApp.cpp b/samples/ViewTypesSample/src/ViewTypesSampleApp.cpp index 8ddfe76..1d6d91f 100644 --- a/samples/ViewTypesSample/src/ViewTypesSampleApp.cpp +++ b/samples/ViewTypesSample/src/ViewTypesSampleApp.cpp @@ -36,13 +36,14 @@ class ViewTypesSampleApp : public BaseApp { }; void ViewTypesSampleApp::prepareSettings(ci::app::App::Settings* settings) { - SettingsManager::getInstance()->setup(settings, "", [](SettingsManager * manager) { + SettingsManager::getInstance()->setup(settings, ci::app::getAssetPath("../assets/settings.json"), [](SettingsManager * manager) { manager->mFullscreen = false; manager->mWindowSize = ivec2(1280, 720); - manager->mConsoleWindowEnabled = false; - manager->mDrawMinimap = true; - manager->mDrawStats = true; - manager->mDrawTouches = true; + manager->mDisplaySize = ivec2(1280, 720); + manager->mConsole = false; + manager->mShowMinimap = true; + manager->mShowStats = true; + manager->mShowTouches = true; manager->mMinimizeParams = true; }); } diff --git a/src/bluecadet/core/BaseApp.cpp b/src/bluecadet/core/BaseApp.cpp index 7d56acc..009e6fd 100644 --- a/src/bluecadet/core/BaseApp.cpp +++ b/src/bluecadet/core/BaseApp.cpp @@ -29,15 +29,12 @@ BaseApp::~BaseApp() { void BaseApp::setup() { auto settings = SettingsManager::getInstance(); - - // Set up screen layout - int displayWidth = settings->hasField("settings.display.width") ? settings->getField("settings.display.width") : getWindowWidth(); - int displayHeight = settings->hasField("settings.display.height") ? settings->getField("settings.display.height") : getWindowHeight(); - int rows = settings->hasField("settings.display.rows") ? settings->getField("settings.display.rows") : ScreenLayout::getInstance()->getNumRows(); - int cols = settings->hasField("settings.display.columns") ? settings->getField("settings.display.columns") : ScreenLayout::getInstance()->getNumColumns(); + + if (settings->mDisplaySize.x <= 0) settings->mDisplaySize.x = getWindowWidth(); + if (settings->mDisplaySize.y <= 0) settings->mDisplaySize.y = getWindowHeight(); ScreenLayout::getInstance()->getAppSizeChangedSignal().connect(bind(&BaseApp::handleAppSizeChange, this, placeholders::_1)); - ScreenLayout::getInstance()->setup(ivec2(displayWidth, displayHeight), rows, cols); + ScreenLayout::getInstance()->setup(settings->mDisplaySize, settings->mDisplayRows, settings->mDisplayColumns); ScreenCamera::getInstance()->setup(ScreenLayout::getInstance()); ScreenCamera::getInstance()->getViewportChangedSignal().connect(bind(&BaseApp::handleViewportChange, this, placeholders::_1)); @@ -53,7 +50,7 @@ void BaseApp::setup() { } // Apply run-time settings - if (settings->mShowMouse) { + if (settings->mShowCursor) { showCursor(); } else { hideCursor(); @@ -123,22 +120,22 @@ void BaseApp::draw(const bool clear) { mRootView->drawScene(); // draw debug touches in app coordinate space - if (settings->mDebugMode && settings->mDrawTouches) { + if (settings->mDebugEnabled && settings->mShowTouches) { touch::TouchManager::getInstance()->debugDrawTouches(); } } - if (settings->mDebugMode) { + if (settings->mDebugEnabled) { // draw params and debug layers in window coordinate space - if (settings->mDrawScreenLayout) { + if (settings->mShowScreenLayout) { gl::ScopedModelMatrix scopedMatrix; gl::multModelMatrix(ScreenCamera::getInstance()->getTransform()); ScreenLayout::getInstance()->draw(); } - if (settings->mDrawMinimap) { + if (settings->mShowMinimap) { mMiniMap->drawScene(); } - if (settings->mDrawStats) { + if (settings->mShowStats) { mStats->drawScene(); } if (settings->getParams()->isVisible()) { @@ -158,8 +155,8 @@ void BaseApp::keyDown(KeyEvent event) { quit(); break; case KeyEvent::KEY_c: - SettingsManager::getInstance()->mShowMouse = !SettingsManager::getInstance()->mShowMouse; - SettingsManager::getInstance()->mShowMouse ? showCursor() : hideCursor(); + SettingsManager::getInstance()->mShowCursor = !SettingsManager::getInstance()->mShowCursor; + SettingsManager::getInstance()->mShowCursor ? showCursor() : hideCursor(); break; case KeyEvent::KEY_f: SettingsManager::getInstance()->mFullscreen = !isFullScreen(); @@ -211,15 +208,15 @@ void BaseApp::addTouchSimulatorParams(float touchesPerSecond) { params->addParam("Enabled", [&](bool v) { if (!mSimulatedTouchDriver.isRunning()) { - SettingsManager::getInstance()->mDrawTouches = true; + SettingsManager::getInstance()->mShowTouches = true; mSimulatedTouchDriver.setBounds(Rectf(vec2(0), getWindowSize())); mSimulatedTouchDriver.start(); } else { - SettingsManager::getInstance()->mDrawTouches = false; + SettingsManager::getInstance()->mShowTouches = false; mSimulatedTouchDriver.stop(); } }, [&] { - return SettingsManager::getInstance()->mDrawTouches && mSimulatedTouchDriver.isRunning(); + return SettingsManager::getInstance()->mShowTouches && mSimulatedTouchDriver.isRunning(); }).group(groupName); static int stressTestMode = 0; diff --git a/src/bluecadet/core/SettingsManager.cpp b/src/bluecadet/core/SettingsManager.cpp index 9968671..f2bb784 100644 --- a/src/bluecadet/core/SettingsManager.cpp +++ b/src/bluecadet/core/SettingsManager.cpp @@ -1,7 +1,6 @@ #include "SettingsManager.h" #include "../views/BaseView.h" -#include "cinder/Log.h" #include #include @@ -15,33 +14,7 @@ namespace core { SettingsManagerRef SettingsManager::sInstance = nullptr; -// Initialization SettingsManager::SettingsManager() { - - // General - mConsoleWindowEnabled = true; - mFps = 60; - mAppVersion = ""; - - // Graphics - mVerticalSync = true; - mClearColor = ci::ColorA(0, 0, 0, 1.0f); - - // Debugging - mDebugMode = true; - mDrawMinimap = true; - mDrawTouches = false; - mDrawScreenLayout = false; - mFullscreen = true; - mBorderless = false; - mShowMouse = true; - mDrawStats = true; - mWindowSize = ivec2(0); - - // Analytics - mAnalyticsAppName = ""; - mAnalyticsTrackingId = ""; - mAnalyticsClientId = ""; } SettingsManager::~SettingsManager() {} @@ -69,19 +42,19 @@ void SettingsManager::setup(ci::app::App::Settings * appSettings, ci::fs::path j } // Parse arguments from command line - addCommandLineParser("debug", [&](const string &value) { mDebugMode = value == "true"; }); + addCommandLineParser("debug", [&](const string &value) { mDebugEnabled = value == "true"; }); addCommandLineParser("fullscreen", [&](const string &value) { mFullscreen = value == "true"; }); addCommandLineParser("borderless", [&](const string &value) { mBorderless = value == "true"; }); addCommandLineParser("vsync", [&](const string &value) { mVerticalSync = value == "true"; }); - addCommandLineParser("console", [&](const string &value) { mConsoleWindowEnabled = value == "true"; }); - addCommandLineParser("cursor", [&](const string &value) { mShowMouse = value == "true"; }); + addCommandLineParser("console", [&](const string &value) { mConsole = value == "true"; }); + addCommandLineParser("cursor", [&](const string &value) { mShowCursor = value == "true"; }); addCommandLineParser("mouse", [&](const string &value) { mMouseEnabled = value == "true"; }); addCommandLineParser("tuio", [&](const string &value) { mTuioTouchEnabled = value == "true"; }); addCommandLineParser("native", [&](const string &value) { mNativeTouchEnabled = value == "true"; }); - addCommandLineParser("drawTouches", [&](const string &value) { mDrawTouches = value == "true"; }); - addCommandLineParser("draw_touches", [&](const string &value) { mDrawTouches = value == "true"; }); - addCommandLineParser("drawStats", [&](const string &value) { mDrawStats = value == "true"; }); - addCommandLineParser("draw_stats", [&](const string &value) { mDrawStats = value == "true"; }); + addCommandLineParser("drawTouches", [&](const string &value) { mShowTouches = value == "true"; }); + addCommandLineParser("draw_touches", [&](const string &value) { mShowTouches = value == "true"; }); + addCommandLineParser("drawStats", [&](const string &value) { mShowStats = value == "true"; }); + addCommandLineParser("draw_stats", [&](const string &value) { mShowStats = value == "true"; }); addCommandLineParser("minimizeParams", [&](const string &value) { mMinimizeParams = value == "true"; }); addCommandLineParser("minimize_params", [&](const string &value) { mMinimizeParams = value == "true"; }); addCommandLineParser("collapseParams", [&](const string &value) { mCollapseParams = value == "true"; }); @@ -117,7 +90,7 @@ void SettingsManager::applyToAppSettings(ci::app::App::Settings * settings) { // Apply pre-launch settings #ifdef CINDER_MSW - settings->setConsoleWindowEnabled(mConsoleWindowEnabled); + settings->setConsoleWindowEnabled(mConsole); #endif settings->setFrameRate((float)mFps); settings->setWindowSize(mWindowSize); @@ -152,38 +125,50 @@ void SettingsManager::addCommandLineParser(const std::string& key, CommandLineAr void SettingsManager::parseJson(ci::JsonTree & json) { // General - setFieldFromJsonIfExists(&mConsoleWindowEnabled, "settings.general.consoleWindowEnabled"); - setFieldFromJsonIfExists(&mFps, "settings.general.FPS"); - setFieldFromJsonIfExists(&mAppVersion, "settings.general.appVersion"); + setFieldFromJsonIfExists(&mConsole, "settings.general.consoleWindowEnabled"); + setFieldFromJsonIfExists(&mConsole, "settings.general.console"); + setFieldFromJsonIfExists(&mAppVersion, "settings.general.version"); + + // Display + setFieldFromJsonIfExists(&mDisplaySize.x, "settings.display.size.x"); + setFieldFromJsonIfExists(&mDisplaySize.y, "settings.display.size.y"); + setFieldFromJsonIfExists(&mDisplayColumns, "settings.display.columns"); + setFieldFromJsonIfExists(&mDisplayRows, "settings.display.rows"); + + // Window + setFieldFromJsonIfExists(&mFps, "settings.window.fps"); + setFieldFromJsonIfExists(&mFps, "settings.window.FPS"); + setFieldFromJsonIfExists(&mVerticalSync, "settings.window.verticalSync"); + setFieldFromJsonIfExists(&mVerticalSync, "settings.window.vsync"); + setFieldFromJsonIfExists(&mFullscreen, "settings.window.fullscreen"); + setFieldFromJsonIfExists(&mBorderless, "settings.window.borderless"); + setFieldFromJsonIfExists(&mWindowSize.x, "settings.window.size.x"); + setFieldFromJsonIfExists(&mWindowSize.y, "settings.window.size.x"); + setFieldFromJsonIfExists(&mCameraOffset.x, "settings.window.cameraOffset.x"); + setFieldFromJsonIfExists(&mCameraOffset.y, "settings.window.cameraOffset.y"); + setFieldFromJsonIfExists(&mClearColor.r, "settings.window.clearColor.r"); + setFieldFromJsonIfExists(&mClearColor.g, "settings.window.clearColor.g"); + setFieldFromJsonIfExists(&mClearColor.b, "settings.window.clearColor.b"); + setFieldFromJsonIfExists(&mClearColor.a, "settings.window.clearColor.a"); - // Graphics - setFieldFromJsonIfExists(&mVerticalSync, "settings.graphics.verticalSync"); - setFieldFromJsonIfExists(&mFullscreen, "settings.graphics.fullscreen"); - setFieldFromJsonIfExists(&mBorderless, "settings.graphics.borderless"); + // Touch + setFieldFromJsonIfExists(&mMouseEnabled, "settings.touch.mouse"); + setFieldFromJsonIfExists(&mTuioTouchEnabled, "settings.touch.tuio"); + setFieldFromJsonIfExists(&mNativeTouchEnabled, "settings.touch.native"); // Debug - setFieldFromJsonIfExists(&mDebugMode, "settings.debug.debugMode"); - setFieldFromJsonIfExists(&mShowMouse, "settings.debug.showMouse"); - setFieldFromJsonIfExists(&mDrawStats, "settings.debug.drawStats"); - setFieldFromJsonIfExists(&mDrawMinimap, "settings.debug.drawMinimap"); - setFieldFromJsonIfExists(&mDrawTouches, "settings.debug.drawTouches"); - setFieldFromJsonIfExists(&mDrawScreenLayout, "settings.debug.drawScreenLayout"); + setFieldFromJsonIfExists(&mDebugEnabled, "settings.debug.debugMode"); + setFieldFromJsonIfExists(&mDebugEnabled, "settings.debug.debugEnabled"); + setFieldFromJsonIfExists(&mShowStats, "settings.debug.showStats"); + setFieldFromJsonIfExists(&mShowMinimap, "settings.debug.showMinimap"); + setFieldFromJsonIfExists(&mShowTouches, "settings.debug.showTouches"); + setFieldFromJsonIfExists(&mShowScreenLayout, "settings.debug.showScreenLayout"); + setFieldFromJsonIfExists(&mShowCursor, "settings.debug.showMouse"); + setFieldFromJsonIfExists(&mShowCursor, "settings.debug.showCursor"); setFieldFromJsonIfExists(&mMinimizeParams, "settings.debug.minimizeParams"); setFieldFromJsonIfExists(&mCollapseParams, "settings.debug.collapseParams"); setFieldFromJsonIfExists(&mZoomToggleHotkeyEnabled, "settings.debug.zoomToggleHotkey"); setFieldFromJsonIfExists(&mDisplayIdHotkeysEnabled, "settings.debug.displayIdHotkeys"); - - // Touch - setFieldFromJsonIfExists(&mMouseEnabled, "settings.touch.mouse"); - setFieldFromJsonIfExists(&mTuioTouchEnabled, "settings.touch.tuio"); - setFieldFromJsonIfExists(&mNativeTouchEnabled, "settings.touch.native"); - - // Analytics - setFieldFromJsonIfExists(&mAnalyticsAppName, "settings.analytics.appName"); - setFieldFromJsonIfExists(&mAnalyticsTrackingId, "settings.analytics.trackingId"); - setFieldFromJsonIfExists(&mAnalyticsTrackingId, "settings.analytics.trackingID"); - setFieldFromJsonIfExists(&mAnalyticsClientId, "settings.analytics.clientId"); - setFieldFromJsonIfExists(&mAnalyticsClientId, "settings.analytics.clientID"); } void SettingsManager::parseCommandLineArgs(const std::vector& args) { @@ -215,12 +200,12 @@ ci::params::InterfaceGlRef SettingsManager::getParams() { static ci::params::InterfaceGlRef params = nullptr; if (!params) { params = ci::params::InterfaceGl::create("Settings", ci::ivec2(250, 250)); - params->addParam("Show Layout", &mDrawScreenLayout).group("App").key("l"); - params->addParam("Show Minimap", &mDrawMinimap).group("App").key("m"); - params->addParam("Show Stats", &mDrawStats).group("App").key("s"); + params->addParam("Show Layout", &mShowScreenLayout).group("App").key("l"); + params->addParam("Show Minimap", &mShowMinimap).group("App").key("m"); + params->addParam("Show Stats", &mShowStats).group("App").key("s"); - params->addParam("Show Touches", &mDrawTouches).group("App").key("t"); - params->addParam("Show Cursor", &mShowMouse).updateFn([&] { mShowMouse ? ci::app::AppBase::get()->showCursor() : ci::app::AppBase::get()->hideCursor(); }).key("c").group("App"); + params->addParam("Show Touches", &mShowTouches).group("App").key("t"); + params->addParam("Show Cursor", &mShowCursor).updateFn([&] { mShowCursor ? ci::app::AppBase::get()->showCursor() : ci::app::AppBase::get()->hideCursor(); }).key("c").group("App"); static int boundIndex = 0; params->addParam("View Bounds", {"None", "Visible", "All"}, [&](int i) { @@ -233,6 +218,8 @@ ci::params::InterfaceGlRef SettingsManager::getParams() { params->minimize(); } + params->addText("Version " + mAppVersion); + if (mCollapseParams) { params->setOptions("App", "opened=false"); } diff --git a/src/bluecadet/core/SettingsManager.h b/src/bluecadet/core/SettingsManager.h index d31dcc2..52a7870 100644 --- a/src/bluecadet/core/SettingsManager.h +++ b/src/bluecadet/core/SettingsManager.h @@ -1,7 +1,8 @@ #pragma once -#include "cinder/Json.h" #include "cinder/app/App.h" +#include "cinder/Json.h" +#include "cinder/Log.h" #include "cinder/params/Params.h" namespace bluecadet { @@ -67,42 +68,42 @@ class SettingsManager { // // General - bool mConsoleWindowEnabled; - int mFps; - std::string mAppVersion; + bool mConsole = true; //! Use external console window + std::string mAppVersion = ""; //! Displays app version in the params // Graphics + int mFps = 60; bool mFullscreen = true; - bool mBorderless = true; - bool mVerticalSync; + bool mBorderless = false; + bool mVerticalSync = true; + + // Display + ci::ivec2 mDisplaySize = ci::ivec2(-1, -1); //! The size of one display. Defaults to getWindowSize() + int mDisplayColumns = 1; //! The number of display columns in a display matrix. Use by ScreenLayout class. + int mDisplayRows = 1; //! The number of display rows in a display matrix. Use by ScreenLayout class. + + // Window + ci::ivec2 mWindowSize; //! The window size on launch + ci::vec2 mCameraOffset; //! The offset of the camera on launch + ci::ColorA mClearColor = ci::ColorA::black(); //! The color used when clearing the screen before draw(). Defaults to opaque black. // Touches - bool mNativeTouchEnabled = false; - bool mTuioTouchEnabled = true; - bool mMouseEnabled = true; + bool mNativeTouchEnabled = false; //! Native touch coming from the OS + bool mTuioTouchEnabled = true; //! TUIO touch events; It's recommended to disable native touch when TUIO is enabled to prevent duplicate events. + bool mMouseEnabled = true; //! Treat mouse events as touch events. // Debugging - bool mDebugMode = false; - bool mDrawTouches = false; - bool mDrawScreenLayout = false; - bool mShowMouse = false; - bool mDrawMinimap = false; - bool mDrawStats = false; - bool mMinimizeParams = false; //! Minimizes the params window + bool mDebugEnabled = false; //! Enable/disable all of the below debug features (except for hotkeys) + bool mShowTouches = false; //! Visualizes all current touch data + bool mShowScreenLayout = false; //! Visualizes the current screen layout and bezels + bool mShowCursor = false; //! Show or hide the mouse cursor (toggle with C) + bool mShowMinimap = false; //! Show or hide the mini-map (toggle with M) + bool mShowStats = false; //! Show or hide the frame-rate graph/plot (toggle with S) + bool mMinimizeParams = false; //! Minimizes the params window (toggle with F1) bool mCollapseParams = false; //! Collapses all the default parameter groups like "App" bool mZoomToggleHotkeyEnabled = true; //! When true, will bind 0 to toggle zoom to 100%/fit bool mDisplayIdHotkeysEnabled = false; //! When true, will bind 1-9 to zoom directly to displays 1-9 - // CLI/runtime only args - ci::ivec2 mWindowSize; //! The window size on launch - ci::vec2 mCameraOffset; //! The offset of the camera on launch - ci::ColorA mClearColor; //! The color used when clearing the screen before draw(). Defaults to opaque black. - - // Analytics - std::string mAnalyticsAppName; - std::string mAnalyticsTrackingId; - std::string mAnalyticsClientId; - protected: static SettingsManagerRef sInstance; @@ -135,46 +136,42 @@ class SettingsManager { }; - - //================================================== - // Template and inline implementations - // +//================================================== +// Template and inline implementations +// template -T SettingsManager::getField(const std::string& field) { +T SettingsManager::getField(const std::string & field) { try { if (!hasField(field)) { - ci::app::console() << "SettingsManager: Could not find settings value for field name '" << field << "' in json file" << std::endl; + CI_LOG_W("Field '" << field << "' could not be found"); return T(); } return mSettingsJson.getValueForKey(field); } catch (cinder::Exception e) { - // ci::app::console() << "SettingsManager: Could not find '" << field << "' in json file: " << e.what() << std::endl; + CI_LOG_EXCEPTION("Could not find '" << field << "' in json file", e); return T(); } }; template -void SettingsManager::setFieldFromJsonIfExists(T* target, const std::string& jsonFieldName) { +void SettingsManager::setFieldFromJsonIfExists(T * target, const std::string & jsonFieldName) { try { if (!hasField(jsonFieldName)) { - // cinder::app::console() << "SettingsManager: Could not find settings value for field name '" << jsonFieldName << "' in json file" << std::endl; + CI_LOG_W("Could not find settings value for field name '" << jsonFieldName << "' in json file"); return; } *target = mSettingsJson.getValueForKey(jsonFieldName); - // ci::app::console() << "SettingsManager: Set '" << jsonFieldName << "' to '" << SettingsManager::toString(target) << "' from json file" << std::endl; } catch (cinder::Exception e) { - // ci::app::console() << "SettingsManager: Could not set '" << jsonFieldName << "' from json file: " << e.what() << std::endl; + CI_LOG_EXCEPTION("Could not set '" << jsonFieldName << "' in json file", e); } } template <> -std::string inline SettingsManager::toString(std::string* target) { +std::string inline SettingsManager::toString(std::string * target) { return *target; } - - } // namespace utils -} // namespace bluecadet \ No newline at end of file +} // namespace bluecadet From 2905c547c31c4e415641957516940e171e74375d Mon Sep 17 00:00:00 2001 From: Benjamin Bojko Date: Mon, 13 Nov 2017 17:32:10 -0500 Subject: [PATCH 04/23] Minor tweaks --- src/bluecadet/core/ScreenLayout.h | 6 +- src/bluecadet/core/SettingsManager.cpp | 82 +++++++++++++------------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/bluecadet/core/ScreenLayout.h b/src/bluecadet/core/ScreenLayout.h index 708f894..ed42eed 100644 --- a/src/bluecadet/core/ScreenLayout.h +++ b/src/bluecadet/core/ScreenLayout.h @@ -51,8 +51,8 @@ class ScreenLayout { void setDisplayHeight(const int height) { mDisplaySize.y = height; updateLayout(); }; //! The size of a single display in the display matrix - ci::ivec2 getDisplaySize() const { return mDisplaySize; } - void setDisplaySize(const ci::ivec2 value) { mDisplaySize = value; } + const ci::ivec2 & getDisplaySize() const { return mDisplaySize; } + void setDisplaySize(const ci::ivec2 value) { mDisplaySize = value; } //! The number of rows of displays in the display matrix. int getNumRows() const { return mNumRows; }; @@ -82,7 +82,7 @@ class ScreenLayout { //! The total app size when scaled at 100% - const ci::ivec2& getAppSize() const { return mAppSize; }; + const ci::ivec2 & getAppSize() const { return mAppSize; }; //! Overall app width when scaled at 100% int getAppWidth() const { return getAppSize().x; } diff --git a/src/bluecadet/core/SettingsManager.cpp b/src/bluecadet/core/SettingsManager.cpp index f2bb784..596ef5e 100644 --- a/src/bluecadet/core/SettingsManager.cpp +++ b/src/bluecadet/core/SettingsManager.cpp @@ -82,47 +82,6 @@ void SettingsManager::setup(ci::app::App::Settings * appSettings, ci::fs::path j applyToAppSettings(appSettings); } -void SettingsManager::applyToAppSettings(ci::app::App::Settings * settings) { - // Default window size to main display size if no custom size has been determined - if (mWindowSize == ivec2(0)) { - mWindowSize = Display::getMainDisplay()->getSize(); - } - - // Apply pre-launch settings -#ifdef CINDER_MSW - settings->setConsoleWindowEnabled(mConsole); -#endif - settings->setFrameRate((float)mFps); - settings->setWindowSize(mWindowSize); - settings->setBorderless(mBorderless); - settings->setFullScreen(mFullscreen); - - if (mNativeTouchEnabled) { - settings->setMultiTouchEnabled(true); - } - - // Keep window top-left within display bounds - if (settings->getWindowPos().x == 0 && settings->getWindowPos().y == 0) { - ivec2 windowPos = (Display::getMainDisplay()->getSize() - settings->getWindowSize()) / 2; - windowPos = glm::max(windowPos, ivec2(0)); - settings->setWindowPos(windowPos); - } -} - -void SettingsManager::addCommandLineParser(const std::string& key, CommandLineArgParserFn callback) { - string lowercaseKey = key; - std::transform(lowercaseKey.begin(), lowercaseKey.end(), lowercaseKey.begin(), ::tolower); - - auto callbackListIt = mCommandLineArgsHandlers.find(lowercaseKey); - - if (callbackListIt == mCommandLineArgsHandlers.end()) { - mCommandLineArgsHandlers[lowercaseKey] = vector(); - callbackListIt = mCommandLineArgsHandlers.find(lowercaseKey); - } - - callbackListIt->second.push_back(callback); -} - void SettingsManager::parseJson(ci::JsonTree & json) { // General setFieldFromJsonIfExists(&mConsole, "settings.general.consoleWindowEnabled"); @@ -171,6 +130,47 @@ void SettingsManager::parseJson(ci::JsonTree & json) { setFieldFromJsonIfExists(&mDisplayIdHotkeysEnabled, "settings.debug.displayIdHotkeys"); } +void SettingsManager::applyToAppSettings(ci::app::App::Settings * settings) { + // Default window size to main display size if no custom size has been determined + if (mWindowSize == ivec2(0)) { + mWindowSize = Display::getMainDisplay()->getSize(); + } + + // Apply pre-launch settings +#ifdef CINDER_MSW + settings->setConsoleWindowEnabled(mConsole); +#endif + settings->setFrameRate((float)mFps); + settings->setWindowSize(mWindowSize); + settings->setBorderless(mBorderless); + settings->setFullScreen(mFullscreen); + + if (mNativeTouchEnabled) { + settings->setMultiTouchEnabled(true); + } + + // Keep window top-left within display bounds + if (settings->getWindowPos().x == 0 && settings->getWindowPos().y == 0) { + ivec2 windowPos = (Display::getMainDisplay()->getSize() - settings->getWindowSize()) / 2; + windowPos = glm::max(windowPos, ivec2(0)); + settings->setWindowPos(windowPos); + } +} + +void SettingsManager::addCommandLineParser(const std::string& key, CommandLineArgParserFn callback) { + string lowercaseKey = key; + std::transform(lowercaseKey.begin(), lowercaseKey.end(), lowercaseKey.begin(), ::tolower); + + auto callbackListIt = mCommandLineArgsHandlers.find(lowercaseKey); + + if (callbackListIt == mCommandLineArgsHandlers.end()) { + mCommandLineArgsHandlers[lowercaseKey] = vector(); + callbackListIt = mCommandLineArgsHandlers.find(lowercaseKey); + } + + callbackListIt->second.push_back(callback); +} + void SettingsManager::parseCommandLineArgs(const std::vector& args) { string allArgsStr; From 20a4e90f445890515a9a29c0a6904b2b350a2c15 Mon Sep 17 00:00:00 2001 From: Benjamin Bojko Date: Mon, 13 Nov 2017 17:41:31 -0500 Subject: [PATCH 05/23] Updated readme and minor SettingsManager h cleanup --- README.md | 2 +- src/bluecadet/core/SettingsManager.h | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c881b71..ea057ce 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ void BaseAppSampleApp::setup() { getRootView()->setBackgroundColor(Color::gray(0.5f)); // Sample content - auto button = TouchViewRef(new TouchView()); + auto button = make_shared(); button->setPosition(vec2(400, 300)); button->setSize(vec2(200, 100)); button->setBackgroundColor(Color(1, 0, 0)); diff --git a/src/bluecadet/core/SettingsManager.h b/src/bluecadet/core/SettingsManager.h index 52a7870..32dd94e 100644 --- a/src/bluecadet/core/SettingsManager.h +++ b/src/bluecadet/core/SettingsManager.h @@ -112,17 +112,16 @@ class SettingsManager { virtual void parseJson(ci::JsonTree & json); //! Parses command line arguments, which can override json settings - virtual void parseCommandLineArgs(const std::vector& args); + virtual void parseCommandLineArgs(const std::vector & args); //! Applies parsed settings to ci::app::App::Settings virtual void applyToAppSettings(ci::app::App::Settings * settings); - //! Set fields within the settings manager class if the setting is defined in the json - template void setFieldFromJsonIfExists(T* target, const std::string& jsonFieldName); // Implemented at end of this file + template void setFieldFromJsonIfExists(T * target, const std::string & jsonFieldName); // Implemented at end of this file //! Helpers to get string from primitive types and strings since we can't call to_string on strings - template inline std::string toString(T* target) { return std::to_string(*target); } + template inline std::string toString(T * target) { return std::to_string(*target); } //! Key-based callbacks that are called when a command line argument with that key is passed in From db68de8a5e2248f574ad3cee45475a236550d243 Mon Sep 17 00:00:00 2001 From: adielfernandez Date: Tue, 14 Nov 2017 13:55:51 -0500 Subject: [PATCH 06/23] Support for bezel correction in ScreenLayout and SettingsManager --- .gitignore | 1 + samples/TextViewSample/assets/settings.json | 6 +++--- samples/ViewTypesSample/assets/settings.json | 3 ++- src/bluecadet/core/BaseApp.cpp | 2 +- src/bluecadet/core/ScreenLayout.cpp | 17 +++++++++++------ src/bluecadet/core/ScreenLayout.h | 6 +++++- src/bluecadet/core/SettingsManager.cpp | 10 ++++++++++ src/bluecadet/core/SettingsManager.h | 1 + 8 files changed, 34 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index efe7a2c..55fa27b 100644 --- a/.gitignore +++ b/.gitignore @@ -176,3 +176,4 @@ $RECYCLE.BIN/ ._.DS_Store *.xcuserstate +src/bluecadet/core/BaseApp.h diff --git a/samples/TextViewSample/assets/settings.json b/samples/TextViewSample/assets/settings.json index bab8f1e..d75909a 100644 --- a/samples/TextViewSample/assets/settings.json +++ b/samples/TextViewSample/assets/settings.json @@ -6,10 +6,10 @@ "appVersion": "alpha-1.0" }, "display": { - "width": 1920, - "height": 1080, + "size": {"x": 1920, "y": 1080}, "columns": 1, - "rows": 1 + "rows": 1, + "bezel": {"x": 0, "y": 0} }, "graphics": { "verticalSync": true, diff --git a/samples/ViewTypesSample/assets/settings.json b/samples/ViewTypesSample/assets/settings.json index fd0a208..8d3c240 100644 --- a/samples/ViewTypesSample/assets/settings.json +++ b/samples/ViewTypesSample/assets/settings.json @@ -7,7 +7,8 @@ "display": { "size": {"x": 1920, "y": 1080}, "columns": 1, - "rows": 1 + "rows": 1, + "bezel": {"x": 0, "y": 0} }, "window": { "fps": 60, diff --git a/src/bluecadet/core/BaseApp.cpp b/src/bluecadet/core/BaseApp.cpp index 009e6fd..ebc76dd 100644 --- a/src/bluecadet/core/BaseApp.cpp +++ b/src/bluecadet/core/BaseApp.cpp @@ -34,7 +34,7 @@ void BaseApp::setup() { if (settings->mDisplaySize.y <= 0) settings->mDisplaySize.y = getWindowHeight(); ScreenLayout::getInstance()->getAppSizeChangedSignal().connect(bind(&BaseApp::handleAppSizeChange, this, placeholders::_1)); - ScreenLayout::getInstance()->setup(settings->mDisplaySize, settings->mDisplayRows, settings->mDisplayColumns); + ScreenLayout::getInstance()->setup(settings->mDisplaySize, settings->mDisplayRows, settings->mDisplayColumns, settings->mBezelDims); ScreenCamera::getInstance()->setup(ScreenLayout::getInstance()); ScreenCamera::getInstance()->getViewportChangedSignal().connect(bind(&BaseApp::handleViewportChange, this, placeholders::_1)); diff --git a/src/bluecadet/core/ScreenLayout.cpp b/src/bluecadet/core/ScreenLayout.cpp index 0f08600..aed256f 100644 --- a/src/bluecadet/core/ScreenLayout.cpp +++ b/src/bluecadet/core/ScreenLayout.cpp @@ -20,10 +20,11 @@ ScreenLayout::ScreenLayout() : ScreenLayout::~ScreenLayout() { } -void ScreenLayout::setup(const ci::ivec2& dislaySize, const int numRows, const int numColumns) { +void ScreenLayout::setup(const ci::ivec2& dislaySize, const int numRows, const int numColumns, const ci::ivec2 bezel) { mDisplaySize = dislaySize; mNumRows = numRows; mNumColumns = numColumns; + mBezelDims = bezel; updateLayout(); } @@ -38,7 +39,7 @@ void ScreenLayout::updateLayout() { } } - mAppSize = mDisplaySize * ivec2(mNumColumns, mNumRows); + mAppSize = mDisplaySize * ivec2(mNumColumns, mNumRows) + mBezelDims * ivec2(mNumColumns - 1, mNumRows - 1); mAppSizeChanged.emit(mAppSize); } @@ -47,11 +48,15 @@ Rectf ScreenLayout::getDisplayBounds(const int displayId) { } Rectf ScreenLayout::getDisplayBounds(const int row, const int col) { + + ivec2 addBezel = mBezelDims * ivec2(col, row); + return Rectf( - (float)(col * mDisplaySize.x), - (float)(row * mDisplaySize.y), - (float)((col + 1) * mDisplaySize.x), - (float)((row + 1) * mDisplaySize.y)); + (float)(col * mDisplaySize.x + addBezel.x), + (float)(row * mDisplaySize.y + addBezel.y), + (float)((col + 1) * mDisplaySize.x + addBezel.x), + (float)((row + 1) * mDisplaySize.y + addBezel.y)); + } void ScreenLayout::draw() { diff --git a/src/bluecadet/core/ScreenLayout.h b/src/bluecadet/core/ScreenLayout.h index ed42eed..bcb1ac3 100644 --- a/src/bluecadet/core/ScreenLayout.h +++ b/src/bluecadet/core/ScreenLayout.h @@ -32,7 +32,7 @@ class ScreenLayout { //! Must be called before calling draw. Adds a key-up event listener. - void setup(const ci::ivec2& dislaySize = ci::app::getWindowSize(), const int numRows = 1, const int numColumns = 1); + void setup(const ci::ivec2& dislaySize = ci::app::getWindowSize(), const int numRows = 1, const int numColumns = 1, const ci::ivec2 bezel = ci::ivec2(0,0)); //! Draws the current screen layout, transformed appropriately to match the position and scale of rootView void draw(); @@ -62,6 +62,9 @@ class ScreenLayout { int getNumColumns() const { return mNumColumns; }; void setNumColumns(const int numColumns) { mNumColumns = numColumns; updateLayout(); }; + //! The amount of bezel correction added between displays + const ci::ivec2 & getBezelDims() const { return mBezelDims; }; + void setBezelDims(const ci::ivec2 bezel) { mBezelDims = bezel; updateLayout(); }; //! Helper to retrieve a display id from a row/col. Ids start at 0 and increment in right-to-left, top-to-bottom sequence. @@ -104,6 +107,7 @@ class ScreenLayout { int mNumRows; int mNumColumns; + ci::ivec2 mBezelDims; ci::ivec2 mDisplaySize; ci::ivec2 mAppSize; diff --git a/src/bluecadet/core/SettingsManager.cpp b/src/bluecadet/core/SettingsManager.cpp index 596ef5e..2b2ce0d 100644 --- a/src/bluecadet/core/SettingsManager.cpp +++ b/src/bluecadet/core/SettingsManager.cpp @@ -69,6 +69,14 @@ void SettingsManager::setup(ci::app::App::Settings * appSettings, ci::fs::path j mWindowSize = ivec2(stoi(wStr), stoi(hStr)); } }); + addCommandLineParser("bezel", [&](const string &value) { + int commaIndex = (int)value.find(","); + if (commaIndex != string::npos) { + string xStr = value.substr(0, commaIndex); + string yStr = value.substr(commaIndex + 1, value.size() - commaIndex - 1); + mBezelDims = ivec2(stoi(xStr), stoi(yStr)); + } + }); addCommandLineParser("offset", [&](const string &value) { int commaIndex = (int)value.find(","); if (commaIndex != string::npos) { @@ -93,6 +101,8 @@ void SettingsManager::parseJson(ci::JsonTree & json) { setFieldFromJsonIfExists(&mDisplaySize.y, "settings.display.size.y"); setFieldFromJsonIfExists(&mDisplayColumns, "settings.display.columns"); setFieldFromJsonIfExists(&mDisplayRows, "settings.display.rows"); + setFieldFromJsonIfExists(&mBezelDims.x, "settings.display.bezel.x"); + setFieldFromJsonIfExists(&mBezelDims.y, "settings.display.bezel.y"); // Window setFieldFromJsonIfExists(&mFps, "settings.window.fps"); diff --git a/src/bluecadet/core/SettingsManager.h b/src/bluecadet/core/SettingsManager.h index 32dd94e..525e1c9 100644 --- a/src/bluecadet/core/SettingsManager.h +++ b/src/bluecadet/core/SettingsManager.h @@ -81,6 +81,7 @@ class SettingsManager { ci::ivec2 mDisplaySize = ci::ivec2(-1, -1); //! The size of one display. Defaults to getWindowSize() int mDisplayColumns = 1; //! The number of display columns in a display matrix. Use by ScreenLayout class. int mDisplayRows = 1; //! The number of display rows in a display matrix. Use by ScreenLayout class. + ci::ivec2 mBezelDims = ci::ivec2(0, 0); //! The amount of bezel correction to add in both X and Y // Window ci::ivec2 mWindowSize; //! The window size on launch From 170799410d4be039f4f391c8baeadd87bf89c597 Mon Sep 17 00:00:00 2001 From: adielfernandez Date: Tue, 14 Nov 2017 14:27:49 -0500 Subject: [PATCH 07/23] Update settings.json template with bezel arguments --- assets/settings.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/assets/settings.json b/assets/settings.json index fd0a208..8d3c240 100644 --- a/assets/settings.json +++ b/assets/settings.json @@ -7,7 +7,8 @@ "display": { "size": {"x": 1920, "y": 1080}, "columns": 1, - "rows": 1 + "rows": 1, + "bezel": {"x": 0, "y": 0} }, "window": { "fps": 60, From 0c29782b8d193dcea946af72e02617355dcfe452 Mon Sep 17 00:00:00 2001 From: adielfernandez Date: Tue, 14 Nov 2017 15:05:43 -0500 Subject: [PATCH 08/23] Fix typo in parsing json window size --- src/bluecadet/core/SettingsManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bluecadet/core/SettingsManager.cpp b/src/bluecadet/core/SettingsManager.cpp index 2b2ce0d..76c38e0 100644 --- a/src/bluecadet/core/SettingsManager.cpp +++ b/src/bluecadet/core/SettingsManager.cpp @@ -112,7 +112,7 @@ void SettingsManager::parseJson(ci::JsonTree & json) { setFieldFromJsonIfExists(&mFullscreen, "settings.window.fullscreen"); setFieldFromJsonIfExists(&mBorderless, "settings.window.borderless"); setFieldFromJsonIfExists(&mWindowSize.x, "settings.window.size.x"); - setFieldFromJsonIfExists(&mWindowSize.y, "settings.window.size.x"); + setFieldFromJsonIfExists(&mWindowSize.y, "settings.window.size.y"); setFieldFromJsonIfExists(&mCameraOffset.x, "settings.window.cameraOffset.x"); setFieldFromJsonIfExists(&mCameraOffset.y, "settings.window.cameraOffset.y"); setFieldFromJsonIfExists(&mClearColor.r, "settings.window.clearColor.r"); From 6ece5b5a327ca2672d306efef4e7bbcf4645d957 Mon Sep 17 00:00:00 2001 From: Benjamin Bojko Date: Tue, 14 Nov 2017 18:36:40 -0500 Subject: [PATCH 09/23] Added name property to BaseView; TextView now has customizable texture format --- src/bluecadet/views/BaseView.cpp | 21 ++++++---- src/bluecadet/views/BaseView.h | 19 +++++---- src/bluecadet/views/TextView.cpp | 68 ++++++++++---------------------- src/bluecadet/views/TextView.h | 61 +++++++++++++--------------- 4 files changed, 72 insertions(+), 97 deletions(-) diff --git a/src/bluecadet/views/BaseView.cpp b/src/bluecadet/views/BaseView.cpp index dd787d5..b6f774e 100644 --- a/src/bluecadet/views/BaseView.cpp +++ b/src/bluecadet/views/BaseView.cpp @@ -52,7 +52,8 @@ BaseView::BaseView() : mParent(nullptr), mViewId(sNumInstances++), - mViewIdStr(to_string(mViewId)) + mViewIdStr(to_string(mViewId)), + mName(mViewIdStr) { } @@ -269,17 +270,17 @@ void BaseView::updateScene(const double deltaTime) { } } -void BaseView::drawScene(const ColorA& parentTint) { +void BaseView::drawScene(const ColorA& parentDrawColor) { const bool shouldDraw = mShouldForceInvisibleDraw || (!mIsHidden && mAlpha > 0.0f); if (shouldDraw || (sDebugDrawBounds && sDebugDrawInvisibleBounds)) { validateTransforms(); validateContent(); - mDrawColor.r = mTint.value().r * parentTint.r; - mDrawColor.g = mTint.value().g * parentTint.g; - mDrawColor.b = mTint.value().b * parentTint.b; - mDrawColor.a = mAlpha.value() * parentTint.a; + mDrawColor.r = mTint.value().r * parentDrawColor.r; + mDrawColor.g = mTint.value().g * parentDrawColor.g; + mDrawColor.b = mTint.value().b * parentDrawColor.b; + mDrawColor.a = mAlpha.value() * parentDrawColor.a; gl::ScopedModelMatrix scopedModelMatrix; gl::ScopedViewMatrix scopedViewMatrix; @@ -343,10 +344,14 @@ void BaseView::draw() { } inline void BaseView::debugDrawOutline() { + static const Font labelFont = Font("Arial", 20); + static const vec2 labelPos = vec2(0, 0); const float hue = (float)mViewId / (float)sNumInstances; - const auto color = ColorAf(ci::hsvToRgb(vec3(hue, 1.0f, 1.0f)), 0.66f); - gl::color(color); + const ColorA color(ci::hsvToRgb(vec3(hue, 1.0f, 1.0f)), 0.9f); + gl::ScopedColor scopedColor(color); + gl::ScopedLineWidth lineWidth(1.0f); gl::drawStrokedRect(Rectf(vec2(0), getSize())); + gl::drawString(mName, labelPos, color, labelFont); } //================================================== diff --git a/src/bluecadet/views/BaseView.h b/src/bluecadet/views/BaseView.h index 2c15abd..4436842 100644 --- a/src/bluecadet/views/BaseView.h +++ b/src/bluecadet/views/BaseView.h @@ -94,7 +94,7 @@ class BaseView : public std::enable_shared_from_this { virtual void updateScene(double deltaTime); //! Applies tint color, alpha and matrices and then draws itself and all children. Validates transforms internally. - virtual void drawScene(const ci::ColorA& parentTint = ci::ColorA(1.0f, 1.0f, 1.0, 1.0f)) final; + virtual void drawScene(const ci::ColorA& parentDrawColor = ci::ColorA(1.0f, 1.0f, 1.0, 1.0f)) final; //! Used for all internal animations ci::TimelineRef getTimeline(); @@ -225,7 +225,7 @@ class BaseView : public std::enable_shared_from_this { //! Defaults to inherit (doesn't change the blend mode). BlendMode getBlendMode() const { return mBlendMode; } - void setBlendMode(const BlendMode value) { mBlendMode = value; } + virtual void setBlendMode(const BlendMode value) { mBlendMode = value; } //! Disables drawing; Update calls are not affected; Defaults to false virtual bool isHidden() const { return mIsHidden; } @@ -247,6 +247,10 @@ class BaseView : public std::enable_shared_from_this { const size_t getViewId() const { return mViewId; } const std::string & getViewIdStr() const { return mViewIdStr; } + //! Custom name that can be assigned to view and used for debugging; Defaults to view id string. + const std::string & getName() const { return mName; } + void setName(const std::string & name) { mName = name; } + //================================================== // Coordinate space conversions @@ -312,11 +316,11 @@ class BaseView : public std::enable_shared_from_this { inline virtual void willDraw() {} //! Called by drawScene before draw() virtual void draw(); //! Called by drawScene and allows for drawing content for this node. By default draws a rectangle with the current size and background color (only if x/y /bg-alpha > 0) virtual void debugDrawOutline(); //! Called in DEBUG if sDebugDrawBounds is set to true. - inline virtual void drawChildren(const ci::ColorA& parentTint); //! Called by drawScene() after draw() and before didDraw(). Implemented at bottom of class. + inline virtual void drawChildren(const ci::ColorA & parentDrawColor); //! Called by drawScene() after draw() and before didDraw(). Implemented at bottom of class. inline virtual void didDraw() {} //! Called by drawScene after draw() - inline virtual void didMoveToView(BaseView* parent) {} //! Called when moved to a parent - inline virtual void willMoveFromView(BaseView* parent) {} //! Called when removed from a parent + inline virtual void didMoveToView(BaseView * parent) {} //! Called when moved to a parent + inline virtual void willMoveFromView(BaseView * parent) {} //! Called when removed from a parent const ci::ColorA& getDrawColor() const { return mDrawColor; } //! The color used for drawing, which is a composite of the alpha and tint colors. @@ -379,6 +383,7 @@ class BaseView : public std::enable_shared_from_this { // Misc const size_t mViewId; const std::string mViewIdStr; + std::string mName; std::map mUserInfo; @@ -390,9 +395,9 @@ class BaseView : public std::enable_shared_from_this { // Inline implementations to improve speed on frequently used methods // -void BaseView::drawChildren(const ci::ColorA& parentTint) { +void BaseView::drawChildren(const ci::ColorA& parentDrawColor) { for (auto child : mChildren) { - child->drawScene(parentTint); + child->drawScene(parentDrawColor); } } diff --git a/src/bluecadet/views/TextView.cpp b/src/bluecadet/views/TextView.cpp index fd2eb88..9fd14de 100644 --- a/src/bluecadet/views/TextView.cpp +++ b/src/bluecadet/views/TextView.cpp @@ -11,59 +11,23 @@ using namespace std; namespace bluecadet { namespace views { -TextView::TextView() : BaseView(), bluecadet::text::StyledTextLayout(), -mTextureFormat(getDefaultTextureFormat()), +TextView::TextView(const ci::gl::Texture::Format & textureFormat) : BaseView(), text::StyledTextLayout(), +mTextureFormat(textureFormat), mTexture(nullptr), -mAutoRenderEnabled(true), -mPremultiplied(false) +mAutoRenderEnabled(true) { } TextView::~TextView() { } -TextViewRef TextView::create(const std::string& text, const std::string& styleKey, const bool parseText, const float maxWidth) { - auto textView = make_shared(); - textView->setup(text, styleKey, parseText, maxWidth); - return textView; -} - -TextViewRef TextView::create(const std::wstring& text, const std::string& styleKey, const bool parseText, const float maxWidth) { - auto textView = make_shared(); - textView->setup(text, styleKey, parseText, maxWidth); - return textView; -} - -const ci::gl::Texture::Format & TextView::getDefaultTextureFormat() { - static gl::Texture::Format format; - static bool initialized = false; - - if (!initialized) { - format.immutableStorage(true); - format.setMaxAnisotropy(4.0f); - format.enableMipmapping(false); - format.setMaxMipmapLevel(0); - format.setMinFilter(GL_LINEAR); - format.setMagFilter(GL_LINEAR); - initialized = true; - } - - return format; -} - -const ci::gl::Texture::Format & TextView::getMipMapTextureFormat() { - static gl::Texture::Format format; - static bool initialized = false; - - if (!initialized) { - format.immutableStorage(true); - format.setMaxAnisotropy(4.0f); - format.enableMipmapping(true); - format.setMinFilter(GL_LINEAR_MIPMAP_LINEAR); - format.setMagFilter(GL_LINEAR); - initialized = true; - } - +ci::gl::Texture::Format TextView::getDefaultTextureFormat() { + gl::Texture::Format format; + format.immutableStorage(true); + format.setMaxAnisotropy(4.0f); + format.enableMipmapping(true); + format.setMinFilter(GL_LINEAR); + format.setMagFilter(GL_LINEAR); return format; } @@ -93,12 +57,13 @@ void TextView::reset() { void TextView::willDraw() { if (needsToBeRendered(false) && mAutoRenderEnabled) { - renderContent(false, true, mPremultiplied); + renderContent(false, true, getBlendMode() == BlendMode::PREMULT); } } void TextView::draw() { BaseView::draw(); + if (mTexture) { gl::draw(mTexture); } @@ -117,7 +82,7 @@ void TextView::renderContent(bool surfaceOnly, bool alpha, bool premultiplied, b } if (mHasInvalidRenderedContent || hasChanges() || (mSurface.getSize() != getTextSize()) || (mTexture && mSurface.getSize() != mTexture->getSize())) { - mSurface = renderToSurface(alpha, premultiplied); + mSurface = renderToSurface(alpha, premultiplied, getBackgroundColor().value()); } if (surfaceOnly) { @@ -158,6 +123,13 @@ inline void TextView::setHeight(const float height){ setMaxHeight(height); } +void TextView::setBlendMode(BlendMode blendMode) { + if (blendMode != getBlendMode()) { + invalidate(false, true); + } + BaseView::setBlendMode(blendMode); +} + const ci::vec2 TextView::getSize() { const vec2 maxSize = StyledTextLayout::getMaxSize(); const vec2 textSize = StyledTextLayout::getTextSize(); diff --git a/src/bluecadet/views/TextView.h b/src/bluecadet/views/TextView.h index 2580330..f14747c 100644 --- a/src/bluecadet/views/TextView.h +++ b/src/bluecadet/views/TextView.h @@ -28,56 +28,49 @@ typedef std::shared_ptr TextViewRef; class TextView : public BaseView, public text::StyledTextLayout { public: - TextView(); + TextView(const ci::gl::Texture::Format & textureFormat = getDefaultTextureFormat()); virtual ~TextView(); - //! Creates a TextViewRef instance. Convenience method that groups a few calls together. - static TextViewRef create(const std::string& text = "", const std::string& styleKey = "", const bool parseText = true, const float maxWidth = -1.0f); - static TextViewRef create(const std::wstring& text = L"", const std::string& styleKey = "", const bool parseText = true, const float maxWidth = -1.0f); - - static const ci::gl::Texture::Format & getDefaultTextureFormat(); //! Default format used for rendering. Optimized for 100% scale. No mip-mapping. - static const ci::gl::Texture::Format & getMipMapTextureFormat(); //! MipMapped format optimized for scaling, but with slightly lower quality at 100%. + static ci::gl::Texture::Format getDefaultTextureFormat(); //! Configures a TextView instance. Convenience method that groups a few calls together. - void setup(const std::wstring& text = L"", const std::string& styleKey = "", const bool parseText = true, const float maxWidth = -1.0f); - void setup(const std::string& text = "", const std::string& styleKey = "", const bool parseText = true, const float maxWidth = -1.0f); + void setup(const std::wstring& text = L"", const std::string& styleKey = "", const bool parseText = true, const float maxWidth = -1.0f); + void setup(const std::string& text = "", const std::string& styleKey = "", const bool parseText = true, const float maxWidth = -1.0f); - void reset() override; + void reset() override; //! Use these methods for more granular rendering control. Textures will otherwise automatically be rendered if necessary when draw() is called. - bool getAutoRenderEnabled() const { return mAutoRenderEnabled; } - void setAutoRenderEnabled(const bool value) { mAutoRenderEnabled = value; } + bool getAutoRenderEnabled() const { return mAutoRenderEnabled; } + void setAutoRenderEnabled(const bool value) { mAutoRenderEnabled = value; } - bool needsToBeRendered(bool surfaceOnly = false) const; + bool needsToBeRendered(bool surfaceOnly = false) const; //! Renders content. If surfaceOnly is false this will render into a texture and has to be called on the main thread. Surfaces can be rendered on a worker thread. - void renderContent(bool surfaceOnly = false, bool alpha = true, bool premultiplied = false, bool force = false); - void resetRenderedContent(); - - //! The format used for the texture. Setting this will force a re-render of the texture. Defaults to TextView::getDefaultTextureFormat(). - void setTextureFormat(const ci::gl::Texture::Format value) { mTextureFormat = value; mHasInvalidRenderedContent = true; } - ci::gl::Texture::Format getTextureFormat() const { return mTextureFormat; } - - //! Use premultiplied alpha or not. Defaults to false. - bool getPremultiplied() const { return mPremultiplied; } - void setPremultiplied(const bool value) { mPremultiplied = value; mHasInvalidRenderedContent = true; } + void renderContent(bool surfaceOnly = false, bool alpha = true, bool premultiplied = false, bool force = false); + void resetRenderedContent(); + void setBlendMode(BlendMode blendMode) override; //! Sets a fixed size for the text view. Any values below 0 will allow the text view to automatically expand in that direction. - inline void setSize(const ci::vec2& size) override; - inline void setWidth(const float width) override; - inline void setHeight(const float height) override; + inline void setSize(const ci::vec2& size) override; + inline void setWidth(const float width) override; + inline void setHeight(const float height) override; + //! Returns the actual size of the text including padding. //! In advanced use-cases this can differ from what was set in setSize(), e.g. if a special clip mode is set or size-trimming is enabled. - inline const ci::vec2 getSize() override; + inline const ci::vec2 getSize() override; + + //! The texture format used to create textures. + void setTextureFormat(const ci::gl::Texture::Format & value) { mTextureFormat = value; } + const ci::gl::Texture::Format & getTextureFormat() const { return mTextureFormat; } protected: //! Will update the text texture if necessary. - void willDraw() override; - void draw() override; + void willDraw() override; + void draw() override; - inline void invalidate(const bool layout = true, const bool size = true) override; + inline void invalidate(const bool layout = true, const bool size = true) override; // Change visibility of these methods from public to protected since setSize()/getSize() should be used. const ci::vec2 & getMaxSize() const override { return StyledTextLayout::getMaxSize(); }; @@ -88,11 +81,11 @@ class TextView : public BaseView, public text::StyledTextLayout { void setMaxHeight(const float value) override { return StyledTextLayout::setMaxHeight(value); }; bool mHasInvalidRenderedContent; - bool mAutoRenderEnabled; - bool mPremultiplied; + bool mSmoothScalingEnabled = true; + bool mAutoRenderEnabled = true; - ci::Surface mSurface; - ci::gl::TextureRef mTexture; + ci::Surface mSurface; + ci::gl::TextureRef mTexture; ci::gl::Texture::Format mTextureFormat; }; From b06fd40ae4175f67dca6209ad1ab204464d18737 Mon Sep 17 00:00:00 2001 From: Benjamin Bojko Date: Tue, 14 Nov 2017 18:40:28 -0500 Subject: [PATCH 10/23] Fixed override discrepancy --- src/bluecadet/views/TextView.cpp | 15 +++++++-------- src/bluecadet/views/TextView.h | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/bluecadet/views/TextView.cpp b/src/bluecadet/views/TextView.cpp index 9fd14de..2e7baf4 100644 --- a/src/bluecadet/views/TextView.cpp +++ b/src/bluecadet/views/TextView.cpp @@ -14,8 +14,7 @@ namespace views { TextView::TextView(const ci::gl::Texture::Format & textureFormat) : BaseView(), text::StyledTextLayout(), mTextureFormat(textureFormat), mTexture(nullptr), -mAutoRenderEnabled(true) -{ +mAutoRenderEnabled(true) { } TextView::~TextView() { @@ -31,7 +30,7 @@ ci::gl::Texture::Format TextView::getDefaultTextureFormat() { return format; } -void TextView::setup(const std::wstring& text, const std::string& styleKey, const bool parseText, const float maxWidth) { +void TextView::setup(const std::wstring & text, const std::string & styleKey, const bool parseText, const float maxWidth) { setMaxWidth(maxWidth); if (text.empty()) { @@ -45,7 +44,7 @@ void TextView::setup(const std::wstring& text, const std::string& styleKey, cons } } -void TextView::setup(const std::string& text, const std::string& styleKey, const bool parseText, const float maxWidth) { +void TextView::setup(const std::string & text, const std::string & styleKey, const bool parseText, const float maxWidth) { setup(text::wideString(text), styleKey, parseText, maxWidth); } @@ -108,22 +107,22 @@ void TextView::resetRenderedContent() { mSurface = ci::Surface(); } -void TextView::setSize(const ci::vec2& size) { +void TextView::setSize(const ci::vec2 & size) { invalidate(); setMaxSize(size); } -inline void TextView::setWidth(const float width){ +inline void TextView::setWidth(const float width) { invalidate(); setMaxWidth(width); } -inline void TextView::setHeight(const float height){ +inline void TextView::setHeight(const float height) { invalidate(); setMaxHeight(height); } -void TextView::setBlendMode(BlendMode blendMode) { +void TextView::setBlendMode(const BlendMode blendMode) { if (blendMode != getBlendMode()) { invalidate(false, true); } diff --git a/src/bluecadet/views/TextView.h b/src/bluecadet/views/TextView.h index f14747c..e097d99 100644 --- a/src/bluecadet/views/TextView.h +++ b/src/bluecadet/views/TextView.h @@ -48,7 +48,7 @@ class TextView : public BaseView, public text::StyledTextLayout { //! Renders content. If surfaceOnly is false this will render into a texture and has to be called on the main thread. Surfaces can be rendered on a worker thread. void renderContent(bool surfaceOnly = false, bool alpha = true, bool premultiplied = false, bool force = false); void resetRenderedContent(); - void setBlendMode(BlendMode blendMode) override; + void setBlendMode(const BlendMode blendMode) override; //! Sets a fixed size for the text view. Any values below 0 will allow the text view to automatically expand in that direction. inline void setSize(const ci::vec2& size) override; From 4becf9d4ee4be55e05be138b2ae158a69edce76e Mon Sep 17 00:00:00 2001 From: adielfernandez Date: Wed, 15 Nov 2017 11:47:49 -0500 Subject: [PATCH 11/23] Add bezel compensation to MiniMap --- src/bluecadet/core/BaseApp.cpp | 3 ++- src/bluecadet/views/MiniMapView.cpp | 19 ++++++++++++++----- src/bluecadet/views/MiniMapView.h | 3 ++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/bluecadet/core/BaseApp.cpp b/src/bluecadet/core/BaseApp.cpp index ebc76dd..659ae33 100644 --- a/src/bluecadet/core/BaseApp.cpp +++ b/src/bluecadet/core/BaseApp.cpp @@ -188,7 +188,8 @@ void BaseApp::handleAppSizeChange(const ci::ivec2 & appSize) { mMiniMap->setLayout( ScreenLayout::getInstance()->getNumColumns(), ScreenLayout::getInstance()->getNumRows(), - ScreenLayout::getInstance()->getDisplaySize() + ScreenLayout::getInstance()->getDisplaySize(), + ScreenLayout::getInstance()->getBezelDims() ); } diff --git a/src/bluecadet/views/MiniMapView.cpp b/src/bluecadet/views/MiniMapView.cpp index 33e663a..cec358d 100644 --- a/src/bluecadet/views/MiniMapView.cpp +++ b/src/bluecadet/views/MiniMapView.cpp @@ -12,6 +12,7 @@ MiniMapView::MiniMapView(const float mapScale) : mCols(0), mRows(0), mDisplaySize(0), + mBezelDims(0), mMapScale(mapScale), mViewportView(new BaseView()), mBorderColor(ColorA(1, 1, 1, 0.75f)) @@ -25,12 +26,13 @@ MiniMapView::MiniMapView(const float mapScale) : MiniMapView::~MiniMapView() { } -void MiniMapView::setLayout(const int cols, const int rows, const ci::ivec2 & displaySize) { +void MiniMapView::setLayout(const int cols, const int rows, const ci::ivec2 & displaySize, const ci::ivec2 bezel) { mCols = cols; mRows = rows; mDisplaySize = displaySize; + mBezelDims = bezel; - mAppSize = mDisplaySize * ivec2(mCols, mRows); + mAppSize = mDisplaySize * ivec2(mCols, mRows) + mBezelDims * ivec2(mCols - 1, mRows - 1); mScaledSize = ivec2(round(vec2(mAppSize) * mMapScale)); setSize(vec2(mScaledSize)); @@ -69,6 +71,7 @@ void MiniMapView::updateContent() { mGlsl->uniform("uAppSize", vec2(mAppSize)); mGlsl->uniform("uScaledSize", vec2(mScaledSize)); mGlsl->uniform("uDisplaySize", vec2(mDisplaySize)); + mGlsl->uniform("uBezelDims", vec2(mBezelDims)); mGlsl->uniform("uBorderColor", mBorderColor); mBatch->draw(); @@ -96,6 +99,7 @@ void MiniMapView::setupShaders() { uniform vec2 uAppSize; uniform vec2 uScaledSize; uniform vec2 uDisplaySize; + uniform vec2 uBezelDims; uniform vec4 uBackgroundColor; uniform vec4 uBorderColor; in vec2 vAppPosition; @@ -103,10 +107,15 @@ void MiniMapView::setupShaders() { void main(void) { vec2 scale = uScaledSize / uAppSize; - vec2 edgeDist = abs(mod(vAppPosition, uDisplaySize)) * scale; + vec2 edgeDist = abs(mod(vAppPosition, uDisplaySize + uBezelDims)) * scale; + vec2 scaledDisplay = uDisplaySize * scale; - if (edgeDist.x <= 1.0 || edgeDist.x >= uDisplaySize.x * scale.x - 1.0 || - edgeDist.y <= 1.0 || edgeDist.y >= uDisplaySize.y * scale.y - 1.0) { + bool bIsLeftEdge = edgeDist.x <= 1.0 && edgeDist.y <= scaledDisplay.y; + bool bIsTopEdge = edgeDist.y <= 1.0 && edgeDist.x <= scaledDisplay.x; + bool bIsRightEdge = edgeDist.x >= scaledDisplay.x - 1.0 && edgeDist.x <= scaledDisplay.x && edgeDist.y <= scaledDisplay.y; + bool bIsBottomEdge = edgeDist.y >= scaledDisplay.y - 1.0 && edgeDist.y <= scaledDisplay.y && edgeDist.x <= scaledDisplay.x; + + if ( bIsLeftEdge || bIsRightEdge || bIsTopEdge || bIsBottomEdge) { oColor = uBorderColor; } else { discard; diff --git a/src/bluecadet/views/MiniMapView.h b/src/bluecadet/views/MiniMapView.h index 2e8ddbe..9fae4b6 100644 --- a/src/bluecadet/views/MiniMapView.h +++ b/src/bluecadet/views/MiniMapView.h @@ -19,7 +19,7 @@ class MiniMapView : public BaseView { MiniMapView(const float mapScale = 0.05f); virtual ~MiniMapView(); - void setLayout(const int cols, const int rows, const ci::ivec2 & displaySize); + void setLayout(const int cols, const int rows, const ci::ivec2 & displaySize, const ci::ivec2 bezel); void setViewport(const ci::Area & viewport); //! Defaults to white @@ -39,6 +39,7 @@ class MiniMapView : public BaseView { int mCols; int mRows; ci::ivec2 mDisplaySize; + ci::ivec2 mBezelDims; ci::ivec2 mAppSize; ci::ivec2 mScaledSize; From ea286b22da15b8e8029aee4dd5f147306dbbdb91 Mon Sep 17 00:00:00 2001 From: shi-weili Date: Thu, 30 Nov 2017 14:10:16 -0500 Subject: [PATCH 12/23] Make sure callbacks are called asynchronously. --- src/bluecadet/views/AnimatedView.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/bluecadet/views/AnimatedView.cpp b/src/bluecadet/views/AnimatedView.cpp index fe8d796..9c211bb 100644 --- a/src/bluecadet/views/AnimatedView.cpp +++ b/src/bluecadet/views/AnimatedView.cpp @@ -85,7 +85,9 @@ void AnimatedView::animateOn(const Options & options, CallbackFn callback) { mCueOn->getSignalCallback().connect(callback); } else { // this can happen if willAnimateOn cancels the animation - callback(false); + App::get()->dispatchAsync([=] { + callback(false); + }); } } } @@ -134,7 +136,9 @@ void AnimatedView::animateOff(const Options & options, CallbackFn callback) { } else { // this can happen if willAnimateOff cancels the animation - callback(false); + App::get()->dispatchAsync([=] { + callback(false); + }); } } } From e4abce124374446a32b9f33052c6df185d191161 Mon Sep 17 00:00:00 2001 From: shi-weili Date: Thu, 30 Nov 2017 14:23:14 -0500 Subject: [PATCH 13/23] Emit callback signals asynchorounsly. --- src/bluecadet/views/AnimatedView.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/bluecadet/views/AnimatedView.cpp b/src/bluecadet/views/AnimatedView.cpp index 9c211bb..3fad1ee 100644 --- a/src/bluecadet/views/AnimatedView.cpp +++ b/src/bluecadet/views/AnimatedView.cpp @@ -15,14 +15,18 @@ namespace views { AnimatedView::CallbackCue::CallbackCue(CallbackFn callback, float time) : ci::Cue([=] { - mSignalCallback.emit(true); // success + App::get()->dispatchAsync([=] { + mSignalCallback.emit(true); // success + }); }, time) { addCallback(callback); } AnimatedView::CallbackCue::~CallbackCue() { if (!isComplete()) { - mSignalCallback.emit(false); // failure + App::get()->dispatchAsync([=] { + mSignalCallback.emit(false); // failure + }); } } From a0355a4d6319389bef352536cb0d48de1c452696 Mon Sep 17 00:00:00 2001 From: Benjamin Bojko Date: Thu, 30 Nov 2017 14:58:39 -0500 Subject: [PATCH 14/23] Added better premult support to ImageView --- src/bluecadet/views/ImageView.cpp | 123 ++++++++++++++++++++---------- src/bluecadet/views/ImageView.h | 21 ++--- 2 files changed, 93 insertions(+), 51 deletions(-) diff --git a/src/bluecadet/views/ImageView.cpp b/src/bluecadet/views/ImageView.cpp index 4f5a990..19f3654 100644 --- a/src/bluecadet/views/ImageView.cpp +++ b/src/bluecadet/views/ImageView.cpp @@ -8,9 +8,12 @@ using namespace std; namespace bluecadet { namespace views { +ImageView::ScaleMode ImageView::sDefaultScaleMode = ImageView::ScaleMode::STRETCH; + ImageView::ImageView() : BaseView(), mTexture(nullptr), -mScaleMode(ScaleMode::NONE) +mTextureScale(1.0f), +mScaleMode(sDefaultScaleMode) { } @@ -19,26 +22,8 @@ ImageView::~ImageView() { void ImageView::reset() { BaseView::reset(); - clearTexture(); -} - -void ImageView::clearTexture() { - mTexture = nullptr; - mDrawingDestRect = Rectf(); - mDrawingArea = Area(); - mScaleMode = ScaleMode::NONE; -} - -void ImageView::setup(const gl::TextureRef texture, const ci::vec2 &size, const ScaleMode scaleMode) { - const bool resizeToTexture = size.x == 0 && size.y == 0; - - setScaleMode(scaleMode); - - setTexture(texture, resizeToTexture); - - if (!resizeToTexture) { - setSize(size); - } + setTexture(nullptr); + setScaleMode(sDefaultScaleMode); } void ImageView::setTexture(ci::gl::TextureRef texture, const bool resizeToTexture) { @@ -57,38 +42,92 @@ void ImageView::setTexture(ci::gl::TextureRef texture, const bool resizeToTextur invalidate(false, true); } -void ImageView::setSize(const ci::vec2& size) { - BaseView::setSize(size); - - mDrawingDestRect = Rectf(vec2(0), size); +void ImageView::validateContent() { + BaseView::validateContent(); - if (mTexture) { - // Aspect fill drawing area - mDrawingArea = Area(mDrawingDestRect.getCenteredFit(mTexture->getBounds(), true)); - } else { - mDrawingArea = Area(); - } -} + mTextureScale = vec2(1.0f); -void ImageView::draw() { - if (!mTexture) return; - - BaseView::draw(); - switch (mScaleMode) { case ScaleMode::NONE: - gl::draw(mTexture); + mTextureScale = vec2(1.0f); + mTextureSize = mTexture->getSize(); break; case ScaleMode::STRETCH: - gl::draw(mTexture, mDrawingDestRect); + mTextureScale = vec2(1.0f); + mTextureSize = getSize(); break; case ScaleMode::FIT: - gl::draw(mTexture, Rectf(mTexture->getBounds()).getCenteredFit(mDrawingDestRect, true)); - break; case ScaleMode::COVER: - gl::draw(mTexture, mDrawingArea, mDrawingDestRect); + { + mTextureSize = getSize(); + mTextureScale = mTextureSize / vec2(mTexture->getSize()); + if (mScaleMode == ScaleMode::FIT) { + mTextureScale /= glm::min(mTextureScale.x, mTextureScale.y); + } else { + mTextureScale /= glm::max(mTextureScale.x, mTextureScale.y); + } break; + } + } +} + +void ImageView::draw() { + if (!mTexture) return; + + BaseView::draw(); + + static gl::GlslProgRef shader = nullptr; + static gl::BatchRef batch = nullptr; + + if (!shader) { + shader = gl::GlslProg::create(gl::GlslProg::Format() + .vertex(CI_GLSL(150, + uniform mat4 ciModelViewProjection; + uniform vec2 uSize; + in vec4 ciPosition; + in vec4 ciColor; + in vec2 ciTexCoord0; + out vec4 vColor; + out vec2 vTexCoord0; + + void main(void) { + vColor = ciColor; + vTexCoord0 = ciTexCoord0; + vec4 pos = ciPosition * vec4(uSize, 0, 1); + gl_Position = ciModelViewProjection * pos; + } + )).fragment(CI_GLSL(150, + uniform sampler2D uTex0; + uniform vec2 uTexScale; + uniform int uPremult; + in vec2 vTexCoord0; + in vec4 vColor; + out vec4 oColor; + + void main(void) { + vec2 texCoord = vec2(vTexCoord0.x, 1.0 - vTexCoord0.y); + texCoord = (texCoord - vec2(0.5)) * uTexScale + vec2(0.5); + + if (texCoord.x < 0 || texCoord.y < 0 || texCoord.x > 1.0 || texCoord.y > 1.0) { + discard; + } + + oColor = texture(uTex0, texCoord); + oColor.rgb = mix(oColor.rgb, oColor.rgb / oColor.a, uPremult); + oColor *= vColor; + } + ))); + + batch = gl::Batch::create(geom::Rect().rect(Rectf(0, 0, 1.0f, 1.0f)), shader); } + + gl::ScopedBlendAlpha scopedBlend; + + mTexture->bind(0); + shader->uniform("uTexScale", mTextureScale); + shader->uniform("uSize", mTextureSize); + shader->uniform("uPremult", getBlendMode() == BlendMode::PREMULT ? 1 : 0); + batch->draw(); } } diff --git a/src/bluecadet/views/ImageView.h b/src/bluecadet/views/ImageView.h index beaceb8..9cdbbdf 100644 --- a/src/bluecadet/views/ImageView.h +++ b/src/bluecadet/views/ImageView.h @@ -32,25 +32,28 @@ class ImageView : public BaseView { virtual ~ImageView(); void reset() override; - virtual void clearTexture(); - - virtual void setup(const ci::gl::TextureRef texture, const ci::vec2& size = ci::vec2(0), const ScaleMode scaleMode = ScaleMode::COVER); - - virtual void setSize(const ci::vec2& size) override; inline ci::gl::TextureRef getTexture() const { return mTexture; } inline void setTexture(const ci::gl::TextureRef value, const bool resizeToTexture = true); + //! Defaults to getDefaultScaleMode() inline ScaleMode getScaleMode() const { return mScaleMode; } - inline void setScaleMode(const ScaleMode scaleMode) { mScaleMode = scaleMode; } + inline void setScaleMode(const ScaleMode scaleMode) { mScaleMode = scaleMode; invalidate(false, true); } + + //! Defaults to STRETCH + static ScaleMode getDefaultScaleMode() { return sDefaultScaleMode; } + static void setDefaultScaleMode(const ScaleMode scaleMode) { sDefaultScaleMode = scaleMode; } private: - virtual void draw() override; + void draw() override; + void validateContent() override; + + static ScaleMode sDefaultScaleMode; ci::gl::TextureRef mTexture; - ci::Rectf mDrawingDestRect; - ci::Area mDrawingArea; + ci::vec2 mTextureScale; + ci::vec2 mTextureSize; ScaleMode mScaleMode; }; From a0a4e1744ae87810baee16273740a8cbe7d299ff Mon Sep 17 00:00:00 2001 From: Benjamin Bojko Date: Thu, 30 Nov 2017 15:19:08 -0500 Subject: [PATCH 15/23] Minor clean up --- src/bluecadet/views/TouchView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bluecadet/views/TouchView.cpp b/src/bluecadet/views/TouchView.cpp index a7fbf26..3736682 100644 --- a/src/bluecadet/views/TouchView.cpp +++ b/src/bluecadet/views/TouchView.cpp @@ -220,7 +220,7 @@ bool TouchView::containsPoint(const vec2 &point) { } bool TouchView::canAcceptTouch(const bluecadet::touch::Touch & touch) const { - return (mMultiTouchEnabled || mTouchIds.empty()) && (getAlphaConst().value() > mMinAlphaForTouches); + return (mMultiTouchEnabled || mTouchIds.empty()) && (getAlphaConst() > mMinAlphaForTouches); } bool TouchView::isHandlingTouch(const int touchId) const { From 81badbecbddab3fd82a54aa3de97a1c0f0dadf9b Mon Sep 17 00:00:00 2001 From: Benjamin Bojko Date: Thu, 30 Nov 2017 15:19:44 -0500 Subject: [PATCH 16/23] Added getBounds() to BaseView; Added crosshair for pos to debug outline --- src/bluecadet/views/BaseView.cpp | 5 ++++- src/bluecadet/views/BaseView.h | 14 ++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/bluecadet/views/BaseView.cpp b/src/bluecadet/views/BaseView.cpp index b6f774e..ccf2992 100644 --- a/src/bluecadet/views/BaseView.cpp +++ b/src/bluecadet/views/BaseView.cpp @@ -346,11 +346,14 @@ void BaseView::draw() { inline void BaseView::debugDrawOutline() { static const Font labelFont = Font("Arial", 20); static const vec2 labelPos = vec2(0, 0); + static const float crosshairRadius = 5.0f; const float hue = (float)mViewId / (float)sNumInstances; const ColorA color(ci::hsvToRgb(vec3(hue, 1.0f, 1.0f)), 0.9f); gl::ScopedColor scopedColor(color); gl::ScopedLineWidth lineWidth(1.0f); - gl::drawStrokedRect(Rectf(vec2(0), getSize())); + gl::drawStrokedRect(getBounds(false).getOffset(-getPosition())); + gl::drawLine(vec2(-crosshairRadius, -crosshairRadius), vec2(crosshairRadius, crosshairRadius)); + gl::drawLine(vec2(-crosshairRadius, crosshairRadius), vec2(crosshairRadius, -crosshairRadius)); gl::drawString(mName, labelPos, color, labelFont); } diff --git a/src/bluecadet/views/BaseView.h b/src/bluecadet/views/BaseView.h index 4436842..ac396b0 100644 --- a/src/bluecadet/views/BaseView.h +++ b/src/bluecadet/views/BaseView.h @@ -162,7 +162,8 @@ class BaseView : public std::enable_shared_from_this { virtual const size_t getNumChildren() const { return mChildren.size(); } //! Local position relative to parent view - virtual ci::Anim& getPosition() { return mPosition; } + virtual ci::Anim & getPosition() { return mPosition; } + virtual const ci::vec2 & getPositionConst() const { return mPosition.value(); } virtual void setPosition(const ci::vec2& position) { mPosition = position; invalidate(); } virtual void setPosition(const ci::vec3& position) { mPosition = ci::vec2(position.x, position.y); invalidate(); } @@ -173,13 +174,15 @@ class BaseView : public std::enable_shared_from_this { virtual ci::vec2 getCenter() { return getPosition().value() + 0.5f * getSize(); } //! Local scale relative to parent view - virtual ci::Anim& getScale() { return mScale; } + virtual ci::Anim & getScale() { return mScale; } + virtual const ci::vec2 & getScaleConst() const { return mScale.value(); } virtual void setScale(const float& scale) { mScale = ci::vec2(scale, scale); invalidate(); } virtual void setScale(const ci::vec2& scale) { mScale = scale; invalidate(); } virtual void setScale(const ci::vec3& scale) { mScale = ci::vec2(scale.x, scale.y); invalidate(); } //! Local rotation relative to parent view. Changing this value invalidates transforms. - virtual ci::Anim& getRotation() { return mRotation; } + virtual ci::Anim & getRotation() { return mRotation; } + virtual const ci::quat & getRotationConst() { return mRotation.value(); } virtual float getRotationZ() const { return glm::roll(mRotation.value()); } virtual void setRotation(const float radians) { mRotation = glm::angleAxis(radians, ci::vec3(0, 0, 1)); invalidate(); } virtual void setRotation(const ci::quat& rotation) { mRotation = rotation; invalidate(); } @@ -206,6 +209,9 @@ class BaseView : public std::enable_shared_from_this { virtual float getHeight() { return getSize().y; } virtual void setHeight(const float height) { ci::vec2 s = getSize(); setSize(ci::vec2(s.x, height)); } + //! Combined size and position in parent coordinate space. Set scaled to true to multiply size by scale. Does not include rotation. + virtual ci::Rectf getBounds(const bool scaled = false) { return ci::Rectf(getPositionConst(), getPositionConst() + (scaled ? getScaleConst() * getSize() : getSize())); } + //! The fill color used when drawing the bounding rect when a size greater than 0, 0 is given. virtual ci::Anim& getBackgroundColor() { return mBackgroundColor; } virtual void setBackgroundColor(const ci::Color color) { mBackgroundColor = ci::ColorA(color, 1.0f); invalidate(false, true); } //! Sets background color with 100% alpha @@ -221,7 +227,7 @@ class BaseView : public std::enable_shared_from_this { virtual void setAlpha(const float alpha) { mAlpha = alpha; } //! Returns a constant reference of getAlpha(). Allows for const access. - virtual const ci::Anim& getAlphaConst() const { return mAlpha; } + virtual float getAlphaConst() const { return mAlpha; } //! Defaults to inherit (doesn't change the blend mode). BlendMode getBlendMode() const { return mBlendMode; } From 344f08f0548520101a2f0076be2314ac873d7f7a Mon Sep 17 00:00:00 2001 From: Benjamin Bojko Date: Thu, 30 Nov 2017 15:23:40 -0500 Subject: [PATCH 17/23] Commented out deprecated JSON fields --- src/bluecadet/core/SettingsManager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bluecadet/core/SettingsManager.cpp b/src/bluecadet/core/SettingsManager.cpp index 76c38e0..ec83f0a 100644 --- a/src/bluecadet/core/SettingsManager.cpp +++ b/src/bluecadet/core/SettingsManager.cpp @@ -92,7 +92,7 @@ void SettingsManager::setup(ci::app::App::Settings * appSettings, ci::fs::path j void SettingsManager::parseJson(ci::JsonTree & json) { // General - setFieldFromJsonIfExists(&mConsole, "settings.general.consoleWindowEnabled"); + //setFieldFromJsonIfExists(&mConsole, "settings.general.consoleWindowEnabled"); setFieldFromJsonIfExists(&mConsole, "settings.general.console"); setFieldFromJsonIfExists(&mAppVersion, "settings.general.version"); @@ -107,7 +107,7 @@ void SettingsManager::parseJson(ci::JsonTree & json) { // Window setFieldFromJsonIfExists(&mFps, "settings.window.fps"); setFieldFromJsonIfExists(&mFps, "settings.window.FPS"); - setFieldFromJsonIfExists(&mVerticalSync, "settings.window.verticalSync"); + //setFieldFromJsonIfExists(&mVerticalSync, "settings.window.verticalSync"); setFieldFromJsonIfExists(&mVerticalSync, "settings.window.vsync"); setFieldFromJsonIfExists(&mFullscreen, "settings.window.fullscreen"); setFieldFromJsonIfExists(&mBorderless, "settings.window.borderless"); @@ -126,13 +126,13 @@ void SettingsManager::parseJson(ci::JsonTree & json) { setFieldFromJsonIfExists(&mNativeTouchEnabled, "settings.touch.native"); // Debug - setFieldFromJsonIfExists(&mDebugEnabled, "settings.debug.debugMode"); + //setFieldFromJsonIfExists(&mDebugEnabled, "settings.debug.debugMode"); setFieldFromJsonIfExists(&mDebugEnabled, "settings.debug.debugEnabled"); setFieldFromJsonIfExists(&mShowStats, "settings.debug.showStats"); setFieldFromJsonIfExists(&mShowMinimap, "settings.debug.showMinimap"); setFieldFromJsonIfExists(&mShowTouches, "settings.debug.showTouches"); setFieldFromJsonIfExists(&mShowScreenLayout, "settings.debug.showScreenLayout"); - setFieldFromJsonIfExists(&mShowCursor, "settings.debug.showMouse"); + //setFieldFromJsonIfExists(&mShowCursor, "settings.debug.showMouse"); setFieldFromJsonIfExists(&mShowCursor, "settings.debug.showCursor"); setFieldFromJsonIfExists(&mMinimizeParams, "settings.debug.minimizeParams"); setFieldFromJsonIfExists(&mCollapseParams, "settings.debug.collapseParams"); From 26709b990cc827f021a9a3d7c0f237587e3a288b Mon Sep 17 00:00:00 2001 From: Benjamin Bojko Date: Thu, 30 Nov 2017 15:25:08 -0500 Subject: [PATCH 18/23] Implemented new bounds calculations for circular views --- src/bluecadet/views/ArcView.cpp | 7 ------- src/bluecadet/views/ArcView.h | 8 +++++++- src/bluecadet/views/EllipseView.cpp | 23 ++++++----------------- src/bluecadet/views/EllipseView.h | 8 +++++++- src/bluecadet/views/StrokedCircleView.cpp | 17 +++++++---------- src/bluecadet/views/StrokedCircleView.h | 8 +++++++- 6 files changed, 34 insertions(+), 37 deletions(-) diff --git a/src/bluecadet/views/ArcView.cpp b/src/bluecadet/views/ArcView.cpp index 1b338dd..9921a6b 100644 --- a/src/bluecadet/views/ArcView.cpp +++ b/src/bluecadet/views/ArcView.cpp @@ -60,13 +60,6 @@ void ArcView::draw() { batch->draw(); } -void ArcView::debugDrawOutline() { - gl::ScopedModelMatrix scopedModelMatrix; - gl::ScopedViewMatrix scopedViewMatrix; - gl::translate(-getSize() * 0.5f); - BaseView::debugDrawOutline(); -} - ci::gl::BatchRef ArcView::getSharedBatch() { static ci::gl::BatchRef batch = nullptr; if (!batch) { diff --git a/src/bluecadet/views/ArcView.h b/src/bluecadet/views/ArcView.h index 7243e8f..f000baf 100644 --- a/src/bluecadet/views/ArcView.h +++ b/src/bluecadet/views/ArcView.h @@ -42,10 +42,16 @@ class ArcView : public BaseView { //! Cancels ArcView animations in addition to BaseView animations. void cancelAnimations() override; + //! Arc bounds extend -outerRadius to +outerRadius both for x and y + ci::Rectf getBounds(const bool scaled) override { + ci::Rectf bounds = BaseView::getBounds(scaled); + bounds.offset(-0.5f * bounds.getSize()); + return bounds; + } + protected: void update(const double deltaTime) override; void draw() override; - void debugDrawOutline() override; static ci::gl::BatchRef getSharedBatch(); static ci::gl::GlslProgRef getSharedProg(); diff --git a/src/bluecadet/views/EllipseView.cpp b/src/bluecadet/views/EllipseView.cpp index 22c4c0b..63a1a30 100644 --- a/src/bluecadet/views/EllipseView.cpp +++ b/src/bluecadet/views/EllipseView.cpp @@ -49,15 +49,6 @@ void EllipseView::draw() { batch->draw(); } -void EllipseView::debugDrawOutline() { - gl::ScopedModelMatrix scopedModelMatrix; - gl::ScopedViewMatrix scopedViewMatrix; - - gl::translate(-getSize() * 0.5f); - - BaseView::debugDrawOutline(); -} - ci::gl::BatchRef EllipseView::getSharedEllipseBatch() { static ci::gl::BatchRef batch = nullptr; if (!batch) { @@ -101,7 +92,10 @@ ci::gl::GlslProgRef EllipseView::getSharedEllipseProg() { void main(void) { vec2 normalizedDelta = normPosition.xy * 2.0f - vec2(1.0f); float normalizedRadiusSq = normalizedDelta.x * normalizedDelta.x + normalizedDelta.y * normalizedDelta.y; - if (normalizedRadiusSq > 1.0f) discard; + + if (normalizedRadiusSq > 1.0f) { + discard; + } float normalizedRadius = sqrt(normalizedRadiusSq); float maxRadius = length(uSize) * 0.5f; @@ -111,16 +105,11 @@ ci::gl::GlslProgRef EllipseView::getSharedEllipseProg() { oColor = color; // interpolate smooth edge - if (uSmoothness > 0 && radius > minRadius) { - float quota = (maxRadius - radius) / uSmoothness; - oColor.w = color.w * smoothstep(0.0f, 1.0f, quota); - } + float quota = uSmoothness == 0 ? 0 : (maxRadius - radius) / uSmoothness; + oColor.w = color.w * smoothstep(0.0f, 1.0f, quota); } )) ); - prog->uniform("uSize", vec2(0)); - prog->uniform("uSmoothness", 1.0f); - prog->uniform("uBackgroundColor", vec4(0)); } return prog; } diff --git a/src/bluecadet/views/EllipseView.h b/src/bluecadet/views/EllipseView.h index 8e7afae..12d7a6d 100644 --- a/src/bluecadet/views/EllipseView.h +++ b/src/bluecadet/views/EllipseView.h @@ -27,13 +27,19 @@ class EllipseView : public BaseView { //! Shorthand for calling setSize(vec2(2.0f * radius)) void setRadius(const float radius); + //! Ellipse bounds extend -radius to +radius both for x and y + ci::Rectf getBounds(const bool scaled) override { + ci::Rectf bounds = BaseView::getBounds(scaled); + bounds.offset(-0.5f * bounds.getSize()); + return bounds; + } + //! The smoothness of the ellipse's edge ci::Anim & getSmoothness() { return mSmoothness; } void setSmoothness(const float value) { mSmoothness = value; invalidate(false, true); } protected: virtual void draw() override; - virtual void debugDrawOutline() override; static ci::gl::BatchRef getSharedEllipseBatch(); static ci::gl::GlslProgRef getSharedEllipseProg(); diff --git a/src/bluecadet/views/StrokedCircleView.cpp b/src/bluecadet/views/StrokedCircleView.cpp index 85ee9df..c37b2be 100644 --- a/src/bluecadet/views/StrokedCircleView.cpp +++ b/src/bluecadet/views/StrokedCircleView.cpp @@ -39,24 +39,18 @@ void StrokedCircleView::draw() { auto batch = getSharedBatch(); auto prog = batch->getGlslProg(); + gl::ScopedBlendAlpha scopedBlend; + prog->uniform("uSize", getSize()); prog->uniform("uStrokeColor", strokeColor); prog->uniform("uBackgroundColor", backgroundColor); prog->uniform("uSmoothness", mSmoothness); prog->uniform("uStrokeWidth", mStrokeWidth); + prog->uniform("uPremult", getBlendMode() == BlendMode::PREMULT ? 1 : 0); batch->draw(); } -void StrokedCircleView::debugDrawOutline() { - gl::ScopedModelMatrix scopedModelMatrix; - gl::ScopedViewMatrix scopedViewMatrix; - - gl::translate(-getSize() * 0.5f); - - BaseView::debugDrawOutline(); -} - ci::gl::BatchRef StrokedCircleView::getSharedBatch() { static ci::gl::BatchRef batch = nullptr; if (!batch) { @@ -94,6 +88,7 @@ ci::gl::GlslProgRef StrokedCircleView::getSharedProg() { uniform float uStrokeWidth; uniform vec4 uStrokeColor; uniform vec4 uBackgroundColor; + uniform int uPremult; //in vec4 vNormPosition; in vec4 vAbsPosition; @@ -128,9 +123,11 @@ ci::gl::GlslProgRef StrokedCircleView::getSharedProg() { // interpolate smooth edge float quota = (radiusC - radius) / uSmoothness; float smoothQuota = smoothstep(1.0f, 0.0f, quota); - oColor = mix(uBackgroundColor, uStrokeColor, smoothQuota); + oColor = mix(uBackgroundColor, oColor, smoothQuota); } + oColor.rgb = mix(oColor.rgb, oColor.rgb / oColor.a, uPremult); + if (oColor.a <= 0) { discard; } diff --git a/src/bluecadet/views/StrokedCircleView.h b/src/bluecadet/views/StrokedCircleView.h index 37935aa..24bb905 100644 --- a/src/bluecadet/views/StrokedCircleView.h +++ b/src/bluecadet/views/StrokedCircleView.h @@ -34,9 +34,15 @@ class StrokedCircleView : public BaseView { inline ci::Anim & getStrokeColor() { return mStrokeColor; } inline void setStrokeColor(ci::ColorA value) { mStrokeColor = value; invalidate(false, true); } + //! Circle bounds extend -radius to +radius both for x and y + ci::Rectf getBounds(const bool scaled) override { + ci::Rectf bounds = BaseView::getBounds(scaled); + bounds.offset(-0.5f * bounds.getSize()); + return bounds; + } + protected: virtual void draw() override; - virtual void debugDrawOutline() override; static ci::gl::BatchRef getSharedBatch(); static ci::gl::GlslProgRef getSharedProg(); From 2de908f844191bb2ce7b41c9548669a3b0eb2bf1 Mon Sep 17 00:00:00 2001 From: shi-weili Date: Thu, 30 Nov 2017 16:10:28 -0500 Subject: [PATCH 19/23] Fix asynchonous callback bug; make callback asynchronism optional. --- src/bluecadet/views/AnimatedView.cpp | 80 ++++++++++++++++++---------- src/bluecadet/views/AnimatedView.h | 10 ++-- 2 files changed, 57 insertions(+), 33 deletions(-) diff --git a/src/bluecadet/views/AnimatedView.cpp b/src/bluecadet/views/AnimatedView.cpp index 3fad1ee..5b394ac 100644 --- a/src/bluecadet/views/AnimatedView.cpp +++ b/src/bluecadet/views/AnimatedView.cpp @@ -15,21 +15,21 @@ namespace views { AnimatedView::CallbackCue::CallbackCue(CallbackFn callback, float time) : ci::Cue([=] { - App::get()->dispatchAsync([=] { - mSignalCallback.emit(true); // success - }); + mSignalCallback.emit(true); // success }, time) { addCallback(callback); } AnimatedView::CallbackCue::~CallbackCue() { if (!isComplete()) { - App::get()->dispatchAsync([=] { - mSignalCallback.emit(false); // failure - }); + mSignalCallback.emit(false); // canceled } } +inline void AnimatedView::CallbackCue::addCallback(CallbackFn callback) { + mConnections += mSignalCallback.connect(callback); +} + //================================================== // Main Class // @@ -45,16 +45,30 @@ AnimatedView::AnimatedView(bool showInitially) : AnimatedView::~AnimatedView() { } -void AnimatedView::animateOn(const Options & options, CallbackFn callback) { +void AnimatedView::animateOn(const Options & options, CallbackFn callback, const bool isCallbackAsync) { mIsInitialized = true; // override initial state + CallbackFn wrappedCallback = nullptr; + + if (callback) { + if (isCallbackAsync) { + wrappedCallback = [=] (bool completed) { + App::get()->dispatchAsync([=] { + if (callback) { + callback(completed); + } + }); + }; + } else { + wrappedCallback = callback; + } + } + if (mIsShowing && mShouldShow) { // already showing; dispatch on next frame - App::get()->dispatchAsync([=] { - if (callback) { - callback(true); - } - }); + if (wrappedCallback) { + wrappedCallback(true); + } return; } @@ -83,29 +97,41 @@ void AnimatedView::animateOn(const Options & options, CallbackFn callback) { mSignalWillAnimateOn.emit(); } - if (callback) { + if (wrappedCallback) { if (mCueOn) { // add callback (multiple callbacks are possible) - mCueOn->getSignalCallback().connect(callback); + mCueOn->getSignalCallback().connect(wrappedCallback); } else { // this can happen if willAnimateOn cancels the animation - App::get()->dispatchAsync([=] { - callback(false); - }); + wrappedCallback(false); } } } -void AnimatedView::animateOff(const Options & options, CallbackFn callback) { +void AnimatedView::animateOff(const Options & options, CallbackFn callback, const bool isCallbackAsync) { mIsInitialized = true; // override initial state + CallbackFn wrappedCallback = nullptr; + + if (callback) { + if (isCallbackAsync) { + wrappedCallback = [=] (bool completed) { + App::get()->dispatchAsync([=] { + if (callback) { + callback(completed); + } + }); + }; + } else { + wrappedCallback = callback; + } + } + if (!mIsShowing && !mShouldShow) { // already hidden; dispatch on next frame - App::get()->dispatchAsync([=] { - if (callback) { - callback(true); - } - }); + if (wrappedCallback) { + wrappedCallback(true); + } return; } @@ -133,16 +159,14 @@ void AnimatedView::animateOff(const Options & options, CallbackFn callback) { mSignalWillAnimateOff.emit(); } - if (callback) { + if (wrappedCallback) { if (mCueOff) { // add callback (multiple callbacks are possible) - mCueOff->getSignalCallback().connect(callback); + mCueOff->getSignalCallback().connect(wrappedCallback); } else { // this can happen if willAnimateOff cancels the animation - App::get()->dispatchAsync([=] { - callback(false); - }); + wrappedCallback(false); } } } diff --git a/src/bluecadet/views/AnimatedView.h b/src/bluecadet/views/AnimatedView.h index 74f51d9..013d977 100644 --- a/src/bluecadet/views/AnimatedView.h +++ b/src/bluecadet/views/AnimatedView.h @@ -65,7 +65,7 @@ class AnimatedView : public BaseView { ~CallbackCue(); //! Adds a single callback to the list - inline void addCallback(CallbackFn callback) { mConnections += mSignalCallback.connect(callback); } + inline void addCallback(CallbackFn callback); //! Removes callbacks without triggering them inline void removeAllCallbacks() { mConnections.clear(); } @@ -88,16 +88,16 @@ class AnimatedView : public BaseView { //! Animate this view on. - void animateOn(const Options & options, CallbackFn callback = nullptr); + void animateOn(const Options & options, CallbackFn callback = nullptr, const bool isCallbackAsync = true); //! Animate this view off. - void animateOff(const Options & options, CallbackFn callback = nullptr); + void animateOff(const Options & options, CallbackFn callback = nullptr, const bool isCallbackAsync = true); //! Shortcut to animateOn() with default options. - void animateOn(CallbackFn callback = nullptr) { animateOn(mDefaultOptions, callback); }; + void animateOn(CallbackFn callback = nullptr, const bool isCallbackAsync = true) { animateOn(mDefaultOptions, callback, isCallbackAsync); }; //! Shortcut to animateOff() with default options. - void animateOff(CallbackFn callback = nullptr) { animateOff(mDefaultOptions, callback); }; + void animateOff(CallbackFn callback = nullptr, const bool isCallbackAsync = true) { animateOff(mDefaultOptions, callback, isCallbackAsync); }; //! Same as animating on with a duration of 0. From bef8817faa0455d90ca4e0a933ae8e1233ca336b Mon Sep 17 00:00:00 2001 From: Benjamin Bojko Date: Thu, 30 Nov 2017 16:59:40 -0500 Subject: [PATCH 20/23] Simplified image and ellipse premult --- .../ViewTypesSample/src/ViewTypesSampleApp.cpp | 5 +++-- src/bluecadet/views/EllipseView.cpp | 18 +++++++++--------- src/bluecadet/views/ImageView.cpp | 6 +----- src/bluecadet/views/StrokedCircleView.cpp | 9 +++------ 4 files changed, 16 insertions(+), 22 deletions(-) diff --git a/samples/ViewTypesSample/src/ViewTypesSampleApp.cpp b/samples/ViewTypesSample/src/ViewTypesSampleApp.cpp index 1d6d91f..6ffcb72 100644 --- a/samples/ViewTypesSample/src/ViewTypesSampleApp.cpp +++ b/samples/ViewTypesSample/src/ViewTypesSampleApp.cpp @@ -51,6 +51,8 @@ void ViewTypesSampleApp::prepareSettings(ci::app::App::Settings* settings) { void ViewTypesSampleApp::setup() { BaseApp::setup(); + getRootView()->setBackgroundColor(Color::gray(0.5f)); + //================================================== // Most basic view // @@ -176,8 +178,6 @@ void ViewTypesSampleApp::setup() { addViewSample(dragView, "TouchView with y drag"); } - getRootView()->setBackgroundColor(Color::gray(0.5f)); - //================================================== // FBO // @@ -278,6 +278,7 @@ void ViewTypesSampleApp::addViewSample(BaseViewRef view, std::string label) { container->setSize(cellSize); container->setPosition(cellPos); container->setBackgroundColor(Color::black()); + //container->setBackgroundColor(Color(1, 1, 0)); getRootView()->addChild(container); vec2 viewOffset = view->getPosition(); diff --git a/src/bluecadet/views/EllipseView.cpp b/src/bluecadet/views/EllipseView.cpp index 63a1a30..72c6698 100644 --- a/src/bluecadet/views/EllipseView.cpp +++ b/src/bluecadet/views/EllipseView.cpp @@ -69,12 +69,12 @@ ci::gl::GlslProgRef EllipseView::getSharedEllipseProg() { in vec4 ciPosition; in vec4 ciColor; - out vec4 color; - out vec4 normPosition; + out vec4 vColor; + out vec4 vNormPosition; void main(void) { - color = ciColor * uBackgroundColor; - normPosition = ciPosition; + vColor = ciColor * uBackgroundColor; + vNormPosition = ciPosition; gl_Position = ciModelViewProjection * vec4( ciPosition.x * uSize.x - uSize.x * 0.5f, ciPosition.y * uSize.y - uSize.y * 0.5f, @@ -85,12 +85,12 @@ ci::gl::GlslProgRef EllipseView::getSharedEllipseProg() { uniform vec2 uSize; uniform float uSmoothness; - in vec4 normPosition; - in vec4 color; + in vec4 vNormPosition; + in vec4 vColor; out vec4 oColor; void main(void) { - vec2 normalizedDelta = normPosition.xy * 2.0f - vec2(1.0f); + vec2 normalizedDelta = vNormPosition.xy * 2.0f - vec2(1.0f); float normalizedRadiusSq = normalizedDelta.x * normalizedDelta.x + normalizedDelta.y * normalizedDelta.y; if (normalizedRadiusSq > 1.0f) { @@ -102,11 +102,11 @@ ci::gl::GlslProgRef EllipseView::getSharedEllipseProg() { float minRadius = max(0, maxRadius - uSmoothness); float radius = maxRadius * normalizedRadius; - oColor = color; + oColor = vColor; // interpolate smooth edge float quota = uSmoothness == 0 ? 0 : (maxRadius - radius) / uSmoothness; - oColor.w = color.w * smoothstep(0.0f, 1.0f, quota); + oColor.a = vColor.a * smoothstep(0.0f, 1.0f, quota); } )) ); diff --git a/src/bluecadet/views/ImageView.cpp b/src/bluecadet/views/ImageView.cpp index 19f3654..62d442c 100644 --- a/src/bluecadet/views/ImageView.cpp +++ b/src/bluecadet/views/ImageView.cpp @@ -113,20 +113,16 @@ void ImageView::draw() { } oColor = texture(uTex0, texCoord); - oColor.rgb = mix(oColor.rgb, oColor.rgb / oColor.a, uPremult); - oColor *= vColor; + oColor.rgb /= oColor.a; } ))); batch = gl::Batch::create(geom::Rect().rect(Rectf(0, 0, 1.0f, 1.0f)), shader); } - gl::ScopedBlendAlpha scopedBlend; - mTexture->bind(0); shader->uniform("uTexScale", mTextureScale); shader->uniform("uSize", mTextureSize); - shader->uniform("uPremult", getBlendMode() == BlendMode::PREMULT ? 1 : 0); batch->draw(); } diff --git a/src/bluecadet/views/StrokedCircleView.cpp b/src/bluecadet/views/StrokedCircleView.cpp index c37b2be..9efc6be 100644 --- a/src/bluecadet/views/StrokedCircleView.cpp +++ b/src/bluecadet/views/StrokedCircleView.cpp @@ -39,14 +39,11 @@ void StrokedCircleView::draw() { auto batch = getSharedBatch(); auto prog = batch->getGlslProg(); - gl::ScopedBlendAlpha scopedBlend; - prog->uniform("uSize", getSize()); prog->uniform("uStrokeColor", strokeColor); prog->uniform("uBackgroundColor", backgroundColor); prog->uniform("uSmoothness", mSmoothness); prog->uniform("uStrokeWidth", mStrokeWidth); - prog->uniform("uPremult", getBlendMode() == BlendMode::PREMULT ? 1 : 0); batch->draw(); } @@ -88,7 +85,6 @@ ci::gl::GlslProgRef StrokedCircleView::getSharedProg() { uniform float uStrokeWidth; uniform vec4 uStrokeColor; uniform vec4 uBackgroundColor; - uniform int uPremult; //in vec4 vNormPosition; in vec4 vAbsPosition; @@ -117,7 +113,8 @@ ci::gl::GlslProgRef StrokedCircleView::getSharedProg() { if (uSmoothness > 0 && radius > radiusB) { // interpolate smooth edge float quota = (radiusA - radius) / uSmoothness; - oColor.a *= smoothstep(0.0f, 1.0f, quota); + float smoothQuota = smoothstep(0.0f, 1.0f, quota); + oColor = mix(vec4(0), oColor, smoothstep(0.0f, 1.0f, smoothQuota)); } else if (uSmoothness > 0 && radius < radiusC) { // interpolate smooth edge @@ -126,7 +123,7 @@ ci::gl::GlslProgRef StrokedCircleView::getSharedProg() { oColor = mix(uBackgroundColor, oColor, smoothQuota); } - oColor.rgb = mix(oColor.rgb, oColor.rgb / oColor.a, uPremult); + oColor.rgb /= oColor.a; if (oColor.a <= 0) { discard; From e61fd8493a1fb1f212e80ff374e550ae8116441e Mon Sep 17 00:00:00 2001 From: Benjamin Bojko Date: Thu, 30 Nov 2017 17:02:26 -0500 Subject: [PATCH 21/23] Minor clean up --- samples/ViewTypesSample/src/ViewTypesSampleApp.cpp | 1 - src/bluecadet/touch/TouchManager.cpp | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/samples/ViewTypesSample/src/ViewTypesSampleApp.cpp b/samples/ViewTypesSample/src/ViewTypesSampleApp.cpp index 6ffcb72..0fa70eb 100644 --- a/samples/ViewTypesSample/src/ViewTypesSampleApp.cpp +++ b/samples/ViewTypesSample/src/ViewTypesSampleApp.cpp @@ -278,7 +278,6 @@ void ViewTypesSampleApp::addViewSample(BaseViewRef view, std::string label) { container->setSize(cellSize); container->setPosition(cellPos); container->setBackgroundColor(Color::black()); - //container->setBackgroundColor(Color(1, 1, 0)); getRootView()->addChild(container); vec2 viewOffset = view->getPosition(); diff --git a/src/bluecadet/touch/TouchManager.cpp b/src/bluecadet/touch/TouchManager.cpp index 7170ef7..ab3a3ac 100644 --- a/src/bluecadet/touch/TouchManager.cpp +++ b/src/bluecadet/touch/TouchManager.cpp @@ -335,7 +335,7 @@ void TouchManager::debugDrawTouch(const Touch & touch, const bool isVirtual) { gl::scale(vec2(circleScale)); fboNormal->bindFramebuffer(); - gl::clear(ColorA(1 ,1, 1, 0)); + gl::clear(ColorA(1, 1, 1, 0)); { gl::ScopedColor scopedColor(ColorA(0, 0, 0, 0.5f)); @@ -349,7 +349,7 @@ void TouchManager::debugDrawTouch(const Touch & touch, const bool isVirtual) { fboNormal->unbindFramebuffer(); fboVirtual->bindFramebuffer(); - gl::clear(ColorA(1 ,1, 1, 0)); + gl::clear(ColorA(1, 1, 1, 0)); { gl::ScopedColor scopedColor(ColorA(0, 0, 0, 0.5f)); From f7755b79551544c2d0a5245a6e4c0964b809eda7 Mon Sep 17 00:00:00 2001 From: Benjamin Bojko Date: Fri, 1 Dec 2017 14:25:40 -0500 Subject: [PATCH 22/23] Made y-flipping optional and disabled by default in ImageView --- src/bluecadet/views/ImageView.cpp | 11 +++++++---- src/bluecadet/views/ImageView.h | 5 +++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/bluecadet/views/ImageView.cpp b/src/bluecadet/views/ImageView.cpp index 62d442c..1448472 100644 --- a/src/bluecadet/views/ImageView.cpp +++ b/src/bluecadet/views/ImageView.cpp @@ -13,7 +13,8 @@ ImageView::ScaleMode ImageView::sDefaultScaleMode = ImageView::ScaleMode::STRETC ImageView::ImageView() : BaseView(), mTexture(nullptr), mTextureScale(1.0f), -mScaleMode(sDefaultScaleMode) +mScaleMode(sDefaultScaleMode), +mTopDown(false) { } @@ -99,14 +100,15 @@ void ImageView::draw() { )).fragment(CI_GLSL(150, uniform sampler2D uTex0; uniform vec2 uTexScale; - uniform int uPremult; + uniform int uTopDown; in vec2 vTexCoord0; in vec4 vColor; out vec4 oColor; void main(void) { - vec2 texCoord = vec2(vTexCoord0.x, 1.0 - vTexCoord0.y); - texCoord = (texCoord - vec2(0.5)) * uTexScale + vec2(0.5); + vec2 texCoord = vTexCoord0; + texCoord.y = uTopDown != 0 ? 1.0 - texCoord.y : texCoord.y; // flip y if necessary + texCoord = (texCoord - vec2(0.5)) * uTexScale + vec2(0.5); // scale around center if (texCoord.x < 0 || texCoord.y < 0 || texCoord.x > 1.0 || texCoord.y > 1.0) { discard; @@ -123,6 +125,7 @@ void ImageView::draw() { mTexture->bind(0); shader->uniform("uTexScale", mTextureScale); shader->uniform("uSize", mTextureSize); + shader->uniform("uTopDown", mTopDown ? 1 : 0); batch->draw(); } diff --git a/src/bluecadet/views/ImageView.h b/src/bluecadet/views/ImageView.h index 9cdbbdf..675ad12 100644 --- a/src/bluecadet/views/ImageView.h +++ b/src/bluecadet/views/ImageView.h @@ -44,6 +44,10 @@ class ImageView : public BaseView { static ScaleMode getDefaultScaleMode() { return sDefaultScaleMode; } static void setDefaultScaleMode(const ScaleMode scaleMode) { sDefaultScaleMode = scaleMode; } + //! Defaults to false. Can be set independently of the texture's top-down setting in case you have less control over that. + void setTopDown(const bool value) { mTopDown = value; } + bool getTopDown() const { return mTopDown; } + private: void draw() override; @@ -55,6 +59,7 @@ class ImageView : public BaseView { ci::vec2 mTextureScale; ci::vec2 mTextureSize; ScaleMode mScaleMode; + bool mTopDown; }; } From c932770cfe24f31ad0b0e20ce355ede855a3150f Mon Sep 17 00:00:00 2001 From: Benjamin Bojko Date: Fri, 1 Dec 2017 18:14:41 -0500 Subject: [PATCH 23/23] Bumped version to 1.6.0 --- README.md | 2 +- cinderblock.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ea057ce..768774c 100644 --- a/README.md +++ b/README.md @@ -205,7 +205,7 @@ void PathView::draw() { ## Notes -Version 1.5.0 +Version 1.6.0 Built for [Cinder v0.9.2 dev](https://github.com/cinder/Cinder/) and [Cinder v0.9.1](https://github.com/cinder/Cinder/tree/v0.9.1). Samples require VS 2015 v140 toolset, but tested with VS 2013 v120 as well. diff --git a/cinderblock.xml b/cinderblock.xml index 8741dca..30ee437 100644 --- a/cinderblock.xml +++ b/cinderblock.xml @@ -7,7 +7,7 @@ author="Bluecadet" summary="Scene graph with nested transforms, events, touch/mouse delegation and app boilerplates." license="MIT" - version="1.5.0" + version="1.6.0" url="https://github.com/bluecadet/Cinder-BluecadetViews" >