Browse Source

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.

master
C. J. Howard 1 year ago
parent
commit
f86fc143ff
22 changed files with 493 additions and 317 deletions
  1. +20
    -7
      CMakeLists.txt
  2. +3
    -6
      src/app/sdl/sdl-input-manager.cpp
  3. +30
    -27
      src/config.hpp.in
  4. +7
    -0
      src/debug/console.cpp
  5. +3
    -0
      src/debug/console.hpp
  6. +1
    -1
      src/event/subscription.hpp
  7. +24
    -25
      src/game/context.hpp
  8. +194
    -143
      src/game/menu.cpp
  9. +5
    -1
      src/game/menu.hpp
  10. +47
    -37
      src/game/state/boot.cpp
  11. +2
    -2
      src/game/state/boot.hpp
  12. +7
    -8
      src/game/state/extras-menu.cpp
  13. +27
    -28
      src/game/state/main-menu.cpp
  14. +13
    -14
      src/game/state/options-menu.cpp
  15. +9
    -1
      src/input/control-map.cpp
  16. +3
    -6
      src/input/input-events.hpp
  17. +4
    -4
      src/input/keyboard.cpp
  18. +3
    -4
      src/input/keyboard.hpp
  19. +3
    -2
      src/main.cpp
  20. +1
    -1
      src/platform/windows/nvidia.cpp
  21. +53
    -0
      src/platform/windows/version.rc.in
  22. +34
    -0
      src/ui/ui-element.hpp

+ 20
- 7
CMakeLists.txt View File

@ -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

+ 3
- 6
src/app/sdl/sdl-input-manager.cpp View File

@ -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;

+ 30
- 27
src/config.hpp.in View File

@ -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<float, 3> global_forward = {0.0f, 0.0f, -1.0f};
constexpr math::vector<float, 3> global_up = {0.0f, 1.0f, 0.0f};
constexpr math::vector<float, 3> global_right = {1.0f, 0.0f, 0.0f};
inline constexpr math::vector<float, 3> global_forward = {0.0f, 0.0f, -1.0f};
inline constexpr math::vector<float, 3> global_up = {0.0f, 1.0f, 0.0f};
inline constexpr math::vector<float, 3> 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<float, 4> menu_active_color{1.0f, 1.0f, 1.0f, 1.0f};
inline constexpr math::vector<float, 4> menu_active_color{1.0f, 1.0f, 1.0f, 1.0f};
/// RGBA color of inactive menu items.
constexpr math::vector<float, 4> menu_inactive_color{1.0f, 1.0f, 1.0f, 0.5f};
inline constexpr math::vector<float, 4> 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

+ 7
- 0
src/debug/console.cpp View File

@ -47,5 +47,12 @@ void disable_vt100()
#endif
}
void enable_utf8()
{
#if defined(_WIN32)
SetConsoleOutputCP(CP_UTF8);
#endif
}
} // namespace console
} // namespace debug

+ 3
- 0
src/debug/console.hpp View File

@ -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

+ 1
- 1
src/event/subscription.hpp View File

