diff options
author | heavydemon21 <nielsstunnebrink1@gmail.com> | 2024-12-11 17:02:18 +0100 |
---|---|---|
committer | heavydemon21 <nielsstunnebrink1@gmail.com> | 2024-12-11 17:02:18 +0100 |
commit | 715be63e514066fec1962f47f85d0754cbf37755 (patch) | |
tree | 5c3bf3728cce9413be36f20021ffbe511bbba20f /src | |
parent | 9b337ae01e4f3efc6ad3be5af33e3df8e9224d71 (diff) | |
parent | 30c17c98e54c1534664de08ca3838c40c859d166 (diff) |
Merge branch 'master' into niels/UI
Diffstat (limited to 'src')
32 files changed, 277 insertions, 318 deletions
diff --git a/src/crepe/Resource.cpp b/src/crepe/Resource.cpp index 27b4c4b..85913ed 100644 --- a/src/crepe/Resource.cpp +++ b/src/crepe/Resource.cpp @@ -1,5 +1,6 @@ #include "Resource.h" +#include "manager/Mediator.h" using namespace crepe; -Resource::Resource(const Asset & asset) {} +Resource::Resource(const Asset & asset, Mediator & mediator) {} diff --git a/src/crepe/Resource.h b/src/crepe/Resource.h index eceb15b..d65206b 100644 --- a/src/crepe/Resource.h +++ b/src/crepe/Resource.h @@ -4,6 +4,7 @@ namespace crepe { class ResourceManager; class Asset; +class Mediator; /** * \brief Resource interface @@ -17,7 +18,7 @@ class Asset; */ class Resource { public: - Resource(const Asset & src); + Resource(const Asset & src, Mediator & mediator); virtual ~Resource() = default; Resource(const Resource &) = delete; diff --git a/src/crepe/api/Animator.cpp b/src/crepe/api/Animator.cpp index b8a91dc..4ce4bf0 100644 --- a/src/crepe/api/Animator.cpp +++ b/src/crepe/api/Animator.cpp @@ -7,23 +7,21 @@ using namespace crepe; -Animator::Animator(game_object_id_t id, Sprite & spritesheet, unsigned int max_row, - unsigned int max_col, const Animator::Data & data) +Animator::Animator(game_object_id_t id, Sprite & spritesheet, const ivec2 & single_frame_size, + const uvec2 & grid_size, const Animator::Data & data) : Component(id), spritesheet(spritesheet), - max_rows(max_row), - max_columns(max_col), + grid_size(grid_size), data(data) { dbg_trace(); - this->spritesheet.mask.h /= this->max_columns; - this->spritesheet.mask.w /= this->max_rows; - this->spritesheet.mask.x = this->data.row * this->spritesheet.mask.w; - this->spritesheet.mask.y = this->data.col * this->spritesheet.mask.h; + this->spritesheet.mask.w = single_frame_size.x; + this->spritesheet.mask.h = single_frame_size.y; + this->spritesheet.mask.x = 0; + this->spritesheet.mask.y = 0; - // need to do this for to get the aspect ratio for a single clipping in the spritesheet this->spritesheet.aspect_ratio - = static_cast<double>(this->spritesheet.mask.w) / this->spritesheet.mask.h; + = static_cast<float>(single_frame_size.x) / single_frame_size.y; } Animator::~Animator() { dbg_trace(); } @@ -54,6 +52,6 @@ void Animator::set_anim(int col) { void Animator::next_anim() { Animator::Data & ctx = this->data; - ctx.row = ctx.row++ % this->max_rows; + ctx.row = ctx.row++ % this->grid_size.x; this->spritesheet.mask.x = ctx.row * this->spritesheet.mask.w; } diff --git a/src/crepe/api/Animator.h b/src/crepe/api/Animator.h index 7c850b8..5918800 100644 --- a/src/crepe/api/Animator.h +++ b/src/crepe/api/Animator.h @@ -75,27 +75,28 @@ public: * * \param id The unique identifier for the component, typically assigned automatically. * \param spritesheet the reference to the spritesheet - * \param max_row maximum of rows inside the given spritesheet - * \param max_col maximum of columns inside the given spritesheet + * \param single_frame_size the width and height in pixels of a single frame inside the + * spritesheet + * \param grid_size the max rows and columns inside the given spritesheet * \param data extra animation data for more control * * This constructor sets up the Animator with the given parameters, and initializes the * animation system. */ - Animator(game_object_id_t id, Sprite & spritesheet, unsigned int max_row, - unsigned int max_col, const Animator::Data & data); + Animator(game_object_id_t id, Sprite & spritesheet, const ivec2 & single_frame_size, + const uvec2 & grid_size, const Animator::Data & data); ~Animator(); // dbg_trace public: - //! The maximum number of columns in the sprite sheet. - const unsigned int max_columns; - //! The maximum number of rows in the sprite sheet. - const unsigned int max_rows; Animator::Data data; private: //! A reference to the Sprite sheet containing. Sprite & spritesheet; + + //! The maximum number of rows and columns inside the spritesheet + const uvec2 grid_size; + //! Uses the spritesheet friend AnimatorSystem; }; diff --git a/src/crepe/api/CMakeLists.txt b/src/crepe/api/CMakeLists.txt index 118c7ce..46deb67 100644 --- a/src/crepe/api/CMakeLists.txt +++ b/src/crepe/api/CMakeLists.txt @@ -6,7 +6,6 @@ target_sources(crepe PUBLIC ParticleEmitter.cpp Transform.cpp Color.cpp - Texture.cpp Sprite.cpp Config.cpp Metadata.cpp @@ -39,7 +38,6 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES Vector2.h Vector2.hpp Color.h - Texture.h Scene.h Metadata.h Camera.h diff --git a/src/crepe/api/LoopManager.h b/src/crepe/api/LoopManager.h index 700afe4..1bafa56 100644 --- a/src/crepe/api/LoopManager.h +++ b/src/crepe/api/LoopManager.h @@ -10,6 +10,7 @@ #include "../system/System.h" #include "LoopTimer.h" +#include "manager/ResourceManager.h" namespace crepe { @@ -101,11 +102,10 @@ private: ResourceManager resource_manager{mediator}; //! Save manager instance SaveManager save_manager{mediator}; - - //! SDL context \todo no more singletons! - SDLContext & sdl_context = SDLContext::get_instance(); - //! Loop timer \todo no more singletons! - LoopTimer & loop_timer = LoopTimer::get_instance(); + //! SDLContext instance + SDLContext sdl_context{mediator}; + //! LoopTimer instance + LoopTimer loop_timer{mediator}; private: /** diff --git a/src/crepe/api/LoopTimer.cpp b/src/crepe/api/LoopTimer.cpp index 15a0e3a..56e48d3 100644 --- a/src/crepe/api/LoopTimer.cpp +++ b/src/crepe/api/LoopTimer.cpp @@ -1,17 +1,16 @@ #include <chrono> -#include "../facade/SDLContext.h" #include "../util/Log.h" +#include "facade/SDLContext.h" +#include "manager/Manager.h" #include "LoopTimer.h" using namespace crepe; -LoopTimer::LoopTimer() { dbg_trace(); } - -LoopTimer & LoopTimer::get_instance() { - static LoopTimer instance; - return instance; +LoopTimer::LoopTimer(Mediator & mediator) : Manager(mediator) { + dbg_trace(); + mediator.timer = *this; } void LoopTimer::start() { @@ -67,7 +66,8 @@ void LoopTimer::enforce_frame_rate() { = std::chrono::duration_cast<std::chrono::milliseconds>(this->frame_target_time - frame_duration); if (delay_time.count() > 0) { - SDLContext::get_instance().delay(delay_time.count()); + SDLContext & ctx = this->mediator.sdl_context; + ctx.delay(delay_time.count()); } } diff --git a/src/crepe/api/LoopTimer.h b/src/crepe/api/LoopTimer.h index 9393439..0a73a4c 100644 --- a/src/crepe/api/LoopTimer.h +++ b/src/crepe/api/LoopTimer.h @@ -1,19 +1,13 @@ #pragma once +#include "manager/Manager.h" #include <chrono> namespace crepe { -class LoopTimer { +class LoopTimer : public Manager { public: /** - * \brief Get the singleton instance of LoopTimer. - * - * \return A reference to the LoopTimer instance. - */ - static LoopTimer & get_instance(); - - /** * \brief Get the current delta time for the current frame. * * \return Delta time in seconds since the last frame. @@ -102,7 +96,7 @@ private: * * Private constructor for singleton pattern to restrict instantiation outside the class. */ - LoopTimer(); + LoopTimer(Mediator & mediator); /** * \brief Update the timer to the current frame. diff --git a/src/crepe/api/Sprite.cpp b/src/crepe/api/Sprite.cpp index cc0e20a..ba684ba 100644 --- a/src/crepe/api/Sprite.cpp +++ b/src/crepe/api/Sprite.cpp @@ -1,26 +1,21 @@ #include <cmath> -#include <utility> #include "../util/Log.h" +#include "api/Asset.h" #include "Component.h" #include "Sprite.h" -#include "Texture.h" #include "types.h" using namespace std; using namespace crepe; -Sprite::Sprite(game_object_id_t id, Texture & texture, const Sprite::Data & data) +Sprite::Sprite(game_object_id_t id, const Asset & texture, const Sprite::Data & data) : Component(id), - texture(std::move(texture)), + source(texture), data(data) { dbg_trace(); - - this->mask.w = this->texture.get_size().x; - this->mask.h = this->texture.get_size().y; - this->aspect_ratio = static_cast<double>(this->mask.w) / this->mask.h; } Sprite::~Sprite() { dbg_trace(); } diff --git a/src/crepe/api/Sprite.h b/src/crepe/api/Sprite.h index dbf41e4..a2409c2 100644 --- a/src/crepe/api/Sprite.h +++ b/src/crepe/api/Sprite.h @@ -1,9 +1,9 @@ #pragma once #include "../Component.h" +#include "api/Asset.h" #include "Color.h" -#include "Texture.h" #include "types.h" namespace crepe { @@ -74,24 +74,15 @@ public: * \param texture asset of the image * \param ctx all the sprite data */ - Sprite(game_object_id_t id, Texture & texture, const Data & data); + Sprite(game_object_id_t id, const Asset & texture, const Data & data); ~Sprite(); //! Texture used for the sprite - const Texture texture; + const Asset source; Data data; private: - /** - * \brief ratio of the img - * - * - This will multiply one of \c size variable if it is 0. - * - Will be adjusted if \c Animator component is added to an GameObject that is why this - * value cannot be const. - */ - float aspect_ratio; - //! Reads the mask of sprite friend class SDLContext; @@ -101,6 +92,14 @@ private: //! Reads the all the variables plus the mask friend class AnimatorSystem; + /** + * \aspect_ratio the ratio of the sprite image + * + * - this value will only be set by the \c Animator component for the ratio of the Animation + * - if \c Animator component is not added it will not use this ratio (because 0) and will use aspect_ratio of the Asset. + */ + float aspect_ratio = 0; + struct Rect { int w = 0; int h = 0; diff --git a/src/crepe/api/Texture.cpp b/src/crepe/api/Texture.cpp deleted file mode 100644 index 2b56271..0000000 --- a/src/crepe/api/Texture.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "../facade/SDLContext.h" -#include "../util/Log.h" - -#include "Asset.h" -#include "Texture.h" -#include "types.h" - -using namespace crepe; -using namespace std; - -Texture::Texture(const Asset & src) { - dbg_trace(); - this->load(src); -} - -Texture::~Texture() { - dbg_trace(); - this->texture.reset(); -} - -Texture::Texture(Texture && other) noexcept : texture(std::move(other.texture)) {} - -Texture & Texture::operator=(Texture && other) noexcept { - if (this != &other) { - texture = std::move(other.texture); - } - return *this; -} - -void Texture::load(const Asset & res) { - SDLContext & ctx = SDLContext::get_instance(); - this->texture = ctx.texture_from_path(res.get_path()); -} - -ivec2 Texture::get_size() const { - if (this->texture == nullptr) return {}; - return SDLContext::get_instance().get_size(*this); -} diff --git a/src/crepe/api/Texture.h b/src/crepe/api/Texture.h deleted file mode 100644 index 1817910..0000000 --- a/src/crepe/api/Texture.h +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once - -// FIXME: this header can't be included because this is an API header, and SDL2 development -// headers won't be bundled with crepe. Why is this facade in the API namespace? - -#include <SDL2/SDL_render.h> -#include <functional> -#include <memory> - -#include "Asset.h" -#include "types.h" - -namespace crepe { - -class SDLContext; -class Animator; - -/** - * \class Texture - * \brief Manages texture loading and properties. - * - * The Texture class is responsible for loading an image from a source and providing access to - * its dimensions. Textures can be used for rendering. - */ -class Texture { - -public: - /** - * \brief Constructs a Texture from an Asset resource. - * \param src Asset with texture data to load. - */ - Texture(const Asset & src); - - /** - * \brief Destroys the Texture instance, freeing associated resources. - */ - ~Texture(); - // FIXME: this constructor shouldn't be necessary because this class doesn't manage memory - - Texture(Texture && other) noexcept; - Texture & operator=(Texture && other) noexcept; - Texture(const Texture &) = delete; - Texture & operator=(const Texture &) = delete; - - /** - * \brief Gets the width and height of the texture. - * \return Width and height of the texture in pixels. - */ - ivec2 get_size() const; - -private: - /** - * \brief Loads the texture from an Asset resource. - * \param res Unique pointer to an Asset resource to load the texture from. - */ - void load(const Asset & res); - -private: - //! The texture of the class from the library - std::unique_ptr<SDL_Texture, std::function<void(SDL_Texture *)>> texture; - - //! Grants SDLContext access to private members. - friend class SDLContext; - - //! Grants Animator access to private members. - friend class Animator; -}; - -} // namespace crepe diff --git a/src/crepe/facade/CMakeLists.txt b/src/crepe/facade/CMakeLists.txt index 4cc53bc..0598e16 100644 --- a/src/crepe/facade/CMakeLists.txt +++ b/src/crepe/facade/CMakeLists.txt @@ -1,5 +1,6 @@ target_sources(crepe PUBLIC Sound.cpp + Texture.cpp SoundContext.cpp SDLContext.cpp DB.cpp @@ -7,6 +8,7 @@ target_sources(crepe PUBLIC target_sources(crepe PUBLIC FILE_SET HEADERS FILES Sound.h + Texture.h SoundContext.h SDLContext.h DB.h diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index 7676cfd..6644c51 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -19,23 +19,18 @@ #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::get_instance() { - static SDLContext instance; - return instance; -} - -SDLContext::SDLContext() { +SDLContext::SDLContext(Mediator & mediator) { dbg_trace(); - if (SDL_Init(SDL_INIT_VIDEO) != 0) { throw runtime_error(format("SDLContext: SDL_Init error: {}", SDL_GetError())); } @@ -63,6 +58,8 @@ SDLContext::SDLContext() { if (!(IMG_Init(img_flags) & img_flags)) { throw runtime_error("SDLContext: SDL_image could not initialize!"); } + + mediator.sdl_context = *this; } SDLContext::~SDLContext() { @@ -222,27 +219,20 @@ 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 * ctx.sprite.aspect_ratio; + size.x = data.size.y * aspect_ratio; } if (data.size.y == 0 && data.size.x != 0) { - size.y = data.size.x / ctx.sprite.aspect_ratio; + size.y = data.size.x / aspect_ratio; } - size *= cam_aux_data.render_scale * ctx.img_scale * data.scale_offset; vec2 screen_pos = (ctx.pos + data.position_offset - cam_aux_data.cam_pos @@ -259,24 +249,33 @@ 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 = this->get_src_rect(ctx.sprite); + 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_FRect dstrect = this->get_dst_rect(SDLContext::DestinationRectangleData{ .sprite = ctx.sprite, + .texture = ctx.texture, .pos = ctx.pos, .img_scale = ctx.scale, }); double angle = ctx.angle + data.angle_offset; - 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); + 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); } void SDLContext::update_camera_view(const Camera & cam, const vec2 & new_pos) { @@ -364,7 +363,7 @@ SDLContext::texture_from_path(const std::string & path) { ivec2 SDLContext::get_size(const Texture & ctx) { ivec2 size; - SDL_QueryTexture(ctx.texture.get(), NULL, NULL, &size.x, &size.y); + SDL_QueryTexture(ctx.get_img(), NULL, NULL, &size.x, &size.y); return size; } @@ -435,6 +434,6 @@ std::vector<SDLContext::EventData> SDLContext::get_events() { return event_list; } void SDLContext::set_color_texture(const Texture & texture, const Color & color) { - SDL_SetTextureColorMod(texture.texture.get(), color.r, color.g, color.b); - SDL_SetTextureAlphaMod(texture.texture.get(), color.a); + SDL_SetTextureColorMod(texture.get_img(), color.r, color.g, color.b); + SDL_SetTextureAlphaMod(texture.get_img(), color.a); } diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h index 6d50ab0..259d4b5 100644 --- a/src/crepe/facade/SDLContext.h +++ b/src/crepe/facade/SDLContext.h @@ -14,14 +14,15 @@ #include "api/Color.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 Texture; +class Mediator; + /** * \class SDLContext * \brief Facade for the SDL library @@ -62,6 +63,7 @@ public: //! rendering data needed to render on screen struct RenderContext { const Sprite & sprite; + const Texture & texture; const vec2 & pos; const double & angle; const double & scale; @@ -91,20 +93,27 @@ public: float scroll_delta = INFINITY; ivec2 rel_mouse_move = {-1, -1}; }; - /** - * \brief Gets the singleton instance of SDLContext. - * \return Reference to the SDLContext instance. - */ - static SDLContext & get_instance(); +public: 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; +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. * @@ -138,9 +147,7 @@ private: */ MouseButton sdl_to_mousebutton(Uint8 sdl_button); -private: - //! Will only use delay - friend class LoopTimer; +public: /** * \brief Gets the current SDL ticks since the program started. * \return Current ticks in milliseconds as a constant uint64_t. @@ -156,23 +163,7 @@ private: */ 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; - +public: /** * \brief Loads a texture from a file path. * \param path Path to the image file. @@ -183,14 +174,11 @@ private: /** * \brief Gets the size of a texture. * \param texture Reference to the Texture object. - * \return Width and height of the texture as an integer. + * \return Width and height of the texture as an integer in pixels. */ ivec2 get_size(const Texture & ctx); -private: - //! Will use draw,clear_screen, present_screen, camera. - friend class RenderSystem; - +public: /** * \brief Draws a sprite to the screen using the specified transform and camera. * \param RenderContext Reference to rendering data to draw @@ -213,29 +201,19 @@ private: */ void update_camera_view(const Camera & camera, const vec2 & new_pos); -private: +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 - * - * \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 + * \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; diff --git a/src/crepe/facade/Sound.cpp b/src/crepe/facade/Sound.cpp index ad50637..97e455e 100644 --- a/src/crepe/facade/Sound.cpp +++ b/src/crepe/facade/Sound.cpp @@ -6,7 +6,7 @@ using namespace crepe; using namespace std; -Sound::Sound(const Asset & src) : Resource(src) { +Sound::Sound(const Asset & src, Mediator & mediator) : Resource(src, mediator) { this->sample.load(src.get_path().c_str()); dbg_trace(); } diff --git a/src/crepe/facade/Sound.h b/src/crepe/facade/Sound.h index 85d141b..4a5d692 100644 --- a/src/crepe/facade/Sound.h +++ b/src/crepe/facade/Sound.h @@ -8,6 +8,7 @@ namespace crepe { class SoundContext; +class Mediator; /** * \brief Sound resource facade @@ -17,7 +18,7 @@ class SoundContext; */ class Sound : public Resource { public: - Sound(const Asset & src); + Sound(const Asset & src, Mediator & mediator); ~Sound(); // dbg_trace private: diff --git a/src/crepe/facade/Texture.cpp b/src/crepe/facade/Texture.cpp new file mode 100644 index 0000000..b63403d --- /dev/null +++ b/src/crepe/facade/Texture.cpp @@ -0,0 +1,28 @@ +#include "../util/Log.h" +#include "facade/SDLContext.h" +#include "manager/Mediator.h" + +#include "Resource.h" +#include "Texture.h" +#include "types.h" + +using namespace crepe; +using namespace std; + +Texture::Texture(const Asset & src, Mediator & mediator) : Resource(src, mediator) { + dbg_trace(); + SDLContext & ctx = mediator.sdl_context; + this->texture = ctx.texture_from_path(src.get_path()); + this->size = ctx.get_size(*this); + this->aspect_ratio = static_cast<float>(this->size.x) / this->size.y; +} + +Texture::~Texture() { + dbg_trace(); + this->texture.reset(); +} + +const ivec2 & Texture::get_size() const noexcept { return this->size; } +const float & Texture::get_ratio() const noexcept { return this->aspect_ratio; } + +SDL_Texture * Texture::get_img() const noexcept { return this->texture.get(); } diff --git a/src/crepe/facade/Texture.h b/src/crepe/facade/Texture.h new file mode 100644 index 0000000..cdacac4 --- /dev/null +++ b/src/crepe/facade/Texture.h @@ -0,0 +1,69 @@ +#pragma once + +#include <SDL2/SDL_render.h> +#include <memory> + +#include "../Resource.h" + +#include "types.h" + +namespace crepe { + +class Mediator; +class Asset; + +/** + * \class Texture + * \brief Manages texture loading and properties. + * + * The Texture class is responsible for loading an image from a source and providing access to + * its dimensions. Textures can be used for rendering. + */ +class Texture : public Resource { + +public: + /** + * \brief Constructs a Texture from an Asset resource. + * \param src Asset with texture data to load. + * \param mediator use the SDLContext reference to load the image + */ + Texture(const Asset & src, Mediator & mediator); + + /** + * \brief Destroys the Texture instance + */ + ~Texture(); + + /** + * \brief get width and height of image in pixels + * \return pixel size width and height + * + */ + const ivec2 & get_size() const noexcept; + + /** + * \brief aspect_ratio of image + * \return ratio + * + */ + const float & get_ratio() const noexcept; + + /** + * \brief get the image texture + * \return SDL_Texture + * + */ + SDL_Texture * get_img() const noexcept; + +private: + //! The texture of the class from the library + std::unique_ptr<SDL_Texture, std::function<void(SDL_Texture *)>> texture; + + // texture size in pixel + ivec2 size; + + //! ratio of image + float aspect_ratio; +}; + +} // namespace crepe diff --git a/src/crepe/manager/Mediator.h b/src/crepe/manager/Mediator.h index 35ac181..628154a 100644 --- a/src/crepe/manager/Mediator.h +++ b/src/crepe/manager/Mediator.h @@ -3,9 +3,7 @@ #include "../util/OptionalRef.h" // TODO: remove these singletons: -#include "../facade/SDLContext.h" #include "EventManager.h" -#include "api/LoopTimer.h" namespace crepe { @@ -13,6 +11,8 @@ class ComponentManager; class SceneManager; class SaveManager; class ResourceManager; +class SDLContext; +class LoopTimer; /** * Struct to pass references to classes that would otherwise need to be singletons down to @@ -27,13 +27,13 @@ class ResourceManager; * \warning This class should never be directly accessible from the API */ struct Mediator { + OptionalRef<SDLContext> sdl_context; OptionalRef<ComponentManager> component_manager; OptionalRef<SceneManager> scene_manager; OptionalRef<SaveManager> save_manager; OptionalRef<EventManager> event_manager = EventManager::get_instance(); OptionalRef<ResourceManager> resource_manager; - OptionalRef<SDLContext> sdl_context = SDLContext::get_instance(); - OptionalRef<LoopTimer> timer = LoopTimer::get_instance(); + OptionalRef<LoopTimer> timer; }; } // namespace crepe diff --git a/src/crepe/manager/ResourceManager.cpp b/src/crepe/manager/ResourceManager.cpp index 7c01808..a141a46 100644 --- a/src/crepe/manager/ResourceManager.cpp +++ b/src/crepe/manager/ResourceManager.cpp @@ -6,8 +6,8 @@ using namespace crepe; using namespace std; ResourceManager::ResourceManager(Mediator & mediator) : Manager(mediator) { - mediator.resource_manager = *this; dbg_trace(); + mediator.resource_manager = *this; } ResourceManager::~ResourceManager() { dbg_trace(); } diff --git a/src/crepe/manager/ResourceManager.hpp b/src/crepe/manager/ResourceManager.hpp index 5167d71..cf5c949 100644 --- a/src/crepe/manager/ResourceManager.hpp +++ b/src/crepe/manager/ResourceManager.hpp @@ -13,7 +13,7 @@ T & ResourceManager::get(const Asset & asset) { "cache must recieve a derivative class of Resource"); CacheEntry & entry = this->get_entry(asset); - if (entry.resource == nullptr) entry.resource = make_unique<T>(asset); + if (entry.resource == nullptr) entry.resource = make_unique<T>(asset, this->mediator); T * concrete_resource = dynamic_cast<T *>(entry.resource.get()); if (concrete_resource == nullptr) diff --git a/src/crepe/system/AISystem.cpp b/src/crepe/system/AISystem.cpp index e2e36a5..7f04432 100644 --- a/src/crepe/system/AISystem.cpp +++ b/src/crepe/system/AISystem.cpp @@ -12,10 +12,11 @@ using namespace crepe; void AISystem::update() { const Mediator & mediator = this->mediator; ComponentManager & mgr = mediator.component_manager; + LoopTimer & timer = mediator.timer; RefVector<AI> ai_components = mgr.get_components_by_type<AI>(); //TODO: Use fixed loop dt (this is not available at master at the moment) - double dt = LoopTimer::get_instance().get_delta_time(); + double dt = timer.get_delta_time(); // Loop through all AI components for (AI & ai : ai_components) { diff --git a/src/crepe/system/AnimatorSystem.cpp b/src/crepe/system/AnimatorSystem.cpp index 549c35d..d61ba35 100644 --- a/src/crepe/system/AnimatorSystem.cpp +++ b/src/crepe/system/AnimatorSystem.cpp @@ -23,7 +23,7 @@ void AnimatorSystem::update() { int last_frame = ctx.row; - int cycle_end = (ctx.cycle_end == -1) ? a.max_rows : ctx.cycle_end; + int cycle_end = (ctx.cycle_end == -1) ? a.grid_size.x : ctx.cycle_end; int total_frames = cycle_end - ctx.cycle_start; int curr_frame = static_cast<int>(elapsed_time / frame_duration) % total_frames; diff --git a/src/crepe/system/InputSystem.cpp b/src/crepe/system/InputSystem.cpp index aaa8bdf..a710ae2 100644 --- a/src/crepe/system/InputSystem.cpp +++ b/src/crepe/system/InputSystem.cpp @@ -1,6 +1,8 @@ #include "../api/Button.h" #include "../manager/ComponentManager.h" #include "../manager/EventManager.h" +#include "facade/SDLContext.h" +#include "util/Log.h" #include "InputSystem.h" @@ -9,7 +11,8 @@ using namespace crepe; void InputSystem::update() { ComponentManager & mgr = this->mediator.component_manager; EventManager & event_mgr = this->mediator.event_manager; - std::vector<SDLContext::EventData> event_list = SDLContext::get_instance().get_events(); + SDLContext & context = this->mediator.sdl_context; + std::vector<SDLContext::EventData> event_list = context.get_events(); RefVector<Button> buttons = mgr.get_components_by_type<Button>(); RefVector<Camera> cameras = mgr.get_components_by_type<Camera>(); OptionalRef<Camera> curr_cam_ref; diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index 1ce9059..7de2673 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -10,7 +10,9 @@ #include "../api/Sprite.h" #include "../api/Transform.h" #include "../facade/SDLContext.h" +#include "../facade/Texture.h" #include "../manager/ComponentManager.h" +#include "../manager/ResourceManager.h" #include "types.h" #include "RenderSystem.h" @@ -72,6 +74,8 @@ bool RenderSystem::render_particle(const Sprite & sprite, const double & scale) ComponentManager & mgr = this->mediator.component_manager; SDLContext & ctx = this->mediator.sdl_context; + ResourceManager & resource_manager = this->mediator.resource_manager; + Texture & res = resource_manager.get<Texture>(sprite.source); vector<reference_wrapper<ParticleEmitter>> emitters = mgr.get_components_by_id<ParticleEmitter>(sprite.game_object_id); @@ -88,6 +92,7 @@ bool RenderSystem::render_particle(const Sprite & sprite, const double & scale) ctx.draw(SDLContext::RenderContext{ .sprite = sprite, + .texture = res, .pos = p.position, .angle = p.angle, .scale = scale, @@ -98,8 +103,12 @@ bool RenderSystem::render_particle(const Sprite & sprite, const double & scale) } void RenderSystem::render_normal(const Sprite & sprite, const Transform & tm) { SDLContext & ctx = this->mediator.sdl_context; + ResourceManager & resource_manager = this->mediator.resource_manager; + const Texture & res = resource_manager.get<Texture>(sprite.source); + ctx.draw(SDLContext::RenderContext{ .sprite = sprite, + .texture = res, .pos = tm.position, .angle = tm.rotation, .scale = tm.scale, diff --git a/src/example/rendering_particle.cpp b/src/example/rendering_particle.cpp index 48e02ba..14f82c8 100644 --- a/src/example/rendering_particle.cpp +++ b/src/example/rendering_particle.cpp @@ -1,4 +1,4 @@ -#include "api/Button.h" +#include "api/Asset.h" #include <crepe/Component.h> #include <crepe/api/Animator.h> #include <crepe/api/Camera.h> @@ -8,12 +8,10 @@ #include <crepe/api/ParticleEmitter.h> #include <crepe/api/Rigidbody.h> #include <crepe/api/Sprite.h> -#include <crepe/api/Texture.h> #include <crepe/api/Transform.h> #include <crepe/manager/ComponentManager.h> #include <crepe/manager/Mediator.h> #include <crepe/types.h> -#include <functional> #include <iostream> using namespace crepe; @@ -44,13 +42,15 @@ using namespace std; class TestScene : public Scene { public: void load_scene() { + + cout << "TestScene" << endl; Mediator & mediator = this->mediator; ComponentManager & mgr = mediator.component_manager; GameObject game_object = mgr.new_object("", "", vec2{0, 0}, 0, 1); Color color(255, 255, 255, 255); - auto img = Texture("asset/spritesheet/pokemon_spritesheet.png"); + Asset img{"asset/spritesheet/spritesheet_test.png"}; Sprite & test_sprite = game_object.add_component<Sprite>( img, Sprite::Data{ @@ -63,13 +63,8 @@ public: .position_offset = {0, 0}, }); - auto & anim = game_object.add_component<Animator>(test_sprite, 4, 4, - Animator::Data{ - .fps = 1, - .looping = false, - }); - anim.set_anim(2); - anim.pause(); + //auto & anim = game_object.add_component<Animator>(test_sprite,ivec2{32, 64}, uvec2{4,1}, Animator::Data{}); + //anim.set_anim(0); auto & cam = game_object.add_component<Camera>(ivec2{720, 1280}, vec2{400, 400}, Camera::Data{ diff --git a/src/test/InputTest.cpp b/src/test/InputTest.cpp index 73eaab3..4c05e56 100644 --- a/src/test/InputTest.cpp +++ b/src/test/InputTest.cpp @@ -24,6 +24,7 @@ class InputTest : public ::testing::Test { public: Mediator mediator; ComponentManager mgr{mediator}; + SDLContext sdl_context{mediator}; InputSystem input_system{mediator}; diff --git a/src/test/ParticleTest.cpp b/src/test/ParticleTest.cpp index 1409c4f..9112a3f 100644 --- a/src/test/ParticleTest.cpp +++ b/src/test/ParticleTest.cpp @@ -1,10 +1,10 @@ +#include "api/Asset.h" #include <crepe/Particle.h> #include <crepe/api/Config.h> #include <crepe/api/GameObject.h> #include <crepe/api/ParticleEmitter.h> #include <crepe/api/Rigidbody.h> #include <crepe/api/Sprite.h> -#include <crepe/api/Texture.h> #include <crepe/api/Transform.h> #include <crepe/manager/ComponentManager.h> #include <crepe/system/ParticleSystem.h> @@ -30,7 +30,7 @@ public: GameObject game_object = mgr.new_object("", "", vec2{0, 0}, 0, 0); Color color(0, 0, 0, 0); - auto s1 = Texture("asset/texture/img.png"); + auto s1 = Asset("asset/texture/img.png"); Sprite & test_sprite = game_object.add_component<Sprite>( s1, Sprite::Data{ .color = color, diff --git a/src/test/Profiling.cpp b/src/test/Profiling.cpp index c753bca..cc4c637 100644 --- a/src/test/Profiling.cpp +++ b/src/test/Profiling.cpp @@ -1,9 +1,11 @@ -#include "manager/Mediator.h" -#include "system/ParticleSystem.h" -#include "system/PhysicsSystem.h" -#include "system/RenderSystem.h" #include <chrono> #include <cmath> +#include <crepe/api/Asset.h> +#include <crepe/manager/Mediator.h> +#include <crepe/manager/ResourceManager.h> +#include <crepe/system/ParticleSystem.h> +#include <crepe/system/PhysicsSystem.h> +#include <crepe/system/RenderSystem.h> #include <gtest/gtest.h> #define private public @@ -54,6 +56,8 @@ public: const std::chrono::microseconds duration = 16000us; Mediator m; + SDLContext sdl_context{m}; + ResourceManager resman{m}; ComponentManager mgr{m}; // Add system used for profling tests CollisionSystem collision_sys{m}; @@ -167,15 +171,15 @@ TEST_F(DISABLED_ProfilingTest, Profiling_2) { gameobject.add_component<BoxCollider>(vec2{0, 0}, vec2{1, 1}); gameobject.add_component<BehaviorScript>().set_script<TestScript>(); - auto img = Texture("asset/texture/square.png"); Sprite & test_sprite = gameobject.add_component<Sprite>( - img, Sprite::Data{ - .color = {0, 0, 0, 0}, - .flip = {.flip_x = false, .flip_y = false}, - .sorting_in_layer = 1, - .order_in_layer = 1, - .size = {.y = 500}, - }); + Asset{"asset/texture/square.png"}, + Sprite::Data{ + .color = {0, 0, 0, 0}, + .flip = {.flip_x = false, .flip_y = false}, + .sorting_in_layer = 1, + .order_in_layer = 1, + .size = {.y = 500}, + }); } this->game_object_count++; @@ -205,15 +209,15 @@ TEST_F(DISABLED_ProfilingTest, Profiling_3) { }); gameobject.add_component<BoxCollider>(vec2{0, 0}, vec2{1, 1}); gameobject.add_component<BehaviorScript>().set_script<TestScript>(); - auto img = Texture("asset/texture/square.png"); Sprite & test_sprite = gameobject.add_component<Sprite>( - img, Sprite::Data{ - .color = {0, 0, 0, 0}, - .flip = {.flip_x = false, .flip_y = false}, - .sorting_in_layer = 1, - .order_in_layer = 1, - .size = {.y = 500}, - }); + Asset{"asset/texture/square.png"}, + Sprite::Data{ + .color = {0, 0, 0, 0}, + .flip = {.flip_x = false, .flip_y = false}, + .sorting_in_layer = 1, + .order_in_layer = 1, + .size = {.y = 500}, + }); auto & test = gameobject.add_component<ParticleEmitter>(ParticleEmitter::Data{ .max_particles = 10, .emission_rate = 100, diff --git a/src/test/RenderSystemTest.cpp b/src/test/RenderSystemTest.cpp index 205f534..b4519cb 100644 --- a/src/test/RenderSystemTest.cpp +++ b/src/test/RenderSystemTest.cpp @@ -1,3 +1,6 @@ +#include "api/Asset.h" +#include "facade/SDLContext.h" +#include "manager/ResourceManager.h" #include "types.h" #include <functional> #include <gtest/gtest.h> @@ -11,7 +14,6 @@ #include <crepe/api/Color.h> #include <crepe/api/GameObject.h> #include <crepe/api/Sprite.h> -#include <crepe/api/Texture.h> #include <crepe/manager/ComponentManager.h> #include <crepe/system/RenderSystem.h> @@ -25,6 +27,8 @@ class RenderSystemTest : public Test { public: ComponentManager mgr{m}; + SDLContext ctx{m}; + ResourceManager resource_manager{m}; RenderSystem sys{m}; GameObject entity1 = this->mgr.new_object("name"); GameObject entity2 = this->mgr.new_object("name"); @@ -32,10 +36,10 @@ public: GameObject entity4 = this->mgr.new_object("name"); void SetUp() override { - auto s1 = Texture("asset/texture/img.png"); - auto s2 = Texture("asset/texture/img.png"); - auto s3 = Texture("asset/texture/img.png"); - auto s4 = Texture("asset/texture/img.png"); + auto s1 = Asset("asset/texture/img.png"); + auto s2 = Asset("asset/texture/img.png"); + auto s3 = Asset("asset/texture/img.png"); + auto s4 = Asset("asset/texture/img.png"); auto & sprite1 = entity1.add_component<Sprite>(s1, Sprite::Data{ .color = Color(0, 0, 0, 0), @@ -45,7 +49,6 @@ public: .size = {10, 10}, }); - ASSERT_NE(sprite1.texture.texture.get(), nullptr); EXPECT_EQ(sprite1.data.order_in_layer, 5); EXPECT_EQ(sprite1.data.sorting_in_layer, 5); auto & sprite2 @@ -55,7 +58,6 @@ public: .sorting_in_layer = 2, .order_in_layer = 1, }); - ASSERT_NE(sprite2.texture.texture.get(), nullptr); EXPECT_EQ(sprite2.data.sorting_in_layer, 2); EXPECT_EQ(sprite2.data.order_in_layer, 1); @@ -66,7 +68,6 @@ public: .sorting_in_layer = 1, .order_in_layer = 2, }); - ASSERT_NE(sprite3.texture.texture.get(), nullptr); EXPECT_EQ(sprite3.data.sorting_in_layer, 1); EXPECT_EQ(sprite3.data.order_in_layer, 2); @@ -77,27 +78,12 @@ public: .sorting_in_layer = 1, .order_in_layer = 1, }); - ASSERT_NE(sprite4.texture.texture.get(), nullptr); EXPECT_EQ(sprite4.data.sorting_in_layer, 1); EXPECT_EQ(sprite4.data.order_in_layer, 1); } }; -TEST_F(RenderSystemTest, expected_throws) { - GameObject entity1 = this->mgr.new_object("NAME"); - - // no texture img - EXPECT_ANY_THROW({ - auto test = Texture(""); - auto & sprite1 = entity1.add_component<Sprite>( - test, Sprite::Data{ - .color = Color(0, 0, 0, 0), - .flip = Sprite::FlipSettings{false, false}, - .sorting_in_layer = 1, - .order_in_layer = 1, - }); - }); - +TEST_F(RenderSystemTest, NoCamera) { // No camera EXPECT_ANY_THROW({ this->sys.update(); }); } @@ -185,7 +171,7 @@ TEST_F(RenderSystemTest, Color) { Camera::Data{.bg_color = Color::WHITE, .zoom = 1.0f}); auto & sprite = this->mgr.get_components_by_id<Sprite>(entity1.id).front().get(); - ASSERT_NE(sprite.texture.texture.get(), nullptr); + //ASSERT_NE(sprite.texture.texture.get(), nullptr); sprite.data.color = Color::GREEN; EXPECT_EQ(sprite.data.color.r, Color::GREEN.r); diff --git a/src/test/ResourceManagerTest.cpp b/src/test/ResourceManagerTest.cpp index 44a5921..965eeab 100644 --- a/src/test/ResourceManagerTest.cpp +++ b/src/test/ResourceManagerTest.cpp @@ -1,3 +1,4 @@ +#include "manager/Mediator.h" #include <gtest/gtest.h> #define private public @@ -30,7 +31,9 @@ public: public: const unsigned instance; - TestResource(const Asset & src) : Resource(src), instance(this->instances++) {} + TestResource(const Asset & src, Mediator & mediator) + : Resource(src, mediator), + instance(this->instances++) {} ~TestResource() { this->instances--; } bool operator==(const TestResource & other) const { return this->instance == other.instance; |