aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/facade/SDLContext.h
blob: e9c334e190d8a2536ca1316ec60fef75a4186b74 (plain)
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
#pragma once

#include <SDL2/SDL.h>
#include <SDL2/SDL_keycode.h>
#include <SDL2/SDL_rect.h>
#include <SDL2/SDL_render.h>
#include <SDL2/SDL_video.h>
#include <cmath>
#include <functional>
#include <memory>
#include <string>
#include <unordered_map>

#include "../types.h"
#include "api/Camera.h"
#include "api/Color.h"
#include "api/KeyCodes.h"
#include "api/Sprite.h"
#include "api/Transform.h"
#include "EventData.h"

#include "FontFacade.h"

namespace crepe {
class Texture;
class Text;
class Font;
class Mediator;

/**
 * \brief Facade for the SDL library
 *
 * SDLContext is a singleton that handles the SDL window and renderer, provides methods for
 * event handling, and rendering to the screen. It is never used directly by the user
 */
class SDLContext {
public:
	//! data that the camera component cannot hold
	struct CameraAuxiliaryData {

		//! zoomed in viewport in game_units
		vec2 zoomed_viewport;

		/**
		 * \brief scaling factor
		 *
		 * depending on the black bars type will the scaling be different.
		 * - letterboxing --> scaling on the y-as
		 * - pillarboxing --> scaling on the x-as
		 */
		vec2 render_scale;

		/**
		 * \brief size of calculated black bars
		 *
		 * depending on the black bars type will the size be different
		 * - lettorboxing --> {0, bar_height}
		 * - pillarboxing --> {bar_width , 0}
		 */
		vec2 bar_size;

		//! Calculated camera position
		vec2 cam_pos;
	};

	//! rendering data needed to render on screen
	struct RenderContext {
		const Sprite & sprite;
		const Texture & texture;
		const vec2 & pos;
		const double & angle;
		const double & scale;
	};

		struct RenderText {
		const Text & text;
		const Font & font;
		const Transform & transform;
	};

public:
	SDLContext(const SDLContext &) = delete;
	SDLContext(SDLContext &&) = delete;
	SDLContext & operator=(const SDLContext &) = delete;
	SDLContext & operator=(SDLContext &&) = delete;

public:
	/**
	 * \brief Constructs an SDLContext instance.
	 * Initializes SDL, creates a window and renderer.
	 */
	SDLContext(Mediator & mediator);

	/**
	 * \brief Destroys the SDLContext instance.
	 * Cleans up SDL resources, including the window and renderer.
	 */
	~SDLContext();

public:
	/**
	 * \brief Retrieves a list of all events from the SDL context.
	 *
	 * This method retrieves all the events from the SDL context that are currently
	 * available. It is primarily used by the InputSystem to process various
	 * input events such as mouse clicks, mouse movements, and keyboard presses.
	 *
	 * \return Events that occurred since last call to `get_events()`
	 */
	std::vector<EventData> get_events();
	/**
	 * \brief Fills event_list with triggered window events
	 *
	 * This method checks if any window events are triggered and adds them to the event_list.
	 *
	 */
	void handle_window_event(const SDL_WindowEvent & window_event,
							 std::vector<EventData> & event_list);
	/**
	 * \brief Converts an SDL scan code to the custom Keycode type.
	 *
	 * This method maps an SDL scan code to the corresponding `Keycode` enum value,
	 * which is used internally by the system to identify the keys.
	 *
	 * \param sdl_key The SDL scan code to convert.
	 * \return The corresponding `Keycode` value or `Keycode::NONE` if the key is unrecognized.
	 */
	Keycode sdl_to_keycode(SDL_Scancode sdl_key);

