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

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