|
1 | 1 | #include "application.hxx" |
2 | 2 |
|
| 3 | +#ifdef RUISAPP_RENDER_OPENGL |
| 4 | +// # include <GL/glew.h> |
| 5 | +# include <ruis/render/opengl/context.hpp> |
| 6 | +#elif defined(RUISAPP_RENDER_OPENGLES) |
| 7 | +// # include <GLES2/gl2.h> |
| 8 | +# include <ruis/render/opengles/context.hpp> |
| 9 | +#else |
| 10 | +# error "Unknown graphics API" |
| 11 | +#endif |
| 12 | + |
| 13 | +using namespace std::string_view_literals; |
| 14 | + |
| 15 | +application_glue::application_glue(const utki::version_duplet& gl_version) : |
| 16 | + gl_version(gl_version), |
| 17 | + shared_gl_context_native_window( // |
| 18 | + utki::make_shared<native_window>( |
| 19 | + this->display, // |
| 20 | + this->gl_version, |
| 21 | + ruisapp::window_parameters{ |
| 22 | + .dims = {1, 1}, |
| 23 | + .title = {}, |
| 24 | + .fullscreen = false |
| 25 | +}, |
| 26 | + nullptr // no shared gl context |
| 27 | + ) |
| 28 | + ), |
| 29 | + resource_loader_ruis_rendering_context( |
| 30 | +#ifdef RUISAPP_RENDER_OPENGL |
| 31 | + utki::make_shared<ruis::render::opengl::context>(this->shared_gl_context_native_window) |
| 32 | +#elif defined(RUISAPP_RENDER_OPENGLES) |
| 33 | + utki::make_shared<ruis::render::opengles::context>(this->shared_gl_context_native_window) |
| 34 | +#else |
| 35 | +# error "Unknown graphics API" |
| 36 | +#endif |
| 37 | + ), |
| 38 | + common_shaders( // |
| 39 | + [&]() { |
| 40 | + utki::assert(this->resource_loader_ruis_rendering_context.to_shared_ptr(), SL); |
| 41 | + return this->resource_loader_ruis_rendering_context.get().make_shaders(); |
| 42 | + }() |
| 43 | + ), |
| 44 | + common_render_objects( // |
| 45 | + utki::make_shared<ruis::render::renderer::objects>(this->resource_loader_ruis_rendering_context) |
| 46 | + ), |
| 47 | + ruis_resource_loader( // |
| 48 | + utki::make_shared<ruis::resource_loader>( |
| 49 | + this->resource_loader_ruis_rendering_context, // |
| 50 | + this->common_render_objects |
| 51 | + ) |
| 52 | + ), |
| 53 | + ruis_style_provider( // |
| 54 | + utki::make_shared<ruis::style_provider>(this->ruis_resource_loader) |
| 55 | + ) |
| 56 | +{} |
| 57 | + |
| 58 | +app_window* application_glue::get_window(native_window::window_id_type id) |
| 59 | +{ |
| 60 | + auto i = this->windows.find(id); |
| 61 | + if (i == this->windows.end()) { |
| 62 | + return nullptr; |
| 63 | + } |
| 64 | + return &i->second.get(); |
| 65 | +} |
| 66 | + |
| 67 | +void application_glue::render() |
| 68 | +{ |
| 69 | + for (auto& w : this->windows) { |
| 70 | + w.second.get().render(); |
| 71 | + } |
| 72 | +} |
| 73 | + |
| 74 | +void application_glue::apply_new_win_dims() |
| 75 | +{ |
| 76 | + for (auto& win : this->windows) { |
| 77 | + auto& w = win.second.get(); |
| 78 | + if (w.new_win_dims.is_positive_or_zero()) { |
| 79 | + w.gui.set_viewport(ruis::rect(0, w.new_win_dims)); |
| 80 | + } |
| 81 | + w.new_win_dims = {-1, -1}; |
| 82 | + } |
| 83 | +} |
| 84 | + |
| 85 | +ruisapp::window& application_glue::make_window(ruisapp::window_parameters window_params) |
| 86 | +{ |
| 87 | + auto ruis_native_window = utki::make_shared<native_window>( |
| 88 | + this->display, |
| 89 | + this->gl_version, |
| 90 | + window_params, |
| 91 | + &this->shared_gl_context_native_window.get() |
| 92 | + ); |
| 93 | + |
| 94 | + auto ruis_context = utki::make_shared<ruis::context>(ruis::context::parameters{ |
| 95 | + .post_to_ui_thread_function = |
| 96 | + [display = this->display](std::function<void()> procedure) { |
| 97 | + SDL_Event e; |
| 98 | + SDL_memset(&e, 0, sizeof(e)); |
| 99 | + e.type = display.get().user_event_type_id; |
| 100 | + e.user.code = 0; |
| 101 | + // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) |
| 102 | + e.user.data1 = new std::function<void()>(std::move(procedure)); |
| 103 | + e.user.data2 = nullptr; |
| 104 | + SDL_PushEvent(&e); |
| 105 | + }, |
| 106 | + .updater = this->updater, |
| 107 | + .renderer = utki::make_shared<ruis::render::renderer>( |
| 108 | +#ifdef RUISAPP_RENDER_OPENGL |
| 109 | + utki::make_shared<ruis::render::opengl::context>(ruis_native_window), |
| 110 | +#elif defined(RUISAPP_RENDER_OPENGLES) |
| 111 | + utki::make_shared<ruis::render::opengles::context>(ruis_native_window), |
| 112 | +#else |
| 113 | +# error "Unknown graphics API" |
| 114 | +#endif |
| 115 | + this->common_shaders, |
| 116 | + this->common_render_objects |
| 117 | + ), |
| 118 | + .style_provider = this->ruis_style_provider, |
| 119 | + .units = ruis::units( |
| 120 | + ruis_native_window.get().get_dpi(), // |
| 121 | + ruis_native_window.get().get_scale_factor() |
| 122 | + ) |
| 123 | + }); |
| 124 | + |
| 125 | + auto ruisapp_window = utki::make_shared<app_window>( |
| 126 | + std::move(ruis_context), // |
| 127 | + std::move(ruis_native_window) |
| 128 | + ); |
| 129 | + |
| 130 | + ruisapp_window.get().gui.set_viewport( // |
| 131 | + ruis::rect({0, 0}, ruisapp_window.get().ruis_native_window.get().get_dims()) |
| 132 | + ); |
| 133 | + |
| 134 | + auto res = this->windows.insert( // |
| 135 | + std::make_pair( |
| 136 | + ruisapp_window.get().ruis_native_window.get().get_id(), // |
| 137 | + std::move(ruisapp_window) |
| 138 | + ) |
| 139 | + ); |
| 140 | + utki::assert(res.second, SL); |
| 141 | + |
| 142 | + return res.first->second.get(); |
| 143 | +} |
| 144 | + |
| 145 | +void application_glue::destroy_window(native_window::window_id_type id) |
| 146 | +{ |
| 147 | + auto i = this->windows.find(id); |
| 148 | + utki::assert(i != this->windows.end(), SL); |
| 149 | + |
| 150 | + this->windows_to_destroy.push_back(std::move(i->second)); |
| 151 | + this->windows.erase(i); |
| 152 | +} |
| 153 | + |
| 154 | +namespace { |
| 155 | +ruisapp::application::directories get_application_directories(std::string_view app_name) |
| 156 | +{ |
| 157 | + char* base_dir = SDL_GetPrefPath("", std::string(app_name).c_str()); |
| 158 | + utki::scope_exit base_dir_scope_exit([&]() { |
| 159 | + SDL_free(base_dir); |
| 160 | + }); |
| 161 | + |
| 162 | + ruisapp::application::directories dirs; |
| 163 | + |
| 164 | + dirs.cache = utki::cat(base_dir, "cache/"sv); |
| 165 | + dirs.config = utki::cat(base_dir, "config/"sv); |
| 166 | + dirs.state = utki::cat(base_dir, "state/"sv); |
| 167 | + |
| 168 | + // std::cout << "cache dir = " << dirs.cache << std::endl; |
| 169 | + // std::cout << "config dir = " << dirs.config << std::endl; |
| 170 | + // std::cout << "state dir = " << dirs.state << std::endl; |
| 171 | + |
| 172 | + return dirs; |
| 173 | +} |
| 174 | +} // namespace |
| 175 | + |
| 176 | +ruisapp::application::application(parameters params) : |
| 177 | + application( |
| 178 | + utki::make_unique<application_glue>(params.graphics_api_version), // |
| 179 | + get_application_directories(params.name), |
| 180 | + std::move(params) |
| 181 | + ) |
| 182 | +{} |
| 183 | + |
| 184 | +void ruisapp::application::quit() noexcept |
| 185 | +{ |
| 186 | + auto& glue = get_glue(*this); |
| 187 | + |
| 188 | + // TODO: send SDL_QUIT event instead of setting the flag? |
| 189 | + glue.quit_flag.store(true); |
| 190 | +} |
| 191 | + |
| 192 | +ruisapp::window& ruisapp::application::make_window(ruisapp::window_parameters window_params) |
| 193 | +{ |
| 194 | + auto& glue = get_glue(*this); |
| 195 | + return glue.make_window(std::move(window_params)); |
| 196 | +} |
| 197 | + |
| 198 | +void ruisapp::application::destroy_window(ruisapp::window& w) |
| 199 | +{ |
| 200 | + auto& glue = get_glue(*this); |
| 201 | + |
| 202 | + utki::assert(dynamic_cast<app_window*>(&w), SL); |
| 203 | + auto& app_win = static_cast<app_window&>(w); |
| 204 | + glue.destroy_window(app_win.ruis_native_window.get().get_id()); |
| 205 | +} |
0 commit comments