💿🐜 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.

614 lines
21 KiB

  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/state/nuptial-flight.hpp"
  20. #include "game/state/pause-menu.hpp"
  21. #include "entity/archetype.hpp"
  22. #include "entity/systems/camera.hpp"
  23. #include "entity/systems/astronomy.hpp"
  24. #include "entity/components/observer.hpp"
  25. #include "entity/components/transform.hpp"
  26. #include "entity/components/terrain.hpp"
  27. #include "entity/components/camera.hpp"
  28. #include "entity/components/constraints/spring-to.hpp"
  29. #include "entity/components/constraints/three-dof.hpp"
  30. #include "entity/components/constraint-stack.hpp"
  31. #include "entity/commands.hpp"
  32. #include "animation/screen-transition.hpp"
  33. #include "animation/ease.hpp"
  34. #include "resources/resource-manager.hpp"
  35. #include "game/world.hpp"
  36. #include "application.hpp"
  37. #include "render/passes/clear-pass.hpp"
  38. #include "render/passes/ground-pass.hpp"
  39. #include "state-machine.hpp"
  40. #include "config.hpp"
  41. namespace game {
  42. namespace state {
  43. nuptial_flight::nuptial_flight(game::context& ctx):
  44. game::state::base(ctx)
  45. {
  46. ctx.logger->push_task("Entering nuptial flight state");
  47. // Disable UI color clear
  48. ctx.ui_clear_pass->set_cleared_buffers(false, true, false);
  49. // Setup and enable sky pass
  50. ctx.sky_pass->set_sky_model(ctx.resource_manager->load<render::model>("celestial-hemisphere.mdl"));
  51. ctx.sky_pass->set_enabled(true);
  52. // Setup and enable ground pass
  53. render::model* terrestrial_hemisphere_model = ctx.resource_manager->load<render::model>("terrestrial-hemisphere.mdl");
  54. (*terrestrial_hemisphere_model->get_groups())[0]->set_material(ctx.resource_manager->load<render::material>("scrub-terrestrial-hemisphere.mtl"));
  55. ctx.ground_pass->set_ground_model(terrestrial_hemisphere_model);
  56. ctx.ground_pass->set_enabled(true);
  57. // Create world
  58. game::world::create_stars(ctx);
  59. game::world::create_sun(ctx);
  60. game::world::create_planet(ctx);
  61. game::world::create_moon(ctx);
  62. // Set time to solar noon
  63. game::world::set_time(ctx, 0.0);
  64. // Freeze time
  65. game::world::set_time_scale(ctx, 0.0);
  66. // Find planet EID by name
  67. entity::id planet_eid = ctx.entities["planet"];
  68. // Remove terrain component from planet (if any)
  69. //if (ctx.entity_registry->has<entity::component::terrain>(planet_eid))
  70. // ctx.entity_registry->remove<entity::component::terrain>(planet_eid);
  71. // Enable clouds in sky pass
  72. //ctx.sky_pass->set_clouds_model(ctx.resource_manager->load<render::model>("cloud-plane.mdl"));
  73. // Create biome terrain component
  74. /*
  75. entity::component::terrain biome_terrain;
  76. biome_terrain.max_lod = 18;
  77. biome_terrain.patch_material = ctx.resource_manager->load<render::material>("desert-terrain.mtl");
  78. biome_terrain.elevation = [](double, double) -> double
  79. {
  80. return 0.0;
  81. };
  82. // Replace planet terrain component with biome terrain component
  83. ctx.entity_registry->replace<entity::component::terrain>(planet_eid, biome_terrain);
  84. */
  85. // Create observer
  86. entity::id observer_eid = ctx.entity_registry->create();
  87. {
  88. entity::component::observer observer;
  89. observer.reference_body_eid = planet_eid;
  90. observer.elevation = 2000.0;
  91. observer.latitude = 0.0;
  92. observer.longitude = 0.0;
  93. observer.camera = ctx.surface_camera;
  94. ctx.entity_registry->assign<entity::component::observer>(observer_eid, observer);
  95. // Set reference location of astronomy system
  96. ctx.astronomy_system->set_reference_body(planet_eid);
  97. ctx.astronomy_system->set_observer_location(double3{observer.elevation, observer.latitude, observer.longitude});
  98. }
  99. // Setup camera
  100. setup_camera();
  101. // Queue fade in
  102. ctx.fade_transition_color->set_value({1, 1, 1});
  103. ctx.function_queue.push(std::bind(&screen_transition::transition, ctx.fade_transition, config::nuptial_flight_fade_in_duration, true, ease<float>::out_sine, true, nullptr));
  104. // Queue control setup
  105. ctx.function_queue.push(std::bind(&nuptial_flight::enable_controls, this));
  106. ctx.logger->pop_task(EXIT_SUCCESS);
  107. }
  108. nuptial_flight::~nuptial_flight()
  109. {
  110. ctx.logger->push_task("Exiting nuptial flight state");
  111. // Resume time
  112. //const double time_scale = (*ctx.config)["time_scale"].get<double>();
  113. //game::world::set_time_scale(ctx, time_scale);
  114. ctx.logger->pop_task(EXIT_SUCCESS);
  115. }
  116. void nuptial_flight::setup_camera()
  117. {
  118. // Switch to surface camera
  119. ctx.underground_camera->set_active(false);
  120. ctx.surface_camera->set_active(true);
  121. // Create surface camera entity
  122. if (!ctx.entities.count("surface_cam"))
  123. {
  124. // Create camera target entity
  125. entity::id target_eid = ctx.entity_registry->create();
  126. ctx.entities["surface_cam_target"] = target_eid;
  127. {
  128. // Transform
  129. entity::component::transform target_transform;
  130. target_transform.local = math::identity_transform<float>;
  131. target_transform.world = target_transform.local;
  132. target_transform.warp = true;
  133. ctx.entity_registry->assign<entity::component::transform>(target_eid, target_transform);
  134. }
  135. // Create camera entity
  136. entity::id camera_eid = ctx.entity_registry->create();
  137. ctx.entities["surface_cam"] = camera_eid;
  138. // Create camera transform component
  139. entity::component::transform transform;
  140. transform.local = math::identity_transform<float>;
  141. transform.world = transform.local;
  142. transform.warp = true;
  143. ctx.entity_registry->assign<entity::component::transform>(camera_eid, transform);
  144. // Create camera camera component
  145. entity::component::camera camera;
  146. camera.object = ctx.surface_camera;
  147. ctx.entity_registry->assign<entity::component::camera>(camera_eid, camera);
  148. // Create camera 3DOF constraint entity
  149. entity::id three_dof_constraint_eid = ctx.entity_registry->create();
  150. ctx.entities["surface_cam_3dof"] = three_dof_constraint_eid;
  151. {
  152. // Create 3DOF to constraint
  153. entity::component::constraint::three_dof three_dof;
  154. three_dof.yaw = 0.0f;
  155. three_dof.pitch = 0.0f;
  156. three_dof.roll = 0.0f;
  157. ctx.entity_registry->assign<entity::component::constraint::three_dof>(three_dof_constraint_eid, three_dof);
  158. // Create constraint stack node component
  159. entity::component::constraint_stack_node node;
  160. node.active = true;
  161. node.weight = 1.0f;
  162. node.next = entt::null;
  163. ctx.entity_registry->assign<entity::component::constraint_stack_node>(three_dof_constraint_eid, node);
  164. }
  165. // Create camera spring to constraint entity
  166. entity::id spring_constraint_eid = ctx.entity_registry->create();
  167. {
  168. // Create spring to constraint
  169. entity::component::constraint::spring_to spring;
  170. spring.target = target_eid;
  171. 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<float>};
  172. spring.translation.w = hz_to_rads(8.0f);
  173. spring.spring_translation = true;
  174. spring.spring_rotation = false;
  175. ctx.entity_registry->assign<entity::component::constraint::spring_to>(spring_constraint_eid, spring);
  176. // Create constraint stack node component
  177. entity::component::constraint_stack_node node;
  178. node.active = true;
  179. node.weight = 1.0f;
  180. node.next = three_dof_constraint_eid;
  181. ctx.entity_registry->assign<entity::component::constraint_stack_node>(spring_constraint_eid, node);
  182. }
  183. // Create camera constraint stack component
  184. entity::component::constraint_stack constraint_stack;
  185. constraint_stack.head = spring_constraint_eid;
  186. ctx.entity_registry->assign<entity::component::constraint_stack>(camera_eid, constraint_stack);
  187. }
  188. float ev100 = 13.5f;
  189. ctx.surface_camera->set_exposure(ev100);
  190. }
  191. void nuptial_flight::enable_controls()
  192. {
  193. // Get camera entities
  194. entity::id camera_eid = ctx.entities["surface_cam"];
  195. entity::id target_eid = ctx.entities["surface_cam_target"];
  196. entity::id three_dof_eid = ctx.entities["surface_cam_3dof"];
  197. const float min_elevation = 0.1f;
  198. const float max_elevation = 100.0f;
  199. const float slow_modifier = 0.25f;
  200. const float fast_modifier = 4.0f;
  201. const float dolly_speed = 5.0f;
  202. const float truck_speed = dolly_speed;
  203. const float pedestal_speed = 5.0f;
  204. float mouse_tilt_sensitivity = 1.0f;
  205. float mouse_pan_sensitivity = 1.0f;
  206. bool mouse_invert_tilt = false;
  207. bool mouse_invert_pan = false;
  208. float gamepad_tilt_sensitivity = 1.0f;
  209. float gamepad_pan_sensitivity = 1.0f;
  210. bool gamepad_invert_tilt = false;
  211. bool gamepad_invert_pan = false;
  212. bool mouse_look_toggle = false;
  213. ctx.mouse_look = false;
  214. const double time_scale = 5000.0;
  215. if (ctx.config->contains("mouse_tilt_sensitivity"))
  216. mouse_tilt_sensitivity = math::radians((*ctx.config)["mouse_tilt_sensitivity"].get<float>());
  217. if (ctx.config->contains("mouse_pan_sensitivity"))
  218. mouse_pan_sensitivity = math::radians((*ctx.config)["mouse_pan_sensitivity"].get<float>());
  219. if (ctx.config->contains("mouse_invert_tilt"))
  220. mouse_invert_tilt = math::radians((*ctx.config)["mouse_invert_tilt"].get<bool>());
  221. if (ctx.config->contains("mouse_invert_pan"))
  222. mouse_invert_pan = math::radians((*ctx.config)["mouse_invert_pan"].get<bool>());
  223. if (ctx.config->contains("mouse_look_toggle"))
  224. mouse_look_toggle = math::radians((*ctx.config)["mouse_look_toggle"].get<bool>());
  225. if (ctx.config->contains("gamepad_tilt_sensitivity"))
  226. gamepad_tilt_sensitivity = math::radians((*ctx.config)["gamepad_tilt_sensitivity"].get<float>());
  227. if (ctx.config->contains("gamepad_pan_sensitivity"))
  228. gamepad_pan_sensitivity = math::radians((*ctx.config)["gamepad_pan_sensitivity"].get<float>());
  229. if (ctx.config->contains("gamepad_invert_tilt"))
  230. gamepad_invert_tilt = math::radians((*ctx.config)["gamepad_invert_tilt"].get<bool>());
  231. if (ctx.config->contains("gamepad_invert_pan"))
  232. gamepad_invert_pan = math::radians((*ctx.config)["gamepad_invert_pan"].get<bool>());
  233. const input::control* move_slow = ctx.controls["move_slow"];
  234. const input::control* move_fast = ctx.controls["move_fast"];
  235. const input::control* mouse_look = ctx.controls["mouse_look"];
  236. float mouse_tilt_factor = mouse_tilt_sensitivity * (mouse_invert_tilt ? -1.0f : 1.0f);
  237. float mouse_pan_factor = mouse_pan_sensitivity * (mouse_invert_pan ? -1.0f : 1.0f);
  238. float gamepad_tilt_factor = gamepad_tilt_sensitivity * (gamepad_invert_tilt ? -1.0f : 1.0f);
  239. float gamepad_pan_factor = gamepad_pan_sensitivity * (gamepad_invert_pan ? -1.0f : 1.0f);
  240. ctx.controls["move_forward"]->set_active_callback
  241. (
  242. [&ctx = this->ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value)
  243. {
  244. if (move_slow->is_active())
  245. value *= slow_modifier;
  246. if (move_fast->is_active())
  247. value *= fast_modifier;
  248. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  249. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  250. const float3 movement = {0.0f, 0.0f, -truck_speed * value * (1.0f / 60.0f)};
  251. entity::command::translate(*ctx.entity_registry, target_eid, yaw * movement);
  252. }
  253. );
  254. // Dolly backward
  255. ctx.controls["move_back"]->set_active_callback
  256. (
  257. [&ctx = this->ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value)
  258. {
  259. if (move_slow->is_active())
  260. value *= slow_modifier;
  261. if (move_fast->is_active())
  262. value *= fast_modifier;
  263. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  264. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  265. const float3 movement = {0.0f, 0.0f, truck_speed * value * (1.0f / 60.0f)};
  266. entity::command::translate(*ctx.entity_registry, target_eid, yaw * movement);
  267. }
  268. );
  269. // Truck right
  270. ctx.controls["move_right"]->set_active_callback
  271. (
  272. [&ctx = this->ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value)
  273. {
  274. if (move_slow->is_active())
  275. value *= slow_modifier;
  276. if (move_fast->is_active())
  277. value *= fast_modifier;
  278. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  279. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  280. const float3 movement = {truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f};
  281. entity::command::translate(*ctx.entity_registry, target_eid, yaw * movement);
  282. }
  283. );
  284. // Truck left
  285. ctx.controls["move_left"]->set_active_callback
  286. (
  287. [&ctx = this->ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value)
  288. {
  289. if (move_slow->is_active())
  290. value *= slow_modifier;
  291. if (move_fast->is_active())
  292. value *= fast_modifier;
  293. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  294. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  295. const float3 movement = {-truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f};
  296. entity::command::translate(*ctx.entity_registry, target_eid, yaw * movement);
  297. }
  298. );
  299. // Pedestal up
  300. ctx.controls["move_up"]->set_active_callback
  301. (
  302. [&ctx = this->ctx, target_eid, pedestal_speed, move_slow, move_fast, slow_modifier, fast_modifier, max_elevation](float value)
  303. {
  304. if (move_slow->is_active())
  305. value *= slow_modifier;
  306. if (move_fast->is_active())
  307. value *= fast_modifier;
  308. float3 movement = {0.0f, pedestal_speed * value * (1.0f / 60.0f), 0.0f};
  309. auto transform = entity::command::get_world_transform(*ctx.entity_registry, target_eid);
  310. if (transform.translation.y + movement.y > max_elevation)
  311. movement.y = max_elevation - transform.translation.y;
  312. entity::command::translate(*ctx.entity_registry, target_eid, movement);
  313. }
  314. );
  315. // Pedestal down
  316. ctx.controls["move_down"]->set_active_callback
  317. (
  318. [&ctx = this->ctx, target_eid, pedestal_speed, move_slow, move_fast, slow_modifier, fast_modifier, min_elevation](float value)
  319. {
  320. if (move_slow->is_active())
  321. value *= slow_modifier;
  322. if (move_fast->is_active())
  323. value *= fast_modifier;
  324. float3 movement = {0.0f, -pedestal_speed * value * (1.0f / 60.0f), 0.0f};
  325. auto transform = entity::command::get_world_transform(*ctx.entity_registry, target_eid);
  326. if (transform.translation.y + movement.y < min_elevation)
  327. movement.y = min_elevation - transform.translation.y;
  328. entity::command::translate(*ctx.entity_registry, target_eid, movement);
  329. }
  330. );
  331. // Mouse rotate
  332. ctx.controls["mouse_look"]->set_activated_callback
  333. (
  334. [&ctx = this->ctx, mouse_look_toggle]()
  335. {
  336. if (mouse_look_toggle)
  337. ctx.mouse_look = !ctx.mouse_look;
  338. else
  339. ctx.mouse_look = true;
  340. ctx.app->set_relative_mouse_mode(ctx.mouse_look);
  341. }
  342. );
  343. ctx.controls["mouse_look"]->set_deactivated_callback
  344. (
  345. [&ctx = this->ctx, mouse_look_toggle]()
  346. {
  347. if (!mouse_look_toggle)
  348. {
  349. ctx.mouse_look = false;
  350. ctx.app->set_relative_mouse_mode(false);
  351. }
  352. }
  353. );
  354. // Pan left
  355. ctx.controls["look_left_gamepad"]->set_active_callback
  356. (
  357. [&ctx = this->ctx, three_dof_eid, gamepad_pan_factor](float value)
  358. {
  359. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  360. three_dof.yaw += gamepad_pan_factor * value * (1.0f / 60.0f);
  361. }
  362. );
  363. ctx.controls["look_left_mouse"]->set_active_callback
  364. (
  365. [&ctx = this->ctx, three_dof_eid, mouse_pan_factor](float value)
  366. {
  367. if (!ctx.mouse_look)
  368. return;
  369. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  370. three_dof.yaw += mouse_pan_factor * value * (1.0f / 60.0f);
  371. }
  372. );
  373. // Pan right
  374. ctx.controls["look_right_gamepad"]->set_active_callback
  375. (
  376. [&ctx = this->ctx, three_dof_eid, gamepad_pan_factor](float value)
  377. {
  378. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  379. three_dof.yaw -= gamepad_pan_factor * value * (1.0f / 60.0f);
  380. }
  381. );
  382. ctx.controls["look_right_mouse"]->set_active_callback
  383. (
  384. [&ctx = this->ctx, three_dof_eid, mouse_pan_factor](float value)
  385. {
  386. if (!ctx.mouse_look)
  387. return;
  388. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  389. three_dof.yaw -= mouse_pan_factor * value * (1.0f / 60.0f);
  390. }
  391. );
  392. // Tilt up
  393. ctx.controls["look_up_gamepad"]->set_active_callback
  394. (
  395. [&ctx = this->ctx, three_dof_eid, gamepad_tilt_factor](float value)
  396. {
  397. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  398. three_dof.pitch -= gamepad_tilt_factor * value * (1.0f / 60.0f);
  399. three_dof.pitch = std::max<float>(math::radians(-90.0f), three_dof.pitch);
  400. }
  401. );
  402. ctx.controls["look_up_mouse"]->set_active_callback
  403. (
  404. [&ctx = this->ctx, three_dof_eid, mouse_tilt_factor](float value)
  405. {
  406. if (!ctx.mouse_look)
  407. return;
  408. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  409. three_dof.pitch -= mouse_tilt_factor * value * (1.0f / 60.0f);
  410. three_dof.pitch = std::max<float>(math::radians(-90.0f), three_dof.pitch);
  411. }
  412. );
  413. // Tilt down
  414. ctx.controls["look_down_gamepad"]->set_active_callback
  415. (
  416. [&ctx = this->ctx, three_dof_eid, gamepad_tilt_factor](float value)
  417. {
  418. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  419. three_dof.pitch += gamepad_tilt_factor * value * (1.0f / 60.0f);
  420. three_dof.pitch = std::min<float>(math::radians(90.0f), three_dof.pitch);
  421. }
  422. );
  423. ctx.controls["look_down_mouse"]->set_active_callback
  424. (
  425. [&ctx = this->ctx, three_dof_eid, mouse_tilt_factor](float value)
  426. {
  427. if (!ctx.mouse_look)
  428. return;
  429. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  430. three_dof.pitch += mouse_tilt_factor * value * (1.0f / 60.0f);
  431. three_dof.pitch = std::min<float>(math::radians(90.0f), three_dof.pitch);
  432. }
  433. );
  434. /*
  435. // Use tool
  436. ctx.controls["use_tool"]->set_activated_callback
  437. (
  438. [&ctx]()
  439. {
  440. if (ctx.entities.count("active_tool"))
  441. {
  442. entity::id tool_eid = ctx.entities["active_tool"];
  443. const auto& tool = ctx.entity_registry->get<entity::component::tool>(tool_eid);
  444. if (tool.activated)
  445. tool.activated();
  446. }
  447. }
  448. );
  449. ctx.controls["use_tool"]->set_deactivated_callback
  450. (
  451. [&ctx]()
  452. {
  453. if (ctx.entities.count("active_tool"))
  454. {
  455. entity::id tool_eid = ctx.entities["active_tool"];
  456. const auto& tool = ctx.entity_registry->get<entity::component::tool>(tool_eid);
  457. if (tool.deactivated)
  458. tool.deactivated();
  459. }
  460. }
  461. );
  462. ctx.controls["use_tool"]->set_active_callback
  463. (
  464. [&ctx](float value)
  465. {
  466. if (ctx.entities.count("active_tool"))
  467. {
  468. entity::id tool_eid = ctx.entities["active_tool"];
  469. const auto& tool = ctx.entity_registry->get<entity::component::tool>(tool_eid);
  470. if (tool.active)
  471. tool.active();
  472. }
  473. }
  474. );
  475. */
  476. // Fast-forward
  477. ctx.controls["fast_forward"]->set_activated_callback
  478. (
  479. [&ctx = this->ctx, time_scale]()
  480. {
  481. game::world::set_time_scale(ctx, time_scale);
  482. }
  483. );
  484. ctx.controls["fast_forward"]->set_deactivated_callback
  485. (
  486. [&ctx = this->ctx, time_scale]()
  487. {
  488. game::world::set_time_scale(ctx, 0.0);
  489. }
  490. );
  491. ctx.controls["rewind"]->set_activated_callback
  492. (
  493. [&ctx = this->ctx, time_scale]()
  494. {
  495. game::world::set_time_scale(ctx, -time_scale);
  496. }
  497. );
  498. ctx.controls["rewind"]->set_deactivated_callback
  499. (
  500. [&ctx = this->ctx, time_scale]()
  501. {
  502. game::world::set_time_scale(ctx, 0.0);
  503. }
  504. );
  505. // Setup pause control
  506. ctx.controls["pause"]->set_activated_callback
  507. (
  508. [this, &ctx = this->ctx]()
  509. {
  510. // Disable controls
  511. this->disable_controls();
  512. // Set resume callback
  513. ctx.resume_callback = [this, &ctx]()
  514. {
  515. this->enable_controls();
  516. ctx.resume_callback = nullptr;
  517. };
  518. // Push pause menu state
  519. ctx.state_machine.emplace(new game::state::pause_menu(ctx));
  520. }
  521. );
  522. }
  523. void nuptial_flight::disable_controls()
  524. {
  525. ctx.controls["move_forward"]->set_active_callback(nullptr);
  526. ctx.controls["move_back"]->set_active_callback(nullptr);
  527. ctx.controls["move_right"]->set_active_callback(nullptr);
  528. ctx.controls["move_left"]->set_active_callback(nullptr);
  529. ctx.controls["move_up"]->set_active_callback(nullptr);
  530. ctx.controls["move_down"]->set_active_callback(nullptr);
  531. ctx.controls["mouse_look"]->set_activated_callback(nullptr);
  532. ctx.controls["mouse_look"]->set_deactivated_callback(nullptr);
  533. ctx.controls["look_left_gamepad"]->set_active_callback(nullptr);
  534. ctx.controls["look_left_mouse"]->set_active_callback(nullptr);
  535. ctx.controls["look_right_gamepad"]->set_active_callback(nullptr);
  536. ctx.controls["look_right_mouse"]->set_active_callback(nullptr);
  537. ctx.controls["look_up_gamepad"]->set_active_callback(nullptr);
  538. ctx.controls["look_up_mouse"]->set_active_callback(nullptr);
  539. ctx.controls["look_down_gamepad"]->set_active_callback(nullptr);
  540. ctx.controls["look_down_mouse"]->set_active_callback(nullptr);
  541. ctx.controls["pause"]->set_activated_callback(nullptr);
  542. }
  543. } // namespace state
  544. } // namespace game