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

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