diff --git a/CMakeLists.txt b/CMakeLists.txt index 7830e5d..61f2475 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,13 @@ target_compile_definitions(scratchcpp-render PRIVATE SCRATCHCPPRENDER_LIBRARY) linkQt(scratchcpp-render) +target_sources(scratchcpp-render + PUBLIC + include/scratchcpp-render/scratchcpp-render.h +) + +target_include_directories(scratchcpp-render PUBLIC include) + include(build/SetUpLibscratchcpp.cmake) target_link_libraries(scratchcpp-render PRIVATE scratchcpp) diff --git a/README.md b/README.md index 36f35b9..17bc3ae 100644 --- a/README.md +++ b/README.md @@ -114,11 +114,15 @@ Button { } ``` -Please note that the ScratchCPP renderer only works with the basic scene graph render loop. -Qt 6 uses the threaded render loop by default, so you'll have to disable it by calling this -before constructing your application object: +**The library must be initialized by the application.** +**To initialize the library, call `scratchcpprender::init()` before constructing the Q(Gui)Application object.** ```cpp -qputenv("QSG_RENDER_LOOP", "basic"); +#include +int main(int argc, char **argv) { + scratchcpprender::init(); + QApplication a(argc, argv); + ... +} ```

(back to top)

diff --git a/include/scratchcpp-render/scratchcpp-render.h b/include/scratchcpp-render/scratchcpp-render.h new file mode 100644 index 0000000..de80b15 --- /dev/null +++ b/include/scratchcpp-render/scratchcpp-render.h @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later + +#pragma once + +/*! \brief The main namespace of the library. */ +namespace scratchcpprender +{ + +/*! Initializes the library. Call this from main before constructing your Q(Gui)Application object. */ +void init(); + +} // namespace scratchcpprender diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c133a57..48d5064 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,11 +18,12 @@ qt_add_qml_module(scratchcpp-render shaders/sprite.frag icons/enter.svg SOURCES - global.h + global.h + global_functions.cpp projectloader.cpp projectloader.h - projectscene.cpp - projectscene.h + projectscene.cpp + projectscene.h stagemodel.cpp stagemodel.h spritemodel.cpp @@ -44,8 +45,8 @@ qt_add_qml_module(scratchcpp-render bitmapskin.h svgskin.cpp svgskin.h - renderedtarget.cpp - renderedtarget.h + renderedtarget.cpp + renderedtarget.h targetpainter.cpp targetpainter.h scenemousearea.cpp diff --git a/src/global_functions.cpp b/src/global_functions.cpp new file mode 100644 index 0000000..38ff464 --- /dev/null +++ b/src/global_functions.cpp @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include +#include + +void scratchcpprender::init() +{ + qputenv("QSG_RENDER_LOOP", "basic"); + QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL); +} diff --git a/src/penlayerpainter.cpp b/src/penlayerpainter.cpp index 1ef6ea0..443b4ab 100644 --- a/src/penlayerpainter.cpp +++ b/src/penlayerpainter.cpp @@ -12,10 +12,8 @@ PenLayerPainter::PenLayerPainter(QOpenGLFramebufferObject *fbo) void PenLayerPainter::paint(QNanoPainter *painter) { - if (QThread::currentThread() != qApp->thread()) { - qFatal("Error: Rendering must happen in the GUI thread to work correctly. Please disable threaded render loop using qputenv(\"QSG_RENDER_LOOP\", \"basic\") before constructing your " - "application object."); - } + if (QThread::currentThread() != qApp->thread()) + qFatal("Error: Rendering must happen in the GUI thread to work correctly. Did you initialize the library using scratchcpprender::init()?"); QOpenGLContext *context = QOpenGLContext::currentContext(); Q_ASSERT(context); diff --git a/src/targetpainter.cpp b/src/targetpainter.cpp index 5258b7f..d25b572 100644 --- a/src/targetpainter.cpp +++ b/src/targetpainter.cpp @@ -23,10 +23,8 @@ TargetPainter::~TargetPainter() void TargetPainter::paint(QNanoPainter *painter) { - if (QThread::currentThread() != qApp->thread()) { - qFatal("Error: Rendering must happen in the GUI thread to work correctly. Please disable threaded render loop using qputenv(\"QSG_RENDER_LOOP\", \"basic\") before constructing your " - "application object."); - } + if (QThread::currentThread() != qApp->thread()) + qFatal("Error: Rendering must happen in the GUI thread to work correctly. Did you initialize the library using scratchcpprender::init()?"); QOpenGLContext *context = QOpenGLContext::currentContext(); Q_ASSERT(context); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 463fd1f..dcd6bef 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -20,6 +20,7 @@ endfunction() add_subdirectory(mocks) +add_subdirectory(global_functions) add_subdirectory(projectloader) add_subdirectory(renderedtarget) add_subdirectory(targetpainter) diff --git a/test/global_functions/CMakeLists.txt b/test/global_functions/CMakeLists.txt new file mode 100644 index 0000000..fb3359d --- /dev/null +++ b/test/global_functions/CMakeLists.txt @@ -0,0 +1,15 @@ +add_executable( + global_functions_test + global_functions_test.cpp +) + +target_link_libraries( + global_functions_test + GTest::gtest_main + GTest::gmock_main + scratchcpp-render + ${QT_LIBS} +) + +add_test(global_functions_test) +gtest_discover_tests(global_functions_test) diff --git a/test/global_functions/global_functions_test.cpp b/test/global_functions/global_functions_test.cpp new file mode 100644 index 0000000..273accd --- /dev/null +++ b/test/global_functions/global_functions_test.cpp @@ -0,0 +1,14 @@ +#include +#include + +#include "../common.h" + +TEST(GlobalFunctionsTest, Init) +{ + qputenv("QSG_RENDER_LOOP", "threaded"); + QQuickWindow::setGraphicsApi(QSGRendererInterface::Software); + + scratchcpprender::init(); + ASSERT_EQ(qgetenv("QSG_RENDER_LOOP"), "basic"); + ASSERT_EQ(QQuickWindow::graphicsApi(), QSGRendererInterface::OpenGL); +}