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

629 lines
21 KiB

2 years ago
2 years ago
2 years ago
  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/forage.hpp"
  20. #include "entity/archetype.hpp"
  21. #include "entity/commands.hpp"
  22. #include "entity/components/observer.hpp"
  23. #include "entity/components/terrain.hpp"
  24. #include "entity/components/transform.hpp"
  25. #include "entity/components/celestial-body.hpp"
  26. #include "entity/components/tool.hpp"
  27. #include "entity/systems/astronomy.hpp"
  28. #include "animation/screen-transition.hpp"
  29. #include "animation/ease.hpp"
  30. #include "resources/resource-manager.hpp"
  31. #include "entity/components/camera.hpp"
  32. #include "entity/components/constraints/spring-to.hpp"
  33. #include "entity/components/constraints/three-dof.hpp"
  34. #include "entity/components/constraint-stack.hpp"
  35. #include "application.hpp"
  36. #include "utility/timestamp.hpp"
  37. #include "animation/animator.hpp"
  38. namespace game {
  39. namespace state {
  40. namespace forage {
  41. static void setup_camera(game::context* ctx);
  42. static void setup_tools(game::context* ctx);
  43. static void setup_controls(game::context* ctx);
  44. void enter(game::context* ctx)
  45. {
  46. setup_camera(ctx);
  47. setup_tools(ctx);
  48. setup_controls(ctx);
  49. // Find planet EID by name
  50. entity::id planet_eid = ctx->entities["planet"];
  51. // Create biome terrain component
  52. entity::component::terrain biome_terrain;
  53. biome_terrain.max_lod = 18;
  54. biome_terrain.patch_material = ctx->resource_manager->load<material>("desert-terrain.mtl");
  55. biome_terrain.elevation = [](double, double) -> double
  56. {
  57. return 0.0;
  58. };
  59. // Replace planet terrain component with biome terrain component
  60. ctx->entity_registry->replace<entity::component::terrain>(planet_eid, biome_terrain);
  61. // Create observer
  62. entity::id observer_eid = ctx->entity_registry->create();
  63. {
  64. entity::component::observer observer;
  65. observer.reference_body_eid = planet_eid;
  66. observer.elevation = 0.0;
  67. observer.latitude = 0.0;
  68. observer.longitude = 0.0;
  69. observer.camera = ctx->surface_camera;
  70. ctx->entity_registry->assign<entity::component::observer>(observer_eid, observer);
  71. // Set reference location of astronomy system
  72. //ctx->astronomy_system->set_reference_body(planet_eid);
  73. ctx->astronomy_system->set_observer_location(double3{observer.elevation, observer.latitude, observer.longitude});
  74. }
  75. // Create larva
  76. {
  77. entity::archetype* larva_archetype = ctx->resource_manager->load<entity::archetype>("ant-larva.ent");
  78. auto larva_eid = larva_archetype->create(*ctx->entity_registry);
  79. entity::command::warp_to(*ctx->entity_registry, larva_eid, {50, 0.1935f, 0});
  80. entity::command::assign_render_layers(*ctx->entity_registry, larva_eid, 0b10);
  81. }
  82. // Create cocoon
  83. {
  84. entity::archetype* cocoon_archetype = ctx->resource_manager->load<entity::archetype>("ant-cocoon.ent");
  85. auto cocoon_eid = cocoon_archetype->create(*ctx->entity_registry);
  86. entity::command::warp_to(*ctx->entity_registry, cocoon_eid, {-50, 0.1935f, 0});
  87. entity::command::assign_render_layers(*ctx->entity_registry, cocoon_eid, 0b10);
  88. }
  89. // Create moon
  90. {
  91. entity::archetype* moon_archetype = ctx->resource_manager->load<entity::archetype>("moon.ent");
  92. auto moon_eid = moon_archetype->create(*ctx->entity_registry);
  93. entity::command::warp_to(*ctx->entity_registry, moon_eid, {50.0f, 50.0f, 50.0f});
  94. entity::command::assign_render_layers(*ctx->entity_registry, moon_eid, 0b10);
  95. entity::command::set_scale(*ctx->entity_registry, moon_eid, float3{1.0f, 1.0f, 1.0f} * 10.0f);
  96. }
  97. ctx->surface_scene->update_tweens();
  98. // Start fade in
  99. ctx->fade_transition->transition(1.0f, true, ease<float>::in_quad);
  100. }
  101. void exit(game::context* ctx)
  102. {}
  103. void setup_camera(game::context* ctx)
  104. {
  105. // Switch to surface camera
  106. ctx->underground_camera->set_active(false);
  107. ctx->surface_camera->set_active(true);
  108. // Create surface camera entity
  109. if (!ctx->entities.count("surface_cam"))
  110. {
  111. // Create camera target entity
  112. entity::id target_eid = ctx->entity_registry->create();
  113. ctx->entities["surface_cam_target"] = target_eid;
  114. {
  115. // Transform
  116. entity::component::transform target_transform;
  117. target_transform.local = math::identity_transform<float>;
  118. target_transform.world = target_transform.local;
  119. target_transform.warp = true;
  120. ctx->entity_registry->assign<entity::component::transform>(target_eid, target_transform);
  121. }
  122. // Create camera entity
  123. entity::id camera_eid = ctx->entity_registry->create();
  124. ctx->entities["surface_cam"] = camera_eid;
  125. // Create camera transform component
  126. entity::component::transform transform;
  127. transform.local = math::identity_transform<float>;
  128. transform.world = transform.local;
  129. transform.warp = true;
  130. ctx->entity_registry->assign<entity::component::transform>(camera_eid, transform);
  131. // Create camera camera component
  132. entity::component::camera camera;
  133. camera.object = ctx->surface_camera;
  134. ctx->entity_registry->assign<entity::component::camera>(camera_eid, camera);
  135. // Create camera 3DOF constraint entity
  136. entity::id three_dof_constraint_eid = ctx->entity_registry->create();
  137. ctx->entities["surface_cam_3dof"] = three_dof_constraint_eid;
  138. {
  139. // Create 3DOF to constraint
  140. entity::component::constraint::three_dof three_dof;
  141. three_dof.yaw = 0.0f;
  142. three_dof.pitch = 0.0f;
  143. three_dof.roll = 0.0f;
  144. ctx->entity_registry->assign<entity::component::constraint::three_dof>(three_dof_constraint_eid, three_dof);
  145. // Create constraint stack node component
  146. entity::component::constraint_stack_node node;
  147. node.active = true;
  148. node.weight = 1.0f;
  149. node.next = entt::null;
  150. ctx->entity_registry->assign<entity::component::constraint_stack_node>(three_dof_constraint_eid, node);
  151. }
  152. // Create camera spring to constraint entity
  153. entity::id spring_constraint_eid = ctx->entity_registry->create();
  154. {
  155. // Create spring to constraint
  156. entity::component::constraint::spring_to spring;
  157. spring.target = target_eid;
  158. 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>};
  159. spring.translation.w = hz_to_rads(8.0f);
  160. spring.spring_translation = true;
  161. spring.spring_rotation = false;
  162. ctx->entity_registry->assign<entity::component::constraint::spring_to>(spring_constraint_eid, spring);
  163. // Create constraint stack node component
  164. entity::component::constraint_stack_node node;
  165. node.active = true;
  166. node.weight = 1.0f;
  167. node.next = three_dof_constraint_eid;
  168. ctx->entity_registry->assign<entity::component::constraint_stack_node>(spring_constraint_eid, node);
  169. }
  170. // Create camera constraint stack component
  171. entity::component::constraint_stack constraint_stack;
  172. constraint_stack.head = spring_constraint_eid;
  173. ctx->entity_registry->assign<entity::component::constraint_stack>(camera_eid, constraint_stack);
  174. }
  175. ctx->surface_camera->set_exposure(-14.5f);
  176. }
  177. void setup_tools(game::context* ctx)
  178. {
  179. if (!ctx->entities.count("move_tool"))
  180. {
  181. entity::id tool_eid = ctx->entity_registry->create();
  182. ctx->entities["move_tool"] = tool_eid;
  183. }
  184. if (!ctx->entities.count("paint_tool"))
  185. {
  186. entity::id tool_eid = ctx->entity_registry->create();
  187. ctx->entities["paint_tool"] = tool_eid;
  188. }
  189. if (!ctx->entities.count("flip_tool"))
  190. {
  191. entity::id tool_eid = ctx->entity_registry->create();
  192. ctx->entities["flip_tool"] = tool_eid;
  193. }
  194. if (!ctx->entities.count("poke_tool"))
  195. {
  196. entity::id tool_eid = ctx->entity_registry->create();
  197. ctx->entities["poke_tool"] = tool_eid;
  198. }
  199. if (!ctx->entities.count("inspect_tool"))
  200. {
  201. entity::id tool_eid = ctx->entity_registry->create();
  202. ctx->entities["inspect_tool"] = tool_eid;
  203. }
  204. if (!ctx->entities.count("label_tool"))
  205. {
  206. entity::id tool_eid = ctx->entity_registry->create();
  207. ctx->entities["label_tool"] = tool_eid;
  208. }
  209. if (!ctx->entities.count("time_tool"))
  210. {
  211. entity::id tool_eid = ctx->entity_registry->create();
  212. ctx->entities["time_tool"] = tool_eid;
  213. entity::component::tool tool;
  214. tool.active = [ctx]()
  215. {
  216. auto [mouse_x, mouse_y] = ctx->app->get_mouse()->get_current_position();
  217. auto [window_w, window_h] = ctx->app->get_viewport_dimensions();
  218. entity::id planet_eid = ctx->entities["planet"];
  219. entity::component::celestial_body body = ctx->entity_registry->get<entity::component::celestial_body>(planet_eid);
  220. body.axial_rotation = math::radians(360.0f) * ((float)mouse_x / (float)window_w);
  221. ctx->entity_registry->replace<entity::component::celestial_body>(planet_eid, body);
  222. };
  223. ctx->entity_registry->assign<entity::component::tool>(tool_eid, tool);
  224. }
  225. if (!ctx->entities.count("camera_tool"))
  226. {
  227. entity::id tool_eid = ctx->entity_registry->create();
  228. ctx->entities["camera_tool"] = tool_eid;
  229. entity::component::tool tool;
  230. tool.activated = [ctx]()
  231. {
  232. if (!ctx->camera_flash_animation->is_stopped())
  233. return;
  234. std::string path = ctx->screenshots_path + "antkeeper-" + timestamp() + ".png";
  235. ctx->app->save_frame(path);
  236. material_property<float4>* tint = static_cast<material_property<float4>*>(ctx->camera_flash_billboard->get_material()->get_property("tint"));
  237. tint->set_value({1.0f, 1.0f, 1.0f, 1.0f});
  238. ctx->camera_flash_billboard->get_material()->update_tweens();
  239. ctx->ui_scene->add_object(ctx->camera_flash_billboard);
  240. ctx->camera_flash_animation->set_end_callback
  241. (
  242. [ctx]()
  243. {
  244. ctx->ui_scene->remove_object(ctx->camera_flash_billboard);
  245. }
  246. );
  247. ctx->camera_flash_animation->set_frame_callback
  248. (
  249. [ctx, tint](int channel, const float& opacity)
  250. {
  251. tint->set_value({1.0f, 1.0f, 1.0f, opacity});
  252. }
  253. );
  254. ctx->animator->remove_animation(ctx->camera_flash_animation);
  255. ctx->animator->add_animation(ctx->camera_flash_animation);
  256. ctx->camera_flash_animation->rewind();
  257. ctx->camera_flash_animation->play();
  258. };
  259. ctx->entity_registry->assign<entity::component::tool>(tool_eid, tool);
  260. }
  261. // Set active tool
  262. ctx->entities["active_tool"] = ctx->entities["camera_tool"];
  263. }
  264. void setup_controls(game::context* ctx)
  265. {
  266. // Get underground camera entity
  267. entity::id camera_eid = ctx->entities["surface_cam"];
  268. entity::id target_eid = ctx->entities["surface_cam_target"];
  269. entity::id three_dof_eid = ctx->entities["surface_cam_3dof"];
  270. const float dolly_speed = 20.0f;
  271. const float truck_speed = dolly_speed;
  272. const float pedestal_speed = 30.0f;
  273. float mouse_tilt_sensitivity = 1.0f;
  274. float mouse_pan_sensitivity = 1.0f;
  275. bool mouse_invert_tilt = false;
  276. bool mouse_invert_pan = false;
  277. float gamepad_tilt_sensitivity = 1.0f;
  278. float gamepad_pan_sensitivity = 1.0f;
  279. bool gamepad_invert_tilt = false;
  280. bool gamepad_invert_pan = false;
  281. bool mouse_look_toggle = false;
  282. ctx->mouse_look = false;
  283. if (ctx->config->contains("mouse_tilt_sensitivity"))
  284. mouse_tilt_sensitivity = math::radians((*ctx->config)["mouse_tilt_sensitivity"].get<float>());
  285. if (ctx->config->contains("mouse_pan_sensitivity"))
  286. mouse_pan_sensitivity = math::radians((*ctx->config)["mouse_pan_sensitivity"].get<float>());
  287. if (ctx->config->contains("mouse_invert_tilt"))
  288. mouse_invert_tilt = math::radians((*ctx->config)["mouse_invert_tilt"].get<bool>());
  289. if (ctx->config->contains("mouse_invert_pan"))
  290. mouse_invert_pan = math::radians((*ctx->config)["mouse_invert_pan"].get<bool>());
  291. if (ctx->config->contains("mouse_look_toggle"))
  292. mouse_look_toggle = math::radians((*ctx->config)["mouse_look_toggle"].get<bool>());
  293. if (ctx->config->contains("gamepad_tilt_sensitivity"))
  294. gamepad_tilt_sensitivity = math::radians((*ctx->config)["gamepad_tilt_sensitivity"].get<float>());
  295. if (ctx->config->contains("gamepad_pan_sensitivity"))
  296. gamepad_pan_sensitivity = math::radians((*ctx->config)["gamepad_pan_sensitivity"].get<float>());
  297. if (ctx->config->contains("gamepad_invert_tilt"))
  298. gamepad_invert_tilt = math::radians((*ctx->config)["gamepad_invert_tilt"].get<bool>());
  299. if (ctx->config->contains("gamepad_invert_pan"))
  300. gamepad_invert_pan = math::radians((*ctx->config)["gamepad_invert_pan"].get<bool>());
  301. const input::control* move_slow = ctx->controls["move_slow"];
  302. const input::control* move_fast = ctx->controls["move_fast"];
  303. const input::control* mouse_look = ctx->controls["mouse_look"];
  304. float mouse_tilt_factor = mouse_tilt_sensitivity * (mouse_invert_tilt ? -1.0f : 1.0f);
  305. float mouse_pan_factor = mouse_pan_sensitivity * (mouse_invert_pan ? -1.0f : 1.0f);
  306. float gamepad_tilt_factor = gamepad_tilt_sensitivity * (gamepad_invert_tilt ? -1.0f : 1.0f);
  307. float gamepad_pan_factor = gamepad_pan_sensitivity * (gamepad_invert_pan ? -1.0f : 1.0f);
  308. ctx->controls["dolly_forward"]->set_active_callback
  309. (
  310. [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value)
  311. {
  312. if (move_slow->is_active())
  313. value *= 0.25f;
  314. if (move_fast->is_active())
  315. value *= 4.0f;
  316. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  317. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  318. const float3 movement = {0.0f, 0.0f, -truck_speed * value * (1.0f / 60.0f)};
  319. entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement);
  320. }
  321. );
  322. // Dolly backward
  323. ctx->controls["dolly_backward"]->set_active_callback
  324. (
  325. [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value)
  326. {
  327. if (move_slow->is_active())
  328. value *= 0.25f;
  329. if (move_fast->is_active())
  330. value *= 4.0f;
  331. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  332. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  333. const float3 movement = {0.0f, 0.0f, truck_speed * value * (1.0f / 60.0f)};
  334. entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement);
  335. }
  336. );
  337. // Truck right
  338. ctx->controls["truck_right"]->set_active_callback
  339. (
  340. [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value)
  341. {
  342. if (move_slow->is_active())
  343. value *= 0.25f;
  344. if (move_fast->is_active())
  345. value *= 4.0f;
  346. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  347. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  348. const float3 movement = {truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f};
  349. entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement);
  350. }
  351. );
  352. // Truck left
  353. ctx->controls["truck_left"]->set_active_callback
  354. (
  355. [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value)
  356. {
  357. if (move_slow->is_active())
  358. value *= 0.25f;
  359. if (move_fast->is_active())
  360. value *= 4.0f;
  361. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  362. const math::quaternion<float> yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f});
  363. const float3 movement = {-truck_speed * value * (1.0f / 60.0f), 0.0f, 0.0f};
  364. entity::command::translate(*ctx->entity_registry, target_eid, yaw * movement);
  365. }
  366. );
  367. // Pedestal up
  368. ctx->controls["pedestal_up"]->set_active_callback
  369. (
  370. [ctx, target_eid, pedestal_speed, move_slow, move_fast](float value)
  371. {
  372. if (move_slow->is_active())
  373. value *= 0.25f;
  374. if (move_fast->is_active())
  375. value *= 4.0f;
  376. const float3 movement = {0.0f, pedestal_speed * value * (1.0f / 60.0f), 0.0f};
  377. entity::command::translate(*ctx->entity_registry, target_eid, movement);
  378. }
  379. );
  380. // Pedestal down
  381. ctx->controls["pedestal_down"]->set_active_callback
  382. (
  383. [ctx, target_eid, pedestal_speed, move_slow, move_fast](float value)
  384. {
  385. if (move_slow->is_active())
  386. value *= 0.25f;
  387. if (move_fast->is_active())
  388. value *= 4.0f;
  389. const float3 movement = {0.0f, -pedestal_speed * value * (1.0f / 60.0f), 0.0f};
  390. entity::command::translate(*ctx->entity_registry, target_eid, movement);
  391. }
  392. );
  393. // Mouse rotate
  394. ctx->controls["mouse_look"]->set_activated_callback
  395. (
  396. [ctx, mouse_look_toggle]()
  397. {
  398. if (mouse_look_toggle)
  399. ctx->mouse_look = !ctx->mouse_look;
  400. else
  401. ctx->mouse_look = true;
  402. ctx->app->set_relative_mouse_mode(ctx->mouse_look);
  403. }
  404. );
  405. ctx->controls["mouse_look"]->set_deactivated_callback
  406. (
  407. [ctx, mouse_look_toggle]()
  408. {
  409. if (!mouse_look_toggle)
  410. {
  411. ctx->mouse_look = false;
  412. ctx->app->set_relative_mouse_mode(false);
  413. }
  414. }
  415. );
  416. // Pan left
  417. ctx->controls["pan_left_gamepad"]->set_active_callback
  418. (
  419. [ctx, three_dof_eid, gamepad_pan_factor](float value)
  420. {
  421. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  422. three_dof.yaw += gamepad_pan_factor * value * (1.0f / 60.0f);
  423. }
  424. );
  425. ctx->controls["pan_left_mouse"]->set_active_callback
  426. (
  427. [ctx, three_dof_eid, mouse_pan_factor](float value)
  428. {
  429. if (!ctx->mouse_look)
  430. return;
  431. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  432. three_dof.yaw += mouse_pan_factor * value * (1.0f / 60.0f);
  433. }
  434. );
  435. // Pan right
  436. ctx->controls["pan_right_gamepad"]->set_active_callback
  437. (
  438. [ctx, three_dof_eid, gamepad_pan_factor](float value)
  439. {
  440. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  441. three_dof.yaw -= gamepad_pan_factor * value * (1.0f / 60.0f);
  442. }
  443. );
  444. ctx->controls["pan_right_mouse"]->set_active_callback
  445. (
  446. [ctx, three_dof_eid, mouse_pan_factor](float value)
  447. {
  448. if (!ctx->mouse_look)
  449. return;
  450. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  451. three_dof.yaw -= mouse_pan_factor * value * (1.0f / 60.0f);
  452. }
  453. );
  454. // Tilt up
  455. ctx->controls["tilt_up_gamepad"]->set_active_callback
  456. (
  457. [ctx, three_dof_eid, gamepad_tilt_factor](float value)
  458. {
  459. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  460. three_dof.pitch -= gamepad_tilt_factor * value * (1.0f / 60.0f);
  461. three_dof.pitch = std::max<float>(math::radians(-90.0f), three_dof.pitch);
  462. }
  463. );
  464. ctx->controls["tilt_up_mouse"]->set_active_callback
  465. (
  466. [ctx, three_dof_eid, mouse_tilt_factor](float value)
  467. {
  468. if (!ctx->mouse_look)
  469. return;
  470. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  471. three_dof.pitch -= mouse_tilt_factor * value * (1.0f / 60.0f);
  472. three_dof.pitch = std::max<float>(math::radians(-90.0f), three_dof.pitch);
  473. }
  474. );
  475. // Tilt down
  476. ctx->controls["tilt_down_gamepad"]->set_active_callback
  477. (
  478. [ctx, three_dof_eid, gamepad_tilt_factor](float value)
  479. {
  480. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  481. three_dof.pitch += gamepad_tilt_factor * value * (1.0f / 60.0f);
  482. three_dof.pitch = std::min<float>(math::radians(90.0f), three_dof.pitch);
  483. }
  484. );
  485. ctx->controls["tilt_down_mouse"]->set_active_callback
  486. (
  487. [ctx, three_dof_eid, mouse_tilt_factor](float value)
  488. {
  489. if (!ctx->mouse_look)
  490. return;
  491. auto& three_dof = ctx->entity_registry->get<entity::component::constraint::three_dof>(three_dof_eid);
  492. three_dof.pitch += mouse_tilt_factor * value * (1.0f / 60.0f);
  493. three_dof.pitch = std::min<float>(math::radians(90.0f), three_dof.pitch);
  494. }
  495. );
  496. // Use tool
  497. ctx->controls["use_tool"]->set_activated_callback
  498. (
  499. [ctx]()
  500. {
  501. if (ctx->entities.count("active_tool"))
  502. {
  503. entity::id tool_eid = ctx->entities["active_tool"];
  504. const auto& tool = ctx->entity_registry->get<entity::component::tool>(tool_eid);
  505. if (tool.activated)
  506. tool.activated();
  507. }
  508. }
  509. );
  510. ctx->controls["use_tool"]->set_deactivated_callback
  511. (
  512. [ctx]()
  513. {
  514. if (ctx->entities.count("active_tool"))
  515. {
  516. entity::id tool_eid = ctx->entities["active_tool"];
  517. const auto& tool = ctx->entity_registry->get<entity::component::tool>(tool_eid);
  518. if (tool.deactivated)
  519. tool.deactivated();
  520. }
  521. }
  522. );
  523. ctx->controls["use_tool"]->set_active_callback
  524. (
  525. [ctx](float value)
  526. {
  527. if (ctx->entities.count("active_tool"))
  528. {
  529. entity::id tool_eid = ctx->entities["active_tool"];
  530. const auto& tool = ctx->entity_registry->get<entity::component::tool>(tool_eid);
  531. if (tool.active)
  532. tool.active();
  533. }
  534. }
  535. );
  536. /*
  537. auto [mouse_x, mouse_y] = ctx->app->get_mouse()->get_current_position();
  538. ctx->logger->log("tool used (" + std::to_string(mouse_x) + ", " + std::to_string(mouse_y) + ")");
  539. entity::id planet_eid = ctx->entities["planet"];
  540. entity::component::celestial_body& body = ctx->entity_registry->get<entity::component::celestial_body>(planet_eid);
  541. body.axial_tilt += math::radians(30.0f) * 1.0f / 60.0f;
  542. */
  543. }
  544. } // namespace forage
  545. } // namespace state
  546. } // namespace game