File: ControlScheme.h

package info (click to toggle)
jazz2-native 3.5.0-1
  • links: PTS, VCS
  • area: contrib
  • in suites:
  • size: 16,836 kB
  • sloc: cpp: 172,557; xml: 113; python: 36; makefile: 5; sh: 2
file content (115 lines) | stat: -rw-r--r-- 4,150 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#pragma once

#include "../PlayerAction.h"
#include "../../nCine/Base/BitArray.h"
#include "../../nCine/Input/InputEvents.h"
#include "../../nCine/Primitives/Vector2.h"

#include <Containers/ArrayView.h>
#include <Containers/SmallVector.h>

using namespace Death::Containers;
using namespace nCine;

namespace Jazz2::UI::Menu
{
	class RemapControlsSection;
}

namespace Jazz2::Input
{
	/** @brief Navigation flags for @ref ControlScheme::FetchNavigation(), supports a bitwise combination of its member values */
	enum class NavigationFlags
	{
		/** @brief None */
		None = 0,
		/** @brief Allow only keyboard key presses */
		AllowKeyboard = 0x01,
		/** @brief Allow only gamepad button presses */
		AllowGamepads = 0x02,
		/** @brief Allow both keyboard and gamepad presses */
		AllowAll = AllowKeyboard | AllowGamepads
	};

	DEATH_ENUM_FLAGS(NavigationFlags);

	/** @brief Control mapping target */
	struct MappingTarget
	{
		/** @brief Opaque data of the target */
		std::uint32_t Data;
	};

	/** @brief Control mapping for a particular action */
	struct ControlSchemeMapping
	{
		/** @brief List of mapping targets */
		SmallVector<MappingTarget, 3> Targets;
	};

	/** @brief Result returned by @ref ControlScheme::FetchProcessedInput() */
	struct ProcessedInput
	{
		/** @brief Pressed actions */
		std::uint64_t PressedActions;
		/** @brief Movement vector */
		Vector2f Movement;
	};

	/** @brief Provides access to a user configured control scheme */
	class ControlScheme
	{
		friend class UI::Menu::RemapControlsSection;

	public:
		ControlScheme() = delete;
		~ControlScheme() = delete;

		/** @{ @name Constants */

		/** @brief Maximum number of supported local players */
		static constexpr std::int32_t MaxSupportedPlayers = 4;
		/** @brief Maximum number of supported connected gamepads */
#if defined(DEATH_TARGET_EMSCRIPTEN) || defined(DEATH_TARGET_SWITCH) || defined(DEATH_TARGET_WINDOWS_RT)
		static constexpr std::int32_t MaxConnectedGamepads = 4;
#else
		static constexpr std::int32_t MaxConnectedGamepads = 6;
#endif

		/** @} */

		/** @brief Resets all bindings to default */
		static void Reset();

		/** @brief Fetches processed standard input for specified player according to the current bindings */
		static ProcessedInput FetchProcessedInput(std::int32_t playerIndex, const BitArray& pressedKeys, const ArrayView<const JoyMappedState*> joyStates, std::uint64_t prevPressedActions, bool analogAsButtons = true);
		/** @brief Fetches navigation input according to the current bindings */
		static std::uint32_t FetchNavigation(const BitArray& pressedKeys, const ArrayView<const JoyMappedState*> joyStates, NavigationFlags flags = NavigationFlags::AllowAll);

		/** @brief Returns the entire mapping configuration */
		static ArrayView<ControlSchemeMapping> GetAllMappings();
		/** @brief Returns a mapping configuration for a given player index */
		static ArrayView<ControlSchemeMapping> GetMappings(std::int32_t playerIdx);
		/** @brief Returns a gamepad index for a given player index */
		static std::int32_t GetGamepadForPlayer(std::int32_t playerIdx);
		/** @brief Returns `true` if the action of any player is bound the specified target */
		static bool ContainsTarget(PlayerAction action, MappingTarget target);

		/** @brief Creates mapping target for a given key */
		static MappingTarget CreateTarget(Keys key);
		/** @brief Creates mapping target for a given gamepad button */
		static MappingTarget CreateTarget(std::uint32_t gamepadIndex, ButtonName button);
		/** @brief Creates mapping target for a given gamepad axis */
		static MappingTarget CreateTarget(std::uint32_t gamepadIndex, AxisName axis, bool negative = false);

	private:
		static constexpr std::uint32_t GamepadMask = 0x80000000u;
		static constexpr std::uint32_t GamepadAnalogMask = 0x40000000u;
		static constexpr std::uint32_t GamepadNegativeMask = 0x20000000u;
		static constexpr std::uint32_t GamepadIndexMask = 0x0FFF0000u;
		static constexpr std::uint32_t ButtonMask = 0x0000FFFFu;
		static constexpr float GamepadDeadZone = 0.1f;

		static ControlSchemeMapping _mappings[MaxSupportedPlayers * (std::int32_t)PlayerAction::Count];
	};
}