diff --git a/src/game/context.hpp b/src/game/context.hpp index cea8bac..d47f49e 100644 --- a/src/game/context.hpp +++ b/src/game/context.hpp @@ -50,6 +50,7 @@ #include "render/material.hpp" #include "render/material-property.hpp" #include "ui/mouse-tracker.hpp" +#include "application.hpp" // Forward declarations class animator; @@ -218,6 +219,7 @@ struct context int* menu_item_index; animation* menu_fade_animation; animation* title_fade_animation; + scene::billboard* menu_bg_billboard; // Surface scene scene::collection* surface_scene; @@ -249,6 +251,9 @@ struct context animation* main_menu_fade_animation; animation* credits_fade_in_animation; animation* credits_scroll_animation; + animation* menu_bg_fade_in_animation; + animation* menu_bg_fade_out_animation; + // Controls input::event_router* input_event_router; @@ -292,6 +297,9 @@ struct context entity::system::orbit* orbit_system; entity::system::proteome* proteome_system; + // State management + std::optional paused_state; + // Debug debug::cli* cli; }; diff --git a/src/game/menu.cpp b/src/game/menu.cpp index cd137a8..3206a3d 100644 --- a/src/game/menu.cpp +++ b/src/game/menu.cpp @@ -279,6 +279,20 @@ void fade_out(game::context* ctx, const std::function& end_callback) ctx->menu_fade_animation->play(); } +void fade_in_bg(game::context* ctx) +{ + ctx->menu_bg_fade_out_animation->stop(); + ctx->menu_bg_fade_in_animation->stop(); + ctx->menu_bg_fade_in_animation->play(); +} + +void fade_out_bg(game::context* ctx) +{ + ctx->menu_bg_fade_in_animation->stop(); + ctx->menu_bg_fade_out_animation->stop(); + ctx->menu_bg_fade_out_animation->play(); +} + void setup_controls(game::context* ctx) { ctx->controls["menu_up"]->set_activated_callback diff --git a/src/game/menu.hpp b/src/game/menu.hpp index 093ec43..87c012c 100644 --- a/src/game/menu.hpp +++ b/src/game/menu.hpp @@ -34,6 +34,9 @@ static constexpr float4 active_color{1.0f, 1.0f, 1.0f, 1.0f}; /// RGBA color of inactive menu items. static constexpr float4 inactive_color{1.0f, 1.0f, 1.0f, 0.5f}; +/// Opacity of the menu background. +static constexpr float bg_opacity = 0.75f; + /// Padding of the mouseover bounds, as a percentage of the font size. static constexpr float mouseover_padding = 0.1f; @@ -41,7 +44,7 @@ static constexpr float mouseover_padding = 0.1f; static constexpr float fade_in_duration = 0.25f; /// Duration of the menu fade out animation -static constexpr float fade_out_duration = 0.25f; +static constexpr float fade_out_duration = 0.125f; void init_menu_item_index(game::context* ctx, const std::string& menu_name); void setup_controls(game::context* ctx); @@ -56,6 +59,9 @@ void delete_animations(game::context* ctx); void fade_in(game::context* ctx, const std::function& end_callback); void fade_out(game::context* ctx, const std::function& end_callback); +void fade_in_bg(game::context* ctx); +void fade_out_bg(game::context* ctx); + void update_text_color(game::context* ctx); void update_text_font(game::context* ctx); void update_text_tweens(game::context* ctx); diff --git a/src/game/states/boot.cpp b/src/game/states/boot.cpp index 5a2d947..2c88eea 100644 --- a/src/game/states/boot.cpp +++ b/src/game/states/boot.cpp @@ -54,7 +54,7 @@ #include "resources/resource-manager.hpp" #include "resources/file-buffer.hpp" #include "scene/scene.hpp" -#include "game/states/loading.hpp" +#include "game/states/splash.hpp" #include "entity/systems/behavior.hpp" #include "entity/systems/camera.hpp" #include "entity/systems/collision.hpp" @@ -84,6 +84,11 @@ #include "input/keyboard.hpp" #include "configuration.hpp" #include "input/scancode.hpp" +#include "game/fonts.hpp" +#include "game/controls.hpp" +#include "game/save.hpp" +#include "game/menu.hpp" +#include "utility/timestamp.hpp" #include #include #include @@ -158,11 +163,13 @@ void enter(application* app, int argc, char** argv) app->set_update_rate((*ctx->config)["update_rate"].get()); } + // Clear paused state + // Queue next application state application::state next_state; - next_state.name = "loading"; - next_state.enter = std::bind(game::state::loading::enter, ctx); - next_state.exit = std::bind(game::state::loading::exit, ctx); + next_state.name = "splash"; + next_state.enter = std::bind(game::state::splash::enter, ctx); + next_state.exit = std::bind(game::state::splash::exit, ctx); app->queue_state(next_state); } @@ -722,6 +729,8 @@ void setup_scenes(game::context* ctx) 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); + ctx->ui_camera->look_at({0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {0.0f, 1.0f, 0.0f}); + ctx->ui_camera->update_tweens(); // Setup underground camera ctx->underground_camera = new scene::camera(); @@ -740,7 +749,6 @@ void setup_scenes(game::context* ctx) // Setup UI scene { ctx->ui_scene = new scene::collection(); - const gl::texture_2d* splash_texture = ctx->resource_manager->load("splash.tex"); auto splash_dimensions = splash_texture->get_dimensions(); ctx->splash_billboard_material = new render::material(); @@ -755,6 +763,20 @@ void setup_scenes(game::context* ctx) ctx->splash_billboard->set_translation({0.0f, 0.0f, 0.0f}); ctx->splash_billboard->update_tweens(); + // Menu BG billboard + render::material* menu_bg_material = new render::material(); + menu_bg_material->set_shader_program(ctx->resource_manager->load("ui-element-untextured.glsl")); + auto menu_bg_tint = menu_bg_material->add_property("tint"); + menu_bg_tint->set_value(float4{0.0f, 0.0f, 0.0f, 0.5f}); + menu_bg_material->set_flags(MATERIAL_FLAG_TRANSLUCENT); + menu_bg_material->update_tweens(); + ctx->menu_bg_billboard = new scene::billboard(); + ctx->menu_bg_billboard->set_active(false); + ctx->menu_bg_billboard->set_material(menu_bg_material); + ctx->menu_bg_billboard->set_scale({(float)viewport_dimensions[0] * 0.5f, (float)viewport_dimensions[1] * 0.5f, 1.0f}); + ctx->menu_bg_billboard->set_translation({0.0f, 0.0f, -100.0f}); + ctx->menu_bg_billboard->update_tweens(); + // Create camera flash billboard render::material* flash_material = new render::material(); @@ -850,6 +872,55 @@ void setup_animation(game::context* ctx) //ctx->ui_scene->add_object(ctx->radial_transition_outer->get_billboard()); //ctx->animator->add_animation(ctx->radial_transition_outer->get_animation()); + + // Menu BG animations + { + render::material_property* menu_bg_tint = static_cast*>(ctx->menu_bg_billboard->get_material()->get_property("tint")); + auto menu_bg_frame_callback = [menu_bg_tint](int channel, const float& opacity) + { + menu_bg_tint->set_value(float4{0.0f, 0.0f, 0.0f, opacity}); + }; + + // Create menu BG fade in animation + ctx->menu_bg_fade_in_animation = new animation(); + { + ctx->menu_bg_fade_in_animation->set_interpolator(ease::out_cubic); + animation_channel* channel = ctx->menu_bg_fade_in_animation->add_channel(0); + channel->insert_keyframe({0.0f, 0.0f}); + channel->insert_keyframe({game::menu::fade_in_duration, game::menu::bg_opacity}); + ctx->menu_bg_fade_in_animation->set_frame_callback(menu_bg_frame_callback); + ctx->menu_bg_fade_in_animation->set_start_callback + ( + [ctx]() + { + ctx->ui_scene->add_object(ctx->menu_bg_billboard); + ctx->menu_bg_billboard->set_active(true); + } + ); + } + + // Create menu BG fade out animation + ctx->menu_bg_fade_out_animation = new animation(); + { + ctx->menu_bg_fade_out_animation->set_interpolator(ease::out_cubic); + animation_channel* channel = ctx->menu_bg_fade_out_animation->add_channel(0); + channel->insert_keyframe({0.0f, game::menu::bg_opacity}); + channel->insert_keyframe({game::menu::fade_out_duration, 0.0f}); + ctx->menu_bg_fade_out_animation->set_frame_callback(menu_bg_frame_callback); + ctx->menu_bg_fade_out_animation->set_end_callback + ( + [ctx]() + { + ctx->ui_scene->remove_object(ctx->menu_bg_billboard); + ctx->menu_bg_billboard->set_active(false); + } + ); + } + + ctx->animator->add_animation(ctx->menu_bg_fade_in_animation); + ctx->animator->add_animation(ctx->menu_bg_fade_out_animation); + } + // Create camera flash animation ctx->camera_flash_animation = new animation(); { @@ -989,7 +1060,96 @@ void setup_controls(game::context* ctx) ctx->app->add_game_controller_mappings(game_controller_db->data(), game_controller_db->size()); ctx->resource_manager->unload("gamecontrollerdb.txt"); ctx->logger->pop_task(EXIT_SUCCESS); - } + } + + // Load controls + ctx->logger->push_task("Loading controls"); + try + { + // If a control profile is set in the config file + if (ctx->config->contains("control_profile")) + { + // Load control profile + json* profile = ctx->resource_manager->load((*ctx->config)["control_profile"].get()); + + // Apply control profile + if (profile) + { + game::apply_control_profile(ctx, *profile); + } + } + + // Calibrate gamepads + for (input::gamepad* gamepad: ctx->app->get_gamepads()) + { + ctx->logger->push_task("Loading calibration for gamepad " + gamepad->get_guid()); + json* calibration = game::load_gamepad_calibration(ctx, gamepad); + if (!calibration) + { + ctx->logger->pop_task(EXIT_FAILURE); + + ctx->logger->push_task("Generating default calibration for gamepad " + gamepad->get_guid()); + json default_calibration = game::default_gamepad_calibration(); + apply_gamepad_calibration(gamepad, default_calibration); + + if (!save_gamepad_calibration(ctx, gamepad, default_calibration)) + ctx->logger->pop_task(EXIT_FAILURE); + else + ctx->logger->pop_task(EXIT_SUCCESS); + } + else + { + ctx->logger->pop_task(EXIT_SUCCESS); + apply_gamepad_calibration(gamepad, *calibration); + } + } + + // Toggle fullscreen + ctx->controls["toggle_fullscreen"]->set_activated_callback + ( + [ctx]() + { + bool fullscreen = !ctx->app->is_fullscreen(); + + ctx->app->set_fullscreen(fullscreen); + + if (!fullscreen) + { + int2 resolution; + resolution.x = (*ctx->config)["windowed_resolution"][0].get(); + resolution.y = (*ctx->config)["windowed_resolution"][1].get(); + + ctx->app->resize_window(resolution.x, resolution.y); + } + + // Save display mode config + (*ctx->config)["fullscreen"] = fullscreen; + game::save_config(ctx); + } + ); + + // Screenshot + ctx->controls["screenshot"]->set_activated_callback + ( + [ctx]() + { + std::string path = ctx->screenshots_path + "antkeeper-" + timestamp() + ".png"; + ctx->app->save_frame(path); + } + ); + + // Set activation threshold for menu navigation controls to mitigate drifting gamepad axes + const float menu_activation_threshold = 0.1f; + ctx->controls["menu_up"]->set_activation_threshold(menu_activation_threshold); + ctx->controls["menu_down"]->set_activation_threshold(menu_activation_threshold); + ctx->controls["menu_left"]->set_activation_threshold(menu_activation_threshold); + ctx->controls["menu_right"]->set_activation_threshold(menu_activation_threshold); + } + catch (...) + { + ctx->logger->pop_task(EXIT_FAILURE); + } + ctx->logger->pop_task(EXIT_SUCCESS); } void setup_ui(game::context* ctx) @@ -1004,6 +1164,18 @@ void setup_ui(game::context* ctx) if (ctx->config->contains("dyslexia_font")) ctx->dyslexia_font = (*ctx->config)["dyslexia_font"].get(); + // Load fonts + ctx->logger->push_task("Loading fonts"); + try + { + game::load_fonts(ctx); + } + catch (...) + { + ctx->logger->pop_task(EXIT_FAILURE); + } + ctx->logger->pop_task(EXIT_SUCCESS); + // Construct mouse tracker ctx->menu_mouse_tracker = new ui::mouse_tracker(); ctx->app->get_event_dispatcher()->subscribe(ctx->menu_mouse_tracker); @@ -1031,6 +1203,14 @@ void setup_callbacks(game::context* ctx) ( [ctx](double t, double dt) { + // Update tweens + ctx->surface_sky_pass->update_tweens(); + ctx->surface_scene->update_tweens(); + ctx->underground_scene->update_tweens(); + ctx->ui_scene->update_tweens(); + + ctx->timeline->advance(dt); + // Update controls for (const auto& control: ctx->controls) control.second->update(); @@ -1047,13 +1227,9 @@ void setup_callbacks(game::context* ctx) } ); - // Update tweens - ctx->surface_sky_pass->update_tweens(); - ctx->surface_scene->update_tweens(); - ctx->underground_scene->update_tweens(); - ctx->ui_scene->update_tweens(); + - ctx->timeline->advance(dt); + @@ -1077,9 +1253,9 @@ void setup_callbacks(game::context* ctx) ctx->constraint_system->update(t, dt); ctx->painting_system->update(t, dt); ctx->proteome_system->update(t, dt); + ctx->animator->animate(dt); ctx->render_system->update(t, dt); - ctx->animator->animate(dt); } ); diff --git a/src/game/states/controls-menu.cpp b/src/game/states/controls-menu.cpp index 1a30c4a..c71b5d9 100644 --- a/src/game/states/controls-menu.cpp +++ b/src/game/states/controls-menu.cpp @@ -23,7 +23,6 @@ #include "game/states/options-menu.hpp" #include "application.hpp" #include "scene/text.hpp" -#include "render/passes/clear-pass.hpp" #include "debug/logger.hpp" #include "game/menu.hpp" #include "animation/timeline.hpp" @@ -34,8 +33,6 @@ namespace controls_menu { void enter(game::context* ctx) { - ctx->ui_clear_pass->set_cleared_buffers(true, true, false); - // Construct menu item texts scene::text* keyboard_text = new scene::text(); scene::text* gamepad_text = new scene::text(); @@ -152,8 +149,6 @@ void exit(game::context* ctx) game::menu::delete_animations(ctx); game::menu::remove_text_from_ui(ctx); game::menu::delete_text(ctx); - - ctx->ui_clear_pass->set_cleared_buffers(false, true, false); } } // namespace controls_menu diff --git a/src/game/states/credits.cpp b/src/game/states/credits.cpp index 500f8af..a017037 100644 --- a/src/game/states/credits.cpp +++ b/src/game/states/credits.cpp @@ -24,7 +24,6 @@ #include "animation/animator.hpp" #include "application.hpp" #include "scene/text.hpp" -#include "render/passes/clear-pass.hpp" namespace game { namespace state { @@ -32,8 +31,6 @@ namespace credits { void enter(game::context* ctx) { - ctx->ui_clear_pass->set_cleared_buffers(true, true, false); - // Construct credits text ctx->credits_text = new scene::text(); ctx->credits_text->set_material(&ctx->menu_font_material); @@ -133,8 +130,6 @@ void exit(game::context* ctx) delete ctx->credits_scroll_animation; ctx->credits_fade_in_animation = nullptr; ctx->credits_scroll_animation = nullptr; - - ctx->ui_clear_pass->set_cleared_buffers(false, true, false); } } // namespace credits diff --git a/src/game/states/extras-menu.cpp b/src/game/states/extras-menu.cpp index 914a1d9..30f70dd 100644 --- a/src/game/states/extras-menu.cpp +++ b/src/game/states/extras-menu.cpp @@ -22,7 +22,6 @@ #include "game/states/credits.hpp" #include "application.hpp" #include "scene/text.hpp" -#include "render/passes/clear-pass.hpp" #include "debug/logger.hpp" #include "game/fonts.hpp" #include "game/menu.hpp" @@ -34,8 +33,6 @@ namespace extras_menu { void enter(game::context* ctx) { - ctx->ui_clear_pass->set_cleared_buffers(true, true, false); - // Construct menu item texts scene::text* credits_text = new scene::text(); scene::text* back_text = new scene::text(); @@ -128,8 +125,6 @@ void exit(game::context* ctx) game::menu::delete_animations(ctx); game::menu::remove_text_from_ui(ctx); game::menu::delete_text(ctx); - - ctx->ui_clear_pass->set_cleared_buffers(false, true, false); } } // namespace extras_menu diff --git a/src/game/states/gamepad-config-menu.cpp b/src/game/states/gamepad-config-menu.cpp index bd81464..ad46c10 100644 --- a/src/game/states/gamepad-config-menu.cpp +++ b/src/game/states/gamepad-config-menu.cpp @@ -21,7 +21,6 @@ #include "game/states/controls-menu.hpp" #include "application.hpp" #include "scene/text.hpp" -#include "render/passes/clear-pass.hpp" #include "debug/logger.hpp" #include "resources/resource-manager.hpp" #include "game/menu.hpp" @@ -279,8 +278,6 @@ static void add_control_item(game::context* ctx, const std::string& control_name void enter(game::context* ctx) { - ctx->ui_clear_pass->set_cleared_buffers(true, true, false); - // Add camera control menu items add_control_item(ctx, "move_forward"); add_control_item(ctx, "move_back"); @@ -364,8 +361,6 @@ void exit(game::context* ctx) // Save control profile game::save_control_profile(ctx); - - ctx->ui_clear_pass->set_cleared_buffers(false, true, false); } } // namespace gamepad_config_menu diff --git a/src/game/states/graphics-menu.cpp b/src/game/states/graphics-menu.cpp index 40ec570..4982875 100644 --- a/src/game/states/graphics-menu.cpp +++ b/src/game/states/graphics-menu.cpp @@ -21,7 +21,6 @@ #include "game/states/options-menu.hpp" #include "application.hpp" #include "scene/text.hpp" -#include "render/passes/clear-pass.hpp" #include "debug/logger.hpp" #include "game/fonts.hpp" #include "game/menu.hpp" @@ -51,8 +50,6 @@ static void update_value_text_content(game::context* ctx) void enter(game::context* ctx) { - ctx->ui_clear_pass->set_cleared_buffers(true, true, false); - // Construct menu item texts scene::text* fullscreen_name_text = new scene::text(); scene::text* fullscreen_value_text = new scene::text(); @@ -333,8 +330,6 @@ void exit(game::context* ctx) game::menu::delete_animations(ctx); game::menu::remove_text_from_ui(ctx); game::menu::delete_text(ctx); - - ctx->ui_clear_pass->set_cleared_buffers(false, true, false); } } // namespace graphics_menu diff --git a/src/game/states/keyboard-config-menu.cpp b/src/game/states/keyboard-config-menu.cpp index f197f10..f0ec7ff 100644 --- a/src/game/states/keyboard-config-menu.cpp +++ b/src/game/states/keyboard-config-menu.cpp @@ -21,7 +21,6 @@ #include "game/states/controls-menu.hpp" #include "application.hpp" #include "scene/text.hpp" -#include "render/passes/clear-pass.hpp" #include "debug/logger.hpp" #include "resources/resource-manager.hpp" #include "game/menu.hpp" @@ -234,8 +233,6 @@ static void add_control_item(game::context* ctx, const std::string& control_name void enter(game::context* ctx) { - ctx->ui_clear_pass->set_cleared_buffers(true, true, false); - // Add camera control menu items add_control_item(ctx, "move_forward"); add_control_item(ctx, "move_back"); @@ -319,8 +316,6 @@ void exit(game::context* ctx) // Save control profile game::save_control_profile(ctx); - - ctx->ui_clear_pass->set_cleared_buffers(false, true, false); } } // namespace keyboard_config_menu diff --git a/src/game/states/language-menu.cpp b/src/game/states/language-menu.cpp index 13b17a5..31e6c78 100644 --- a/src/game/states/language-menu.cpp +++ b/src/game/states/language-menu.cpp @@ -21,7 +21,6 @@ #include "game/states/options-menu.hpp" #include "application.hpp" #include "scene/text.hpp" -#include "render/passes/clear-pass.hpp" #include "debug/logger.hpp" #include "game/fonts.hpp" #include "game/menu.hpp" @@ -43,8 +42,6 @@ static void update_text_content(game::context* ctx) void enter(game::context* ctx) { - ctx->ui_clear_pass->set_cleared_buffers(true, true, false); - // Construct menu item texts scene::text* language_name_text = new scene::text(); scene::text* language_value_text = new scene::text(); @@ -187,8 +184,6 @@ void exit(game::context* ctx) game::menu::delete_animations(ctx); game::menu::remove_text_from_ui(ctx); game::menu::delete_text(ctx); - - ctx->ui_clear_pass->set_cleared_buffers(false, true, false); } } // namespace language_menu diff --git a/src/game/states/main-menu.cpp b/src/game/states/main-menu.cpp index cd58ea0..d5ecd05 100644 --- a/src/game/states/main-menu.cpp +++ b/src/game/states/main-menu.cpp @@ -260,8 +260,6 @@ void exit(game::context* ctx) ctx->ui_scene->remove_object(ctx->title_text); delete ctx->title_text; ctx->title_text = nullptr; - - ctx->ui_clear_pass->set_cleared_buffers(false, true, false); } } // namespace main_menu diff --git a/src/game/states/nuptial-flight.cpp b/src/game/states/nuptial-flight.cpp index f16e09a..8f1aa8d 100644 --- a/src/game/states/nuptial-flight.cpp +++ b/src/game/states/nuptial-flight.cpp @@ -18,6 +18,7 @@ */ #include "game/states/nuptial-flight.hpp" +#include "game/states/pause-menu.hpp" #include "entity/archetype.hpp" #include "entity/systems/astronomy.hpp" #include "entity/systems/orbit.hpp" @@ -25,17 +26,55 @@ #include "entity/components/observer.hpp" #include "entity/components/transform.hpp" #include "entity/components/terrain.hpp" +#include "entity/components/camera.hpp" +#include "entity/components/constraints/spring-to.hpp" +#include "entity/components/constraints/three-dof.hpp" +#include "entity/components/constraint-stack.hpp" #include "entity/commands.hpp" #include "animation/screen-transition.hpp" #include "animation/ease.hpp" #include "resources/resource-manager.hpp" +#include "game/world.hpp" +#include "application.hpp" +#include "render/passes/clear-pass.hpp" +#include "animation/timeline.hpp" namespace game { namespace state { namespace nuptial_flight { +static void setup_camera(game::context* ctx); +static void enable_controls(game::context* ctx); +static void disable_controls(game::context* ctx); + void enter(game::context* ctx) { + // Resume if paused + if (ctx->paused_state) + { + // Clear paused state + ctx->paused_state.reset(); + + // Enable controls + enable_controls(ctx); + return; + } + + // Disable UI color clear + ctx->ui_clear_pass->set_cleared_buffers(false, true, false); + + // Create world + game::world::create_stars(ctx); + game::world::create_sun(ctx); + game::world::create_planet(ctx); + game::world::create_moon(ctx); + + // Set time to solar noon + game::world::set_time(ctx, 0.0); + + // Freeze time + game::world::set_time_scale(ctx, 0.0); + // Switch to surface camera ctx->underground_camera->set_active(false); ctx->surface_camera->set_active(true); @@ -44,11 +83,11 @@ void enter(game::context* ctx) entity::id planet_eid = ctx->entities["planet"]; // Remove terrain component from planet (if any) - if (ctx->entity_registry->has(planet_eid)) - ctx->entity_registry->remove(planet_eid); + //if (ctx->entity_registry->has(planet_eid)) + // ctx->entity_registry->remove(planet_eid); // Enable clouds in sky pass - ctx->surface_sky_pass->set_clouds_model(ctx->resource_manager->load("cloud-plane.mdl")); + //ctx->surface_sky_pass->set_clouds_model(ctx->resource_manager->load("cloud-plane.mdl")); // Create observer entity::id observer_eid = ctx->entity_registry->create(); @@ -67,26 +106,454 @@ void enter(game::context* ctx) } // Setup camera + setup_camera(ctx); + /* ctx->surface_camera->look_at({0, 0, 1}, {0, 0, 0}, {0, 1, 0}); ctx->surface_camera->set_exposure(-14.5f); - ctx->surface_scene->update_tweens(); + */ - // Pause motion of celestial objects - ctx->astronomy_system->set_time_scale(0.0); - ctx->orbit_system->set_time_scale(0.0); + // Schedule control setup + timeline* timeline = ctx->timeline; + float t = timeline->get_position(); + timeline->add_sequence({{t + 0.01f, std::bind(enable_controls, ctx)}}); - // Start fade in from white + // Schedule fade in ctx->fade_transition_color->set_value({1, 1, 1}); ctx->fade_transition->transition(5.0f, true, math::lerp); + //timeline->add_sequence({{t + 10.0f, [ctx](){ctx->fade_transition->transition(5.0f, true, math::lerp);}}}); } void exit(game::context* ctx) { - // Resume motion of celestial objects - const double time_scale = (*ctx->config)["time_scale"].get(); - ctx->astronomy_system->set_time_scale(time_scale); - ctx->orbit_system->set_time_scale(time_scale); + // Resume time + //const double time_scale = (*ctx->config)["time_scale"].get(); + //game::world::set_time_scale(ctx, time_scale); +} + +void setup_camera(game::context* ctx) +{ + // Switch to surface camera + ctx->underground_camera->set_active(false); + ctx->surface_camera->set_active(true); + + // Create surface camera entity + if (!ctx->entities.count("surface_cam")) + { + // Create camera target entity + entity::id target_eid = ctx->entity_registry->create(); + ctx->entities["surface_cam_target"] = target_eid; + { + // Transform + entity::component::transform target_transform; + target_transform.local = math::identity_transform; + target_transform.world = target_transform.local; + target_transform.warp = true; + ctx->entity_registry->assign(target_eid, target_transform); + } + + // Create camera entity + entity::id camera_eid = ctx->entity_registry->create(); + ctx->entities["surface_cam"] = camera_eid; + + // Create camera transform component + entity::component::transform transform; + transform.local = math::identity_transform; + transform.world = transform.local; + transform.warp = true; + ctx->entity_registry->assign(camera_eid, transform); + + // Create camera camera component + entity::component::camera camera; + camera.object = ctx->surface_camera; + ctx->entity_registry->assign(camera_eid, camera); + + // Create camera 3DOF constraint entity + entity::id three_dof_constraint_eid = ctx->entity_registry->create(); + ctx->entities["surface_cam_3dof"] = three_dof_constraint_eid; + { + // Create 3DOF to constraint + entity::component::constraint::three_dof three_dof; + three_dof.yaw = 0.0f; + three_dof.pitch = 0.0f; + three_dof.roll = 0.0f; + ctx->entity_registry->assign(three_dof_constraint_eid, three_dof); + + // Create constraint stack node component + entity::component::constraint_stack_node node; + node.active = true; + node.weight = 1.0f; + node.next = entt::null; + ctx->entity_registry->assign(three_dof_constraint_eid, node); + } + + // Create camera spring to constraint entity + entity::id spring_constraint_eid = ctx->entity_registry->create(); + { + // Create spring to constraint + entity::component::constraint::spring_to spring; + spring.target = target_eid; + spring.translation = {{0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f}, 1.0f, math::two_pi}; + spring.translation.w = hz_to_rads(8.0f); + + spring.spring_translation = true; + spring.spring_rotation = false; + ctx->entity_registry->assign(spring_constraint_eid, spring); + + // Create constraint stack node component + entity::component::constraint_stack_node node; + node.active = true; + node.weight = 1.0f; + node.next = three_dof_constraint_eid; + ctx->entity_registry->assign(spring_constraint_eid, node); + } + + // Create camera constraint stack component + entity::component::constraint_stack constraint_stack; + constraint_stack.head = spring_constraint_eid; + ctx->entity_registry->assign(camera_eid, constraint_stack); + } + + ctx->surface_camera->set_exposure(-12.0f); +} + +void enable_controls(game::context* ctx) +{ + /// @WARNING!!! SOMETIMES THIS CALLBACK IS SKIPPED BY THE TIMELINE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ctx->logger->log("ENABLING CONTROLS"); + + // Get camera entities + entity::id camera_eid = ctx->entities["surface_cam"]; + entity::id target_eid = ctx->entities["surface_cam_target"]; + entity::id three_dof_eid = ctx->entities["surface_cam_3dof"]; + + const float slow_modifier = 0.25f; + const float fast_modifier = 4.0f; + const float dolly_speed = 20.0f; + const float truck_speed = dolly_speed; + const float pedestal_speed = 30.0f; + float mouse_tilt_sensitivity = 1.0f; + float mouse_pan_sensitivity = 1.0f; + bool mouse_invert_tilt = false; + bool mouse_invert_pan = false; + float gamepad_tilt_sensitivity = 1.0f; + float gamepad_pan_sensitivity = 1.0f; + bool gamepad_invert_tilt = false; + bool gamepad_invert_pan = false; + bool mouse_look_toggle = false; + ctx->mouse_look = false; + + if (ctx->config->contains("mouse_tilt_sensitivity")) + mouse_tilt_sensitivity = math::radians((*ctx->config)["mouse_tilt_sensitivity"].get()); + if (ctx->config->contains("mouse_pan_sensitivity")) + mouse_pan_sensitivity = math::radians((*ctx->config)["mouse_pan_sensitivity"].get()); + if (ctx->config->contains("mouse_invert_tilt")) + mouse_invert_tilt = math::radians((*ctx->config)["mouse_invert_tilt"].get()); + if (ctx->config->contains("mouse_invert_pan")) + mouse_invert_pan = math::radians((*ctx->config)["mouse_invert_pan"].get()); + if (ctx->config->contains("mouse_look_toggle")) + mouse_look_toggle = math::radians((*ctx->config)["mouse_look_toggle"].get()); + + if (ctx->config->contains("gamepad_tilt_sensitivity")) + gamepad_tilt_sensitivity = math::radians((*ctx->config)["gamepad_tilt_sensitivity"].get()); + if (ctx->config->contains("gamepad_pan_sensitivity")) + gamepad_pan_sensitivity = math::radians((*ctx->config)["gamepad_pan_sensitivity"].get()); + if (ctx->config->contains("gamepad_invert_tilt")) + gamepad_invert_tilt = math::radians((*ctx->config)["gamepad_invert_tilt"].get()); + if (ctx->config->contains("gamepad_invert_pan")) + gamepad_invert_pan = math::radians((*ctx->config)["gamepad_invert_pan"].get()); + + const input::control* move_slow = ctx->controls["move_slow"]; + const input::control* move_fast = ctx->controls["move_fast"]; + const input::control* mouse_look = ctx->controls["mouse_look"]; + + float mouse_tilt_factor = mouse_tilt_sensitivity * (mouse_invert_tilt ? -1.0f : 1.0f); + float mouse_pan_factor = mouse_pan_sensitivity * (mouse_invert_pan ? -1.0f : 1.0f); + float gamepad_tilt_factor = gamepad_tilt_sensitivity * (gamepad_invert_tilt ? -1.0f : 1.0f); + float gamepad_pan_factor = gamepad_pan_sensitivity * (gamepad_invert_pan ? -1.0f : 1.0f); + + ctx->controls["move_forward"]->set_active_callback + ( + [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value) + { + if (move_slow->is_active()) + value *= slow_modifier; + if (move_fast->is_active()) + value *= fast_modifier; + + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); + + const float3 movement = {0.0f, 0.0f, -truck_speed * value * (1.0f / 60.0f)}; + entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement); + } + ); + + // Dolly backward + ctx->controls["move_back"]->set_active_callback + ( + [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value) + { + if (move_slow->is_active()) + value *= slow_modifier; + if (move_fast->is_active()) + value *= fast_modifier; + + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); + + const float3 movement = {0.0f, 0.0f, truck_speed * value * (1.0f / 60.0f)}; + entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement); + } + ); + + // Truck right + ctx->controls["move_right"]->set_active_callback + ( + [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value) + { + if (move_slow->is_active()) + value *= slow_modifier; + if (move_fast->is_active()) + value *= fast_modifier; + + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); + + const float3 movement = {truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f}; + entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement); + } + ); + + // Truck left + ctx->controls["move_left"]->set_active_callback + ( + [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value) + { + if (move_slow->is_active()) + value *= slow_modifier; + if (move_fast->is_active()) + value *= fast_modifier; + + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); + + const float3 movement = {-truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f}; + entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement); + } + ); + + // Pedestal up + ctx->controls["move_up"]->set_active_callback + ( + [ctx, target_eid, pedestal_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value) + { + if (move_slow->is_active()) + value *= slow_modifier; + if (move_fast->is_active()) + value *= fast_modifier; + + const float3 movement = {0.0f, pedestal_speed * value * (1.0f / 60.0f), 0.0f}; + entity::command::translate(*ctx->entity_registry, target_eid, movement); + } + ); + + // Pedestal down + ctx->controls["move_down"]->set_active_callback + ( + [ctx, target_eid, pedestal_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value) + { + if (move_slow->is_active()) + value *= slow_modifier; + if (move_fast->is_active()) + value *= fast_modifier; + + const float3 movement = {0.0f, -pedestal_speed * value * (1.0f / 60.0f), 0.0f}; + entity::command::translate(*ctx->entity_registry, target_eid, movement); + } + ); + + // Mouse rotate + ctx->controls["mouse_look"]->set_activated_callback + ( + [ctx, mouse_look_toggle]() + { + if (mouse_look_toggle) + ctx->mouse_look = !ctx->mouse_look; + else + ctx->mouse_look = true; + + ctx->app->set_relative_mouse_mode(ctx->mouse_look); + } + ); + ctx->controls["mouse_look"]->set_deactivated_callback + ( + [ctx, mouse_look_toggle]() + { + if (!mouse_look_toggle) + { + ctx->mouse_look = false; + ctx->app->set_relative_mouse_mode(false); + } + } + ); + // Pan left + ctx->controls["look_left_gamepad"]->set_active_callback + ( + [ctx, three_dof_eid, gamepad_pan_factor](float value) + { + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + three_dof.yaw += gamepad_pan_factor * value * (1.0f / 60.0f); + } + ); + ctx->controls["look_left_mouse"]->set_active_callback + ( + [ctx, three_dof_eid, mouse_pan_factor](float value) + { + if (!ctx->mouse_look) + return; + + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + three_dof.yaw += mouse_pan_factor * value * (1.0f / 60.0f); + } + ); + + // Pan right + ctx->controls["look_right_gamepad"]->set_active_callback + ( + [ctx, three_dof_eid, gamepad_pan_factor](float value) + { + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + three_dof.yaw -= gamepad_pan_factor * value * (1.0f / 60.0f); + } + ); + ctx->controls["look_right_mouse"]->set_active_callback + ( + [ctx, three_dof_eid, mouse_pan_factor](float value) + { + if (!ctx->mouse_look) + return; + + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + three_dof.yaw -= mouse_pan_factor * value * (1.0f / 60.0f); + } + ); + // Tilt up + ctx->controls["look_up_gamepad"]->set_active_callback + ( + [ctx, three_dof_eid, gamepad_tilt_factor](float value) + { + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + three_dof.pitch -= gamepad_tilt_factor * value * (1.0f / 60.0f); + three_dof.pitch = std::max(math::radians(-90.0f), three_dof.pitch); + } + ); + ctx->controls["look_up_mouse"]->set_active_callback + ( + [ctx, three_dof_eid, mouse_tilt_factor](float value) + { + if (!ctx->mouse_look) + return; + + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + three_dof.pitch -= mouse_tilt_factor * value * (1.0f / 60.0f); + three_dof.pitch = std::max(math::radians(-90.0f), three_dof.pitch); + } + ); + // Tilt down + ctx->controls["look_down_gamepad"]->set_active_callback + ( + [ctx, three_dof_eid, gamepad_tilt_factor](float value) + { + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + three_dof.pitch += gamepad_tilt_factor * value * (1.0f / 60.0f); + three_dof.pitch = std::min(math::radians(90.0f), three_dof.pitch); + } + ); + ctx->controls["look_down_mouse"]->set_active_callback + ( + [ctx, three_dof_eid, mouse_tilt_factor](float value) + { + if (!ctx->mouse_look) + return; + + auto& three_dof = ctx->entity_registry->get(three_dof_eid); + three_dof.pitch += mouse_tilt_factor * value * (1.0f / 60.0f); + three_dof.pitch = std::min(math::radians(90.0f), three_dof.pitch); + } + ); + /* + // Use tool + ctx->controls["use_tool"]->set_activated_callback + ( + [ctx]() + { + if (ctx->entities.count("active_tool")) + { + entity::id tool_eid = ctx->entities["active_tool"]; + const auto& tool = ctx->entity_registry->get(tool_eid); + if (tool.activated) + tool.activated(); + } + } + ); + ctx->controls["use_tool"]->set_deactivated_callback + ( + [ctx]() + { + if (ctx->entities.count("active_tool")) + { + entity::id tool_eid = ctx->entities["active_tool"]; + const auto& tool = ctx->entity_registry->get(tool_eid); + if (tool.deactivated) + tool.deactivated(); + } + } + ); + ctx->controls["use_tool"]->set_active_callback + ( + [ctx](float value) + { + if (ctx->entities.count("active_tool")) + { + entity::id tool_eid = ctx->entities["active_tool"]; + const auto& tool = ctx->entity_registry->get(tool_eid); + if (tool.active) + tool.active(); + } + } + ); + */ + + // Setup pause control + ctx->controls["pause"]->set_activated_callback + ( + [ctx]() + { + // Disable controls + disable_controls(ctx); + + // Store paused state + ctx->paused_state = + { + "nuptial_flight", + std::bind(game::state::nuptial_flight::enter, ctx), + std::bind(game::state::nuptial_flight::exit, ctx) + }; + + // Change to pause menu state + application::state next_state; + next_state.name = "pause_menu"; + next_state.enter = std::bind(game::state::pause_menu::enter, ctx); + next_state.exit = std::bind(game::state::pause_menu::exit, ctx); + ctx->app->change_state(next_state); + } + ); +} + +void disable_controls(game::context* ctx) +{ + ctx->controls["pause"]->set_activated_callback(nullptr); } } // namespace nuptial_flight diff --git a/src/game/states/options-menu.cpp b/src/game/states/options-menu.cpp index ffc59b6..3b15bd8 100644 --- a/src/game/states/options-menu.cpp +++ b/src/game/states/options-menu.cpp @@ -23,6 +23,7 @@ #include "game/states/graphics-menu.hpp" #include "game/states/sound-menu.hpp" #include "game/states/language-menu.hpp" +#include "game/states/pause-menu.hpp" #include "game/save.hpp" #include "game/menu.hpp" #include "animation/ease.hpp" @@ -31,7 +32,6 @@ #include "animation/timeline.hpp" #include "application.hpp" #include "scene/text.hpp" -#include "render/passes/clear-pass.hpp" namespace game { namespace state { @@ -39,8 +39,6 @@ namespace options_menu { void enter(game::context* ctx) { - ctx->ui_clear_pass->set_cleared_buffers(true, true, false); - // Construct menu item texts scene::text* controls_text = new scene::text(); scene::text* graphics_text = new scene::text(); @@ -157,19 +155,23 @@ void enter(game::context* ctx) // Save config game::save_config(ctx); - // Return to main menu - game::menu::fade_out - ( - ctx, - [ctx]() - { - application::state next_state; - next_state.name = "main_menu"; - next_state.enter = std::bind(game::state::main_menu::enter, ctx, false); - next_state.exit = std::bind(game::state::main_menu::exit, ctx); - ctx->app->queue_state(next_state); - } - ); + application::state next_state; + if (ctx->paused_state) + { + // Return to pause menu + next_state.name = "pause_menu"; + next_state.enter = std::bind(game::state::pause_menu::enter, ctx); + next_state.exit = std::bind(game::state::pause_menu::exit, ctx); + } + else + { + // Return to main menu + next_state.name = "main_menu"; + next_state.enter = std::bind(game::state::main_menu::enter, ctx, false); + next_state.exit = std::bind(game::state::main_menu::exit, ctx); + } + + game::menu::fade_out(ctx, std::bind(&application::queue_state, ctx->app, next_state)); }; // Build list of menu select callbacks @@ -208,8 +210,6 @@ void exit(game::context* ctx) // Save config game::save_config(ctx); - - ctx->ui_clear_pass->set_cleared_buffers(false, true, false); } } // namespace options_menu diff --git a/src/game/states/pause-menu.cpp b/src/game/states/pause-menu.cpp new file mode 100644 index 0000000..5430243 --- /dev/null +++ b/src/game/states/pause-menu.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2021 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code 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. + * + * Antkeeper source code 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 Antkeeper source code. If not, see . + */ + +#include "game/states/pause-menu.hpp" +#include "game/states/main-menu.hpp" +#include "game/states/options-menu.hpp" +#include "game/menu.hpp" +#include "animation/ease.hpp" +#include "animation/animation.hpp" +#include "animation/animator.hpp" +#include "animation/timeline.hpp" +#include "application.hpp" +#include "scene/text.hpp" + +namespace game { +namespace state { +namespace pause_menu { + +void enter(game::context* ctx) +{ + // Construct menu item texts + scene::text* resume_text = new scene::text(); + scene::text* options_text = new scene::text(); + scene::text* main_menu_text = new scene::text(); + scene::text* quit_text = new scene::text(); + + // Set content of menu item texts + resume_text->set_content((*ctx->strings)["pause_menu_resume"]); + options_text->set_content((*ctx->strings)["pause_menu_options"]); + main_menu_text->set_content((*ctx->strings)["pause_menu_main_menu"]); + quit_text->set_content((*ctx->strings)["pause_menu_quit"]); + + // Build list of menu item texts + ctx->menu_item_texts.push_back({resume_text, nullptr}); + ctx->menu_item_texts.push_back({options_text, nullptr}); + ctx->menu_item_texts.push_back({main_menu_text, nullptr}); + ctx->menu_item_texts.push_back({quit_text, nullptr}); + + // Init menu item index + game::menu::init_menu_item_index(ctx, "pause"); + + game::menu::update_text_color(ctx); + game::menu::update_text_font(ctx); + game::menu::align_text(ctx, true, false); + game::menu::update_text_tweens(ctx); + game::menu::add_text_to_ui(ctx); + game::menu::setup_animations(ctx); + + // Construct menu item callbacks + auto select_resume_callback = [ctx]() + { + // Disable unpause control + ctx->controls["pause"]->set_activated_callback(nullptr); + + // Disable menu controls + game::menu::clear_controls(ctx); + + auto resume_paused_state = [ctx]() + { + ctx->app->queue_state(*ctx->paused_state); + }; + + // Fade out pause menu then resume paused state + game::menu::fade_out(ctx, resume_paused_state); + game::menu::fade_out_bg(ctx); + }; + auto select_options_callback = [ctx]() + { + // Disable unpause control + //ctx->controls["pause"]->set_activated_callback(nullptr); + + // Disable menu controls + game::menu::clear_controls(ctx); + + // Fade out pause menu then open options menu + game::menu::fade_out + ( + ctx, + [ctx]() + { + application::state next_state; + next_state.name = "options_menu"; + next_state.enter = std::bind(game::state::options_menu::enter, ctx); + next_state.exit = std::bind(game::state::options_menu::exit, ctx); + ctx->app->queue_state(next_state); + } + ); + }; + auto select_main_menu_callback = [ctx]() + { + // Disable unpause control + ctx->controls["pause"]->set_activated_callback(nullptr); + + // Disable menu controls + game::menu::clear_controls(ctx); + + // Clear paused state + ctx->paused_state.reset(); + + // Fade out pause menu then return to main menu + game::menu::fade_out + ( + ctx, + [ctx]() + { + application::state next_state; + next_state.name = "main_menu"; + next_state.enter = std::bind(game::state::main_menu::enter, ctx, true); + next_state.exit = std::bind(game::state::main_menu::exit, ctx); + ctx->app->queue_state(next_state); + } + ); + }; + auto select_quit_callback = [ctx]() + { + // Disable unpause control + ctx->controls["pause"]->set_activated_callback(nullptr); + + // Disable menu controls + game::menu::clear_controls(ctx); + + // Clear paused state + ctx->paused_state.reset(); + + // Fade out then quit + game::menu::fade_out(ctx, std::bind(&application::close, ctx->app, EXIT_SUCCESS)); + }; + + // Build list of menu select callbacks + ctx->menu_select_callbacks.push_back(select_resume_callback); + ctx->menu_select_callbacks.push_back(select_options_callback); + ctx->menu_select_callbacks.push_back(select_main_menu_callback); + ctx->menu_select_callbacks.push_back(select_quit_callback); + + // Build list of menu right callbacks + ctx->menu_right_callbacks.resize(4, nullptr); + + // Build list of menu left callbacks + ctx->menu_left_callbacks.resize(4, nullptr); + + // Set menu back callback + ctx->menu_back_callback = select_resume_callback; + + // Schedule control setup + timeline* timeline = ctx->timeline; + float t = timeline->get_position(); + timeline->add_sequence + ({{ + t + game::menu::input_delay, + [ctx, select_resume_callback]() + { + // Enable unpause control + ctx->controls["pause"]->set_activated_callback(select_resume_callback); + + // Enable menu controls + game::menu::setup_controls(ctx); + } + }}); + + // Fade in menu and menu BG + game::menu::fade_in(ctx, nullptr); + if (!ctx->menu_bg_billboard->is_active()) + game::menu::fade_in_bg(ctx); +} + +void exit(game::context* ctx) +{ + // Destruct menu + game::menu::clear_controls(ctx); + game::menu::clear_callbacks(ctx); + game::menu::delete_animations(ctx); + game::menu::remove_text_from_ui(ctx); + game::menu::delete_text(ctx); +} + +} // namespace pause_menu +} // namespace state +} // namespace game diff --git a/src/game/states/loading.hpp b/src/game/states/pause-menu.hpp similarity index 80% rename from src/game/states/loading.hpp rename to src/game/states/pause-menu.hpp index 92ddbd5..585046f 100644 --- a/src/game/states/loading.hpp +++ b/src/game/states/pause-menu.hpp @@ -17,23 +17,23 @@ * along with Antkeeper source code. If not, see . */ -#ifndef ANTKEEPER_GAME_STATE_LOADING_HPP -#define ANTKEEPER_GAME_STATE_LOADING_HPP +#ifndef ANTKEEPER_GAME_STATE_PAUSE_MENU_HPP +#define ANTKEEPER_GAME_STATE_PAUSE_MENU_HPP #include "game/context.hpp" namespace game { namespace state { -/// Loading game state functions. -namespace loading { +/// Pause menu screen game state functions. +namespace pause_menu { void enter(game::context* ctx); void exit(game::context* ctx); -} // namespace loading +} // namespace pause_menu } // namespace state } // namespace game -#endif // ANTKEEPER_GAME_STATE_LOADING_HPP +#endif // ANTKEEPER_GAME_STATE_PAUSE_MENU_HPP diff --git a/src/game/states/sound-menu.cpp b/src/game/states/sound-menu.cpp index 69c17f2..5861690 100644 --- a/src/game/states/sound-menu.cpp +++ b/src/game/states/sound-menu.cpp @@ -21,7 +21,6 @@ #include "game/states/options-menu.hpp" #include "application.hpp" #include "scene/text.hpp" -#include "render/passes/clear-pass.hpp" #include "debug/logger.hpp" #include "game/menu.hpp" #include "animation/timeline.hpp" @@ -45,8 +44,6 @@ static void update_value_text_content(game::context* ctx) void enter(game::context* ctx) { - ctx->ui_clear_pass->set_cleared_buffers(true, true, false); - // Construct menu item texts scene::text* master_volume_name_text = new scene::text(); scene::text* master_volume_value_text = new scene::text(); @@ -250,8 +247,6 @@ void exit(game::context* ctx) (*ctx->config)["mono_audio"] = ctx->mono_audio; (*ctx->config)["captions"] = ctx->captions; (*ctx->config)["captions_size"] = ctx->captions_size; - - ctx->ui_clear_pass->set_cleared_buffers(false, true, false); } } // namespace sound_menu diff --git a/src/game/states/loading.cpp b/src/game/world.cpp similarity index 57% rename from src/game/states/loading.cpp rename to src/game/world.cpp index 41deb6a..3c7bb7a 100644 --- a/src/game/states/loading.cpp +++ b/src/game/world.cpp @@ -17,8 +17,8 @@ * along with Antkeeper source code. If not, see . */ -#include "game/states/loading.hpp" -#include "application.hpp" +#include "game/world.hpp" +#include "scene/text.hpp" #include "astro/illuminance.hpp" #include "color/color.hpp" #include "entity/components/atmosphere.hpp" @@ -31,11 +31,6 @@ #include "entity/systems/orbit.hpp" #include "entity/commands.hpp" #include "entity/archetype.hpp" -#include "game/states/nuptial-flight.hpp" -#include "game/states/splash.hpp" -#include "game/states/main-menu.hpp" -#include "game/controls.hpp" -#include "game/save.hpp" #include "geom/spherical.hpp" #include "gl/drawing-mode.hpp" #include "gl/vertex-array.hpp" @@ -50,319 +45,15 @@ #include "resources/resource-manager.hpp" #include "scene/ambient-light.hpp" #include "scene/directional-light.hpp" -#include "utility/timestamp.hpp" -#include "configuration.hpp" -#include - #include "gl/texture-wrapping.hpp" #include "gl/texture-filter.hpp" #include "render/material-flags.hpp" -#include "game/fonts.hpp" +#include "configuration.hpp" namespace game { -namespace state { -namespace loading { - -/// Loads control profile and calibrates gamepads -static void load_controls(game::context* ctx); - -/// Creates the universe and solar system. -static void cosmogenesis(game::context* ctx); - -/// Creates a sun. -static void heliogenesis(game::context* ctx); - -/// Creates a planet. -static void planetogenesis(game::context* ctx); - -/// Creates a moon. -static void selenogenesis(game::context* ctx); - -/// Creates fixed stars. -static void extrasolar_heliogenesis(game::context* ctx); - -/// Creates an ant colony -static void colonigenesis(game::context* ctx); - -void enter(game::context* ctx) -{ - // Load controls - ctx->logger->push_task("Loading controls"); - try - { - load_controls(ctx); - } - catch (...) - { - ctx->logger->pop_task(EXIT_FAILURE); - } - ctx->logger->pop_task(EXIT_SUCCESS); - - // Load fonts - ctx->logger->push_task("Loading fonts"); - try - { - game::load_fonts(ctx); - } - catch (...) - { - ctx->logger->pop_task(EXIT_FAILURE); - } - ctx->logger->pop_task(EXIT_SUCCESS); - - /* - // Create universe - ctx->logger->push_task("Creating the universe"); - try - { - cosmogenesis(ctx); - } - catch (...) - { - ctx->logger->pop_task(EXIT_FAILURE); - throw; - } - ctx->logger->pop_task(EXIT_SUCCESS); - */ - - // Determine next game state - application::state next_state; - if (ctx->option_quick_start.has_value()) - { - next_state.name = "main_menu"; - next_state.enter = std::bind(game::state::main_menu::enter, ctx, true); - next_state.exit = std::bind(game::state::main_menu::exit, ctx); - } - else - { - next_state.name = "splash"; - next_state.enter = std::bind(game::state::splash::enter, ctx); - next_state.exit = std::bind(game::state::splash::exit, ctx); - } - - // Queue next game state - ctx->app->queue_state(next_state); -} - -void exit(game::context* ctx) -{} - -void load_controls(game::context* ctx) -{ - // If a control profile is set in the config file - if (ctx->config->contains("control_profile")) - { - // Load control profile - json* profile = ctx->resource_manager->load((*ctx->config)["control_profile"].get()); - - // Apply control profile - if (profile) - { - game::apply_control_profile(ctx, *profile); - } - } - - // Calibrate gamepads - for (input::gamepad* gamepad: ctx->app->get_gamepads()) - { - ctx->logger->push_task("Loading calibration for gamepad " + gamepad->get_guid()); - json* calibration = game::load_gamepad_calibration(ctx, gamepad); - if (!calibration) - { - ctx->logger->pop_task(EXIT_FAILURE); - - ctx->logger->push_task("Generating default calibration for gamepad " + gamepad->get_guid()); - json default_calibration = game::default_gamepad_calibration(); - apply_gamepad_calibration(gamepad, default_calibration); - - if (!save_gamepad_calibration(ctx, gamepad, default_calibration)) - ctx->logger->pop_task(EXIT_FAILURE); - else - ctx->logger->pop_task(EXIT_SUCCESS); - } - else - { - ctx->logger->pop_task(EXIT_SUCCESS); - apply_gamepad_calibration(gamepad, *calibration); - } - } - - // Toggle fullscreen - ctx->controls["toggle_fullscreen"]->set_activated_callback - ( - [ctx]() - { - bool fullscreen = !ctx->app->is_fullscreen(); - - ctx->app->set_fullscreen(fullscreen); - - if (!fullscreen) - { - int2 resolution; - resolution.x = (*ctx->config)["windowed_resolution"][0].get(); - resolution.y = (*ctx->config)["windowed_resolution"][1].get(); - - ctx->app->resize_window(resolution.x, resolution.y); - } - - // Save display mode config - (*ctx->config)["fullscreen"] = fullscreen; - game::save_config(ctx); - } - ); - - // Screenshot - ctx->controls["screenshot"]->set_activated_callback - ( - [ctx]() - { - std::string path = ctx->screenshots_path + "antkeeper-" + timestamp() + ".png"; - ctx->app->save_frame(path); - } - ); - - // Set activation threshold for menu navigation controls to mitigate drifting gamepad axes - const float menu_activation_threshold = 0.1f; - ctx->controls["menu_up"]->set_activation_threshold(menu_activation_threshold); - ctx->controls["menu_down"]->set_activation_threshold(menu_activation_threshold); - ctx->controls["menu_left"]->set_activation_threshold(menu_activation_threshold); - ctx->controls["menu_right"]->set_activation_threshold(menu_activation_threshold); -} - -void cosmogenesis(game::context* ctx) -{ - // Init time - const double time = 0.0; - ctx->astronomy_system->set_universal_time(time); - ctx->orbit_system->set_universal_time(time); - - // Create sun - ctx->logger->push_task("Creating the sun"); - try - { - heliogenesis(ctx); - } - catch (...) - { - ctx->logger->pop_task(EXIT_FAILURE); - throw; - } - ctx->logger->pop_task(EXIT_SUCCESS); - - // Create planet - ctx->logger->push_task("Creating the planet"); - try - { - planetogenesis(ctx); - } - catch (...) - { - ctx->logger->pop_task(EXIT_FAILURE); - throw; - } - ctx->logger->pop_task(EXIT_SUCCESS); - - // Create moon - ctx->logger->push_task("Creating the moon"); - try - { - selenogenesis(ctx); - } - catch (...) - { - ctx->logger->pop_task(EXIT_FAILURE); - throw; - } - ctx->logger->pop_task(EXIT_SUCCESS); - - // Create fixed stars - ctx->logger->push_task("Creating fixed stars"); - try - { - extrasolar_heliogenesis(ctx); - } - catch (...) - { - ctx->logger->pop_task(EXIT_FAILURE); - throw; - } - ctx->logger->pop_task(EXIT_SUCCESS); - - // Create ant colony - ctx->logger->push_task("Creating ant colony"); - try - { - colonigenesis(ctx); - } - catch (...) - { - ctx->logger->pop_task(EXIT_FAILURE); - throw; - } - ctx->logger->pop_task(EXIT_SUCCESS); -} - -void heliogenesis(game::context* ctx) -{ - // Create solar entity - entity::archetype* sun_archetype = ctx->resource_manager->load("sun.ent"); - entity::id sun_eid = sun_archetype->create(*ctx->entity_registry); - ctx->entities["sun"] = sun_eid; - - // Create direct sun light scene object - scene::directional_light* sun_direct = new scene::directional_light(); - - // Create ambient sun light scene object - scene::ambient_light* sun_ambient = new scene::ambient_light(); - sun_ambient->set_color({1, 1, 1}); - sun_ambient->set_intensity(0.0f); - sun_ambient->update_tweens(); - - // Add sun light scene objects to surface scene - ctx->surface_scene->add_object(sun_direct); - ctx->surface_scene->add_object(sun_ambient); - - // Pass direct sun light scene object to shadow map pass and astronomy system - ctx->surface_shadow_map_pass->set_light(sun_direct); - ctx->astronomy_system->set_sun_light(sun_direct); -} - -void planetogenesis(game::context* ctx) -{ - // Create planetary entity - entity::archetype* planet_archetype = ctx->resource_manager->load("planet.ent"); - entity::id planet_eid = planet_archetype->create(*ctx->entity_registry); - ctx->entities["planet"] = planet_eid; - - // Assign planetary terrain component - entity::component::terrain terrain; - terrain.elevation = [](double, double) -> double - { - //return math::random(0.0, 1.0); - return 0.0; - }; - terrain.max_lod = 0; - terrain.patch_material = nullptr; - ctx->entity_registry->assign(planet_eid, terrain); - - // Pass planet to astronomy system as reference body - ctx->astronomy_system->set_reference_body(planet_eid); - - // Load sky model - ctx->surface_sky_pass->set_sky_model(ctx->resource_manager->load("sky-dome.mdl")); -} +namespace world { -void selenogenesis(game::context* ctx) -{ - // Create lunar entity - entity::id moon_eid = ctx->entity_registry->create(); - ctx->entities["moon"] = moon_eid; - - // Pass moon model to sky pass - ctx->surface_sky_pass->set_moon_model(ctx->resource_manager->load("moon.mdl")); -} - -void extrasolar_heliogenesis(game::context* ctx) +void create_stars(game::context* ctx) { // Load star catalog string_table* star_catalog = ctx->resource_manager->load("stars.csv"); @@ -492,9 +183,80 @@ void extrasolar_heliogenesis(game::context* ctx) ctx->surface_sky_pass->set_stars_model(stars_model); } -void colonigenesis(game::context* ctx) -{} +void create_sun(game::context* ctx) +{ + // Create sun entity + entity::archetype* sun_archetype = ctx->resource_manager->load("sun.ent"); + entity::id sun_eid = sun_archetype->create(*ctx->entity_registry); + ctx->entities["sun"] = sun_eid; + + // Create direct sun light scene object + scene::directional_light* sun_direct = new scene::directional_light(); + + // Create ambient sun light scene object + scene::ambient_light* sun_ambient = new scene::ambient_light(); + sun_ambient->set_color({1, 1, 1}); + sun_ambient->set_intensity(0.0f); + sun_ambient->update_tweens(); + + // Add sun light scene objects to surface scene + ctx->surface_scene->add_object(sun_direct); + ctx->surface_scene->add_object(sun_ambient); + + // Pass direct sun light scene object to shadow map pass and astronomy system + ctx->surface_shadow_map_pass->set_light(sun_direct); + ctx->astronomy_system->set_sun_light(sun_direct); +} + +void create_planet(game::context* ctx) +{ + // Create planet entity + entity::archetype* planet_archetype = ctx->resource_manager->load("planet.ent"); + entity::id planet_eid = planet_archetype->create(*ctx->entity_registry); + ctx->entities["planet"] = planet_eid; + + // Assign planetary terrain component + entity::component::terrain terrain; + terrain.elevation = [](double, double) -> double + { + //return math::random(0.0, 1.0); + return 0.0; + }; + terrain.max_lod = 0; + terrain.patch_material = nullptr; + ctx->entity_registry->assign(planet_eid, terrain); + + // Pass planet to astronomy system as reference body + ctx->astronomy_system->set_reference_body(planet_eid); + + // Load sky model + ctx->surface_sky_pass->set_sky_model(ctx->resource_manager->load("sky-dome.mdl")); +} + +void create_moon(game::context* ctx) +{ + // Create lunar entity + entity::id moon_eid = ctx->entity_registry->create(); + ctx->entities["moon"] = moon_eid; + + // Pass moon model to sky pass + ctx->surface_sky_pass->set_moon_model(ctx->resource_manager->load("moon.mdl")); +} + +void set_time(game::context* ctx, double t) +{ + ctx->astronomy_system->set_universal_time(t); + ctx->orbit_system->set_universal_time(t); +} + +void set_time_scale(game::context* ctx, double scale) +{ + static constexpr double seconds_per_day = 24.0 * 60.0 * 60.0; + scale /= seconds_per_day; + + ctx->orbit_system->set_time_scale(scale); + ctx->astronomy_system->set_time_scale(scale); +} -} // namespace loading -} // namespace state +} // namespace world } // namespace game diff --git a/src/game/world.hpp b/src/game/world.hpp new file mode 100644 index 0000000..8b409b5 --- /dev/null +++ b/src/game/world.hpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2021 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code 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. + * + * Antkeeper source code 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 Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_GAME_WORLD_HPP +#define ANTKEEPER_GAME_WORLD_HPP + +#include "game/context.hpp" + +namespace game { + +/// World creation and manipulation functions. +namespace world { + +/// Creates the fixed stars. +void create_stars(game::context* ctx); + +/// Creates the sun. +void create_sun(game::context* ctx); + +/// Creates the planet. +void create_planet(game::context* ctx); + +/// Creates the moon. +void create_moon(game::context* ctx); + +/// Sets the current time. +void set_time(game::context* ctx, double t); + +/// Sets rate at which time passes. +void set_time_scale(game::context* ctx, double scale); + +} // namespace menu +} // namespace game + +#endif // ANTKEEPER_GAME_WORLD_HPP diff --git a/src/render/passes/material-pass.cpp b/src/render/passes/material-pass.cpp index fa6ea33..0374b8f 100644 --- a/src/render/passes/material-pass.cpp +++ b/src/render/passes/material-pass.cpp @@ -659,7 +659,7 @@ bool operation_compare(const render::operation& a, const render::operation& b) else { // A and B are both transparent, but not decals, render back to front - return (a.depth >= b.depth); + return (a.depth <= b.depth); } } } diff --git a/src/render/passes/sky-pass.cpp b/src/render/passes/sky-pass.cpp index d06ea5b..e46930f 100644 --- a/src/render/passes/sky-pass.cpp +++ b/src/render/passes/sky-pass.cpp @@ -188,8 +188,8 @@ void sky_pass::render(const render::context& ctx, render::queue& queue) const } glEnable(GL_BLEND); - //glBlendFunc(GL_SRC_ALPHA, GL_ONE); - glBlendFunc(GL_ONE, GL_ONE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + //glBlendFunc(GL_ONE, GL_ONE); // Draw stars if (stars_model) @@ -249,8 +249,6 @@ void sky_pass::render(const render::context& ctx, render::queue& queue) const rasterizer->draw_arrays(*moon_model_vao, moon_model_drawing_mode, moon_model_start_index, moon_model_index_count); } */ - - } void sky_pass::set_sky_model(const model* model) diff --git a/src/type/font-metrics.hpp b/src/type/font-metrics.hpp index 4cf7a59..21f8fac 100644 --- a/src/type/font-metrics.hpp +++ b/src/type/font-metrics.hpp @@ -27,7 +27,7 @@ namespace type { */ struct font_metrics { - /// Vertical size of the font, in pixels. + /// Vertical size of the font. float size; /// Positive distance from the baseline to the highest or upper grid coordinate.