diff --git a/src/app/sdl/sdl-window.cpp b/src/app/sdl/sdl-window.cpp index a456cb6..dd6c500 100644 --- a/src/app/sdl/sdl-window.cpp +++ b/src/app/sdl/sdl-window.cpp @@ -236,7 +236,9 @@ void sdl_window::set_maximized(bool maximized) void sdl_window::set_fullscreen(bool fullscreen) { + //SDL_HideWindow(internal_window); SDL_SetWindowFullscreen(internal_window, (fullscreen) ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); + //SDL_ShowWindow(internal_window); this->fullscreen = fullscreen; } diff --git a/src/game/context.hpp b/src/game/context.hpp index 03bac24..10322d4 100644 --- a/src/game/context.hpp +++ b/src/game/context.hpp @@ -149,6 +149,7 @@ struct context app::window* window; bool closed; std::shared_ptr<::event::subscription> window_closed_subscription; + std::shared_ptr<::event::subscription> window_resized_subscription; // Input management and input event handling app::input_manager* input_manager; @@ -331,8 +332,6 @@ struct context const ecoregion* active_ecoregion; render::anti_aliasing_method anti_aliasing_method; - - std::shared_ptr<::event::subscription> ui_resize_subscription; }; } // namespace game diff --git a/src/game/controls.cpp b/src/game/controls.cpp index 893544f..1347fd4 100644 --- a/src/game/controls.cpp +++ b/src/game/controls.cpp @@ -232,8 +232,8 @@ void enable_menu_controls(game::context& ctx) max_y += padding; const auto& viewport = ctx.window->get_viewport_size(); - const float x = static_cast(event.position.x() - viewport[0] / 2); - const float y = static_cast((viewport[1] - event.position.y() + 1) - viewport[1] / 2); + const float x = static_cast(event.position.x()); + const float y = static_cast((viewport[1] - event.position.y() + 1)); if (x >= min_x && x <= max_x) { @@ -280,8 +280,8 @@ void enable_menu_controls(game::context& ctx) max_y += padding; const auto& viewport = ctx.window->get_viewport_size(); - const float x = static_cast(event.position.x() - viewport[0] / 2); - const float y = static_cast((viewport[1] - event.position.y() + 1) - viewport[1] / 2); + const float x = static_cast(event.position.x()); + const float y = static_cast((viewport[1] - event.position.y() + 1)); if (x >= min_x && x <= max_x) { @@ -290,17 +290,25 @@ void enable_menu_controls(game::context& ctx) *ctx.menu_item_index = i; game::menu::update_text_color(ctx); + auto callback = ctx.menu_select_callbacks[i]; if (event.button == input::mouse_button::left) { - const auto& callback = ctx.menu_select_callbacks[i]; - if (callback) - callback(); + if (ctx.menu_left_callbacks[i]) + { + callback = ctx.menu_left_callbacks[i]; + } } else if (event.button == input::mouse_button::right) { - const auto& callback = ctx.menu_left_callbacks[i]; - if (callback) - callback(); + if (ctx.menu_right_callbacks[i]) + { + callback = ctx.menu_right_callbacks[i]; + } + } + + if (callback) + { + callback(); } return; @@ -313,7 +321,7 @@ void enable_menu_controls(game::context& ctx) } void disable_window_controls(game::context& ctx) -{ +{ ctx.window_controls.disconnect(); } diff --git a/src/game/menu.cpp b/src/game/menu.cpp index a81bc33..00e99b0 100644 --- a/src/game/menu.cpp +++ b/src/game/menu.cpp @@ -24,6 +24,9 @@ #include "animation/ease.hpp" #include "config.hpp" #include +#include "math/glsl.hpp" + +using namespace math::glsl; namespace game { namespace menu { @@ -82,6 +85,9 @@ void update_text_tweens(game::context& ctx) void align_text(game::context& ctx, bool center, bool has_back, float anchor_y) { + const vec2 viewport_size = vec2(ctx.window->get_viewport_size()); + const vec2 viewport_center = viewport_size * 0.5f; + // Calculate menu width float menu_width = 0.0f; float menu_spacing = ctx.menu_font.get_glyph_metrics(U'M').width; @@ -114,8 +120,8 @@ void align_text(game::context& ctx, bool center, bool has_back, float anchor_y) else menu_height = ctx.menu_item_texts.size() * ctx.menu_font.get_font_metrics().linespace - ctx.menu_font.get_font_metrics().linegap; - float menu_x = -menu_width * 0.5f; - float menu_y = anchor_y + menu_height * 0.5f - ctx.menu_font.get_font_metrics().size; + float menu_x = viewport_center.x() - menu_width * 0.5f; + float menu_y = viewport_center.y() + anchor_y + menu_height * 0.5f - ctx.menu_font.get_font_metrics().size; for (std::size_t i = 0; i < ctx.menu_item_texts.size(); ++i) { @@ -130,7 +136,7 @@ void align_text(game::context& ctx, bool center, bool has_back, float anchor_y) { const auto& name_bounds = static_cast&>(name->get_local_bounds()); const float name_width = name_bounds.max_point.x() - name_bounds.min_point.x(); - x = -name_width * 0.5f; + x = viewport_center.x() - name_width * 0.5f; } name->set_translation({std::round(x), std::round(y), 0.0f}); @@ -141,7 +147,7 @@ void align_text(game::context& ctx, bool center, bool has_back, float anchor_y) const float value_width = value_bounds.max_point.x() - value_bounds.min_point.x(); if (center || i == ctx.menu_item_texts.size() - 1) - x = -value_width * 0.5f; + x = viewport_center.x() - value_width * 0.5f; else x = menu_x + menu_width - value_width; diff --git a/src/game/state/boot.cpp b/src/game/state/boot.cpp index f7a2618..5ba82fc 100644 --- a/src/game/state/boot.cpp +++ b/src/game/state/boot.cpp @@ -781,10 +781,10 @@ void boot::setup_scenes() // Setup UI camera ctx.ui_camera = new scene::camera(); ctx.ui_camera->set_compositor(ctx.ui_compositor); - float clip_left = -viewport_size[0] * 0.5f; - float clip_right = viewport_size[0] * 0.5f; - float clip_top = -viewport_size[1] * 0.5f; - float clip_bottom = viewport_size[1] * 0.5f; + float clip_left = 0.0f; + float clip_right = viewport_size[0]; + float clip_top = 0.0f; + float clip_bottom = viewport_size[1]; float clip_near = 0.0f; float clip_far = 1000.0f; ctx.ui_camera->set_orthographic(clip_left, clip_right, clip_top, clip_bottom, clip_near, clip_far); @@ -1151,23 +1151,41 @@ void boot::setup_ui() debug::log::error("Failed to load fonts"); } - // Setup UI resize handler - // ctx.ui_resize_subscription = ctx.window_manager->get_event_queue().subscribe - // ( - // [&](const auto& event) - // { - // const auto& viewport_size = event.window->get_viewport_size(); + // Setup window resized callback + ctx.window_resized_subscription = ctx.window->get_resized_channel().subscribe + ( + [&](const auto& event) + { + const auto& viewport_size = event.window->get_viewport_size(); + const float viewport_aspect_ratio = static_cast(viewport_size.x()) / static_cast(viewport_size.y()); - // const float clip_left = static_cast(viewport_size.x()) * -0.5f; - // const float clip_right = static_cast(viewport_size.x()) * 0.5f; - // const float clip_top = static_cast(viewport_size.y()) * -0.5f; - // const float clip_bottom = static_cast(viewport_size.y()) * 0.5f; - // const float clip_near = ctx.ui_camera->get_clip_near(); - // const float clip_far = ctx.ui_camera->get_clip_far(); + // Resize framebuffers + game::graphics::change_render_resolution(ctx, ctx.render_scale); - // ctx.ui_camera->set_orthographic(clip_left, clip_right, clip_top, clip_bottom, clip_near, clip_far); - // } - // ); + // Update camera projection matrix + ctx.surface_camera->set_perspective + ( + ctx.surface_camera->get_fov(), + viewport_aspect_ratio, + ctx.surface_camera->get_clip_near(), + ctx.surface_camera->get_clip_far() + ); + + // Update UI camera projection matrix + ctx.ui_camera->set_orthographic + ( + 0.0f, + viewport_size.x(), + 0.0f, + viewport_size.y(), + ctx.ui_camera->get_clip_near(), + ctx.ui_camera->get_clip_far() + ); + + // Re-align menu text + game::menu::align_text(ctx); + } + ); } void boot::setup_debugging() diff --git a/src/game/state/credits.cpp b/src/game/state/credits.cpp index 1d5b42d..63bbc05 100644 --- a/src/game/state/credits.cpp +++ b/src/game/state/credits.cpp @@ -27,8 +27,10 @@ #include "debug/log.hpp" #include "game/strings.hpp" #include "utility/hash/fnv1a.hpp" +#include "math/glsl.hpp" using namespace hash::literals; +using namespace math::glsl; namespace game { namespace state { @@ -38,6 +40,9 @@ credits::credits(game::context& ctx): { debug::log::trace("Entering credits state..."); + const vec2 viewport_size = vec2(ctx.window->get_viewport_size()); + const vec2 viewport_center = viewport_size * 0.5f; + // Construct credits text credits_text.set_material(&ctx.menu_font_material); credits_text.set_font(&ctx.menu_font); @@ -48,7 +53,7 @@ credits::credits(game::context& ctx): const auto& credits_aabb = static_cast&>(credits_text.get_local_bounds()); float credits_w = credits_aabb.max_point.x() - credits_aabb.min_point.x(); float credits_h = credits_aabb.max_point.y() - credits_aabb.min_point.y(); - credits_text.set_translation({std::round(-credits_w * 0.5f), std::round(-credits_h * 0.5f), 0.0f}); + credits_text.set_translation({std::round(viewport_center.x() - credits_w * 0.5f), std::round(viewport_center.y() - credits_h * 0.5f), 0.0f}); credits_text.update_tweens(); // Set up animation timing configuration @@ -73,26 +78,36 @@ credits::credits(game::context& ctx): // Start credits fade in animation credits_fade_in_animation.play(); - // Construct splash skip function + // Setup window resized callback + window_resized_subscription = ctx.window->get_resized_channel().subscribe + ( + [&](const auto& event) + { + const vec2 viewport_size = vec2(event.window->get_viewport_size()); + const vec2 viewport_center = viewport_size * 0.5f; + const auto& credits_aabb = static_cast&>(credits_text.get_local_bounds()); + float credits_w = credits_aabb.max_point.x() - credits_aabb.min_point.x(); + float credits_h = credits_aabb.max_point.y() - credits_aabb.min_point.y(); + credits_text.set_translation({std::round(viewport_center.x() - credits_w * 0.5f), std::round(viewport_center.y() - credits_h * 0.5f), 0.0f}); + credits_text.update_tweens(); + } + ); + + // Construct credits skip function auto skip = [&](const auto& event) { ctx.function_queue.emplace ( [&]() { - // Black out screen - ctx.window->get_rasterizer()->set_clear_color(0.0f, 0.0f, 0.0f, 1.0f); - ctx.window->get_rasterizer()->clear_framebuffer(true, false, false); - ctx.window->swap_buffers(); - - // Change to main menu state + // Change to extras menu state ctx.state_machine.pop(); ctx.state_machine.emplace(new game::state::extras_menu(ctx)); } ); }; - // Set up splash skippers + // Set up credits skippers input_mapped_subscriptions.emplace_back ( ctx.input_mapper.get_gamepad_button_mapped_channel().subscribe diff --git a/src/game/state/credits.hpp b/src/game/state/credits.hpp index 9767265..02e330c 100644 --- a/src/game/state/credits.hpp +++ b/src/game/state/credits.hpp @@ -40,6 +40,7 @@ private: animation credits_fade_in_animation; animation credits_scroll_animation; std::vector> input_mapped_subscriptions; + std::shared_ptr window_resized_subscription; }; } // namespace state diff --git a/src/game/state/main-menu.cpp b/src/game/state/main-menu.cpp index defd3e2..740800c 100644 --- a/src/game/state/main-menu.cpp +++ b/src/game/state/main-menu.cpp @@ -43,9 +43,11 @@ #include "render/passes/sky-pass.hpp" #include "resources/resource-manager.hpp" #include "utility/hash/fnv1a.hpp" +#include "math/glsl.hpp" #include using namespace hash::literals; +using namespace math::glsl; namespace game { namespace state { @@ -57,6 +59,9 @@ main_menu::main_menu(game::context& ctx, bool fade_in): ctx.ui_clear_pass->set_cleared_buffers(true, true, false); + const vec2 viewport_size = vec2(ctx.window->get_viewport_size()); + const vec2 viewport_center = viewport_size * 0.5f; + // Construct title text title_text.set_material(&ctx.title_font_material); title_text.set_color({1.0f, 1.0f, 1.0f, (fade_in) ? 1.0f : 0.0f}); @@ -67,7 +72,7 @@ main_menu::main_menu(game::context& ctx, bool fade_in): const auto& title_aabb = static_cast&>(title_text.get_local_bounds()); float title_w = title_aabb.max_point.x() - title_aabb.min_point.x(); float title_h = title_aabb.max_point.y() - title_aabb.min_point.y(); - title_text.set_translation({std::round(-title_w * 0.5f), std::round(-title_h * 0.5f + (ctx.window->get_viewport_size().y() / 3.0f) / 2.0f), 0.0f}); + title_text.set_translation({std::round(viewport_center.x() - title_w * 0.5f), std::round(viewport_center.y() - title_h * 0.5f + (viewport_size.y() / 3.0f) / 2.0f), 0.0f}); title_text.update_tweens(); // Add title text to UI @@ -110,7 +115,7 @@ main_menu::main_menu(game::context& ctx, bool fade_in): game::menu::update_text_color(ctx); game::menu::update_text_font(ctx); - game::menu::align_text(ctx, true, false, (-ctx.window->get_viewport_size().y() / 3.0f) / 2.0f); + game::menu::align_text(ctx, true, false, (-viewport_size.y() / 3.0f) / 2.0f); game::menu::update_text_tweens(ctx); game::menu::add_text_to_ui(ctx); game::menu::setup_animations(ctx); @@ -261,9 +266,7 @@ main_menu::main_menu(game::context& ctx, bool fade_in): const float ev100_sunny16 = physics::light::ev::from_settings(16.0f, 1.0f / 100.0f, 100.0f); ctx.surface_camera->set_exposure(ev100_sunny16); - const auto& viewport_size = ctx.window->get_viewport_size(); - const float aspect_ratio = static_cast(viewport_size[0]) / static_cast(viewport_size[1]); - + const float aspect_ratio = viewport_size.x() / viewport_size.y(); float fov = math::vertical_fov(math::radians(100.0f), aspect_ratio); ctx.surface_camera->look_at({0, 2.0f, 0}, {0, 0, 0}, {0, 0, 1}); @@ -280,6 +283,25 @@ main_menu::main_menu(game::context& ctx, bool fade_in): //if (!ctx.menu_bg_billboard->is_active()) // game::menu::fade_in_bg(ctx); + // Setup window resized callback + window_resized_subscription = ctx.window->get_resized_channel().subscribe + ( + [&](const auto& event) + { + const vec2 viewport_size = vec2(event.window->get_viewport_size()); + const vec2 viewport_center = viewport_size * 0.5f; + + // Re-align title text + const auto& title_aabb = static_cast&>(title_text.get_local_bounds()); + float title_w = title_aabb.max_point.x() - title_aabb.min_point.x(); + float title_h = title_aabb.max_point.y() - title_aabb.min_point.y(); + title_text.set_translation({std::round(viewport_center.x() - title_w * 0.5f), std::round(viewport_center.y() - title_h * 0.5f + (viewport_size.y() / 3.0f) / 2.0f), 0.0f}); + title_text.update_tweens(); + + game::menu::align_text(ctx, true, false, (-viewport_size.y() / 3.0f) / 2.0f); + } + ); + // Enable menu controls ctx.function_queue.push(std::bind(game::enable_menu_controls, std::ref(ctx))); diff --git a/src/game/state/main-menu.hpp b/src/game/state/main-menu.hpp index b41a5b2..6f226c0 100644 --- a/src/game/state/main-menu.hpp +++ b/src/game/state/main-menu.hpp @@ -24,6 +24,8 @@ #include "scene/text.hpp" #include "animation/animation.hpp" #include "entity/id.hpp" +#include "event/subscription.hpp" +#include namespace game { namespace state { @@ -42,6 +44,7 @@ private: animation title_fade_animation; entity::id swarm_eid; + std::shared_ptr window_resized_subscription; }; } // namespace state diff --git a/src/game/state/nuptial-flight.cpp b/src/game/state/nuptial-flight.cpp index 18332bf..44024ee 100644 --- a/src/game/state/nuptial-flight.cpp +++ b/src/game/state/nuptial-flight.cpp @@ -76,6 +76,7 @@ nuptial_flight::nuptial_flight(game::context& ctx): // Create observer game::world::create_observer(ctx); } + game::world::enter_ecoregion(ctx, *ctx.resource_manager->load("seedy-scrub.eco")); // Set world time game::world::set_time(ctx, 2022, 6, 21, 12, 0, 0.0); diff --git a/src/game/state/splash.cpp b/src/game/state/splash.cpp index 38e21f1..571eb8f 100644 --- a/src/game/state/splash.cpp +++ b/src/game/state/splash.cpp @@ -29,6 +29,9 @@ #include "render/material-flags.hpp" #include "render/passes/clear-pass.hpp" #include "resources/resource-manager.hpp" +#include "math/glsl.hpp" + +using namespace math::glsl; namespace game { namespace state { @@ -38,6 +41,9 @@ splash::splash(game::context& ctx): { debug::log::trace("Entering splash state..."); + const vec2 viewport_size = vec2(ctx.window->get_viewport_size()); + const vec2 viewport_center = viewport_size * 0.5f; + // Enable color buffer clearing in UI pass ctx.ui_clear_pass->set_cleared_buffers(true, true, false); @@ -58,7 +64,7 @@ splash::splash(game::context& ctx): // Construct splash billboard splash_billboard.set_material(&splash_billboard_material); splash_billboard.set_scale({(float)std::get<0>(splash_dimensions) * 0.5f, (float)std::get<1>(splash_dimensions) * 0.5f, 1.0f}); - splash_billboard.set_translation({0.0f, 0.0f, 0.0f}); + splash_billboard.set_translation({std::round(viewport_center.x()), std::round(viewport_center.y()), 0.0f}); splash_billboard.update_tweens(); // Add splash billboard to UI scene @@ -123,6 +129,18 @@ splash::splash(game::context& ctx): // Start splash fade in animation splash_fade_in_animation.play(); + // Setup window resized callback + window_resized_subscription = ctx.window->get_resized_channel().subscribe + ( + [&](const auto& event) + { + const vec2 viewport_size = vec2(event.window->get_viewport_size()); + const vec2 viewport_center = viewport_size * 0.5f; + splash_billboard.set_translation({std::round(viewport_center.x()), std::round(viewport_center.y()), 0.0f}); + splash_billboard.update_tweens(); + } + ); + // Construct splash skip function auto skip = [&](const auto& event) { diff --git a/src/game/state/splash.hpp b/src/game/state/splash.hpp index 1f2b855..3dff350 100644 --- a/src/game/state/splash.hpp +++ b/src/game/state/splash.hpp @@ -42,6 +42,7 @@ private: animation splash_fade_in_animation; animation splash_fade_out_animation; std::vector> input_mapped_subscriptions; + std::shared_ptr window_resized_subscription; }; } // namespace state