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

544 lines
18 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/astronomy.hpp"
  23. #include "entity/systems/orbit.hpp"
  24. #include "entity/systems/camera.hpp"
  25. #include "entity/components/observer.hpp"
  26. #include "entity/components/transform.hpp"
  27. #include "entity/components/terrain.hpp"
  28. #include "entity/components/camera.hpp"
  29. #include "entity/components/constraints/spring-to.hpp"
  30. #include "entity/components/constraints/three-dof.hpp"
  31. #include "entity/components/constraint-stack.hpp"
  32. #include "entity/commands.hpp"
  33. #include "animation/screen-transition.hpp"
  34. #include "animation/ease.hpp"
  35. #include "resources/resource-manager.hpp"
  36. #include "game/world.hpp"
  37. #include "application.hpp"
  38. #include "render/passes/clear-pass.hpp"
  39. #include <memory>
  40. #include <iostream>
  41. #include "state-machine.hpp"
  42. namespace game {
  43. namespace state {
  44. nuptial_flight::nuptial_flight(game::context& ctx):
  45. game::state::base(ctx)
  46. {
  47. ctx.logger->push_task("Entering nuptial flight state");
  48. // Disable UI color clear
  49. ctx.ui_clear_pass->set_cleared_buffers(false, true, false);
  50. // Create world
  51. game::world::create_stars(ctx);
  52. game::world::create_sun(ctx);
  53. game::world::create_planet(ctx);
  54. game::world::create_moon(ctx);
  55. // Set time to solar noon
  56. game::world::set_time(ctx, 0.0);
  57. // Freeze time
  58. game::world::set_time_scale(ctx, 0.0);
  59. // Switch to surface camera
  60. ctx.underground_camera->set_active(false);
  61. ctx.surface_camera->set_active(true);
  62. // Find planet EID by name
  63. entity::id planet_eid = ctx.entities["planet"];
  64. // Remove terrain component from planet (if any)
  65. //if (ctx.entity_registry->has<entity::component::terrain>(planet_eid))
  66. // ctx.entity_registry->remove<entity::component::terrain>(planet_eid);
  67. // Enable clouds in sky pass
  68. //ctx.surface_sky_pass->set_clouds_model(ctx.resource_manager->load<render::model>("cloud-plane.mdl"));
  69. // Create observer
  70. entity::id observer_eid = ctx.entity_registry->create();
  71. {
  72. entity::component::observer observer;
  73. observer.reference_body_eid = planet_eid;
  74. observer.elevation = 2000.0;
  75. observer.latitude = 0.0;
  76. observer.longitude = 0.0;
  77. observer.camera = ctx.surface_camera;
  78. ctx.entity_registry->assign<entity::component::observer>(observer_eid, observer);
  79. // Set reference location of astronomy system
  80. ctx.astronomy_system->set_reference_body(planet_eid);
  81. ctx.astronomy_system->set_observer_location(double3{observer.elevation, observer.latitude, observer.longitude});
  82. }
  83. // Setup camera
  84. setup_camera();
  85. /*
  86. ctx.surface_camera->look_at({0, 0, 1}, {0, 0, 0}, {0, 1, 0});
  87. ctx.surface_camera->set_exposure(-14.5f);
  88. ctx.surface_scene->update_tweens();
  89. */
  90. // Queue fade in
  91. ctx.fade_transition_color->set_value({1, 1, 1});
  92. ctx.function_queue.push(std::bind(&screen_transition::transition, ctx.fade_transition, 5.0f, true, math::lerp<float, float>, true));
  93. // Queue control setup
  94. ctx.function_queue.push(std::bind(&nuptial_flight::enable_controls, this));
  95. ctx.logger->pop_task(EXIT_SUCCESS);
  96. }
  97. nuptial_flight::~nuptial_flight()
  98. {
  99. ctx.logger->push_task("Exiting nuptial flight state");
  100. // Resume time
  101. //const double time_scale = (*ctx.config)["time_scale"].get<double>();
  102. //game::world::set_time_scale(ctx, time_scale);
  103. ctx.logger->pop_task(EXIT_SUCCESS);
  104. }
  105. void nuptial_flight::setup_camera()
  106. {
  107. // Switch to surface camera
  108. ctx.underground_camera->set_active(false);
  109. ctx.surface_camera->set_active(true);
  110. // Create surface camera entity
  111. if (!ctx.entities.count("surface_cam"))
  112. {
  113. // Create camera target entity
  114. entity::id target_eid = ctx.entity_registry->create();
  115. ctx.entities["surface_cam_target"] = target_eid;
  116. {
  117. // Transform
  118. entity::component::transform target_transform;
  119. target_transform.local = math::identity_transform<float>;
  120. target_transform.world = target_transform.local;
  121. target_transform.warp = true;
  122. ctx.entity_registry->assign<entity::component::transform>(target_eid, target_transform);
  123. }
  124. // Create camera entity
  125. entity::id camera_eid = ctx.entity_registry->create();
  126. ctx.entities["surface_cam"] = camera_eid;
  127. // Create camera transform component
  128. entity::component::transform transform;
  129. transform.local = math::identity_transform<float>;
  130. transform.world = transform.local;
  131. transform.warp = true;
  132. ctx.entity_registry->assign<entity::component::transform>(camera_eid, transform);
  133. // Create camera camera component
  134. entity::component::camera camera;
  135. camera.object = ctx.surface_camera;
  136. ctx.entity_registry->assign<entity::component::camera>(camera_eid, camera);
  137. // Create camera 3DOF constraint entity
  138. entity::id three_dof_constraint_eid = ctx.entity_registry->create();
  139. ctx.entities["surface_cam_3dof"] = three_dof_constraint_eid;
  140. {
  141. // Create 3DOF to constraint
  142. entity::component::constraint::three_dof three_dof;
  143. three_dof.yaw = 0.0f;
  144. three_dof.pitch = 0.0f;
  145. three_dof.roll = 0.0f;
  146. ctx.entity_registry->assign<entity::component::constraint::three_dof>(three_dof_constraint_eid, three_dof);
  147. // Create constraint stack node component
  148. entity::component::constraint_stack_node node;
  149. node.active = true;
  150. node.weight = 1.0f;
  151. node.next = entt::null;
  152. ctx.entity_registry->assign<entity::component::constraint_stack_node>(three_dof_constraint_eid, node);
  153. }
  154. // Create camera spring to constraint entity
  155. entity::id spring_constraint_eid = ctx.entity_registry->create();
  156. {
  157. // Create spring to constraint
  158. entity::component::constraint::spring_to spring;
  159. spring.target = target_eid;
  160. 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>};
  161. spring.translation.w = hz_to_rads(8.0f);
  162. spring.spring_translation = true;
  163. spring.spring_rotation = false;
  164. ctx.entity_registry->assign<entity::component::constraint::spring_to>(spring_constraint_eid, spring);
  165. // Create constraint stack node component
  166. entity::component::constraint_stack_node node;
  167. node.active = true;
  168. node.weight = 1.0f;
  169. node.next = three_dof_constraint_eid;
  170. ctx.entity_registry->assign<entity::component::constraint_stack_node>(spring_constraint_eid, node);
  171. }
  172. // Create camera constraint stack component
  173. entity::component::constraint_stack constraint_stack;
  174. constraint_stack.head = spring_constraint_eid;
  175. ctx.entity_registry->assign<entity::component::constraint_stack>(camera_eid, constraint_stack);
  176. }
  177. ctx.surface_camera->set_exposure(-12.0f);
  178. }
  179. void nuptial_flight::enable_controls()
  180. {
  181. // Get camera entities
  182. entity::id camera_eid = ctx.entities["surface_cam"];
  183. entity::id target_eid = ctx.entities["surface_cam_target"];
  184. entity::id three_dof_eid = ctx.entities["surface_cam_3dof"];
  185. const float slow_modifier = 0.25f;
  186. const float fast_modifier = 4.0f;
  187. const float dolly_speed = 20.0f;
  188. const float truck_speed = dolly_speed;
  189. const float pedestal_speed = 30.0f;
  190. float mouse_tilt_sensitivity = 1.0f;
  191. float mouse_pan_sensitivity = 1.0f;
  192. bool mouse_invert_tilt = false;
  193. bool mouse_invert_pan = false;
  194. float gamepad_tilt_sensitivity = 1.0f;
  195. float gamepad_pan_sensitivity = 1.0f;
  196. bool gamepad_invert_tilt = false;
  197. bool gamepad_invert_pan = false;
  198. bool mouse_look_toggle = false;
  199. ctx.mouse_look = false;
  200. if (ctx.config->contains("mouse_tilt_sensitivity"))
  201. mouse_tilt_sensitivity = math::radians((*ctx.config)["mouse_tilt_sensitivity"].get<float>());
  202. if (ctx.config->contains("mouse_pan_sensitivity"))
  203. mouse_pan_sensitivity = math::radians((*ctx.config)["mouse_pan_sensitivity"].get<float>());
  204. if (ctx.config->contains("mouse_invert_tilt"))
  205. mouse_invert_tilt = math::radians((*ctx.config)["mouse_invert_tilt"].get<bool>());
  206. if (ctx.config->contains("mouse_invert_pan"))
  207. mouse_invert_pan = math::radians((*ctx.config)["mouse_invert_pan"].get<bool>());
  208. if (ctx.config->contains("mouse_look_toggle"))
  209. mouse_look_toggle = math::radians((*ctx.config)["mouse_look_toggle"].get<bool>());
  210. if (ctx.config->contains("gamepad_tilt_sensitivity"))
  211. gamepad_tilt_sensitivity = math::radians((*ctx.config)["gamepad_tilt_sensitivity"].get<float>());
  212. if (ctx.config->contains("gamepad_pan_sensitivity"))
  213. gamepad_pan_sensitivity = math::radians((*ctx.config)["gamepad_pan_sensitivity"].get<float>());
  214. if (ctx.config->contains("gamepad_invert_tilt"))
  215. gamepad_invert_tilt = math::radians((*ctx.config)["gamepad_invert_tilt"].get<bool>());
  216. if (ctx.config->contains("gamepad_invert_pan"))
  217. gamepad_invert_pan = math::radians((*ctx.config)["gamepad_invert_pan"].get<bool>());
  218. const input::control* move_slow = ctx.controls["move_slow"];
  219. const input::control* move_fast = ctx.controls["move_fast"];
  220. const input::control* mouse_look = ctx.controls["mouse_look"];
  221. float mouse_tilt_factor = mouse_tilt_sensitivity * (mouse_invert_tilt ? -1.0f : 1.0f);
  222. float mouse_pan_factor = mouse_pan_sensitivity * (mouse_invert_pan ? -1.0f : 1.0f);
  223. float gamepad_tilt_factor = gamepad_tilt_sensitivity * (gamepad_invert_tilt ? -1.0f : 1.0f);
  224. float gamepad_pan_factor = gamepad_pan_sensitivity * (gamepad_invert_pan ? -1.0f : 1.0f);
  225. ctx.controls["move_forward"]->set_active_callback
  226. (
  227. [&ctx = this->ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value)
  228. {
  229. if (move_slow->is_active())
  230. value *= slow_modifier;
  231. if (move_fast->is_active())
  232. value *= fast_modifier;
  233. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  234. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  235. const float3 movement = {0.0f, 0.0f, -truck_speed * value * (1.0f / 60.0f)};
  236. entity::command::translate(*ctx.entity_registry, target_eid, yaw * movement);
  237. }
  238. );
  239. // Dolly backward
  240. ctx.controls["move_back"]->set_active_callback
  241. (
  242. [&ctx = this->ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value)
  243. {
  244. if (move_slow->is_active())
  245. value *= slow_modifier;
  246. if (move_fast->is_active())
  247. value *= fast_modifier;
  248. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  249. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  250. const float3 movement = {0.0f, 0.0f, truck_speed * value * (1.0f / 60.0f)};
  251. entity::command::translate(*ctx.entity_registry, target_eid, yaw * movement);
  252. }
  253. );
  254. // Truck right
  255. ctx.controls["move_right"]->set_active_callback
  256. (
  257. [&ctx = this->ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value)
  258. {
  259. if (move_slow->is_active())
  260. value *= slow_modifier;
  261. if (move_fast->is_active())
  262. value *= fast_modifier;
  263. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  264. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  265. const float3 movement = {truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f};
  266. entity::command::translate(*ctx.entity_registry, target_eid, yaw * movement);
  267. }
  268. );
  269. // Truck left
  270. ctx.controls["move_left"]->set_active_callback
  271. (
  272. [&ctx = this->ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value)
  273. {
  274. if (move_slow->is_active())
  275. value *= slow_modifier;
  276. if (move_fast->is_active())
  277. value *= fast_modifier;
  278. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  279. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  280. const float3 movement = {-truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f};
  281. entity::command::translate(*ctx.entity_registry, target_eid, yaw * movement);
  282. }
  283. );
  284. // Pedestal up
  285. ctx.controls["move_up"]->set_active_callback
  286. (
  287. [&ctx = this->ctx, target_eid, pedestal_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value)
  288. {
  289. if (move_slow->is_active())
  290. value *= slow_modifier;
  291. if (move_fast->is_active())
  292. value *= fast_modifier;
  293. const float3 movement = {0.0f, pedestal_speed * value * (1.0f / 60.0f), 0.0f};
  294. entity::command::translate(*ctx.entity_registry, target_eid, movement);
  295. }
  296. );
  297. // Pedestal down
  298. ctx.controls["move_down"]->set_active_callback
  299. (
  300. [&ctx = this->ctx, target_eid, pedestal_speed, move_slow, move_fast, slow_modifier, fast_modifier](float value)
  301. {
  302. if (move_slow->is_active())
  303. value *= slow_modifier;
  304. if (move_fast->is_active())
  305. value *= fast_modifier;
  306. const float3 movement = {0.0f, -pedestal_speed * value * (1.0f / 60.0f), 0.0f};
  307. entity::command::translate(*ctx.entity_registry, target_eid, movement);
  308. }
  309. );
  310. // Mouse rotate
  311. ctx.controls["mouse_look"]->set_activated_callback
  312. (
  313. [&ctx = this->ctx, mouse_look_toggle]()
  314. {
  315. if (mouse_look_toggle)
  316. ctx.mouse_look = !ctx.mouse_look;
  317. else
  318. ctx.mouse_look = true;
  319. ctx.app->set_relative_mouse_mode(ctx.mouse_look);
  320. }
  321. );
  322. ctx.controls["mouse_look"]->set_deactivated_callback
  323. (
  324. [&ctx = this->ctx, mouse_look_toggle]()
  325. {
  326. if (!mouse_look_toggle)
  327. {
  328. ctx.mouse_look = false;
  329. ctx.app->set_relative_mouse_mode(false);
  330. }
  331. }
  332. );
  333. // Pan left
  334. ctx.controls["look_left_gamepad"]->set_active_callback
  335. (
  336. [&ctx = this->ctx, three_dof_eid, gamepad_pan_factor](float value)
  337. {
  338. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  339. three_dof.yaw += gamepad_pan_factor * value * (1.0f / 60.0f);
  340. }
  341. );
  342. ctx.controls["look_left_mouse"]->set_active_callback
  343. (
  344. [&ctx = this->ctx, three_dof_eid, mouse_pan_factor](float value)
  345. {
  346. if (!ctx.mouse_look)
  347. return;
  348. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  349. three_dof.yaw += mouse_pan_factor * value * (1.0f / 60.0f);
  350. }
  351. );
  352. // Pan right
  353. ctx.controls["look_right_gamepad"]->set_active_callback
  354. (
  355. [&ctx = this->ctx, three_dof_eid, gamepad_pan_factor](float value)
  356. {
  357. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  358. three_dof.yaw -= gamepad_pan_factor * value * (1.0f / 60.0f);
  359. }
  360. );
  361. ctx.controls["look_right_mouse"]->set_active_callback
  362. (
  363. [&ctx = this->ctx, three_dof_eid, mouse_pan_factor](float value)
  364. {
  365. if (!ctx.mouse_look)
  366. return;
  367. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  368. three_dof.yaw -= mouse_pan_factor * value * (1.0f / 60.0f);
  369. }
  370. );
  371. // Tilt up
  372. ctx.controls["look_up_gamepad"]->set_active_callback
  373. (
  374. [&ctx = this->ctx, three_dof_eid, gamepad_tilt_factor](float value)
  375. {
  376. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  377. three_dof.pitch -= gamepad_tilt_factor * value * (1.0f / 60.0f);
  378. three_dof.pitch = std::max<float>(math::radians(-90.0f), three_dof.pitch);
  379. }
  380. );
  381. ctx.controls["look_up_mouse"]->set_active_callback
  382. (
  383. [&ctx = this->ctx, three_dof_eid, mouse_tilt_factor](float value)
  384. {
  385. if (!ctx.mouse_look)
  386. return;
  387. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  388. three_dof.pitch -= mouse_tilt_factor * value * (1.0f / 60.0f);
  389. three_dof.pitch = std::max<float>(math::radians(-90.0f), three_dof.pitch);
  390. }
  391. );
  392. // Tilt down
  393. ctx.controls["look_down_gamepad"]->set_active_callback
  394. (
  395. [&ctx = this->ctx, three_dof_eid, gamepad_tilt_factor](float value)
  396. {
  397. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  398. three_dof.pitch += gamepad_tilt_factor * value * (1.0f / 60.0f);
  399. three_dof.pitch = std::min<float>(math::radians(90.0f), three_dof.pitch);
  400. }
  401. );
  402. ctx.controls["look_down_mouse"]->set_active_callback
  403. (
  404. [&ctx = this->ctx, three_dof_eid, mouse_tilt_factor](float value)
  405. {
  406. if (!ctx.mouse_look)
  407. return;
  408. auto& three_dof = ctx.entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  409. three_dof.pitch += mouse_tilt_factor * value * (1.0f / 60.0f);
  410. three_dof.pitch = std::min<float>(math::radians(90.0f), three_dof.pitch);
  411. }
  412. );
  413. /*
  414. // Use tool
  415. ctx.controls["use_tool"]->set_activated_callback
  416. (
  417. [&ctx]()
  418. {
  419. if (ctx.entities.count("active_tool"))
  420. {
  421. entity::id tool_eid = ctx.entities["active_tool"];
  422. const auto& tool = ctx.entity_registry->get<entity::component::tool>(tool_eid);
  423. if (tool.activated)
  424. tool.activated();
  425. }
  426. }
  427. );
  428. ctx.controls["use_tool"]->set_deactivated_callback
  429. (
  430. [&ctx]()
  431. {
  432. if (ctx.entities.count("active_tool"))
  433. {
  434. entity::id tool_eid = ctx.entities["active_tool"];
  435. const auto& tool = ctx.entity_registry->get<entity::component::tool>(tool_eid);
  436. if (tool.deactivated)
  437. tool.deactivated();
  438. }
  439. }
  440. );
  441. ctx.controls["use_tool"]->set_active_callback
  442. (
  443. [&ctx](float value)
  444. {
  445. if (ctx.entities.count("active_tool"))
  446. {
  447. entity::id tool_eid = ctx.entities["active_tool"];
  448. const auto& tool = ctx.entity_registry->get<entity::component::tool>(tool_eid);
  449. if (tool.active)
  450. tool.active();
  451. }
  452. }
  453. );
  454. */
  455. // Setup pause control
  456. ctx.controls["pause"]->set_activated_callback
  457. (
  458. [this, &ctx = this->ctx]()
  459. {
  460. // Disable controls
  461. this->disable_controls();
  462. // Set resume callback
  463. ctx.resume_callback = [this, &ctx]()
  464. {
  465. this->enable_controls();
  466. ctx.resume_callback = nullptr;
  467. };
  468. // Push pause menu state
  469. ctx.state_machine.emplace(new game::state::pause_menu(ctx));
  470. }
  471. );
  472. }
  473. void nuptial_flight::disable_controls()
  474. {
  475. ctx.controls["pause"]->set_activated_callback(nullptr);
  476. }
  477. } // namespace state
  478. } // namespace game