diff options
| -rw-r--r-- | src/crepe/api/Text.cpp | 2 | ||||
| -rw-r--r-- | src/crepe/api/Text.h | 49 | ||||
| -rw-r--r-- | src/crepe/facade/Font.cpp | 4 | ||||
| -rw-r--r-- | src/crepe/facade/Font.h | 15 | ||||
| -rw-r--r-- | src/crepe/facade/SDLContext.cpp | 202 | ||||
| -rw-r--r-- | src/example/loadfont.cpp | 13 | 
6 files changed, 181 insertions, 104 deletions
diff --git a/src/crepe/api/Text.cpp b/src/crepe/api/Text.cpp index dd44dd9..12d01f1 100644 --- a/src/crepe/api/Text.cpp +++ b/src/crepe/api/Text.cpp @@ -2,5 +2,5 @@  using namespace crepe; -Text::Text(game_object_id_t id,const vec2 & dimensions, const vec2 & offset, const Asset & font) : UIObject(id,dimensions,offset),source(font){} +Text::Text(game_object_id_t id,const vec2 & dimensions, const vec2 & offset,std::string text,std::string font_family) : UIObject(id,dimensions,offset),text(text), font_family(font_family){} diff --git a/src/crepe/api/Text.h b/src/crepe/api/Text.h index d5f47fa..51bab98 100644 --- a/src/crepe/api/Text.h +++ b/src/crepe/api/Text.h @@ -9,27 +9,42 @@  #include "UIObject.h"  namespace crepe{ + +/** + * \brief Text UIObject component for displaying text + *  + * This class can be used to display text on screen. By setting the font_family to a font already stored on the current device it will automatically be loaded in. + */  class Text : public UIObject{  public: -	Text(game_object_id_t id,const vec2 & dimensions, const vec2 & offset, const Asset & font); +	Text(game_object_id_t id,const vec2 & dimensions, const vec2 & offset,std::string text,std::string font_family); +	//! Text data that does not have to be set in the constructor +	struct Data { +		//! Label text color. +		Color text_color = Color::BLACK; +		/** +		 *  \brief fontsize for text rendering +		 *  +		 * \note this is not the actual font size that is loaded in. +		 *  +		 * Since SDL_TTF requires the font size when loading in the font it is not possible to switch the font size. +		 * The default font size that is loaded is set in the Config. +		 * Instead this value is used to upscale the font texture which can cause blurring or distorted text when upscaling or downscaling too much. +		 */ +		unsigned int font_size = 16; +		//! Layer sorting level of the text +		const int sorting_in_layer = 0; +		//! Order within the sorting text +		const int order_in_layer = 0; +	}; +public: +	//! font family name such as (Arial,Helvetica,Inter) +	std::string font_family = "";  	//! Label text. -	std::string text; -	//! Label text color. -	Color text_color = Color::BLACK; -	/** -	 *  \brief fontsize for text rendering -	 *  -	 * \note this is not the actual font size that is loaded in. -	 *  -	 * Since SDL_TTF requires the font size when loading in the font it is not possible to switch the font size. -	 * The default font size that is loaded is set in the Config. -	 * Instead this value is used to upscale the font texture which can cause blurring or distorted text when upscaling or downscaling too much. -	 */ -	unsigned int font_size = 16; -	//! Font asset -	const Asset source; -private: +	std::string text = ""; +	// Data instance for data not gotten from constructor +	Data data;  };  } // namespace crepe diff --git a/src/crepe/facade/Font.cpp b/src/crepe/facade/Font.cpp index b600b01..66835ee 100644 --- a/src/crepe/facade/Font.cpp +++ b/src/crepe/facade/Font.cpp @@ -23,6 +23,6 @@ Font::Font(std::unique_ptr<Asset> res){  	this->load(std::move(res));  } -const TTF_Font& Font::get_font() const{ -	return this->font; +TTF_Font* Font::get_font() const{ +	return this->font.get();  } diff --git a/src/crepe/facade/Font.h b/src/crepe/facade/Font.h index 8bf9fc9..dd1cebf 100644 --- a/src/crepe/facade/Font.h +++ b/src/crepe/facade/Font.h @@ -17,17 +17,20 @@ class Font : public Resource{  public:      /**  	 * \param src Asset with font data to load. -	 * \param mediator use the SDLContext reference to load text +	 * \param mediator use the SDLContext reference to get_font()  	 */ -    Font( src, Mediator & mediator); +    Font(const Asset & src, Mediator & mediator); - -    ~Font() = default -	const TTF_Font& get_font() const; +	/** +	 * \brief getter for TTF_Font +	 *  +	 * \param src Asset with font data to load. +	 * \param mediator use the SDLContext reference to get_font() +	 */ +	TTF_Font* get_font() const;  private:  	//! The SDL_ttf font object with custom deleter.      std::unique_ptr<TTF_Font, decltype(&TTF_CloseFont)> font; -	unsigned int default_font_size = Config::get_instance().font.size;  };  } // namespace crepe diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index d71a9c8..8f6c02c 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -18,18 +18,23 @@  #include "../api/Color.h"  #include "../api/Config.h"  #include "../api/Sprite.h" +#include "../api/Texture.h"  #include "../util/Log.h" -#include "manager/Mediator.h"  #include "SDLContext.h" -#include "Texture.h"  #include "types.h"  using namespace crepe;  using namespace std; -SDLContext::SDLContext(Mediator & mediator) { +SDLContext & SDLContext::get_instance() { +	static SDLContext instance; +	return instance; +} + +SDLContext::SDLContext() {  	dbg_trace(); +  	if (SDL_Init(SDL_INIT_VIDEO) != 0) {  		throw runtime_error(format("SDLContext: SDL_Init error: {}", SDL_GetError()));  	} @@ -57,8 +62,6 @@ SDLContext::SDLContext(Mediator & mediator) {  	if (!(IMG_Init(img_flags) & img_flags)) {  		throw runtime_error("SDLContext: SDL_image could not initialize!");  	} - -	mediator.sdl_context = *this;  }  SDLContext::~SDLContext() { @@ -74,11 +77,12 @@ SDLContext::~SDLContext() {  	SDL_Quit();  } -Keycode SDLContext::sdl_to_keycode(SDL_Keycode sdl_key) { +Keycode SDLContext::sdl_to_keycode(SDL_Scancode sdl_key) {  	static const std::array<Keycode, SDL_NUM_SCANCODES> LOOKUP_TABLE = [] {  		std::array<Keycode, SDL_NUM_SCANCODES> table{};  		table.fill(Keycode::NONE); +		// Map all SDL scancodes to Keycodes  		table[SDL_SCANCODE_SPACE] = Keycode::SPACE;  		table[SDL_SCANCODE_APOSTROPHE] = Keycode::APOSTROPHE;  		table[SDL_SCANCODE_COMMA] = Keycode::COMMA; @@ -180,13 +184,27 @@ Keycode SDLContext::sdl_to_keycode(SDL_Keycode sdl_key) {  		return table;  	}(); -  	if (sdl_key < 0 || sdl_key >= SDL_NUM_SCANCODES) {  		return Keycode::NONE;  	} -  	return LOOKUP_TABLE[sdl_key];  } +std::array<bool, Keycode::NUM_KEYCODES> SDLContext::get_keyboard_state() { +	// Array to hold the key states (true if pressed, false if not) +	std::array<bool, Keycode::NUM_KEYCODES> keyState{}; +	SDL_PumpEvents(); +	const Uint8 * current_state = SDL_GetKeyboardState(nullptr); + +	for (int i = 0; i < SDL_NUM_SCANCODES; ++i) { +		Keycode key = sdl_to_keycode(static_cast<SDL_Scancode>(i)); + +		if (key != Keycode::NONE) { +			keyState[key] = current_state[i] != 0; +		} +	} + +	return keyState; +}  MouseButton SDLContext::sdl_to_mousebutton(Uint8 sdl_button) {  	static const std::array<MouseButton, 5> MOUSE_BUTTON_LOOKUP_TABLE = [] { @@ -218,19 +236,25 @@ void SDLContext::present_screen() {  	SDL_RenderPresent(this->game_renderer.get());  } +SDL_Rect SDLContext::get_src_rect(const Sprite & sprite) const { +	return SDL_Rect{ +		.x = sprite.mask.x, +		.y = sprite.mask.y, +		.w = sprite.mask.w, +		.h = sprite.mask.h, +	}; +} +  SDL_FRect SDLContext::get_dst_rect(const DestinationRectangleData & ctx) const {  	const Sprite::Data & data = ctx.sprite.data; -	float aspect_ratio -		= (ctx.sprite.aspect_ratio == 0) ? ctx.texture.get_ratio() : ctx.sprite.aspect_ratio; -  	vec2 size = data.size;  	if (data.size.x == 0 && data.size.y != 0) { -		size.x = data.size.y * aspect_ratio; +		size.x = data.size.y * ctx.sprite.aspect_ratio;  	}  	if (data.size.y == 0 && data.size.x != 0) { -		size.y = data.size.x / aspect_ratio; +		size.y = data.size.x / ctx.sprite.aspect_ratio;  	}  	const CameraValues & cam = ctx.cam; @@ -251,24 +275,15 @@ SDL_FRect SDLContext::get_dst_rect(const DestinationRectangleData & ctx) const {  }  void SDLContext::draw(const RenderContext & ctx) { +  	const Sprite::Data & data = ctx.sprite.data;  	SDL_RendererFlip render_flip  		= (SDL_RendererFlip) ((SDL_FLIP_HORIZONTAL * data.flip.flip_x)  							  | (SDL_FLIP_VERTICAL * data.flip.flip_y)); -	SDL_Rect srcrect; -	SDL_Rect * srcrect_ptr = NULL; -	if (ctx.sprite.mask.w != 0 || ctx.sprite.mask.h != 0) { -		srcrect.w = ctx.sprite.mask.w; -		srcrect.h = ctx.sprite.mask.h; -		srcrect.x = ctx.sprite.mask.x; -		srcrect.y = ctx.sprite.mask.y; -		srcrect_ptr = &srcrect; -	} - +	SDL_Rect srcrect = this->get_src_rect(ctx.sprite);  	SDL_FRect dstrect = this->get_dst_rect(SDLContext::DestinationRectangleData{  		.sprite = ctx.sprite, -		.texture = ctx.texture,  		.cam = ctx.cam,  		.pos = ctx.pos,  		.img_scale = ctx.scale, @@ -276,9 +291,9 @@ void SDLContext::draw(const RenderContext & ctx) {  	double angle = ctx.angle + data.angle_offset; -	this->set_color_texture(ctx.texture, ctx.sprite.data.color); -	SDL_RenderCopyExF(this->game_renderer.get(), ctx.texture.get_img(), srcrect_ptr, &dstrect, -					  angle, NULL, render_flip); +	this->set_color_texture(ctx.sprite.texture, ctx.sprite.data.color); +	SDL_RenderCopyExF(this->game_renderer.get(), ctx.sprite.texture.texture.get(), &srcrect, +					  &dstrect, angle, NULL, render_flip);  }  SDLContext::CameraValues SDLContext::set_camera(const Camera & cam) { @@ -340,6 +355,8 @@ SDLContext::CameraValues SDLContext::set_camera(const Camera & cam) {  	return ret_cam;  } +uint64_t SDLContext::get_ticks() const { return SDL_GetTicks64(); } +  std::unique_ptr<SDL_Texture, std::function<void(SDL_Texture *)>>  SDLContext::texture_from_path(const std::string & path) { @@ -366,71 +383,112 @@ SDLContext::texture_from_path(const std::string & path) {  ivec2 SDLContext::get_size(const Texture & ctx) {  	ivec2 size; -	SDL_QueryTexture(ctx.get_img(), NULL, NULL, &size.x, &size.y); +	SDL_QueryTexture(ctx.texture.get(), NULL, NULL, &size.x, &size.y);  	return size;  } +void SDLContext::delay(int ms) const { SDL_Delay(ms); } +  std::vector<SDLContext::EventData> SDLContext::get_events() {  	std::vector<SDLContext::EventData> event_list;  	SDL_Event event; + +	// Handle general SDL events  	while (SDL_PollEvent(&event)) {  		switch (event.type) {  			case SDL_QUIT: -				event_list.push_back(EventData{ -					.event_type = SDLContext::EventType::SHUTDOWN, -				}); +				event_list.push_back({SDLContext::EventType::SHUTDOWN, {}, {}, {}});  				break;  			case SDL_KEYDOWN: -				event_list.push_back(EventData{ -					.event_type = SDLContext::EventType::KEYDOWN, -					.key = sdl_to_keycode(event.key.keysym.scancode), -					.key_repeat = (event.key.repeat != 0), -				}); +				event_list.push_back( +					{SDLContext::EventType::KEYDOWN, +					 {sdl_to_keycode(event.key.keysym.scancode), event.key.repeat != 0}, +					 {}, +					 {}});  				break;  			case SDL_KEYUP: -				event_list.push_back(EventData{ -					.event_type = SDLContext::EventType::KEYUP, -					.key = sdl_to_keycode(event.key.keysym.scancode), -				}); +				event_list.push_back({SDLContext::EventType::KEYUP, +									  {sdl_to_keycode(event.key.keysym.scancode), false}, +									  {}, +									  {}});  				break;  			case SDL_MOUSEBUTTONDOWN: -				event_list.push_back(EventData{ -					.event_type = SDLContext::EventType::MOUSEDOWN, -					.mouse_button = sdl_to_mousebutton(event.button.button), -					.mouse_position = {event.button.x, event.button.y}, -				}); +				event_list.push_back({SDLContext::EventType::MOUSEDOWN, +									  {}, +									  {sdl_to_mousebutton(event.button.button), +									   {event.button.x, event.button.y}}, +									  {}}); +				break; +			case SDL_MOUSEBUTTONUP: +				event_list.push_back({SDLContext::EventType::MOUSEUP, +									  {}, +									  {sdl_to_mousebutton(event.button.button), +									   {event.button.x, event.button.y}}, +									  {}}); +				break; +			case SDL_MOUSEMOTION: +				event_list.push_back({SDLContext::EventType::MOUSEMOVE, +									  {}, +									  {{}, +									   {event.motion.x, event.motion.y}, +									   -1, +									   INFINITY, +									   {event.motion.xrel, event.motion.yrel}}, +									  {}});  				break; -			case SDL_MOUSEBUTTONUP: { -				int x, y; -				SDL_GetMouseState(&x, &y); -				event_list.push_back(EventData{ -					.event_type = SDLContext::EventType::MOUSEUP, -					.mouse_button = sdl_to_mousebutton(event.button.button), -					.mouse_position = {event.button.x, event.button.y}, -				}); -			} break; - -			case SDL_MOUSEMOTION: { +			case SDL_MOUSEWHEEL:  				event_list.push_back( -					EventData{.event_type = SDLContext::EventType::MOUSEMOVE, -							  .mouse_position = {event.motion.x, event.motion.y}, -							  .rel_mouse_move = {event.motion.xrel, event.motion.yrel}}); -			} break; - -			case SDL_MOUSEWHEEL: { -				event_list.push_back(EventData{ -					.event_type = SDLContext::EventType::MOUSEWHEEL, -					.mouse_position = {event.motion.x, event.motion.y}, -					// TODO: why is this needed? -					.scroll_direction = event.wheel.y < 0 ? -1 : 1, -					.scroll_delta = event.wheel.preciseY, -				}); -			} break; +					{SDLContext::EventType::MOUSEWHEEL, +					 {}, +					 {{}, {}, event.wheel.y < 0 ? -1 : 1, event.wheel.preciseY, {}}, +					 {}}); +				break; + +			// Forward window events for further processing +			case SDL_WINDOWEVENT: +				this->handle_window_event(event.window, event_list); +				break;  		}  	} +  	return event_list;  } + +// Separate function for SDL_WINDOWEVENT subtypes +void SDLContext::handle_window_event(const SDL_WindowEvent & window_event, +									 std::vector<SDLContext::EventData> & event_list) { +	switch (window_event.event) { +		case SDL_WINDOWEVENT_EXPOSED: +			event_list.push_back({SDLContext::EventType::WINDOW_EXPOSE, {}, {}, {}}); +			break; +		case SDL_WINDOWEVENT_RESIZED: +			event_list.push_back({SDLContext::EventType::WINDOW_RESIZE, +								  {}, +								  {}, +								  {{}, {window_event.data1, window_event.data2}}}); +			break; +		case SDL_WINDOWEVENT_MOVED: +			event_list.push_back({SDLContext::EventType::WINDOW_MOVE, +								  {}, +								  {}, +								  {{window_event.data1, window_event.data2}, {}}}); +			break; +		case SDL_WINDOWEVENT_MINIMIZED: +			event_list.push_back({SDLContext::EventType::WINDOW_MINIMIZE, {}, {}, {}}); +			break; +		case SDL_WINDOWEVENT_MAXIMIZED: +			event_list.push_back({SDLContext::EventType::WINDOW_MAXIMIZE, {}, {}, {}}); +			break; +		case SDL_WINDOWEVENT_FOCUS_GAINED: +			event_list.push_back({SDLContext::EventType::WINDOW_FOCUS_GAIN, {}, {}, {}}); +			break; +		case SDL_WINDOWEVENT_FOCUS_LOST: +			event_list.push_back({SDLContext::EventType::WINDOW_FOCUS_LOST, {}, {}, {}}); +			break; +	} +} +  void SDLContext::set_color_texture(const Texture & texture, const Color & color) { -	SDL_SetTextureColorMod(texture.get_img(), color.r, color.g, color.b); -	SDL_SetTextureAlphaMod(texture.get_img(), color.a); +	SDL_SetTextureColorMod(texture.texture.get(), color.r, color.g, color.b); +	SDL_SetTextureAlphaMod(texture.texture.get(), color.a);  } diff --git a/src/example/loadfont.cpp b/src/example/loadfont.cpp index 0002026..fe5466f 100644 --- a/src/example/loadfont.cpp +++ b/src/example/loadfont.cpp @@ -3,18 +3,19 @@  #include <memory>  #include <crepe/facade/SDLFontContext.h>  #include <crepe/api/Text.h> - +#include <crepe/facade/Font.h> +#include <crepe/manager/Mediator.h>  using namespace crepe;  int main() {      SDLFontContext font_facade; - -    // Create a unique pointer to the font asset -    std::unique_ptr<Asset> asset = font_facade.get_font_asset("OpenSymbol"); -    std::cout << "path: " << asset->get_path() << std::endl; +	Mediator mediator;  	try{  		  // Correct way to create a unique pointer for Text -    std::unique_ptr<Text> label = std::make_unique<Text>(1, vec2(100, 100), vec2(0, 0), *asset); +    std::unique_ptr<Text> label = std::make_unique<Text>(1, vec2(100, 100), vec2(0, 0), "test test","OpenSymbol"); +	std::unique_ptr<Asset> asset = font_facade.get_font_asset(label->font_family); +	std::cout << "path: " << asset->get_path() << std::endl; +	std::unique_ptr<Font> font = make_unique<Font>(asset,mediator)  	}catch (const std::exception& e) {      std::cout << "Standard exception thrown: " << e.what() << std::endl;  	}  |