[nostalgia/core/studio] Add scrolling support to TileSheetEditor
This commit is contained in:
parent
9af7eb2fd7
commit
96e2510e64
@ -6,10 +6,12 @@
|
|||||||
|
|
||||||
#include <ox/std/types.hpp>
|
#include <ox/std/types.hpp>
|
||||||
#include <ox/model/def.hpp>
|
#include <ox/model/def.hpp>
|
||||||
|
#include <nostalgia/common/point.hpp>
|
||||||
#include <nostalgia/common/size.hpp>
|
#include <nostalgia/common/size.hpp>
|
||||||
|
|
||||||
#include "color.hpp"
|
#include "color.hpp"
|
||||||
#include "context.hpp"
|
#include "context.hpp"
|
||||||
|
#include "ptidxconv.hpp"
|
||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
@ -36,6 +38,46 @@ struct NostalgiaGraphic {
|
|||||||
ox::FileAddress defaultPalette;
|
ox::FileAddress defaultPalette;
|
||||||
NostalgiaPalette pal;
|
NostalgiaPalette pal;
|
||||||
ox::Vector<uint8_t> pixels;
|
ox::Vector<uint8_t> pixels;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr auto getPixel4Bpp(const common::Point &pt) const noexcept {
|
||||||
|
oxAssert(bpp == 4, "NostalgiaGraphic::getPixel4Bpp: wrong bpp");
|
||||||
|
const auto idx = ptToIdx(pt, this->columns);
|
||||||
|
if (idx & 1) {
|
||||||
|
return this->pixels[idx / 2];
|
||||||
|
} else {
|
||||||
|
return this->pixels[idx / 2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr auto getPixel8Bpp(const common::Point &pt) const noexcept {
|
||||||
|
oxAssert(bpp == 8, "NostalgiaGraphic::getPixel8Bpp: wrong bpp");
|
||||||
|
const auto idx = ptToIdx(pt, this->columns);
|
||||||
|
return this->pixels[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
constexpr auto getPixel(const common::Point &pt) const noexcept {
|
||||||
|
if (this->bpp == 4) {
|
||||||
|
return getPixel4Bpp(pt);
|
||||||
|
} else {
|
||||||
|
return getPixel8Bpp(pt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void setPixel(const common::Point &pt, uint8_t palIdx) noexcept {
|
||||||
|
const auto idx = ptToIdx(pt, this->columns);
|
||||||
|
if (bpp == 4) {
|
||||||
|
if (idx & 1) {
|
||||||
|
pixels[idx / 2] &= 0b0000'1111 | (palIdx << 4);
|
||||||
|
} else {
|
||||||
|
pixels[idx / 2] &= 0b1111'0000 | (palIdx);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this->pixels[idx] = palIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
oxModelBegin(NostalgiaPalette)
|
oxModelBegin(NostalgiaPalette)
|
||||||
|
@ -6,26 +6,28 @@
|
|||||||
|
|
||||||
#include <nostalgia/common/point.hpp>
|
#include <nostalgia/common/point.hpp>
|
||||||
|
|
||||||
|
#include "consts.hpp"
|
||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr int pointToIdx(int w, int x, int y) noexcept {
|
constexpr std::size_t pointToIdx(int w, int x, int y) noexcept {
|
||||||
constexpr auto colLength = PixelsPerTile;
|
constexpr auto colLength = static_cast<std::size_t>(PixelsPerTile);
|
||||||
const auto rowLength = (w / TileWidth) * colLength;
|
const auto rowLength = static_cast<std::size_t>(static_cast<std::size_t>(w / TileWidth) * colLength);
|
||||||
const auto colStart = colLength * (x / TileWidth);
|
const auto colStart = static_cast<std::size_t>(colLength * static_cast<std::size_t>(x / TileWidth));
|
||||||
const auto rowStart = rowLength * (y / TileHeight);
|
const auto rowStart = static_cast<std::size_t>(rowLength * static_cast<std::size_t>(y / TileHeight));
|
||||||
const auto colOffset = x % TileWidth;
|
const auto colOffset = static_cast<std::size_t>(x % TileWidth);
|
||||||
const auto rowOffset = (y % TileHeight) * TileHeight;
|
const auto rowOffset = static_cast<std::size_t>((y % TileHeight) * TileHeight);
|
||||||
return colStart + colOffset + rowStart + rowOffset;
|
return static_cast<std::size_t>(colStart + colOffset + rowStart + rowOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr int ptToIdx(int x, int y, int c) noexcept {
|
constexpr std::size_t ptToIdx(int x, int y, int c) noexcept {
|
||||||
return pointToIdx(c * TileWidth, x, y);
|
return pointToIdx(c * TileWidth, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr int ptToIdx(common::Point pt, int c) noexcept {
|
constexpr std::size_t ptToIdx(common::Point pt, int c) noexcept {
|
||||||
return pointToIdx(c * TileWidth, pt.x, pt.y);
|
return pointToIdx(c * TileWidth, pt.x, pt.y);
|
||||||
}
|
}
|
||||||
|
|
@ -7,7 +7,9 @@
|
|||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
#include <nostalgia/common/point.hpp>
|
#include <nostalgia/common/point.hpp>
|
||||||
|
#include <nostalgia/core/consts.hpp>
|
||||||
#include <nostalgia/core/media.hpp>
|
#include <nostalgia/core/media.hpp>
|
||||||
|
#include <nostalgia/core/ptidxconv.hpp>
|
||||||
|
|
||||||
#include "tilesheeteditor.hpp"
|
#include "tilesheeteditor.hpp"
|
||||||
|
|
||||||
@ -15,12 +17,11 @@ namespace nostalgia::core {
|
|||||||
|
|
||||||
TileSheetEditor::TileSheetEditor(Context *ctx, const ox::String &path) {
|
TileSheetEditor::TileSheetEditor(Context *ctx, const ox::String &path) {
|
||||||
m_itemPath = path;
|
m_itemPath = path;
|
||||||
const auto lastSlash = std::find(m_itemPath.crbegin(), m_itemPath.crend(), '/').offset();
|
const auto lastSlash = std::find(m_itemPath.rbegin(), m_itemPath.rend(), '/').offset();
|
||||||
m_itemName = m_itemPath.substr(lastSlash + 1);
|
m_itemName = m_itemPath.substr(lastSlash + 1);
|
||||||
m_ctx = ctx;
|
|
||||||
// build shaders
|
// build shaders
|
||||||
oxThrowError(m_pixels.buildShader());
|
oxThrowError(m_pixelsDrawer.buildShader());
|
||||||
oxThrowError(m_pixelGrid.buildShader());
|
oxThrowError(m_pixelGridDrawer.buildShader());
|
||||||
oxRequireT(img, readObj<NostalgiaGraphic>(ctx, m_itemPath.c_str()));
|
oxRequireT(img, readObj<NostalgiaGraphic>(ctx, m_itemPath.c_str()));
|
||||||
oxThrowError(readObj<NostalgiaPalette>(ctx, img->defaultPalette).moveTo(&m_pal));
|
oxThrowError(readObj<NostalgiaPalette>(ctx, img->defaultPalette).moveTo(&m_pal));
|
||||||
m_img = *img;
|
m_img = *img;
|
||||||
@ -47,36 +48,56 @@ void TileSheetEditor::paste() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetEditor::draw(core::Context*) noexcept {
|
void TileSheetEditor::draw(core::Context*) noexcept {
|
||||||
const auto size = ImGui::GetContentRegionAvail();
|
const auto paneSize = ImGui::GetContentRegionAvail();
|
||||||
const auto sizei = common::Size(static_cast<int>(size.x), static_cast<int>(size.y));
|
const auto sizei = common::Size(static_cast<int>(paneSize.x), static_cast<int>(paneSize.y));
|
||||||
if (m_updated || m_framebuffer.width != sizei.width || m_framebuffer.height != sizei.height) {
|
if (m_framebuffer.width != sizei.width || m_framebuffer.height != sizei.height) {
|
||||||
if (!m_framebuffer) {
|
|
||||||
m_framebuffer = glutils::generateFrameBuffer(sizei.width, sizei.height);
|
m_framebuffer = glutils::generateFrameBuffer(sizei.width, sizei.height);
|
||||||
}
|
m_pixelsDrawer.initBufferSet(m_img, *m_pal);
|
||||||
m_pixels.initBufferSet(m_img, *m_pal);
|
m_pixelGridDrawer.initBufferSet(m_img);
|
||||||
m_pixelGrid.initBufferSet(m_img);
|
} else if (m_updated) {
|
||||||
|
m_pixelsDrawer.initBufferSet(m_img, *m_pal);
|
||||||
|
m_pixelGridDrawer.initBufferSet(m_img);
|
||||||
}
|
}
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
|
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
|
||||||
glViewport(0, 0, sizei.width, sizei.height);
|
glViewport(0, 0, sizei.width, sizei.height);
|
||||||
glDraw();
|
glDraw();
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
ImGui::Image(reinterpret_cast<void*>(m_framebuffer.color.id), size, ImVec2(0, 1), ImVec2(1, 0));
|
ImGui::Image(reinterpret_cast<void*>(m_framebuffer.color.id), paneSize, ImVec2(0, 1), ImVec2(1, 0));
|
||||||
|
// handle input, this must come after drawing
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
const auto &io = ImGui::GetIO();
|
const auto &io = ImGui::GetIO();
|
||||||
const auto wheel = io.MouseWheel * 0.01f;
|
const auto wheel = io.MouseWheel;
|
||||||
|
const auto wheelh = io.MouseWheelH;
|
||||||
|
if (wheel != 0) {
|
||||||
const auto zoomMod = ox::defines::OS == ox::defines::OS::Darwin ? io.KeySuper : io.KeyCtrl;
|
const auto zoomMod = ox::defines::OS == ox::defines::OS::Darwin ? io.KeySuper : io.KeyCtrl;
|
||||||
if (zoomMod && wheel != 0) {
|
const auto pixelSize = m_pixelsDrawer.pixelSize(paneSize);
|
||||||
m_pixelSizeMod = ox::clamp(m_pixelSizeMod + wheel, 0.55f, 2.f);
|
const ImVec2 sheetSize(pixelSize.x * static_cast<float>(m_img.columns) * TileWidth,
|
||||||
m_pixels.setPixelSizeMod(m_pixelSizeMod);
|
pixelSize.y * static_cast<float>(m_img.rows) * TileHeight);
|
||||||
m_pixelGrid.setPixelSizeMod(m_pixelSizeMod);
|
if (zoomMod) {
|
||||||
|
m_pixelSizeMod = ox::clamp(m_pixelSizeMod + wheel * 0.02f, 0.55f, 2.f);
|
||||||
|
m_pixelsDrawer.setPixelSizeMod(m_pixelSizeMod);
|
||||||
|
m_pixelGridDrawer.setPixelSizeMod(m_pixelSizeMod);
|
||||||
m_updated = true;
|
m_updated = true;
|
||||||
|
} else {
|
||||||
|
m_scrollOffset.y -= wheel * 0.1f;
|
||||||
}
|
}
|
||||||
if (io.MouseClicked[0]) {
|
// adjust scroll offset in both cases because the image can be zoomed
|
||||||
auto clickPos = io.MouseClickedPos[0];
|
// or scrolled off screen
|
||||||
|
m_scrollOffset.y = ox::clamp(m_scrollOffset.y, 0.f, sheetSize.y / 2);
|
||||||
|
}
|
||||||
|
if (wheelh != 0) {
|
||||||
|
const auto pixelSize = m_pixelsDrawer.pixelSize(paneSize);
|
||||||
|
const ImVec2 sheetSize(pixelSize.x * static_cast<float>(m_img.columns) * TileWidth,
|
||||||
|
pixelSize.y * static_cast<float>(m_img.rows) * TileHeight);
|
||||||
|
m_scrollOffset.x += wheelh * 0.1f;
|
||||||
|
m_scrollOffset.x = ox::clamp(m_scrollOffset.x, -(sheetSize.x / 2), 0.f);
|
||||||
|
}
|
||||||
|
if (io.MouseDown[0]) {
|
||||||
|
auto clickPos = io.MousePos;
|
||||||
const auto &winPos = ImGui::GetWindowPos();
|
const auto &winPos = ImGui::GetWindowPos();
|
||||||
clickPos.x -= winPos.x;
|
clickPos.x -= winPos.x + 8;
|
||||||
clickPos.y -= winPos.y;
|
clickPos.y -= winPos.y + 31;
|
||||||
std::cout << clickPos.x - 8 << ", " << clickPos.y - 31 << '\n';
|
clickPixel(paneSize, clickPos.x, clickPos.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,8 +107,8 @@ void TileSheetEditor::glDraw() noexcept {
|
|||||||
constexpr Color32 bgColor = 0x717d7e;
|
constexpr Color32 bgColor = 0x717d7e;
|
||||||
glClearColor(redf(bgColor), greenf(bgColor), bluef(bgColor), 1.f);
|
glClearColor(redf(bgColor), greenf(bgColor), bluef(bgColor), 1.f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
m_pixels.draw(m_updated);
|
m_pixelsDrawer.draw(m_updated, m_scrollOffset);
|
||||||
m_pixelGrid.draw(m_updated);
|
m_pixelGridDrawer.draw(m_updated, m_scrollOffset);
|
||||||
m_updated = false;
|
m_updated = false;
|
||||||
//oxAssert(glGetError() == 0, "There was an OpenGL error");
|
//oxAssert(glGetError() == 0, "There was an OpenGL error");
|
||||||
}
|
}
|
||||||
@ -95,4 +116,50 @@ void TileSheetEditor::glDraw() noexcept {
|
|||||||
void TileSheetEditor::saveItem() {
|
void TileSheetEditor::saveItem() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TileSheetEditor::getFillPixels(bool *pixels, common::Point pt, int oldColor) const {
|
||||||
|
const auto tileIdx = [this](const common::Point &pt) noexcept {
|
||||||
|
return ptToIdx(pt, m_img.columns) / PixelsPerTile;
|
||||||
|
};
|
||||||
|
// get points
|
||||||
|
const auto leftPt = pt + common::Point(-1, 0);
|
||||||
|
const auto rightPt = pt + common::Point(1, 0);
|
||||||
|
const auto topPt = pt + common::Point(0, -1);
|
||||||
|
const auto bottomPt = pt + common::Point(0, 1);
|
||||||
|
// calculate indices
|
||||||
|
const auto idx = ptToIdx(pt, m_img.columns);
|
||||||
|
const auto leftIdx = ptToIdx(leftPt, m_img.columns);
|
||||||
|
const auto rightIdx = ptToIdx(rightPt, m_img.columns);
|
||||||
|
const auto topIdx = ptToIdx(topPt, m_img.columns);
|
||||||
|
const auto bottomIdx = ptToIdx(bottomPt, m_img.columns);
|
||||||
|
const auto tile = tileIdx(pt);
|
||||||
|
// mark pixels to update
|
||||||
|
pixels[idx % PixelsPerTile] = true;
|
||||||
|
if (!pixels[leftIdx % PixelsPerTile] && tile == tileIdx(leftPt) && m_img.pixels[leftIdx] == oldColor) {
|
||||||
|
getFillPixels(pixels, leftPt, oldColor);
|
||||||
|
}
|
||||||
|
if (!pixels[rightIdx % PixelsPerTile] && tile == tileIdx(rightPt) && m_img.pixels[rightIdx] == oldColor) {
|
||||||
|
getFillPixels(pixels, rightPt, oldColor);
|
||||||
|
}
|
||||||
|
if (!pixels[topIdx % PixelsPerTile] && tile == tileIdx(topPt) && m_img.pixels[topIdx] == oldColor) {
|
||||||
|
getFillPixels(pixels, topPt, oldColor);
|
||||||
|
}
|
||||||
|
if (!pixels[bottomIdx % PixelsPerTile] && tile == tileIdx(bottomPt) && m_img.pixels[bottomIdx] == oldColor) {
|
||||||
|
getFillPixels(pixels, bottomPt, oldColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TileSheetEditor::clickPixel(const ImVec2 &paneSize, float x, float y) noexcept {
|
||||||
|
const auto pixDrawSz = m_pixelsDrawer.pixelSize(paneSize);
|
||||||
|
x /= paneSize.x;
|
||||||
|
y /= paneSize.y;
|
||||||
|
x += m_scrollOffset.x / 2;
|
||||||
|
y += m_scrollOffset.y / 2;
|
||||||
|
x /= pixDrawSz.x;
|
||||||
|
y /= pixDrawSz.y;
|
||||||
|
const auto pt = common::Point(static_cast<int>(x * 2), static_cast<int>(y * 2));
|
||||||
|
const uint8_t palIdx = 0;
|
||||||
|
m_img.setPixel(pt, palIdx);
|
||||||
|
m_updated = true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -100,13 +100,13 @@ class TileSheetEditor: public studio::Editor {
|
|||||||
ox::String m_itemPath;
|
ox::String m_itemPath;
|
||||||
ox::String m_itemName;
|
ox::String m_itemName;
|
||||||
glutils::FrameBuffer m_framebuffer;
|
glutils::FrameBuffer m_framebuffer;
|
||||||
TileSheetGrid m_pixelGrid;
|
TileSheetGrid m_pixelGridDrawer;
|
||||||
TileSheetPixels m_pixels;
|
TileSheetPixels m_pixelsDrawer;
|
||||||
bool m_updated = false;
|
bool m_updated = false;
|
||||||
NostalgiaGraphic m_img;
|
NostalgiaGraphic m_img;
|
||||||
AssetRef<NostalgiaPalette> m_pal;
|
AssetRef<NostalgiaPalette> m_pal;
|
||||||
Context *m_ctx = nullptr;
|
|
||||||
float m_pixelSizeMod = 1;
|
float m_pixelSizeMod = 1;
|
||||||
|
ImVec2 m_scrollOffset;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TileSheetEditor(Context *ctx, const ox::String &path);
|
TileSheetEditor(Context *ctx, const ox::String &path);
|
||||||
@ -132,6 +132,8 @@ class TileSheetEditor: public studio::Editor {
|
|||||||
protected:
|
protected:
|
||||||
void saveItem() override;
|
void saveItem() override;
|
||||||
|
|
||||||
|
void getFillPixels(bool *pixels, common::Point pt, int oldColor) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setPalette();
|
void setPalette();
|
||||||
|
|
||||||
@ -145,6 +147,8 @@ class TileSheetEditor: public studio::Editor {
|
|||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
ox::String palettePath(const ox::String &palettePath) const;
|
ox::String palettePath(const ox::String &palettePath) const;
|
||||||
|
|
||||||
|
void clickPixel(const ImVec2 &paneSize, float x, float y) noexcept;
|
||||||
|
|
||||||
// slots
|
// slots
|
||||||
public:
|
public:
|
||||||
ox::Error colorSelected() noexcept;
|
ox::Error colorSelected() noexcept;
|
||||||
|
@ -18,13 +18,15 @@ ox::Error TileSheetGrid::buildShader() noexcept {
|
|||||||
return glutils::buildShaderProgram(pixelLineVshad, pixelLineFshad, pixelLineGshad).moveTo(&m_shader);
|
return glutils::buildShaderProgram(pixelLineVshad, pixelLineFshad, pixelLineGshad).moveTo(&m_shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetGrid::draw(bool update) noexcept {
|
void TileSheetGrid::draw(bool update, const ImVec2 &scroll) noexcept {
|
||||||
glLineWidth(3);
|
glLineWidth(3 * m_pixelSizeMod * 0.5f);
|
||||||
glUseProgram(m_shader);
|
glUseProgram(m_shader);
|
||||||
glBindVertexArray(m_bufferSet.vao);
|
glBindVertexArray(m_bufferSet.vao);
|
||||||
if (update) {
|
if (update) {
|
||||||
glutils::sendVbo(m_bufferSet);
|
glutils::sendVbo(m_bufferSet);
|
||||||
}
|
}
|
||||||
|
const auto uniformScroll = static_cast<GLint>(glGetUniformLocation(m_shader, "gScroll"));
|
||||||
|
glUniform2f(uniformScroll, scroll.x, scroll.y);
|
||||||
glDrawArrays(GL_POINTS, 0, m_bufferSet.vertices.size() / VertexVboRowLength);
|
glDrawArrays(GL_POINTS, 0, m_bufferSet.vertices.size() / VertexVboRowLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,8 +98,8 @@ void TileSheetGrid::setBufferObjects(const NostalgiaGraphic &img, glutils::Buffe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImVec2 TileSheetGrid::pixelSize() const noexcept {
|
ImVec2 TileSheetGrid::pixelSize(const ImVec2 &paneSize) const noexcept {
|
||||||
const auto [sw, sh] = ImGui::GetContentRegionAvail();
|
const auto [sw, sh] = paneSize;
|
||||||
constexpr float ymod = 0.35f / 10.0f;
|
constexpr float ymod = 0.35f / 10.0f;
|
||||||
const auto xmod = ymod * sh / sw;
|
const auto xmod = ymod * sh / sw;
|
||||||
return {xmod * m_pixelSizeMod, ymod * m_pixelSizeMod};
|
return {xmod * m_pixelSizeMod, ymod * m_pixelSizeMod};
|
||||||
|
@ -49,11 +49,12 @@ class TileSheetGrid {
|
|||||||
in vec3 gColor[];
|
in vec3 gColor[];
|
||||||
in vec2 gPt2[];
|
in vec2 gPt2[];
|
||||||
out vec3 fColor;
|
out vec3 fColor;
|
||||||
|
uniform vec2 gScroll;
|
||||||
void main() {
|
void main() {
|
||||||
fColor = gColor[0];
|
fColor = gColor[0];
|
||||||
gl_Position = gl_in[0].gl_Position;
|
gl_Position = gl_in[0].gl_Position + vec4(gScroll, 0, 0);
|
||||||
EmitVertex();
|
EmitVertex();
|
||||||
gl_Position = vec4(gPt2[0], 0, 1);
|
gl_Position = vec4(gPt2[0] + gScroll, 0, 1);
|
||||||
EmitVertex();
|
EmitVertex();
|
||||||
EndPrimitive();
|
EndPrimitive();
|
||||||
})glsl";
|
})glsl";
|
||||||
@ -67,7 +68,7 @@ class TileSheetGrid {
|
|||||||
|
|
||||||
ox::Error buildShader() noexcept;
|
ox::Error buildShader() noexcept;
|
||||||
|
|
||||||
void draw(bool update) noexcept;
|
void draw(bool update, const ImVec2 &scroll) noexcept;
|
||||||
|
|
||||||
void initBufferSet(const NostalgiaGraphic &img) noexcept;
|
void initBufferSet(const NostalgiaGraphic &img) noexcept;
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ class TileSheetGrid {
|
|||||||
void setBufferObjects(const NostalgiaGraphic &img, glutils::BufferSet *bg) noexcept;
|
void setBufferObjects(const NostalgiaGraphic &img, glutils::BufferSet *bg) noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
class ImVec2 pixelSize() const noexcept;
|
class ImVec2 pixelSize(const ImVec2 &paneSize = ImGui::GetContentRegionAvail()) const noexcept;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <nostalgia/core/consts.hpp>
|
#include <nostalgia/core/consts.hpp>
|
||||||
#include "ptidxconv.hpp"
|
#include <nostalgia/core/ptidxconv.hpp>
|
||||||
#include "tilesheetpixels.hpp"
|
#include "tilesheetpixels.hpp"
|
||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
@ -18,12 +18,14 @@ ox::Error TileSheetPixels::buildShader() noexcept {
|
|||||||
return glutils::buildShaderProgram(Vshad, Fshad).moveTo(&m_shader);
|
return glutils::buildShaderProgram(Vshad, Fshad).moveTo(&m_shader);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetPixels::draw(bool update) noexcept {
|
void TileSheetPixels::draw(bool update, const ImVec2 &scroll) noexcept {
|
||||||
glUseProgram(m_shader);
|
glUseProgram(m_shader);
|
||||||
glBindVertexArray(m_bufferSet.vao);
|
glBindVertexArray(m_bufferSet.vao);
|
||||||
if (update) {
|
if (update) {
|
||||||
glutils::sendVbo(m_bufferSet);
|
glutils::sendVbo(m_bufferSet);
|
||||||
}
|
}
|
||||||
|
const auto uniformScroll = static_cast<GLint>(glGetUniformLocation(m_shader, "vScroll"));
|
||||||
|
glUniform2f(uniformScroll, scroll.x, scroll.y);
|
||||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(m_bufferSet.elements.size()), GL_UNSIGNED_INT, nullptr);
|
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(m_bufferSet.elements.size()), GL_UNSIGNED_INT, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,6 +49,13 @@ void TileSheetPixels::initBufferSet(const NostalgiaGraphic &img, const Nostalgia
|
|||||||
reinterpret_cast<void*>(2 * sizeof(float)));
|
reinterpret_cast<void*>(2 * sizeof(float)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImVec2 TileSheetPixels::pixelSize(const ImVec2 &paneSize) const noexcept {
|
||||||
|
const auto [sw, sh] = paneSize;
|
||||||
|
constexpr float ymod = 0.35f / 10.0f;
|
||||||
|
const auto xmod = ymod * sh / sw;
|
||||||
|
return {xmod * m_pixelSizeMod, ymod * m_pixelSizeMod};
|
||||||
|
}
|
||||||
|
|
||||||
void TileSheetPixels::setPixelBufferObject(unsigned vertexRow, float x, float y, Color16 color, float *vbo, GLuint *ebo) noexcept {
|
void TileSheetPixels::setPixelBufferObject(unsigned vertexRow, float x, float y, Color16 color, float *vbo, GLuint *ebo) noexcept {
|
||||||
const auto [xmod, ymod] = pixelSize();
|
const auto [xmod, ymod] = pixelSize();
|
||||||
x *= xmod;
|
x *= xmod;
|
||||||
@ -102,11 +111,4 @@ void TileSheetPixels::setBufferObjects(const NostalgiaGraphic &img, const Nostal
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImVec2 TileSheetPixels::pixelSize() const noexcept {
|
|
||||||
const auto [sw, sh] = ImGui::GetContentRegionAvail();
|
|
||||||
constexpr float ymod = 0.35f / 10.0f;
|
|
||||||
const auto xmod = ymod * sh / sw;
|
|
||||||
return {xmod * m_pixelSizeMod, ymod * m_pixelSizeMod};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,9 @@ class TileSheetPixels {
|
|||||||
in vec2 vPosition;
|
in vec2 vPosition;
|
||||||
in vec3 vColor;
|
in vec3 vColor;
|
||||||
out vec3 fColor;
|
out vec3 fColor;
|
||||||
|
uniform vec2 vScroll;
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = vec4(vPosition, 0.0, 1.0);
|
gl_Position = vec4(vPosition + vScroll, 0.0, 1.0);
|
||||||
fColor = vColor;
|
fColor = vColor;
|
||||||
})";
|
})";
|
||||||
static constexpr auto FShad = R"(
|
static constexpr auto FShad = R"(
|
||||||
@ -46,18 +47,18 @@ class TileSheetPixels {
|
|||||||
|
|
||||||
ox::Error buildShader() noexcept;
|
ox::Error buildShader() noexcept;
|
||||||
|
|
||||||
void draw(bool update) noexcept;
|
void draw(bool update, const ImVec2 &scroll) noexcept;
|
||||||
|
|
||||||
void initBufferSet(const NostalgiaGraphic &img, const NostalgiaPalette &pal) noexcept;
|
void initBufferSet(const NostalgiaGraphic &img, const NostalgiaPalette &pal) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
ImVec2 pixelSize(const ImVec2 &paneSize = ImGui::GetContentRegionAvail()) const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setPixelBufferObject(unsigned vertexRow, float x, float y, Color16 color, float *vbo, GLuint *ebo) noexcept;
|
void setPixelBufferObject(unsigned vertexRow, float x, float y, Color16 color, float *vbo, GLuint *ebo) noexcept;
|
||||||
|
|
||||||
void setBufferObjects(const NostalgiaGraphic &img, const NostalgiaPalette &pal, glutils::BufferSet *bg) noexcept;
|
void setBufferObjects(const NostalgiaGraphic &img, const NostalgiaPalette &pal, glutils::BufferSet *bg) noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
|
||||||
ImVec2 pixelSize() const noexcept;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user