From f86fc143ffa00e3adf53afa860e64465bebed973 Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Thu, 9 Feb 2023 00:05:34 +0800 Subject: [PATCH] Fix key repeat input bindings. Start to fix menu controls that were broken changes to the input and event systems. Add Windows version resource file. Enable UTF-8 console output on Windows. --- CMakeLists.txt | 27 ++- src/app/sdl/sdl-input-manager.cpp | 9 +- src/config.hpp.in | 57 ++--- src/debug/console.cpp | 7 + src/debug/console.hpp | 3 + src/event/subscription.hpp | 2 +- src/game/context.hpp | 49 ++--- src/game/menu.cpp | 337 +++++++++++++++++------------ src/game/menu.hpp | 6 +- src/game/state/boot.cpp | 84 +++---- src/game/state/boot.hpp | 4 +- src/game/state/extras-menu.cpp | 15 +- src/game/state/main-menu.cpp | 55 +++-- src/game/state/options-menu.cpp | 27 ++- src/input/control-map.cpp | 10 +- src/input/input-events.hpp | 9 +- src/input/keyboard.cpp | 8 +- src/input/keyboard.hpp | 7 +- src/main.cpp | 5 +- src/platform/windows/nvidia.cpp | 2 +- src/platform/windows/version.rc.in | 53 +++++ src/ui/ui-element.hpp | 34 +++ 22 files changed, 493 insertions(+), 317 deletions(-) create mode 100644 src/platform/windows/version.rc.in create mode 100644 src/ui/ui-element.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b41e73..baf682a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,18 @@ cmake_minimum_required(VERSION 3.25) -option(VERSION_STRING "Project version string" "0.0.0") +option(APPLICATION_NAME "Application name" "Antkeeper") +option(APPLICATION_VERSION "Application version string" "0.0.0") +option(APPLICATION_AUTHOR "Application author" "C. J. Howard") -project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX) +# Slugify application name +string(TOLOWER ${APPLICATION_NAME} APPLICATION_SLUG) +string(REPLACE " " "-" APPLICATION_SLUG ${APPLICATION_SLUG}) + +project(${APPLICATION_SLUG} VERSION ${APPLICATION_VERSION} LANGUAGES CXX) + +set(APPLICATION_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) +set(APPLICATION_VERSION_MINOR ${PROJECT_VERSION_MINOR}) +set(APPLICATION_VERSION_PATCH ${PROJECT_VERSION_PATCH}) # Find dependency packages find_package(dr_wav REQUIRED CONFIG) @@ -54,19 +64,22 @@ if(MSVC) # Generate Windows icon resource file set(ICON_FILE "${PROJECT_SOURCE_DIR}/../antkeeper-data/src/icons/antkeeper.ico") if(EXISTS "${ICON_FILE}") - configure_file(${PROJECT_SOURCE_DIR}/src/platform/windows/icon.rc.in - ${PROJECT_BINARY_DIR}/src/platform/windows/icon.rc) + configure_file(${PROJECT_SOURCE_DIR}/src/platform/windows/icon.rc.in ${PROJECT_BINARY_DIR}/src/platform/windows/icon.rc) list(APPEND SOURCE_FILES "${PROJECT_BINARY_DIR}/src/platform/windows/icon.rc") endif() - # Make DPI-aware on Windows + # Generate Windows version-information resource file + configure_file(${PROJECT_SOURCE_DIR}/src/platform/windows/version.rc.in ${PROJECT_BINARY_DIR}/src/platform/windows/version.rc) + list(APPEND SOURCE_FILES "${PROJECT_BINARY_DIR}/src/platform/windows/version.rc") + + # Make executable DPI-aware on Windows list(APPEND SOURCE_FILES "${PROJECT_SOURCE_DIR}/src/platform/windows/dpi-aware.manifest") endif() # Add executable target -set(EXECUTABLE_TARGET ${PROJECT_NAME}-executable) +set(EXECUTABLE_TARGET ${APPLICATION_SLUG}-executable) add_executable(${EXECUTABLE_TARGET} ${SOURCE_FILES}) -set_target_properties(${EXECUTABLE_TARGET} PROPERTIES OUTPUT_NAME ${PROJECT_NAME}) +set_target_properties(${EXECUTABLE_TARGET} PROPERTIES OUTPUT_NAME ${APPLICATION_SLUG}) if(MSVC) # Select the static multithreaded MSVC runtime library diff --git a/src/app/sdl/sdl-input-manager.cpp b/src/app/sdl/sdl-input-manager.cpp index 90215af..f74b3a9 100644 --- a/src/app/sdl/sdl-input-manager.cpp +++ b/src/app/sdl/sdl-input-manager.cpp @@ -119,7 +119,7 @@ void sdl_input_manager::update() break; } - case SDL_KEYDOWN: + [[likely]] case SDL_KEYDOWN: case SDL_KEYUP: { // Get scancode of key @@ -153,16 +153,13 @@ void sdl_input_manager::update() modifier_keys |= input::modifier_key::alt_gr; } - // Determine if event was generated from a key repeat - const bool repeat = event.key.repeat > 0; - if (event.type == SDL_KEYDOWN) { - keyboard.press(scancode, repeat, modifier_keys); + keyboard.press(scancode, modifier_keys, (event.key.repeat > 0)); } else { - keyboard.release(scancode, repeat, modifier_keys); + keyboard.release(scancode, modifier_keys); } break; diff --git a/src/config.hpp.in b/src/config.hpp.in index 5ae32fe..7f183ae 100644 --- a/src/config.hpp.in +++ b/src/config.hpp.in @@ -36,19 +36,22 @@ namespace config { /// @{ /// Application name string. -constexpr const char* application_name = "@PROJECT_NAME@"; +inline constexpr const char* application_name = "@APPLICATION_NAME@"; + +/// Application slug string. +inline constexpr const char* application_slug = "@APPLICATION_SLUG@"; /// Application major version number. -constexpr int application_version_major = @PROJECT_VERSION_MAJOR@; +inline constexpr int application_version_major = @APPLICATION_VERSION_MAJOR@; /// Application minor version number. -constexpr int application_version_minor = @PROJECT_VERSION_MINOR@; +inline constexpr int application_version_minor = @APPLICATION_VERSION_MINOR@; /// Application patch version number. -constexpr int application_version_patch = @PROJECT_VERSION_PATCH@; +inline constexpr int application_version_patch = @APPLICATION_VERSION_PATCH@; /// Application version string ("`major.minor.patch`") -constexpr const char* application_version_string = "@PROJECT_VERSION@"; +inline constexpr const char* application_version_string = "@APPLICATION_VERSION@"; /// @} @@ -56,7 +59,7 @@ constexpr const char* application_version_string = "@PROJECT_VERSION@"; /// @{ /// Maximum number of debug logs to archive. -constexpr std::size_t debug_log_archive_capacity = 5; +inline constexpr std::size_t debug_log_archive_capacity = 5; /// @} @@ -64,64 +67,64 @@ constexpr std::size_t debug_log_archive_capacity = 5; /// @{ /// OpenGL major version number, used when creating OpenGL contexts. -constexpr int opengl_version_major = 3; +inline constexpr int opengl_version_major = 3; /// OpenGL minor version number, used when creating OpenGL contexts. -constexpr int opengl_version_minor = 3; +inline constexpr int opengl_version_minor = 3; /// Minimum number of bits in the red channel of the color attachment of the OpenGL default framebuffer. -constexpr int opengl_min_red_size = 8; +inline constexpr int opengl_min_red_size = 8; /// Minimum number of bits in the green channel of the color attachment of the OpenGL default framebuffer. -constexpr int opengl_min_green_size = 8; +inline constexpr int opengl_min_green_size = 8; /// Minimum number of bits in the blue channel of the color attachment of the OpenGL default framebuffer. -constexpr int opengl_min_blue_size = 8; +inline constexpr int opengl_min_blue_size = 8; /// Minimum number of bits in the alpha channel of the color attachment of the OpenGL default framebuffer. -constexpr int opengl_min_alpha_size = 0; +inline constexpr int opengl_min_alpha_size = 0; /// Minimum number of bits in the depth attachment, if any, of the OpenGL default framebuffer. -constexpr int opengl_min_depth_size = 0; +inline constexpr int opengl_min_depth_size = 0; /// Minimum number of bits in the stencil attachment, if any, of the OpenGL default framebuffer. -constexpr int opengl_min_stencil_size = 0; +inline constexpr int opengl_min_stencil_size = 0; /// @} -constexpr math::vector global_forward = {0.0f, 0.0f, -1.0f}; -constexpr math::vector global_up = {0.0f, 1.0f, 0.0f}; -constexpr math::vector global_right = {1.0f, 0.0f, 0.0f}; +inline constexpr math::vector global_forward = {0.0f, 0.0f, -1.0f}; +inline constexpr math::vector global_up = {0.0f, 1.0f, 0.0f}; +inline constexpr math::vector global_right = {1.0f, 0.0f, 0.0f}; /// Duration of the menu fade in animation, in seconds. -constexpr float menu_fade_in_duration = 0.25f; +inline constexpr float menu_fade_in_duration = 0.25f; /// Duration of the menu fade out animation, in seconds. -constexpr float menu_fade_out_duration = 0.125f; +inline constexpr float menu_fade_out_duration = 0.125f; /// Padding of the a menu item mouseover bounds, as a percentage of the font size. -constexpr float menu_mouseover_padding = 0.1f; +inline constexpr float menu_mouseover_padding = 0.1f; /// Opacity of the menu background. -constexpr float menu_bg_opacity = 2.0f / 4.0f; +inline constexpr float menu_bg_opacity = 2.0f / 4.0f; /// RGBA color of active menu items. -constexpr math::vector menu_active_color{1.0f, 1.0f, 1.0f, 1.0f}; +inline constexpr math::vector menu_active_color{1.0f, 1.0f, 1.0f, 1.0f}; /// RGBA color of inactive menu items. -constexpr math::vector menu_inactive_color{1.0f, 1.0f, 1.0f, 0.5f}; +inline constexpr math::vector menu_inactive_color{1.0f, 1.0f, 1.0f, 0.5f}; /// Duration of the title screen fade in, in seconds. -constexpr float title_fade_in_duration = 1.0f; +inline constexpr float title_fade_in_duration = 1.0f; /// Duration of the fade out when quitting the game or returning to the main menu, in seconds. -constexpr float quit_fade_out_duration = 0.5f; +inline constexpr float quit_fade_out_duration = 0.5f; /// Duration of the fade out when a new colony is started, in seconds. -constexpr float new_colony_fade_out_duration = 1.0f; +inline constexpr float new_colony_fade_out_duration = 1.0f; /// Duration of the nuptial flight fade in, in seconds. -constexpr float nuptial_flight_fade_in_duration = 5.0f; +inline constexpr float nuptial_flight_fade_in_duration = 5.0f; #define MATERIAL_PASS_MAX_AMBIENT_LIGHT_COUNT 1 #define MATERIAL_PASS_MAX_POINT_LIGHT_COUNT 1 diff --git a/src/debug/console.cpp b/src/debug/console.cpp index b5109b1..d5fef6d 100644 --- a/src/debug/console.cpp +++ b/src/debug/console.cpp @@ -47,5 +47,12 @@ void disable_vt100() #endif } +void enable_utf8() +{ + #if defined(_WIN32) + SetConsoleOutputCP(CP_UTF8); + #endif +} + } // namespace console } // namespace debug diff --git a/src/debug/console.hpp b/src/debug/console.hpp index ef42254..1d2fa12 100644 --- a/src/debug/console.hpp +++ b/src/debug/console.hpp @@ -33,6 +33,9 @@ void enable_vt100(); /// Disables VT100 virtual terminal sequences. void disable_vt100(); +/// Enables UTF-8 output. +void enable_utf8(); + } // namespace console } // namespace debug diff --git a/src/event/subscription.hpp b/src/event/subscription.hpp index 71911d3..aea7068 100644 --- a/src/event/subscription.hpp +++ b/src/event/subscription.hpp @@ -26,7 +26,7 @@ namespace event { /** - * Subscription object which unsubscribes on destruction. + * Unsubscribes a subscriber on destruction. */ class subscription { diff --git a/src/game/context.hpp b/src/game/context.hpp index 4b3c0c9..7758a1a 100644 --- a/src/game/context.hpp +++ b/src/game/context.hpp @@ -21,8 +21,8 @@ #define ANTKEEPER_GAME_CONTEXT_HPP #include "animation/tween.hpp" -#include "app/window-manager.hpp" #include "app/input-manager.hpp" +#include "app/window-manager.hpp" #include "debug/performance-sampler.hpp" #include "entity/id.hpp" #include "entity/registry.hpp" @@ -36,6 +36,8 @@ #include "gl/texture-2d.hpp" #include "gl/vertex-array.hpp" #include "gl/vertex-buffer.hpp" +#include "i18n/string-map.hpp" +#include "i18n/string-table.hpp" #include "input/control-map.hpp" #include "input/control.hpp" #include "input/mapper.hpp" @@ -44,13 +46,11 @@ #include "render/material.hpp" #include "resources/json.hpp" #include "scene/scene.hpp" -#include "utility/state-machine.hpp" #include "type/bitmap-font.hpp" #include "type/typeface.hpp" #include "utility/dict.hpp" #include "utility/fundamental-types.hpp" -#include "i18n/string-table.hpp" -#include "i18n/string-map.hpp" +#include "utility/state-machine.hpp" #include #include #include @@ -134,25 +134,24 @@ struct context // Resource management and paths resource_manager* resource_manager; - std::filesystem::path data_path; + std::filesystem::path data_package_path; + std::filesystem::path mods_path; std::filesystem::path local_config_path; std::filesystem::path shared_config_path; - std::filesystem::path mods_path; std::filesystem::path saves_path; std::filesystem::path screenshots_path; std::filesystem::path controls_path; - std::filesystem::path data_package_path; // Persistent settings dict* settings; - // Window management and event handling + // Window management and window event handling app::window_manager* window_manager; app::window* window; bool closed; std::shared_ptr<::event::subscription> window_closed_subscription; - // Input management and event handling + // Input management and input event handling app::input_manager* input_manager; std::shared_ptr<::event::subscription> application_quit_subscription; @@ -171,6 +170,22 @@ struct context render::material menu_font_material; render::material title_font_material; + // Control maps, controls, and control event handling + input::mapper input_mapper; + input::control_map window_controls; + input::control fullscreen_control; + input::control screenshot_control; + std::forward_list> control_subscriptions; + input::control_map menu_controls; + input::control menu_up_control; + input::control menu_down_control; + input::control menu_left_control; + input::control menu_right_control; + input::control menu_select_control; + input::control menu_back_control; + input::control menu_modifier_control; + std::forward_list> menu_control_subscriptions; + // Hierarchichal state machine hsm::state_machine state_machine; std::function resume_callback; @@ -185,22 +200,6 @@ struct context // Parallel processes std::unordered_map> processes; - // Controls - input::mapper input_mapper; - std::forward_list> control_subscriptions; - - input::control_map window_controls; - input::control fullscreen_control; - input::control screenshot_control; - - input::control_map menu_controls; - input::control menu_up_control; - input::control menu_down_control; - input::control menu_left_control; - input::control menu_right_control; - input::control menu_select_control; - input::control menu_back_control; - input::control menu_modifier_control; bool mouse_look; diff --git a/src/game/menu.cpp b/src/game/menu.cpp index 19a5e3f..a8c436f 100644 --- a/src/game/menu.cpp +++ b/src/game/menu.cpp @@ -295,186 +295,237 @@ void fade_out_bg(game::context& ctx) void setup_controls(game::context& ctx) { - /* - ctx.controls["menu_up"]->set_activated_callback + // Map menu controls + ctx.menu_controls.add_mapping(ctx.menu_up_control, input::key_mapping(nullptr, input::scancode::up, true)); + ctx.menu_controls.add_mapping(ctx.menu_up_control, input::key_mapping(nullptr, input::scancode::w, true)); + ctx.menu_controls.add_mapping(ctx.menu_up_control, input::key_mapping(nullptr, input::scancode::i, true)); + ctx.menu_controls.add_mapping(ctx.menu_down_control, input::key_mapping(nullptr, input::scancode::down, true)); + ctx.menu_controls.add_mapping(ctx.menu_down_control, input::key_mapping(nullptr, input::scancode::s, true)); + ctx.menu_controls.add_mapping(ctx.menu_down_control, input::key_mapping(nullptr, input::scancode::k, true)); + ctx.menu_controls.add_mapping(ctx.menu_left_control, input::key_mapping(nullptr, input::scancode::left, true)); + ctx.menu_controls.add_mapping(ctx.menu_left_control, input::key_mapping(nullptr, input::scancode::a, true)); + ctx.menu_controls.add_mapping(ctx.menu_left_control, input::key_mapping(nullptr, input::scancode::j, true)); + ctx.menu_controls.add_mapping(ctx.menu_right_control, input::key_mapping(nullptr, input::scancode::right, true)); + ctx.menu_controls.add_mapping(ctx.menu_right_control, input::key_mapping(nullptr, input::scancode::d, true)); + ctx.menu_controls.add_mapping(ctx.menu_right_control, input::key_mapping(nullptr, input::scancode::l, true)); + ctx.menu_controls.add_mapping(ctx.menu_select_control, input::key_mapping(nullptr, input::scancode::enter, false)); + ctx.menu_controls.add_mapping(ctx.menu_select_control, input::key_mapping(nullptr, input::scancode::space, false)); + ctx.menu_controls.add_mapping(ctx.menu_select_control, input::key_mapping(nullptr, input::scancode::e, false)); + ctx.menu_controls.add_mapping(ctx.menu_back_control, input::key_mapping(nullptr, input::scancode::escape, false)); + ctx.menu_controls.add_mapping(ctx.menu_back_control, input::key_mapping(nullptr, input::scancode::backspace, false)); + ctx.menu_controls.add_mapping(ctx.menu_back_control, input::key_mapping(nullptr, input::scancode::q, false)); + ctx.menu_controls.add_mapping(ctx.menu_modifier_control, input::key_mapping(nullptr, input::scancode::left_shift, false)); + ctx.menu_controls.add_mapping(ctx.menu_modifier_control, input::key_mapping(nullptr, input::scancode::right_shift, false)); + + // Setup menu control callbacks + ctx.menu_control_subscriptions.emplace_front ( - [&ctx]() - { - --(*ctx.menu_item_index); - if (*ctx.menu_item_index < 0) - *ctx.menu_item_index = ctx.menu_item_texts.size() - 1; - - update_text_color(ctx); - } + ctx.menu_up_control.get_activated_channel().subscribe + ( + [&ctx](const auto& event) + { + --(*ctx.menu_item_index); + if (*ctx.menu_item_index < 0) + *ctx.menu_item_index = static_cast(ctx.menu_item_texts.size()) - 1; + + update_text_color(ctx); + } + ) ); - ctx.controls["menu_down"]->set_activated_callback + ctx.menu_control_subscriptions.emplace_front ( - [&ctx]() - { - ++(*ctx.menu_item_index); - if (*ctx.menu_item_index >= ctx.menu_item_texts.size()) - *ctx.menu_item_index = 0; - - update_text_color(ctx); - } + ctx.menu_down_control.get_activated_channel().subscribe + ( + [&ctx](const auto& event) + { + ++(*ctx.menu_item_index); + if (*ctx.menu_item_index >= ctx.menu_item_texts.size()) + *ctx.menu_item_index = 0; + + update_text_color(ctx); + } + ) ); - ctx.controls["menu_left"]->set_activated_callback + ctx.menu_control_subscriptions.emplace_front ( - [&ctx]() - { - auto callback = ctx.menu_left_callbacks[*ctx.menu_item_index]; - if (callback != nullptr) - callback(); - } + ctx.menu_left_control.get_activated_channel().subscribe + ( + [&ctx](const auto& event) + { + auto callback = ctx.menu_left_callbacks[*ctx.menu_item_index]; + if (callback != nullptr) + callback(); + } + ) ); - ctx.controls["menu_right"]->set_activated_callback + ctx.menu_control_subscriptions.emplace_front ( - [&ctx]() - { - auto callback = ctx.menu_right_callbacks[*ctx.menu_item_index]; - if (callback != nullptr) - callback(); - } + ctx.menu_right_control.get_activated_channel().subscribe + ( + [&ctx](const auto& event) + { + auto callback = ctx.menu_right_callbacks[*ctx.menu_item_index]; + if (callback != nullptr) + callback(); + } + ) ); - ctx.controls["menu_select"]->set_activated_callback + ctx.menu_control_subscriptions.emplace_front ( - [&ctx]() - { - auto callback = ctx.menu_select_callbacks[*ctx.menu_item_index]; - if (callback != nullptr) - callback(); - } + ctx.menu_select_control.get_activated_channel().subscribe + ( + [&ctx](const auto& event) + { + auto callback = ctx.menu_select_callbacks[*ctx.menu_item_index]; + if (callback != nullptr) + callback(); + } + ) ); - ctx.controls["menu_back"]->set_activated_callback + ctx.menu_control_subscriptions.emplace_front ( - [&ctx]() - { - if (ctx.menu_back_callback != nullptr) - ctx.menu_back_callback(); - } + ctx.menu_back_control.get_activated_channel().subscribe + ( + [&ctx](const auto& event) + { + if (ctx.menu_back_callback != nullptr) + ctx.menu_back_callback(); + } + ) ); - ctx.menu_mouse_tracker->set_mouse_moved_callback + // Setup mouse event callbacks + ctx.menu_control_subscriptions.emplace_front ( - [&ctx](const mouse_moved_event& event) - { - const float padding = config::menu_mouseover_padding * ctx.menu_font.get_font_metrics().size; - - for (std::size_t i = 0; i < ctx.menu_item_texts.size(); ++i) + ctx.input_manager->get_event_queue().subscribe + ( + [&ctx](const auto& event) { - auto [name, value] = ctx.menu_item_texts[i]; - - const auto& name_bounds = static_cast&>(name->get_world_bounds()); - float min_x = name_bounds.min_point.x(); - float min_y = name_bounds.min_point.y(); - float max_x = name_bounds.max_point.x(); - float max_y = name_bounds.max_point.y(); - if (value) - { - const auto& value_bounds = static_cast&>(value->get_world_bounds()); - min_x = std::min(min_x, value_bounds.min_point.x()); - min_y = std::min(min_y, value_bounds.min_point.y()); - max_x = std::max(max_x, value_bounds.max_point.x()); - max_y = std::max(max_y, value_bounds.max_point.y()); - } - - min_x -= padding; - min_y -= padding; - max_x += padding; - max_y += padding; - - const auto& viewport = ctx.window->get_viewport_size(); - const float x = static_cast(event.x - viewport[0] / 2); - const float y = static_cast((viewport[1] - event.y + 1) - viewport[1] / 2); - - if (x >= min_x && x <= max_x) + const float padding = config::menu_mouseover_padding * ctx.menu_font.get_font_metrics().size; + + for (std::size_t i = 0; i < ctx.menu_item_texts.size(); ++i) { - if (y >= min_y && y <= max_y) + auto [name, value] = ctx.menu_item_texts[i]; + + const auto& name_bounds = static_cast&>(name->get_world_bounds()); + float min_x = name_bounds.min_point.x(); + float min_y = name_bounds.min_point.y(); + float max_x = name_bounds.max_point.x(); + float max_y = name_bounds.max_point.y(); + if (value) { - *ctx.menu_item_index = i; - update_text_color(ctx); - break; + const auto& value_bounds = static_cast&>(value->get_world_bounds()); + min_x = std::min(min_x, value_bounds.min_point.x()); + min_y = std::min(min_y, value_bounds.min_point.y()); + max_x = std::max(max_x, value_bounds.max_point.x()); + max_y = std::max(max_y, value_bounds.max_point.y()); + } + + min_x -= padding; + min_y -= padding; + max_x += padding; + max_y += padding; + + const auto& viewport = ctx.window->get_viewport_size(); + const float x = static_cast(event.position.x() - viewport[0] / 2); + const float y = static_cast((viewport[1] - event.position.y() + 1) - viewport[1] / 2); + + if (x >= min_x && x <= max_x) + { + if (y >= min_y && y <= max_y) + { + *ctx.menu_item_index = i; + update_text_color(ctx); + break; + } } } } - } + ) ); - - ctx.menu_mouse_tracker->set_mouse_button_pressed_callback + ctx.menu_control_subscriptions.emplace_front ( - [&ctx](const mouse_button_pressed_event& event) - { - const float padding = config::menu_mouseover_padding * ctx.menu_font.get_font_metrics().size; - - for (std::size_t i = 0; i < ctx.menu_item_texts.size(); ++i) + ctx.input_manager->get_event_queue().subscribe + ( + [&ctx](const auto& event) { - auto [name, value] = ctx.menu_item_texts[i]; + const float padding = config::menu_mouseover_padding * ctx.menu_font.get_font_metrics().size; - const auto& name_bounds = static_cast&>(name->get_world_bounds()); - float min_x = name_bounds.min_point.x(); - float min_y = name_bounds.min_point.y(); - float max_x = name_bounds.max_point.x(); - float max_y = name_bounds.max_point.y(); - if (value) + for (std::size_t i = 0; i < ctx.menu_item_texts.size(); ++i) { - const auto& value_bounds = static_cast&>(value->get_world_bounds()); - min_x = std::min(min_x, value_bounds.min_point.x()); - min_y = std::min(min_y, value_bounds.min_point.y()); - max_x = std::max(max_x, value_bounds.max_point.x()); - max_y = std::max(max_y, value_bounds.max_point.y()); - } - - min_x -= padding; - min_y -= padding; - max_x += padding; - max_y += padding; - - const auto& viewport = ctx.window->get_viewport_size(); - const float x = static_cast(event.x - viewport[0] / 2); - const float y = static_cast((viewport[1] - event.y + 1) - viewport[1] / 2); - - if (x >= min_x && x <= max_x) - { - if (y >= min_y && y <= max_y) + auto [name, value] = ctx.menu_item_texts[i]; + + const auto& name_bounds = static_cast&>(name->get_world_bounds()); + float min_x = name_bounds.min_point.x(); + float min_y = name_bounds.min_point.y(); + float max_x = name_bounds.max_point.x(); + float max_y = name_bounds.max_point.y(); + if (value) { - *ctx.menu_item_index = i; - update_text_color(ctx); - - if (event.button == 1) - { - auto callback = ctx.menu_select_callbacks[i]; - if (callback) - callback(); - } - else if (event.button == 3) + const auto& value_bounds = static_cast&>(value->get_world_bounds()); + min_x = std::min(min_x, value_bounds.min_point.x()); + min_y = std::min(min_y, value_bounds.min_point.y()); + max_x = std::max(max_x, value_bounds.max_point.x()); + max_y = std::max(max_y, value_bounds.max_point.y()); + } + + min_x -= padding; + min_y -= padding; + max_x += padding; + max_y += padding; + + const auto& viewport = ctx.window->get_viewport_size(); + const float x = static_cast(event.position.x() - viewport[0] / 2); + const float y = static_cast((viewport[1] - event.position.y() + 1) - viewport[1] / 2); + + if (x >= min_x && x <= max_x) + { + if (y >= min_y && y <= max_y) { - auto callback = ctx.menu_left_callbacks[i]; - if (callback) - callback(); + *ctx.menu_item_index = i; + update_text_color(ctx); + + //if (event.button == input::mouse_button::left) + { + auto callback = ctx.menu_select_callbacks[i]; + if (callback) + callback(); + } + // else if (event.button == input::mouse_button::right) + // { + // auto callback = ctx.menu_left_callbacks[i]; + // if (callback) + // callback(); + // } + + return; } - - return; } } } - } + ) ); - */ } void clear_controls(game::context& ctx) { - /* - ctx.controls["menu_up"]->set_activated_callback(nullptr); - ctx.controls["menu_down"]->set_activated_callback(nullptr); - ctx.controls["menu_left"]->set_activated_callback(nullptr); - ctx.controls["menu_right"]->set_activated_callback(nullptr); - ctx.controls["menu_select"]->set_activated_callback(nullptr); - ctx.controls["menu_back"]->set_activated_callback(nullptr); + // Unsubscribe menu control event callbacks + ctx.menu_control_subscriptions.clear(); - ctx.menu_mouse_tracker->set_mouse_moved_callback(nullptr); - ctx.menu_mouse_tracker->set_mouse_button_pressed_callback(nullptr); - */ + // Clear menu control mappings + ctx.menu_controls.remove_mappings(); +} + +void enable_controls(game::context& ctx) +{ + // Enable menu controls + ctx.menu_controls.connect(ctx.input_manager->get_event_queue()); +} + +void disable_controls(game::context& ctx) +{ + // Disable menu controls + ctx.menu_controls.disconnect(); } } // namespace menu diff --git a/src/game/menu.hpp b/src/game/menu.hpp index 183efd3..714ad73 100644 --- a/src/game/menu.hpp +++ b/src/game/menu.hpp @@ -27,14 +27,18 @@ namespace menu { void init_menu_item_index(game::context& ctx, const std::string& menu_name); void setup_controls(game::context& ctx); +void clear_controls(game::context& ctx); +void enable_controls(game::context& ctx); +void disable_controls(game::context& ctx); void setup_animations(game::context& ctx); -void clear_controls(game::context& ctx); void clear_callbacks(game::context& ctx); void remove_text_from_ui(game::context& ctx); void delete_text(game::context& ctx); void delete_animations(game::context& ctx); + + void fade_in(game::context& ctx, const std::function& end_callback); void fade_out(game::context& ctx, const std::function& end_callback); diff --git a/src/game/state/boot.cpp b/src/game/state/boot.cpp index 30a2f59..cfa44a1 100644 --- a/src/game/state/boot.cpp +++ b/src/game/state/boot.cpp @@ -105,7 +105,7 @@ using namespace hash::literals; namespace game { namespace state { -boot::boot(game::context& ctx, int argc, char** argv): +boot::boot(game::context& ctx, int argc, const char* const* argv): game::state::base(ctx) { // Boot process @@ -172,14 +172,20 @@ boot::~boot() debug::log::trace("Boot down complete"); } -void boot::parse_options(int argc, char** argv) +void boot::parse_options(int argc, const char* const* argv) { + if (argc <= 1) + { + // No command-line options specified + return; + } + debug::log::trace("Parsing command-line options..."); // Parse command-line options with cxxopts try { - cxxopts::Options options(config::application_name, "Ant colony simulation game"); + cxxopts::Options options(config::application_name, config::application_name); options.add_options() ("c,continue", "Continues from the last save") ("d,data", "Sets the data package path", cxxopts::value()) @@ -233,7 +239,7 @@ void boot::parse_options(int argc, char** argv) ctx.option_v_sync = result["v-sync"].as(); } - // --window + // --windowed if (result.count("windowed")) { ctx.option_windowed = true; @@ -252,19 +258,39 @@ void boot::setup_resources() // Allocate resource manager ctx.resource_manager = new resource_manager(); - // Detect paths - ctx.data_path = get_executable_data_path(); + // Get executable data path + const auto data_path = get_executable_data_path(); + + // Determine data package path + if (ctx.option_data) + { + // Handle command-line data path option + ctx.data_package_path = ctx.option_data.value(); + if (ctx.data_package_path.is_relative()) + { + ctx.data_package_path = data_path / ctx.data_package_path; + } + } + else + { + ctx.data_package_path = data_path / (config::application_slug + std::string("-data.zip")); + } + + // Determine mods path + ctx.mods_path = data_path / "mods"; + + // Determine config paths ctx.local_config_path = get_local_config_path() / config::application_name; ctx.shared_config_path = get_shared_config_path() / config::application_name; - ctx.mods_path = ctx.data_path / "mods"; ctx.saves_path = ctx.shared_config_path / "saves"; ctx.screenshots_path = ctx.shared_config_path / "gallery"; ctx.controls_path = ctx.shared_config_path / "controls"; - // Log resource paths - debug::log::info("Data path: \"{}\"", ctx.data_path.string()); + // Log paths + debug::log::info("Data package path: \"{}\"", ctx.data_package_path.string()); debug::log::info("Local config path: \"{}\"", ctx.local_config_path.string()); debug::log::info("Shared config path: \"{}\"", ctx.shared_config_path.string()); + debug::log::info("Mods path: \"{}\"", ctx.mods_path.string()); // Set write dir ctx.resource_manager->set_write_dir(ctx.shared_config_path); @@ -273,26 +299,22 @@ void boot::setup_resources() std::vector config_paths; config_paths.push_back(ctx.local_config_path); config_paths.push_back(ctx.shared_config_path); - //config_paths.push_back(ctx.mods_path); config_paths.push_back(ctx.saves_path); config_paths.push_back(ctx.screenshots_path); config_paths.push_back(ctx.controls_path); - for (const std::filesystem::path& path: config_paths) + for (const auto& path: config_paths) { - if (!std::filesystem::exists(path)) + try { - const std::string path_string = path.string(); - - debug::log::trace("Creating directory \"{}\"...", path_string); if (std::filesystem::create_directories(path)) { - debug::log::trace("Created directory \"{}\"", path_string); - } - else - { - debug::log::error("Failed to create directory \"{}\"", path_string); + debug::log::info("Created directory \"{}\"", path.string()); } } + catch (const std::filesystem::filesystem_error& e) + { + debug::log::error("Failed to create directory \"{}\": {}", path.string(), e.what()); + } } // Scan for mods @@ -309,22 +331,7 @@ void boot::setup_resources() } } - // Determine data package path - if (ctx.option_data) - { - // Handle command-line data package path option - ctx.data_package_path = ctx.option_data.value(); - if (ctx.data_package_path.is_relative()) - { - ctx.data_package_path = ctx.data_path / ctx.data_package_path; - } - } - else - { - ctx.data_package_path = ctx.data_path / "antkeeper.dat"; - } - - // Mount mods + // Mount mod paths for (const std::filesystem::path& mod_path: mod_paths) { ctx.resource_manager->mount(ctx.mods_path / mod_path); @@ -334,7 +341,7 @@ void boot::setup_resources() ctx.resource_manager->mount(ctx.local_config_path); ctx.resource_manager->mount(ctx.shared_config_path); - // Mount data package + // Mount data package path ctx.resource_manager->mount(ctx.data_package_path); // Include resource search paths in order of priority @@ -1155,6 +1162,9 @@ void boot::setup_controls() { debug::log::error("Failed to load controls"); } + + // Setup menu controls + game::menu::setup_controls(ctx); } void boot::setup_ui() diff --git a/src/game/state/boot.hpp b/src/game/state/boot.hpp index c57e1c5..1e336bc 100644 --- a/src/game/state/boot.hpp +++ b/src/game/state/boot.hpp @@ -40,7 +40,7 @@ public: * @param argc Command line argument count. * @param argv Command line argument vector. */ - boot(game::context& ctx, int argc, char** argv); + boot(game::context& ctx, int argc, const char* const* argv); /** * Boots down the game. @@ -48,7 +48,7 @@ public: virtual ~boot(); private: - void parse_options(int argc, char** argv); + void parse_options(int argc, const char* const* argv); void setup_resources(); void load_settings(); void setup_window(); diff --git a/src/game/state/extras-menu.cpp b/src/game/state/extras-menu.cpp index 32c4060..70aae98 100644 --- a/src/game/state/extras-menu.cpp +++ b/src/game/state/extras-menu.cpp @@ -62,8 +62,8 @@ extras_menu::extras_menu(game::context& ctx): // Construct menu item callbacks auto select_credits_callback = [&ctx]() { - // Disable controls - game::menu::clear_controls(ctx); + // Queue disable menu controls + ctx.function_queue.push(std::bind(game::menu::disable_controls, std::ref(ctx))); game::menu::fade_out ( @@ -84,8 +84,8 @@ extras_menu::extras_menu(game::context& ctx): }; auto select_back_callback = [&ctx]() { - // Disable controls - game::menu::clear_controls(ctx); + // Queue disable menu controls + ctx.function_queue.push(std::bind(game::menu::disable_controls, std::ref(ctx))); game::menu::fade_out ( @@ -120,12 +120,12 @@ extras_menu::extras_menu(game::context& ctx): // Set menu back callback ctx.menu_back_callback = select_back_callback; - // Queue menu control setup - ctx.function_queue.push(std::bind(game::menu::setup_controls, std::ref(ctx))); - // Fade in menu game::menu::fade_in(ctx, nullptr); + // Queue enable menu controls + ctx.function_queue.push(std::bind(game::menu::enable_controls, std::ref(ctx))); + debug::log::trace("Entered extras menu state"); } @@ -134,7 +134,6 @@ extras_menu::~extras_menu() debug::log::trace("Exiting extras menu state..."); // Destruct menu - game::menu::clear_controls(ctx); game::menu::clear_callbacks(ctx); game::menu::delete_animations(ctx); game::menu::remove_text_from_ui(ctx); diff --git a/src/game/state/main-menu.cpp b/src/game/state/main-menu.cpp index b02b614..91a9db7 100644 --- a/src/game/state/main-menu.cpp +++ b/src/game/state/main-menu.cpp @@ -18,31 +18,31 @@ */ #include "game/state/main-menu.hpp" -#include "game/state/options-menu.hpp" -#include "game/state/extras-menu.hpp" -#include "game/state/nuptial-flight.hpp" -#include "game/world.hpp" -#include "game/menu.hpp" -#include "game/ecoregion.hpp" -#include "game/ant/swarm.hpp" -#include "render/passes/clear-pass.hpp" -#include "render/passes/ground-pass.hpp" -#include "render/passes/sky-pass.hpp" -#include "resources/resource-manager.hpp" -#include "render/model.hpp" #include "animation/animation.hpp" #include "animation/animator.hpp" -#include "animation/screen-transition.hpp" #include "animation/ease.hpp" +#include "animation/screen-transition.hpp" #include "config.hpp" -#include "physics/light/exposure.hpp" +#include "game/ant/swarm.hpp" #include "game/component/model.hpp" #include "game/component/steering.hpp" #include "game/component/transform.hpp" -#include "math/projection.hpp" -#include +#include "game/ecoregion.hpp" +#include "game/menu.hpp" +#include "game/state/extras-menu.hpp" +#include "game/state/nuptial-flight.hpp" +#include "game/state/options-menu.hpp" #include "game/strings.hpp" +#include "game/world.hpp" +#include "math/projection.hpp" +#include "physics/light/exposure.hpp" +#include "render/model.hpp" +#include "render/passes/clear-pass.hpp" +#include "render/passes/ground-pass.hpp" +#include "render/passes/sky-pass.hpp" +#include "resources/resource-manager.hpp" #include "utility/hash/fnv1a.hpp" +#include using namespace hash::literals; @@ -116,9 +116,8 @@ main_menu::main_menu(game::context& ctx, bool fade_in): auto select_start_callback = [this, &ctx]() { - // Disable controls and menu callbacks - game::menu::clear_controls(ctx); - game::menu::clear_callbacks(ctx); + // Disable menu controls + ctx.function_queue.push(std::bind(game::menu::disable_controls, std::ref(ctx))); // Create change state function auto change_state_nuptial_flight = [&ctx]() @@ -146,7 +145,8 @@ main_menu::main_menu(game::context& ctx, bool fade_in): }; auto select_options_callback = [this, &ctx]() { - game::menu::clear_controls(ctx); + // Disable menu controls + ctx.function_queue.push(std::bind(game::menu::disable_controls, std::ref(ctx))); // Fade out title this->fade_out_title(); @@ -171,8 +171,8 @@ main_menu::main_menu(game::context& ctx, bool fade_in): }; auto select_extras_callback = [this, &ctx]() { - // Disable controls - game::menu::clear_controls(ctx); + // Disable menu controls + ctx.function_queue.push(std::bind(game::menu::disable_controls, std::ref(ctx))); // Fade out title this->fade_out_title(); @@ -197,8 +197,8 @@ main_menu::main_menu(game::context& ctx, bool fade_in): }; auto select_quit_callback = [this, &ctx]() { - // Disable controls - game::menu::clear_controls(ctx); + // Disable menu controls + ctx.function_queue.push(std::bind(game::menu::disable_controls, std::ref(ctx))); // Fade out title this->fade_out_title(); @@ -231,9 +231,6 @@ main_menu::main_menu(game::context& ctx, bool fade_in): // Set menu back callback ctx.menu_back_callback = select_quit_callback; - // Queue menu control setup - ctx.function_queue.push(std::bind(game::menu::setup_controls, std::ref(ctx))); - if (fade_in) { // Fade in from black @@ -282,6 +279,9 @@ main_menu::main_menu(game::context& ctx, bool fade_in): //if (!ctx.menu_bg_billboard->is_active()) // game::menu::fade_in_bg(ctx); + // Queue enable menu controls + ctx.function_queue.push(std::bind(game::menu::enable_controls, std::ref(ctx))); + debug::log::trace("Entered main menu state"); } @@ -290,7 +290,6 @@ main_menu::~main_menu() debug::log::trace("Exiting main menu state..."); // Destruct menu - game::menu::clear_controls(ctx); game::menu::clear_callbacks(ctx); game::menu::delete_animations(ctx); game::menu::remove_text_from_ui(ctx); diff --git a/src/game/state/options-menu.cpp b/src/game/state/options-menu.cpp index 8221e8b..501ae0b 100644 --- a/src/game/state/options-menu.cpp +++ b/src/game/state/options-menu.cpp @@ -77,8 +77,8 @@ options_menu::options_menu(game::context& ctx): // Construct menu item callbacks auto select_controls_callback = [&ctx]() { - // Disable controls - game::menu::clear_controls(ctx); + // Queue disable menu controls + ctx.function_queue.push(std::bind(game::menu::disable_controls, std::ref(ctx))); // Return to main menu game::menu::fade_out @@ -100,8 +100,8 @@ options_menu::options_menu(game::context& ctx): }; auto select_graphics_callback = [&ctx]() { - // Disable controls - game::menu::clear_controls(ctx); + // Queue disable menu controls + ctx.function_queue.push(std::bind(game::menu::disable_controls, std::ref(ctx))); // Return to main menu game::menu::fade_out @@ -123,8 +123,8 @@ options_menu::options_menu(game::context& ctx): }; auto select_sound_callback = [&ctx]() { - // Disable controls - game::menu::clear_controls(ctx); + // Queue disable menu controls + ctx.function_queue.push(std::bind(game::menu::disable_controls, std::ref(ctx))); // Return to main menu game::menu::fade_out @@ -146,8 +146,8 @@ options_menu::options_menu(game::context& ctx): }; auto select_language_callback = [&ctx]() { - // Disable controls - game::menu::clear_controls(ctx); + // Queue disable menu controls + ctx.function_queue.push(std::bind(game::menu::disable_controls, std::ref(ctx))); // Return to main menu game::menu::fade_out @@ -169,8 +169,8 @@ options_menu::options_menu(game::context& ctx): }; auto select_back_callback = [&ctx]() { - // Disable controls - game::menu::clear_controls(ctx); + // Queue disable menu controls + ctx.function_queue.push(std::bind(game::menu::disable_controls, std::ref(ctx))); // Save config //game::save::config(ctx); @@ -212,12 +212,12 @@ options_menu::options_menu(game::context& ctx): // Set menu back callback ctx.menu_back_callback = select_back_callback; - // Queue menu control setup - ctx.function_queue.push(std::bind(game::menu::setup_controls, std::ref(ctx))); - // Fade in menu game::menu::fade_in(ctx, nullptr); + // Queue enable menu controls + ctx.function_queue.push(std::bind(game::menu::enable_controls, std::ref(ctx))); + debug::log::trace("Entered options menu state"); } @@ -226,7 +226,6 @@ options_menu::~options_menu() debug::log::trace("Exiting options menu state..."); // Destruct menu - game::menu::clear_controls(ctx); game::menu::clear_callbacks(ctx); game::menu::delete_animations(ctx); game::menu::remove_text_from_ui(ctx); diff --git a/src/input/control-map.cpp b/src/input/control-map.cpp index 246df80..879dfd7 100644 --- a/src/input/control-map.cpp +++ b/src/input/control-map.cpp @@ -221,7 +221,15 @@ void control_map::handle_key_pressed(const key_pressed_event& event) if (mapping.scancode == event.scancode && (!mapping.keyboard || mapping.keyboard == event.keyboard)) { - control->evaluate(1.0f); + if (!event.repeat) + { + control->evaluate(1.0f); + } + else if (mapping.repeat) + { + control->evaluate(0.0f); + control->evaluate(1.0f); + } } } } diff --git a/src/input/input-events.hpp b/src/input/input-events.hpp index 73ffbbc..b618606 100644 --- a/src/input/input-events.hpp +++ b/src/input/input-events.hpp @@ -146,11 +146,11 @@ struct key_pressed_event /// Scancode of the key being pressed. scancode scancode; - /// `true` if the key press was generated by a key repeat, `false` otherwise. - bool repeat; - /// Bit mask containing the active modifier keys. std::uint16_t modifiers; + + /// `true` if the key press was generated by a key repeat, `false` otherwise. + bool repeat; }; /** @@ -164,9 +164,6 @@ struct key_released_event /// Scancode of the key being released. scancode scancode; - /// `true` if the key release was generated by a key repeat, `false` otherwise. - bool repeat; - /// Bit mask containing the active modifier keys. std::uint16_t modifiers; }; diff --git a/src/input/keyboard.cpp b/src/input/keyboard.cpp index f981cd7..bd0a275 100644 --- a/src/input/keyboard.cpp +++ b/src/input/keyboard.cpp @@ -22,14 +22,14 @@ namespace input { -void keyboard::press(scancode scancode, bool repeat, std::uint16_t modifiers) +void keyboard::press(scancode scancode, std::uint16_t modifiers, bool repeat) { - key_pressed_publisher.publish({this, scancode, repeat, modifiers}); + key_pressed_publisher.publish({this, scancode, modifiers, repeat}); } -void keyboard::release(scancode scancode, bool repeat, std::uint16_t modifiers) +void keyboard::release(scancode scancode, std::uint16_t modifiers) { - key_released_publisher.publish({this, scancode, repeat, modifiers}); + key_released_publisher.publish({this, scancode, modifiers}); } } // namespace input diff --git a/src/input/keyboard.hpp b/src/input/keyboard.hpp index 733a1ac..2b9bd07 100644 --- a/src/input/keyboard.hpp +++ b/src/input/keyboard.hpp @@ -46,19 +46,18 @@ public: * Simulates a key press. * * @param scancode Scancode of the key to press. - * @param repeat `true` if the key press is from a key repeat, `false` otherwise. * @param modifiers Bit mask containing the active modifier keys. + * @param repeat `true` if the key press is from a key repeat, `false` otherwise. */ - void press(scancode scancode, bool repeat = false, std::uint16_t modifiers = modifier_key::none); + void press(scancode scancode, std::uint16_t modifiers = modifier_key::none, bool repeat = false); /** * Simulates a key release. * * @param scancode Scancode of the key to release. - * @param repeat `true` if the key release is from a key repeat, `false` otherwise. * @param modifiers Bit mask containing the active modifier keys. */ - void release(scancode scancode, bool repeat = false, std::uint16_t modifiers = modifier_key::none); + void release(scancode scancode, std::uint16_t modifiers = modifier_key::none); /// Returns the channel through which key pressed events are published. [[nodiscard]] inline ::event::channel& get_key_pressed_channel() noexcept diff --git a/src/main.cpp b/src/main.cpp index 81e2c8e..4b83e02 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -37,7 +37,8 @@ int main(int argc, char* argv[]) // Get time at which the application launched const auto launch_time = std::chrono::system_clock::now(); - // Enable VT100 sequences in console for colored text + // Enable console UTF-8 output and VT100 sequences (for colored text) + debug::console::enable_utf8(); debug::console::enable_vt100(); // Subscribe log to cout function to message logged events @@ -141,7 +142,7 @@ int main(int argc, char* argv[]) { // Determine log filename const auto time = std::chrono::floor(launch_time); - const std::string log_filename = std::format("{0}-{1:%Y%m%d}T{1:%H%M%S}Z.log", config::application_name, time); + const std::string log_filename = std::format("{0}-{1:%Y%m%d}T{1:%H%M%S}Z.log", config::application_slug, time); // Open log file log_filepath = log_archive_path / log_filename; diff --git a/src/platform/windows/nvidia.cpp b/src/platform/windows/nvidia.cpp index a35feb8..900b3a5 100644 --- a/src/platform/windows/nvidia.cpp +++ b/src/platform/windows/nvidia.cpp @@ -22,6 +22,6 @@ extern "C" { - /// Direct Nvidia Optimus to use high-performance graphics + // Direct Nvidia Optimus to use high-performance graphics _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; } diff --git a/src/platform/windows/version.rc.in b/src/platform/windows/version.rc.in new file mode 100644 index 0000000..608af3a --- /dev/null +++ b/src/platform/windows/version.rc.in @@ -0,0 +1,53 @@ +#include + +#define VER_FILEVERSION @APPLICATION_VERSION_MAJOR@,@APPLICATION_VERSION_MINOR@,@APPLICATION_VERSION_PATCH@,0 +#define VER_PRODUCTVERSION VER_FILEVERSION +#if !defined(NDEBUG) + #define VER_FILEFLAGS (VS_FF_DEBUG | VS_FF_PRERELEASE) +#else + #define VER_FILEFLAGS 0 +#endif + +#define VER_COMMENTS_STR "" +#define VER_COMPANYNAME_STR "@APPLICATION_AUTHOR@" +#define VER_FILEDESCRIPTION_STR "@APPLICATION_NAME@" +#define VER_FILEVERSION_STR "@APPLICATION_VERSION@" +#define VER_INTERNALNAME_STR "@APPLICATION_SLUG@" +#define VER_LEGALCOPYRIGHT_STR "\251 @APPLICATION_AUTHOR@. All rights reserved." +#define VER_LEGALTRADEMARKS1_STR "" +#define VER_LEGALTRADEMARKS2_STR "" +#define VER_ORIGINALFILENAME_STR "@APPLICATION_SLUG@.exe" +#define VER_PRODUCTNAME_STR "@APPLICATION_NAME@" +#define VER_PRODUCTVERSION_STR VER_FILEVERSION_STR + +VS_VERSION_INFO VERSIONINFO +FILEVERSION VER_FILEVERSION +PRODUCTVERSION VER_PRODUCTVERSION +FILEFLAGSMASK VER_FILEFLAGS +FILEOS VOS__WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "Comments", VER_COMMENTS_STR + VALUE "CompanyName", VER_COMPANYNAME_STR + VALUE "FileDescription", VER_FILEDESCRIPTION_STR + VALUE "FileVersion", VER_FILEVERSION_STR + VALUE "InternalName", VER_INTERNALNAME_STR + VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR + VALUE "LegalTrademarks1", VER_LEGALTRADEMARKS1_STR + VALUE "LegalTrademarks2", VER_LEGALTRADEMARKS2_STR + VALUE "OriginalFilename", VER_ORIGINALFILENAME_STR + VALUE "ProductName", VER_PRODUCTNAME_STR + VALUE "ProductVersion", VER_PRODUCTVERSION_STR + END + END + + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1252 + END +END \ No newline at end of file diff --git a/src/ui/ui-element.hpp b/src/ui/ui-element.hpp new file mode 100644 index 0000000..9e0b23a --- /dev/null +++ b/src/ui/ui-element.hpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2023 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_UI_ELEMENT_HPP +#define ANTKEEPER_UI_ELEMENT_HPP + +namespace ui {} + +class element +{ +public: + +private: +}; + +} // namesoace ui + +#endif // ANTKEEPER_UI_ELEMENT_HPP