mirror of https://github.com/auygun/kaliber.git
117 lines
3.2 KiB
C++
117 lines
3.2 KiB
C++
#include "engine/image_quad.h"
|
|
|
|
#include "base/log.h"
|
|
#include "engine/engine.h"
|
|
#include "engine/renderer/geometry.h"
|
|
#include "engine/renderer/shader.h"
|
|
#include "engine/renderer/texture.h"
|
|
|
|
using namespace base;
|
|
|
|
namespace eng {
|
|
|
|
ImageQuad::ImageQuad() = default;
|
|
|
|
ImageQuad::~ImageQuad() {
|
|
Destory();
|
|
}
|
|
|
|
void ImageQuad::Create(const std::string& asset_name,
|
|
std::array<int, 2> num_frames,
|
|
int frame_width,
|
|
int frame_height) {
|
|
texture_ = Engine::Get().AcquireTexture(asset_name);
|
|
|
|
num_frames_ = std::move(num_frames);
|
|
frame_width_ = frame_width;
|
|
frame_height_ = frame_height;
|
|
|
|
if ((frame_width_ > 0 && frame_height_ > 0) || texture_->IsValid())
|
|
AutoScale();
|
|
|
|
asset_name_ = asset_name;
|
|
}
|
|
|
|
void ImageQuad::Destory() {
|
|
Engine::Get().ReleaseTexture(asset_name_);
|
|
texture_ = nullptr;
|
|
}
|
|
|
|
void ImageQuad::AutoScale() {
|
|
auto& engine = Engine::Get();
|
|
Vector2f dimensions = {GetFrameWidth(), GetFrameHeight()};
|
|
Vector2f size = engine.ToScale(dimensions);
|
|
float s =
|
|
static_cast<float>(engine.image_dpi()) * engine.GetImageScaleFactor();
|
|
size *= static_cast<float>(engine.GetDeviceDpi()) / s;
|
|
SetSize(size);
|
|
}
|
|
|
|
void ImageQuad::SetCustomShader(Shader* shader) {
|
|
custom_shader_ = shader;
|
|
custom_uniforms_.clear();
|
|
}
|
|
|
|
void ImageQuad::SetFrame(size_t frame) {
|
|
DCHECK(frame < GetNumFrames())
|
|
<< "asset: " << asset_name_ << " frame: " << frame;
|
|
current_frame_ = frame;
|
|
}
|
|
|
|
size_t ImageQuad::GetNumFrames() const {
|
|
return num_frames_[0] * num_frames_[1];
|
|
}
|
|
|
|
void ImageQuad::Draw(float frame_frac) {
|
|
DCHECK(IsVisible());
|
|
|
|
if (!texture_ || !texture_->IsValid())
|
|
return;
|
|
|
|
texture_->Activate();
|
|
|
|
Vector2f tex_scale = {GetFrameWidth() / texture_->GetWidth(),
|
|
GetFrameHeight() / texture_->GetHeight()};
|
|
|
|
Shader* shader =
|
|
custom_shader_ ? custom_shader_ : Engine::Get().GetPassThroughShader();
|
|
|
|
shader->Activate();
|
|
shader->SetUniform("offset", position_);
|
|
shader->SetUniform("scale", GetSize());
|
|
shader->SetUniform("rotation", rotation_);
|
|
shader->SetUniform("tex_offset", GetUVOffset(current_frame_));
|
|
shader->SetUniform("tex_scale", tex_scale);
|
|
shader->SetUniform("projection", Engine::Get().GetProjectionMatrix());
|
|
shader->SetUniform("color", color_);
|
|
shader->SetUniform("texture_0", 0);
|
|
if (custom_shader_) {
|
|
for (auto& cu : custom_uniforms_)
|
|
std::visit(
|
|
[shader, &cu](auto&& arg) { shader->SetUniform(cu.first, arg); },
|
|
cu.second);
|
|
}
|
|
shader->UploadUniforms();
|
|
|
|
Engine::Get().GetQuad()->Draw();
|
|
}
|
|
|
|
float ImageQuad::GetFrameWidth() const {
|
|
return frame_width_ > 0 ? (float)frame_width_
|
|
: texture_->GetWidth() / (float)num_frames_[0];
|
|
}
|
|
|
|
float ImageQuad::GetFrameHeight() const {
|
|
return frame_height_ > 0 ? (float)frame_height_
|
|
: texture_->GetHeight() / (float)num_frames_[1];
|
|
}
|
|
|
|
// Return the uv offset for the given frame.
|
|
Vector2f ImageQuad::GetUVOffset(int frame) const {
|
|
DCHECK(frame < GetNumFrames())
|
|
<< "asset: " << asset_name_ << " frame: " << frame;
|
|
return {(float)(frame % num_frames_[0]), (float)(frame / num_frames_[0])};
|
|
}
|
|
|
|
} // namespace eng
|