diff --git a/src/entity/components/select.hpp b/src/entity/components/select.hpp new file mode 100644 index 0000000..e02b66b --- /dev/null +++ b/src/entity/components/select.hpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2021 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_ENTITY_COMPONENT_SELECT_HPP +#define ANTKEEPER_ENTITY_COMPONENT_SELECT_HPP + +namespace entity { +namespace component { + +/// Allows an entity to be selected. +struct select +{ + /// Radius of selection bounds. + float radius; +}; + +} // namespace component +} // namespace entity + +#endif // ANTKEEPER_ENTITY_COMPONENT_SELECT_HPP diff --git a/src/game/bootloader.cpp b/src/game/bootloader.cpp index 9c5918a..e7941cd 100644 --- a/src/game/bootloader.cpp +++ b/src/game/bootloader.cpp @@ -50,7 +50,6 @@ #include "renderer/vertex-attributes.hpp" #include "renderer/compositor.hpp" #include "renderer/renderer.hpp" -#include "resources/config-file.hpp" #include "resources/resource-manager.hpp" #include "resources/resource-manager.hpp" #include "scene/scene.hpp" @@ -357,7 +356,7 @@ void load_config(game::context* ctx) logger->push_task("Loading config"); // Load config file - ctx->config = ctx->resource_manager->load("config.txt"); + ctx->config = ctx->resource_manager->load("config.json"); if (!ctx->config) { logger->pop_task(EXIT_FAILURE); @@ -376,7 +375,7 @@ void load_strings(game::context* ctx) build_string_table_map(&ctx->string_table_map, *ctx->string_table); - ctx->language_code = ctx->config->get("language"); + ctx->language_code = (*ctx->config)["language"].get(); ctx->language_index = -1; for (int i = 2; i < (*ctx->string_table)[0].size(); ++i) { @@ -397,7 +396,7 @@ void setup_window(game::context* ctx) logger->push_task("Setting up window"); application* app = ctx->app; - config_file* config = ctx->config; + json* config = ctx->config; // Set fullscreen or windowed mode bool fullscreen = true; @@ -405,8 +404,8 @@ void setup_window(game::context* ctx) fullscreen = true; else if (ctx->option_windowed.has_value()) fullscreen = false; - else if (config->has("fullscreen")) - fullscreen = (config->get("fullscreen") != 0); + else if (config->contains("fullscreen")) + fullscreen = (*config)["fullscreen"].get(); app->set_fullscreen(fullscreen); // Set resolution @@ -414,13 +413,19 @@ void setup_window(game::context* ctx) int2 resolution = {display_dimensions[0], display_dimensions[1]}; if (fullscreen) { - if (config->has("fullscreen_resolution")) - resolution = config->get("fullscreen_resolution"); + if (config->contains("fullscreen_resolution")) + { + resolution.x = (*config)["fullscreen_resolution"][0].get(); + resolution.y = (*config)["fullscreen_resolution"][1].get(); + } } else { - if (config->has("windowed_resolution")) - resolution = config->get("windowed_resolution"); + if (config->contains("windowed_resolution")) + { + resolution.x = (*config)["windowed_resolution"][0].get(); + resolution.y = (*config)["windowed_resolution"][1].get(); + } } app->resize_window(resolution.x, resolution.y); @@ -428,8 +433,8 @@ void setup_window(game::context* ctx) bool vsync = true; if (ctx->option_vsync.has_value()) vsync = (ctx->option_vsync.value() != 0); - else if (config->has("vsync")) - vsync = (config->get("vsync") != 0); + else if (config->contains("vsync")) + vsync = (*config)["vsync"].get(); app->set_vsync(vsync); // Set title @@ -466,9 +471,9 @@ void setup_rendering(game::context* ctx) // Create shadow map framebuffer int shadow_map_resolution = 4096; - if (ctx->config->has("shadow_map_resolution")) + if (ctx->config->contains("shadow_map_resolution")) { - shadow_map_resolution = ctx->config->get("shadow_map_resolution"); + shadow_map_resolution = (*ctx->config)["shadow_map_resolution"].get(); } ctx->shadow_map_depth_texture = new gl::texture_2d(shadow_map_resolution, shadow_map_resolution, gl::pixel_type::float_32, gl::pixel_format::d); ctx->shadow_map_depth_texture->set_wrapping(gl::texture_wrapping::extend, gl::texture_wrapping::extend); @@ -846,10 +851,10 @@ void setup_systems(game::context* ctx) ctx->proteome_system = new entity::system::proteome(*ctx->entity_registry); // Set time scale - float time_scale = 60.0f; - if (ctx->config->has("time_scale")) + double time_scale = 60.0; + if (ctx->config->contains("time_scale")) { - time_scale = ctx->config->get("time_scale"); + time_scale = (*ctx->config)["time_scale"].get(); } ctx->orbit_system->set_time_scale(time_scale / seconds_per_day); diff --git a/src/game/context.hpp b/src/game/context.hpp index 3432cf9..2b43185 100644 --- a/src/game/context.hpp +++ b/src/game/context.hpp @@ -42,6 +42,7 @@ #include #include #include +#include "resources/json.hpp" // Forward declarations class animator; @@ -49,7 +50,6 @@ class application; class bloom_pass; class clear_pass; class compositor; -class config_file; class final_pass; class material; class material_pass; @@ -129,8 +129,8 @@ struct context std::string screenshots_path; std::string data_package_path; - // Config - config_file* config; + // Configuration + json* config; // Resources resource_manager* resource_manager; diff --git a/src/game/states/forage.cpp b/src/game/states/forage.cpp index c11592f..95c6a8c 100644 --- a/src/game/states/forage.cpp +++ b/src/game/states/forage.cpp @@ -38,6 +38,7 @@ namespace state { namespace forage { static void setup_camera(game::context* ctx); +static void setup_tools(game::context* ctx); static void setup_controls(game::context* ctx); void enter(game::context* ctx) @@ -187,6 +188,54 @@ void setup_camera(game::context* ctx) ctx->surface_camera->set_exposure(-14.5f); } +void setup_tools(game::context* ctx) +{ + if (!ctx->entities.count("move_tool")) + { + entity::id tool_eid = ctx->entity_registry->create(); + ctx->entities["move_tool"] = tool_eid; + } + + if (!ctx->entities.count("paint_tool")) + { + entity::id tool_eid = ctx->entity_registry->create(); + ctx->entities["paint_tool"] = tool_eid; + } + + if (!ctx->entities.count("flip_tool")) + { + entity::id tool_eid = ctx->entity_registry->create(); + ctx->entities["flip_tool"] = tool_eid; + } + + if (!ctx->entities.count("poke_tool")) + { + entity::id tool_eid = ctx->entity_registry->create(); + ctx->entities["poke_tool"] = tool_eid; + } + + if (!ctx->entities.count("inspect_tool")) + { + entity::id tool_eid = ctx->entity_registry->create(); + ctx->entities["inspect_tool"] = tool_eid; + } + + if (!ctx->entities.count("label_tool")) + { + entity::id tool_eid = ctx->entity_registry->create(); + ctx->entities["label_tool"] = tool_eid; + } + + if (!ctx->entities.count("wait_tool")) + { + entity::id tool_eid = ctx->entity_registry->create(); + ctx->entities["wait_tool"] = tool_eid; + } + + // Set move tool as active tool + ctx->entities["active_tool"] = ctx->entities["move_tool"]; +} + void setup_controls(game::context* ctx) { // Get underground camera entity @@ -209,9 +258,9 @@ void setup_controls(game::context* ctx) [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value) { if (move_slow->is_active()) - value *= 0.5f; + value *= 0.25f; if (move_fast->is_active()) - value *= 2.0f; + value *= 4.0f; auto& three_dof = ctx->entity_registry->get(three_dof_eid); const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); @@ -227,9 +276,9 @@ void setup_controls(game::context* ctx) [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value) { if (move_slow->is_active()) - value *= 0.5f; + value *= 0.25f; if (move_fast->is_active()) - value *= 2.0f; + value *= 4.0f; auto& three_dof = ctx->entity_registry->get(three_dof_eid); const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); @@ -245,9 +294,9 @@ void setup_controls(game::context* ctx) [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value) { if (move_slow->is_active()) - value *= 0.5f; + value *= 0.25f; if (move_fast->is_active()) - value *= 2.0f; + value *= 4.0f; auto& three_dof = ctx->entity_registry->get(three_dof_eid); const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); @@ -263,9 +312,9 @@ void setup_controls(game::context* ctx) [ctx, target_eid, three_dof_eid, truck_speed, move_slow, move_fast](float value) { if (move_slow->is_active()) - value *= 0.5f; + value *= 0.25f; if (move_fast->is_active()) - value *= 2.0f; + value *= 4.0f; auto& three_dof = ctx->entity_registry->get(three_dof_eid); const math::quaternion yaw = math::angle_axis(three_dof.yaw, {0.0f, 1.0f, 0.0f}); @@ -281,9 +330,9 @@ void setup_controls(game::context* ctx) [ctx, target_eid, pedestal_speed, move_slow, move_fast](float value) { if (move_slow->is_active()) - value *= 0.5f; + value *= 0.25f; if (move_fast->is_active()) - value *= 2.0f; + value *= 4.0f; const float3 movement = {0.0f, pedestal_speed * value * (1.0f / 60.0f), 0.0f}; entity::command::translate(*ctx->entity_registry, target_eid, movement); @@ -296,9 +345,9 @@ void setup_controls(game::context* ctx) [ctx, target_eid, pedestal_speed, move_slow, move_fast](float value) { if (move_slow->is_active()) - value *= 0.5f; + value *= 0.25f; if (move_fast->is_active()) - value *= 2.0f; + value *= 4.0f; const float3 movement = {0.0f, -pedestal_speed * value * (1.0f / 60.0f), 0.0f}; entity::command::translate(*ctx->entity_registry, target_eid, movement); @@ -374,6 +423,39 @@ void setup_controls(game::context* ctx) three_dof.pitch = std::min(math::radians(90.0f), three_dof.pitch); } ); + + // Use tool + ctx->controls["use_tool"]->set_activated_callback + ( + [ctx]() + { + if (ctx->entities["active_tool"] == ctx->entities["move_tool"]) + { + // Project mouse position into scene and grab selectable entity + auto [mouse_x, mouse_y] = ctx->app->get_mouse()->get_current_position(); + } + } + ); + + ctx->controls["use_tool"]->set_deactivated_callback + ( + [ctx]() + { + if (ctx->entities["active_tool"] == ctx->entities["move_tool"]) + { + + } + } + ); + + ctx->controls["use_tool"]->set_active_callback + ( + [ctx](float value) + { + auto [mouse_x, mouse_y] = ctx->app->get_mouse()->get_current_position(); + ctx->logger->log("tool used (" + std::to_string(mouse_x) + ", " + std::to_string(mouse_y) + ")"); + } + ); } } // namespace forage diff --git a/src/game/states/loading.cpp b/src/game/states/loading.cpp index 131d0cc..8173efa 100644 --- a/src/game/states/loading.cpp +++ b/src/game/states/loading.cpp @@ -47,7 +47,6 @@ #include "resources/resource-manager.hpp" #include "scene/ambient-light.hpp" #include "scene/directional-light.hpp" -#include "resources/config-file.hpp" #include "utility/timestamp.hpp" namespace game { @@ -143,11 +142,14 @@ void load_controls(game::context* ctx) if (!fullscreen) { - int2 resolution = ctx->config->get("windowed_resolution"); + int2 resolution; + resolution.x = (*ctx->config)["windowed_resolution"][0].get(); + resolution.y = (*ctx->config)["windowed_resolution"][1].get(); + ctx->app->resize_window(resolution.x, resolution.y); } - ctx->config->set("fullscreen", (fullscreen) ? 1 : 0); + (*ctx->config)["fullscreen"] = fullscreen; } ); @@ -288,6 +290,14 @@ void load_controls(game::context* ctx) ctx->input_event_router->add_mapping(input::mouse_motion_mapping(control, nullptr, input::mouse_motion_axis::positive_y)); ctx->controls["mouse_down"] = control; } + + // Use tool + if (!ctx->controls.count("use_tool")) + { + input::control* control = new input::control(); + ctx->input_event_router->add_mapping(input::mouse_button_mapping(control, nullptr, 1)); + ctx->controls["use_tool"] = control; + } } void cosmogenesis(game::context* ctx) diff --git a/src/game/states/nuptial-flight.cpp b/src/game/states/nuptial-flight.cpp index bf0ed9d..2ba04ff 100644 --- a/src/game/states/nuptial-flight.cpp +++ b/src/game/states/nuptial-flight.cpp @@ -29,7 +29,6 @@ #include "renderer/material-property.hpp" #include "animation/screen-transition.hpp" #include "animation/ease.hpp" -#include "resources/config-file.hpp" #include "resources/resource-manager.hpp" namespace game { @@ -102,7 +101,7 @@ void enter(game::context* ctx) void exit(game::context* ctx) { // Resume motion of celestial objects - const double time_scale = ctx->config->get("time_scale"); + const double time_scale = (*ctx->config)["time_scale"].get(); ctx->astronomy_system->set_time_scale(time_scale); ctx->orbit_system->set_time_scale(time_scale); } diff --git a/src/resources/config-file-loader.cpp b/src/resources/config-file-loader.cpp deleted file mode 100644 index 6c5b8e5..0000000 --- a/src/resources/config-file-loader.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2021 Christopher J. Howard - * - * This file is part of Antkeeper source code. - * - * Antkeeper source code is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Antkeeper source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Antkeeper source code. If not, see . - */ - -#include "resources/resource-loader.hpp" -#include "resources/resource-manager.hpp" -#include "resources/config-file.hpp" -#include "resources/text-file.hpp" - -template <> -config_file* resource_loader::load(resource_manager* resource_manager, PHYSFS_File* file) -{ - // Load as text file - text_file* text = resource_loader::load(resource_manager, file); - - config_file* config = new config_file(); - for (const std::string& line: *text) - { - if (line[0] == '#') - continue; - - std::size_t delimeter = line.find_first_of('='); - if (delimeter == std::string::npos) - continue; - - std::string name = line.substr(0, delimeter); - std::string value = line.substr(delimeter + 1, line.length() - delimeter - 1); - - if (name.empty() || value.empty()) - continue; - - config->set(name, value); - } - - delete text; - - return config; -} diff --git a/src/resources/config-file.hpp b/src/resources/config-file.hpp deleted file mode 100644 index fa59a04..0000000 --- a/src/resources/config-file.hpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2021 Christopher J. Howard - * - * This file is part of Antkeeper source code. - * - * Antkeeper source code is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Antkeeper source code is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Antkeeper source code. If not, see . - */ - -#ifndef CONFIG_FILE_HPP -#define CONFIG_FILE_HPP - -#include -#include -#include - -class config_file -{ -public: - template - void set(const std::string& name, const T& value); - - template - T get(const std::string& name) const; - - bool has(const std::string& name) const; - -private: - std::unordered_map variables; -}; - -template -void config_file::set(const std::string& name, const T& value) -{ - std::stringstream stream; - stream << value; - variables[name] = stream.str(); -} - -template -T config_file::get(const std::string& name) const -{ - T value; - if (auto it = variables.find(name); it != variables.end()) - std::stringstream(it->second) >> value; - return value; -} - -inline bool config_file::has(const std::string& name) const -{ - return (variables.find(name) != variables.end()); -} - -#endif // CONFIG_FILE_HPP diff --git a/src/resources/json-loader.cpp b/src/resources/json-loader.cpp new file mode 100644 index 0000000..cb798a7 --- /dev/null +++ b/src/resources/json-loader.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2021 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#include "resource-loader.hpp" +#include "resource-manager.hpp" +#include "json.hpp" +#include + +template <> +json* resource_loader::load(resource_manager* resource_manager, PHYSFS_File* file) +{ + // Read file into buffer + std::size_t size = static_cast(PHYSFS_fileLength(file)); + std::string buffer; + buffer.resize(size); + PHYSFS_readBytes(file, &buffer[0], size); + + // Parse json from file buffer + json* data = new json(json::parse(buffer)); + + return data; +} diff --git a/src/resources/json.hpp b/src/resources/json.hpp new file mode 100644 index 0000000..91f26d2 --- /dev/null +++ b/src/resources/json.hpp @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2021 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_RESOURCES_JSON_HPP +#define ANTKEEPER_RESOURCES_JSON_HPP + +#include + +/// JSON data +typedef nlohmann::json json; + +#endif // ANTKEEPER_RESOURCES_JSON_HPP