Browse Source

Add support for saving control profiles

master
C. J. Howard 1 year ago
parent
commit
52e54d5274
8 changed files with 239 additions and 34 deletions
  1. +0
    -1
      CMakeLists.txt
  2. +192
    -0
      src/game/controls.cpp
  3. +7
    -0
      src/game/controls.hpp
  4. +9
    -9
      src/game/states/controls-menu.cpp
  5. +14
    -10
      src/game/states/gamepad-config-menu.cpp
  6. +6
    -6
      src/game/states/gamepad-config-menu.hpp
  7. +10
    -6
      src/game/states/keyboard-config-menu.cpp
  8. +1
    -2
      src/input/event-router.hpp

+ 0
- 1
CMakeLists.txt View File

@ -1,6 +1,5 @@
cmake_minimum_required(VERSION 3.7)
option(VERSION_STRING "Project version string" "0.0.0")
project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX)

+ 192
- 0
src/game/controls.cpp View File

@ -19,6 +19,7 @@
#include "controls.hpp"
#include "resources/resource-manager.hpp"
#include "resources/json.hpp"
#include "application.hpp"
#include <fstream>
@ -345,6 +346,197 @@ void apply_control_profile(game::context* ctx, const json& profile)
}
}
void save_control_profile(game::context* ctx)
{
std::string control_profile_path;
if (ctx->config->contains("control_profile"))
control_profile_path = ctx->config_path + "controls/" + (*ctx->config)["control_profile"].get<std::string>();
ctx->logger->push_task("Saving control profile to \"" + control_profile_path + "\"");
try
{
json control_profile;
// Add controls element
auto& controls_element = control_profile["controls"];
controls_element = json::object();
for (auto controls_it = ctx->controls.begin(); controls_it != ctx->controls.end(); ++controls_it)
{
const std::string& control_name = controls_it->first;
input::control* control = controls_it->second;
// Add control element
auto& control_element = controls_element[control_name];
control_element = json::array();
// Add control mappings
auto mappings = ctx->input_event_router->get_mappings(control);
for (input::mapping* mapping: *mappings)
{
json mapping_element;
switch (mapping->get_type())
{
case input::mapping_type::key:
{
const input::key_mapping* key_mapping = static_cast<const input::key_mapping*>(mapping);
mapping_element["device"] = "keyboard";
mapping_element["key"] = input::keyboard::get_scancode_name(key_mapping->scancode);
break;
}
case input::mapping_type::mouse_wheel:
{
const input::mouse_wheel_mapping* wheel_mapping = static_cast<const input::mouse_wheel_mapping*>(mapping);
mapping_element["device"] = "mouse";
switch (wheel_mapping->axis)
{
case input::mouse_wheel_axis::negative_x:
mapping_element["device"] = "x-";
break;
case input::mouse_wheel_axis::positive_x:
mapping_element["device"] = "x+";
break;
case input::mouse_wheel_axis::negative_y:
mapping_element["device"] = "y-";
break;
case input::mouse_wheel_axis::positive_y:
mapping_element["device"] = "y+";
break;
default:
break;
}
break;
}
case input::mapping_type::mouse_button:
{
const input::mouse_button_mapping* button_mapping = static_cast<const input::mouse_button_mapping*>(mapping);
mapping_element["device"] = "mouse";
mapping_element["button"] = button_mapping->button;
break;
}
case input::mapping_type::gamepad_axis:
{
const input::gamepad_axis_mapping* axis_mapping = static_cast<const input::gamepad_axis_mapping*>(mapping);
mapping_element["device"] = "gamepad";
switch (axis_mapping->axis)
{
case input::gamepad_axis::left_x:
if (axis_mapping->negative)
mapping_element["axis"] = "leftx-";
else
mapping_element["axis+"] = "leftx+";
break;
case input::gamepad_axis::left_y:
if (axis_mapping->negative)
mapping_element["axis"] = "lefty-";
else
mapping_element["axis"] = "lefty+";
break;
case input::gamepad_axis::right_x:
if (axis_mapping->negative)
mapping_element["axis"] = "rightx-";
else
mapping_element["axis+"] = "rightx+";
break;
case input::gamepad_axis::right_y:
if (axis_mapping->negative)
mapping_element["axis"] = "righty-";
else
mapping_element["axis"] = "righty+";
break;
case input::gamepad_axis::left_trigger:
mapping_element["axis"] = "lefttrigger+";
break;
case input::gamepad_axis::right_trigger:
mapping_element["axis"] = "righttrigger+";
break;
default:
break;
}
break;
}
case input::mapping_type::gamepad_button:
{
const input::gamepad_button_mapping* button_mapping = static_cast<const input::gamepad_button_mapping*>(mapping);
mapping_element["device"] = "gamepad";
switch (button_mapping->button)
{
case input::gamepad_button::a:
mapping_element["button"] = "a";
break;
case input::gamepad_button::b:
mapping_element["button"] = "b";
break;
case input::gamepad_button::x:
mapping_element["button"] = "x";
break;
case input::gamepad_button::y:
mapping_element["button"] = "y";
break;
case input::gamepad_button::back:
mapping_element["button"] = "back";
break;
case input::gamepad_button::guide:
mapping_element["button"] = "guide";
break;
case input::gamepad_button::start:
mapping_element["button"] = "start";
break;
case input::gamepad_button::left_stick:
mapping_element["button"] = "leftstick";
break;
case input::gamepad_button::right_stick:
mapping_element["button"] = "rightstick";
break;
case input::gamepad_button::left_shoulder:
mapping_element["button"] = "leftshoulder";
break;
case input::gamepad_button::right_shoulder:
mapping_element["button"] = "rightshoulder";
break;
case input::gamepad_button::dpad_up:
mapping_element["button"] = "dpup";
break;
case input::gamepad_button::dpad_down:
mapping_element["button"] = "dpdown";
break;
case input::gamepad_button::dpad_left:
mapping_element["button"] = "dpleft";
break;
case input::gamepad_button::dpad_right:
mapping_element["button"] = "dpright";
break;
default:
break;
}
break;
}
default:
break;
}
control_element.push_back(mapping_element);
}
}
std::ofstream control_profile_file(control_profile_path);
control_profile_file << control_profile;
}
catch (...)
{
ctx->logger->pop_task(EXIT_FAILURE);
}
ctx->logger->pop_task(EXIT_SUCCESS);
}
void apply_gamepad_calibration(input::gamepad* gamepad, const json& calibration)
{
// Parse and apply activation thresholds

+ 7
- 0
src/game/controls.hpp View File

@ -34,6 +34,13 @@ namespace game {
*/
void apply_control_profile(game::context* ctx, const json& profile);
/**
* Saves the current control profile.
*
* @param ctx Game context.
*/
void save_control_profile(game::context* ctx);
/**
* Generates a default control profile.
*

+ 9
- 9
src/game/states/controls-menu.cpp View File

@ -19,7 +19,7 @@
#include "game/states/controls-menu.hpp"
#include "game/states/keyboard-config-menu.hpp"
#include "game/states/controller-config-menu.hpp"
#include "game/states/gamepad-config-menu.hpp"
#include "game/states/options-menu.hpp"
#include "application.hpp"
#include "scene/text.hpp"
@ -38,17 +38,17 @@ void enter(game::context* ctx)
// Construct menu item texts
scene::text* keyboard_text = new scene::text();
scene::text* controller_text = new scene::text();
scene::text* gamepad_text = new scene::text();
scene::text* back_text = new scene::text();
// Build list of menu item texts
ctx->menu_item_texts.push_back({keyboard_text, nullptr});
ctx->menu_item_texts.push_back({controller_text, nullptr});
ctx->menu_item_texts.push_back({gamepad_text, nullptr});
ctx->menu_item_texts.push_back({back_text, nullptr});
// Set content of menu item texts
keyboard_text->set_content((*ctx->strings)["controls_menu_keyboard"]);
controller_text->set_content((*ctx->strings)["controls_menu_controller"]);
gamepad_text->set_content((*ctx->strings)["controls_menu_gamepad"]);
back_text->set_content((*ctx->strings)["back"]);
// Init menu item index
@ -69,12 +69,12 @@ void enter(game::context* ctx)
next_state.exit = std::bind(game::state::keyboard_config_menu::exit, ctx);
ctx->app->change_state(next_state);
};
auto select_controller_callback = [ctx]()
auto select_gamepad_callback = [ctx]()
{
application::state next_state;
next_state.name = "controller_config_menu";
next_state.enter = std::bind(game::state::controller_config_menu::enter, ctx);
next_state.exit = std::bind(game::state::controller_config_menu::exit, ctx);
next_state.name = "gamepad_config_menu";
next_state.enter = std::bind(game::state::gamepad_config_menu::enter, ctx);
next_state.exit = std::bind(game::state::gamepad_config_menu::exit, ctx);
ctx->app->change_state(next_state);
};
auto select_back_callback = [ctx]()
@ -88,7 +88,7 @@ void enter(game::context* ctx)
// Build list of menu select callbacks
ctx->menu_select_callbacks.push_back(select_keyboard_callback);
ctx->menu_select_callbacks.push_back(select_controller_callback);
ctx->menu_select_callbacks.push_back(select_gamepad_callback);
ctx->menu_select_callbacks.push_back(select_back_callback);
// Build list of menu left callbacks

src/game/states/controller-config-menu.cpp → src/game/states/gamepad-config-menu.cpp View File

@ -17,7 +17,7 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "game/states/controller-config-menu.hpp"
#include "game/states/gamepad-config-menu.hpp"
#include "game/states/controls-menu.hpp"
#include "application.hpp"
#include "scene/text.hpp"
@ -25,11 +25,12 @@
#include "debug/logger.hpp"
#include "resources/resource-manager.hpp"
#include "game/menu.hpp"
#include "game/controls.hpp"
#include "animation/timeline.hpp"
namespace game {
namespace state {
namespace controller_config_menu {
namespace gamepad_config_menu {
static std::string get_binding_string(game::context* ctx, input::control* control)
{
@ -273,12 +274,12 @@ void enter(game::context* ctx)
ctx->ui_clear_pass->set_cleared_buffers(true, true, false);
// Add camera control menu items
add_control_item(ctx, "dolly_forward");
add_control_item(ctx, "dolly_backward");
add_control_item(ctx, "truck_left");
add_control_item(ctx, "truck_right");
add_control_item(ctx, "pedestal_up");
add_control_item(ctx, "pedestal_down");
add_control_item(ctx, "move_forward");
add_control_item(ctx, "move_back");
add_control_item(ctx, "move_left");
add_control_item(ctx, "move_right");
add_control_item(ctx, "move_up");
add_control_item(ctx, "move_down");
// Add application control menu items
add_control_item(ctx, "toggle_fullscreen");
@ -294,7 +295,7 @@ void enter(game::context* ctx)
back_text->set_content((*ctx->strings)["back"]);
// Init menu item index
game::menu::init_menu_item_index(ctx, "controller_config");
game::menu::init_menu_item_index(ctx, "gamepad_config");
game::menu::update_text_color(ctx);
game::menu::update_text_font(ctx);
@ -338,9 +339,12 @@ void exit(game::context* ctx)
game::menu::remove_text_from_ui(ctx);
game::menu::delete_text(ctx);
// Save control profile
game::save_control_profile(ctx);
ctx->ui_clear_pass->set_cleared_buffers(false, true, false);
}
} // namespace controller_config_menu
} // namespace gamepad_config_menu
} // namespace state
} // namespace game

src/game/states/controller-config-menu.hpp → src/game/states/gamepad-config-menu.hpp View File

@ -17,23 +17,23 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_GAME_STATE_CONTROLLER_CONFIG_MENU_HPP
#define ANTKEEPER_GAME_STATE_CONTROLLER_CONFIG_MENU_HPP
#ifndef ANTKEEPER_GAME_STATE_GAMEPAD_CONFIG_MENU_HPP
#define ANTKEEPER_GAME_STATE_GAMEPAD_CONFIG_MENU_HPP
#include "game/context.hpp"
namespace game {
namespace state {
/// Game controller config menu screen game state functions.
namespace controller_config_menu {
/// Gamepad config menu screen game state functions.
namespace gamepad_config_menu {
void enter(game::context* ctx);
void exit(game::context* ctx);
} // namespace controller_config_menu
} // namespace gamepad_config_menu
} // namespace state
} // namespace game
#endif // ANTKEEPER_GAME_STATE_CONTROLLER_CONFIG_MENU_HPP
#endif // ANTKEEPER_GAME_STATE_GAMEPAD_CONFIG_MENU_HPP

+ 10
- 6
src/game/states/keyboard-config-menu.cpp View File

@ -25,6 +25,7 @@
#include "debug/logger.hpp"
#include "resources/resource-manager.hpp"
#include "game/menu.hpp"
#include "game/controls.hpp"
#include "animation/timeline.hpp"
namespace game {
@ -234,12 +235,12 @@ void enter(game::context* ctx)
ctx->ui_clear_pass->set_cleared_buffers(true, true, false);
// Add camera control menu items
add_control_item(ctx, "dolly_forward");
add_control_item(ctx, "dolly_backward");
add_control_item(ctx, "truck_left");
add_control_item(ctx, "truck_right");
add_control_item(ctx, "pedestal_up");
add_control_item(ctx, "pedestal_down");
add_control_item(ctx, "move_forward");
add_control_item(ctx, "move_back");
add_control_item(ctx, "move_left");
add_control_item(ctx, "move_right");
add_control_item(ctx, "move_up");
add_control_item(ctx, "move_down");
// Add application control menu items
add_control_item(ctx, "toggle_fullscreen");
@ -299,6 +300,9 @@ void exit(game::context* ctx)
game::menu::remove_text_from_ui(ctx);
game::menu::delete_text(ctx);
// Save control profile
game::save_control_profile(ctx);
ctx->ui_clear_pass->set_cleared_buffers(false, true, false);
}

+ 1
- 2
src/input/event-router.hpp View File

@ -71,8 +71,7 @@ public:
* @param mapping Input mapping to add.
*/
void add_mapping(const mapping& mapping);
/**
* Removes all input mappings from the router that are associated with the specified control.
*

Loading…
Cancel
Save