spacebox/src/Sprite.cpp

354 lines
6.2 KiB
C++

#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<fs::path> 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<int>& 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<float>(w), s.x);
s.y = std::max(static_cast<float>(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;
}