💿🐜 Antkeeper source code https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

202 lines
6.9 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. /*
  2. * Copyright (C) 2021 Christopher J. Howard
  3. *
  4. * This file is part of Antkeeper source code.
  5. *
  6. * Antkeeper source code is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Antkeeper source code is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include "game/states/main-menu.hpp"
  20. #include "game/states/forage.hpp"
  21. #include "game/states/nuptial-flight.hpp"
  22. #include "render/passes/clear-pass.hpp"
  23. #include "resources/resource-manager.hpp"
  24. #include "render/model.hpp"
  25. #include "animation/screen-transition.hpp"
  26. #include "animation/ease.hpp"
  27. #include "animation/timeline.hpp"
  28. #include "application.hpp"
  29. #include <limits>
  30. namespace game {
  31. namespace state {
  32. namespace main_menu {
  33. void enter(game::context* ctx)
  34. {
  35. ctx->ui_clear_pass->set_cleared_buffers(true, true, false);
  36. // Construct main menu texts
  37. ctx->main_menu_start_text = new scene::text();
  38. ctx->main_menu_options_text = new scene::text();
  39. ctx->main_menu_credits_text = new scene::text();
  40. ctx->main_menu_quit_text = new scene::text();
  41. // Set content of texts
  42. ctx->main_menu_start_text->set_content((*ctx->strings)["main_menu_start"]);
  43. ctx->main_menu_options_text->set_content((*ctx->strings)["main_menu_options"]);
  44. ctx->main_menu_credits_text->set_content((*ctx->strings)["main_menu_credits"]);
  45. ctx->main_menu_quit_text->set_content((*ctx->strings)["main_menu_quit"]);
  46. std::vector<scene::text*> texts;
  47. texts.push_back(ctx->main_menu_start_text);
  48. texts.push_back(ctx->main_menu_options_text);
  49. texts.push_back(ctx->main_menu_credits_text);
  50. texts.push_back(ctx->main_menu_quit_text);
  51. float offset_y = 0.0f;
  52. for (scene::text* text: texts)
  53. {
  54. text->set_material(&ctx->menu_font_material);
  55. text->set_font(&ctx->menu_font);
  56. text->set_color({1.0f, 1.0f, 1.0f, 0.5f});
  57. ctx->ui_scene->add_object(text);
  58. // Align text
  59. const auto& text_aabb = static_cast<const geom::aabb<float>&>(text->get_local_bounds());
  60. float title_w = text_aabb.max_point.x - text_aabb.min_point.x;
  61. float title_h = text_aabb.max_point.y - text_aabb.min_point.y;
  62. text->set_translation({std::round(-title_w * 0.5f), std::round(-title_h * 0.5f) + offset_y, 0.0f});
  63. offset_y -= ctx->menu_font.get_font_metrics().linespace * 1.5f;
  64. // Update menu AABB
  65. }
  66. // Load pointer
  67. ctx->ui_pointer = new scene::model_instance();
  68. ctx->ui_pointer->set_model(ctx->resource_manager->load<render::model>("pointer.mdl"));
  69. ctx->ui_scene->add_object(ctx->ui_pointer);
  70. // Scale and position pointer
  71. float pointer_scale = (ctx->menu_font.get_font_metrics().ascent - ctx->menu_font.get_font_metrics().descent) * (1.0f/3.0f);
  72. ctx->ui_pointer->set_scale({pointer_scale, pointer_scale, pointer_scale});
  73. float advance_x = ctx->menu_font.get_glyph_metrics(U' ').horizontal_advance * 2.0f;
  74. const auto& text_aabb = static_cast<const geom::aabb<float>&>(ctx->main_menu_start_text->get_local_bounds());
  75. const auto& text_translation = ctx->main_menu_start_text->get_translation();
  76. ctx->ui_pointer->set_translation(text_translation + float3{-advance_x, (text_aabb.max_point.y - text_aabb.min_point.y) * 0.5f, 0.0f});
  77. ctx->main_menu_start_text->set_color({1.0f, 1.0f, 1.0f, 1.0f});
  78. ctx->controls["menu_down"]->set_activated_callback
  79. (
  80. [ctx]()
  81. {
  82. ctx->ui_pointer->set_translation(ctx->ui_pointer->get_translation() - float3{0.0f, ctx->menu_font.get_font_metrics().linespace * 1.5f, 0.0f});
  83. }
  84. );
  85. ctx->controls["menu_up"]->set_activated_callback
  86. (
  87. [ctx]()
  88. {
  89. ctx->ui_pointer->set_translation(ctx->ui_pointer->get_translation() + float3{0.0f, ctx->menu_font.get_font_metrics().linespace * 1.5f, 0.0f});
  90. }
  91. );
  92. ctx->controls["menu_select"]->set_activated_callback
  93. (
  94. [ctx]()
  95. {
  96. // Disable menu controls
  97. ctx->controls["menu_down"]->set_activated_callback(nullptr);
  98. ctx->controls["menu_up"]->set_activated_callback(nullptr);
  99. ctx->controls["menu_select"]->set_activated_callback(nullptr);
  100. // Create change state functions
  101. auto change_state_nuptial_flight = [ctx]()
  102. {
  103. application::state next_state;
  104. next_state.name = "nuptial_flight";
  105. next_state.enter = std::bind(game::state::nuptial_flight::enter, ctx);
  106. next_state.exit = std::bind(game::state::nuptial_flight::exit, ctx);
  107. ctx->app->change_state(next_state);
  108. };
  109. // Set up timing
  110. const float fade_out_duration = 1.0f;
  111. // Schedule state change
  112. timeline* timeline = ctx->timeline;
  113. float t = timeline->get_position();
  114. timeline::sequence sequence =
  115. {
  116. {t + fade_out_duration, change_state_nuptial_flight}
  117. };
  118. timeline->add_sequence(sequence);
  119. // Start fade out to white
  120. ctx->fade_transition_color->set_value({1, 1, 1});
  121. ctx->fade_transition->transition(fade_out_duration, false, ease<float>::out_quad, false);
  122. }
  123. );
  124. // Disable control callbacks
  125. ctx->controls["menu_down"]->set_callbacks_enabled(false);
  126. ctx->controls["menu_up"]->set_callbacks_enabled(false);
  127. ctx->controls["menu_select"]->set_callbacks_enabled(false);
  128. // Start fade in from black
  129. const float fade_in_duration = 0.5f;
  130. ctx->fade_transition_color->set_value({0, 0, 0});
  131. ctx->fade_transition->transition(fade_in_duration, true, ease<float>::in_quad);
  132. // Schedule enabling of control callbacks
  133. auto enable_control_callbacks = [ctx]()
  134. {
  135. ctx->controls["menu_down"]->set_callbacks_enabled(true);
  136. ctx->controls["menu_up"]->set_callbacks_enabled(true);
  137. ctx->controls["menu_select"]->set_callbacks_enabled(true);
  138. };
  139. timeline* timeline = ctx->timeline;
  140. float t = timeline->get_position();
  141. timeline::sequence sequence =
  142. {
  143. {t + fade_in_duration, enable_control_callbacks}
  144. };
  145. timeline->add_sequence(sequence);
  146. }
  147. void exit(game::context* ctx)
  148. {
  149. // Remove control callbacks
  150. ctx->controls["menu_down"]->set_activated_callback(nullptr);
  151. ctx->controls["menu_up"]->set_activated_callback(nullptr);
  152. ctx->controls["menu_select"]->set_activated_callback(nullptr);
  153. // Remove text objects from UI
  154. std::vector<scene::text*> texts;
  155. texts.push_back(ctx->main_menu_start_text);
  156. texts.push_back(ctx->main_menu_options_text);
  157. texts.push_back(ctx->main_menu_credits_text);
  158. texts.push_back(ctx->main_menu_quit_text);
  159. for (scene::text* text: texts)
  160. {
  161. ctx->ui_scene->remove_object(text);
  162. delete text;
  163. text = nullptr;
  164. }
  165. // Remove pointer from UI
  166. ctx->ui_scene->remove_object(ctx->ui_pointer);
  167. delete ctx->ui_pointer;
  168. ctx->ui_pointer = nullptr;
  169. ctx->ui_clear_pass->set_cleared_buffers(false, true, false);
  170. }
  171. } // namespace main_menu
  172. } // namespace state
  173. } // namespace game