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

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