[nostalgia] Add start for Scene editor in Studio
This commit is contained in:
@@ -7,12 +7,6 @@ add_library(
|
||||
typestore.cpp
|
||||
)
|
||||
|
||||
add_library(
|
||||
NostalgiaCore-Headless
|
||||
headless/core.cpp
|
||||
headless/gfx.cpp
|
||||
)
|
||||
|
||||
add_library(NostalgiaCore)
|
||||
|
||||
if(NOT NOSTALGIA_BUILD_TYPE STREQUAL "GBA")
|
||||
@@ -65,11 +59,6 @@ target_link_libraries(
|
||||
NostalgiaCore-Common
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
NostalgiaCore-Headless PUBLIC
|
||||
NostalgiaCore-Common
|
||||
)
|
||||
|
||||
if(NOSTALGIA_BUILD_STUDIO)
|
||||
add_subdirectory(studio)
|
||||
endif()
|
||||
@@ -84,7 +73,9 @@ install(
|
||||
core.hpp
|
||||
event.hpp
|
||||
gfx.hpp
|
||||
ptidxconv.hpp
|
||||
input.hpp
|
||||
tilesheet.hpp
|
||||
typeconv.hpp
|
||||
typestore.hpp
|
||||
DESTINATION
|
||||
@@ -94,7 +85,6 @@ install(
|
||||
install(
|
||||
TARGETS
|
||||
NostalgiaCore
|
||||
NostalgiaCore-Headless
|
||||
DESTINATION
|
||||
LIBRARY DESTINATION lib/nostalgia
|
||||
ARCHIVE DESTINATION lib/nostalgia
|
||||
|
||||
@@ -10,7 +10,7 @@ constexpr auto TileWidth = 8;
|
||||
constexpr auto TileHeight = 8;
|
||||
constexpr auto PixelsPerTile = TileWidth * TileHeight;
|
||||
|
||||
constexpr auto FileExt_ng = ".ng";
|
||||
constexpr auto FileExt_npal = ".npal";
|
||||
constexpr auto FileExt_ng = "ng";
|
||||
constexpr auto FileExt_npal = "npal";
|
||||
|
||||
}
|
||||
|
||||
@@ -9,10 +9,22 @@
|
||||
#include <ox/std/buffer.hpp>
|
||||
|
||||
#include <nostalgia/foundation/context.hpp>
|
||||
#include <nostalgia/geo/size.hpp>
|
||||
|
||||
#include "event.hpp"
|
||||
#include "input.hpp"
|
||||
|
||||
namespace nostalgia::core::gl {
|
||||
void drawMainView(core::Context*) noexcept;
|
||||
void setRenderSize(core::Context*, int width, int height) noexcept;
|
||||
geo::Size getRenderSize(core::Context*) noexcept;
|
||||
void clearRenderSize(core::Context *ctx) noexcept;
|
||||
}
|
||||
|
||||
namespace nostalgia::core::renderer {
|
||||
ox::Error init(Context *ctx) noexcept;
|
||||
}
|
||||
|
||||
namespace nostalgia::geo {
|
||||
class Size;
|
||||
}
|
||||
@@ -58,6 +70,7 @@ class Context: public foundation::Context {
|
||||
friend int getScreenHeight(Context *ctx) noexcept;
|
||||
friend int getScreenWidth(Context *ctx) noexcept;
|
||||
friend ox::Error initGfx(Context *ctx) noexcept;
|
||||
friend ox::Error renderer::init(Context *ctx) noexcept;
|
||||
friend ox::Error loadBgTileSheet(Context *ctx,
|
||||
unsigned cbb,
|
||||
const ox::FileAddress &tilesheetPath,
|
||||
@@ -84,14 +97,18 @@ class Context: public foundation::Context {
|
||||
friend constexpr KeyEventHandler keyEventHandler(Context *ctx) noexcept;
|
||||
friend void setTile(Context *ctx, unsigned bgIdx, int column, int row, uint8_t tile) noexcept;
|
||||
friend void setSprite(Context *ctx,
|
||||
unsigned idx,
|
||||
int x,
|
||||
int y,
|
||||
unsigned tileIdx,
|
||||
unsigned spriteShape,
|
||||
unsigned spriteSize,
|
||||
unsigned flipX) noexcept;
|
||||
unsigned idx,
|
||||
int x,
|
||||
int y,
|
||||
unsigned tileIdx,
|
||||
unsigned spriteShape,
|
||||
unsigned spriteSize,
|
||||
unsigned flipX) noexcept;
|
||||
friend void hideSprite(Context *ctx, unsigned idx) noexcept;
|
||||
friend void gl::drawMainView(core::Context*) noexcept;
|
||||
friend void gl::setRenderSize(core::Context*, int width, int height) noexcept;
|
||||
friend geo::Size gl::getRenderSize(core::Context*) noexcept;
|
||||
friend void gl::clearRenderSize(core::Context *ctx) noexcept;
|
||||
|
||||
public:
|
||||
ox::Vector<Drawer*, 5> drawers;
|
||||
|
||||
@@ -18,6 +18,12 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
namespace gl {
|
||||
|
||||
void setMainViewEnabled(bool) noexcept;
|
||||
|
||||
}
|
||||
|
||||
extern ox::Array<char, 128> charMap;
|
||||
|
||||
class Drawer {
|
||||
|
||||
@@ -216,9 +216,7 @@ ox::Error initGfx(Context *ctx) noexcept {
|
||||
ImGui_ImplGlfw_InitForOpenGL(id->window, true);
|
||||
}
|
||||
themeImgui();
|
||||
void *rendererData = nullptr;
|
||||
oxReturnError(renderer::init(ctx, &rendererData));
|
||||
ctx->setRendererData(rendererData);
|
||||
oxReturnError(renderer::init(ctx));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <nostalgia/core/core.hpp>
|
||||
#include <nostalgia/core/input.hpp>
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
ox::Result<ox::UniquePtr<Context>> init(ox::UniquePtr<ox::FileSystem>, ox::CRStringView) noexcept {
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
void setUpdateHandler(Context*, UpdateHandler) noexcept {
|
||||
}
|
||||
|
||||
uint64_t ticksMs(Context*) noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool buttonDown(Context*, Key) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <nostalgia/core/context.hpp>
|
||||
#include <nostalgia/core/gfx.hpp>
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
ox::Error initGfx(Context*) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
ox::Error shutdownGfx(Context*) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
void setWindowTitle(Context*, ox::CRStringView) noexcept {
|
||||
}
|
||||
|
||||
void focusWindow(Context*) noexcept {
|
||||
}
|
||||
|
||||
int getScreenWidth(Context*) noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getScreenHeight(Context*) noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
geo::Size getScreenSize(Context*) noexcept {
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
uint8_t bgStatus(Context*) noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setBgStatus(Context*, uint32_t) noexcept {
|
||||
}
|
||||
|
||||
bool bgStatus(Context*, unsigned) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
void setBgStatus(Context*, unsigned, bool) noexcept {
|
||||
}
|
||||
|
||||
// Do NOT rely on Context in the GBA version of this function.
|
||||
ox::Error initConsole(Context*) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
ox::Error loadBgTileSheet(Context*,
|
||||
int,
|
||||
const ox::FileAddress&,
|
||||
const ox::FileAddress&) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
ox::Error loadSpriteTileSheet(Context*,
|
||||
const ox::FileAddress&,
|
||||
const ox::FileAddress&) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
ox::Error loadBgPalette(Context*, int, const ox::FileAddress&) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
ox::Error loadSpritePalette(Context*, int, const ox::FileAddress&) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
// Do NOT use Context in the GBA version of this function.
|
||||
void puts(Context*, int, int, ox::CRStringView) noexcept {
|
||||
}
|
||||
|
||||
void setTile(Context*, int, int, int, uint8_t) noexcept {
|
||||
}
|
||||
|
||||
// Do NOT use Context in the GBA version of this function.
|
||||
void clearTileLayer(Context*, int) noexcept {
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
void hideSprite(Context*, unsigned) noexcept {
|
||||
}
|
||||
|
||||
void setSprite(Context*,
|
||||
unsigned,
|
||||
int,
|
||||
int,
|
||||
unsigned,
|
||||
unsigned,
|
||||
unsigned,
|
||||
unsigned) noexcept {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,8 +14,29 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
class CoreModule: public foundation::Module {
|
||||
private:
|
||||
NostalgiaPaletteToPaletteConverter nostalgiaPaletteToPaletteConverter;
|
||||
TileSheetV1ToTileSheetConverter nostalgiaGraphicToTileSheetConverter;
|
||||
TileSheetToCompactTileSheetConverter tileSheetToCompactTileSheetConverter;
|
||||
TileSheetV2ToTileSheetConverter tileSheetV2ToTileSheetConverter;
|
||||
|
||||
public:
|
||||
static CoreModule mod;
|
||||
[[nodiscard]]
|
||||
ox::Vector<foundation::TypeDescGenerator> types() const noexcept override;
|
||||
[[nodiscard]]
|
||||
ox::Vector<const foundation::BaseConverter*> converters() const noexcept override;
|
||||
[[nodiscard]]
|
||||
ox::Vector<foundation::PackTransform> packTransforms() const noexcept override;
|
||||
};
|
||||
|
||||
CoreModule CoreModule::mod;
|
||||
|
||||
const foundation::Module *module() noexcept {
|
||||
return &CoreModule::mod;
|
||||
}
|
||||
|
||||
ox::Vector<foundation::TypeDescGenerator> CoreModule::types() const noexcept {
|
||||
return {
|
||||
foundation::generateTypeDesc<TileSheetV1>,
|
||||
|
||||
@@ -6,25 +6,8 @@
|
||||
|
||||
#include <nostalgia/foundation/module.hpp>
|
||||
|
||||
#include "typeconv.hpp"
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
class CoreModule: public foundation::Module {
|
||||
private:
|
||||
NostalgiaPaletteToPaletteConverter nostalgiaPaletteToPaletteConverter;
|
||||
TileSheetV1ToTileSheetConverter nostalgiaGraphicToTileSheetConverter;
|
||||
TileSheetToCompactTileSheetConverter tileSheetToCompactTileSheetConverter;
|
||||
TileSheetV2ToTileSheetConverter tileSheetV2ToTileSheetConverter;
|
||||
|
||||
public:
|
||||
static CoreModule mod;
|
||||
[[nodiscard]]
|
||||
ox::Vector<foundation::TypeDescGenerator> types() const noexcept override;
|
||||
[[nodiscard]]
|
||||
ox::Vector<const foundation::BaseConverter*> converters() const noexcept override;
|
||||
[[nodiscard]]
|
||||
ox::Vector<foundation::PackTransform> packTransforms() const noexcept override;
|
||||
};
|
||||
const foundation::Module *module() noexcept;
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,16 @@ namespace nostalgia::core {
|
||||
|
||||
void ImGui_Impl_NewFrame() noexcept;
|
||||
|
||||
namespace gl {
|
||||
|
||||
static bool mainViewEnabled = true;
|
||||
|
||||
void setMainViewEnabled(bool enabled) noexcept {
|
||||
mainViewEnabled = enabled;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace renderer {
|
||||
|
||||
constexpr uint64_t TileRows = 128;
|
||||
@@ -67,6 +77,7 @@ struct GlImplData {
|
||||
SpriteBlockset spriteBlocks;
|
||||
ox::Array<Sprite, 128> spriteStates;
|
||||
ox::Array<Background, 4> backgrounds;
|
||||
ox::Optional<geo::Size> renderSize;
|
||||
};
|
||||
|
||||
constexpr ox::StringView bgvshadTmpl = R"(
|
||||
@@ -74,9 +85,13 @@ constexpr ox::StringView bgvshadTmpl = R"(
|
||||
in vec2 vTexCoord;
|
||||
in vec2 vPosition;
|
||||
out vec2 fTexCoord;
|
||||
uniform float vXScale;
|
||||
uniform float vTileHeight;
|
||||
void main() {
|
||||
gl_Position = vec4(vPosition, 0.0, 1.0);
|
||||
float xScaleInvert = 1.0 - vXScale;
|
||||
gl_Position = vec4(
|
||||
vPosition.x * vXScale - xScaleInvert, vPosition.y,
|
||||
0.0, 1.0);
|
||||
fTexCoord = vTexCoord * vec2(1, vTileHeight);
|
||||
})";
|
||||
|
||||
@@ -98,9 +113,13 @@ constexpr ox::StringView spritevshadTmpl = R"(
|
||||
in vec2 vTexCoord;
|
||||
in vec2 vPosition;
|
||||
out vec2 fTexCoord;
|
||||
uniform float vXScale;
|
||||
uniform float vTileHeight;
|
||||
void main() {
|
||||
gl_Position = vec4(vPosition, 0.0, 1.0);
|
||||
float xScaleInvert = 1.0 - vXScale;
|
||||
gl_Position = vec4(
|
||||
vPosition.x * vXScale - xScaleInvert, vPosition.y,
|
||||
0.0, 1.0);
|
||||
fTexCoord = vTexCoord * vec2(1, vTileHeight) * vec2(vEnabled, vEnabled);
|
||||
})";
|
||||
|
||||
@@ -111,7 +130,7 @@ static constexpr auto bgVertexRow(unsigned x, unsigned y) noexcept {
|
||||
return y * TileRows + x;
|
||||
}
|
||||
|
||||
static void setSpriteBufferObject(Context *ctx,
|
||||
static void setSpriteBufferObject(Context*,
|
||||
unsigned vi,
|
||||
float enabled,
|
||||
float x, float y,
|
||||
@@ -120,9 +139,8 @@ static void setSpriteBufferObject(Context *ctx,
|
||||
float *vbo,
|
||||
GLuint *ebo) noexcept {
|
||||
// don't worry, this memcpy gets optimized to something much more ideal
|
||||
const auto [sw, sh] = getScreenSize(ctx);
|
||||
constexpr float xmod = 0.1f;
|
||||
constexpr float ymod = 0.1f;
|
||||
const auto xmod = ymod * static_cast<float>(sh) / static_cast<float>(sw);
|
||||
x *= xmod;
|
||||
y *= -ymod;
|
||||
x -= 1.f;
|
||||
@@ -144,7 +162,7 @@ static void setSpriteBufferObject(Context *ctx,
|
||||
memcpy(ebo, elms.data(), sizeof(elms));
|
||||
}
|
||||
|
||||
static void setTileBufferObject(Context *ctx,
|
||||
static void setTileBufferObject(Context*,
|
||||
unsigned vi,
|
||||
float x,
|
||||
float y,
|
||||
@@ -152,9 +170,8 @@ static void setTileBufferObject(Context *ctx,
|
||||
float *vbo,
|
||||
GLuint *ebo) noexcept {
|
||||
// don't worry, this memcpy gets optimized to something much more ideal
|
||||
const auto [sw, sh] = getScreenSize(ctx);
|
||||
constexpr float ymod = 2.0f / 20.0f;
|
||||
const float xmod = ymod * static_cast<float>(sh) / static_cast<float>(sw);
|
||||
constexpr float ymod = 0.1f;
|
||||
constexpr float xmod = 0.1f;
|
||||
x *= xmod;
|
||||
y *= -ymod;
|
||||
x -= 1.0f;
|
||||
@@ -279,11 +296,15 @@ static void drawBackground(CBB *cbb) noexcept {
|
||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(cbb->elements.size()), GL_UNSIGNED_INT, nullptr);
|
||||
}
|
||||
|
||||
static void drawBackgrounds(GlImplData *id) noexcept {
|
||||
static void drawBackgrounds(core::Context *ctx, GlImplData *id) noexcept {
|
||||
// load background shader and its uniforms
|
||||
glUseProgram(id->bgShader);
|
||||
const auto uniformXScale = static_cast<GLint>(glGetUniformLocation(id->bgShader, "vXScale"));
|
||||
const auto uniformTileHeight = static_cast<GLint>(glGetUniformLocation(id->bgShader, "vTileHeight"));
|
||||
//glUniform3fv(uniformPalette, GlImplData::ColorCnt, id->palette.data());
|
||||
const auto [wi, hi] = gl::getRenderSize(ctx);
|
||||
const auto wf = static_cast<float>(wi);
|
||||
const auto hf = static_cast<float>(hi);
|
||||
glUniform1f(uniformXScale, hf / wf);
|
||||
for (const auto &bg : id->backgrounds) {
|
||||
if (bg.enabled) {
|
||||
auto &cbb = id->cbbs[bg.cbbIdx];
|
||||
@@ -294,10 +315,15 @@ static void drawBackgrounds(GlImplData *id) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
static void drawSprites(GlImplData *id) noexcept {
|
||||
static void drawSprites(core::Context *ctx, GlImplData *id) noexcept {
|
||||
glUseProgram(id->spriteShader);
|
||||
auto &sb = id->spriteBlocks;
|
||||
const auto uniformXScale = static_cast<GLint>(glGetUniformLocation(id->bgShader, "vXScale"));
|
||||
const auto uniformTileHeight = static_cast<GLint>(glGetUniformLocation(id->spriteShader, "vTileHeight"));
|
||||
const auto [wi, hi] = gl::getRenderSize(ctx);
|
||||
const auto wf = static_cast<float>(wi);
|
||||
const auto hf = static_cast<float>(hi);
|
||||
glUniform1f(uniformXScale, hf / wf);
|
||||
// update vbo
|
||||
glBindVertexArray(sb.vao);
|
||||
if (sb.updated) {
|
||||
@@ -312,7 +338,7 @@ static void drawSprites(GlImplData *id) noexcept {
|
||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(sb.elements.size()), GL_UNSIGNED_INT, nullptr);
|
||||
}
|
||||
|
||||
ox::Error init(Context *ctx, void **rendererData) noexcept {
|
||||
ox::Error init(Context *ctx) noexcept {
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
const auto bgVshad = ox::sfmt(bgvshadTmpl, glutils::GlslVersion);
|
||||
@@ -320,7 +346,7 @@ ox::Error init(Context *ctx, void **rendererData) noexcept {
|
||||
const auto spriteVshad = ox::sfmt(spritevshadTmpl, glutils::GlslVersion);
|
||||
const auto spriteFshad = ox::sfmt(spritefshadTmpl, glutils::GlslVersion);
|
||||
const auto id = ox::make<GlImplData>();
|
||||
*rendererData = id;
|
||||
ctx->setRendererData(id);
|
||||
oxReturnError(glutils::buildShaderProgram(bgVshad.c_str(), bgFshad.c_str()).moveTo(&id->bgShader));
|
||||
oxReturnError(glutils::buildShaderProgram(spriteVshad.c_str(), spriteFshad.c_str()).moveTo(&id->spriteShader));
|
||||
for (auto &bg : id->cbbs) {
|
||||
@@ -328,7 +354,7 @@ ox::Error init(Context *ctx, void **rendererData) noexcept {
|
||||
}
|
||||
initSpritesBufferset(ctx, id->spriteShader, &id->spriteBlocks);
|
||||
ImGui_ImplOpenGL3_Init(glutils::GlslVersion);
|
||||
return OxError(0);
|
||||
return {};
|
||||
}
|
||||
|
||||
void shutdown(Context*, void *rendererData) noexcept {
|
||||
@@ -422,9 +448,8 @@ void draw(Context *ctx) noexcept {
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
// render
|
||||
renderer::drawBackgrounds(id);
|
||||
if (id->spriteBlocks.tex) {
|
||||
renderer::drawSprites(id);
|
||||
if (gl::mainViewEnabled) {
|
||||
gl::drawMainView(ctx);
|
||||
}
|
||||
for (const auto cd : ctx->drawers) {
|
||||
cd->draw(ctx);
|
||||
@@ -530,4 +555,35 @@ void setTile(Context *ctx, unsigned bgIdx, int column, int row, uint8_t tile) no
|
||||
bg.updated = true;
|
||||
}
|
||||
|
||||
namespace gl {
|
||||
|
||||
void drawMainView(core::Context *ctx) noexcept {
|
||||
const auto id = ctx->rendererData<renderer::GlImplData>();
|
||||
renderer::drawBackgrounds(ctx, id);
|
||||
if (id->spriteBlocks.tex) {
|
||||
renderer::drawSprites(ctx, id);
|
||||
}
|
||||
}
|
||||
|
||||
void setRenderSize(core::Context *ctx, int width, int height) noexcept {
|
||||
const auto id = ctx->rendererData<renderer::GlImplData>();
|
||||
id->renderSize.emplace(width, height);
|
||||
}
|
||||
|
||||
void clearRenderSize(core::Context *ctx) noexcept {
|
||||
auto id = ctx->rendererData<renderer::GlImplData>();
|
||||
id->renderSize.reset();
|
||||
}
|
||||
|
||||
geo::Size getRenderSize(core::Context *ctx) noexcept {
|
||||
const auto id = ctx->rendererData<renderer::GlImplData>();
|
||||
if (id->renderSize.has_value()) {
|
||||
return id->renderSize.value();
|
||||
} else {
|
||||
return core::getScreenSize(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user