[jasper/world] Remove palette based animation system
This commit is contained in:
BIN
project/.DS_Store
vendored
BIN
project/.DS_Store
vendored
Binary file not shown.
@ -9,6 +9,10 @@ O1;net.drinkingtea.ox.TypeDescriptor;1;{
|
|||||||
"fieldName" : "name",
|
"fieldName" : "name",
|
||||||
"typeId" : "net.drinkingtea.ox.BasicString#8#;1"
|
"typeId" : "net.drinkingtea.ox.BasicString#8#;1"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldName" : "intervalMs",
|
||||||
|
"typeId" : "B.uint16;0"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldName" : "pal_bank",
|
"fieldName" : "pal_bank",
|
||||||
"typeId" : "B.uint16;0"
|
"typeId" : "B.uint16;0"
|
||||||
|
@ -18,7 +18,7 @@ O1;net.drinkingtea.ox.TypeDescriptor;1;{
|
|||||||
"subscriptType" : 4
|
"subscriptType" : 4
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"typeId" : "net.drinkingtea.jasper.world.PaletteCycle;1"
|
"typeId" : "net.drinkingtea.ox.FileAddress;1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldName" : "objects",
|
"fieldName" : "objects",
|
||||||
|
@ -14,7 +14,7 @@ O1;net.drinkingtea.ox.TypeDescriptor;1;{
|
|||||||
"subscriptType" : 4
|
"subscriptType" : 4
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"typeId" : "net.drinkingtea.jasper.world.PaletteCycle;1"
|
"typeId" : "net.drinkingtea.ox.FileAddress;1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldName" : "columns",
|
"fieldName" : "columns",
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -26,7 +26,7 @@ class ObjectCache {
|
|||||||
ox::Vector<Obj> objects;
|
ox::Vector<Obj> objects;
|
||||||
};
|
};
|
||||||
ox::Vector<ox::FileAddress> m_tilesheets;
|
ox::Vector<ox::FileAddress> m_tilesheets;
|
||||||
ox::Vector<PaletteCycle> m_palettes;
|
ox::Vector<ox::FileAddress> m_palettes;
|
||||||
size_t m_tileIdx{};
|
size_t m_tileIdx{};
|
||||||
size_t m_palBank{};
|
size_t m_palBank{};
|
||||||
ox::Vector<ObjSet> m_objSets;
|
ox::Vector<ObjSet> m_objSets;
|
||||||
@ -42,7 +42,7 @@ class ObjectCache {
|
|||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
ncore::TileSheetSet const&tilesheets() const noexcept;
|
ncore::TileSheetSet const&tilesheets() const noexcept;
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
ox::Vector<PaletteCycle> const&palettes() const noexcept;
|
ox::Vector<ox::FileAddress> const&palettes() const noexcept;
|
||||||
private:
|
private:
|
||||||
void addTileSheet(ox::FileAddress path, int32_t tiles) noexcept;
|
void addTileSheet(ox::FileAddress path, int32_t tiles) noexcept;
|
||||||
};
|
};
|
||||||
|
@ -16,15 +16,10 @@ 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;
|
||||||
WorldStatic const&m_worldStatic;
|
WorldStatic const&m_worldStatic;
|
||||||
#ifndef OX_OS_BareMetal
|
#ifndef OX_OS_BareMetal
|
||||||
turbine::TimeMs m_prevUpdateTime{};
|
//turbine::TimeMs m_prevUpdateTime{};
|
||||||
turbine::TimeMs m_nextUpdateTime{};
|
turbine::TimeMs m_nextUpdateTime{};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -13,19 +13,6 @@ namespace jasper::world {
|
|||||||
|
|
||||||
namespace ncore = nostalgia::core;
|
namespace ncore = nostalgia::core;
|
||||||
|
|
||||||
struct PaletteCycle {
|
|
||||||
static constexpr auto TypeName = "net.drinkingtea.jasper.world.PaletteCycle";
|
|
||||||
static constexpr auto TypeVersion = 1;
|
|
||||||
ox::FileAddress palette;
|
|
||||||
uint16_t intervalMs = 1000;
|
|
||||||
};
|
|
||||||
|
|
||||||
oxModelBegin(PaletteCycle)
|
|
||||||
oxModelField(palette)
|
|
||||||
oxModelField(intervalMs)
|
|
||||||
oxModelEnd()
|
|
||||||
|
|
||||||
|
|
||||||
using CollisionMap = uint32_t;
|
using CollisionMap = uint32_t;
|
||||||
|
|
||||||
enum class ObjectType: uint8_t {
|
enum class ObjectType: uint8_t {
|
||||||
@ -42,6 +29,7 @@ struct WorldObject {
|
|||||||
static constexpr auto TypeVersion = 1;
|
static constexpr auto TypeVersion = 1;
|
||||||
ObjectId id{};
|
ObjectId id{};
|
||||||
ox::String name;
|
ox::String name;
|
||||||
|
uint16_t intervalMs{};
|
||||||
uint16_t palBank{};
|
uint16_t palBank{};
|
||||||
ncore::SubSheetId subsheetId{};
|
ncore::SubSheetId subsheetId{};
|
||||||
CollisionMap collisionMap{};
|
CollisionMap collisionMap{};
|
||||||
@ -54,6 +42,7 @@ struct WorldObject {
|
|||||||
oxModelBegin(WorldObject)
|
oxModelBegin(WorldObject)
|
||||||
oxModelField(id)
|
oxModelField(id)
|
||||||
oxModelField(name)
|
oxModelField(name)
|
||||||
|
oxModelFieldRename(intervalMs, interval_ms)
|
||||||
oxModelFieldRename(palBank, pal_bank)
|
oxModelFieldRename(palBank, pal_bank)
|
||||||
oxModelFieldRename(subsheetId, subsheet_id)
|
oxModelFieldRename(subsheetId, subsheet_id)
|
||||||
oxModelFieldRename(collisionMap, collision_map)
|
oxModelFieldRename(collisionMap, collision_map)
|
||||||
@ -80,7 +69,7 @@ struct WorldObjectSet {
|
|||||||
// index used to assign unique IDs to objects in the set
|
// index used to assign unique IDs to objects in the set
|
||||||
ObjectId objIdIdx = 0;
|
ObjectId objIdIdx = 0;
|
||||||
ox::FileAddress tilesheet;
|
ox::FileAddress tilesheet;
|
||||||
ox::Vector<PaletteCycle> palettes;
|
ox::Vector<ox::FileAddress> palettes;
|
||||||
ox::Vector<WorldObject> objects;
|
ox::Vector<WorldObject> objects;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ struct WorldStatic {
|
|||||||
constexpr static auto TypeVersion = 1;
|
constexpr static auto TypeVersion = 1;
|
||||||
constexpr static auto Preloadable = true;
|
constexpr static auto Preloadable = true;
|
||||||
ncore::TileSheetSet tilesheets;
|
ncore::TileSheetSet tilesheets;
|
||||||
ox::Vector<PaletteCycle> palettes;
|
ox::Vector<ox::FileAddress> palettes;
|
||||||
int16_t columns{};
|
int16_t columns{};
|
||||||
int16_t rows{};
|
int16_t rows{};
|
||||||
ox::Array<BgLayer, 3> map;
|
ox::Array<BgLayer, 3> map;
|
||||||
|
@ -24,7 +24,6 @@ static class: public keel::Module {
|
|||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
ox::Vector<keel::TypeDescGenerator> types() const noexcept override {
|
ox::Vector<keel::TypeDescGenerator> types() const noexcept override {
|
||||||
return {
|
return {
|
||||||
keel::generateTypeDesc<PaletteCycle>,
|
|
||||||
keel::generateTypeDesc<WorldObjectSet>,
|
keel::generateTypeDesc<WorldObjectSet>,
|
||||||
keel::generateTypeDesc<WorldDoc>,
|
keel::generateTypeDesc<WorldDoc>,
|
||||||
keel::generateTypeDesc<WorldStatic>,
|
keel::generateTypeDesc<WorldStatic>,
|
||||||
|
@ -41,7 +41,7 @@ ox::Error ObjectCache::indexSet(
|
|||||||
addTileSheet(objSet.tilesheet, static_cast<int32_t>(tileCnt));
|
addTileSheet(objSet.tilesheet, static_cast<int32_t>(tileCnt));
|
||||||
for (auto const&pal : objSet.palettes) {
|
for (auto const&pal : objSet.palettes) {
|
||||||
m_palettes.emplace_back(pal);
|
m_palettes.emplace_back(pal);
|
||||||
oxRequire(p, readObj<ncore::Palette>(kctx, pal.palette));
|
oxRequire(p, readObj<ncore::Palette>(kctx, pal));
|
||||||
m_palBank += largestPage(*p);
|
m_palBank += largestPage(*p);
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
@ -65,7 +65,7 @@ ncore::TileSheetSet const&ObjectCache::tilesheets() const noexcept {
|
|||||||
return m_tilesheetSet;
|
return m_tilesheetSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Vector<PaletteCycle> const&ObjectCache::palettes() const noexcept {
|
ox::Vector<ox::FileAddress> const&ObjectCache::palettes() const noexcept {
|
||||||
return m_palettes;
|
return m_palettes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -431,7 +431,7 @@ ox::Error WorldEditorImGui::loadObjectSets() noexcept {
|
|||||||
oxRequireM(os, readObj<WorldObjectSet>(kctx, set.path));
|
oxRequireM(os, readObj<WorldObjectSet>(kctx, set.path));
|
||||||
oxLogError(addDependency(os->tilesheet));
|
oxLogError(addDependency(os->tilesheet));
|
||||||
for (auto const&pal : os->palettes) {
|
for (auto const&pal : os->palettes) {
|
||||||
oxLogError(addDependency(pal.palette));
|
oxLogError(addDependency(pal));
|
||||||
}
|
}
|
||||||
m_objSets.emplace_back(ox::String(set.path), set.id, std::move(os));
|
m_objSets.emplace_back(ox::String(set.path), set.id, std::move(os));
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ target_sources(
|
|||||||
commands/editobject.cpp
|
commands/editobject.cpp
|
||||||
commands/addpalette.cpp
|
commands/addpalette.cpp
|
||||||
commands/rmpalette.cpp
|
commands/rmpalette.cpp
|
||||||
commands/editpalette.cpp
|
|
||||||
commands/changetilesheet.cpp
|
commands/changetilesheet.cpp
|
||||||
collisionmapview.cpp
|
collisionmapview.cpp
|
||||||
worldobjectseteditor-imgui.cpp
|
worldobjectseteditor-imgui.cpp
|
||||||
|
@ -15,18 +15,18 @@ AddPalette::AddPalette(WorldObjectSet &doc, ox::FileAddress palAddr) noexcept:
|
|||||||
}
|
}
|
||||||
|
|
||||||
ox::Error AddPalette::redo() noexcept {
|
ox::Error AddPalette::redo() noexcept {
|
||||||
m_doc.palettes.emplace_back(PaletteCycle{
|
m_doc.palettes.emplace_back(m_palAddr);
|
||||||
.palette = m_palAddr
|
std::sort(m_doc.palettes.begin(), m_doc.palettes.end(),
|
||||||
});
|
[](ox::FileAddress const&a, ox::FileAddress const&b) {
|
||||||
std::sort(m_doc.palettes.begin(), m_doc.palettes.end(), [](PaletteCycle const&a, PaletteCycle const&b) {
|
return a.getPath().or_value("") < b.getPath().or_value("");
|
||||||
return a.palette.getPath().or_value("") < b.palette.getPath().or_value("");
|
|
||||||
});
|
});
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error AddPalette::undo() noexcept {
|
ox::Error AddPalette::undo() noexcept {
|
||||||
auto const idx = std::find_if(m_doc.palettes.begin(), m_doc.palettes.end(), [this](PaletteCycle const&v) {
|
auto const idx = std::find_if(m_doc.palettes.begin(), m_doc.palettes.end(),
|
||||||
return v.palette == m_palAddr;
|
[this](ox::FileAddress const&v) {
|
||||||
|
return v == m_palAddr;
|
||||||
});
|
});
|
||||||
return m_doc.palettes.erase(idx).error;
|
return m_doc.palettes.erase(idx).error;
|
||||||
}
|
}
|
||||||
|
@ -11,12 +11,12 @@ enum class WorldObjCommand {
|
|||||||
AddObject,
|
AddObject,
|
||||||
RmObject,
|
RmObject,
|
||||||
EditObjectName,
|
EditObjectName,
|
||||||
|
EditObjectInterval,
|
||||||
EditObjectPalette,
|
EditObjectPalette,
|
||||||
EditObjectSubSheet,
|
EditObjectSubSheet,
|
||||||
EditObjectCollisionMap,
|
EditObjectCollisionMap,
|
||||||
AddPalette,
|
AddPalette,
|
||||||
RmPalette,
|
RmPalette,
|
||||||
EditPalette,
|
|
||||||
ChangeTileSheet,
|
ChangeTileSheet,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -43,6 +43,38 @@ bool EditObjectName::mergeWith(UndoCommand const&cmd) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EditObjectInterval::EditObjectInterval(WorldObjectSet &doc, size_t objIdx, uint16_t newInterval) noexcept:
|
||||||
|
m_doc(doc),
|
||||||
|
m_objIdx(objIdx),
|
||||||
|
m_oldVal(m_doc.objects[objIdx].intervalMs),
|
||||||
|
m_newVal(newInterval) {}
|
||||||
|
|
||||||
|
ox::Error EditObjectInterval::redo() noexcept {
|
||||||
|
auto &obj = m_doc.objects[m_objIdx];
|
||||||
|
obj.intervalMs = m_newVal;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
ox::Error EditObjectInterval::undo() noexcept {
|
||||||
|
auto &obj = m_doc.objects[m_objIdx];
|
||||||
|
obj.intervalMs = m_oldVal;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
int EditObjectInterval::commandId() const noexcept {
|
||||||
|
return static_cast<int>(WorldObjCommand::EditObjectInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EditObjectInterval::mergeWith(UndoCommand const&cmd) noexcept {
|
||||||
|
auto const en = dynamic_cast<EditObjectInterval const*>(&cmd);
|
||||||
|
if (en && m_objIdx == en->m_objIdx) {
|
||||||
|
m_newVal = en->m_newVal;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
EditObjectSubSheet::EditObjectSubSheet(
|
EditObjectSubSheet::EditObjectSubSheet(
|
||||||
WorldObjectSet &doc,
|
WorldObjectSet &doc,
|
||||||
size_t objIdx,
|
size_t objIdx,
|
||||||
|
@ -27,6 +27,21 @@ class EditObjectName: public studio::UndoCommand {
|
|||||||
bool mergeWith(UndoCommand const&cmd) noexcept override;
|
bool mergeWith(UndoCommand const&cmd) noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class EditObjectInterval: public studio::UndoCommand {
|
||||||
|
private:
|
||||||
|
WorldObjectSet &m_doc;
|
||||||
|
size_t const m_objIdx{};
|
||||||
|
uint16_t const m_oldVal{};
|
||||||
|
uint16_t m_newVal{};
|
||||||
|
public:
|
||||||
|
EditObjectInterval(WorldObjectSet &doc, size_t objIdx, uint16_t newName) noexcept;
|
||||||
|
ox::Error redo() noexcept override;
|
||||||
|
ox::Error undo() noexcept override;
|
||||||
|
[[nodiscard]]
|
||||||
|
int commandId() const noexcept override;
|
||||||
|
bool mergeWith(UndoCommand const&cmd) noexcept override;
|
||||||
|
};
|
||||||
|
|
||||||
class EditObjectSubSheet: public studio::UndoCommand {
|
class EditObjectSubSheet: public studio::UndoCommand {
|
||||||
private:
|
private:
|
||||||
WorldObjectSet &m_doc;
|
WorldObjectSet &m_doc;
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "commands.hpp"
|
|
||||||
#include "editpalette.hpp"
|
|
||||||
|
|
||||||
namespace jasper::world {
|
|
||||||
|
|
||||||
EditPalette::EditPalette(PaletteCycle &doc, uint16_t interval) noexcept:
|
|
||||||
m_doc(doc),
|
|
||||||
m_oldVal(doc.intervalMs),
|
|
||||||
m_newVal(interval) {
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Error EditPalette::redo() noexcept {
|
|
||||||
m_doc.intervalMs = m_newVal;
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
ox::Error EditPalette::undo() noexcept {
|
|
||||||
m_doc.intervalMs = m_oldVal;
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
int EditPalette::commandId() const noexcept {
|
|
||||||
return static_cast<int>(WorldObjCommand::EditPalette);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <ox/fs/fs.hpp>
|
|
||||||
|
|
||||||
#include <studio/undostack.hpp>
|
|
||||||
|
|
||||||
#include <jasper/world/worldobject.hpp>
|
|
||||||
|
|
||||||
namespace jasper::world {
|
|
||||||
|
|
||||||
class EditPalette: public studio::UndoCommand {
|
|
||||||
private:
|
|
||||||
PaletteCycle &m_doc;
|
|
||||||
uint16_t const m_oldVal{};
|
|
||||||
uint16_t const m_newVal{};
|
|
||||||
public:
|
|
||||||
EditPalette(PaletteCycle &doc, uint16_t interval) noexcept;
|
|
||||||
ox::Error redo() noexcept override;
|
|
||||||
ox::Error undo() noexcept override;
|
|
||||||
[[nodiscard]]
|
|
||||||
int commandId() const noexcept override;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
@ -22,8 +22,9 @@ ox::Error RmPalette::redo() noexcept {
|
|||||||
|
|
||||||
ox::Error RmPalette::undo() noexcept {
|
ox::Error RmPalette::undo() noexcept {
|
||||||
m_doc.palettes.emplace_back(std::move(m_pal));
|
m_doc.palettes.emplace_back(std::move(m_pal));
|
||||||
std::sort(m_doc.palettes.begin(), m_doc.palettes.end(), [](PaletteCycle const&a, PaletteCycle const&b) {
|
std::sort(m_doc.palettes.begin(), m_doc.palettes.end(),
|
||||||
return a.palette.getPath().or_value("") < b.palette.getPath().or_value("");
|
[](ox::FileAddress const&a, ox::FileAddress const&b) {
|
||||||
|
return a.getPath().or_value("") < b.getPath().or_value("");
|
||||||
});
|
});
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ namespace jasper::world {
|
|||||||
class RmPalette: public studio::UndoCommand {
|
class RmPalette: public studio::UndoCommand {
|
||||||
private:
|
private:
|
||||||
WorldObjectSet &m_doc;
|
WorldObjectSet &m_doc;
|
||||||
PaletteCycle m_pal;
|
ox::FileAddress m_pal;
|
||||||
size_t const m_rmIdx = 0;
|
size_t const m_rmIdx = 0;
|
||||||
public:
|
public:
|
||||||
RmPalette(WorldObjectSet &doc, size_t rmIdx) noexcept;
|
RmPalette(WorldObjectSet &doc, size_t rmIdx) noexcept;
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include "commands/editobject.hpp"
|
#include "commands/editobject.hpp"
|
||||||
#include "commands/addpalette.hpp"
|
#include "commands/addpalette.hpp"
|
||||||
#include "commands/rmpalette.hpp"
|
#include "commands/rmpalette.hpp"
|
||||||
#include "commands/editpalette.hpp"
|
|
||||||
#include "commands/changetilesheet.hpp"
|
#include "commands/changetilesheet.hpp"
|
||||||
|
|
||||||
#include "worldobjectseteditor-imgui.hpp"
|
#include "worldobjectseteditor-imgui.hpp"
|
||||||
@ -26,12 +25,12 @@ WorldObjectSetEditorImGui::WorldObjectSetEditorImGui(
|
|||||||
Editor(path),
|
Editor(path),
|
||||||
m_sctx(ctx),
|
m_sctx(ctx),
|
||||||
m_itemPath(path),
|
m_itemPath(path),
|
||||||
m_doc(*readObj<WorldObjectSet>(keelCtx(ctx.tctx), path).unwrapThrow()),
|
m_doc(*readObj<WorldObjectSet>(keelCtx(m_sctx), path).unwrapThrow()),
|
||||||
m_tileSheet(readObj<ncore::TileSheet>(keelCtx(m_sctx.tctx), m_doc.tilesheet).unwrapThrow()) {
|
m_tileSheet(readObj<ncore::TileSheet>(keelCtx(m_sctx), m_doc.tilesheet).unwrapThrow()) {
|
||||||
auto const&tilesheetList = m_sctx.project->fileList(ncore::FileExt_ng);
|
auto const&tilesheetList = m_sctx.project->fileList(ncore::FileExt_ng);
|
||||||
auto &kctx = keelCtx(m_sctx.tctx);
|
auto &kctx = keelCtx(m_sctx);
|
||||||
auto const [tsPath, err] = getPath(kctx, m_doc.tilesheet);
|
auto const [tsPath, err] = getPath(kctx, m_doc.tilesheet);
|
||||||
if (err) {
|
if (!err) {
|
||||||
m_selectedTilesheetIdx = std::find(tilesheetList.begin(), tilesheetList.end(), tsPath).offset();
|
m_selectedTilesheetIdx = std::find(tilesheetList.begin(), tilesheetList.end(), tsPath).offset();
|
||||||
}
|
}
|
||||||
loadObj();
|
loadObj();
|
||||||
@ -67,7 +66,6 @@ void WorldObjectSetEditorImGui::draw(studio::StudioContext&) noexcept {
|
|||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
drawAddPalettePopup();
|
drawAddPalettePopup();
|
||||||
drawEditPalettePopup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldObjectSetEditorImGui::onActivated() noexcept {
|
void WorldObjectSetEditorImGui::onActivated() noexcept {
|
||||||
@ -84,8 +82,8 @@ WorldObject &WorldObjectSetEditorImGui::activeObj() noexcept {
|
|||||||
void WorldObjectSetEditorImGui::buildPaletteDisplayNameList() noexcept {
|
void WorldObjectSetEditorImGui::buildPaletteDisplayNameList() noexcept {
|
||||||
m_paletteDisplayNames.clear();
|
m_paletteDisplayNames.clear();
|
||||||
for (auto i = 1u; auto const&pal : m_doc.palettes) {
|
for (auto i = 1u; auto const&pal : m_doc.palettes) {
|
||||||
auto const path = keel::getPath(keelCtx(m_sctx.tctx), pal.palette).or_value("Invalid path");
|
auto const path = keel::getPath(keelCtx(m_sctx.tctx), pal).or_value("Invalid path");
|
||||||
m_paletteDisplayNames.emplace_back(ox::sfmt("{}: {} - {} ms", i, path, pal.intervalMs));
|
m_paletteDisplayNames.emplace_back(ox::sfmt("{}: {}", i, path));
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,11 +93,11 @@ void WorldObjectSetEditorImGui::drawTileSheetSelector() noexcept {
|
|||||||
auto sel = m_selectedTilesheetIdx;
|
auto sel = m_selectedTilesheetIdx;
|
||||||
if (ig::ComboBox("Tile Sheet", tilesheetList, sel)) {
|
if (ig::ComboBox("Tile Sheet", tilesheetList, sel)) {
|
||||||
auto const [uuid, err] = keel::pathToUuid(
|
auto const [uuid, err] = keel::pathToUuid(
|
||||||
keelCtx(m_sctx.tctx), tilesheetList[m_addPalPopup.selectedIdx]);
|
keelCtx(m_sctx.tctx), tilesheetList[sel]);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
auto const uuidUrl = ox::sfmt("uuid://{}", uuid.toString());
|
auto const uuidUrl = ox::sfmt("uuid://{}", uuid.toString());
|
||||||
std::ignore = undoStack()->push(ox::make_unique<ChangeTileSheet>
|
std::ignore = pushCommand<ChangeTileSheet>
|
||||||
(m_doc, ox::FileAddress(uuidUrl), sel, m_selectedTilesheetIdx));
|
(m_doc, ox::FileAddress(uuidUrl), sel, m_selectedTilesheetIdx);
|
||||||
loadObj();
|
loadObj();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,7 +113,7 @@ void WorldObjectSetEditorImGui::drawObjSelector() noexcept {
|
|||||||
}
|
}
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ig::PushButton("-", btnSize)) {
|
if (ig::PushButton("-", btnSize)) {
|
||||||
std::ignore = undoStack()->push(ox::make_unique<RmObject>(m_doc, m_selectedObj));
|
std::ignore = pushCommand<RmObject>(m_doc, m_selectedObj);
|
||||||
}
|
}
|
||||||
if (ig::ListBox("Objects", [this](size_t i) -> ox::CStringView {
|
if (ig::ListBox("Objects", [this](size_t i) -> ox::CStringView {
|
||||||
return m_doc.objects[i].name;
|
return m_doc.objects[i].name;
|
||||||
@ -132,6 +130,7 @@ void WorldObjectSetEditorImGui::loadObj() noexcept {
|
|||||||
auto &nameBuff = m_objEditor.nameBuff;
|
auto &nameBuff = m_objEditor.nameBuff;
|
||||||
ox::strncpy(nameBuff.data(), obj.name.data(), nameBuff.size());
|
ox::strncpy(nameBuff.data(), obj.name.data(), nameBuff.size());
|
||||||
m_objEditor.palette = obj.palBank;
|
m_objEditor.palette = obj.palBank;
|
||||||
|
m_objEditor.interval = obj.intervalMs;
|
||||||
m_subsheet = getSubsheet(*m_tileSheet, obj.subsheetId);
|
m_subsheet = getSubsheet(*m_tileSheet, obj.subsheetId);
|
||||||
int w = 0;
|
int w = 0;
|
||||||
int h = 0;
|
int h = 0;
|
||||||
@ -142,7 +141,7 @@ void WorldObjectSetEditorImGui::loadObj() noexcept {
|
|||||||
auto const idx = getTileIdx(*m_tileSheet, obj.subsheetId);
|
auto const idx = getTileIdx(*m_tileSheet, obj.subsheetId);
|
||||||
oxLogError(m_colView.setup(
|
oxLogError(m_colView.setup(
|
||||||
m_doc.tilesheet,
|
m_doc.tilesheet,
|
||||||
m_doc.palettes[obj.palBank].palette,
|
m_doc.palettes[obj.palBank],
|
||||||
w,
|
w,
|
||||||
h,
|
h,
|
||||||
static_cast<uint_t>(idx),
|
static_cast<uint_t>(idx),
|
||||||
@ -164,17 +163,22 @@ void WorldObjectSetEditorImGui::drawObjEditor() noexcept {
|
|||||||
ImGui::NewLine();
|
ImGui::NewLine();
|
||||||
auto &nameBuff = m_objEditor.nameBuff;
|
auto &nameBuff = m_objEditor.nameBuff;
|
||||||
if (ImGui::InputText("Name", nameBuff.data(), nameBuff.size())) {
|
if (ImGui::InputText("Name", nameBuff.data(), nameBuff.size())) {
|
||||||
std::ignore = undoStack()->push(ox::make_unique<EditObjectName>(
|
std::ignore = pushCommand<EditObjectName>(
|
||||||
m_doc,
|
m_doc,
|
||||||
m_selectedObj,
|
m_selectedObj,
|
||||||
ox::String(nameBuff.data(), ox::strnlen(nameBuff.data(), nameBuff.size()))));
|
ox::String(nameBuff.data(), ox::strnlen(nameBuff.data(), nameBuff.size())));
|
||||||
}
|
}
|
||||||
// SubSheet Selector
|
// SubSheet Selector
|
||||||
{
|
{
|
||||||
ig::IDStackItem const subsheetSelectorStackItem("SubsheetSelector");
|
ig::IDStackItem const subsheetSelectorStackItem("SubsheetSelector");
|
||||||
if (ig::ComboBox("Palette", m_paletteDisplayNames, m_objEditor.palette)) {
|
if (ig::ComboBox("Palette", m_paletteDisplayNames, m_objEditor.palette)) {
|
||||||
std::ignore = undoStack()->push(ox::make_unique<EditObjectPalette>(
|
std::ignore = pushCommand<EditObjectPalette>(
|
||||||
m_doc, m_selectedObj, static_cast<uint16_t>(m_objEditor.palette)));
|
m_doc, m_selectedObj, static_cast<uint16_t>(m_objEditor.palette));
|
||||||
|
}
|
||||||
|
if (ImGui::InputInt("Interval (ms)", &m_objEditor.interval, 50, 1000)) {
|
||||||
|
m_objEditor.interval = ox::clamp(m_objEditor.interval, 50, 65535);
|
||||||
|
std::ignore = pushCommand<EditObjectInterval>(
|
||||||
|
m_doc, m_selectedObj, static_cast<uint16_t>(m_objEditor.interval));
|
||||||
}
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::Text("Subsheet:");
|
ImGui::Text("Subsheet:");
|
||||||
@ -213,8 +217,7 @@ void WorldObjectSetEditorImGui::drawObjEditor() noexcept {
|
|||||||
auto &obj = activeObj();
|
auto &obj = activeObj();
|
||||||
auto intermediate = obj.collisionMap;
|
auto intermediate = obj.collisionMap;
|
||||||
if (m_colView.click(mousePos, intermediate)) {
|
if (m_colView.click(mousePos, intermediate)) {
|
||||||
std::ignore = undoStack()->push(ox::make_unique<EditObjectCollisionMap>(
|
std::ignore = pushCommand<EditObjectCollisionMap>(m_doc, m_selectedObj, intermediate);
|
||||||
m_doc, m_selectedObj, intermediate));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,7 +237,7 @@ void WorldObjectSetEditorImGui::drawSubSheetNode(ncore::TileSheet::SubSheet cons
|
|||||||
}
|
}
|
||||||
} else if (ImGui::TreeNodeEx(ss.name.c_str(), ImGuiTreeNodeFlags_Leaf | selected)) {
|
} else if (ImGui::TreeNodeEx(ss.name.c_str(), ImGuiTreeNodeFlags_Leaf | selected)) {
|
||||||
if (ImGui::IsItemClicked()) {
|
if (ImGui::IsItemClicked()) {
|
||||||
std::ignore = undoStack()->push(ox::make_unique<EditObjectSubSheet>(m_doc, m_selectedObj, ss.id));
|
std::ignore = pushCommand<EditObjectSubSheet>(m_doc, m_selectedObj, ss.id);
|
||||||
}
|
}
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
@ -249,14 +252,9 @@ void WorldObjectSetEditorImGui::drawPaletteList() noexcept {
|
|||||||
if (ig::PushButton("-", btnSize)) {
|
if (ig::PushButton("-", btnSize)) {
|
||||||
rmPalette();
|
rmPalette();
|
||||||
}
|
}
|
||||||
ImGui::SameLine();
|
|
||||||
if (ig::PushButton("Edit")) {
|
|
||||||
editPalette();
|
|
||||||
}
|
|
||||||
constexpr auto flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
|
constexpr auto flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
|
||||||
if (ImGui::BeginTable("Subsheets", 2, flags)) {
|
if (ImGui::BeginTable("Subsheets", 1, flags)) {
|
||||||
ImGui::TableSetupColumn("Palette", ImGuiTableColumnFlags_NoHide);
|
ImGui::TableSetupColumn("Palette", ImGuiTableColumnFlags_NoHide);
|
||||||
ImGui::TableSetupColumn("Interval", ImGuiTableColumnFlags_WidthFixed, 100);
|
|
||||||
ImGui::TableHeadersRow();
|
ImGui::TableHeadersRow();
|
||||||
drawPaletteListItems();
|
drawPaletteListItems();
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
@ -269,17 +267,12 @@ void WorldObjectSetEditorImGui::drawPaletteListItems() noexcept {
|
|||||||
ImGui::TableNextRow();
|
ImGui::TableNextRow();
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
auto const path
|
auto const path
|
||||||
= keel::getPath(keelCtx(m_sctx.tctx), pal.palette).or_value("Invalid path");
|
= keel::getPath(keelCtx(m_sctx.tctx), pal).or_value("Invalid path");
|
||||||
ImGui::Text("%s", path.c_str());
|
ImGui::Text("%s", path.c_str());
|
||||||
ImGui::TableNextColumn();
|
|
||||||
ImGui::Text("%d ms", pal.intervalMs);
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
if (ImGui::Selectable("##PaletteSelection", i == m_selectedPal, ImGuiSelectableFlags_SpanAllColumns)) {
|
if (ImGui::Selectable("##PaletteSelection", i == m_selectedPal, ImGuiSelectableFlags_SpanAllColumns)) {
|
||||||
m_selectedPal = i;
|
m_selectedPal = i;
|
||||||
}
|
}
|
||||||
if (ImGui::IsMouseDoubleClicked(0) && ImGui::IsItemHovered()) {
|
|
||||||
editPalette();
|
|
||||||
}
|
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -299,48 +292,20 @@ void WorldObjectSetEditorImGui::drawAddPalettePopup() noexcept {
|
|||||||
keelCtx(m_sctx.tctx), palettes[m_addPalPopup.selectedIdx]);
|
keelCtx(m_sctx.tctx), palettes[m_addPalPopup.selectedIdx]);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
auto const uuidUrl = ox::sfmt("uuid://{}", uuid.toString());
|
auto const uuidUrl = ox::sfmt("uuid://{}", uuid.toString());
|
||||||
std::ignore = undoStack()->push(ox::make_unique<AddPalette>(
|
std::ignore = pushCommand<AddPalette>(m_doc, ox::FileAddress(uuidUrl));
|
||||||
m_doc, ox::FileAddress(uuidUrl)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldObjectSetEditorImGui::drawEditPalettePopup() noexcept {
|
|
||||||
if (!m_editPalPopup.show) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto constexpr popupName = ox::CStringView("Edit Palette");
|
|
||||||
auto constexpr popupSz = ImVec2{300.f, 0};
|
|
||||||
ig::IDStackItem const idStackItem("EditPalette");
|
|
||||||
if (ig::BeginPopup(m_sctx.tctx, popupName, m_editPalPopup.show, popupSz)) {
|
|
||||||
auto &pal = m_doc.palettes[m_selectedPal];
|
|
||||||
ImGui::InputInt("Interval (ms)", &m_editPalPopup.intervalInputVal, 1000);
|
|
||||||
m_editPalPopup.intervalInputVal =
|
|
||||||
static_cast<uint16_t>(ox::clamp(m_editPalPopup.intervalInputVal, 0, 60000));
|
|
||||||
if (ig::PopupControlsOkCancel(popupSz.x, m_editPalPopup.show) == ig::PopupResponse::OK) {
|
|
||||||
std::ignore = undoStack()->push(ox::make_unique<EditPalette>(
|
|
||||||
pal, static_cast<uint16_t>(m_editPalPopup.intervalInputVal)));
|
|
||||||
}
|
|
||||||
ImGui::EndPopup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldObjectSetEditorImGui::addPalette() noexcept {
|
void WorldObjectSetEditorImGui::addPalette() noexcept {
|
||||||
m_addPalPopup.show = true;
|
m_addPalPopup.show = true;
|
||||||
m_addPalPopup.selectedIdx = 0;
|
m_addPalPopup.selectedIdx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WorldObjectSetEditorImGui::rmPalette() noexcept {
|
void WorldObjectSetEditorImGui::rmPalette() noexcept {
|
||||||
std::ignore = undoStack()->push(ox::make_unique<RmPalette>(
|
std::ignore = pushCommand<RmPalette>(m_doc, m_selectedPal);
|
||||||
m_doc, m_selectedPal));
|
|
||||||
}
|
|
||||||
|
|
||||||
void WorldObjectSetEditorImGui::editPalette() noexcept {
|
|
||||||
auto &pal = m_doc.palettes[m_selectedPal];
|
|
||||||
m_editPalPopup.show = true;
|
|
||||||
m_editPalPopup.intervalInputVal = pal.intervalMs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error WorldObjectSetEditorImGui::handleCmd(studio::UndoCommand const*cmd) noexcept {
|
ox::Error WorldObjectSetEditorImGui::handleCmd(studio::UndoCommand const*cmd) noexcept {
|
||||||
@ -349,8 +314,7 @@ ox::Error WorldObjectSetEditorImGui::handleCmd(studio::UndoCommand const*cmd) no
|
|||||||
oxLogError(readObj<ncore::TileSheet>(kctx, m_doc.tilesheet).moveTo(m_tileSheet));
|
oxLogError(readObj<ncore::TileSheet>(kctx, m_doc.tilesheet).moveTo(m_tileSheet));
|
||||||
} else if (
|
} else if (
|
||||||
dynamic_cast<AddPalette const*>(cmd) ||
|
dynamic_cast<AddPalette const*>(cmd) ||
|
||||||
dynamic_cast<RmPalette const*>(cmd) ||
|
dynamic_cast<RmPalette const*>(cmd)) {
|
||||||
dynamic_cast<EditPalette const*>(cmd)) {
|
|
||||||
buildPaletteDisplayNameList();
|
buildPaletteDisplayNameList();
|
||||||
} else if (dynamic_cast<EditObjectPalette const*>(cmd)) {
|
} else if (dynamic_cast<EditObjectPalette const*>(cmd)) {
|
||||||
auto const&obj = activeObj();
|
auto const&obj = activeObj();
|
||||||
|
@ -29,13 +29,10 @@ class WorldObjectSetEditorImGui: public studio::Editor {
|
|||||||
bool show{};
|
bool show{};
|
||||||
size_t selectedIdx{};
|
size_t selectedIdx{};
|
||||||
} m_addPalPopup;
|
} m_addPalPopup;
|
||||||
struct {
|
|
||||||
bool show{};
|
|
||||||
int intervalInputVal{};
|
|
||||||
} m_editPalPopup;
|
|
||||||
CollisionView m_colView{m_sctx};
|
CollisionView m_colView{m_sctx};
|
||||||
struct {
|
struct {
|
||||||
ox::Buffer nameBuff = ox::Buffer(256);
|
ox::Buffer nameBuff = ox::Buffer(256);
|
||||||
|
int interval{};
|
||||||
size_t palette{};
|
size_t palette{};
|
||||||
} m_objEditor;
|
} m_objEditor;
|
||||||
|
|
||||||
@ -69,14 +66,10 @@ class WorldObjectSetEditorImGui: public studio::Editor {
|
|||||||
|
|
||||||
void drawAddPalettePopup() noexcept;
|
void drawAddPalettePopup() noexcept;
|
||||||
|
|
||||||
void drawEditPalettePopup() noexcept;
|
|
||||||
|
|
||||||
void addPalette() noexcept;
|
void addPalette() noexcept;
|
||||||
|
|
||||||
void rmPalette() noexcept;
|
void rmPalette() noexcept;
|
||||||
|
|
||||||
void editPalette() noexcept;
|
|
||||||
|
|
||||||
ox::Error handleCmd(studio::UndoCommand const*cmd) noexcept;
|
ox::Error handleCmd(studio::UndoCommand const*cmd) noexcept;
|
||||||
|
|
||||||
ox::Error saveItem() noexcept final;
|
ox::Error saveItem() noexcept final;
|
||||||
|
@ -18,11 +18,9 @@ ox::Error World::setupDisplay() noexcept {
|
|||||||
if (m_worldStatic.palettes.empty()) {
|
if (m_worldStatic.palettes.empty()) {
|
||||||
return OxError(1, "World has no palettes");
|
return OxError(1, "World has no palettes");
|
||||||
}
|
}
|
||||||
m_palettes.clear();
|
for (auto i = 0u; auto const&palAddr : m_worldStatic.palettes) {
|
||||||
for (auto i = 0u; auto const&pal : m_worldStatic.palettes) {
|
oxRequire(pal, readObj<ncore::CompactPalette>(keelCtx(m_nctx), palAddr));
|
||||||
auto &palRef = m_palettes.emplace_back();
|
oxReturnError(ncore::loadBgPalette(m_nctx, i, *pal));
|
||||||
oxReturnError(readObj<ncore::CompactPalette>(keelCtx(m_nctx), pal.palette).moveTo(palRef.pal));
|
|
||||||
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,15 +66,7 @@ void World::setupLayer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ox::Result<int> World::update() noexcept {
|
ox::Result<int> World::update() noexcept {
|
||||||
auto const time = ticksMs(turbineCtx(m_nctx));
|
|
||||||
int expiresIn = 60'000;
|
int expiresIn = 60'000;
|
||||||
for (size_t i = 0; auto const&pal : m_palettes) {
|
|
||||||
auto const interval = m_worldStatic.palettes[i].intervalMs;
|
|
||||||
auto const page = (time / interval) % pal.pal->pages.size();
|
|
||||||
expiresIn = ox::min(expiresIn, static_cast<int>(time % interval));
|
|
||||||
oxReturnError(ncore::loadBgPalette(m_nctx, i, *pal.pal, static_cast<size_t>(page)));
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
return expiresIn;
|
return expiresIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,22 +75,6 @@ ox::Result<int> World::editorModeUpdate() noexcept {
|
|||||||
auto const time = ticksMs(turbineCtx(m_nctx));
|
auto const time = ticksMs(turbineCtx(m_nctx));
|
||||||
if (time >= m_nextUpdateTime) {
|
if (time >= m_nextUpdateTime) {
|
||||||
turbine::TimeMs expiresIn = 60'000;
|
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;
|
m_nextUpdateTime = time + expiresIn;
|
||||||
}
|
}
|
||||||
return static_cast<int>(m_nextUpdateTime - time);
|
return static_cast<int>(m_nextUpdateTime - time);
|
||||||
|
Reference in New Issue
Block a user