	/**
	 * \brief Converts an SDL mouse button code to the custom MouseButton type.
	 *
	 * This method maps an SDL mouse button code to the corresponding `MouseButton`
	 * enum value, which is used internally by the system to identify mouse buttons.
	 *
	 * \param sdl_button The SDL mouse button code to convert.
	 * \return The corresponding `MouseButton` value or `MouseButton::NONE` if the key is unrecognized
	 */
	MouseButton sdl_to_mousebutton(Uint8 sdl_button);
	/**
	 * \brief Gets the current state of the keyboard.
	 *
	 * Updates the internal keyboard state by checking the current key states using
	 * SDL's `SDL_GetKeyboardState()`, and returns a reference to the `keyboard_state_t`.
	 *
	 * \return A constant reference to the `keyboard_state_t`, which holds the state
	 *         of each key (true = pressed, false = not pressed).
	 */
	const keyboard_state_t & get_keyboard_state();

public:
	/**
	 * \brief Gets the current SDL ticks since the program started.
	 * \return Current ticks in milliseconds as a constant uint64_t.
	 */
	uint64_t get_ticks() const;
	/**
	 * \brief Pauses the execution for a specified duration.
	 *
	 * This function uses SDL's delay function to halt the program execution for a given number
	 * of milliseconds, allowing for frame rate control or other timing-related functionality.
	 *
	 * \param ms Duration of the delay in milliseconds.
	 */
	void delay(int ms) const;

public:
	/**
	 * \brief Loads a texture from a file path.
	 * \param path Path to the image file.
	 * \return Pointer to the created SDL_Texture.
	 */
	std::unique_ptr<SDL_Texture, std::function<void(SDL_Texture *)>>
	texture_from_path(const std::string & path);
	/**
	 * \brief Gets the size of a texture.
	 * \param texture Reference to the Texture object.
	 * \return Width and height of the texture as an integer in pixels.
	 */
	ivec2 get_size(const Texture & ctx);

public:
	/**
	 * \brief Draws a sprite to the screen using the specified transform and camera.
	 * \param RenderContext Reference to rendering data to draw
	 */
	void draw(const RenderContext & ctx);

	/**
	 * \brief draws a text to the screen 
	 *
	 * \param data Reference to the rendering data needed to draw
	 */
	void draw_text(const RenderText & data);

	//! Clears the screen, preparing for a new frame.
	void clear_screen();

	//! Presents the rendered frame to the screen.
	void present_screen();

	/**
	 * \brief calculates camera view settings. such as black_bars, zoomed_viewport, scaling and
	 * adjusting window size.
	 *
	 * \note only supports windowed mode.
	 * \param camera Reference to the current Camera object in the scene.
	 * \param new_pos new camera position from transform and offset
	 */
	void update_camera_view(const Camera & camera, const vec2 & new_pos);

public:
	//! the data needed to construct a sdl dst rectangle
	struct DestinationRectangleData {
		const Sprite & sprite;
		const Texture & texture;
		const vec2 & pos;
		const double & img_scale;
	};

	/**
	 * \brief calculates the sqaure size of the image for destination
	 *
	 * \param data needed to calculate a destination rectangle
	 * \return sdl rectangle to draw a dst image to draw on the screen
	 */
	SDL_FRect get_dst_rect(const DestinationRectangleData & data) const;
	/**
	 * \brief Set an additional color value multiplied into render copy operations.
	 *
	 * \param  texture the given texture to adjust
	 * \param  color the color data for the texture
	 */
	void set_color_texture(const Texture & texture, const Color & color);

private:
	//! sdl Window
	std::unique_ptr<SDL_Window, std::function<void(SDL_Window *)>> game_window;

	//! renderer for the crepe engine
	std::unique_ptr<SDL_Renderer, std::function<void(SDL_Renderer *)>> game_renderer;

	//! black bars rectangle to draw
	SDL_FRect black_bars[2] = {};