@ -26,7 +26,7 @@
namespace event {
/**
* Subscription object which unsubscribes on destruction.
* Unsubscribes a subscriber on destruction.
*/
class subscription
{

+ 24
- 25
src/game/context.hpp View File

@ -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 <AL/al.h>
#include <AL/alc.h>
#include <entt/entt.hpp>
@ -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<std::uint32_t>* 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<std::shared_ptr<::event::subscription>> 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<std::shared_ptr<::event::subscription>> menu_control_subscriptions;
// Hierarchichal state machine
hsm::state_machine<game::state::base> state_machine;
std::function<void()> resume_callback;
@ -185,22 +200,6 @@ struct context
// Parallel processes
std::unordered_map<std::string, std::function<void(double, double)>> processes;
// Controls
input::mapper input_mapper;
std::forward_list<std::shared_ptr<::event::subscription>> 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;

+ 194
- 143
src/game/menu.cpp View File

@ -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<int>(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<input::mouse_moved_event>
(
[&ctx](const auto& event)
{
auto [name, value] = ctx.menu_item_texts[i];
const auto& name_bounds = static_cast<const geom::aabb<float>&>(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<const geom::aabb<float>&>(value->get_world_bounds());
min_x = std::min<float>(min_x, value_bounds.min_point.x());
min_y = std::min<float>(min_y, value_bounds.min_point.y());
max_x = std::max<float>(max_x, value_bounds.max_point.x());
max_y = std::max<float>(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<float>(event.x - viewport[0] / 2);
const float y = static_cast<float>((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<const geom::aabb<float>&>(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<const geom::aabb<float>&>(value->get_world_bounds());
min_x = std::min<float>(min_x, value_bounds.min_point.x());
min_y = std::min<float>(min_y, value_bounds.min_point.y());
max_x = std::max<float>(max_x, value_bounds.max_point.x());
max_y = std::max<float>(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<float>(event.position.x() - viewport[0] / 2);
const float y = static_cast<float>((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<input::mouse_button_pressed_event>
(
[&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<const geom::aabb<float>&>(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<const geom::aabb<float>&>(value->get_world_bounds());
min_x = std::min<float>(min_x, value_bounds.min_point.x());
min_y = std::min<float>(min_y, value_bounds.min_point.y());
max_x = std::max<float>(max_x, value_bounds.max_point.x());
max_y = std::max<float>(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<float>(event.x - viewport[0] / 2);
const float y = static_cast<float>((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<const geom::aabb<float>&>(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<const geom::aabb<float>&>(value->get_world_bounds());
min_x = std::min<float>(min_x, value_bounds.min_point.x());
min_y = std::min<float>(min_y, value_bounds.min_point.y());
max_x = std::max<float>(max_x, value_bounds.max_point.x());
max_y = std::max<float>(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<float>(event.position.x() - viewport[0] / 2);
const float y = static_cast<float>((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

+ 5
- 1
src/game/menu.hpp View File

@ -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<void()>& end_callback);
void fade_out(game::context& ctx, const std::function<void()>& end_callback);

+ 47
- 37
src/game/state/boot.cpp View File

@ -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<std::string>())
@ -233,7 +239,7 @@ void boot::parse_options(int argc, char** argv)
ctx.option_v_sync = result["v-sync"].as<int>();
}
// --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<std::filesystem::path> 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()

+ 2
- 2
src/game/state/boot.hpp View File

@ -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();

+ 7
- 8
src/game/state/extras-menu.cpp View File

@ -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);

+ 27
- 28
src/game/state/main-menu.cpp View File

@ -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 <limits>
#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 <limits>
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);

+ 13
- 14
src/game/state/options-menu.cpp View File

@ -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);

+ 9
- 1
src/input/control-map.cpp View File

@ -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);
}
}
}
}

+ 3
- 6
src/input/input-events.hpp View File

@ -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;
};

+ 4
- 4
src/input/keyboard.cpp View File

@ -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

+ 3
- 4
src/input/keyboard.hpp View File

@ -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<key_pressed_event>& get_key_pressed_channel() noexcept

+ 3
- 2
src/main.cpp View File

@ -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<std::chrono::seconds>(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;

+ 1
- 1
src/platform/windows/nvidia.cpp View File

@ -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;
}

+ 53
- 0
src/platform/windows/version.rc.in View File

@ -0,0 +1,53 @@
#include <Winver.h>
#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

+ 34
- 0
src/ui/ui-element.hpp View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_UI_ELEMENT_HPP
#define ANTKEEPER_UI_ELEMENT_HPP
namespace ui {}
class element
{
public:
private:
};
} // namesoace ui
#endif // ANTKEEPER_UI_ELEMENT_HPP

Loading…
Cancel
Save