488 lines
9.0 KiB
C++
488 lines
9.0 KiB
C++
#include "Sprite.hpp"
|
|
#include "Game.hpp"
|
|
|
|
Sprite::Sprite() : Sprite(NULL) {}
|
|
|
|
Sprite::Sprite(Node* parent) :
|
|
Node(parent), 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];
|
|
}
|
|
|
|
Box& Sprite::get_box(int index)
|
|
{
|
|
return boxes[index];
|
|
}
|
|
|
|
void Sprite::add_box(glm::vec2 position, bool absolute)
|
|
{
|
|
if (!absolute)
|
|
{
|
|
position += get_nw();
|
|
}
|
|
boxes.emplace_back(glm::vec2(position.x, position.y), glm::vec2(get_w(), get_h()));
|
|
}
|
|
|
|
void Sprite::update_size()
|
|
{
|
|
for (Box& box : boxes)
|
|
{
|
|
box.set_size(get_current_frameset().get_size());
|
|
}
|
|
}
|
|
|
|
void Sprite::set_scale(float s)
|
|
{
|
|
scale = s;
|
|
for (auto& member : framesets)
|
|
{
|
|
member.second.set_size(member.second.get_size() * s);
|
|
}
|
|
update_size();
|
|
}
|
|
|
|
float Sprite::get_scale() const
|
|
{
|
|
return scale;
|
|
}
|
|
|
|
bool Sprite::is_loaded() const
|
|
{
|
|
return !frames.empty();
|
|
}
|
|
|
|
void Sprite::unload()
|
|
{
|
|
while (!frames.empty())
|
|
{
|
|
SDL_DestroyTexture(frames.back());
|
|
frames.pop_back();
|
|
}
|
|
for (Box& box : boxes)
|
|
{
|
|
box.clear();
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void Sprite::set_alpha_mod(Uint8 mod)
|
|
{
|
|
alpha_mod = mod;
|
|
}
|
|
|
|
Uint8 Sprite::get_alpha_mod() const
|
|
{
|
|
return alpha_mod;
|
|
}
|
|
|
|
float Sprite::get_w()
|
|
{
|
|
return get_box().get_w();
|
|
}
|
|
|
|
float Sprite::get_h()
|
|
{
|
|
return get_box().get_h();
|
|
}
|
|
|
|
glm::vec2 Sprite::get_size()
|
|
{
|
|
return get_box().get_size();
|
|
}
|
|
|
|
float Sprite::get_top(int index)
|
|
{
|
|
return get_box(index).get_top();
|
|
}
|
|
|
|
float Sprite::get_right(int index)
|
|
{
|
|
return get_box(index).get_right();
|
|
}
|
|
|
|
float Sprite::get_bottom(int index)
|
|
{
|
|
return get_box(index).get_bottom();
|
|
}
|
|
|
|
float Sprite::get_left(int index)
|
|
{
|
|
return get_box(index).get_left();
|
|
}
|
|
|
|
glm::vec2 Sprite::get_nw(int index)
|
|
{
|
|
return get_box(index).get_nw();
|
|
}
|
|
|
|
glm::vec2 Sprite::get_north(int index)
|
|
{
|
|
return get_box(index).get_north();
|
|
}
|
|
|
|
glm::vec2 Sprite::get_ne(int index)
|
|
{
|
|
return get_box(index).get_ne();
|
|
}
|
|
|
|
glm::vec2 Sprite::get_east(int index)
|
|
{
|
|
return get_box(index).get_east();
|
|
}
|
|
|
|
glm::vec2 Sprite::get_west(int index)
|
|
{
|
|
return get_box(index).get_west();
|
|
}
|
|
|
|
glm::vec2 Sprite::get_center(int index)
|
|
{
|
|
return get_box(index).get_center();
|
|
}
|
|
|
|
void Sprite::set_nw(const glm::vec2& nw)
|
|
{
|
|
move(nw - get_nw(), false);
|
|
}
|
|
|
|
void Sprite::set_ne(const glm::vec2& ne)
|
|
{
|
|
move(ne - get_ne(), false);
|
|
}
|
|
|
|
void Sprite::set_center(const glm::vec2& center)
|
|
{
|
|
move(center - get_center(), false);
|
|
}
|
|
|
|
void Sprite::add_wrap(bool x, bool y)
|
|
{
|
|
add_wrap(x, y, get_display().get_window_box());
|
|
}
|
|
|
|
void Sprite::add_wrap(bool x, bool y, Box frame)
|
|
{
|
|
wrap = {x, y};
|
|
int original_box_count = boxes.size();
|
|
for (int ii = 0; ii < original_box_count; ii++)
|
|
{
|
|
if (x)
|
|
{
|
|
add_box({frame.get_w(), 0});
|
|
}
|
|
if (y)
|
|
{
|
|
add_box({0, frame.get_h()});
|
|
}
|
|
if (x && y)
|
|
{
|
|
add_box({frame.get_w(), frame.get_h()});
|
|
}
|
|
}
|
|
wrap_frame = frame;
|
|
}
|
|
|
|
glm::vec2 Sprite::move(glm::vec2 delta, bool weighted)
|
|
{
|
|
if (weighted)
|
|
{
|
|
delta = get_root()->weight(delta);
|
|
}
|
|
for (Box& box : boxes)
|
|
{
|
|
box.move(delta);
|
|
}
|
|
if (wrap.x)
|
|
{
|
|
if (get_right() > wrap_frame.get_right())
|
|
{
|
|
move({-wrap_frame.get_w(), 0}, false);
|
|
}
|
|
else if (get_right() < wrap_frame.get_left())
|
|
{
|
|
move({wrap_frame.get_w(), 0}, false);
|
|
}
|
|
}
|
|
if (wrap.y)
|
|
{
|
|
if (get_bottom() > wrap_frame.get_bottom())
|
|
{
|
|
move({0, -wrap_frame.get_h()}, false);
|
|
}
|
|
else if (get_bottom() < wrap_frame.get_top())
|
|
{
|
|
move({0, wrap_frame.get_h()}, false);
|
|
}
|
|
}
|
|
return 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);
|
|
if (wrap.x || wrap.y)
|
|
{
|
|
SDL_Rect wrap_frame_rect = wrap_frame.get_int_rect();
|
|
SDL_RenderSetClipRect(renderer, &wrap_frame_rect);
|
|
}
|
|
for (Box& box : boxes)
|
|
{
|
|
SDL_RenderCopyF(renderer, texture, NULL, box.get_rect());
|
|
}
|
|
if (wrap.x || wrap.y)
|
|
{
|
|
SDL_RenderSetClipRect(renderer, NULL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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 * sprite->scale), s.x);
|
|
s.y = std::max(static_cast<float>(h * sprite->scale), 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;
|
|
}
|