[jasper/world/studio] Make WorldEditor able to animate BG
All checks were successful
Build / build (push) Successful in 3m17s
All checks were successful
Build / build (push) Successful in 3m17s
This commit is contained in:
parent
e008416d08
commit
cab71a5fcf
@ -16,16 +16,28 @@ namespace ncore = nostalgia::core;
|
|||||||
|
|
||||||
class World {
|
class World {
|
||||||
private:
|
private:
|
||||||
|
struct PaletteTracker {
|
||||||
|
keel::AssetRef<ncore::CompactPalette> pal;
|
||||||
|
int page{};
|
||||||
|
};
|
||||||
|
ox::Vector<PaletteTracker, 10> m_palettes;
|
||||||
ncore::Context &m_nctx;
|
ncore::Context &m_nctx;
|
||||||
ox::Vector<keel::AssetRef<ncore::CompactPalette>, 10> m_palettes;
|
|
||||||
WorldStatic const&m_worldStatic;
|
WorldStatic const&m_worldStatic;
|
||||||
|
#ifndef OX_OS_BareMetal
|
||||||
|
turbine::TimeMs m_prevUpdateTime{};
|
||||||
|
turbine::TimeMs m_nextUpdateTime{};
|
||||||
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit World(ncore::Context &nctx, WorldStatic const&worldStatic) noexcept;
|
explicit World(ncore::Context &nctx, WorldStatic const&worldStatic) noexcept;
|
||||||
|
|
||||||
ox::Error setupDisplay() noexcept;
|
ox::Error setupDisplay() noexcept;
|
||||||
|
|
||||||
ox::Result<int> update() const noexcept;
|
ox::Result<int> update() noexcept;
|
||||||
|
|
||||||
|
#ifndef OX_OS_BareMetal
|
||||||
|
ox::Result<int> editorModeUpdate() noexcept;
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupLayer(uint_t lyr, uint_t cbb) const noexcept;
|
void setupLayer(uint_t lyr, uint_t cbb) const noexcept;
|
||||||
|
@ -251,11 +251,19 @@ void WorldEditorImGui::drawPropEditor() noexcept {
|
|||||||
|
|
||||||
void WorldEditorImGui::drawMenu() noexcept {
|
void WorldEditorImGui::drawMenu() noexcept {
|
||||||
ig::IDStackItem const idStackItem("Menu");
|
ig::IDStackItem const idStackItem("Menu");
|
||||||
if (ig::PushButton("Resize")) {
|
if (ImGui::Button("Resize")) {
|
||||||
m_sizeEditor.show = true;
|
m_sizeEditor.show = true;
|
||||||
m_sizeEditor.columns = m_doc.columns;
|
m_sizeEditor.columns = m_doc.columns;
|
||||||
m_sizeEditor.rows = m_doc.rows;
|
m_sizeEditor.rows = m_doc.rows;
|
||||||
}
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
{
|
||||||
|
bool animate = m_view.animate();
|
||||||
|
if (ImGui::Checkbox("Animate", &animate) && !animate) {
|
||||||
|
oxLogError(m_view.setupWorld());
|
||||||
|
}
|
||||||
|
m_view.setAnimate(animate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldEditorImGui::drawResources() noexcept {
|
void WorldEditorImGui::drawResources() noexcept {
|
||||||
|
@ -34,10 +34,12 @@ void WorldEditorView::draw(ox::Size const&targetSz) noexcept {
|
|||||||
glutils::resizeInitFrameBuffer(m_frameBuffer, ncore::gl::drawSize(m_scale));
|
glutils::resizeInitFrameBuffer(m_frameBuffer, ncore::gl::drawSize(m_scale));
|
||||||
}
|
}
|
||||||
glutils::FrameBufferBind const frameBufferBind(m_frameBuffer);
|
glutils::FrameBufferBind const frameBufferBind(m_frameBuffer);
|
||||||
auto const wakeUp = m_world.update();
|
if (m_animateWorld) {
|
||||||
|
auto const wakeUp = m_world.editorModeUpdate();
|
||||||
if (wakeUp.ok()) {
|
if (wakeUp.ok()) {
|
||||||
turbine::setRefreshWithin(m_sctx.tctx, wakeUp.value);
|
turbine::setRefreshWithin(m_sctx.tctx, wakeUp.value);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
ncore::gl::draw(*m_cctx, m_scale);
|
ncore::gl::draw(*m_cctx, m_scale);
|
||||||
m_highlighter.draw();
|
m_highlighter.draw();
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ class WorldEditorView {
|
|||||||
ox::Size m_scaleSz = ncore::gl::drawSize(m_scale);
|
ox::Size m_scaleSz = ncore::gl::drawSize(m_scale);
|
||||||
ox::Optional<studio::Selection> m_selection;
|
ox::Optional<studio::Selection> m_selection;
|
||||||
MapTileHighlighter m_highlighter;
|
MapTileHighlighter m_highlighter;
|
||||||
|
bool m_animateWorld{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WorldEditorView(studio::StudioContext &ctx, WorldStatic const&worldStatic);
|
WorldEditorView(studio::StudioContext &ctx, WorldStatic const&worldStatic);
|
||||||
@ -44,6 +45,11 @@ class WorldEditorView {
|
|||||||
|
|
||||||
void setSelection(studio::Selection const&sel) noexcept;
|
void setSelection(studio::Selection const&sel) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool animate() const noexcept { return m_animateWorld; }
|
||||||
|
|
||||||
|
void setAnimate(bool animate) noexcept { m_animateWorld = animate; }
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
glutils::FrameBuffer const&framebuffer() const noexcept;
|
glutils::FrameBuffer const&framebuffer() const noexcept;
|
||||||
|
|
||||||
|
@ -12,8 +12,7 @@ namespace jasper::world {
|
|||||||
|
|
||||||
World::World(ncore::Context &nctx, WorldStatic const&worldStatic) noexcept:
|
World::World(ncore::Context &nctx, WorldStatic const&worldStatic) noexcept:
|
||||||
m_nctx(nctx),
|
m_nctx(nctx),
|
||||||
m_worldStatic(worldStatic) {
|
m_worldStatic(worldStatic) {}
|
||||||
}
|
|
||||||
|
|
||||||
ox::Error World::setupDisplay() noexcept {
|
ox::Error World::setupDisplay() noexcept {
|
||||||
if (m_worldStatic.palettes.empty()) {
|
if (m_worldStatic.palettes.empty()) {
|
||||||
@ -22,8 +21,8 @@ ox::Error World::setupDisplay() noexcept {
|
|||||||
m_palettes.clear();
|
m_palettes.clear();
|
||||||
for (auto i = 0u; auto const&pal : m_worldStatic.palettes) {
|
for (auto i = 0u; auto const&pal : m_worldStatic.palettes) {
|
||||||
auto &palRef = m_palettes.emplace_back();
|
auto &palRef = m_palettes.emplace_back();
|
||||||
oxReturnError(readObj<ncore::CompactPalette>(keelCtx(m_nctx), pal.palette).moveTo(palRef));
|
oxReturnError(readObj<ncore::CompactPalette>(keelCtx(m_nctx), pal.palette).moveTo(palRef.pal));
|
||||||
oxReturnError(ncore::loadBgPalette(m_nctx, i, *palRef));
|
oxReturnError(ncore::loadBgPalette(m_nctx, i, *palRef.pal));
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
oxReturnError(ncore::loadBgTileSheet(m_nctx, 0, m_worldStatic.tilesheets));
|
oxReturnError(ncore::loadBgTileSheet(m_nctx, 0, m_worldStatic.tilesheets));
|
||||||
@ -68,17 +67,44 @@ void World::setupLayer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Result<int> World::update() const noexcept {
|
ox::Result<int> World::update() noexcept {
|
||||||
auto const time = ticksMs(turbineCtx(m_nctx));
|
auto const time = ticksMs(turbineCtx(m_nctx));
|
||||||
int expiresIn = 30 * 1000;
|
int expiresIn = 60'000;
|
||||||
for (size_t i = 0; auto const&pal : m_palettes) {
|
for (size_t i = 0; auto const&pal : m_palettes) {
|
||||||
auto const interval = m_worldStatic.palettes[i].intervalMs;
|
auto const interval = m_worldStatic.palettes[i].intervalMs;
|
||||||
auto const page = (time / interval) % pal->pages.size();
|
auto const page = (time / interval) % pal.pal->pages.size();
|
||||||
expiresIn = ox::min(expiresIn, static_cast<int>(time % interval));
|
expiresIn = ox::min(expiresIn, static_cast<int>(time % interval));
|
||||||
oxReturnError(ncore::loadBgPalette(m_nctx, i, *pal, static_cast<size_t>(page)));
|
oxReturnError(ncore::loadBgPalette(m_nctx, i, *pal.pal, static_cast<size_t>(page)));
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
return expiresIn;
|
return expiresIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef OX_OS_BareMetal
|
||||||
|
ox::Result<int> World::editorModeUpdate() noexcept {
|
||||||
|
auto const time = ticksMs(turbineCtx(m_nctx));
|
||||||
|
if (time >= m_nextUpdateTime) {
|
||||||
|
turbine::TimeMs expiresIn = 60'000;
|
||||||
|
bool updated = false;
|
||||||
|
auto const elapsedSincePrev = time - m_prevUpdateTime;
|
||||||
|
for (size_t i = 0; auto &pal: m_palettes) {
|
||||||
|
auto const interval = m_worldStatic.palettes[i].intervalMs;
|
||||||
|
auto &page = pal.page;
|
||||||
|
auto const update = (elapsedSincePrev >= interval);
|
||||||
|
page += update * 1;
|
||||||
|
page %= static_cast<int>(pal.pal->pages.size());
|
||||||
|
oxReturnError(ncore::loadBgPalette(m_nctx, i, *pal.pal, static_cast<size_t>(page)));
|
||||||
|
updated = updated || update;
|
||||||
|
expiresIn = ox::min<turbine::TimeMs>(expiresIn, interval);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
if (updated) {
|
||||||
|
m_prevUpdateTime = time;
|
||||||
|
}
|
||||||
|
m_nextUpdateTime = time + expiresIn;
|
||||||
|
}
|
||||||
|
return static_cast<int>(m_nextUpdateTime - time);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,9 @@ ox::Error run(turbine::Context &tctx, ox::StringView, ox::SpanView<ox::String> a
|
|||||||
oxReturnError(world.setupDisplay());
|
oxReturnError(world.setupDisplay());
|
||||||
turbine::setApplicationData(tctx, &world);
|
turbine::setApplicationData(tctx, &world);
|
||||||
setUpdateHandler(tctx, [](turbine::Context &tctx) -> int {
|
setUpdateHandler(tctx, [](turbine::Context &tctx) -> int {
|
||||||
auto const&world = *applicationData<world::World>(tctx);
|
auto &world = *applicationData<world::World>(tctx);
|
||||||
auto [sleepTime, err] = world.update();
|
auto [sleepTime, err] = world.update();
|
||||||
if (err) {
|
if (err) {
|
||||||
oxDebugf("error: {}", toStr(err));
|
|
||||||
oxLogError(err);
|
oxLogError(err);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user