1 /*
2  * Portions of this file are copyright Rebirth contributors and licensed as
3  * described in COPYING.txt.
4  * Portions of this file are copyright Parallax Software and licensed
5  * according to the Parallax license below.
6  * See COPYING.txt for license details.
7 
8 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
9 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
10 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
11 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
12 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
13 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
14 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
15 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
16 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
17 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
18 */
19 
20 /*
21  *
22  * Prototypes for reading controls
23  *
24  */
25 
26 #pragma once
27 
28 #include <type_traits>
29 #include "joy.h"
30 #include "dxxsconf.h"
31 
32 #include "maths.h"
33 #include <vector>
34 #include "fwd-event.h"
35 #include "strutil.h"
36 #include <array>
37 
38 #ifdef dsx
39 namespace dcx {
40 
41 struct control_info
42 {
43 	template <typename T>
44 	struct ramp_controls_t
45 	{
46 		T	key_pitch_forward,
47 			key_pitch_backward,
48 			key_heading_left,
49 			key_heading_right,
50 			key_slide_left,
51 			key_slide_right,
52 			key_slide_up,
53 			key_slide_down,
54 			key_bank_left,
55 			key_bank_right;
56 	};
57 	struct fire_controls_t
58 	{
59 		uint8_t fire_primary, fire_secondary, fire_flare, drop_bomb;
60 	};
61 	struct state_controls_t :
62 		public fire_controls_t,
63 		public ramp_controls_t<uint8_t>
64 	{
65 		uint8_t btn_slide_left, btn_slide_right,
66 			btn_slide_up, btn_slide_down,
67 			btn_bank_left, btn_bank_right,
68 			slide_on, bank_on,
69 			accelerate, reverse,
70 			cruise_plus, cruise_minus, cruise_off,
71 			rear_view,
72 			automap,
73 			cycle_primary, cycle_secondary, select_weapon,
74 			show_menu;
75 	};
76 	struct mouse_axis_values
77 	{
78 		std::array<fix, 3> mouse_axis, raw_mouse_axis;
79 	};
80 #if DXX_MAX_AXES_PER_JOYSTICK
81 	struct joystick_axis_values
82 	{
83 		std::array<fix, JOY_MAX_AXES> joy_axis, raw_joy_axis;
84 	};
85 #endif
86 	ramp_controls_t<float> down_time; // to scale movement depending on how long the key is pressed
87 	fix pitch_time, vertical_thrust_time, heading_time, sideways_thrust_time, bank_time, forward_thrust_time;
88         fix excess_pitch_time, excess_vertical_thrust_time, excess_heading_time, excess_sideways_thrust_time, excess_bank_time, excess_forward_thrust_time;
89 };
90 
91 void kconfig_begin_loop(control_info &);
92 
93 }
94 
95 namespace dsx {
96 
97 enum class dxx_kconfig_ui_kc_keyboard : unsigned;
98 enum class dxx_kconfig_ui_kc_mouse : unsigned;
99 #if DXX_MAX_JOYSTICKS
100 enum class dxx_kconfig_ui_kc_joystick : unsigned;
101 #endif
102 enum class dxx_kconfig_ui_kc_rebirth : unsigned;
103 
104 struct state_control_info
105 {
106 #if defined(DXX_BUILD_DESCENT_I)
107 	/* Avoid creating a typedef for a single use.  Qualify the name so
108 	 * that it can be found.
109 	 */
110 	::dcx::control_info::
111 #elif defined(DXX_BUILD_DESCENT_II)
112 	/* Extend the original type with new Descent2-specific members.
113 	 */
114 	struct state_controls_t : ::dcx::control_info::state_controls_t
115 	{
116 		uint8_t toggle_bomb,
117 			afterburner, headlight, energy_to_shield;
118 	};
119 #endif
120 	state_controls_t state; // to scale movement for keys only we need them to be separate from joystick/mouse buttons
121 };
122 
123 /* This inheritance construct is needed so that joystick_axis_values is
124  * at the end of the structure.  The joystick values are placed at the
125  * end because they are far larger than the rest of the structure
126  * members combined, so moving them to the end provides the best
127  * locality of access.
128  */
129 struct control_info : ::dcx::control_info,
130 	state_control_info,
131 	::dcx::control_info::mouse_axis_values
132 #if DXX_MAX_AXES_PER_JOYSTICK
133 	, ::dcx::control_info::joystick_axis_values
134 #endif
135 {
136 #if defined(DXX_BUILD_DESCENT_II)
137 	using typename state_control_info::state_controls_t;
138 #endif
139 };
140 
141 extern control_info Controls;
142 
143 }
144 #endif
145 
146 #define CONTROL_USING_JOYSTICK	1
147 #define CONTROL_USING_MOUSE		2
148 #define MOUSEFS_DELTA_RANGE 512
149 #ifdef dsx
150 namespace dsx {
151 #if defined(DXX_BUILD_DESCENT_I)
152 constexpr std::integral_constant<unsigned, 50> MAX_CONTROLS{};
153 #elif defined(DXX_BUILD_DESCENT_II)
154 constexpr std::integral_constant<unsigned, 60> MAX_CONTROLS{};		// there are actually 48, so this leaves room for more
155 #endif
156 void kconfig_read_controls(control_info &, const d_event &event, int automap_flag);
157 }
158 namespace dcx {
159 extern fix Cruise_speed;
160 
161 constexpr std::integral_constant<unsigned, 30> MAX_DXX_REBIRTH_CONTROLS{};
162 extern const std::array<uint8_t, MAX_DXX_REBIRTH_CONTROLS> DefaultKeySettingsRebirth;
163 }
164 #endif
165 
166 enum class kconfig_type
167 {
168 	keyboard,
169 #if DXX_MAX_JOYSTICKS
170 	joystick,
171 #endif
172 	mouse,
173 	rebirth,
174 };
175 
176 void kconfig(kconfig_type n);
177 
178 extern void kc_set_controls();
179 
180 //set the cruise speed to zero
181 extern void reset_cruise(void);
182 
183 #if DXX_MAX_JOYSTICKS
184 namespace dcx {
185 
186 template <std::size_t N>
187 class joystick_text_t : std::vector<std::array<char, N>>
188 {
189 	using vector_type = std::vector<std::array<char, N>>;
190 public:
191 	using vector_type::clear;
192 	using vector_type::size;
193 	using vector_type::resize;
194 	typename vector_type::reference operator[](typename vector_type::size_type s)
195 	{
196 		return this->at(s);
197 	}
198 };
199 
200 #if DXX_MAX_AXES_PER_JOYSTICK
201 using joyaxis_text_t = joystick_text_t<sizeof("J A") + number_to_text_length<DXX_MAX_JOYSTICKS> + number_to_text_length<DXX_MAX_AXES_PER_JOYSTICK>>;
202 extern joyaxis_text_t joyaxis_text;
203 #endif
204 
205 #define DXX_JOY_MAX(A,B)	((A) < (B) ? (B) : (A))
206 using joybutton_text_t = joystick_text_t<number_to_text_length<DXX_MAX_JOYSTICKS> + DXX_JOY_MAX(DXX_JOY_MAX(sizeof("J H ") + number_to_text_length<DXX_MAX_HATS_PER_JOYSTICK>, sizeof("J B") + number_to_text_length<DXX_MAX_BUTTONS_PER_JOYSTICK>), sizeof("J -A") + number_to_text_length<DXX_MAX_AXES_PER_JOYSTICK>)>;
207 #undef DXX_JOY_MAX
208 extern joybutton_text_t joybutton_text;
209 
210 }
211 #endif
212