aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/facade/SDLContext.h
blob: bd0427a0997316ee561e402716c69340afea4ef5 (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
#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 <utility>

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

namespace crepe {

class LoopManager;
class InputSystem;
/**
 * \class SDLContext
 * \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:
	struct RenderContext {
		const Sprite & sprite;
		const Camera & cam;
		const vec2 & cam_pos;
		const vec2 & pos;
		const double & angle;
		const double & scale;
	};

public:
	//! EventType enum for passing eventType
	enum EventType {
		NONE = 0,
		MOUSEDOWN,
		MOUSEUP,
		MOUSEMOVE,
		MOUSEWHEEL,
		KEYUP,
		KEYDOWN,
		SHUTDOWN,

	};
	//! EventData struct for passing event data from facade
	struct EventData {
		SDLContext::EventType event_type = SDLContext::EventType::NONE;
		Keycode key = Keycode::NONE;
		bool key_repeat = false;
		MouseButton mouse_button = MouseButton::NONE;
		std::pair<int, int> mouse_position = {-1, -1};
		int scroll_direction = -1;
		float scroll_delta = INFINITY;
		std::pair<int, int> rel_mouse_move = {-1, -1};
	};
	/**
	 * \brief Gets the singleton instance of SDLContext.
	 * \return Reference to the SDLContext instance.
	 */
	static SDLContext & get_instance();

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

private:
	//! will only use get_events
	friend class InputSystem;
	/**
	 * \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<SDLContext::EventData> get_events();

	/**
	 * \brief Converts an SDL key code to the custom Keycode type.
	 * 
	 * This method maps an SDL key code to the corresponding `Keycode` enum value,
	 * which is used internally by the system to identify the keys.
	 * 
	 * \param sdl_key The SDL key code to convert.
	 * \return The corresponding `Keycode` value or `Keycode::NONE` if the key is unrecognized.
	 */
	Keycode sdl_to_keycode(SDL_Keycode 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);

private:
	//! Will only use get_ticks
	friend class AnimatorSystem;
	//! Will only use delay
	friend class LoopTimer;
	/**
	 * \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;

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

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

private:
	//! Will use the funtions: texture_from_path, get_width,get_height.
	friend class Texture;

	/**
	 * \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.
	 */
	ivec2 get_size(const Texture & ctx);

private:
	//! Will use draw,clear_screen, present_screen, camera.
	friend class RenderSystem;

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

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

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

	/**
	 * \brief sets the background of the camera (will be adjusted in future PR)
	 * \param camera Reference to the Camera object.
	 */
	void set_camera(const Camera & camera);

private:
	/**
	 * \brief calculates the sqaure size of the image
	 *
	 * \param sprite Reference to the sprite to calculate the rectangle
	 * \return sdl rectangle to draw a src image
	 */
	SDL_Rect get_src_rect(const Sprite & sprite) const;

	/**
	 * \brief calculates the sqaure size of the image for destination
	 *
	 * \param sprite Reference to the sprite to calculate rectangle
	 * \param pos the pos in world units
	 * \param cam the camera of the current scene
	 * \param cam_pos the current postion of the camera
	 * \param img_scale the image multiplier for increasing img size 
	 * \return sdl rectangle to draw a dst image to draw on the screen
	 */
	SDL_Rect get_dst_rect(const Sprite & sprite, const vec2 & pos, const Camera & cam,
						  const vec2 & cam_pos, const double & img_scale) 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;
};

} // namespace crepe