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

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