[nostalgia/core/studio] Add pixel outline to tile sheet editor
This commit is contained in:
parent
99550b60ee
commit
f6be36741c
@ -86,6 +86,16 @@ constexpr uint8_t blue32(Color32 c) noexcept {
|
||||
return (c & 0x00ff0000) >> 16;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Color32 color32(uint8_t r, uint8_t g, uint8_t b) noexcept {
|
||||
return static_cast<Color32>(r | (g << 8) | (b << 16));
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Color32 color32(float r, float g, float b) noexcept {
|
||||
return static_cast<Color32>(static_cast<uint8_t>(r * 255) | (static_cast<uint8_t>(g * 255) << 8) | (static_cast<uint8_t>(b * 255) << 16));
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr float redf(Color16 c) noexcept {
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/model/def.hpp>
|
||||
|
||||
#include <nostalgia/common/bounds.hpp>
|
||||
#include <nostalgia/core/gfx.hpp>
|
||||
#include <nostalgia/glutils/glutils.hpp>
|
||||
@ -20,7 +22,7 @@ enum class CommandId {
|
||||
ModPixel = 2,
|
||||
UpdateDimension = 3,
|
||||
InsertTile = 4,
|
||||
ClipboardPaste = 4,
|
||||
ClipboardPaste = 5,
|
||||
};
|
||||
|
||||
enum class TileSheetTool: int {
|
||||
@ -49,20 +51,16 @@ struct PixelChunk {
|
||||
int size = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error model(T *io, PixelChunk *c) noexcept {
|
||||
io->template setTypeInfo<PixelChunk>();
|
||||
oxReturnError(io->field("pt", &c->pt));
|
||||
oxReturnError(io->field("size", &c->size));
|
||||
return OxError(0);
|
||||
}
|
||||
oxModelBegin(PixelChunk)
|
||||
oxModelField(pt)
|
||||
oxModelField(size)
|
||||
oxModelEnd()
|
||||
|
||||
struct TileSheetClipboard {
|
||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetClipboard";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
|
||||
template<typename T>
|
||||
friend ox::Error model(T*, TileSheetClipboard*);
|
||||
oxModelFriend(TileSheetClipboard);
|
||||
|
||||
protected:
|
||||
ox::Vector<int> m_pixels;
|
||||
@ -158,4 +156,4 @@ class TileSheetEditor: public studio::Editor {
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -15,24 +15,23 @@ ox::Error TileSheetGrid::buildShader() noexcept {
|
||||
}
|
||||
|
||||
void TileSheetGrid::draw(bool update) noexcept {
|
||||
glLineWidth(3);
|
||||
glUseProgram(m_shader);
|
||||
glBindVertexArray(m_bufferSet.vao);
|
||||
if (update) {
|
||||
glutils::sendVbo(m_bufferSet);
|
||||
}
|
||||
glDrawElements(GL_POINTS, static_cast<GLsizei>(m_bufferSet.elements.size()), GL_UNSIGNED_INT, nullptr);
|
||||
glDrawArrays(GL_POINTS, 0, m_bufferSet.vertices.size() / VertexVboRowLength);
|
||||
}
|
||||
|
||||
void TileSheetGrid::initBufferSet(const NostalgiaGraphic &img) noexcept {
|
||||
// vao
|
||||
m_bufferSet.vao = glutils::generateVertexArrayObject();
|
||||
glBindVertexArray(m_bufferSet.vao);
|
||||
// vbo & ebo
|
||||
// vbo
|
||||
m_bufferSet.vbo = glutils::generateBuffer();
|
||||
m_bufferSet.ebo = glutils::generateBuffer();
|
||||
setBufferObjects(img, &m_bufferSet);
|
||||
glutils::sendVbo(m_bufferSet);
|
||||
glutils::sendEbo(m_bufferSet);
|
||||
// vbo layout
|
||||
const auto pt1Attr = static_cast<GLuint>(glGetAttribLocation(m_shader, "vPt1"));
|
||||
glEnableVertexAttribArray(pt1Attr);
|
||||
@ -41,41 +40,54 @@ void TileSheetGrid::initBufferSet(const NostalgiaGraphic &img) noexcept {
|
||||
glEnableVertexAttribArray(pt2Attr);
|
||||
glVertexAttribPointer(pt2Attr, 2, GL_FLOAT, GL_FALSE, VertexVboRowLength * sizeof(float),
|
||||
reinterpret_cast<void*>(2 * sizeof(float)));
|
||||
const auto colorAttr = static_cast<GLuint>(glGetAttribLocation(m_shader, "vColor"));
|
||||
glEnableVertexAttribArray(colorAttr);
|
||||
glVertexAttribPointer(colorAttr, 3, GL_FLOAT, GL_FALSE, VertexVboRowLength * sizeof(float),
|
||||
reinterpret_cast<void*>(4 * sizeof(float)));
|
||||
}
|
||||
|
||||
void TileSheetGrid::setBufferObject(unsigned vertexRow, common::Point pt1, common::Point pt2, float *vbo, GLuint *ebo) noexcept {
|
||||
const auto ps = pixelSize();
|
||||
const auto x1 = static_cast<float>(pt1.x) * ps.x;
|
||||
const auto y1 = static_cast<float>(pt1.y) * ps.y;
|
||||
const auto x2 = static_cast<float>(pt2.x) * ps.x;
|
||||
const auto y2 = static_cast<float>(pt2.y) * ps.y;
|
||||
// don't worry, these memcpys gets optimized to something much more ideal
|
||||
const float vertices[VertexVboLength] = {x1, y1, x2, y2};
|
||||
void TileSheetGrid::setBufferObject(common::Point pt1, common::Point pt2, Color32 c, float *vbo, const ImVec2 &pixSize) noexcept {
|
||||
const auto x1 = static_cast<float>(pt1.x) * pixSize.x - 1.f;
|
||||
const auto y1 = 1.f - static_cast<float>(pt1.y) * pixSize.y;
|
||||
const auto x2 = static_cast<float>(pt2.x) * pixSize.x - 1.f;
|
||||
const auto y2 = 1.f - static_cast<float>(pt2.y) * pixSize.y;
|
||||
// don't worry, this memcpy gets optimized to something much more ideal
|
||||
const float vertices[VertexVboLength] = {x1, y1, x2, y2, redf(c), greenf(c), bluef(c)};
|
||||
memcpy(vbo, vertices, sizeof(vertices));
|
||||
const GLuint elms[VertexEboLength] = {vertexRow};
|
||||
memcpy(ebo, elms, sizeof(elms));
|
||||
}
|
||||
|
||||
void TileSheetGrid::setBufferObjects(const NostalgiaGraphic &img, glutils::BufferSet *bg) noexcept {
|
||||
const auto set = [bg](unsigned i, common::Point pt1, common::Point pt2) {
|
||||
const auto pixSize = pixelSize();
|
||||
const auto set = [bg, pixSize](unsigned i, common::Point pt1, common::Point pt2, Color32 c) {
|
||||
const auto vbo = &bg->vertices[i * VertexVboLength];
|
||||
const auto ebo = &bg->elements[i * VertexEboLength];
|
||||
setBufferObject(i * VertexVboRows, pt1, pt2, vbo, ebo);
|
||||
setBufferObject(pt1, pt2, c, vbo, pixSize);
|
||||
};
|
||||
// set buffer lengths
|
||||
// set buffer length
|
||||
const auto width = img.columns * TileWidth;
|
||||
const auto height = img.rows * TileHeight;
|
||||
const auto tiles = static_cast<unsigned>(width * height);
|
||||
m_bufferSet.vertices.resize(tiles * VertexVboLength);
|
||||
m_bufferSet.elements.resize(tiles * VertexEboLength);
|
||||
// set buffers
|
||||
const auto pixelCnt = static_cast<unsigned>(width * height);
|
||||
const auto tileCnt = static_cast<unsigned>(img.columns * img.rows);
|
||||
m_bufferSet.vertices.resize((tileCnt + pixelCnt) * VertexVboLength);
|
||||
// set buffer
|
||||
auto i = 0ull;
|
||||
for (auto x = 0; x < img.columns; ++x) {
|
||||
set(0, {x, 0}, {x, img.rows});
|
||||
// pixel outlines
|
||||
constexpr auto pixOutlineColor = color32(0.4431f, 0.4901f, 0.4941f);
|
||||
for (auto x = 0; x < img.columns * TileWidth + 1; ++x) {
|
||||
set(i, {x, 0}, {x, img.rows * TileHeight}, pixOutlineColor);
|
||||
++i;
|
||||
}
|
||||
for (auto y = 0; y < img.rows; ++y) {
|
||||
set(0, {0, y}, {img.columns, y});
|
||||
for (auto y = 0; y < img.rows * TileHeight + 1; ++y) {
|
||||
set(i, {0, y}, {img.columns * TileWidth, y}, pixOutlineColor);
|
||||
++i;
|
||||
}
|
||||
// tile outlines
|
||||
constexpr auto tileOutlineColor = color32(0.f, 0.f, 0.f);
|
||||
for (auto x = 0; x < img.columns * TileWidth + 1; x += TileWidth) {
|
||||
set(i, {x, 0}, {x, img.rows * TileHeight}, tileOutlineColor);
|
||||
++i;
|
||||
}
|
||||
for (auto y = 0; y < img.rows * TileHeight + 1; y += TileHeight) {
|
||||
set(i, {0, y}, {img.columns * TileWidth, y}, tileOutlineColor);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
@ -17,45 +17,45 @@ class TileSheetGrid {
|
||||
|
||||
private:
|
||||
static constexpr auto VertexVboRows = 1;
|
||||
static constexpr auto VertexVboRowLength = 4;
|
||||
static constexpr auto VertexVboRowLength = 7;
|
||||
static constexpr auto VertexVboLength = VertexVboRows * VertexVboRowLength;
|
||||
static constexpr auto VertexEboLength = 1;
|
||||
|
||||
static constexpr auto VShad = R"(
|
||||
static constexpr auto VShad = R"glsl(
|
||||
{}
|
||||
in vec2 vPt1;
|
||||
in vec2 vPt2;
|
||||
out VS_OUT {
|
||||
vec2 pt1;
|
||||
vec2 pt2;
|
||||
} vs_out;
|
||||
in vec3 vColor;
|
||||
out vec2 gPt2;
|
||||
out vec3 gColor;
|
||||
void main() {
|
||||
vs_out.pt1 = vPt1;
|
||||
vs_out.pt2 = vPt2;
|
||||
gColor = vColor;
|
||||
gl_Position = vec4(vPt1, 0.0, 1.0);
|
||||
})";
|
||||
gPt2 = vPt2;
|
||||
})glsl";
|
||||
|
||||
static constexpr auto FShad = R"(
|
||||
static constexpr auto FShad = R"glsl(
|
||||
{}
|
||||
in vec3 fColor;
|
||||
out vec4 outColor;
|
||||
void main() {
|
||||
outColor = vec4(0.4431, 0.4901, 0.4941, 1.0);
|
||||
})";
|
||||
outColor = vec4(fColor, 1);
|
||||
//outColor = vec4(0.4431, 0.4901, 0.4941, 1.0);
|
||||
})glsl";
|
||||
|
||||
static constexpr auto GShad = R"glsl(
|
||||
{}
|
||||
in VS_OUT {
|
||||
vec2 pt1;
|
||||
vec2 pt2;
|
||||
} gs_in[];
|
||||
layout(line_strip, max_vertices = 2) out;
|
||||
layout(points) in;
|
||||
layout(line_strip, max_vertices = 9) out;
|
||||
in vec3 gColor[];
|
||||
in vec2 gPt2[];
|
||||
out vec3 fColor;
|
||||
void main() {
|
||||
//gl_Position = vec4(gs_in[0].pt1, 0, 0);
|
||||
//EmitVertex();
|
||||
//gl_Position = vec4(gs_in[0].pt2, 0, 0);
|
||||
//EmitVertex();
|
||||
//EndPrimitive();
|
||||
fColor = gColor[0];
|
||||
gl_Position = gl_in[0].gl_Position;
|
||||
EmitVertex();
|
||||
gl_Position = vec4(gPt2[0], 0, 1);
|
||||
EmitVertex();
|
||||
EndPrimitive();
|
||||
})glsl";
|
||||
|
||||
glutils::GLProgram m_shader;
|
||||
@ -69,7 +69,7 @@ class TileSheetGrid {
|
||||
void initBufferSet(const NostalgiaGraphic &img) noexcept;
|
||||
|
||||
private:
|
||||
static void setBufferObject(unsigned vertexRow, common::Point pt1, common::Point pt2, float *vbo, GLuint *ebo) noexcept;
|
||||
static void setBufferObject(common::Point pt1, common::Point pt2, Color32 c, float *vbo, const ImVec2 &pixSize) noexcept;
|
||||
|
||||
void setBufferObjects(const NostalgiaGraphic &img, glutils::BufferSet *bg) noexcept;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user