[jasper/world] Remove palette based animation system
This commit is contained in:
@ -26,7 +26,7 @@ class ObjectCache {
|
||||
ox::Vector<Obj> objects;
|
||||
};
|
||||
ox::Vector<ox::FileAddress> m_tilesheets;
|
||||
ox::Vector<PaletteCycle> m_palettes;
|
||||
ox::Vector<ox::FileAddress> m_palettes;
|
||||
size_t m_tileIdx{};
|
||||
size_t m_palBank{};
|
||||
ox::Vector<ObjSet> m_objSets;
|
||||
@ -42,7 +42,7 @@ class ObjectCache {
|
||||
[[nodiscard]]
|
||||
ncore::TileSheetSet const&tilesheets() const noexcept;
|
||||
[[nodiscard]]
|
||||
ox::Vector<PaletteCycle> const&palettes() const noexcept;
|
||||
ox::Vector<ox::FileAddress> const&palettes() const noexcept;
|
||||
private:
|
||||
void addTileSheet(ox::FileAddress path, int32_t tiles) noexcept;
|
||||
};
|
||||
|
@ -16,15 +16,10 @@ namespace ncore = nostalgia::core;
|
||||
|
||||
class World {
|
||||
private:
|
||||
struct PaletteTracker {
|
||||
keel::AssetRef<ncore::CompactPalette> pal;
|
||||
int page{};
|
||||
};
|
||||
ox::Vector<PaletteTracker, 10> m_palettes;
|
||||
ncore::Context &m_nctx;
|
||||
WorldStatic const&m_worldStatic;
|
||||
#ifndef OX_OS_BareMetal
|
||||
turbine::TimeMs m_prevUpdateTime{};
|
||||
//turbine::TimeMs m_prevUpdateTime{};
|
||||
turbine::TimeMs m_nextUpdateTime{};
|
||||
#endif
|
||||
|
||||
|
@ -13,19 +13,6 @@ namespace jasper::world {
|
||||
|
||||
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;
|
||||
|
||||
enum class ObjectType: uint8_t {
|
||||
@ -42,6 +29,7 @@ struct WorldObject {
|
||||
static constexpr auto TypeVersion = 1;
|
||||
ObjectId id{};
|
||||
ox::String name;
|
||||
uint16_t intervalMs{};
|
||||
uint16_t palBank{};
|
||||
ncore::SubSheetId subsheetId{};
|
||||
CollisionMap collisionMap{};
|
||||
@ -54,6 +42,7 @@ struct WorldObject {
|
||||
oxModelBegin(WorldObject)
|
||||
oxModelField(id)
|
||||
oxModelField(name)
|
||||
oxModelFieldRename(intervalMs, interval_ms)
|
||||
oxModelFieldRename(palBank, pal_bank)
|
||||
oxModelFieldRename(subsheetId, subsheet_id)
|
||||
oxModelFieldRename(collisionMap, collision_map)
|
||||
@ -80,7 +69,7 @@ struct WorldObjectSet {
|
||||
// index used to assign unique IDs to objects in the set
|
||||
ObjectId objIdIdx = 0;
|
||||
ox::FileAddress tilesheet;
|
||||
ox::Vector<PaletteCycle> palettes;
|
||||
ox::Vector<ox::FileAddress> palettes;
|
||||
ox::Vector<WorldObject> objects;
|
||||
};
|
||||
|
||||
|
@ -91,7 +91,7 @@ struct WorldStatic {
|
||||
constexpr static auto TypeVersion = 1;
|
||||
constexpr static auto Preloadable = true;
|
||||
ncore::TileSheetSet tilesheets;
|
||||
ox::Vector<PaletteCycle> palettes;
|
||||
ox::Vector<ox::FileAddress> palettes;
|
||||
int16_t columns{};
|
||||
int16_t rows{};
|
||||
ox::Array<BgLayer, 3> map;
|
||||
|
@ -24,7 +24,6 @@ static class: public keel::Module {
|
||||
[[nodiscard]]
|
||||
ox::Vector<keel::TypeDescGenerator> types() const noexcept override {
|
||||
return {
|
||||
keel::generateTypeDesc<PaletteCycle>,
|
||||
keel::generateTypeDesc<WorldObjectSet>,
|
||||
keel::generateTypeDesc<WorldDoc>,
|
||||
keel::generateTypeDesc<WorldStatic>,
|
||||
|
@ -41,7 +41,7 @@ ox::Error ObjectCache::indexSet(
|
||||
addTileSheet(objSet.tilesheet, static_cast<int32_t>(tileCnt));
|
||||
for (auto const&pal : objSet.palettes) {
|
||||
m_palettes.emplace_back(pal);
|
||||
oxRequire(p, readObj<ncore::Palette>(kctx, pal.palette));
|
||||
oxRequire(p, readObj<ncore::Palette>(kctx, pal));
|
||||
m_palBank += largestPage(*p);
|
||||
}
|
||||
return {};
|
||||
@ -65,7 +65,7 @@ ncore::TileSheetSet const&ObjectCache::tilesheets() const noexcept {
|
||||
return m_tilesheetSet;
|
||||
}
|
||||
|
||||
ox::Vector<PaletteCycle> const&ObjectCache::palettes() const noexcept {
|
||||
ox::Vector<ox::FileAddress> const&ObjectCache::palettes() const noexcept {
|
||||
return m_palettes;
|
||||
}
|
||||
|
||||
|
@ -431,7 +431,7 @@ ox::Error WorldEditorImGui::loadObjectSets() noexcept {
|
||||
oxRequireM(os, readObj<WorldObjectSet>(kctx, set.path));
|
||||
oxLogError(addDependency(os->tilesheet));
|
||||
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));
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ target_sources(
|
||||
commands/editobject.cpp
|
||||
commands/addpalette.cpp
|
||||
commands/rmpalette.cpp
|
||||
commands/editpalette.cpp
|
||||
commands/changetilesheet.cpp
|
||||
collisionmapview.cpp
|
||||
worldobjectseteditor-imgui.cpp
|
||||
|
@ -15,19 +15,19 @@ AddPalette::AddPalette(WorldObjectSet &doc, ox::FileAddress palAddr) noexcept:
|
||||
}
|
||||
|
||||
ox::Error AddPalette::redo() noexcept {
|
||||
m_doc.palettes.emplace_back(PaletteCycle{
|
||||
.palette = m_palAddr
|
||||
});
|
||||
std::sort(m_doc.palettes.begin(), m_doc.palettes.end(), [](PaletteCycle const&a, PaletteCycle const&b) {
|
||||
return a.palette.getPath().or_value("") < b.palette.getPath().or_value("");
|
||||
});
|
||||
m_doc.palettes.emplace_back(m_palAddr);
|
||||
std::sort(m_doc.palettes.begin(), m_doc.palettes.end(),
|
||||
[](ox::FileAddress const&a, ox::FileAddress const&b) {
|
||||
return a.getPath().or_value("") < b.getPath().or_value("");
|
||||
});
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error AddPalette::undo() noexcept {
|
||||
auto const idx = std::find_if(m_doc.palettes.begin(), m_doc.palettes.end(), [this](PaletteCycle const&v) {
|
||||
return v.palette == m_palAddr;
|
||||
});
|
||||
auto const idx = std::find_if(m_doc.palettes.begin(), m_doc.palettes.end(),
|
||||
[this](ox::FileAddress const&v) {
|
||||
return v == m_palAddr;
|
||||
});
|
||||
return m_doc.palettes.erase(idx).error;
|
||||
}
|
||||
|
||||
|
@ -11,12 +11,12 @@ enum class WorldObjCommand {
|
||||
AddObject,
|
||||
RmObject,
|
||||
EditObjectName,
|
||||
EditObjectInterval,
|
||||
EditObjectPalette,
|
||||
EditObjectSubSheet,
|
||||
EditObjectCollisionMap,
|
||||
AddPalette,
|
||||
RmPalette,
|
||||
EditPalette,
|
||||
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(
|
||||
WorldObjectSet &doc,
|
||||
size_t objIdx,
|
||||
|
@ -27,6 +27,21 @@ class EditObjectName: public studio::UndoCommand {
|
||||
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 {
|
||||
private:
|
||||
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,9 +22,10 @@ ox::Error RmPalette::redo() noexcept {
|
||||
|
||||
ox::Error RmPalette::undo() noexcept {
|
||||
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) {
|
||||
return a.palette.getPath().or_value("") < b.palette.getPath().or_value("");
|
||||
});
|
||||
std::sort(m_doc.palettes.begin(), m_doc.palettes.end(),
|
||||
[](ox::FileAddress const&a, ox::FileAddress const&b) {
|
||||
return a.getPath().or_value("") < b.getPath().or_value("");
|
||||
});
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ namespace jasper::world {
|
||||
class RmPalette: public studio::UndoCommand {
|
||||
private:
|
||||
WorldObjectSet &m_doc;
|
||||
PaletteCycle m_pal;
|
||||
ox::FileAddress m_pal;
|
||||
size_t const m_rmIdx = 0;
|
||||
public:
|
||||
RmPalette(WorldObjectSet &doc, size_t rmIdx) noexcept;
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "commands/editobject.hpp"
|
||||
#include "commands/addpalette.hpp"
|
||||
#include "commands/rmpalette.hpp"
|
||||
#include "commands/editpalette.hpp"
|
||||
#include "commands/changetilesheet.hpp"
|
||||
|
||||
#include "worldobjectseteditor-imgui.hpp"
|
||||
@ -26,12 +25,12 @@ WorldObjectSetEditorImGui::WorldObjectSetEditorImGui(
|
||||
Editor(path),
|
||||
m_sctx(ctx),
|
||||
m_itemPath(path),
|
||||
m_doc(*readObj<WorldObjectSet>(keelCtx(ctx.tctx), path).unwrapThrow()),
|
||||
m_tileSheet(readObj<ncore::TileSheet>(keelCtx(m_sctx.tctx), m_doc.tilesheet).unwrapThrow()) {
|
||||
m_doc(*readObj<WorldObjectSet>(keelCtx(m_sctx), path).unwrapThrow()),
|
||||
m_tileSheet(readObj<ncore::TileSheet>(keelCtx(m_sctx), m_doc.tilesheet).unwrapThrow()) {
|
||||
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);
|
||||
if (err) {
|
||||
if (!err) {
|
||||
m_selectedTilesheetIdx = std::find(tilesheetList.begin(), tilesheetList.end(), tsPath).offset();
|
||||
}
|
||||
loadObj();
|
||||
@ -67,7 +66,6 @@ void WorldObjectSetEditorImGui::draw(studio::StudioContext&) noexcept {
|
||||
}
|
||||
ImGui::EndChild();
|
||||
drawAddPalettePopup();
|
||||
drawEditPalettePopup();
|
||||
}
|
||||
|
||||
void WorldObjectSetEditorImGui::onActivated() noexcept {
|
||||
@ -84,8 +82,8 @@ WorldObject &WorldObjectSetEditorImGui::activeObj() noexcept {
|
||||
void WorldObjectSetEditorImGui::buildPaletteDisplayNameList() noexcept {
|
||||
m_paletteDisplayNames.clear();
|
||||
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");
|
||||
m_paletteDisplayNames.emplace_back(ox::sfmt("{}: {} - {} ms", i, path, pal.intervalMs));
|
||||
auto const path = keel::getPath(keelCtx(m_sctx.tctx), pal).or_value("Invalid path");
|
||||
m_paletteDisplayNames.emplace_back(ox::sfmt("{}: {}", i, path));
|
||||
++i;
|
||||
}
|
||||
}
|
||||
@ -95,11 +93,11 @@ void WorldObjectSetEditorImGui::drawTileSheetSelector() noexcept {
|
||||
auto sel = m_selectedTilesheetIdx;
|
||||
if (ig::ComboBox("Tile Sheet", tilesheetList, sel)) {
|
||||
auto const [uuid, err] = keel::pathToUuid(
|
||||
keelCtx(m_sctx.tctx), tilesheetList[m_addPalPopup.selectedIdx]);
|
||||
keelCtx(m_sctx.tctx), tilesheetList[sel]);
|
||||
if (!err) {
|
||||
auto const uuidUrl = ox::sfmt("uuid://{}", uuid.toString());
|
||||
std::ignore = undoStack()->push(ox::make_unique<ChangeTileSheet>
|
||||
(m_doc, ox::FileAddress(uuidUrl), sel, m_selectedTilesheetIdx));
|
||||
std::ignore = pushCommand<ChangeTileSheet>
|
||||
(m_doc, ox::FileAddress(uuidUrl), sel, m_selectedTilesheetIdx);
|
||||
loadObj();
|
||||
}
|
||||
}
|
||||
@ -115,7 +113,7 @@ void WorldObjectSetEditorImGui::drawObjSelector() noexcept {
|
||||
}
|
||||
ImGui::SameLine();
|
||||
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 {
|
||||
return m_doc.objects[i].name;
|
||||
@ -132,6 +130,7 @@ void WorldObjectSetEditorImGui::loadObj() noexcept {
|
||||
auto &nameBuff = m_objEditor.nameBuff;
|
||||
ox::strncpy(nameBuff.data(), obj.name.data(), nameBuff.size());
|
||||
m_objEditor.palette = obj.palBank;
|
||||
m_objEditor.interval = obj.intervalMs;
|
||||
m_subsheet = getSubsheet(*m_tileSheet, obj.subsheetId);
|
||||
int w = 0;
|
||||
int h = 0;
|
||||
@ -142,7 +141,7 @@ void WorldObjectSetEditorImGui::loadObj() noexcept {
|
||||
auto const idx = getTileIdx(*m_tileSheet, obj.subsheetId);
|
||||
oxLogError(m_colView.setup(
|
||||
m_doc.tilesheet,
|
||||
m_doc.palettes[obj.palBank].palette,
|
||||
m_doc.palettes[obj.palBank],
|
||||
w,
|
||||
h,
|
||||
static_cast<uint_t>(idx),
|
||||
@ -164,17 +163,22 @@ void WorldObjectSetEditorImGui::drawObjEditor() noexcept {
|
||||
ImGui::NewLine();
|
||||
auto &nameBuff = m_objEditor.nameBuff;
|
||||
if (ImGui::InputText("Name", nameBuff.data(), nameBuff.size())) {
|
||||
std::ignore = undoStack()->push(ox::make_unique<EditObjectName>(
|
||||
std::ignore = pushCommand<EditObjectName>(
|
||||
m_doc,
|
||||
m_selectedObj,
|
||||
ox::String(nameBuff.data(), ox::strnlen(nameBuff.data(), nameBuff.size()))));
|
||||
ox::String(nameBuff.data(), ox::strnlen(nameBuff.data(), nameBuff.size())));
|
||||
}
|
||||
// SubSheet Selector
|
||||
{
|
||||
ig::IDStackItem const subsheetSelectorStackItem("SubsheetSelector");
|
||||
if (ig::ComboBox("Palette", m_paletteDisplayNames, m_objEditor.palette)) {
|
||||
std::ignore = undoStack()->push(ox::make_unique<EditObjectPalette>(
|
||||
m_doc, m_selectedObj, static_cast<uint16_t>(m_objEditor.palette)));
|
||||
std::ignore = pushCommand<EditObjectPalette>(
|
||||
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::Text("Subsheet:");
|
||||
@ -213,8 +217,7 @@ void WorldObjectSetEditorImGui::drawObjEditor() noexcept {
|
||||
auto &obj = activeObj();
|
||||
auto intermediate = obj.collisionMap;
|
||||
if (m_colView.click(mousePos, intermediate)) {
|
||||
std::ignore = undoStack()->push(ox::make_unique<EditObjectCollisionMap>(
|
||||
m_doc, m_selectedObj, intermediate));
|
||||
std::ignore = pushCommand<EditObjectCollisionMap>(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)) {
|
||||
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();
|
||||
}
|
||||
@ -249,14 +252,9 @@ void WorldObjectSetEditorImGui::drawPaletteList() noexcept {
|
||||
if (ig::PushButton("-", btnSize)) {
|
||||
rmPalette();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ig::PushButton("Edit")) {
|
||||
editPalette();
|
||||
}
|
||||
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("Interval", ImGuiTableColumnFlags_WidthFixed, 100);
|
||||
ImGui::TableHeadersRow();
|
||||
drawPaletteListItems();
|
||||
ImGui::EndTable();
|
||||
@ -269,17 +267,12 @@ void WorldObjectSetEditorImGui::drawPaletteListItems() noexcept {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
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::TableNextColumn();
|
||||
ImGui::Text("%d ms", pal.intervalMs);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Selectable("##PaletteSelection", i == m_selectedPal, ImGuiSelectableFlags_SpanAllColumns)) {
|
||||
m_selectedPal = i;
|
||||
}
|
||||
if (ImGui::IsMouseDoubleClicked(0) && ImGui::IsItemHovered()) {
|
||||
editPalette();
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
@ -299,48 +292,20 @@ void WorldObjectSetEditorImGui::drawAddPalettePopup() noexcept {
|
||||
keelCtx(m_sctx.tctx), palettes[m_addPalPopup.selectedIdx]);
|
||||
if (!err) {
|
||||
auto const uuidUrl = ox::sfmt("uuid://{}", uuid.toString());
|
||||
std::ignore = undoStack()->push(ox::make_unique<AddPalette>(
|
||||
m_doc, ox::FileAddress(uuidUrl)));
|
||||
std::ignore = pushCommand<AddPalette>(m_doc, ox::FileAddress(uuidUrl));
|
||||
}
|
||||
}
|
||||
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 {
|
||||
m_addPalPopup.show = true;
|
||||
m_addPalPopup.selectedIdx = 0;
|
||||
}
|
||||
|
||||
void WorldObjectSetEditorImGui::rmPalette() noexcept {
|
||||
std::ignore = undoStack()->push(ox::make_unique<RmPalette>(
|
||||
m_doc, m_selectedPal));
|
||||
}
|
||||
|
||||
void WorldObjectSetEditorImGui::editPalette() noexcept {
|
||||
auto &pal = m_doc.palettes[m_selectedPal];
|
||||
m_editPalPopup.show = true;
|
||||
m_editPalPopup.intervalInputVal = pal.intervalMs;
|
||||
std::ignore = pushCommand<RmPalette>(m_doc, m_selectedPal);
|
||||
}
|
||||
|
||||
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));
|
||||
} else if (
|
||||
dynamic_cast<AddPalette const*>(cmd) ||
|
||||
dynamic_cast<RmPalette const*>(cmd) ||
|
||||
dynamic_cast<EditPalette const*>(cmd)) {
|
||||
dynamic_cast<RmPalette const*>(cmd)) {
|
||||
buildPaletteDisplayNameList();
|
||||
} else if (dynamic_cast<EditObjectPalette const*>(cmd)) {
|
||||
auto const&obj = activeObj();
|
||||
|
@ -29,13 +29,10 @@ class WorldObjectSetEditorImGui: public studio::Editor {
|
||||
bool show{};
|
||||
size_t selectedIdx{};
|
||||
} m_addPalPopup;
|
||||
struct {
|
||||
bool show{};
|
||||
int intervalInputVal{};
|
||||
} m_editPalPopup;
|
||||
CollisionView m_colView{m_sctx};
|
||||
struct {
|
||||
ox::Buffer nameBuff = ox::Buffer(256);
|
||||
int interval{};
|
||||
size_t palette{};
|
||||
} m_objEditor;
|
||||
|
||||
@ -69,14 +66,10 @@ class WorldObjectSetEditorImGui: public studio::Editor {
|
||||
|
||||
void drawAddPalettePopup() noexcept;
|
||||
|
||||
void drawEditPalettePopup() noexcept;
|
||||
|
||||
void addPalette() noexcept;
|
||||
|
||||
void rmPalette() noexcept;
|
||||
|
||||
void editPalette() noexcept;
|
||||
|
||||
ox::Error handleCmd(studio::UndoCommand const*cmd) noexcept;
|
||||
|
||||
ox::Error saveItem() noexcept final;
|
||||
|
@ -18,11 +18,9 @@ ox::Error World::setupDisplay() noexcept {
|
||||
if (m_worldStatic.palettes.empty()) {
|
||||
return OxError(1, "World has no palettes");
|
||||
}
|
||||
m_palettes.clear();
|
||||
for (auto i = 0u; auto const&pal : m_worldStatic.palettes) {
|
||||
auto &palRef = m_palettes.emplace_back();
|
||||
oxReturnError(readObj<ncore::CompactPalette>(keelCtx(m_nctx), pal.palette).moveTo(palRef.pal));
|
||||
oxReturnError(ncore::loadBgPalette(m_nctx, i, *palRef.pal));
|
||||
for (auto i = 0u; auto const&palAddr : m_worldStatic.palettes) {
|
||||
oxRequire(pal, readObj<ncore::CompactPalette>(keelCtx(m_nctx), palAddr));
|
||||
oxReturnError(ncore::loadBgPalette(m_nctx, i, *pal));
|
||||
++i;
|
||||
}
|
||||
oxReturnError(ncore::loadBgTileSheet(m_nctx, 0, m_worldStatic.tilesheets));
|
||||
@ -68,15 +66,7 @@ void World::setupLayer(
|
||||
}
|
||||
|
||||
ox::Result<int> World::update() noexcept {
|
||||
auto const time = ticksMs(turbineCtx(m_nctx));
|
||||
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;
|
||||
}
|
||||
|
||||
@ -85,22 +75,6 @@ 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);
|
||||
|
Reference in New Issue
Block a user