162 lines
4.0 KiB
C++
162 lines
4.0 KiB
C++
#include <algorithm>
|
|
#include <cassert>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <GL/glew.h>
|
|
#include <imgui.h>
|
|
|
|
#include "app.hh"
|
|
#include "input.hh"
|
|
|
|
|
|
namespace pg {
|
|
namespace {
|
|
|
|
class Player final : public App {
|
|
public:
|
|
static inline TypeInfo kType = TypeInfo::Create<Player>("Player");
|
|
|
|
static constexpr size_t kTexW = 1024;
|
|
static constexpr size_t kTexH = 1024;
|
|
|
|
Player() noexcept {
|
|
glGenTextures(1, &tex_);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, tex_);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
}
|
|
~Player() noexcept {
|
|
glDeleteTextures(1, &tex_);
|
|
}
|
|
|
|
void Update() noexcept override {
|
|
const auto em = ImGui::GetFontSize();
|
|
const auto id = "Player | "+
|
|
std::to_string(reinterpret_cast<uintptr_t>(this));
|
|
|
|
ImGui::SetNextWindowSize({32*em, 16*em}, ImGuiCond_Once);
|
|
if (ImGui::Begin(id.c_str())) {
|
|
bool mod = false;
|
|
|
|
ImGui::BeginGroup();
|
|
{
|
|
ImGui::PushItemWidth(4*em);
|
|
mod |= ImGui::DragInt("input_slot", &slot_, 1, 0, 1024);
|
|
mod |= ImGui::DragInt("time", &t_, 1, 0, 1024);
|
|
|
|
ImGui::Checkbox("auto increment", &auto_inc_);
|
|
if (auto_inc_) {
|
|
++t_; mod = true;
|
|
}
|
|
|
|
ImGui::PopItemWidth();
|
|
}
|
|
ImGui::EndGroup();
|
|
ImGui::SameLine();
|
|
|
|
ImVec2 img_min = {0, 0};
|
|
ImVec2 img_max = {0, 0};
|
|
if (mod) UpdateTex();
|
|
const auto wf = static_cast<float>(w_);
|
|
const auto hf = static_cast<float>(h_);
|
|
|
|
ImGui::BeginGroup();
|
|
{
|
|
if (w_ && h_) {
|
|
const auto tex = (void*) (uintptr_t) tex_;
|
|
const auto z = wf / ImGui::GetContentRegionAvail().x;
|
|
ImGui::Image(tex, {wf/z, hf/z}, {0, 0}, uv_);
|
|
img_min = ImGui::GetItemRectMin();
|
|
img_max = ImGui::GetItemRectMax();
|
|
}
|
|
}
|
|
ImGui::EndGroup();
|
|
|
|
if (msg_.size() > 0) {
|
|
ImGui::TextUnformatted(msg_.c_str());
|
|
} else if (w_ && h_) {
|
|
const auto m = ImGui::GetMousePos();
|
|
const auto xf = (m.x-img_min.x)/(img_max.x-img_min.x);
|
|
const auto yf = (m.y-img_min.y)/(img_max.y-img_min.y);
|
|
ImGui::Text("x=%f, y=%f, xf=%f, yf=%f", xf*wf, yf*hf, xf, yf);
|
|
} else {
|
|
ImGui::TextUnformatted("no image shown");
|
|
}
|
|
}
|
|
ImGui::End();
|
|
}
|
|
|
|
private:
|
|
std::string msg_;
|
|
|
|
int slot_ = 0;
|
|
int t_ = 0;
|
|
bool auto_inc_ = false;
|
|
|
|
GLsizei w_ = 0, h_ = 0;
|
|
ImVec2 uv_;
|
|
|
|
GLuint tex_;
|
|
GLsizei texw_ = 0, texh_ = 0;
|
|
|
|
|
|
void UpdateTex() noexcept
|
|
try {
|
|
msg_ = "";
|
|
|
|
auto data = Input::instance().slots(static_cast<size_t>(slot_));
|
|
if (data == nullptr) {
|
|
throw "missing slot";
|
|
}
|
|
if (static_cast<size_t>(t_) >= data->frames()) {
|
|
throw "time out of range";
|
|
}
|
|
const auto frame = data->Fetch(static_cast<size_t>(t_));
|
|
if (!frame.rgba) {
|
|
throw "got an empty frame";
|
|
}
|
|
w_ = static_cast<GLsizei>(frame.w);
|
|
h_ = static_cast<GLsizei>(frame.h);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, tex_);
|
|
|
|
const auto ptexw = texw_;
|
|
const auto ptexh = texh_;
|
|
texw_ = std::max(texw_, NextPowerOf2(w_));
|
|
texh_ = std::max(texh_, NextPowerOf2(h_));
|
|
if (texw_ != ptexw || texh_ != ptexh) {
|
|
glTexImage2D(
|
|
GL_TEXTURE_2D, 0, GL_RGBA, texw_, texh_,
|
|
0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
|
}
|
|
|
|
glTexSubImage2D(
|
|
GL_TEXTURE_2D, 0, 0, 0, w_, h_,
|
|
GL_RGBA, GL_UNSIGNED_BYTE, frame.rgba);
|
|
uv_ = {
|
|
static_cast<float>(w_)/static_cast<float>(texw_),
|
|
static_cast<float>(h_)/static_cast<float>(texh_)};
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
assert(glGetError() == 0);
|
|
} catch (const char* msg) {
|
|
msg_ = msg;
|
|
}
|
|
|
|
|
|
template <typename I>
|
|
static I NextPowerOf2(I x) {
|
|
I y = 1;
|
|
while (y < x) y *= 2;
|
|
return y;
|
|
}
|
|
};
|
|
|
|
}
|
|
} // namespace pg
|