[jasper/world] Remove palette based animation system
This commit is contained in:
@@ -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;
|
||||
|
Reference in New Issue
Block a user