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

952 lines
33 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/locomotion.hpp"
  25. #include "entity/components/transform.hpp"
  26. #include "entity/components/terrain.hpp"
  27. #include "entity/components/camera.hpp"
  28. #include "entity/components/model.hpp"
  29. #include "entity/components/constraints/spring-to.hpp"
  30. #include "entity/components/constraints/three-dof.hpp"
  31. #include "entity/components/constraint-stack.hpp"
  32. #include "entity/commands.hpp"
  33. #include "animation/screen-transition.hpp"
  34. #include "animation/ease.hpp"
  35. #include "resources/resource-manager.hpp"
  36. #include "game/world.hpp"
  37. #include "application.hpp"
  38. #include "render/passes/clear-pass.hpp"
  39. #include "render/passes/ground-pass.hpp"
  40. #include "state-machine.hpp"
  41. #include "config.hpp"
  42. #include "game/load.hpp"
  43. #include "game/ant/breed.hpp"
  44. #include "game/ant/morphogenesis.hpp"
  45. using namespace game::ant;
  46. namespace game {
  47. namespace state {
  48. nuptial_flight::nuptial_flight(game::context& ctx):
  49. game::state::base(ctx)
  50. {
  51. ctx.logger->push_task("Entering nuptial flight state");
  52. // Allocate ant breed
  53. ant::breed breed;
  54. // Load morphological traits
  55. breed.head = ctx.resource_manager->load<ant::trait::head>("collared-harvester-head.dna");
  56. breed.mandibles = ctx.resource_manager->load<ant::trait::mandibles>("harvester-mandibles.dna");
  57. breed.antennae = ctx.resource_manager->load<ant::trait::antennae>("slender-antennae.dna");
  58. breed.eyes = ctx.resource_manager->load<ant::trait::eyes>("vestigial-eyes.dna");
  59. breed.mesosoma = ctx.resource_manager->load<ant::trait::mesosoma>("humpback-mesosoma.dna");
  60. breed.legs = ctx.resource_manager->load<ant::trait::legs>("trekking-legs.dna");
  61. breed.waist = ctx.resource_manager->load<ant::trait::waist>("harvester-waist.dna");
  62. breed.gaster = ctx.resource_manager->load<ant::trait::gaster>("ovoid-gaster.dna");
  63. breed.ocelli = ctx.resource_manager->load<ant::trait::ocelli>("absent-ocelli.dna");
  64. breed.sting = ctx.resource_manager->load<ant::trait::sting>("bullet-sting.dna");
  65. breed.sculpturing = ctx.resource_manager->load<ant::trait::sculpturing>("politus-sculpturing.dna");
  66. breed.pigmentation = ctx.resource_manager->load<ant::trait::pigmentation>("onyx-pigmentation.dna");
  67. breed.egg = ctx.resource_manager->load<ant::trait::egg>("ellipsoid-egg.dna");
  68. breed.larva = ctx.resource_manager->load<ant::trait::larva>("old-larva.dna");
  69. breed.cocoon = ctx.resource_manager->load<ant::trait::cocoon>("cocoon-present.dna");
  70. breed.pilosity = ctx.resource_manager->load<ant::trait::pilosity>("hairless-pilosity.dna");
  71. breed.forewings = nullptr;
  72. breed.hindwings = nullptr;
  73. // Load behavioral traits
  74. breed.foraging_time = ctx.resource_manager->load<ant::trait::foraging_time>("crepuscular-foraging-time.dna");
  75. breed.diet = nullptr;
  76. breed.nest = ctx.resource_manager->load<ant::trait::nest>("hypogeic-nest.dna");
  77. // Build caste models
  78. render::model* worker_model = ant::morphogenesis(breed, ant::caste::worker);
  79. // Disable UI color clear
  80. ctx.ui_clear_pass->set_cleared_buffers(false, true, false);
  81. // Create world if not yet created
  82. if (ctx.entities.find("planet") == ctx.entities.end())
  83. {
  84. game::world::create_stars(ctx);
  85. game::world::create_sun(ctx);
  86. game::world::create_planet(ctx);
  87. game::world::create_moon(ctx);
  88. // Set time to solar noon
  89. game::world::set_time(ctx, 0.3);
  90. // Freeze time
  91. game::world::set_time_scale(ctx, 0.0);
  92. }
  93. // Load biome
  94. game::load::biome(ctx, "desert-scrub.bio");
  95. // Setup and enable sky and ground passes
  96. ctx.sky_pass->set_enabled(true);
  97. ctx.ground_pass->set_enabled(true);
  98. // Create color checker
  99. {
  100. entity::archetype* color_checker_archetype = ctx.resource_manager->load<entity::archetype>("color-checker.ent");
  101. auto color_checker_eid = color_checker_archetype->create(*ctx.entity_registry);
  102. entity::command::warp_to(*ctx.entity_registry, color_checker_eid, {0, 0, -10});
  103. }
  104. // Create ruler
  105. {
  106. entity::archetype* ruler_10cm_archetype = ctx.resource_manager->load<entity::archetype>("ruler-10cm.ent");
  107. auto ruler_10cm_eid = ruler_10cm_archetype->create(*ctx.entity_registry);
  108. entity::command::warp_to(*ctx.entity_registry, ruler_10cm_eid, {0, 0, 10});
  109. }
  110. // Create ant_test
  111. {
  112. entity::archetype* ant_test_10cm_archetype = ctx.resource_manager->load<entity::archetype>("ant-test.ent");
  113. auto ant_test_eid = ant_test_10cm_archetype->create(*ctx.entity_registry);
  114. entity::command::warp_to(*ctx.entity_registry, ant_test_eid, {10, 0, 0});
  115. }
  116. // Create keeper if not yet created
  117. if (ctx.entities.find("keeper") == ctx.entities.end())
  118. {
  119. entity::id keeper_eid = ctx.entity_registry->create();
  120. ctx.entities["keeper"] = keeper_eid;
  121. }
  122. // Create ant if not created
  123. if (ctx.entities.find("ant") == ctx.entities.end())
  124. {
  125. auto boid_eid = ctx.entity_registry->create();
  126. entity::component::model model;
  127. model.render_model = ctx.resource_manager->load<render::model>("ant-test.mdl");
  128. model.instance_count = 0;
  129. model.layers = 1;
  130. ctx.entity_registry->assign<entity::component::model>(boid_eid, model);
  131. entity::component::transform transform;
  132. transform.local = math::identity_transform<float>;
  133. transform.world = math::identity_transform<float>;
  134. transform.warp = true;
  135. ctx.entity_registry->assign<entity::component::transform>(boid_eid, transform);
  136. entity::component::locomotion locomotion;
  137. locomotion.yaw = 0.0f;
  138. ctx.entity_registry->assign<entity::component::locomotion>(boid_eid, locomotion);
  139. // Set target ant
  140. ctx.entities["ant"] = boid_eid;
  141. }
  142. // Start as ant-keeper
  143. is_keeper = true;
  144. // Setup camera
  145. setup_camera();
  146. // Queue fade in
  147. ctx.fade_transition_color->set_value({1, 1, 1});
  148. 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));
  149. // Queue control setup
  150. ctx.function_queue.push(std::bind(&nuptial_flight::enable_keeper_controls, this));
  151. ctx.logger->pop_task(EXIT_SUCCESS);
  152. }
  153. nuptial_flight::~nuptial_flight()
  154. {
  155. ctx.logger->push_task("Exiting nuptial flight state");
  156. ctx.logger->pop_task(EXIT_SUCCESS);
  157. }
  158. void nuptial_flight::setup_camera()
  159. {
  160. // Switch to surface camera
  161. ctx.underground_camera->set_active(false);
  162. ctx.surface_camera->set_active(true);
  163. // Create surface camera entity
  164. if (!ctx.entities.count("surface_cam"))
  165. {
  166. // Create camera target entity
  167. entity::id target_eid = ctx.entity_registry->create();
  168. ctx.entities["surface_cam_target"] = target_eid;
  169. {
  170. // Transform
  171. entity::component::transform target_transform;
  172. target_transform.local = math::identity_transform<float>;
  173. target_transform.world = target_transform.local;
  174. target_transform.warp = true;
  175. ctx.entity_registry->assign<entity::component::transform>(target_eid, target_transform);
  176. }
  177. // Create camera entity
  178. entity::id camera_eid = ctx.entity_registry->create();
  179. ctx.entities["surface_cam"] = camera_eid;
  180. // Create camera transform component
  181. entity::component::transform transform;
  182. transform.local = math::identity_transform<float>;
  183. transform.world = transform.local;
  184. transform.warp = true;
  185. ctx.entity_registry->assign<entity::component::transform>(camera_eid, transform);
  186. // Create camera camera component
  187. entity::component::camera camera;
  188. camera.object = ctx.surface_camera;
  189. ctx.entity_registry->assign<entity::component::camera>(camera_eid, camera);
  190. // Create camera 3DOF constraint entity
  191. entity::id three_dof_constraint_eid = ctx.entity_registry->create();
  192. ctx.entities["surface_cam_3dof"] = three_dof_constraint_eid;
  193. {
  194. // Create 3DOF to constraint
  195. entity::component::constraint::three_dof three_dof;
  196. three_dof.yaw = 0.0f;
  197. three_dof.pitch = 0.0f;
  198. three_dof.roll = 0.0f;
  199. ctx.entity_registry->assign<entity::component::constraint::three_dof>(three_dof_constraint_eid, three_dof);
  200. // Create constraint stack node component
  201. entity::component::constraint_stack_node node;
  202. node.active = true;
  203. node.weight = 1.0f;
  204. node.next = entt::null;
  205. ctx.entity_registry->assign<entity::component::constraint_stack_node>(three_dof_constraint_eid, node);
  206. }
  207. // Create camera spring to constraint entity
  208. entity::id spring_constraint_eid = ctx.entity_registry->create();
  209. {
  210. // Create spring to constraint
  211. entity::component::constraint::spring_to spring;
  212. spring.target = target_eid;
  213. 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>};
  214. spring.translation.w = hz_to_rads(8.0f);
  215. spring.spring_translation = true;
  216. spring.spring_rotation = false;
  217. ctx.entity_registry->assign<entity::component::constraint::spring_to>(spring_constraint_eid, spring);
  218. // Create constraint stack node component
  219. entity::component::constraint_stack_node node;
  220. node.active = true;
  221. node.weight = 1.0f;
  222. node.next = three_dof_constraint_eid;
  223. ctx.entity_registry->assign<entity::component::constraint_stack_node>(spring_constraint_eid, node);
  224. }
  225. // Create camera constraint stack component
  226. entity::component::constraint_stack constraint_stack;
  227. constraint_stack.head = spring_constraint_eid;
  228. ctx.entity_registry->assign<entity::component::constraint_stack>(camera_eid, constraint_stack);
  229. }
  230. float ev100 = 13.5f;
  231. ctx.surface_camera->set_exposure(ev100);
  232. }
  233. void nuptial_flight::enable_keeper_controls()
  234. {
  235. // Get camera entities
  236. entity::id camera_eid = ctx.entities["surface_cam"];
  237. entity::id target_eid = ctx.entities["surface_cam_target"];
  238. entity::id three_dof_eid = ctx.entities["surface_cam_3dof"];
  239. const float min_elevation = 0.1f;
  240. const float max_elevation = 100.0f;
  241. const float slow_modifier = 0.25f;
  242. const float fast_modifier = 4.0f;
  243. const float dolly_speed = 5.0f;
  244. const float truck_speed = dolly_speed;
  245. const float pedestal_speed = 5.0f;
  246. float mouse_tilt_sensitivity = 1.0f;
  247. float mouse_pan_sensitivity = 1.0f;
  248. bool mouse_invert_tilt = false;
  249. bool mouse_invert_pan = false;
  250. float gamepad_tilt_sensitivity = 1.0f;
  251. float gamepad_pan_sensitivity = 1.0f;
  252. bool gamepad_invert_tilt = false;
  253. bool gamepad_invert_pan = false;
  254. bool mouse_look_toggle = false;
  255. ctx.mouse_look = false;
  256. const double time_scale = 5000.0;
  257. if (ctx.config->contains("mouse_tilt_sensitivity"))
  258. mouse_tilt_sensitivity = math::radians((*ctx.config)["mouse_tilt_sensitivity"].get<float>());
  259. if (ctx.config->contains("mouse_pan_sensitivity"))
  260. mouse_pan_sensitivity = math::radians((*ctx.config)["mouse_pan_sensitivity"].get<float>());
  261. if (ctx.config->contains("mouse_invert_tilt"))
  262. mouse_invert_tilt = math::radians((*ctx.config)["mouse_invert_tilt"].get<bool>());
  263. if (ctx.config->contains("mouse_invert_pan"))
  264. mouse_invert_pan = math::radians((*ctx.config)["mouse_invert_pan"].get<bool>());
  265. if (ctx.config->contains("mouse_look_toggle"))
  266. mouse_look_toggle = math::radians((*ctx.config)["mouse_look_toggle"].get<bool>());
  267. if (ctx.config->contains("gamepad_tilt_sensitivity"))
  268. gamepad_tilt_sensitivity = math::radians((*ctx.config)["gamepad_tilt_sensitivity"].get<float>());
  269. if (ctx.config->contains("gamepad_pan_sensitivity"))
  270. gamepad_pan_sensitivity = math::radians((*ctx.config)["gamepad_pan_sensitivity"].get<float>());
  271. if (ctx.config->contains("gamepad_invert_tilt"))
  272. gamepad_invert_tilt = math::radians((*ctx.config)["gamepad_invert_tilt"].get<bool>());
  273. if (ctx.config->contains("gamepad_invert_pan"))
  274. gamepad_invert_pan = math::radians((*ctx.config)["gamepad_invert_pan"].get<bool>());
  275. const input::control* move_slow = ctx.controls["move_slow"];
  276. const input::control* move_fast = ctx.controls["move_fast"];
  277. const input::control* mouse_look = ctx.controls["mouse_look"];
  278. float mouse_tilt_factor = mouse_tilt_sensitivity * (mouse_invert_tilt ? -1.0f : 1.0f);
  279. float mouse_pan_factor = mouse_pan_sensitivity * (mouse_invert_pan ? -1.0f : 1.0f);
  280. float gamepad_tilt_factor = gamepad_tilt_sensitivity * (gamepad_invert_tilt ? -1.0f : 1.0f);
  281. float gamepad_pan_factor = gamepad_pan_sensitivity * (gamepad_invert_pan ? -1.0f : 1.0f);
  282. ctx.controls["move_forward"]->set_active_callback
  283. (
  284. [&ctx = this->ctx, target_eid, three_dof_eid, dolly_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value)
  285. {
  286. if (move_slow->is_active())
  287. value *= slow_modifier;
  288. if (move_fast->is_active())
  289. value *= fast_modifier;
  290. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  291. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  292. const float3 movement = {0.0f, 0.0f, -dolly_speed * value * (1.0f / 60.0f)};
  293. entity::command::translate(*ctx.entity_registry, target_eid, yaw * movement);
  294. }
  295. );
  296. // Dolly backward
  297. ctx.controls["move_back"]->set_active_callback
  298. (
  299. [&ctx = this->ctx, target_eid, three_dof_eid, dolly_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value)
  300. {
  301. if (move_slow->is_active())
  302. value *= slow_modifier;
  303. if (move_fast->is_active())
  304. value *= fast_modifier;
  305. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  306. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  307. const float3 movement = {0.0f, 0.0f, dolly_speed * value * (1.0f / 60.0f)};
  308. entity::command::translate(*ctx.entity_registry, target_eid, yaw * movement);
  309. }
  310. );
  311. // Truck right
  312. ctx.controls["move_right"]->set_active_callback
  313. (
  314. [&ctx = this->ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value)
  315. {
  316. if (move_slow->is_active())
  317. value *= slow_modifier;
  318. if (move_fast->is_active())
  319. value *= fast_modifier;
  320. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  321. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  322. const float3 movement = {truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f};
  323. entity::command::translate(*ctx.entity_registry, target_eid, yaw * movement);
  324. }
  325. );
  326. // Truck left
  327. ctx.controls["move_left"]->set_active_callback
  328. (
  329. [&ctx = this->ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value)
  330. {
  331. if (move_slow->is_active())
  332. value *= slow_modifier;
  333. if (move_fast->is_active())
  334. value *= fast_modifier;
  335. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  336. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  337. const float3 movement = {-truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f};
  338. entity::command::translate(*ctx.entity_registry, target_eid, yaw * movement);
  339. }
  340. );
  341. // Pedestal up
  342. ctx.controls["move_up"]->set_active_callback
  343. (
  344. [&ctx = this->ctx, target_eid, pedestal_speed, move_slow, move_fast, slow_modifier, fast_modifier, max_elevation](float value)
  345. {
  346. if (move_slow->is_active())
  347. value *= slow_modifier;
  348. if (move_fast->is_active())
  349. value *= fast_modifier;
  350. float3 movement = {0.0f, pedestal_speed * value * (1.0f / 60.0f), 0.0f};
  351. auto transform = entity::command::get_world_transform(*ctx.entity_registry, target_eid);
  352. if (transform.translation.y + movement.y > max_elevation)
  353. movement.y = max_elevation - transform.translation.y;
  354. entity::command::translate(*ctx.entity_registry, target_eid, movement);
  355. }
  356. );
  357. // Pedestal down
  358. ctx.controls["move_down"]->set_active_callback
  359. (
  360. [&ctx = this->ctx, target_eid, pedestal_speed, move_slow, move_fast, slow_modifier, fast_modifier, min_elevation](float value)
  361. {
  362. if (move_slow->is_active())
  363. value *= slow_modifier;
  364. if (move_fast->is_active())
  365. value *= fast_modifier;
  366. float3 movement = {0.0f, -pedestal_speed * value * (1.0f / 60.0f), 0.0f};
  367. auto transform = entity::command::get_world_transform(*ctx.entity_registry, target_eid);
  368. if (transform.translation.y + movement.y < min_elevation)
  369. movement.y = min_elevation - transform.translation.y;
  370. entity::command::translate(*ctx.entity_registry, target_eid, movement);
  371. }
  372. );
  373. // Mouse rotate
  374. ctx.controls["mouse_look"]->set_activated_callback
  375. (
  376. [&ctx = this->ctx, mouse_look_toggle]()
  377. {
  378. if (mouse_look_toggle)
  379. ctx.mouse_look = !ctx.mouse_look;
  380. else
  381. ctx.mouse_look = true;
  382. ctx.app->set_relative_mouse_mode(ctx.mouse_look);
  383. }
  384. );
  385. ctx.controls["mouse_look"]->set_deactivated_callback
  386. (
  387. [&ctx = this->ctx, mouse_look_toggle]()
  388. {
  389. if (!mouse_look_toggle)
  390. {
  391. ctx.mouse_look = false;
  392. ctx.app->set_relative_mouse_mode(false);
  393. }
  394. }
  395. );
  396. // Pan left
  397. ctx.controls["look_left_gamepad"]->set_active_callback
  398. (
  399. [&ctx = this->ctx, three_dof_eid, gamepad_pan_factor](float value)
  400. {
  401. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  402. three_dof.yaw += gamepad_pan_factor * value * (1.0f / 60.0f);
  403. }
  404. );
  405. ctx.controls["look_left_mouse"]->set_active_callback
  406. (
  407. [&ctx = this->ctx, three_dof_eid, mouse_pan_factor](float value)
  408. {
  409. if (!ctx.mouse_look)
  410. return;
  411. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  412. three_dof.yaw += mouse_pan_factor * value * (1.0f / 60.0f);
  413. }
  414. );
  415. // Pan right
  416. ctx.controls["look_right_gamepad"]->set_active_callback
  417. (
  418. [&ctx = this->ctx, three_dof_eid, gamepad_pan_factor](float value)
  419. {
  420. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  421. three_dof.yaw -= gamepad_pan_factor * value * (1.0f / 60.0f);
  422. }
  423. );
  424. ctx.controls["look_right_mouse"]->set_active_callback
  425. (
  426. [&ctx = this->ctx, three_dof_eid, mouse_pan_factor](float value)
  427. {
  428. if (!ctx.mouse_look)
  429. return;
  430. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  431. three_dof.yaw -= mouse_pan_factor * value * (1.0f / 60.0f);
  432. }
  433. );
  434. // Tilt up
  435. ctx.controls["look_up_gamepad"]->set_active_callback
  436. (
  437. [&ctx = this->ctx, three_dof_eid, gamepad_tilt_factor](float value)
  438. {
  439. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  440. three_dof.pitch -= gamepad_tilt_factor * value * (1.0f / 60.0f);
  441. three_dof.pitch = std::max<float>(math::radians(-90.0f), three_dof.pitch);
  442. }
  443. );
  444. ctx.controls["look_up_mouse"]->set_active_callback
  445. (
  446. [&ctx = this->ctx, three_dof_eid, mouse_tilt_factor](float value)
  447. {
  448. if (!ctx.mouse_look)
  449. return;
  450. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  451. three_dof.pitch -= mouse_tilt_factor * value * (1.0f / 60.0f);
  452. three_dof.pitch = std::max<float>(math::radians(-90.0f), three_dof.pitch);
  453. }
  454. );
  455. // Tilt down
  456. ctx.controls["look_down_gamepad"]->set_active_callback
  457. (
  458. [&ctx = this->ctx, three_dof_eid, gamepad_tilt_factor](float value)
  459. {
  460. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  461. three_dof.pitch += gamepad_tilt_factor * value * (1.0f / 60.0f);
  462. three_dof.pitch = std::min<float>(math::radians(90.0f), three_dof.pitch);
  463. }
  464. );
  465. ctx.controls["look_down_mouse"]->set_active_callback
  466. (
  467. [&ctx = this->ctx, three_dof_eid, mouse_tilt_factor](float value)
  468. {
  469. if (!ctx.mouse_look)
  470. return;
  471. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  472. three_dof.pitch += mouse_tilt_factor * value * (1.0f / 60.0f);
  473. three_dof.pitch = std::min<float>(math::radians(90.0f), three_dof.pitch);
  474. }
  475. );
  476. // Setup switch POV control
  477. ctx.controls["switch_pov"]->set_activated_callback
  478. (
  479. [this]()
  480. {
  481. // Disable keeper controls
  482. this->disable_keeper_controls();
  483. // Switch to ant
  484. this->is_keeper = false;
  485. // Enable ant controls
  486. this->enable_ant_controls();
  487. }
  488. );
  489. // Fast-forward
  490. ctx.controls["fast_forward"]->set_activated_callback
  491. (
  492. [&ctx = this->ctx, time_scale]()
  493. {
  494. game::world::set_time_scale(ctx, time_scale);
  495. }
  496. );
  497. ctx.controls["fast_forward"]->set_deactivated_callback
  498. (
  499. [&ctx = this->ctx, time_scale]()
  500. {
  501. game::world::set_time_scale(ctx, 0.0);
  502. }
  503. );
  504. ctx.controls["rewind"]->set_activated_callback
  505. (
  506. [&ctx = this->ctx, time_scale]()
  507. {
  508. game::world::set_time_scale(ctx, -time_scale);
  509. }
  510. );
  511. ctx.controls["rewind"]->set_deactivated_callback
  512. (
  513. [&ctx = this->ctx, time_scale]()
  514. {
  515. game::world::set_time_scale(ctx, 0.0);
  516. }
  517. );
  518. // Setup pause control
  519. ctx.controls["pause"]->set_activated_callback
  520. (
  521. [this, &ctx = this->ctx]()
  522. {
  523. // Disable controls
  524. this->disable_controls();
  525. // Set resume callback
  526. ctx.resume_callback = [this, &ctx]()
  527. {
  528. this->enable_controls();
  529. ctx.resume_callback = nullptr;
  530. };
  531. // Push pause menu state
  532. ctx.state_machine.emplace(new game::state::pause_menu(ctx));
  533. }
  534. );
  535. }
  536. void nuptial_flight::disable_keeper_controls()
  537. {
  538. ctx.controls["move_forward"]->set_active_callback(nullptr);
  539. ctx.controls["move_back"]->set_active_callback(nullptr);
  540. ctx.controls["move_right"]->set_active_callback(nullptr);
  541. ctx.controls["move_left"]->set_active_callback(nullptr);
  542. ctx.controls["move_up"]->set_active_callback(nullptr);
  543. ctx.controls["move_down"]->set_active_callback(nullptr);
  544. ctx.controls["mouse_look"]->set_activated_callback(nullptr);
  545. ctx.controls["mouse_look"]->set_deactivated_callback(nullptr);
  546. ctx.controls["look_left_gamepad"]->set_active_callback(nullptr);
  547. ctx.controls["look_left_mouse"]->set_active_callback(nullptr);
  548. ctx.controls["look_right_gamepad"]->set_active_callback(nullptr);
  549. ctx.controls["look_right_mouse"]->set_active_callback(nullptr);
  550. ctx.controls["look_up_gamepad"]->set_active_callback(nullptr);
  551. ctx.controls["look_up_mouse"]->set_active_callback(nullptr);
  552. ctx.controls["look_down_gamepad"]->set_active_callback(nullptr);
  553. ctx.controls["look_down_mouse"]->set_active_callback(nullptr);
  554. ctx.controls["switch_pov"]->set_activated_callback(nullptr);
  555. ctx.controls["fast_forward"]->set_activated_callback(nullptr);
  556. ctx.controls["rewind"]->set_activated_callback(nullptr);
  557. ctx.controls["pause"]->set_activated_callback(nullptr);
  558. }
  559. void nuptial_flight::enable_ant_controls()
  560. {
  561. // Get ant controller entities
  562. entity::id ant_eid = ctx.entities["ant"];
  563. const float move_forward_speed = 5.0f;
  564. const float move_back_speed = move_forward_speed * 0.5f;
  565. const float strafe_speed = move_forward_speed * 0.5f;
  566. const float turn_speed = math::radians(270.0f);
  567. const float slow_modifier = 0.5f;
  568. const float fast_modifier = 2.0f;
  569. float mouse_tilt_sensitivity = 1.0f;
  570. float mouse_pan_sensitivity = 1.0f;
  571. bool mouse_invert_tilt = false;
  572. bool mouse_invert_pan = false;
  573. float gamepad_tilt_sensitivity = 1.0f;
  574. float gamepad_pan_sensitivity = 1.0f;
  575. bool gamepad_invert_tilt = false;
  576. bool gamepad_invert_pan = false;
  577. const double time_scale = 5000.0;
  578. if (ctx.config->contains("mouse_tilt_sensitivity"))
  579. mouse_tilt_sensitivity = math::radians((*ctx.config)["mouse_tilt_sensitivity"].get<float>());
  580. if (ctx.config->contains("mouse_pan_sensitivity"))
  581. mouse_pan_sensitivity = math::radians((*ctx.config)["mouse_pan_sensitivity"].get<float>());
  582. if (ctx.config->contains("mouse_invert_tilt"))
  583. mouse_invert_tilt = math::radians((*ctx.config)["mouse_invert_tilt"].get<bool>());
  584. if (ctx.config->contains("mouse_invert_pan"))
  585. mouse_invert_pan = math::radians((*ctx.config)["mouse_invert_pan"].get<bool>());
  586. if (ctx.config->contains("gamepad_tilt_sensitivity"))
  587. gamepad_tilt_sensitivity = math::radians((*ctx.config)["gamepad_tilt_sensitivity"].get<float>());
  588. if (ctx.config->contains("gamepad_pan_sensitivity"))
  589. gamepad_pan_sensitivity = math::radians((*ctx.config)["gamepad_pan_sensitivity"].get<float>());
  590. if (ctx.config->contains("gamepad_invert_tilt"))
  591. gamepad_invert_tilt = math::radians((*ctx.config)["gamepad_invert_tilt"].get<bool>());
  592. if (ctx.config->contains("gamepad_invert_pan"))
  593. gamepad_invert_pan = math::radians((*ctx.config)["gamepad_invert_pan"].get<bool>());
  594. const input::control* move_slow = ctx.controls["move_slow"];
  595. const input::control* move_fast = ctx.controls["move_fast"];
  596. const input::control* mouse_look = ctx.controls["mouse_look"];
  597. float mouse_tilt_factor = mouse_tilt_sensitivity * (mouse_invert_tilt ? -1.0f : 1.0f);
  598. float mouse_pan_factor = mouse_pan_sensitivity * (mouse_invert_pan ? -1.0f : 1.0f);
  599. float gamepad_tilt_factor = gamepad_tilt_sensitivity * (gamepad_invert_tilt ? -1.0f : 1.0f);
  600. float gamepad_pan_factor = gamepad_pan_sensitivity * (gamepad_invert_pan ? -1.0f : 1.0f);
  601. // Move forward
  602. ctx.controls["move_forward"]->set_active_callback
  603. (
  604. [&ctx = this->ctx, ant_eid, move_forward_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value)
  605. {
  606. if (move_slow->is_active())
  607. value *= slow_modifier;
  608. if (move_fast->is_active())
  609. value *= fast_modifier;
  610. auto& locomotion = ctx.entity_registry->get<entity::component::locomotion>(ant_eid);
  611. const math::quaternion<float> yaw = math::angle_axis(locomotion.yaw, {0.0f, 1.0f, 0.0f});
  612. const float3 movement = {0.0f, 0.0f, move_forward_speed * value * (1.0f / 60.0f)};
  613. entity::command::translate(*ctx.entity_registry, ant_eid, yaw * movement);
  614. }
  615. );
  616. // Move back
  617. ctx.controls["move_back"]->set_active_callback
  618. (
  619. [&ctx = this->ctx, ant_eid, move_back_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value)
  620. {
  621. if (move_slow->is_active())
  622. value *= slow_modifier;
  623. if (move_fast->is_active())
  624. value *= fast_modifier;
  625. auto& locomotion = ctx.entity_registry->get<entity::component::locomotion>(ant_eid);
  626. const math::quaternion<float> yaw = math::angle_axis(locomotion.yaw, {0.0f, 1.0f, 0.0f});
  627. const float3 movement = {0.0f, 0.0f, -move_back_speed * value * (1.0f / 60.0f)};
  628. entity::command::translate(*ctx.entity_registry, ant_eid, yaw * movement);
  629. }
  630. );
  631. // Turn right
  632. ctx.controls["move_right"]->set_active_callback
  633. (
  634. [&ctx = this->ctx, ant_eid, turn_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value)
  635. {
  636. if (move_slow->is_active())
  637. value *= slow_modifier;
  638. if (move_fast->is_active())
  639. value *= fast_modifier;
  640. auto& locomotion = ctx.entity_registry->get<entity::component::locomotion>(ant_eid);
  641. float delta_yaw = -turn_speed * value * (1.0f / 60.0f);
  642. locomotion.yaw += delta_yaw;
  643. entity::command::rotate(*ctx.entity_registry, ant_eid, delta_yaw, {0.0f, 1.0f, 0.0f});
  644. }
  645. );
  646. // Truck left
  647. ctx.controls["move_left"]->set_active_callback
  648. (
  649. [&ctx = this->ctx, ant_eid, turn_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value)
  650. {
  651. if (move_slow->is_active())
  652. value *= slow_modifier;
  653. if (move_fast->is_active())
  654. value *= fast_modifier;
  655. auto& locomotion = ctx.entity_registry->get<entity::component::locomotion>(ant_eid);
  656. float delta_yaw = turn_speed * value * (1.0f / 60.0f);
  657. locomotion.yaw += delta_yaw;
  658. entity::command::rotate(*ctx.entity_registry, ant_eid, delta_yaw, {0.0f, 1.0f, 0.0f});
  659. }
  660. );
  661. // Pan left
  662. /*
  663. ctx.controls["look_left_gamepad"]->set_active_callback
  664. (
  665. [&ctx = this->ctx, three_dof_eid, gamepad_pan_factor](float value)
  666. {
  667. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  668. three_dof.yaw += gamepad_pan_factor * value * (1.0f / 60.0f);
  669. }
  670. );
  671. ctx.controls["look_left_mouse"]->set_active_callback
  672. (
  673. [&ctx = this->ctx, three_dof_eid, mouse_pan_factor](float value)
  674. {
  675. if (!ctx.mouse_look)
  676. return;
  677. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  678. three_dof.yaw += mouse_pan_factor * value * (1.0f / 60.0f);
  679. }
  680. );
  681. // Pan right
  682. ctx.controls["look_right_gamepad"]->set_active_callback
  683. (
  684. [&ctx = this->ctx, three_dof_eid, gamepad_pan_factor](float value)
  685. {
  686. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  687. three_dof.yaw -= gamepad_pan_factor * value * (1.0f / 60.0f);
  688. }
  689. );
  690. ctx.controls["look_right_mouse"]->set_active_callback
  691. (
  692. [&ctx = this->ctx, three_dof_eid, mouse_pan_factor](float value)
  693. {
  694. if (!ctx.mouse_look)
  695. return;
  696. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  697. three_dof.yaw -= mouse_pan_factor * value * (1.0f / 60.0f);
  698. }
  699. );
  700. // Tilt up
  701. ctx.controls["look_up_gamepad"]->set_active_callback
  702. (
  703. [&ctx = this->ctx, three_dof_eid, gamepad_tilt_factor](float value)
  704. {
  705. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  706. three_dof.pitch -= gamepad_tilt_factor * value * (1.0f / 60.0f);
  707. three_dof.pitch = std::max<float>(math::radians(-90.0f), three_dof.pitch);
  708. }
  709. );
  710. ctx.controls["look_up_mouse"]->set_active_callback
  711. (
  712. [&ctx = this->ctx, three_dof_eid, mouse_tilt_factor](float value)
  713. {
  714. if (!ctx.mouse_look)
  715. return;
  716. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  717. three_dof.pitch -= mouse_tilt_factor * value * (1.0f / 60.0f);
  718. three_dof.pitch = std::max<float>(math::radians(-90.0f), three_dof.pitch);
  719. }
  720. );
  721. // Tilt down
  722. ctx.controls["look_down_gamepad"]->set_active_callback
  723. (
  724. [&ctx = this->ctx, three_dof_eid, gamepad_tilt_factor](float value)
  725. {
  726. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  727. three_dof.pitch += gamepad_tilt_factor * value * (1.0f / 60.0f);
  728. three_dof.pitch = std::min<float>(math::radians(90.0f), three_dof.pitch);
  729. }
  730. );
  731. ctx.controls["look_down_mouse"]->set_active_callback
  732. (
  733. [&ctx = this->ctx, three_dof_eid, mouse_tilt_factor](float value)
  734. {
  735. if (!ctx.mouse_look)
  736. return;
  737. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  738. three_dof.pitch += mouse_tilt_factor * value * (1.0f / 60.0f);
  739. three_dof.pitch = std::min<float>(math::radians(90.0f), three_dof.pitch);
  740. }
  741. );
  742. */
  743. // Setup switch POV control
  744. ctx.controls["switch_pov"]->set_activated_callback
  745. (
  746. [this]()
  747. {
  748. // Disable ant controls
  749. this->disable_ant_controls();
  750. // Switch to keeper
  751. this->is_keeper = true;
  752. // Enable keeper controls
  753. this->enable_keeper_controls();
  754. }
  755. );
  756. // Fast-forward
  757. ctx.controls["fast_forward"]->set_activated_callback
  758. (
  759. [&ctx = this->ctx, time_scale]()
  760. {
  761. game::world::set_time_scale(ctx, time_scale);
  762. }
  763. );
  764. ctx.controls["fast_forward"]->set_deactivated_callback
  765. (
  766. [&ctx = this->ctx, time_scale]()
  767. {
  768. game::world::set_time_scale(ctx, 0.0);
  769. }
  770. );
  771. ctx.controls["rewind"]->set_activated_callback
  772. (
  773. [&ctx = this->ctx, time_scale]()
  774. {
  775. game::world::set_time_scale(ctx, -time_scale);
  776. }
  777. );
  778. ctx.controls["rewind"]->set_deactivated_callback
  779. (
  780. [&ctx = this->ctx, time_scale]()
  781. {
  782. game::world::set_time_scale(ctx, 0.0);
  783. }
  784. );
  785. // Setup pause control
  786. ctx.controls["pause"]->set_activated_callback
  787. (
  788. [this, &ctx = this->ctx]()
  789. {
  790. // Disable controls
  791. this->disable_controls();
  792. // Set resume callback
  793. ctx.resume_callback = [this, &ctx]()
  794. {
  795. this->enable_controls();
  796. ctx.resume_callback = nullptr;
  797. };
  798. // Push pause menu state
  799. ctx.state_machine.emplace(new game::state::pause_menu(ctx));
  800. }
  801. );
  802. }
  803. void nuptial_flight::disable_ant_controls()
  804. {
  805. ctx.controls["move_forward"]->set_active_callback(nullptr);
  806. ctx.controls["move_back"]->set_active_callback(nullptr);
  807. ctx.controls["move_right"]->set_active_callback(nullptr);
  808. ctx.controls["move_left"]->set_active_callback(nullptr);
  809. ctx.controls["look_left_gamepad"]->set_active_callback(nullptr);
  810. ctx.controls["look_left_mouse"]->set_active_callback(nullptr);
  811. ctx.controls["look_right_gamepad"]->set_active_callback(nullptr);
  812. ctx.controls["look_right_mouse"]->set_active_callback(nullptr);
  813. ctx.controls["look_up_gamepad"]->set_active_callback(nullptr);
  814. ctx.controls["look_up_mouse"]->set_active_callback(nullptr);
  815. ctx.controls["look_down_gamepad"]->set_active_callback(nullptr);
  816. ctx.controls["look_down_mouse"]->set_active_callback(nullptr);
  817. ctx.controls["switch_pov"]->set_activated_callback(nullptr);
  818. ctx.controls["fast_forward"]->set_activated_callback(nullptr);
  819. ctx.controls["rewind"]->set_activated_callback(nullptr);
  820. ctx.controls["pause"]->set_activated_callback(nullptr);
  821. }
  822. void nuptial_flight::enable_controls()
  823. {
  824. if (is_keeper)
  825. enable_keeper_controls();
  826. else
  827. enable_ant_controls();
  828. }
  829. void nuptial_flight::disable_controls()
  830. {
  831. if (is_keeper)
  832. disable_keeper_controls();
  833. else
  834. disable_ant_controls();
  835. }
  836. } // namespace state
  837. } // namespace game