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

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