	/**
	 * \cam_aux_data extra data that the component cannot hold.
	 *
	 * - this is defined in this class because get_events() needs this information aswell
	 */
	CameraAuxiliaryData cam_aux_data;

private:
	//! variable to store the state of each key (true = pressed, false = not pressed)
	keyboard_state_t keyboard_state;
	//! lookup table for converting SDL_SCANCODES to Keycodes
	const std::unordered_map<SDL_Scancode, Keycode> LOOKUP_TABLE
		= {{SDL_SCANCODE_SPACE, Keycode::SPACE},
		   {SDL_SCANCODE_APOSTROPHE, Keycode::APOSTROPHE},
		   {SDL_SCANCODE_COMMA, Keycode::COMMA},
		   {SDL_SCANCODE_MINUS, Keycode::MINUS},
		   {SDL_SCANCODE_PERIOD, Keycode::PERIOD},
		   {SDL_SCANCODE_SLASH, Keycode::SLASH},
		   {SDL_SCANCODE_0, Keycode::D0},
		   {SDL_SCANCODE_1, Keycode::D1},
		   {SDL_SCANCODE_2, Keycode::D2},
		   {SDL_SCANCODE_3, Keycode::D3},
		   {SDL_SCANCODE_4, Keycode::D4},
		   {SDL_SCANCODE_5, Keycode::D5},
		   {SDL_SCANCODE_6, Keycode::D6},
		   {SDL_SCANCODE_7, Keycode::D7},
		   {SDL_SCANCODE_8, Keycode::D8},
		   {SDL_SCANCODE_9, Keycode::D9},
		   {SDL_SCANCODE_SEMICOLON, Keycode::SEMICOLON},
		   {SDL_SCANCODE_EQUALS, Keycode::EQUAL},
		   {SDL_SCANCODE_A, Keycode::A},
		   {SDL_SCANCODE_B, Keycode::B},
		   {SDL_SCANCODE_C, Keycode::C},
		   {SDL_SCANCODE_D, Keycode::D},
		   {SDL_SCANCODE_E, Keycode::E},
		   {SDL_SCANCODE_F, Keycode::F},
		   {SDL_SCANCODE_G, Keycode::G},
		   {SDL_SCANCODE_H, Keycode::H},
		   {SDL_SCANCODE_I, Keycode::I},
		   {SDL_SCANCODE_J, Keycode::J},
		   {SDL_SCANCODE_K, Keycode::K},
		   {SDL_SCANCODE_L, Keycode::L},
		   {SDL_SCANCODE_M, Keycode::M},
		   {SDL_SCANCODE_N, Keycode::N},
		   {SDL_SCANCODE_O, Keycode::O},
		   {SDL_SCANCODE_P, Keycode::P},
		   {SDL_SCANCODE_Q, Keycode::Q},
		   {SDL_SCANCODE_R, Keycode::R},
		   {SDL_SCANCODE_S, Keycode::S},
		   {SDL_SCANCODE_T, Keycode::T},
		   {SDL_SCANCODE_U, Keycode::U},
		   {SDL_SCANCODE_V, Keycode::V},
		   {SDL_SCANCODE_W, Keycode::W},
		   {SDL_SCANCODE_X, Keycode::X},
		   {SDL_SCANCODE_Y, Keycode::Y},
		   {SDL_SCANCODE_Z, Keycode::Z},
		   {SDL_SCANCODE_LEFTBRACKET, Keycode::LEFT_BRACKET},
		   {SDL_SCANCODE_BACKSLASH, Keycode::BACKSLASH},
		   {SDL_SCANCODE_RIGHTBRACKET, Keycode::RIGHT_BRACKET},
		   {SDL_SCANCODE_GRAVE, Keycode::GRAVE_ACCENT},
		   {SDL_SCANCODE_ESCAPE, Keycode::ESCAPE},
		   {SDL_SCANCODE_RETURN, Keycode::ENTER},
		   {SDL_SCANCODE_TAB, Keycode::TAB},
		   {SDL_SCANCODE_BACKSPACE, Keycode::BACKSPACE},
		   {SDL_SCANCODE_INSERT, Keycode::INSERT},
		   {SDL_SCANCODE_DELETE, Keycode::DELETE},
		   {SDL_SCANCODE_RIGHT, Keycode::RIGHT},
		   {SDL_SCANCODE_LEFT, Keycode::LEFT},
		   {SDL_SCANCODE_DOWN, Keycode::DOWN},
		   {SDL_SCANCODE_UP, Keycode::UP},
		   {SDL_SCANCODE_PAGEUP, Keycode::PAGE_UP},
		   {SDL_SCANCODE_PAGEDOWN, Keycode::PAGE_DOWN},
		   {SDL_SCANCODE_HOME, Keycode::HOME},
		   {SDL_SCANCODE_END, Keycode::END},
		   {SDL_SCANCODE_CAPSLOCK, Keycode::CAPS_LOCK},
		   {SDL_SCANCODE_SCROLLLOCK, Keycode::SCROLL_LOCK},
		   {SDL_SCANCODE_NUMLOCKCLEAR, Keycode::NUM_LOCK},
		   {SDL_SCANCODE_PRINTSCREEN, Keycode::PRINT_SCREEN},
		   {SDL_SCANCODE_PAUSE, Keycode::PAUSE},
		   {SDL_SCANCODE_F1, Keycode::F1},
		   {SDL_SCANCODE_F2, Keycode::F2},
		   {SDL_SCANCODE_F3, Keycode::F3},
		   {SDL_SCANCODE_F4, Keycode::F4},
		   {SDL_SCANCODE_F5, Keycode::F5},
		   {SDL_SCANCODE_F6, Keycode::F6},
		   {SDL_SCANCODE_F7, Keycode::F7},
		   {SDL_SCANCODE_F8, Keycode::F8},
		   {SDL_SCANCODE_F9, Keycode::F9},
		   {SDL_SCANCODE_F10, Keycode::F10},
		   {SDL_SCANCODE_F11, Keycode::F11},
		   {SDL_SCANCODE_F12, Keycode::F12},
		   {SDL_SCANCODE_KP_0, Keycode::KP0},
		   {SDL_SCANCODE_KP_1, Keycode::KP1},
		   {SDL_SCANCODE_KP_2, Keycode::KP2},
		   {SDL_SCANCODE_KP_3, Keycode::KP3},
		   {SDL_SCANCODE_KP_4, Keycode::KP4},
		   {SDL_SCANCODE_KP_5, Keycode::KP5},
		   {SDL_SCANCODE_KP_6, Keycode::KP6},
		   {SDL_SCANCODE_KP_7, Keycode::KP7},
		   {SDL_SCANCODE_KP_8, Keycode::KP8},
		   {SDL_SCANCODE_KP_9, Keycode::KP9},
		   {SDL_SCANCODE_LSHIFT, Keycode::LEFT_SHIFT},
		   {SDL_SCANCODE_LCTRL, Keycode::LEFT_CONTROL},
		   {SDL_SCANCODE_LALT, Keycode::LEFT_ALT},
		   {SDL_SCANCODE_LGUI, Keycode::LEFT_SUPER},
		   {SDL_SCANCODE_RSHIFT, Keycode::RIGHT_SHIFT},
		   {SDL_SCANCODE_RCTRL, Keycode::RIGHT_CONTROL},
		   {SDL_SCANCODE_RALT, Keycode::RIGHT_ALT},
		   {SDL_SCANCODE_RGUI, Keycode::RIGHT_SUPER},
		   {SDL_SCANCODE_MENU, Keycode::MENU}};

private:
	//! instance of the font_facade
	FontFacade font_facade{};

public:
	/**
	 * \brief Function to Get asset from font_family
	 * 
	 * This function uses the FontFacade function to convert a font_family to an asset.
	 * 
	 * \param font_family name of the font style that needs to be used (will return an asset with default font path of the font_family doesnt exist)
	 * 
	 * \return asset with the font style absolute path
	 */
	Asset get_font_from_name(const std::string & font_family);
};

} // namespace crepe