#include "Sprite.hpp" #include "Game.hpp" Sprite::Sprite() : Sprite(NULL) {} Sprite::Sprite(Node* parent) : Node(parent, true), current_frameset_name(get_configuration()["animation"]["all-frames-frameset-name"]) { add_frameset(current_frameset_name); frame_animation.play(); } Sprite::Sprite(Node* parent, std::string path) : Sprite(parent) { associate(path); } void Sprite::set_frame_length(float length) { frame_animation.set_frame_length(length); } void Sprite::associate(std::string path) { if (fs::is_regular_file(path)) { frame_paths.push_back(fs::path(path)); } else if (fs::is_directory(path)) { fs::directory_iterator directory(path); std::vector paths; std::copy(directory, fs::directory_iterator(), std::back_inserter(paths)); std::sort(paths.begin(), paths.end()); for (const fs::path &name : paths) { frame_paths.push_back(name); } } else { std::ostringstream message; message << "invalid path " << path; get_root()->print_error(message.str()); } } void Sprite::load() { for (const fs::path &path : frame_paths) { load_file(path); } } void Sprite::load_file(fs::path path) { Game *game = get_root(); SDL_Texture *texture = IMG_LoadTexture(game->renderer, path.string().c_str()); if (not texture) { game->print_sdl_error("Could not load image"); } else { add_frame(texture); } } void Sprite::add_frame(SDL_Texture* texture) { frames.push_back(texture); Frameset& all_frames_frameset = get_all_frames_frameset(); all_frames_frameset.clear(); for (int ii = 0; ii < frames.size(); ii++) { all_frames_frameset.add_frame_index(ii); } for (auto& member : framesets) { member.second.set_size(); } update_size(); } Frameset& Sprite::get_all_frames_frameset() { return framesets[get_configuration()["animation"]["all-frames-frameset-name"]]; } Frameset& Sprite::add_frameset(std::string name) { if (framesets.find(name) == framesets.end()) { framesets[name] = Frameset(this); } return framesets[name]; } void Sprite::set_frameset(std::string name) { current_frameset_name = name; frame_animation.set_frame_length(get_current_frameset().get_frame_length()); update_size(); } Frameset& Sprite::get_current_frameset() { return framesets[current_frameset_name]; } void Sprite::update_size() { box.set_size(get_current_frameset().get_size()); } bool Sprite::is_loaded() const { return !frames.empty(); } void Sprite::unload() { while (!frames.empty()) { SDL_DestroyTexture(frames.back()); frames.pop_back(); } box.zero(); } void Sprite::advance_frame() { get_current_frameset().step(); } void Sprite::hide() { hidden = true; } void Sprite::unhide() { hidden = false; } void Sprite::toggle_hidden() { hidden = !hidden; } bool Sprite::is_hidden() const { return hidden; } void Sprite::set_step(glm::vec2 s) { step.x = s.x; step.y = s.y; } float Sprite::get_w() const { return box.get_w(); } float Sprite::get_h() const { return box.get_h(); } glm::vec2 Sprite::get_size() const { return box.get_size(); } float Sprite::get_top() const { return box.get_top(); } float Sprite::get_right() const { return box.get_right(); } float Sprite::get_bottom() const { return box.get_bottom(); } float Sprite::get_left() const { return box.get_left(); } glm::vec2 Sprite::get_nw() const { return box.get_nw(); } glm::vec2 Sprite::get_north() const { return box.get_north(); } glm::vec2 Sprite::get_west() const { return box.get_west(); } void Sprite::set_nw(const glm::vec2& nw) { box.set_nw(nw); } void Sprite::move(glm::vec2 delta, bool weighted) { Game *game = get_root(); if (weighted) { delta = game->weight(delta); } box.move(delta); } void Sprite::update() { if (active) { move(step); frame_animation.update(); blink_animation.update(); if (is_loaded() && !is_hidden() && get_current_frameset().get_frame_count()) { int index = get_current_frameset().get_current_frame_index(); SDL_Texture* texture = frames[index]; SDL_Renderer* renderer = get_root()->renderer; SDL_SetTextureAlphaMod(texture, alpha_mod); SDL_SetRenderTarget(renderer, NULL); SDL_RenderCopyF(renderer, texture, NULL, box.get_rect()); } } } Frameset::Frameset() : Frameset(NULL) {} Frameset::Frameset(Sprite* sprite) : sprite(sprite) {} void Frameset::add_frame_index(int index) { add_frame_indicies({index}); } void Frameset::add_frame_indicies(const std::vector& indicies) { order.insert(order.end(), indicies.begin(), indicies.end()); } void Frameset::set_frame_length(float length) { frame_length = length; } float Frameset::get_frame_length() const { return frame_length; } void Frameset::reset() { current_index = 0; } void Frameset::clear() { order.clear(); reset(); } int Frameset::get_current_frame_index() const { return order[current_index]; } glm::vec2 Frameset::measure() const { glm::vec2 s(0, 0); int w, h; for (int index : order) { if (index < sprite->frames.size()) { SDL_QueryTexture(sprite->frames[index], NULL, NULL, &w, &h); s.x = std::max(static_cast(w), s.x); s.y = std::max(static_cast(h), s.y); } } return s; } void Frameset::set_size() { set_size(measure()); } void Frameset::set_size(const glm::vec2& s) { size = s; } const glm::vec2& Frameset::get_size() const { return size; } void Frameset::step() { if (order.size() > 0) { increment_index(); } } void Frameset::increment_index() { int increment; if (!reversed) { increment = 1; } else { increment = -1; } increment_index(increment); } void Frameset::increment_index(int increment) { current_index = (current_index + increment) % order.size(); } int Frameset::get_frame_count() const { return order.size(); } void Frameset::reverse() { reversed = !reversed; }