diff --git a/demo/Demo.cpp b/demo/Demo.cpp index 4153e5c..82dde40 100644 --- a/demo/Demo.cpp +++ b/demo/Demo.cpp @@ -10,7 +10,8 @@ config parameters on command line, effects chain, asset dict with metadata, move added sprite locations by offset when location is changed, gradients, level select code input, logging, variable screen resolution, debug display, - loading wheel animation, shadowed sprite, separate update and draw + loading wheel animation, shadowed sprite, separate update and draw, sprite + movement cage :) SWEATY HANDS :) OILY SNACKS :) AND BAD HYGIENE :) diff --git a/src/Box.cpp b/src/Box.cpp index debb30d..f5241b4 100644 --- a/src/Box.cpp +++ b/src/Box.cpp @@ -47,10 +47,15 @@ glm::vec2 Box::get_size() const return glm::vec2(get_w(), get_h()); } -void Box::set_size(const glm::vec2& size) +void Box::set_size(const glm::vec2& size, bool preserve_center) { + glm::vec2 center = get_center(); set_w(size.x); set_h(size.y); + if (preserve_center) + { + set_center(center); + } } float Box::get_top() const @@ -179,10 +184,15 @@ void Box::clear() set_size(glm::vec2(0, 0)); } -void Box::scale(float amount) +void Box::scale(float amount, bool preserve_center) { + glm::vec2 center = get_center(); set_w(get_w() * amount); set_h(get_h() * amount); + if (preserve_center) + { + set_center(center); + } } void Box::move(const glm::vec2& delta) diff --git a/src/Box.hpp b/src/Box.hpp index f628716..94187ff 100644 --- a/src/Box.hpp +++ b/src/Box.hpp @@ -23,7 +23,7 @@ struct Box void set_w(float); void set_h(float); glm::vec2 get_size() const; - void set_size(const glm::vec2&); + void set_size(const glm::vec2&, bool = false); float get_top() const; float get_right() const; float get_bottom() const; @@ -49,7 +49,7 @@ struct Box SDL_FRect* get_rect(); SDL_Rect get_int_rect(); void clear(); - void scale(float); + void scale(float, bool = false); void move(const glm::vec2&); std::string get_class_name() { return "Box"; } std::ostream& to_string (std::ostream&) const; diff --git a/src/Delegate.cpp b/src/Delegate.cpp index 14617ae..9e20399 100644 --- a/src/Delegate.cpp +++ b/src/Delegate.cpp @@ -58,8 +58,8 @@ bool Delegate::compare(SDL_Event& event, const std::vector& command bool Delegate::compare(SDL_Event& event, const std::string& command, bool neutral, bool cancel) { return event.type == command_event_type && - (command == "" || command == *static_cast(event.user.data1)) && - (neutral || (cancel == *static_cast(event.user.data2))); + (command == "" || command == get_event_command(event)) && + (neutral || (cancel == get_event_cancel_state(event))); } bool Delegate::compare_cancel(SDL_Event& event, const std::string& command) @@ -76,3 +76,13 @@ void Delegate::cancel_propagation() { cancelling_propagation = true; } + +const std::string& Delegate::get_event_command(SDL_Event& event) const +{ + return *static_cast(event.user.data1); +} + +bool Delegate::get_event_cancel_state(SDL_Event& event) const +{ + return *static_cast(event.user.data2); +} diff --git a/src/Delegate.hpp b/src/Delegate.hpp index 24db5fb..1ef6de1 100644 --- a/src/Delegate.hpp +++ b/src/Delegate.hpp @@ -33,6 +33,8 @@ struct Delegate : Node bool compare_cancel(SDL_Event&, const std::string& = ""); bool compare_neutral(SDL_Event&, const std::string& = ""); void cancel_propagation(); + const std::string& get_event_command(SDL_Event&) const; + bool get_event_cancel_state(SDL_Event&) const; template void subscribe(void(T::*f)(SDL_Event&), T* o, int type = command_event_type) diff --git a/src/Node.hpp b/src/Node.hpp index b2d9917..c20ae3c 100644 --- a/src/Node.hpp +++ b/src/Node.hpp @@ -23,6 +23,7 @@ struct Node void set_parent(Node*); void activate(); void deactivate(); + virtual void reset() { deactivate(); }; bool is_active() const; nlohmann::json& get_configuration(); Delegate& get_delegate(); diff --git a/src/Sprite.cpp b/src/Sprite.cpp index d0fa20f..c331ff1 100644 --- a/src/Sprite.cpp +++ b/src/Sprite.cpp @@ -51,7 +51,10 @@ void Sprite::load() void Sprite::load_file(fs::path path) { Game *game = get_root(); + const char* previous_scale_quality = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, scale_quality.c_str()); SDL_Texture *texture = IMG_LoadTexture(game->renderer, path.string().c_str()); + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, previous_scale_quality); if (not texture) { game->print_sdl_error("Could not load image"); @@ -64,6 +67,7 @@ void Sprite::load_file(fs::path path) void Sprite::add_frame(SDL_Texture* texture) { + bool preserve_center = frames.size() > 0; frames.push_back(texture); Frameset& all_frames_frameset = get_all_frames_frameset(); all_frames_frameset.clear(); @@ -75,7 +79,7 @@ void Sprite::add_frame(SDL_Texture* texture) { member.second.set_size(); } - update_size(); + update_size(preserve_center); } Frameset& Sprite::get_all_frames_frameset() @@ -96,7 +100,7 @@ Frameset& Sprite::set_frameset(std::string name) { current_frameset_name = name; frame_animation.set_frame_length(get_current_frameset().get_frame_length()); - update_size(); + update_size(true); return get_current_frameset(); } @@ -119,22 +123,27 @@ void Sprite::add_box(glm::vec2 position, bool absolute) boxes.emplace_back(glm::vec2(position.x, position.y), glm::vec2(get_w(), get_h())); } -void Sprite::update_size() +void Sprite::update_size(bool preserve_center) { - for (Box& box : boxes) + for (int ii = 0; ii < boxes.size(); ii++) { - box.set_size(get_current_frameset().get_size()); + get_box(ii).set_size(get_current_frameset().get_size(), preserve_center); + if (scale != 1) + { + get_box(ii).scale(scale, preserve_center); + } } } void Sprite::set_scale(float s) { scale = s; - for (auto& member : framesets) - { - member.second.set_size(member.second.get_size() * s); - } - update_size(); + update_size(true); +} + +void Sprite::set_scale_quality(const std::string& quality) +{ + scale_quality = quality; } float Sprite::get_scale() const @@ -256,6 +265,11 @@ glm::vec2 Sprite::get_east(int index) return get_box(index).get_east(); } +glm::vec2 Sprite::get_south(int index) +{ + return get_box(index).get_south(); +} + glm::vec2 Sprite::get_west(int index) { return get_box(index).get_west(); @@ -266,6 +280,11 @@ glm::vec2 Sprite::get_center(int index) return get_box(index).get_center(); } +void Sprite::set_south(const glm::vec2& south) +{ + move(south - get_south(), false); +} + void Sprite::set_nw(const glm::vec2& nw) { move(nw - get_nw(), false); @@ -362,9 +381,9 @@ void Sprite::update() SDL_Rect wrap_frame_rect = wrap_frame.get_int_rect(); SDL_RenderSetClipRect(renderer, &wrap_frame_rect); } - for (Box& box : boxes) + for (int ii = 0; ii < boxes.size(); ii++) { - SDL_RenderCopyF(renderer, texture, NULL, box.get_rect()); + SDL_RenderCopyF(renderer, texture, NULL, get_box(ii).get_rect()); } if (wrap.x || wrap.y) { @@ -400,7 +419,7 @@ float Frameset::get_frame_length() const void Frameset::reset() { - current_index = 0; + set_order_index(0); } void Frameset::clear() @@ -409,9 +428,19 @@ void Frameset::clear() reset(); } +int Frameset::get_order_index() const +{ + return order_index; +} + +void Frameset::set_order_index(int index) +{ + order_index = index; +} + int Frameset::get_current_frame_index() const { - return order[current_index]; + return order[get_order_index()]; } glm::vec2 Frameset::measure() const @@ -469,7 +498,7 @@ void Frameset::increment_index() void Frameset::increment_index(int increment) { - current_index = (current_index + increment) % order.size(); + set_order_index((order_index + increment) % order.size()); } int Frameset::get_frame_count() const diff --git a/src/Sprite.hpp b/src/Sprite.hpp index 8109144..c6fcd36 100644 --- a/src/Sprite.hpp +++ b/src/Sprite.hpp @@ -29,6 +29,7 @@ struct Sprite : Node bool hidden = false; glm::vec2 step = {0, 0}; float scale = 1; + std::string scale_quality = "nearest"; Uint8 alpha_mod = 255; std::map framesets; std::string current_frameset_name; @@ -48,8 +49,9 @@ struct Sprite : Node Frameset& get_current_frameset(); Box& get_box(int = 0); void add_box(glm::vec2, bool = false); - void update_size(); + void update_size(bool = false); void set_scale(float); + void set_scale_quality(const std::string&); float get_scale() const; bool is_loaded() const; void unload(); @@ -72,10 +74,12 @@ struct Sprite : Node glm::vec2 get_north(int = 0); glm::vec2 get_ne(int = 0); glm::vec2 get_east(int = 0); + glm::vec2 get_south(int = 0); glm::vec2 get_west(int = 0); glm::vec2 get_center(int = 0); void set_nw(const glm::vec2&); void set_ne(const glm::vec2&); + void set_south(const glm::vec2&); void set_center(const glm::vec2&); void add_wrap(bool, bool); void add_wrap(bool, bool, Box); @@ -91,7 +95,7 @@ struct Frameset Sprite* sprite; std::vector order; - int current_index = 0; + int order_index = 0; float frame_length = 0; bool reversed = false; glm::vec2 size; @@ -104,6 +108,8 @@ struct Frameset float get_frame_length() const; void reset(); void clear(); + int get_order_index() const; + void set_order_index(int); int get_current_frame_index() const; glm::vec2 measure() const; void set_size(); diff --git a/src/extension.cpp b/src/extension.cpp index 94e2579..4f8e7cc 100644 --- a/src/extension.cpp +++ b/src/extension.cpp @@ -18,9 +18,10 @@ Box sfw::get_texture_box(SDL_Texture* texture) return Box(glm::vec2(0, 0), glm::vec2(w, h)); } -void sfw::fill_texture(SDL_Renderer* renderer, SDL_Texture* texture, int r, int g, int b, int a) +void sfw::fill_texture(SDL_Renderer* renderer, SDL_Texture* texture, Uint8 r, Uint8 g, Uint8 b, Uint8 a) { SDL_SetRenderTarget(renderer, texture); + SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE); SDL_SetRenderDrawColor(renderer, r, g, b, a); SDL_RenderFillRect(renderer, NULL); } @@ -40,6 +41,20 @@ void sfw::fill_texture(SDL_Renderer* renderer, SDL_Texture* texture, SDL_Texture } } +SDL_Texture* sfw::get_filled_texture(SDL_Renderer* renderer, glm::vec2 size, const SDL_Color& color, Uint32 format) +{ + SDL_Texture* texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, size.x, size.y); + sfw::fill_texture(renderer, texture, color.r, color.g, color.b, color.a); + return texture; +} + +SDL_Texture* sfw::get_filled_texture(SDL_Renderer* renderer, glm::vec2 size, SDL_Texture* tile, Uint32 format) +{ + SDL_Texture* texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_TARGET, size.x, size.y); + sfw::fill_texture(renderer, texture, tile); + return texture; +} + SDL_Texture* sfw::duplicate_texture(SDL_Renderer* renderer, SDL_Texture* base, Uint32 format) { Box box = get_texture_box(base); diff --git a/src/extension.hpp b/src/extension.hpp index bdd1b3b..dc2eddc 100644 --- a/src/extension.hpp +++ b/src/extension.hpp @@ -28,8 +28,10 @@ namespace sfw glm::vec2 get_step(glm::vec2, glm::vec2, float); void set_magnitude(glm::vec2&, float); Box get_texture_box(SDL_Texture*); - void fill_texture(SDL_Renderer*, SDL_Texture*, int, int, int, int = 0xff); + void fill_texture(SDL_Renderer*, SDL_Texture*, Uint8, Uint8, Uint8, Uint8 = 0xff); void fill_texture(SDL_Renderer*, SDL_Texture*, SDL_Texture*); + SDL_Texture* get_filled_texture(SDL_Renderer*, glm::vec2, const SDL_Color&, Uint32 = SDL_PIXELFORMAT_RGBA32); + SDL_Texture* get_filled_texture(SDL_Renderer*, glm::vec2, SDL_Texture*, Uint32 = SDL_PIXELFORMAT_RGBA32); SDL_Texture* duplicate_texture(SDL_Renderer*, SDL_Texture*, Uint32 = SDL_PIXELFORMAT_RGBA32); SDL_Texture* get_remapped_texture( SDL_Renderer*, SDL_Texture*, const std::map&, Uint32 = SDL_PIXELFORMAT_RGBA32); @@ -43,6 +45,18 @@ namespace sfw void print_error(const std::string&); void print_sdl_error(const std::string&); + template class Map> + std::vector get_keys(const Map& map) + { + std::vector keys; + keys.reserve(map.size()); + for (auto& member : map) + { + keys.push_back(member.first); + } + return keys; + } + template bool is_in_container(T1& container, T2& member) {