diff --git a/.gitmodules b/.gitmodules index 7c6cfdb94..cb71c3459 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,20 +1,20 @@ [submodule "tests/harness/modules/ruisapp"] path = tests/harness/modules/ruisapp url = ../ruisapp - branch = main + branch = multiwindow # main [submodule "tests/harness/modules/ruis-render-opengl"] path = tests/harness/modules/ruis-render-opengl url = ../ruis-render-opengl - branch = main + branch = multiwindow # main [submodule "tests/harness/modules/ruis-render-opengles"] path = tests/harness/modules/ruis-render-opengles url = ../ruis-render-opengles - branch = main -[submodule "tool-configs"] - path = tool-configs - url = ../tool-configs - branch = main + branch = multiwindow # main [submodule "tests/harness/modules/ruis-render-null"] path = tests/harness/modules/ruis-render-null url = ../ruis-render-null + branch = multiwindow # main +[submodule "tool-configs"] + path = tool-configs + url = ../tool-configs branch = main diff --git a/.vscode/launch.json b/.vscode/launch.json index 2e085ddd4..2d60009b8 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,7 +5,7 @@ "version": "0.2.0", "configurations": [ { - "name": "(gdb) app", + "name": "(gdb) app-xorg", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/tests/app/out/dev/tests", @@ -15,7 +15,11 @@ "environment": [ { "name": "LD_LIBRARY_PATH", - "value": "../../src/out/dev:../harness/modules/ruisapp/src/out/rel_no_install/opengl-xorg:../harness/modules/ruis-render-opengl/src/out/rel_no_install" + "value": "../../src/out/dev:../harness/modules/ruisapp/src/out/dev/opengl-xorg:../harness/modules/ruis-render-opengl/src/out/dev" + }, + { + "name": "DYLD_LIBRARY_PATH", + "value": "../../src/out/dev:../harness/modules/ruisapp/src/out/dev/opengl:../harness/modules/ruis-render-opengl/src/out/dev" } ], "externalConsole": false, @@ -27,7 +31,57 @@ "ignoreFailures": true } ], - "preLaunchTask": "build-dev" + // "preLaunchTask": "build-dev" + }, + { + "name": "(gdb) app-wayland", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/tests/app/out/dev/tests", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}/tests/app", + "environment": [ + { + "name": "LD_LIBRARY_PATH", + "value": "../../src/out/dev:../harness/modules/ruisapp/src/out/dev/opengles-wayland:../harness/modules/ruis-render-opengles/src/out/dev" + } + ], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + // "preLaunchTask": "build-dev" + }, + { + "name": "(gdb) app-sdl", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/tests/app/out/dev/tests", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}/tests/app", + "environment": [ + { + "name": "LD_LIBRARY_PATH", + "value": "../../src/out/dev:../harness/modules/ruisapp/src/out/dev/opengl-sdl:../harness/modules/ruis-render-opengl/src/out/dev" + } + ], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + // "preLaunchTask": "build-dev" }, { "name": "(gdb) app2", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index de70b7a1b..dd9966851 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -207,6 +207,13 @@ "problemMatcher": [], "group": "build" }, + { + "label": "run-app-gl-sdl-dev", + "type": "shell", + "command": "make run-app win=sdl config=dev", + "problemMatcher": [], + "group": "build" + }, { "label": "run-app-dev", "type": "shell", diff --git a/build/android/app/CMakeLists.txt b/build/android/app/CMakeLists.txt index 3aaaf060d..391d177c0 100644 --- a/build/android/app/CMakeLists.txt +++ b/build/android/app/CMakeLists.txt @@ -12,15 +12,13 @@ file(GLOB_RECURSE srcs include (${ANDROID_GRADLE_NATIVE_BUNDLE_PLUGIN_MK}) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -DDEBUG") include_directories( ../../../src ../../../tests/harness/modules/ruisapp/src ../../../tests/harness/modules/ruis-render-opengles/src ) -#link_directories(../ruis/build/intermediates/cmake/release/obj/${ANDROID_ABI}) -#link_directories(../ruis/.cxx/Debug/4x66344r/arm64-v8a) add_library( # Specifies the name of the library. diff --git a/build/android/app/build.gradle b/build/android/app/build.gradle index e4abe2313..1b6360f31 100755 --- a/build/android/app/build.gradle +++ b/build/android/app/build.gradle @@ -55,7 +55,7 @@ dependencies { // implementation 'io.github.cppfw:png:+' // implementation 'io.github.cppfw:jpeg:+' implementation 'io.github.cppfw:freetype:+' -// implementation project(path: ':ruis') + // implementation project(path: ':ruis') } task copyResToAssets { diff --git a/build/android/app/src/main/java/io/github/cppfw/ruisapp/RuisappActivity.java b/build/android/app/src/main/java/io/github/cppfw/ruisapp/RuisappActivity.java deleted file mode 100755 index fb92e9fa6..000000000 --- a/build/android/app/src/main/java/io/github/cppfw/ruisapp/RuisappActivity.java +++ /dev/null @@ -1,117 +0,0 @@ -package io.github.cppfw.ruisapp; - -import android.app.NativeActivity; -import android.app.Service; -import android.content.Context; -import android.graphics.Rect; -import android.os.Bundle; -import android.util.DisplayMetrics; -import android.util.Log; -import android.view.Display; -import android.view.KeyCharacterMap; -import android.view.KeyEvent; -import android.view.Window; -import android.view.WindowManager; -import android.view.inputmethod.InputMethodManager; - -import java.io.IOException; - - -public class RuisappActivity extends NativeActivity { - { - System.loadLibrary("c++_shared"); - System.loadLibrary("ruisapp_application"); - } - - public static final String LOGTAG = "ruisapp java side"; - - private int curKeyDevice; - private KeyCharacterMap curCharMap; - - public int resolveKeyUnicode(int deviceID, int metaState, int keyCode){ - Log.d(LOGTAG, "resolveKeyUnicode(): invoked, keyCode = " + keyCode); - if(this.curCharMap == null || curKeyDevice != deviceID){ - try{ - this.curCharMap = KeyCharacterMap.load(deviceID); - this.curKeyDevice = deviceID; - }catch(Exception e){ - Log.e(LOGTAG, "resolveKeyUnicode(): Could not load KeyCharacterMap"); - return 0;//could not load char map, thus could not resolve character - } - } - - return this.curCharMap.get(keyCode, metaState); - } - - public float getDotsPerInch(){ - Display d = ((WindowManager)getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); - DisplayMetrics m = new DisplayMetrics(); - d.getMetrics(m); - Log.d(LOGTAG, "getDotsPerInch(): xdpi = " + m.xdpi + " ydpi = " + m.ydpi + " density = " + m.density); - return (m.xdpi + m.ydpi) / 2.0f; - } - - private static native void handleCharacterStringInput(String str); - - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - Log.d(LOGTAG, "dispatchKeyEvent(): invoked"); - if(event.getAction() == KeyEvent.ACTION_MULTIPLE && event.getKeyCode() == KeyEvent.KEYCODE_UNKNOWN){ - Log.d(LOGTAG, "dispatchKeyEvent(): multiple characters are being delivered, chars = " + event.getCharacters()); - //Multiple characters are being delivered. NativeActivity currently does not - //support passing multiple characters from KeyEvent to native code, so we need to do it here. - this.handleCharacterStringInput(event.getCharacters()); - return true; - } - return super.dispatchKeyEvent(event); - } - - //Override the Back button handler to prevent activity from automatically closing by Back key. - @Override - public void onBackPressed() { - } - - private InputMethodManager imm; - - @Override - protected void onCreate(Bundle savedInstanceState){ - super.onCreate(savedInstanceState); - - this.imm = (InputMethodManager)this.getSystemService(Service.INPUT_METHOD_SERVICE); - } - - - public void showVirtualKeyboard(){ - this.imm.showSoftInput(this.getWindow().getDecorView(), InputMethodManager.SHOW_FORCED); - Rect r = new Rect(); - this.getWindow().getDecorView().getWindowVisibleDisplayFrame(r); - Log.d(LOGTAG, "showVirtualKeyboard(): visible rect = " + r.left + ", " + r.right + ", " + r.top + ", " + r.bottom); - } - - public void hideVirtualKeyboard(){ - this.imm.hideSoftInputFromWindow(this.getWindow().getDecorView().getWindowToken(), InputMethodManager.HIDE_IMPLICIT_ONLY); - } - - public String[] listDirContents(String path){ - try { - String[] list = getAssets().list(path); - - for(int i = 0; i != list.length; ++i){ - if(getAssets().list(path + "/" + list[i]).length > 0){ - //this is a directory - list[i] += "/"; - } - } - -// Log.d(LOGTAG, "file list = " + list); - return list; - }catch (IOException e){ - Log.d(LOGTAG, e.getMessage()); - } - return null; - } - - public String getStorageDir(){ - return this.getFilesDir().getPath(); - } -} diff --git a/build/android/app/src/main/java/io/github/cppfw/ruisapp/RuisappActivity.java b/build/android/app/src/main/java/io/github/cppfw/ruisapp/RuisappActivity.java new file mode 120000 index 000000000..5fce9376a --- /dev/null +++ b/build/android/app/src/main/java/io/github/cppfw/ruisapp/RuisappActivity.java @@ -0,0 +1 @@ +../../../../../../../../../../tests/harness/modules/ruisapp/build/android/ruisapp/src/main/java/io/github/cppfw/ruisapp/RuisappActivity.java \ No newline at end of file diff --git a/build/conan/conanfile.py b/build/conan/conanfile.py index d82c04c79..b1b829d81 100644 --- a/build/conan/conanfile.py +++ b/build/conan/conanfile.py @@ -57,7 +57,7 @@ def source(self): # shallow fetch commit git.fetch_commit(url=sources["url"], commit=sources['commit']) # shallow clone submodules - git.run("submodule update --init --remote --depth 1") + git.run("submodule update --init --remote") def build(self): if self.settings.os == "Emscripten": diff --git a/build/vcpkg/test/vcpkg-configuration.json b/build/vcpkg/test/vcpkg-configuration.json index 42f6d2c85..242e5e3e3 100644 --- a/build/vcpkg/test/vcpkg-configuration.json +++ b/build/vcpkg/test/vcpkg-configuration.json @@ -8,7 +8,7 @@ { "kind": "git", "repository": "https://github.com/cppfw/vcpkg-repo/", - "baseline": "d48205c0ac1f9dec582330ec79d145cdd5905949", + "baseline": "623f683b18c6f49a18104e1c52e7d3c17f38ef92", "reference": "main", "packages": [ "myci", diff --git a/config/rel.mk b/config/rel.mk index 5668adc2a..bdc5995ac 100644 --- a/config/rel.mk +++ b/config/rel.mk @@ -1,9 +1,19 @@ include $(config_dir)base/base.mk +this_cxxflags += -O3 + # TODO: compilation with -O3 currently fails with unjustified "maybe used uninitialized" error # when building with "g++ (Debian 12.2.0-14) 12.2.0", -# have't tried it with clang++. Need to restore -O3 when GCC is fixed. -this_cxxflags += -O1 +# have't tried it with clang++. Need to remove this warning suppression when GCC is fixed. +ifeq ($(this_cxx),g++) + ifeq ($(os),macosx) + # On macos, the this_cxx can be set to g++, but it is still clang compiler, becuase + # often, on macos the g++ is symlinked to clang++. + # Thus, on macos do not suppress the warning, because it is not supported by clang. + else + this_cxxflags += -Wno-maybe-uninitialized + endif +endif # WORKAROUND: on ubuntu jammy dpkg-buildpackage passes -ffat-lto-objects compilation flag # which is not supported by clang and clang-tidy complains about it: diff --git a/src/ruis/context.cpp b/src/ruis/context.cpp index 046a21699..790ce4a52 100644 --- a/src/ruis/context.cpp +++ b/src/ruis/context.cpp @@ -25,17 +25,11 @@ along with this program. If not, see . using namespace ruis; -context::context( - utki::shared_ref style_provider, - utki::shared_ref updater, - parameters params -) : +context::context(parameters params) : post_to_ui_thread_function(std::move(params.post_to_ui_thread_function)), - style_provider(std::move(style_provider)), - res_loader(this->style_provider.get().res_loader), - renderer(this->res_loader.get().renderer), - updater(std::move(updater)), - cursor_stack(std::move(params.set_mouse_cursor_function)), + style_provider(std::move(params.style_provider)), + renderer(std::move(params.renderer)), + updater(std::move(params.updater)), localization(std::move(params.localization)), units(std::move(params.units)) { diff --git a/src/ruis/context.hpp b/src/ruis/context.hpp index 24d8e1c11..64659f975 100644 --- a/src/ruis/context.hpp +++ b/src/ruis/context.hpp @@ -26,7 +26,6 @@ along with this program. If not, see . #include "util/events.hpp" #include "util/localization.hpp" #include "util/mouse_cursor.hpp" -#include "util/mouse_cursor_stack.hpp" #include "util/units.hpp" #include "resource_loader.hpp" @@ -70,19 +69,13 @@ class context : public std::enable_shared_from_this return this->style_provider.get(); } - /** - * @brief Resource loader. - * Allows loading and managing life time of resources. - */ - const utki::shared_ref res_loader; - /** * @brief Shorthand alias for resource loader. * @return this->res_loader.get(). */ resource_loader& loader() noexcept { - return this->res_loader.get(); + return this->style().res_loader.get(); } /** @@ -104,11 +97,20 @@ class context : public std::enable_shared_from_this * @brief Shorthand alias for renderer. * @return this->renderer.get(). */ - const ruis::render::renderer& ren() const noexcept + ruis::render::renderer& ren() const noexcept { return this->renderer.get(); } + /** + * @brief Shorthand alias for native_window. + * @return The native window of this GUI context. + */ + ruis::render::native_window& window() noexcept + { + return this->ren().ctx().native_window; + } + /** * @brief Updater which updates updatables from within UI thread. * The updater calls active updatables periodically from the UI thread. @@ -116,12 +118,6 @@ class context : public std::enable_shared_from_this // potentially, updater can be shared between contexts, this is why it is shared_ref const utki::shared_ref updater; - /** - * @brief Mouse cursor stack. - * It allows changing shape of the mouse cursor. - */ - mouse_cursor_stack cursor_stack; - /** * @brief current localization. * Vocabulary of localized strings. @@ -144,22 +140,18 @@ class context : public std::enable_shared_from_this struct parameters { std::function)> post_to_ui_thread_function; - std::function set_mouse_cursor_function; - ruis::units units; + utki::shared_ref updater; + utki::shared_ref renderer; + utki::shared_ref style_provider; utki::shared_ref localization = utki::make_shared(); + ruis::units units; }; /** * @brief Constructor. - * @param style_provider - style provider to use for this context. - * @param updater - updater to use along with this context. * @param params - context parameters. */ - context( - utki::shared_ref style_provider, - utki::shared_ref updater, - parameters params - ); + context(parameters params); context(const context&) = delete; context& operator=(const context&) = delete; diff --git a/src/ruis/font/font.hpp b/src/ruis/font/font.hpp index 326febc24..59cfe5df8 100644 --- a/src/ruis/font/font.hpp +++ b/src/ruis/font/font.hpp @@ -88,7 +88,8 @@ class font * rendering. */ virtual render_result render_internal( - const ruis::matrix4& matrix, // + render::renderer& renderer, // + const ruis::matrix4& matrix, const ruis::color& color, const std::u32string_view str, unsigned tab_size, @@ -132,7 +133,8 @@ class font * @return Render result. */ render_result render( - const ruis::matrix4& matrix, // + render::renderer& renderer, // + const ruis::matrix4& matrix, const ruis::color& color, const std::u32string_view str, unsigned tab_size = 4, @@ -140,7 +142,8 @@ class font ) const { return this->render_internal( - matrix, // + renderer, // + matrix, color, str, tab_size, @@ -160,7 +163,8 @@ class font * @return Render result. */ render_result render( - const ruis::matrix4& matrix, // + render::renderer& renderer, // + const ruis::matrix4& matrix, const ruis::color& color, utki::utf8_iterator str, unsigned tab_size = 4, @@ -168,7 +172,8 @@ class font ) const { return this->render( - matrix, // + renderer, // + matrix, color, utki::to_utf32(str), tab_size, @@ -188,6 +193,7 @@ class font * @return Render result. */ render_result render( + render::renderer& renderer, // const ruis::matrix4& matrix, // const ruis::color& color, const char* str, @@ -196,9 +202,12 @@ class font ) const { return this->render( - matrix, // + renderer, // + matrix, color, - utki::utf8_iterator(str) + utki::utf8_iterator(str), + tab_size, + offset ); } @@ -214,17 +223,19 @@ class font * @return Redner result. */ render_result render( + render::renderer& renderer, // const ruis::matrix4& matrix, // const ruis::color& color, - const std::string& str, + std::string_view str, unsigned tab_size = 4, size_t offset = std::numeric_limits::max() ) const { return this->render( - matrix, // + renderer, // + matrix, color, - str.c_str(), + utki::utf8_iterator(str), tab_size, offset ); diff --git a/src/ruis/font/texture_font.cpp b/src/ruis/font/texture_font.cpp index 76adc7c09..1e59ac30b 100644 --- a/src/ruis/font/texture_font.cpp +++ b/src/ruis/font/texture_font.cpp @@ -173,19 +173,19 @@ texture_font::glyph texture_font::load_glyph(char32_t c) const g.top_left = ftg.vertices[0]; g.bottom_right = ftg.vertices[2]; - auto& r = this->renderer.get(); + auto& rc = this->rendering_context.get(); // clang-format off - g.vao = r.render_context.get().make_vertex_array( + g.vao = rc.make_vertex_array( { - r.render_context.get().make_vertex_buffer(utki::make_span(ftg.vertices)), - this->renderer.get().obj().quad_01_vbo + rc.make_vertex_buffer(utki::make_span(ftg.vertices)), + this->common_rendering_objects.get().quad_01_vbo }, - this->renderer.get().obj().quad_fan_indices, + this->common_rendering_objects.get().quad_fan_indices, render::vertex_array::mode::triangle_fan ).to_shared_ptr(); - g.tex = this->renderer.get().render_context.get().make_texture_2d( + g.tex = rc.make_texture_2d( std::move(ftg.image), { .min_filter = render::texture_2d::filter::nearest, @@ -199,15 +199,16 @@ texture_font::glyph texture_font::load_glyph(char32_t c) const } texture_font::texture_font( - utki::shared_ref renderer, - // NOLINTNEXTLINE(modernize-pass-by-value) - const utki::shared_ref& face, + utki::shared_ref rendering_context, // + utki::shared_ref common_rendering_objects, + utki::shared_ref face, unsigned font_size, unsigned max_cached ) : - renderer(std::move(renderer)), + rendering_context(std::move(rendering_context)), + common_rendering_objects(std::move(common_rendering_objects)), font_size(font_size), - face(face), + face(std::move(face)), max_cached(max_cached) { // TRACE(<< "texture_font::Load(): enter" << std::endl) @@ -253,7 +254,8 @@ const texture_font::glyph& texture_font::get_glyph(char32_t c) const } real texture_font::render_glyph_internal( - const ruis::matrix4& matrix, // + render::renderer& renderer, // + const ruis::matrix4& matrix, const ruis::color& color, char32_t ch ) const @@ -263,7 +265,7 @@ real texture_font::render_glyph_internal( // texture can be null for glyph of empty characters, like space, tab etc... if (g.tex) { ASSERT(g.vao) - this->renderer.get().shaders().color_pos_tex_alpha->render( + renderer.shaders().color_pos_tex_alpha->render( matrix, // *g.vao, color, @@ -337,6 +339,7 @@ ruis::rect texture_font::get_bounding_box_internal(std::u32string_view str, unsi } font::render_result texture_font::render_internal( + render::renderer& renderer, // const ruis::matrix4& matrix, const ruis::color& color, const std::u32string_view str, @@ -350,7 +353,7 @@ font::render_result texture_font::render_internal( return ret; } - this->renderer.get().render_context.get().set_simple_alpha_blending(); + renderer.rendering_context.get().set_simple_alpha_blending(); ruis::matrix4 matr(matrix); @@ -374,7 +377,12 @@ font::render_result texture_font::render_internal( cur_offset += actual_tab_size; return advance; } else { // all other characters - auto advance = this->render_glyph_internal(matr, color, c); + auto advance = this->render_glyph_internal( + renderer, // + matr, + color, + c + ); ++ret.length; ++cur_offset; return advance; diff --git a/src/ruis/font/texture_font.hxx b/src/ruis/font/texture_font.hxx index 84a8a0a52..d3074dc15 100644 --- a/src/ruis/font/texture_font.hxx +++ b/src/ruis/font/texture_font.hxx @@ -104,7 +104,8 @@ public: */ class texture_font : public font { - const utki::shared_ref renderer; + const utki::shared_ref rendering_context; + const utki::shared_ref common_rendering_objects; const unsigned font_size; @@ -142,17 +143,22 @@ public: * @param max_cached - maximum number of glyphs to cache. */ texture_font( - utki::shared_ref renderer, - const utki::shared_ref& face, + utki::shared_ref rendering_context, // + utki::shared_ref common_rendering_objects, + utki::shared_ref face, unsigned font_size, unsigned max_cached ); - real get_advance(char32_t c, unsigned tab_size) const override; + real get_advance( + char32_t c, // + unsigned tab_size + ) const override; protected: render_result render_internal( - const ruis::matrix4& matrix, // + render::renderer& renderer, // + const ruis::matrix4& matrix, const ruis::color& color, const std::u32string_view str, unsigned tab_size, @@ -171,7 +177,8 @@ protected: private: real render_glyph_internal( - const ruis::matrix4& matrix, // + render::renderer& renderer, // + const ruis::matrix4& matrix, const ruis::color& color, char32_t ch ) const; diff --git a/src/ruis/font/texture_font_provider.cpp b/src/ruis/font/texture_font_provider.cpp index c82b70671..6134fd233 100644 --- a/src/ruis/font/texture_font_provider.cpp +++ b/src/ruis/font/texture_font_provider.cpp @@ -24,20 +24,22 @@ along with this program. If not, see . using namespace ruis; texture_font_provider::texture_font_provider( - utki::shared_ref renderer, - // NOLINTNEXTLINE(modernize-pass-by-value) - const utki::shared_ref& face, + utki::shared_ref rendering_context, // + utki::shared_ref common_rendering_objects, + utki::shared_ref face, unsigned max_cached ) : - renderer(std::move(renderer)), - face(face), + rendering_context(std::move(rendering_context)), + common_rendering_objects(std::move(common_rendering_objects)), + face(std::move(face)), max_cached(max_cached) {} utki::shared_ref texture_font_provider::create(real size) const { return utki::make_shared( - this->renderer, // + this->rendering_context, // + this->common_rendering_objects, this->face, unsigned(size), max_cached diff --git a/src/ruis/font/texture_font_provider.hxx b/src/ruis/font/texture_font_provider.hxx index 97e8b92ed..828913edf 100644 --- a/src/ruis/font/texture_font_provider.hxx +++ b/src/ruis/font/texture_font_provider.hxx @@ -28,15 +28,17 @@ namespace ruis { class texture_font_provider : public font_provider { - const utki::shared_ref renderer; + const utki::shared_ref rendering_context; + const utki::shared_ref common_rendering_objects; const utki::shared_ref face; const unsigned max_cached; public: texture_font_provider( - utki::shared_ref renderer, - const utki::shared_ref& face, + utki::shared_ref rendering_context, // + utki::shared_ref common_rendering_objects, + utki::shared_ref face, unsigned max_cached ); diff --git a/src/ruis/gui.cpp b/src/ruis/gui.cpp index ba5f90077..67079f57c 100644 --- a/src/ruis/gui.cpp +++ b/src/ruis/gui.cpp @@ -28,8 +28,8 @@ along with this program. If not, see . using namespace ruis; // NOLINTNEXTLINE(modernize-pass-by-value) -gui::gui(const utki::shared_ref& context) : - context(context), +gui::gui(utki::shared_ref context) : + context(std::move(context)), root_widget(ruis::make::gap(this->context, {})) {} @@ -88,11 +88,23 @@ void gui::init_standard_widgets(papki::file& fi) } } -void gui::set_viewport(const ruis::vector2& size) +void gui::set_viewport(const ruis::rect& rect) { - this->viewport_size = size; + if (this->viewport_rect == rect) { + return; + } + + this->context.get().ren().ctx().apply([&]() { + this->viewport_rect = rect; + + utki::log_debug([&](auto& o) { + o << "gui::set_viewport(): new viewport retangle = " << this->viewport_rect << std::endl; + }); + + this->context.get().ren().ctx().set_viewport(this->viewport_rect.to()); - this->root_widget.get().resize(this->viewport_size); + this->root_widget.get().resize(this->viewport_rect.d); + }); } void gui::set_root(utki::shared_ref w) @@ -101,10 +113,14 @@ void gui::set_root(utki::shared_ref w) throw std::invalid_argument("given widget is already added to some container"); } + if (w.get().context.to_shared_ptr() != this->context.to_shared_ptr()) { + throw std::invalid_argument("cannot set root widget from another GUI context"); + } + this->root_widget = std::move(w); this->root_widget.get().move_to(ruis::vector2(0)); - this->root_widget.get().resize(this->viewport_size); + this->root_widget.get().resize(this->viewport_rect.d); } void gui::render(const matrix4& matrix) const @@ -117,12 +133,18 @@ void gui::render(const matrix4& matrix) const this->root_widget.get().lay_out(); } - ruis::matrix4 m = make_viewport_matrix(matrix, this->viewport_size); + ruis::matrix4 m = make_viewport_matrix( + matrix, // + this->viewport_rect.d + ); this->get_root().render_internal(m); } -void gui::send_mouse_move(const vector2& pos, unsigned id) +void gui::send_mouse_move( + const vector2& pos, // + unsigned id +) { auto& rw = this->get_root(); if (rw.is_interactive()) { @@ -131,7 +153,12 @@ void gui::send_mouse_move(const vector2& pos, unsigned id) } } -void gui::send_mouse_button(bool is_down, const vector2& pos, mouse_button button, unsigned id) +void gui::send_mouse_button( + bool is_down, // + const vector2& pos, + mouse_button button, + unsigned id +) { auto& rw = this->get_root(); if (rw.is_interactive()) { @@ -140,12 +167,18 @@ void gui::send_mouse_button(bool is_down, const vector2& pos, mouse_button butto } } -void gui::send_mouse_hover(bool is_hovered, unsigned pointer_id) +void gui::send_mouse_hover( + bool is_hovered, // + unsigned pointer_id +) { this->get_root().set_hovered(is_hovered, pointer_id); } -void gui::send_key(bool is_down, key key_code) +void gui::send_key( + bool is_down, // + key key_code +) { // TRACE(<< "HandleKeyEvent(): is_down = " << is_down << " is_char_input_only = " << is_char_input_only << " // keyCode = " << unsigned(keyCode) << std::endl) @@ -169,16 +202,19 @@ void gui::send_key(bool is_down, key key_code) } } -void gui::send_character_input(const input_string_provider& string_provider, key key_code) +void gui::send_character_input( + const input_string_provider& string_provider, // + key key_code +) { if (auto w = this->context.get().focused_widget.lock()) { - character_input_event e; - auto str = string_provider.get(); - e.string = str; - e.combo.key = key_code; - e.combo.modifiers = this->key_modifiers; - if (auto c = dynamic_cast(w.get())) { + character_input_event e; + auto str = string_provider.get(); + e.string = str; + e.combo.key = key_code; + e.combo.modifiers = this->key_modifiers; + c->on_character_input(e); } } diff --git a/src/ruis/gui.hpp b/src/ruis/gui.hpp index c01418550..58b813bed 100644 --- a/src/ruis/gui.hpp +++ b/src/ruis/gui.hpp @@ -38,7 +38,7 @@ class gui final * @brief Constructor. * @param context - ruis context to use for this gui instance. */ - gui(const utki::shared_ref& context); + gui(utki::shared_ref context); gui(const gui&) = delete; gui& operator=(const gui&) = delete; @@ -81,15 +81,15 @@ class gui final } private: - vector2 viewport_size{0, 0}; + ruis::rect viewport_rect = {0, 0, 0, 0}; public: /** - * @brief Set viewport size for GUI. - * Set the dimensions of the rectangular area where GUI will be rendered. - * @param size - dimensions of the viewport, in pixels. + * @brief Set viewport rectangle. + * Set the rectangular area within the native window where GUI will be rendered. + * @param rect - viewport rectangle within the native window, in pixels. */ - void set_viewport(const ruis::vector2& size); + void set_viewport(const ruis::rect& rect); /** * @brief Render GUI. @@ -108,18 +108,9 @@ class gui final * widgets to be used by application. * @param fi - file interface to use for resource loading. */ + // TODO: make free function taking context as argument void init_standard_widgets(papki::file& fi); - /** - * @brief Update GUI. - * Call this function from main loop of the program. - * @return number of milliseconds to sleep before next call. - */ - uint32_t update() - { - return this->context.get().updater.get().update(); - } - /** * @brief Feed in the mouse move event to GUI. * @param pos - new position of the mouse pointer. @@ -188,7 +179,10 @@ class gui final * @param string_provider - input string provider. * @param key_code - key code associated with character input, can be unknown. */ - void send_character_input(const input_string_provider& string_provider, ruis::key key_code); + void send_character_input( + const input_string_provider& string_provider, // + ruis::key key_code + ); }; } // namespace ruis diff --git a/src/ruis/paint/frame_vao.cpp b/src/ruis/paint/frame_vao.cpp index 641abf920..f5f74050a 100644 --- a/src/ruis/paint/frame_vao.cpp +++ b/src/ruis/paint/frame_vao.cpp @@ -48,11 +48,11 @@ void frame_vao::set(vector2 dims, vector2 thickness) // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) std::array indices = {0, 4, 1, 5, 2, 6, 3, 7, 0, 4}; - this->vao = this->renderer.get().render_context.get().make_vertex_array( + this->vao = this->renderer.get().rendering_context.get().make_vertex_array( { - this->renderer.get().render_context.get().make_vertex_buffer(vertices), + this->renderer.get().rendering_context.get().make_vertex_buffer(vertices), }, - this->renderer.get().render_context.get().make_index_buffer(indices), + this->renderer.get().rendering_context.get().make_index_buffer(indices), ruis::render::vertex_array::mode::triangle_strip ); } diff --git a/src/ruis/paint/path_vao.cpp b/src/ruis/paint/path_vao.cpp index bacd85025..22054b7e9 100644 --- a/src/ruis/paint/path_vao.cpp +++ b/src/ruis/paint/path_vao.cpp @@ -32,21 +32,21 @@ path_vao::path_vao(const utki::shared_ref& r) : void path_vao::set(const path::vertices& path) { - auto core_buf = this->renderer.get().render_context.get().make_vertex_buffer(path.pos); + auto core_buf = this->renderer.get().rendering_context.get().make_vertex_buffer(path.pos); - this->core = this->renderer.get().render_context.get().make_vertex_array( + this->core = this->renderer.get().rendering_context.get().make_vertex_array( { core_buf, }, - this->renderer.get().render_context.get().make_index_buffer(path.in_indices), + this->renderer.get().rendering_context.get().make_index_buffer(path.in_indices), ruis::render::vertex_array::mode::triangle_strip ); - this->border = this->renderer.get().render_context.get().make_vertex_array( + this->border = this->renderer.get().rendering_context.get().make_vertex_array( { core_buf, - this->renderer.get().render_context.get().make_vertex_buffer(path.alpha), + this->renderer.get().rendering_context.get().make_vertex_buffer(path.alpha), }, - this->renderer.get().render_context.get().make_index_buffer(path.out_indices), + this->renderer.get().rendering_context.get().make_index_buffer(path.out_indices), ruis::render::vertex_array::mode::triangle_strip ); } diff --git a/src/ruis/render/context.cpp b/src/ruis/render/context.cpp index 5e7af0393..c89f05b57 100644 --- a/src/ruis/render/context.cpp +++ b/src/ruis/render/context.cpp @@ -23,18 +23,72 @@ along with this program. If not, see . using namespace ruis::render; -context::context(parameters params) : +std::vector ruis::render::context::cur_context_stack; + +context::context( + utki::shared_ref native_window, // + parameters params +) : + native_window(std::move(native_window)), initial_matrix(std::move(params.initial_matrix)) -{} +{ + // insert this context to the bottom of the current contexts stack + cur_context_stack.insert(cur_context_stack.begin(), this); + + if (this->is_current()) { + // this context is the first one created, so it should become current + this->native_window.get().bind_rendering_context(); + } +} + +context::~context() +{ + if (this->is_current()) { + cur_context_stack.pop_back(); + } + + // remove all occurrencies of this context from current contexts stack, + // because there can be several of them + cur_context_stack.erase( + std::remove( + cur_context_stack.begin(), // + cur_context_stack.end(), + this + ), + cur_context_stack.end() + ); + + if (!cur_context_stack.empty()) { + cur_context_stack.back()->native_window.get().bind_rendering_context(); + } +} void context::apply(std::function func) { + utki::assert(func, SL); + if (this->is_current()) { + // this context is already current func(); return; } - throw std::logic_error("context::apply(): the context is non-current, switching context is not yet implemented"); + cur_context_stack.push_back(this); + + utki::scope_exit restore_old_current_context_scope_exit([&]() { + utki::assert(this->is_current(), SL); + cur_context_stack.pop_back(); + if (!cur_context_stack.empty()) { + // bind the previous context + cur_context_stack.back()->native_window.get().bind_rendering_context(); + } + }); + + this->native_window.get().bind_rendering_context(); + + utki::assert(this->is_current(), SL); + + func(); } void context::set_framebuffer(frame_buffer* fb) diff --git a/src/ruis/render/context.hpp b/src/ruis/render/context.hpp index f06422013..ae6e4b3e1 100644 --- a/src/ruis/render/context.hpp +++ b/src/ruis/render/context.hpp @@ -21,6 +21,8 @@ along with this program. If not, see . #pragma once +#include + #include #include @@ -30,6 +32,7 @@ along with this program. If not, see . #include "shaders/texturing_shader.hpp" #include "frame_buffer.hpp" +#include "native_window.hpp" #include "texture_cube.hpp" #include "texture_depth.hpp" @@ -38,16 +41,26 @@ class context : public std::enable_shared_from_this { friend class frame_buffer; + // Context destruction is rare, so removing from the middle of stack is rare, ok to use std::vector. + static std::vector cur_context_stack; + protected: utki::shared_ref get_shared_ref() { - return utki::make_shared_from(*this); + return utki::shared_ref(this->shared_from_this()); + } + + utki::shared_ref get_shared_ref() const + { + return utki::shared_ref(this->shared_from_this()); } private: std::weak_ptr cur_fb; public: + const utki::shared_ref native_window; + struct parameters { r4::matrix4 initial_matrix; }; @@ -59,7 +72,10 @@ class context : public std::enable_shared_from_this */ const r4::matrix4 initial_matrix; - context(parameters params); + context( + utki::shared_ref, // + parameters params + ); context(const context&) = delete; context& operator=(const context&) = delete; @@ -67,24 +83,28 @@ class context : public std::enable_shared_from_this context(context&&) = delete; context& operator=(context&&) = delete; - virtual ~context() = default; + virtual ~context(); bool is_current() const noexcept { - // TODO: actually check that the context is current - return true; + // if at least one context exists then the cur_context_stack is not empty + utki::assert(!cur_context_stack.empty(), SL); + return cur_context_stack.back() == this; } /** * @brief Execute procedure with this context made current. + * Previous context will be restored to be current after procedure execution. * @param proc - procedure to execute. */ + // TODO: make argument generic callable instead of std::function? i.e. template method for compiler optimizations? void apply(std::function proc); // =============================== // ====== factory functions ====== struct shaders { + // TODO: make unique_ref std::unique_ptr pos_tex; std::unique_ptr color_pos; std::unique_ptr color_pos_lum; @@ -93,7 +113,7 @@ class context : public std::enable_shared_from_this std::unique_ptr color_pos_tex_alpha; }; - virtual utki::shared_ref make_shaders() = 0; + virtual utki::shared_ref make_shaders() const = 0; struct texture_2d_parameters { texture_2d::filter min_filter = texture_2d::filter::nearest; @@ -105,19 +125,20 @@ class context : public std::enable_shared_from_this rasterimage::format format, rasterimage::dimensioned::dimensions_type dims, texture_2d_parameters params - ) = 0; + ) const = 0; virtual utki::shared_ref make_texture_2d( const rasterimage::image_variant& imvar, texture_2d_parameters params - ) = 0; + ) const = 0; virtual utki::shared_ref make_texture_2d( rasterimage::image_variant&& imvar, texture_2d_parameters params - ) = 0; + ) const = 0; - virtual utki::shared_ref make_texture_depth(rasterimage::dimensioned::dimensions_type dims) = 0; + virtual utki::shared_ref make_texture_depth(rasterimage::dimensioned::dimensions_type dims + ) const = 0; virtual utki::shared_ref make_texture_cube( rasterimage::image_variant&& positive_x, @@ -126,25 +147,21 @@ class context : public std::enable_shared_from_this rasterimage::image_variant&& negative_y, rasterimage::image_variant&& positive_z, rasterimage::image_variant&& negative_z - ) = 0; - - virtual utki::shared_ref make_vertex_buffer(utki::span> vertices) = 0; - - virtual utki::shared_ref make_vertex_buffer(utki::span> vertices) = 0; + ) const = 0; - virtual utki::shared_ref make_vertex_buffer(utki::span> vertices) = 0; + virtual utki::shared_ref make_vertex_buffer(utki::span> vertices) const = 0; + virtual utki::shared_ref make_vertex_buffer(utki::span> vertices) const = 0; + virtual utki::shared_ref make_vertex_buffer(utki::span> vertices) const = 0; + virtual utki::shared_ref make_vertex_buffer(utki::span vertices) const = 0; - virtual utki::shared_ref make_vertex_buffer(utki::span vertices) = 0; - - virtual utki::shared_ref make_index_buffer(utki::span indices) = 0; - - virtual utki::shared_ref make_index_buffer(utki::span indices) = 0; + virtual utki::shared_ref make_index_buffer(utki::span indices) const = 0; + virtual utki::shared_ref make_index_buffer(utki::span indices) const = 0; virtual utki::shared_ref make_vertex_array( std::vector> buffers, utki::shared_ref indices, vertex_array::mode rendering_mode - ) = 0; + ) const = 0; virtual utki::shared_ref make_framebuffer( // std::shared_ptr color, @@ -167,7 +184,7 @@ class context : public std::enable_shared_from_this * @brief Get current frame buffer. * @return Current frame buffer. If nullptr, then it is a screen buffer. */ - std::shared_ptr get_framebuffer() + std::shared_ptr get_framebuffer() const { return this->cur_fb.lock(); } @@ -201,7 +218,7 @@ class context : public std::enable_shared_from_this * should be interpreted in context of the specific renderer. * @return Window coordinates of the point. */ - virtual r4::vector2 to_window_coords(ruis::vec2 point) const = 0; + virtual r4::vector2 to_window_coords(const ruis::vec2& point) const = 0; /** * @brief Check if scissor test is enabled. @@ -231,7 +248,7 @@ class context : public std::enable_shared_from_this * TODO: * @param r - new scissor rectangle. */ - virtual void set_scissor(r4::rectangle r) = 0; + virtual void set_scissor(const r4::rectangle& r) = 0; /** * @brief Get current rendering viewport within application window. @@ -255,7 +272,7 @@ class context : public std::enable_shared_from_this * covering the whole framebuffer. * @param r - new viewport rectangle. */ - virtual void set_viewport(r4::rectangle r) = 0; + virtual void set_viewport(const r4::rectangle& r) = 0; virtual void enable_blend(bool enable) = 0; diff --git a/src/ruis/render/frame_buffer.cpp b/src/ruis/render/frame_buffer.cpp index 12784c38a..83a8160a4 100644 --- a/src/ruis/render/frame_buffer.cpp +++ b/src/ruis/render/frame_buffer.cpp @@ -28,7 +28,7 @@ along with this program. If not, see . using namespace ruis::render; frame_buffer::frame_buffer( // - utki::shared_ref render_context, + utki::shared_ref rendering_context, std::shared_ptr color, std::shared_ptr depth, std::shared_ptr stencil @@ -60,7 +60,7 @@ frame_buffer::frame_buffer( // return cur_tex->dims(); }()), - render_context(std::move(render_context)), + rendering_context(std::move(rendering_context)), color(std::move(color)), depth(std::move(depth)), stencil(std::move(stencil)) @@ -68,9 +68,9 @@ frame_buffer::frame_buffer( // void frame_buffer::apply(std::function func) { - auto& rc = this->render_context.get(); + auto& rc = this->rendering_context.get(); if (!rc.is_current()) { - throw std::logic_error("framebuffer::apply(): the framebuffer's render_context is not current"); + throw std::logic_error("framebuffer::apply(): the framebuffer's rendering_context is not current"); } utki::scope_exit framebuffer_scope_exit([old_framebuffer = rc.get_framebuffer(), &rc]() { diff --git a/src/ruis/render/frame_buffer.hpp b/src/ruis/render/frame_buffer.hpp index 26942ab36..1ac9c0bf9 100644 --- a/src/ruis/render/frame_buffer.hpp +++ b/src/ruis/render/frame_buffer.hpp @@ -37,16 +37,18 @@ class frame_buffer : public std::enable_shared_from_this { protected: + // in OpneGL framebuffer objects are not shared between contexts, + // so the reference stored here is for non-const context object which owns the framebuffer + const utki::shared_ref rendering_context; + frame_buffer( // - utki::shared_ref render_context, + utki::shared_ref rendering_context, std::shared_ptr color, std::shared_ptr depth, std::shared_ptr stencil ); public: - const utki::shared_ref render_context; - const std::shared_ptr color; const std::shared_ptr depth; const std::shared_ptr stencil; diff --git a/src/ruis/render/index_buffer.hpp b/src/ruis/render/index_buffer.hpp index 131f9a4c6..139897792 100644 --- a/src/ruis/render/index_buffer.hpp +++ b/src/ruis/render/index_buffer.hpp @@ -29,14 +29,14 @@ class context; class index_buffer { + const utki::shared_ref rendering_context; + protected: - index_buffer(utki::shared_ref render_context) : - render_context(std::move(render_context)) + index_buffer(utki::shared_ref rendering_context) : + rendering_context(std::move(rendering_context)) {} public: - const utki::shared_ref render_context; - index_buffer(const index_buffer&) = delete; index_buffer& operator=(const index_buffer&) = delete; diff --git a/src/ruis/util/mouse_cursor_stack.cpp b/src/ruis/render/native_window.cpp similarity index 66% rename from src/ruis/util/mouse_cursor_stack.cpp rename to src/ruis/render/native_window.cpp index eff75eeb4..8d62bf41d 100644 --- a/src/ruis/util/mouse_cursor_stack.cpp +++ b/src/ruis/render/native_window.cpp @@ -19,23 +19,24 @@ along with this program. If not, see . /* ================ LICENSE END ================ */ -#include "mouse_cursor_stack.hpp" +#include "native_window.hpp" #include -using namespace ruis; +using namespace ruis::render; -mouse_cursor_stack::mouse_cursor_stack(std::function set_mouse_cursor) : - set_mouse_cursor(std::move(set_mouse_cursor)) +void native_window::set_fullscreen(bool enable) { - if (!this->set_mouse_cursor) { - throw std::invalid_argument( // - "mouse_cursor_stack::mouse_cursor_stack(): set_mouse_cursor function cannot be null" - ); + if (enable == this->is_fullscreen()) { + return; } + + this->set_fullscreen_internal(enable); + + this->is_fullscreen_v = enable; } -decltype(mouse_cursor_stack::cursor_stack)::iterator mouse_cursor_stack::push(mouse_cursor cursor) +native_window::cursor_id native_window::push_mouse_cursor(mouse_cursor cursor) { this->cursor_stack.push_front(cursor); @@ -44,9 +45,9 @@ decltype(mouse_cursor_stack::cursor_stack)::iterator mouse_cursor_stack::push(mo return this->cursor_stack.begin(); } -void mouse_cursor_stack::pop(decltype(cursor_stack)::iterator i) +void native_window::pop_mouse_cursor(cursor_id i) { - ASSERT(this->cursor_stack.size() > 1) + utki::assert(this->cursor_stack.size() > 1, SL); bool top_cursor = i == this->cursor_stack.begin(); this->cursor_stack.erase(i); diff --git a/src/ruis/render/native_window.hpp b/src/ruis/render/native_window.hpp new file mode 100644 index 000000000..394ff0304 --- /dev/null +++ b/src/ruis/render/native_window.hpp @@ -0,0 +1,88 @@ +/* +ruis - GUI framework + +Copyright (C) 2012-2025 Ivan Gagis + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* ================ LICENSE END ================ */ + +#pragma once + +#include +#include + +#include "../util/mouse_cursor.hpp" + +namespace ruis::render { +class context; + +// TODO: doxygen +class native_window +{ + friend class ruis::render::context; + + bool is_fullscreen_v = false; + + virtual void bind_rendering_context() {} + + virtual void set_fullscreen_internal(bool enable) {} + + std::list cursor_stack = {mouse_cursor::arrow}; + + virtual void set_mouse_cursor(ruis::mouse_cursor c) {} + +public: + native_window() = default; + + native_window(const native_window&) = delete; + native_window& operator=(const native_window&) = delete; + + native_window(native_window&&) = delete; + native_window& operator=(native_window&&) = delete; + + virtual ~native_window() = default; + + // TODO: make private somehow? + virtual void swap_frame_buffers() {} + + void set_fullscreen(bool enable); + + bool is_fullscreen() const noexcept + { + return this->is_fullscreen_v; + } + + // TODO: add set_maximized(bool) & is_maximized() + // TODO: add set_minimized(bool) & is_minimized() + // TODO: add set_hidden(bool) & is_hidden() + + /** + * @brief Handler of window close event. + * Invoked when user tries to close the window, e.g. by clicking the window's close button. + */ + std::function close_handler; + + // ================ + // = mouse cursor = + + using cursor_id = decltype(cursor_stack)::iterator; + + cursor_id push_mouse_cursor(mouse_cursor cursor); + void pop_mouse_cursor(cursor_id i); + + virtual void set_mouse_cursor_visible(bool visible) {} +}; +} // namespace ruis::render diff --git a/src/ruis/render/renderer.cpp b/src/ruis/render/renderer.cpp index 06c9d780c..4e442eaed 100644 --- a/src/ruis/render/renderer.cpp +++ b/src/ruis/render/renderer.cpp @@ -25,62 +25,55 @@ along with this program. If not, see . using namespace ruis::render; -renderer::renderer(utki::shared_ref render_context) : - render_context(std::move(render_context)), - common_objects(utki::make_shared([this]() -> objects { - // clang-format off - objects self{ - .shaders = this->render_context.get().make_shaders(), - .empty_vertex_array = this->render_context.get().make_vertex_array( - { - this->render_context.get().make_vertex_buffer(utki::span>()) - }, - this->render_context.get().make_index_buffer(utki::span()), - ruis::render::vertex_array::mode::triangle_strip - ), - .quad_01_vbo = this->render_context.get().make_vertex_buffer( - utki::make_span(std::array{ - vec2(0, 0), - vec2(0, 1), - vec2(1, 1), - vec2(1, 0) - }) - ), - .quad_fan_indices = this->render_context.get().make_index_buffer( - utki::make_span(std::array{0, 1, 2, 3}) - ), - .pos_quad_01_vao = this->render_context.get().make_vertex_array( - {self.quad_01_vbo}, - self.quad_fan_indices, - vertex_array::mode::triangle_fan - ), - .pos_tex_quad_01_vao = this->render_context.get().make_vertex_array( - { - self.quad_01_vbo, - self.quad_01_vbo - }, - self.quad_fan_indices, - vertex_array::mode::triangle_fan - ), - .white_texture = this->render_context.get().make_texture_2d( - []() { - // raster image 1 by 1 pixel - rasterimage::image_variant imvar( - {1, 1}, // - rasterimage::format::rgba, - rasterimage::depth::uint_8_bit - ); +renderer::renderer( + utki::shared_ref rendering_context, // + utki::shared_ref common_shaders, + utki::shared_ref common_objects +) : + rendering_context(std::move(rendering_context)), + common_shaders(std::move(common_shaders)), + common_objects(std::move(common_objects)) +{} + +renderer::objects::objects(const ruis::render::context& rendering_context) : + empty_vertex_array(rendering_context.make_vertex_array( + {// + rendering_context.make_vertex_buffer(utki::span>()) + }, + rendering_context.make_index_buffer(utki::span()), + ruis::render::vertex_array::mode::triangle_strip + )), + quad_01_vbo(rendering_context.make_vertex_buffer(utki::make_span(std::array{ + vec2(0, 0), // + vec2(0, 1), + vec2(1, 1), + vec2(1, 0) + }))), + quad_fan_indices(rendering_context.make_index_buffer(utki::make_span(std::array{0, 1, 2, 3}))), + pos_quad_01_vao(rendering_context.make_vertex_array( + {this->quad_01_vbo}, + this->quad_fan_indices, + vertex_array::mode::triangle_fan + )), + pos_tex_quad_01_vao(rendering_context.make_vertex_array( + {this->quad_01_vbo, this->quad_01_vbo}, + this->quad_fan_indices, + vertex_array::mode::triangle_fan + )), + white_texture(rendering_context.make_texture_2d( + []() { + // raster image 1 by 1 pixel + rasterimage::image_variant imvar( + {1, 1}, // + rasterimage::format::rgba, + rasterimage::depth::uint_8_bit + ); - auto& im = imvar.get(); - constexpr auto opaque_white = - std::remove_reference_t::pixel_type{0xff, 0xff, 0xff, 0xff}; - im[0][0] = opaque_white; - return imvar; - }(), - {} - ) - }; - // clang-format on - return self; - }())) + auto& im = imvar.get(); + constexpr auto opaque_white = std::remove_reference_t::pixel_type{0xff, 0xff, 0xff, 0xff}; + im[0][0] = opaque_white; + return imvar; + }(), + {} + )) {} diff --git a/src/ruis/render/renderer.hpp b/src/ruis/render/renderer.hpp index 6458befef..1bb736e88 100644 --- a/src/ruis/render/renderer.hpp +++ b/src/ruis/render/renderer.hpp @@ -28,29 +28,31 @@ namespace ruis::render { class renderer : public std::enable_shared_from_this { public: - const utki::shared_ref render_context; + const utki::shared_ref rendering_context; /** * @brief Shorthand alias for render context. - * @return this->render_context.get(). + * @return this->rendering_context.get(). */ ruis::render::context& ctx() noexcept { - return this->render_context.get(); + return this->rendering_context.get(); } /** * @brief Shorthand alias for render context. - * @return this->render_context.get(). + * @return this->rendering_context.get(). */ - // TODO: return const ref? ruis::render::context& ctx() const noexcept { - return this->render_context.get(); + return this->rendering_context.get(); } + const utki::shared_ref common_shaders; + struct objects { - utki::shared_ref shaders; + objects(const ruis::render::context& rendering_context); + utki::shared_ref empty_vertex_array; /** @@ -75,14 +77,13 @@ class renderer : public std::enable_shared_from_this const ruis::render::context::shaders& shaders() const noexcept { - return this->common_objects.get().shaders.get(); + return this->common_shaders.get(); } - renderer(utki::shared_ref render_context); - renderer( - utki::shared_ref render_context, // - utki::shared_ref common_objects + utki::shared_ref rendering_context, // + utki::shared_ref common_shaders, + utki::shared_ref common_objects ); renderer(const renderer&) = delete; diff --git a/src/ruis/render/shaders/coloring_shader.hpp b/src/ruis/render/shaders/coloring_shader.hpp index 27e13bfd2..228c03d07 100644 --- a/src/ruis/render/shaders/coloring_shader.hpp +++ b/src/ruis/render/shaders/coloring_shader.hpp @@ -33,14 +33,14 @@ class context; class coloring_shader { + const utki::shared_ref rendering_context; + protected: - coloring_shader(utki::shared_ref render_context) : - render_context(std::move(render_context)) + coloring_shader(utki::shared_ref rendering_context) : + rendering_context(std::move(rendering_context)) {} public: - const utki::shared_ref render_context; - coloring_shader(const coloring_shader&) = delete; coloring_shader& operator=(const coloring_shader&) = delete; diff --git a/src/ruis/render/shaders/coloring_texturing_shader.hpp b/src/ruis/render/shaders/coloring_texturing_shader.hpp index 6b6f83e6c..c8140ca84 100644 --- a/src/ruis/render/shaders/coloring_texturing_shader.hpp +++ b/src/ruis/render/shaders/coloring_texturing_shader.hpp @@ -34,14 +34,14 @@ class context; class coloring_texturing_shader { + const utki::shared_ref rendering_context; + protected: - coloring_texturing_shader(utki::shared_ref render_context) : - render_context(std::move(render_context)) + coloring_texturing_shader(utki::shared_ref rendering_context) : + rendering_context(std::move(rendering_context)) {} public: - const utki::shared_ref render_context; - coloring_texturing_shader(const coloring_texturing_shader&) = delete; coloring_texturing_shader& operator=(const coloring_texturing_shader&) = delete; diff --git a/src/ruis/render/shaders/shader.hpp b/src/ruis/render/shaders/shader.hpp index 27cf292be..1ac026c73 100644 --- a/src/ruis/render/shaders/shader.hpp +++ b/src/ruis/render/shaders/shader.hpp @@ -31,14 +31,14 @@ class context; class shader { + const utki::shared_ref rendering_context; + protected: - shader(utki::shared_ref render_context) : - render_context(std::move(render_context)) + shader(utki::shared_ref rendering_context) : + rendering_context(std::move(rendering_context)) {} public: - const utki::shared_ref render_context; - shader(const shader&) = delete; shader& operator=(const shader&) = delete; diff --git a/src/ruis/render/shaders/texturing_shader.hpp b/src/ruis/render/shaders/texturing_shader.hpp index a6daa72e0..3473e6f25 100644 --- a/src/ruis/render/shaders/texturing_shader.hpp +++ b/src/ruis/render/shaders/texturing_shader.hpp @@ -30,14 +30,14 @@ class context; class texturing_shader { + const utki::shared_ref rendering_context; + protected: - texturing_shader(utki::shared_ref render_context) : - render_context(std::move(render_context)) + texturing_shader(utki::shared_ref rendering_context) : + rendering_context(std::move(rendering_context)) {} public: - const utki::shared_ref render_context; - texturing_shader(const texturing_shader&) = delete; texturing_shader& operator=(const texturing_shader&) = delete; diff --git a/src/ruis/render/texture_2d.hpp b/src/ruis/render/texture_2d.hpp index e37d753a9..17f9ffb62 100644 --- a/src/ruis/render/texture_2d.hpp +++ b/src/ruis/render/texture_2d.hpp @@ -32,6 +32,8 @@ class context; class texture_2d : public rasterimage::dimensioned { + const utki::shared_ref rendering_context; + public: enum class filter { nearest, @@ -44,15 +46,13 @@ class texture_2d : public rasterimage::dimensioned linear }; - const utki::shared_ref render_context; - protected: texture_2d( - utki::shared_ref render_context, // + utki::shared_ref rendering_context, // r4::vector2 dims ) : rasterimage::dimensioned(dims), - render_context(std::move(render_context)) + rendering_context(std::move(rendering_context)) {} public: diff --git a/src/ruis/render/texture_cube.hpp b/src/ruis/render/texture_cube.hpp index fa21259d7..996acac82 100644 --- a/src/ruis/render/texture_cube.hpp +++ b/src/ruis/render/texture_cube.hpp @@ -29,14 +29,14 @@ class context; class texture_cube { + const utki::shared_ref rendering_context; + protected: - texture_cube(utki::shared_ref render_context) : - render_context(std::move(render_context)) + texture_cube(utki::shared_ref rendering_context) : + rendering_context(std::move(rendering_context)) {} public: - const utki::shared_ref render_context; - texture_cube(const texture_cube&) = delete; texture_cube& operator=(const texture_cube&) = delete; diff --git a/src/ruis/render/texture_depth.hpp b/src/ruis/render/texture_depth.hpp index da7d9d13e..f1320259b 100644 --- a/src/ruis/render/texture_depth.hpp +++ b/src/ruis/render/texture_depth.hpp @@ -30,18 +30,18 @@ class context; class texture_depth : public rasterimage::dimensioned { + const utki::shared_ref rendering_context; + protected: texture_depth( - utki::shared_ref render_context, // + utki::shared_ref rendering_context, // r4::vector2 dims ) : rasterimage::dimensioned(dims), - render_context(std::move(render_context)) + rendering_context(std::move(rendering_context)) {} public: - const utki::shared_ref render_context; - texture_depth(const texture_depth&) = delete; texture_depth& operator=(const texture_depth&) = delete; diff --git a/src/ruis/render/texture_stencil.hpp b/src/ruis/render/texture_stencil.hpp index 5eabba698..1fcb0c2d5 100644 --- a/src/ruis/render/texture_stencil.hpp +++ b/src/ruis/render/texture_stencil.hpp @@ -30,18 +30,18 @@ class context; class texture_stencil : public rasterimage::dimensioned { + const utki::shared_ref rendering_context; + protected: texture_stencil( - utki::shared_ref render_context, // + utki::shared_ref rendering_context, // r4::vector2 dims ) : rasterimage::dimensioned(dims), - render_context(std::move(render_context)) + rendering_context(std::move(rendering_context)) {} public: - const utki::shared_ref render_context; - texture_stencil(const texture_stencil&) = delete; texture_stencil& operator=(const texture_stencil&) = delete; diff --git a/src/ruis/render/vertex_array.cpp b/src/ruis/render/vertex_array.cpp index b36de1a2f..b24f48988 100644 --- a/src/ruis/render/vertex_array.cpp +++ b/src/ruis/render/vertex_array.cpp @@ -26,12 +26,12 @@ along with this program. If not, see . using namespace ruis::render; vertex_array::vertex_array( - utki::shared_ref render_context, // + utki::shared_ref rendering_context, // buffers_type buffers, utki::shared_ref indices, mode rendering_mode ) : - render_context(std::move(render_context)), + rendering_context(std::move(rendering_context)), buffers(std::move(buffers)), indices(std::move(indices)), rendering_mode(rendering_mode) diff --git a/src/ruis/render/vertex_array.hpp b/src/ruis/render/vertex_array.hpp index 8daf6e25f..ea84833bc 100644 --- a/src/ruis/render/vertex_array.hpp +++ b/src/ruis/render/vertex_array.hpp @@ -35,9 +35,9 @@ class context; class vertex_array { -public: - const utki::shared_ref render_context; + const utki::shared_ref rendering_context; +public: using buffers_type = std::vector>; const buffers_type buffers; @@ -63,7 +63,7 @@ class vertex_array protected: vertex_array( - utki::shared_ref render_context, // + utki::shared_ref rendering_context, // buffers_type buffers, utki::shared_ref indices, mode rendering_mode diff --git a/src/ruis/render/vertex_buffer.hpp b/src/ruis/render/vertex_buffer.hpp index cb87c2455..3bf6aa710 100644 --- a/src/ruis/render/vertex_buffer.hpp +++ b/src/ruis/render/vertex_buffer.hpp @@ -31,17 +31,17 @@ class context; class vertex_buffer { -public: - const utki::shared_ref render_context; + const utki::shared_ref rendering_context; +public: const size_t size; protected: vertex_buffer( - utki::shared_ref render_context, // + utki::shared_ref rendering_context, // size_t size ) : - render_context(std::move(render_context)), + rendering_context(std::move(rendering_context)), size(size) {} diff --git a/src/ruis/res/font.cpp b/src/ruis/res/font.cpp index 8c8d1a4d3..385d63281 100644 --- a/src/ruis/res/font.cpp +++ b/src/ruis/res/font.cpp @@ -33,7 +33,8 @@ using namespace ruis; using namespace ruis::res; res::font::font( - utki::shared_ref renderer, // + utki::shared_ref rendering_context, // + utki::shared_ref common_rendering_objects, const papki::file& file_normal, std::unique_ptr file_bold, std::unique_ptr file_italic, @@ -42,18 +43,27 @@ res::font::font( ) { // NOLINTNEXTLINE(bugprone-unused-return-value, "false positive") - this->fonts[unsigned(style::normal)] = - std::make_unique(renderer, utki::make_shared(file_normal), max_cached); + this->fonts[unsigned(style::normal)] = std::make_unique( + rendering_context, // + common_rendering_objects, + utki::make_shared(file_normal), + max_cached + ); if (file_bold) { // NOLINTNEXTLINE(bugprone-unused-return-value, "false positive") - this->fonts[unsigned(style::bold)] = - std::make_unique(renderer, utki::make_shared(*file_bold), max_cached); + this->fonts[unsigned(style::bold)] = std::make_unique( + rendering_context, // + common_rendering_objects, + utki::make_shared(*file_bold), + max_cached + ); } if (file_italic) { // NOLINTNEXTLINE(bugprone-unused-return-value, "false positive") this->fonts[unsigned(style::italic)] = std::make_unique( - renderer, + rendering_context, // + common_rendering_objects, utki::make_shared(*file_italic), max_cached ); @@ -61,7 +71,8 @@ res::font::font( if (file_bold_italic) { // NOLINTNEXTLINE(bugprone-unused-return-value, "false positive") this->fonts[unsigned(style::bold_italic)] = std::make_unique( - std::move(renderer), + std::move(rendering_context), // + std::move(common_rendering_objects), utki::make_shared(*file_bold_italic), max_cached ); @@ -98,7 +109,8 @@ utki::shared_ref res::font::load( } return utki::make_shared( - loader.renderer, + loader.rendering_context, + loader.common_rendering_objects, fi, std::move(file_bold), std::move(file_italic), diff --git a/src/ruis/res/font.hpp b/src/ruis/res/font.hpp index 649e178ad..98a7ca42b 100644 --- a/src/ruis/res/font.hpp +++ b/src/ruis/res/font.hpp @@ -74,7 +74,8 @@ class font : public ruis::resource public: font( - utki::shared_ref renderer, // + utki::shared_ref rendering_context, // + utki::shared_ref common_rendering_objects, const papki::file& file_normal, std::unique_ptr file_bold, std::unique_ptr file_italic, diff --git a/src/ruis/res/gradient.cpp b/src/ruis/res/gradient.cpp index 7a684c2c1..a1cf9e0bb 100644 --- a/src/ruis/res/gradient.cpp +++ b/src/ruis/res/gradient.cpp @@ -29,18 +29,25 @@ along with this program. If not, see . using namespace ruis::res; -ruis::res::gradient::gradient(utki::shared_ref renderer) : - renderer(std::move(renderer)), - vao(this->renderer.get().obj().empty_vertex_array) +ruis::res::gradient::gradient( + const ruis::render::context& rendering_context, // + utki::span> stops, + bool vertical +) : + vao(make_vao( + rendering_context, // + stops, + vertical + )) {} -void gradient::set( - std::vector>& stops, // +utki::shared_ref gradient::make_vao( + const ruis::render::context& rendering_context, // + utki::span> stops, bool vertical ) { std::vector> vertices; - // std::vector colors; std::vector> colors; for (auto& s : stops) { { @@ -71,15 +78,13 @@ void gradient::set( indices.push_back(uint16_t(i)); } - auto& r = this->renderer.get(); - // clang-format off - this->vao = r.render_context.get().make_vertex_array( + return rendering_context.make_vertex_array( { - r.render_context.get().make_vertex_buffer(utki::make_span(vertices)), - r.render_context.get().make_vertex_buffer(utki::make_span(colors)) + rendering_context.make_vertex_buffer(utki::make_span(vertices)), + rendering_context.make_vertex_buffer(utki::make_span(colors)) }, - r.render_context.get().make_index_buffer(utki::make_span(indices)), + rendering_context.make_index_buffer(utki::make_span(indices)), render::vertex_array::mode::triangle_strip ); // clang-format on @@ -114,9 +119,8 @@ utki::shared_ref gradient::load( } } - auto ret = utki::make_shared(loader.renderer); - - ret.get().set( + auto ret = utki::make_shared( + loader.rendering_context, stops, // vertical ); @@ -124,9 +128,12 @@ utki::shared_ref gradient::load( return ret; } -void gradient::render(const ruis::matrix4& m) const +void gradient::render( + ruis::render::renderer& renderer, // + const ruis::matrix4& m +) const { - this->renderer.get().shaders().pos_clr->render( + renderer.shaders().pos_clr->render( m, // this->vao.get() ); diff --git a/src/ruis/res/gradient.hpp b/src/ruis/res/gradient.hpp index 04fab7415..266cda2b1 100644 --- a/src/ruis/res/gradient.hpp +++ b/src/ruis/res/gradient.hpp @@ -58,21 +58,28 @@ class gradient : public resource { friend class ruis::resource_loader; -public: - const utki::shared_ref renderer; - private: utki::shared_ref vao; + static utki::shared_ref make_vao( + const ruis::render::context& rendering_context, // + utki::span> stops, + bool vertical + ); + public: /** * @brief Create gradient resource form aray of gradient stops. * A gradient stop is a pair of values. First one is a floating point value * from [0:1] defining the position of the gradient stop. The second value * defines the color of the stop. - * @param renderer - ruis renderer. + * @param rendering_context - ruis rendering context. */ - gradient(utki::shared_ref renderer); + gradient( + const ruis::render::context& rendering_context, // + utki::span> stops, + bool vertical + ); gradient(const gradient&) = delete; gradient& operator=(const gradient&) = delete; @@ -82,26 +89,19 @@ class gradient : public resource ~gradient() override = default; - /** - * @brief Set gradient. - * @param stops - array of gradient stops. - * @param vertical - if true, the gradient is vertical. If false, the gradient is horizontal. - */ - void set( - std::vector>& stops, // - bool vertical - ); - /** * @brief render gradient. * Renders the gradient as a rectangle ((0,0),(1,1)). * @param m - transformation matrix. */ - void render(const ruis::matrix4& m) const; + void render( + ruis::render::renderer& renderer, // + const ruis::matrix4& m + ) const; private: static utki::shared_ref load( - const ruis::resource_loader& loader, + const ruis::resource_loader& loader, // const ::tml::forest& desc, const papki::file& fi ); diff --git a/src/ruis/res/image.cpp b/src/ruis/res/image.cpp index fe1b6da86..d101f9c2a 100644 --- a/src/ruis/res/image.cpp +++ b/src/ruis/res/image.cpp @@ -68,7 +68,7 @@ class res_raster_image : public image const papki::file& fi ) { - return utki::make_shared(loader.renderer.get().render_context.get().make_texture_2d( + return utki::make_shared(loader.rendering_context.get().make_texture_2d( rasterimage::read(fi), { // TODO: what about params? @@ -80,23 +80,29 @@ class res_raster_image : public image class res_svg_image : public image { public: - const utki::shared_ref renderer; + const utki::shared_ref rendering_context; private: std::unique_ptr dom; public: res_svg_image( // - utki::shared_ref renderer, + utki::shared_ref rendering_context, decltype(dom) dom ) : - renderer(std::move(renderer)), + rendering_context(std::move(rendering_context)), dom(std::move(dom)) {} r4::vector2 dims(const ruis::units& units) const noexcept override { - ASSERT(units.dots_per_pp() > 0) + utki::assert( + units.dots_per_pp() > 0, + [&](auto& o) { + o << "units.dots_per_pp() = " << units.dots_per_pp(); + }, + SL + ); auto wh = this->dom->get_dimensions(units.dots_per_inch() / units.dots_per_pp()); wh *= units.dots_per_pp(); using std::ceil; @@ -151,7 +157,7 @@ class res_svg_image : public image auto dims = im.dims(); // clang-format off - auto tex_2d = this->renderer.get().render_context.get().make_texture_2d( + auto tex_2d = this->rendering_context.get().make_texture_2d( std::move(im), { .min_filter = render::texture_2d::filter::nearest, @@ -180,7 +186,7 @@ class res_svg_image : public image auto dom = svgdom::load(fi); ASSERT(dom) return utki::make_shared( - loader.renderer, // + loader.rendering_context, // std::move(dom) ); } diff --git a/src/ruis/res/nine_patch.cpp b/src/ruis/res/nine_patch.cpp index aa111d1ee..549486ae4 100644 --- a/src/ruis/res/nine_patch.cpp +++ b/src/ruis/res/nine_patch.cpp @@ -60,7 +60,8 @@ utki::shared_ref nine_patch::load( ); return utki::make_shared( // - loader.renderer, + loader.rendering_context, + loader.common_rendering_objects, std::move(image), fraction_borders ); @@ -68,45 +69,46 @@ utki::shared_ref nine_patch::load( namespace { utki::shared_ref make_quad_vao( - ruis::render::renderer& r, // + const ruis::render::context& rendering_context, // + const ruis::render::renderer::objects& common_rendering_objects, utki::span quad_tex_coords ) { - return r.ctx().make_vertex_array( + return rendering_context.make_vertex_array( // clang-format off { - r.obj().quad_01_vbo, - r.ctx().make_vertex_buffer(quad_tex_coords) + common_rendering_objects.quad_01_vbo, + rendering_context.make_vertex_buffer(quad_tex_coords) }, // clang-format on - r.obj().quad_fan_indices, + common_rendering_objects.quad_fan_indices, ruis::render::vertex_array::mode::triangle_fan ); } } // namespace nine_patch::nine_patch( - utki::shared_ref renderer, // + const ruis::render::context& rendering_context, // + const ruis::render::renderer::objects& common_rendering_objects, utki::shared_ref image, sides fraction_borders ) : - renderer(std::move(renderer)), // clang-format off vaos{{ { - make_quad_vao(this->renderer, utki::span({ + make_quad_vao(rendering_context, common_rendering_objects, utki::span({ vec2(0, 0), vec2(0, fraction_borders.top()), fraction_borders.left_top(), vec2(fraction_borders.left(), 0) })), - make_quad_vao(this->renderer, utki::span({ + make_quad_vao(rendering_context, common_rendering_objects, utki::span({ vec2(fraction_borders.left(), 0), fraction_borders.left_top(), vec2(real(1) - fraction_borders.right(), fraction_borders.top()), vec2(real(1) - fraction_borders.right(), 0) })), - make_quad_vao(this->renderer, utki::span({ + make_quad_vao(rendering_context, common_rendering_objects, utki::span({ vec2(real(1) - fraction_borders.right(), 0), vec2(real(1) - fraction_borders.right(), fraction_borders.top()), vec2(real(1), fraction_borders.top()), @@ -114,19 +116,19 @@ nine_patch::nine_patch( })) }, { - make_quad_vao(this->renderer, utki::span({ + make_quad_vao(rendering_context, common_rendering_objects, utki::span({ vec2(0, fraction_borders.top()), vec2(0, real(1) - fraction_borders.bottom()), vec2(fraction_borders.left(), real(1) - fraction_borders.bottom()), vec2(fraction_borders.left(), fraction_borders.top()), })), - make_quad_vao(this->renderer, utki::span({ + make_quad_vao(rendering_context, common_rendering_objects, utki::span({ fraction_borders.left_top(), vec2(fraction_borders.left(), real(1) - fraction_borders.bottom()), vec2(real(1) - fraction_borders.right(), real(1) - fraction_borders.bottom()), vec2(real(1) - fraction_borders.right(), fraction_borders.top()) })), - make_quad_vao(this->renderer, utki::span({ + make_quad_vao(rendering_context, common_rendering_objects, utki::span({ vec2(real(1) - fraction_borders.right(), fraction_borders.top()), vec2(real(1) - fraction_borders.right(), real(1) - fraction_borders.bottom()), vec2(real(1), real(1) - fraction_borders.bottom()), @@ -134,19 +136,19 @@ nine_patch::nine_patch( })) }, { - make_quad_vao(this->renderer, utki::span({ + make_quad_vao(rendering_context, common_rendering_objects, utki::span({ vec2(0, real(1) - fraction_borders.bottom()), vec2(0, real(1)), vec2(fraction_borders.left(), real(1)), vec2(fraction_borders.left(), real(1) - fraction_borders.bottom()), })), - make_quad_vao(this->renderer, utki::span({ + make_quad_vao(rendering_context, common_rendering_objects, utki::span({ vec2(fraction_borders.left(), real(1) - fraction_borders.bottom()), vec2(fraction_borders.left(), real(1)), vec2(real(1) - fraction_borders.right(), real(1)), vec2(real(1) - fraction_borders.right(), real(1) - fraction_borders.bottom()), })), - make_quad_vao(this->renderer, utki::span({ + make_quad_vao(rendering_context, common_rendering_objects, utki::span({ vec2(real(1) - fraction_borders.right(), real(1) - fraction_borders.bottom()), vec2(real(1) - fraction_borders.right(), real(1)), vec2(1, 1), diff --git a/src/ruis/res/nine_patch.hpp b/src/ruis/res/nine_patch.hpp index 90757cd0b..1e2c140ad 100644 --- a/src/ruis/res/nine_patch.hpp +++ b/src/ruis/res/nine_patch.hpp @@ -50,8 +50,6 @@ class nine_patch : public resource friend class ruis::resource_loader; public: - const utki::shared_ref renderer; - /** * @brief Nine-patch vertex_array objects in row-column order. */ @@ -71,7 +69,8 @@ class nine_patch : public resource ~nine_patch() override = default; nine_patch( - utki::shared_ref renderer, + const ruis::render::context& rendering_context, + const ruis::render::renderer::objects& common_rendering_objects, utki::shared_ref image, sides fraction_borders ); diff --git a/src/ruis/res/texture_2d.cpp b/src/ruis/res/texture_2d.cpp index b60134c88..2d94a8c40 100644 --- a/src/ruis/res/texture_2d.cpp +++ b/src/ruis/res/texture_2d.cpp @@ -87,7 +87,7 @@ utki::shared_ref texture_2d::load( } } - auto tex = loader.renderer.get().render_context.get().make_texture_2d( // + auto tex = loader.rendering_context.get().make_texture_2d( // rasterimage::read(fi), std::move(params) ); diff --git a/src/ruis/res/texture_cube.cpp b/src/ruis/res/texture_cube.cpp index 9d3d1a058..a9ebf81c4 100644 --- a/src/ruis/res/texture_cube.cpp +++ b/src/ruis/res/texture_cube.cpp @@ -81,7 +81,7 @@ utki::shared_ref texture_cube::load( } } - auto tex = loader.renderer.get().render_context.get().make_texture_cube( // + auto tex = loader.rendering_context.get().make_texture_cube( // rasterimage::read(fi.set_path(check_not_empty(file_px, file_px_param))), rasterimage::read(fi.set_path(check_not_empty(file_nx, file_nx_param))), rasterimage::read(fi.set_path(check_not_empty(file_py, file_py_param))), diff --git a/src/ruis/resource_loader.hpp b/src/ruis/resource_loader.hpp index b97446a09..2e7e19a36 100644 --- a/src/ruis/resource_loader.hpp +++ b/src/ruis/resource_loader.hpp @@ -67,7 +67,9 @@ class resource_loader friend class resource; public: - const utki::shared_ref renderer; + const utki::shared_ref rendering_context; + + const utki::shared_ref common_rendering_objects; private: class res_pack_entry @@ -111,8 +113,12 @@ class resource_loader std::list res_packs; public: - resource_loader(utki::shared_ref renderer) : - renderer(std::move(renderer)) + resource_loader( + utki::shared_ref rendering_context, + utki::shared_ref common_rendering_objects + ) : + rendering_context(std::move(rendering_context)), + common_rendering_objects(std::move(common_rendering_objects)) {} public: diff --git a/src/ruis/widget/base/fraction_widget.cpp b/src/ruis/widget/base/fraction_widget.cpp index 8584a56b8..355c8d6d8 100644 --- a/src/ruis/widget/base/fraction_widget.cpp +++ b/src/ruis/widget/base/fraction_widget.cpp @@ -54,7 +54,11 @@ void fraction_widget::set_fraction( // We still need to call the on_fraction_change() callback, so to make sure the handler // is not invoked by default implementation of the callback, unset it for the time of calling the callback. auto f = std::move(this->fraction_change_handler); - ASSERT(!this->fraction_change_handler) + + // Moving-from does not guarantee it will be nulled out, so set to nullptr explicitly. + // For example it is needed on Macos (clang + libc++). + this->fraction_change_handler = nullptr; + this->on_fraction_change(); this->fraction_change_handler = std::move(f); } diff --git a/src/ruis/widget/base/text_widget.hpp b/src/ruis/widget/base/text_widget.hpp index 77b1ec5e7..fd34e255d 100644 --- a/src/ruis/widget/base/text_widget.hpp +++ b/src/ruis/widget/base/text_widget.hpp @@ -53,7 +53,11 @@ class text_widget : virtual public widget private: parameters params; - utki::enum_array, res::font::style> fonts; + utki::enum_array< + std::shared_ptr, // + res::font::style // + > + fonts; void update_fonts(); void update_fonts_and_notify(); diff --git a/src/ruis/widget/container.cpp b/src/ruis/widget/container.cpp index 0ddcd632b..8f2667ccd 100644 --- a/src/ruis/widget/container.cpp +++ b/src/ruis/widget/container.cpp @@ -270,6 +270,10 @@ widget_list::const_iterator container::insert_internal( throw std::invalid_argument("container::insert(): the widget is already added to some other container"); } + if (ww.context.to_shared_ptr() != this->context.to_shared_ptr()) { + throw std::invalid_argument("container::insert(): cannot insert widget from another GUI context"); + } + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access) auto ret = this->children_list.variable.emplace( before, // diff --git a/src/ruis/widget/group/tiling_area.cpp b/src/ruis/widget/group/tiling_area.cpp index da956968b..870619c1b 100644 --- a/src/ruis/widget/group/tiling_area.cpp +++ b/src/ruis/widget/group/tiling_area.cpp @@ -38,7 +38,7 @@ class dragger : public ruis::gap tiling_area& owner; - ruis::mouse_cursor_stack::iterator arrows_cursor_iter; + ruis::render::native_window::cursor_id arrows_cursor_iter; public: // TODO: use shared_ref? @@ -74,7 +74,7 @@ class dragger : public ruis::gap if (!this->grabbed) { if (!this->is_hovered()) { - this->context.get().cursor_stack.pop(this->arrows_cursor_iter); + this->context.get().window().pop_mouse_cursor(this->arrows_cursor_iter); } } @@ -138,7 +138,7 @@ class dragger : public ruis::gap } if (this->is_hovered() || grabbed) { - this->arrows_cursor_iter = this->context.get().cursor_stack.push( // + this->arrows_cursor_iter = this->context.get().window().push_mouse_cursor( // [&]() { if (this->owner.is_vertical()) { return ruis::mouse_cursor::up_down_arrow; @@ -148,7 +148,7 @@ class dragger : public ruis::gap }() ); } else { - this->context.get().cursor_stack.pop(this->arrows_cursor_iter); + this->context.get().window().pop_mouse_cursor(this->arrows_cursor_iter); } } diff --git a/src/ruis/widget/group/window.cpp b/src/ruis/widget/group/window.cpp index fc8c3f986..741e66b8e 100644 --- a/src/ruis/widget/group/window.cpp +++ b/src/ruis/widget/group/window.cpp @@ -416,7 +416,7 @@ void ruis::window::setup_widgets() this->title_bg = this->try_get_widget_as("ruis_window_title_bg"); ASSERT(this->title_bg); - auto make_mouse_button_handler = [this](cursor_iter& iter) { + auto make_mouse_button_handler = [this](ruis::render::native_window::cursor_id& iter) { return decltype(mouse_proxy::mouse_button_handler)([this, &iter](mouse_proxy& mp, const mouse_button_event& e) { if (e.button != mouse_button::left) { return false; @@ -428,14 +428,14 @@ void ruis::window::setup_widgets() this->capture_point = e.pos; } else { if (!mp.is_hovered()) { - this->context.get().cursor_stack.pop(iter); + this->context.get().window().pop_mouse_cursor(iter); } } return true; }); }; - auto make_hovered_change_handler = [this](ruis::mouse_cursor cursor, cursor_iter& iter) { + auto make_hovered_change_handler = [this](ruis::mouse_cursor cursor, render::native_window::cursor_id& iter) { return [this, cursor, &iter](mouse_proxy& mp, unsigned pointer_id) { // LOG("hover = " << mp.is_hovered() << std::endl) // LOG("this->mouse_captured = " << this->mouse_captured << std::endl) @@ -443,9 +443,9 @@ void ruis::window::setup_widgets() return; } if (mp.is_hovered()) { - iter = this->context.get().cursor_stack.push(cursor); + iter = this->context.get().window().push_mouse_cursor(cursor); } else { - this->context.get().cursor_stack.pop(iter); + this->context.get().window().pop_mouse_cursor(iter); } }; }; diff --git a/src/ruis/widget/group/window.hpp b/src/ruis/widget/group/window.hpp index 4979ccc82..0a193944a 100644 --- a/src/ruis/widget/group/window.hpp +++ b/src/ruis/widget/group/window.hpp @@ -63,16 +63,15 @@ class window : std::shared_ptr lb_border; std::shared_ptr rb_border; - using cursor_iter = decltype(std::declval().push(mouse_cursor::arrow)); - cursor_iter caption_cursor_iter; - cursor_iter lt_border_cursor_iter; - cursor_iter rt_border_cursor_iter; - cursor_iter t_border_cursor_iter; - cursor_iter l_border_cursor_iter; - cursor_iter r_border_cursor_iter; - cursor_iter b_border_cursor_iter; - cursor_iter lb_border_cursor_iter; - cursor_iter rb_border_cursor_iter; + render::native_window::cursor_id caption_cursor_iter; + render::native_window::cursor_id lt_border_cursor_iter; + render::native_window::cursor_id rt_border_cursor_iter; + render::native_window::cursor_id t_border_cursor_iter; + render::native_window::cursor_id l_border_cursor_iter; + render::native_window::cursor_id r_border_cursor_iter; + render::native_window::cursor_id b_border_cursor_iter; + render::native_window::cursor_id lb_border_cursor_iter; + render::native_window::cursor_id rb_border_cursor_iter; bool mouse_captured = false; ruis::vector2 capture_point; diff --git a/src/ruis/widget/input/text_input_line.cpp b/src/ruis/widget/input/text_input_line.cpp index 088e42f01..6bb5400a3 100644 --- a/src/ruis/widget/input/text_input_line.cpp +++ b/src/ruis/widget/input/text_input_line.cpp @@ -102,6 +102,7 @@ void text_input_line::render(const ruis::matrix4& matrix) const ASSERT(this->first_visible_char_index <= this->get_string().size()) font.render( + this->ctx().ren(), // matr, this->get_current_color(), this->get_string().substr( diff --git a/src/ruis/widget/label/gradient.cpp b/src/ruis/widget/label/gradient.cpp index 15a81393f..8bc1bfed3 100644 --- a/src/ruis/widget/label/gradient.cpp +++ b/src/ruis/widget/label/gradient.cpp @@ -40,13 +40,16 @@ gradient::gradient( // void gradient::render(const matrix4& matrix) const { - this->context.get().renderer.get().render_context.get().set_simple_alpha_blending(); + this->context.get().renderer.get().rendering_context.get().set_simple_alpha_blending(); ruis::matrix4 matr(matrix); matr.scale(this->rect().d); if (this->params.gradient) { // TRACE(<< "this->rect().d = " << this->rect().d << std::endl) - this->params.gradient->render(matr); + this->params.gradient->render( + this->ctx().ren(), // + matr + ); } } diff --git a/src/ruis/widget/label/rectangle.cpp b/src/ruis/widget/label/rectangle.cpp index d76ccef8c..1f0f5f81b 100644 --- a/src/ruis/widget/label/rectangle.cpp +++ b/src/ruis/widget/label/rectangle.cpp @@ -69,7 +69,7 @@ void rectangle::render(const ruis::matrix4& matrix) const { auto& r = this->context.get().renderer.get(); - r.render_context.get().set_simple_alpha_blending(); + r.rendering_context.get().set_simple_alpha_blending(); if (!this->rounded_corners_tex) { ruis::matrix4 matr(matrix); diff --git a/src/ruis/widget/label/text.cpp b/src/ruis/widget/label/text.cpp index 1448ed08b..70fa6acf0 100644 --- a/src/ruis/widget/label/text.cpp +++ b/src/ruis/widget/label/text.cpp @@ -61,7 +61,8 @@ void text::render(const ruis::matrix4& matrix) const ); font.render( - matr, // + this->ctx().ren(), // + matr, this->get_current_color(), this->get_string() ); diff --git a/src/ruis/widget/widget.cpp b/src/ruis/widget/widget.cpp index 691913b48..35113eaf6 100644 --- a/src/ruis/widget/widget.cpp +++ b/src/ruis/widget/widget.cpp @@ -159,11 +159,11 @@ void widget::render_internal(const ruis::matrix4& matrix) const if (this->params.cache) { if (this->cache_dirty) { utki::scope_exit scissor_test_enabled_scope_exit( - [&r, scissor_test_was_enabled = r.render_context.get().is_scissor_enabled()]() { - r.render_context.get().enable_scissor(scissor_test_was_enabled); + [&r, scissor_test_was_enabled = r.rendering_context.get().is_scissor_enabled()]() { + r.rendering_context.get().enable_scissor(scissor_test_was_enabled); } ); - r.render_context.get().enable_scissor(false); + r.rendering_context.get().enable_scissor(false); this->cache_frame_buffer = this->render_to_texture(std::move(this->cache_frame_buffer)).to_shared_ptr(); @@ -171,41 +171,41 @@ void widget::render_internal(const ruis::matrix4& matrix) const } // after rendering to texture it is most likely there will be transparent areas, so enable simple blending - this->context.get().renderer.get().render_context.get().set_simple_alpha_blending(); + this->context.get().renderer.get().rendering_context.get().set_simple_alpha_blending(); this->render_from_cache(matrix); } else { if (this->params.depth) { - r.render_context.get().enable_depth(true); - r.render_context.get().clear_framebuffer_depth(); + r.rendering_context.get().enable_depth(true); + r.rendering_context.get().clear_framebuffer_depth(); } if (this->params.clip) { r4::rectangle scissor = this->compute_viewport_rect(matrix); r4::rectangle old_scissor{}; - bool scissor_test_was_enabled = r.render_context.get().is_scissor_enabled(); + bool scissor_test_was_enabled = r.rendering_context.get().is_scissor_enabled(); if (scissor_test_was_enabled) { - old_scissor = r.render_context.get().get_scissor(); + old_scissor = r.rendering_context.get().get_scissor(); scissor.intersect(old_scissor); } else { - r.render_context.get().enable_scissor(true); + r.rendering_context.get().enable_scissor(true); } - r.render_context.get().set_scissor(scissor); + r.rendering_context.get().set_scissor(scissor); this->render(matrix); if (scissor_test_was_enabled) { - r.render_context.get().set_scissor(old_scissor); + r.rendering_context.get().set_scissor(old_scissor); } else { - r.render_context.get().enable_scissor(false); + r.rendering_context.get().enable_scissor(false); } } else { this->render(matrix); } - r.render_context.get().enable_depth(false); + r.rendering_context.get().enable_depth(false); } // render border @@ -237,31 +237,31 @@ utki::shared_ref widget::render_to_texture(std::shared_ptr return utki::shared_ref(std::move(reuse)); } - return r.render_context.get().make_framebuffer( - r.render_context.get().make_texture_2d( // + return r.rendering_context.get().make_framebuffer( + r.rendering_context.get().make_texture_2d( // rasterimage::format::rgba, dims, {} ), - this->params.depth ? r.render_context.get().make_texture_depth(dims) + this->params.depth ? r.rendering_context.get().make_texture_depth(dims) : std::shared_ptr(nullptr), nullptr ); }(); fb.get().apply([&]() { - r.render_context.get().clear_framebuffer_color(); + r.rendering_context.get().clear_framebuffer_color(); - utki::scope_exit depth_scope_exit([old_depth = r.render_context.get().is_depth_enabled(), &r]() { - r.render_context.get().enable_depth(old_depth); + utki::scope_exit depth_scope_exit([old_depth = r.rendering_context.get().is_depth_enabled(), &r]() { + r.rendering_context.get().enable_depth(old_depth); }); - r.render_context.get().enable_depth(this->params.depth); + r.rendering_context.get().enable_depth(this->params.depth); if (this->params.depth) { - r.render_context.get().clear_framebuffer_depth(); + r.rendering_context.get().clear_framebuffer_depth(); } - this->render(make_viewport_matrix(r.render_context.get().initial_matrix, this->rect().d)); + this->render(make_viewport_matrix(r.rendering_context.get().initial_matrix, this->rect().d)); }); return fb; @@ -332,8 +332,8 @@ r4::rectangle widget::compute_viewport_rect(const matrix4& matrix) con using std::round; r4::rectangle ret{ - {this->context.get().renderer.get().render_context.get().to_window_coords(matrix * vector2(0, 0)), - this->context.get().renderer.get().render_context.get().to_window_coords(matrix * this->rect().d)} + {this->context.get().renderer.get().rendering_context.get().to_window_coords(matrix * vector2(0, 0)), + this->context.get().renderer.get().rendering_context.get().to_window_coords(matrix * this->rect().d)} }; return ret; } diff --git a/tests/align/src/main.cpp b/tests/align/src/main.cpp index 2c16db03d..11ae78033 100644 --- a/tests/align/src/main.cpp +++ b/tests/align/src/main.cpp @@ -312,18 +312,27 @@ utki::shared_ref make_layout(utki::shared_ref c) } class application : public ruisapp::application{ + ruisapp::window& window; public: application() : ruisapp::application( - "ruis-tests", + { + .name = "ruis-tests" + } + ), + window(this->make_window( { .dims = {1024, 800} } - ) + )) { - this->gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); + this->window.gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); + + this->window.gui.set_root(make_layout(this->window.gui.context)); - this->gui.set_root(make_layout(this->gui.context)); + this->window.gui.context.get().window().close_handler = [this](){ + this->quit(); + }; } }; diff --git a/tests/app/src/cube_widget.cpp b/tests/app/src/cube_widget.cpp index 4c3fc5a42..f822dd4ca 100644 --- a/tests/app/src/cube_widget.cpp +++ b/tests/app/src/cube_widget.cpp @@ -26,7 +26,7 @@ cube_widget::cube_widget( ruis::vector3(-1, -1, 1), ruis::vector3( 1, -1, -1), ruis::vector3( 1, -1, 1) }}; - auto pos_vbo = this->context.get().renderer.get().render_context.get().make_vertex_buffer(utki::make_span(cube_pos)); + auto pos_vbo = this->context.get().renderer.get().rendering_context.get().make_vertex_buffer(utki::make_span(cube_pos)); // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) std::array cube_tex = {{ @@ -44,7 +44,7 @@ cube_widget::cube_widget( ruis::vector2(1, 0), ruis::vector2(1, 1), ruis::vector2(0, 1) }}; - auto tex_vbo = this->context.get().renderer.get().render_context.get().make_vertex_buffer(utki::make_span(cube_tex)); + auto tex_vbo = this->context.get().renderer.get().rendering_context.get().make_vertex_buffer(utki::make_span(cube_tex)); // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) std::array indices = {{ @@ -52,9 +52,9 @@ cube_widget::cube_widget( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 }}; - auto cube_indices = this->context.get().renderer.get().render_context.get().make_index_buffer(utki::make_span(indices)); + auto cube_indices = this->context.get().renderer.get().rendering_context.get().make_index_buffer(utki::make_span(indices)); - this->cubeVAO = this->context.get().renderer.get().render_context.get().make_vertex_array( + this->cubeVAO = this->context.get().renderer.get().rendering_context.get().make_vertex_array( {pos_vbo, tex_vbo}, cube_indices, ruis::render::vertex_array::mode::triangles @@ -70,7 +70,9 @@ void cube_widget::update(uint32_t dt){ // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers) this->rot *= ruis::quaternion().set_rotation(r4::vector3(1, 2, 1).normalize(), 1.5f * (float(dt) / std::milli::den)); if(this->fpsSecCounter >= std::milli::den){ - std::cout << "fps = " << std::dec << fps << std::endl; + utki::log([&](auto&o){ + o << "fps = " << std::dec << fps << std::endl; + }); this->fpsSecCounter = 0; this->fps = 0; } @@ -91,5 +93,5 @@ void cube_widget::render(const ruis::matrix4& matrix)const{ // glDisable(GL_CULL_FACE); - this->context.get().renderer.get().obj().shaders.get().pos_tex->render(matr, *this->cubeVAO, this->tex->tex()); + this->context.get().renderer.get().shaders().pos_tex->render(matr, *this->cubeVAO, this->tex->tex()); } diff --git a/tests/app/src/main.cpp b/tests/app/src/main.cpp index 11846148d..e9eff2ab1 100644 --- a/tests/app/src/main.cpp +++ b/tests/app/src/main.cpp @@ -55,23 +55,32 @@ using namespace ruis::make; } class application : public ruisapp::application{ + ruisapp::window& window; public: application() : ruisapp::application( - "ruis-tests", { - .dims = {1024, 800}, - .buffers = {ruisapp::buffer::depth} + .name = "ruis-tests"s } - ) + ), + window(this->make_window({ + .dims = {1024, 800}, + .buffers = {ruisapp::buffer::depth} + })) { - this->gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); + this->window.gui.context.get().window().close_handler = [this](){ + this->quit(); + }; + + auto& gui = this->window.gui; + + gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); - this->gui.context.get().loader().mount_res_pack(*this->get_res_file("res/")); + gui.context.get().loader().mount_res_pack(*this->get_res_file("res/")); // this->ResMan().MountResPack(ruis::ZipFile::New(papki::FSFile::New("res.zip"))); - auto c = make_root_widget(this->gui.context); - this->gui.set_root(c); + auto c = make_root_widget(gui.context); + gui.set_root(c); utki::dynamic_reference_cast(c).get().key_handler = [this](ruis::key_proxy&, const ruis::key_event& e) -> bool { if(e.is_down){ @@ -90,10 +99,10 @@ class application : public ruisapp::application{ this->show_virtual_keyboard(); }; - std::dynamic_pointer_cast(c.get().try_get_widget("push_button_in_scroll_container"))->click_handler = [this](ruis::push_button&){ - this->gui.context.get().post_to_ui_thread( + std::dynamic_pointer_cast(c.get().try_get_widget("push_button_in_scroll_container"))->click_handler = [ctx = gui.context](ruis::push_button&){ + ctx.get().post_to_ui_thread( [](){ - std::cout << "Print from UI thread!!!!!!!!" << std::endl; + utki::logcat("Print from UI thread!!!!!!!!", '\n'); } ); }; @@ -322,26 +331,27 @@ class application : public ruisapp::application{ { auto b = c.get().try_get_widget_as("fullscreen_button"); ASSERT(b) - b->click_handler = [this](ruis::push_button&) { - this->set_fullscreen(!this->is_fullscreen()); + b->click_handler = [](ruis::push_button& b) { + auto& w = b.context.get().window(); + w.set_fullscreen(!w.is_fullscreen()); }; } { auto b = c.get().try_get_widget_as("image_push_button"); ASSERT(b) - b->click_handler = [this](ruis::push_button&) { - this->set_fullscreen(true); + b->click_handler = [](ruis::push_button& b) { + b.context.get().window().set_fullscreen(true); }; } // mouse cursor { - auto b = c.get().try_get_widget_as("showhide_mousecursor_button"); + auto& b = c.get().get_widget_as("showhide_mousecursor_button"); bool visible = true; - this->set_mouse_cursor_visible(visible); - b->click_handler = [visible, this](ruis::push_button&) mutable{ + b.context.get().window().set_mouse_cursor_visible(visible); + b.click_handler = [visible](ruis::push_button& b) mutable{ visible = !visible; - this->set_mouse_cursor_visible(visible); + b.context.get().window().set_mouse_cursor_visible(visible); }; } diff --git a/tests/app/src/new_native_window.cpp b/tests/app/src/new_native_window.cpp new file mode 100644 index 000000000..4c8e70aad --- /dev/null +++ b/tests/app/src/new_native_window.cpp @@ -0,0 +1,97 @@ +#include "new_native_window.hpp" + +#include +#include +#include +#include +#include +#include + +using namespace std::string_literals; +using namespace std::string_view_literals; + +namespace m{ +using namespace ruis::make; +} + +utki::shared_ref make_new_native_window_root_widget( + utki::shared_ref c, // + ruisapp::window& win +){ + // clang-format off + auto button = m::push_button(c, + { + .layout_params{ + .dims{ruis::dim::fill, ruis::dim::fill}, + .weight = 1 + } + }, + { + m::text(c, {}, U"the button"s) + } + ); + // clang-format on + + button.get().click_handler = [](ruis::push_button& b){ + utki::logcat("the button clicked", '\n'); + }; + + // clang-format off + auto close_button = m::push_button(c, + {}, + { + m::text(c, {}, U"X"s) + } + ); + // clang-format on + + close_button.get().click_handler = [&win](auto& b){ + ruisapp::inst().destroy_window(win); + }; + + // clang-format off + return m::column(c, + {}, + { + m::row(c, + { + .layout_params{ + .align = {ruis::align::front, ruis::align::center} + } + }, + { + m::text(c, {}, U"Native window"s), + std::move(close_button) + } + ), + m::nine_patch(c, + { + .layout_params{ + .dims{ruis::dim::max, ruis::dim::min} + }, + .widget_params{ + .id = "text_input"s + }, + .nine_patch_params{ + .nine_patch = c.get().loader().load("ruis_npt_textfield_background"sv) + } + }, + { + m::text_input_line(c, + { + .layout_params{ + .dims{ruis::dim::fill, ruis::dim::max} + }, + .color_params{ + .color = c.get().style().get_color_text_normal() + } + }, + U"Hello Wrodl!!!"s + ) + } + ), + std::move(button) + } + ); + // clang-format on +} diff --git a/tests/app/src/new_native_window.hpp b/tests/app/src/new_native_window.hpp new file mode 100644 index 000000000..03e3e1fa7 --- /dev/null +++ b/tests/app/src/new_native_window.hpp @@ -0,0 +1,9 @@ +#pragma once + +#include +#include + +utki::shared_ref make_new_native_window_root_widget( + utki::shared_ref c, // + ruisapp::window& win +); diff --git a/tests/app/src/text_input_window.cpp b/tests/app/src/text_input_window.cpp index 8715e2f9e..ae1862806 100644 --- a/tests/app/src/text_input_window.cpp +++ b/tests/app/src/text_input_window.cpp @@ -7,6 +7,9 @@ #include #include #include +#include + +#include "new_native_window.hpp" using namespace std::string_literals; using namespace std::string_view_literals; @@ -47,6 +50,35 @@ utki::shared_ref make_text_input_window( ruis::vec2_length pos ) { + // clang-format off + auto new_native_window_button = m::push_button(c, + {}, + { + m::text(c, {}, U"new native window"s) + } + ); + // clang-format on + + new_native_window_button.get().click_handler = [](ruis::push_button& b){ + utki::logcat("new native window button clicked", '\n'); + + auto& nw = ruisapp::inst().make_window( + { + .title = "new native_window"s, + .taskbar = false + } + ); + + auto c = make_new_native_window_root_widget(nw.gui.context, // + nw); + nw.gui.set_root(c); + + nw.gui.context.get().window().close_handler = [&nw](){ + utki::logcat("native window close handler called", '\n'); + ruisapp::inst().destroy_window(nw); + }; + }; + // clang-format off return m::window(c, { @@ -131,7 +163,8 @@ utki::shared_ref make_text_input_window( .pressed_image = c.get().loader().load("img_button_pressed"sv) } } - ) + ), + std::move(new_native_window_button) } ) } diff --git a/tests/app2/makefile b/tests/app2/makefile index 53cb41da8..926b21061 100644 --- a/tests/app2/makefile +++ b/tests/app2/makefile @@ -1,8 +1,13 @@ include prorab.mk include prorab-test.mk +include prorab-clang-format.mk +include prorab-license.mk this__is_interactive := true include $(d)../common.mk $(eval $(prorab-clang-format)) + +this_license_file := ../../LICENSE +$(eval $(prorab-license)) diff --git a/tests/app2/src/application.cpp b/tests/app2/src/application.cpp new file mode 100644 index 000000000..a170847e0 --- /dev/null +++ b/tests/app2/src/application.cpp @@ -0,0 +1,66 @@ +/* +ruis - GUI framework + +Copyright (C) 2012-2025 Ivan Gagis + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* ================ LICENSE END ================ */ + +#include "application.hpp" + +#include +#include + +#include "gui.hpp" + +application::application() : + ruisapp::application({ + .name = "ruis-tests" +}), + window(this->make_window({.dims = {1024, 800}})) +{ + this->window.gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); + + this->window.gui.context.get().localization.get() = + ruis::localization(tml::read(*this->get_res_file("res/localization/en.tml"))); + + this->window.gui.context.get().loader().mount_res_pack(*this->get_res_file("res/")); + + // clang-format off + auto kp = ruis::make::key_proxy( + this->window.gui.context, + { + .container_params{ + .layout = ruis::layout::pile + } + }, + { + make_root_widgets_structure(this->window.gui.context) + } + ); + // clang-format on + + kp.get().key_handler = [this](ruis::key_proxy&, const ruis::key_event& e) -> bool { + if (e.is_down) { + if (e.combo.key == ruis::key::escape) { + this->quit(); + } + } + return false; + }; + + this->window.gui.set_root(std::move(kp)); +} diff --git a/src/ruis/util/mouse_cursor_stack.hpp b/tests/app2/src/application.hpp similarity index 63% rename from src/ruis/util/mouse_cursor_stack.hpp rename to tests/app2/src/application.hpp index 07d7f7537..f217d880b 100644 --- a/src/ruis/util/mouse_cursor_stack.hpp +++ b/tests/app2/src/application.hpp @@ -21,27 +21,18 @@ along with this program. If not, see . #pragma once -#include -#include +#include -#include "mouse_cursor.hpp" - -namespace ruis { - -class mouse_cursor_stack +class application : public ruisapp::application { - std::list cursor_stack = {mouse_cursor::arrow}; - - const std::function set_mouse_cursor; - public: - using iterator = decltype(cursor_stack)::iterator; - - mouse_cursor_stack(std::function set_mouse_cursor); + ruisapp::window& window; - iterator push(mouse_cursor cursor); + application(); - void pop(iterator i); + static application& inst() + { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-static-cast-downcast, "intentional") + return static_cast(ruisapp::inst()); + } }; - -} // namespace ruis diff --git a/tests/app2/src/gui.cpp b/tests/app2/src/gui.cpp index b53058ff6..829f7fe2f 100644 --- a/tests/app2/src/gui.cpp +++ b/tests/app2/src/gui.cpp @@ -1,3 +1,24 @@ +/* +ruis - GUI framework + +Copyright (C) 2012-2025 Ivan Gagis + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* ================ LICENSE END ================ */ + #include "gui.hpp" #include @@ -14,6 +35,7 @@ #include #include +#include "application.hpp" #include "rectangles_window.hpp" #include "table_list_window.hpp" #include "table_tree_view_window.hpp" @@ -301,13 +323,13 @@ utki::shared_ref make_selection_box_window( ASSERT(sel < language_id_to_name_mapping.size()) sb.context.get().post_to_ui_thread([lng = language_id_to_name_mapping.at(sel).first]() { - auto& app = ruisapp::inst(); + auto& app = application::inst(); // std::cout << "new localization = " << lng << std::endl; - app.gui.context.get().localization.get() = + app.window.gui.context.get().localization.get() = ruis::localization(tml::read(*app.get_res_file(utki::cat("res/localization/", lng, ".tml")))); - app.gui.get_root().reload(); + app.window.gui.get_root().reload(); }); }; diff --git a/tests/app2/src/gui.hpp b/tests/app2/src/gui.hpp index 98d6e289c..7c70a5f09 100644 --- a/tests/app2/src/gui.hpp +++ b/tests/app2/src/gui.hpp @@ -1,3 +1,24 @@ +/* +ruis - GUI framework + +Copyright (C) 2012-2025 Ivan Gagis + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* ================ LICENSE END ================ */ + #pragma once #include diff --git a/tests/app2/src/main.cpp b/tests/app2/src/main.cpp index 125aafd4c..24977416a 100644 --- a/tests/app2/src/main.cpp +++ b/tests/app2/src/main.cpp @@ -1,52 +1,25 @@ -#include -#include +/* +ruis - GUI framework -#include "gui.hpp" +Copyright (C) 2012-2025 Ivan Gagis -class application : public ruisapp::application -{ -public: - application() : - ruisapp::application( - "ruis-tests", - { - .dims = {1024, 800} - } - ) - { - this->gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. - this->gui.context.get().localization.get() = - ruis::localization(tml::read(*this->get_res_file("res/localization/en.tml"))); +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. - this->gui.context.get().loader().mount_res_pack(*this->get_res_file("res/")); +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ - // clang-format off - auto kp = ruis::make::key_proxy( - this->gui.context, - { - .container_params{ - .layout = ruis::layout::pile - } - }, - { - make_root_widgets_structure(this->gui.context) - } - ); - // clang-format on +/* ================ LICENSE END ================ */ - kp.get().key_handler = [this](ruis::key_proxy&, const ruis::key_event& e) -> bool { - if (e.is_down) { - if (e.combo.key == ruis::key::escape) { - this->quit(); - } - } - return false; - }; - - this->gui.set_root(std::move(kp)); - } -}; +#include "application.hpp" const ruisapp::application_factory app_fac([](auto executable, auto args) { return std::make_unique<::application>(); diff --git a/tests/app2/src/rectangles_window.cpp b/tests/app2/src/rectangles_window.cpp index 189f5f09f..1516e1a44 100644 --- a/tests/app2/src/rectangles_window.cpp +++ b/tests/app2/src/rectangles_window.cpp @@ -1,3 +1,24 @@ +/* +ruis - GUI framework + +Copyright (C) 2012-2025 Ivan Gagis + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* ================ LICENSE END ================ */ + #include "rectangles_window.hpp" #include diff --git a/tests/app2/src/rectangles_window.hpp b/tests/app2/src/rectangles_window.hpp index e1373d611..58a2a77ea 100644 --- a/tests/app2/src/rectangles_window.hpp +++ b/tests/app2/src/rectangles_window.hpp @@ -1,3 +1,24 @@ +/* +ruis - GUI framework + +Copyright (C) 2012-2025 Ivan Gagis + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* ================ LICENSE END ================ */ + #pragma once #include diff --git a/tests/app2/src/table_list_window.cpp b/tests/app2/src/table_list_window.cpp index de2d9b2c3..6de7e35bb 100644 --- a/tests/app2/src/table_list_window.cpp +++ b/tests/app2/src/table_list_window.cpp @@ -1,3 +1,24 @@ +/* +ruis - GUI framework + +Copyright (C) 2012-2025 Ivan Gagis + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* ================ LICENSE END ================ */ + #include "table_list_window.hpp" #include diff --git a/tests/app2/src/table_list_window.hpp b/tests/app2/src/table_list_window.hpp index be47261c0..88046b371 100644 --- a/tests/app2/src/table_list_window.hpp +++ b/tests/app2/src/table_list_window.hpp @@ -1,3 +1,24 @@ +/* +ruis - GUI framework + +Copyright (C) 2012-2025 Ivan Gagis + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* ================ LICENSE END ================ */ + #pragma once #include diff --git a/tests/app2/src/table_tree_view_window.cpp b/tests/app2/src/table_tree_view_window.cpp index 7c95ec1cd..dee45fe3b 100644 --- a/tests/app2/src/table_tree_view_window.cpp +++ b/tests/app2/src/table_tree_view_window.cpp @@ -1,3 +1,24 @@ +/* +ruis - GUI framework + +Copyright (C) 2012-2025 Ivan Gagis + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* ================ LICENSE END ================ */ + #include "table_tree_view_window.hpp" #include diff --git a/tests/app2/src/table_tree_view_window.hpp b/tests/app2/src/table_tree_view_window.hpp index 467880e01..4278580a7 100644 --- a/tests/app2/src/table_tree_view_window.hpp +++ b/tests/app2/src/table_tree_view_window.hpp @@ -1,3 +1,24 @@ +/* +ruis - GUI framework + +Copyright (C) 2012-2025 Ivan Gagis + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* ================ LICENSE END ================ */ + #pragma once #include diff --git a/tests/aspect_ratio_proxy/src/main.cpp b/tests/aspect_ratio_proxy/src/main.cpp index 6a72f2f4f..ca1f3bd7e 100644 --- a/tests/aspect_ratio_proxy/src/main.cpp +++ b/tests/aspect_ratio_proxy/src/main.cpp @@ -14,26 +14,33 @@ using namespace ruis::make; } class application : public ruisapp::application{ + ruisapp::window& window; public: application() : - ruisapp::application( - "ruis-tests", - { + ruisapp::application({ + .name = "ruis-tests"} + ), + window(this->make_window({ .dims = {1024, 800} - } - ) + })) { - this->gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); + this->window.gui.context.get().window().close_handler = [this](){ + this->quit(); + }; + + this->window.gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); + + auto ctx = this->window.gui.context; // clang-format off - auto c = m::container(this->gui.context, + auto c = m::container(ctx, { .container_params{ .layout = ruis::layout::trivial } }, { - m::window(this->gui.context, + m::window(ctx, { .widget_params{ .rectangle = {{200, 200}, {200, 100}} @@ -44,14 +51,14 @@ class application : public ruisapp::application{ .title = U"aspect ratio proxy"s }, { - m::pile(this->gui.context, + m::pile(ctx, { .layout_params{ .dims = {ruis::dim::min, ruis::dim::fill} } }, { - m::aspect_ratio_proxy(this->gui.context, + m::aspect_ratio_proxy(ctx, { .layout_params{ .dims = {ruis::dim::min, ruis::dim::fill} @@ -61,7 +68,7 @@ class application : public ruisapp::application{ } } ), - m::rectangle(this->gui.context, + m::rectangle(ctx, { .layout_params{ .dims = {ruis::dim::fill, ruis::dim::fill} @@ -71,7 +78,7 @@ class application : public ruisapp::application{ } } ), - m::text(this->gui.context, + m::text(ctx, {}, U"1:2"s ) @@ -83,7 +90,7 @@ class application : public ruisapp::application{ ); // clang-format on - this->gui.set_root(c); + this->window.gui.set_root(c); } }; diff --git a/tests/book/src/cube_page.cpp b/tests/book/src/cube_page.cpp index e1b48cae2..2f6de1356 100644 --- a/tests/book/src/cube_page.cpp +++ b/tests/book/src/cube_page.cpp @@ -47,7 +47,7 @@ class cube_widget : public ruis::widget, public ruis::updateable{ {-1, -1, 1}, {1, -1, -1}, { 1, -1, 1} }}; - auto pos_vbo = this->context.get().renderer.get().render_context.get().make_vertex_buffer(utki::make_span(cube_pos)); + auto pos_vbo = this->context.get().renderer.get().rendering_context.get().make_vertex_buffer(utki::make_span(cube_pos)); std::array cube_tex = {{ {0, 0}, {1, 0}, {0, 1}, @@ -64,15 +64,15 @@ class cube_widget : public ruis::widget, public ruis::updateable{ {1, 0}, {1, 1}, {0, 1} }}; - auto tex_vbo = this->context.get().renderer.get().render_context.get().make_vertex_buffer(utki::make_span(cube_tex)); + auto tex_vbo = this->context.get().renderer.get().rendering_context.get().make_vertex_buffer(utki::make_span(cube_tex)); std::array indices = {{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 }}; - auto cube_indices = this->context.get().renderer.get().render_context.get().make_index_buffer(utki::make_span(indices)); + auto cube_indices = this->context.get().renderer.get().rendering_context.get().make_index_buffer(utki::make_span(indices)); - this->cube_vao = this->context.get().renderer.get().render_context.get().make_vertex_array( + this->cube_vao = this->context.get().renderer.get().rendering_context.get().make_vertex_array( { pos_vbo, tex_vbo diff --git a/tests/book/src/main.cpp b/tests/book/src/main.cpp index ae30604bd..b137d645a 100644 --- a/tests/book/src/main.cpp +++ b/tests/book/src/main.cpp @@ -24,24 +24,33 @@ namespace m{ } class application : public ruisapp::application{ + ruisapp::window& window; public: application() : - ruisapp::application( - "ruis-tests", + ruisapp::application({ + .name = "ruis-tests" + }), + window(this->make_window( { .dims = {640, 480} } - ) + )) { - this->gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); + this->window.gui.context.get().window().close_handler = [this](){ + this->quit(); + }; - this->gui.context.get().loader().mount_res_pack(*this->get_res_file("res/")); + this->window.gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); + + this->window.gui.context.get().loader().mount_res_pack(*this->get_res_file("res/")); + + auto& ctx = this->window.gui.context; // clang-format off - auto c = m::column(this->gui.context, + auto c = m::column(ctx, {}, { - m::book(this->gui.context, + m::book(ctx, { .layout_params{ .dims = {ruis::dim::fill, ruis::dim::max}, @@ -56,12 +65,12 @@ class application : public ruisapp::application{ ); // clang-format on - this->gui.set_root(c); + this->window.gui.set_root(c); auto& book = c.get().get_widget_as("book"); { - auto mp = make_main_page(this->gui.context); + auto mp = make_main_page(ctx); mp.get().get_widget_as("cube_button").click_handler = [&mp = mp.get()](ruis::push_button& b){ mp.get_parent_book()->push(utki::make_shared(mp.context)); diff --git a/tests/busy/src/main.cpp b/tests/busy/src/main.cpp index d32760a34..db1511f52 100644 --- a/tests/busy/src/main.cpp +++ b/tests/busy/src/main.cpp @@ -10,19 +10,25 @@ #include "root_gui.hpp" class application : public ruisapp::application{ + ruisapp::window& window; public: application() : ruisapp::application( - "ruis-tests", { + .name = "ruis-tests"} + ), + window(this->make_window({ .dims = {1024, 800} - } - ) + })) { - this->gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); + this->window.gui.context.get().window().close_handler = [this](){ + this->quit(); + }; + + this->window.gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); - auto c = make_root_gui(this->gui.context); - this->gui.set_root(c); + auto c = make_root_gui(this->window.gui.context); + this->window.gui.set_root(c); { auto spinner = utki::make_weak_from( diff --git a/tests/easing/src/main.cpp b/tests/easing/src/main.cpp index eec13a235..4fdeb0e20 100644 --- a/tests/easing/src/main.cpp +++ b/tests/easing/src/main.cpp @@ -5,23 +5,23 @@ class application : public ruisapp::application { + ruisapp::window& window; + public: application() : - ruisapp::application( - "ruis-tests", - { - .dims = {1024, 800} - } - ) + ruisapp::application({ + .name = "ruis-tests", + }), + window(this->make_window({.dims = {1024, 800}})) { - this->gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); + this->window.gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); // this->gui.context.get().loader.mount_res_pack(*this->get_res_file("res/")); auto kp = ruis::make::key_proxy( - this->gui.context, + this->window.gui.context, {.container_params = {.layout = ruis::layout::pile}}, - {make_gui(this->gui.context)} + {make_gui(this->window.gui.context)} ); kp.get().key_handler = [this](ruis::key_proxy&, const ruis::key_event& e) -> bool { @@ -33,7 +33,11 @@ class application : public ruisapp::application return false; }; - this->gui.set_root(std::move(kp)); + this->window.gui.set_root(std::move(kp)); + + this->window.gui.context.get().window().close_handler = [this]() { + this->quit(); + }; } }; diff --git a/tests/harness/modules/module_cfg.mk b/tests/harness/modules/module_cfg.mk index 92c63f1e3..e932df965 100644 --- a/tests/harness/modules/module_cfg.mk +++ b/tests/harness/modules/module_cfg.mk @@ -1,2 +1,2 @@ -module_cfg := rel_no_install -# module_cfg := dbg +# module_cfg := rel_no_install +module_cfg := dev diff --git a/tests/harness/modules/ruis-render-opengles b/tests/harness/modules/ruis-render-opengles index 434b912b2..fd79a2cd0 160000 --- a/tests/harness/modules/ruis-render-opengles +++ b/tests/harness/modules/ruis-render-opengles @@ -1 +1 @@ -Subproject commit 434b912b20a70352daf135df65151204b54b7390 +Subproject commit fd79a2cd08a43e2d0f7a1225ab5d159e99c691a1 diff --git a/tests/harness/modules/ruisapp b/tests/harness/modules/ruisapp index 174393119..71f979de3 160000 --- a/tests/harness/modules/ruisapp +++ b/tests/harness/modules/ruisapp @@ -1 +1 @@ -Subproject commit 1743931191c47a10d1b91edb08dcd5f95fed316e +Subproject commit 71f979de3989f43ee22c25f7e7022aecc86fb857 diff --git a/tests/harness/util/dummy_context.cpp b/tests/harness/util/dummy_context.cpp index 46f8c9ad8..46c69a96d 100644 --- a/tests/harness/util/dummy_context.cpp +++ b/tests/harness/util/dummy_context.cpp @@ -4,18 +4,23 @@ #include utki::shared_ref make_dummy_context(){ + auto rendering_context = utki::make_shared(); + auto common_objects = utki::make_shared(rendering_context); return utki::make_shared( - utki::make_shared( - utki::make_shared( - utki::make_shared( - utki::make_shared() - ) - ) - ), - utki::make_shared(), ruis::context::parameters{ .post_to_ui_thread_function = [](std::function){}, - .set_mouse_cursor_function = [](ruis::mouse_cursor){}, + .updater = utki::make_shared(), + .renderer = utki::make_shared( + rendering_context,// + rendering_context.get().make_shaders(), + common_objects + ), + .style_provider = utki::make_shared( + utki::make_shared( + rendering_context,// + common_objects + ) + ), .units = ruis::units( ruis::real(96), // ruis::real(1) diff --git a/tests/paint/src/main.cpp b/tests/paint/src/main.cpp index 7f4d1abb7..c905777c8 100644 --- a/tests/paint/src/main.cpp +++ b/tests/paint/src/main.cpp @@ -177,18 +177,23 @@ utki::shared_ref make_root_widget(utki::shared_ref } class application : public ruisapp::application{ + ruisapp::window& window; public: application() : - ruisapp::application( - "ruis-tests", - { + ruisapp::application({ + .name = "ruis-tests" + }), + window(this->make_window({ .dims = {1024, 800} - } - ) + })) { - this->gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); + this->window.gui.context.get().window().close_handler = [this](){ + this->quit(); + }; + + this->window.gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); - this->gui.set_root(make_root_widget(this->gui.context)); + this->window.gui.set_root(make_root_widget(this->window.gui.context)); } }; diff --git a/tests/tabbed_book/src/main.cpp b/tests/tabbed_book/src/main.cpp index bd1ea2272..2142170f6 100644 --- a/tests/tabbed_book/src/main.cpp +++ b/tests/tabbed_book/src/main.cpp @@ -154,19 +154,25 @@ utki::shared_ref make_root_widget(utki::shared_ref } class application : public ruisapp::application{ + ruisapp::window& window; public: application() : - ruisapp::application( - "ruis-tests", - { - .dims = {640, 480} + ruisapp::application({ + .name = "ruis-tests" } - ) + ), + window(this->make_window({ + .dims = {640, 480} + })) { - this->gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); + this->window.gui.context.get().window().close_handler = [this](){ + this->quit(); + }; + + this->window.gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); - auto c = make_root_widget(this->gui.context); - this->gui.set_root(c); + auto c = make_root_widget(this->window.gui.context); + this->window.gui.set_root(c); auto& book = c.get().get_widget_as("book"); diff --git a/tests/unit/src/style.cpp b/tests/unit/src/style.cpp index 1de26fc75..d0a43ece3 100644 --- a/tests/unit/src/style.cpp +++ b/tests/unit/src/style.cpp @@ -7,12 +7,22 @@ #include #include #include - -#include "../../harness/util/dummy_context.hpp" +#include using namespace std::string_literals; using namespace std::string_view_literals; +namespace{ +utki::shared_ref make_style_provider(){ + auto ren_ctx = utki::make_shared(); + auto res_loader = utki::make_shared( + ren_ctx, // + utki::make_shared(ren_ctx) + ); + return utki::make_shared(res_loader); +} +} + namespace{ const tst::set set("style", [](tst::suite& suite){ // test style_sheet loading and getting style value descriptions @@ -69,9 +79,8 @@ const tst::set set("style", [](tst::suite& suite){ auto ss = utki::make_shared(std::move(desc)); - auto c = make_dummy_context(); - - ruis::style_provider s(c.get().res_loader); + auto style_provider = make_style_provider(); + auto& s = style_provider.get(); s.set(std::move(ss)); @@ -91,8 +100,12 @@ const tst::set set("style", [](tst::suite& suite){ } )qwertyuiop"s); - auto c = make_dummy_context(); - ruis::style_provider s(c.get().res_loader); + auto ren_ctx = utki::make_shared(); + auto res_loader = utki::make_shared( + ren_ctx, // + utki::make_shared(ren_ctx) + ); + ruis::style_provider s(res_loader); s.set(utki::make_shared(std::move(ss_desc))); @@ -109,8 +122,8 @@ const tst::set set("style", [](tst::suite& suite){ } )qwertyuiop"s); - auto c = make_dummy_context(); - ruis::style_provider s(c.get().res_loader); + auto style_provider = make_style_provider(); + auto& s = style_provider.get(); s.set(utki::make_shared(std::move(ss_desc))); @@ -120,9 +133,8 @@ const tst::set set("style", [](tst::suite& suite){ // test that style values are updated when style sheet is changed suite.add("style__values_are_updated_when_sheet_changes", [](){ - auto c = make_dummy_context(); - - ruis::style_provider s(c.get().res_loader); + auto style_provider = make_style_provider(); + auto& s = style_provider.get(); auto ss1 = utki::make_shared( tml::read( @@ -174,8 +186,6 @@ const tst::set set("style", [](tst::suite& suite){ // test resource type style values suite.add("style__resource_values", [](){ - auto c = make_dummy_context(); - auto res_pack_desc = R"qwertyuiop( tml_resource1{ forest{Hello world!} @@ -185,9 +195,9 @@ const tst::set set("style", [](tst::suite& suite){ } )qwertyuiop"s; - c.get().loader().mount_res_pack(papki::span_file(utki::make_span(res_pack_desc))); - - ruis::style_provider s(c.get().res_loader); + auto style_provider = make_style_provider(); + auto& s = style_provider.get(); + s.res_loader.get().mount_res_pack(papki::span_file(utki::make_span(res_pack_desc))); auto ss1 = utki::make_shared( tml::read( diff --git a/tests/widget_set/src/main.cpp b/tests/widget_set/src/main.cpp index 5aa792e20..0d0ca4819 100644 --- a/tests/widget_set/src/main.cpp +++ b/tests/widget_set/src/main.cpp @@ -88,20 +88,24 @@ utki::shared_ref make_root_widget(utki::shared_ref } class application : public ruisapp::application{ + ruisapp::window& window; public: - application() : - ruisapp::application( - "ruis-tests", - { + ruisapp::application({ + .name = "ruis-tests"} + ), + window(this->make_window({ .dims = {1024, 800} - } - ) + })) { - this->gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); + this->window.gui.context.get().window().close_handler = [this](){ + this->quit(); + }; + + this->window.gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); - auto c = make_root_widget(this->gui.context); - this->gui.set_root(c); + auto c = make_root_widget(this->window.gui.context); + this->window.gui.set_root(c); auto spinner = utki::make_weak( utki::make_shared_from( diff --git a/tests/wire_area/src/main.cpp b/tests/wire_area/src/main.cpp index 8c2fea36d..77fd4ecf8 100644 --- a/tests/wire_area/src/main.cpp +++ b/tests/wire_area/src/main.cpp @@ -111,20 +111,25 @@ utki::shared_ref make_root_widget(utki::shared_ref } class application : public ruisapp::application{ + ruisapp::window& window; public: application() : - ruisapp::application( - "ruis-tests", - { + ruisapp::application({ + .name = "ruis-tests"} + ), + window(this->make_window({ .dims = {640, 480} - } - ) + })) { - this->gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); + this->window.gui.context.get().window().close_handler = [this](){ + this->quit(); + }; + + this->window.gui.init_standard_widgets(*this->get_res_file("../../res/ruis_res/")); - auto c = make_root_widget(this->gui.context); + auto c = make_root_widget(this->window.gui.context); - this->gui.set_root(c); + this->window.gui.set_root(c); } };