[nostalgia] Add NewMenu for creating new files
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include "ox/std/memory.hpp"
|
||||
#include "paletteeditor-imgui.hpp"
|
||||
#include "tilesheeteditor-imgui.hpp"
|
||||
|
||||
@@ -30,4 +31,11 @@ ox::Vector<studio::EditorMaker> Module::editors(core::Context *ctx) noexcept {
|
||||
};
|
||||
}
|
||||
|
||||
ox::Vector<ox::UniquePtr<studio::ItemMaker>> Module::itemMakers(core::Context*) noexcept {
|
||||
ox::Vector<ox::UniquePtr<studio::ItemMaker>> out;
|
||||
out.emplace_back(new studio::ItemMakerT<core::TileSheet>("Tile Sheet", "TileSheets", "ng"));
|
||||
out.emplace_back(new studio::ItemMakerT<core::Palette>("Palette", "Palettes", "npal"));
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace nostalgia::core {
|
||||
class Module: public studio::Module {
|
||||
public:
|
||||
ox::Vector<studio::EditorMaker> editors(core::Context *ctx) noexcept override;
|
||||
ox::Vector<ox::UniquePtr<studio::ItemMaker>> itemMakers(core::Context*) noexcept override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -87,13 +87,16 @@ void TileSheetEditorImGui::keyStateChanged(core::Key key, bool down) {
|
||||
if (!down) {
|
||||
return;
|
||||
}
|
||||
const auto colorCnt = model()->pal().colors.size();
|
||||
if (key >= core::Key::Num_1 && key <= core::Key::Num_0 + colorCnt) {
|
||||
auto idx = ox::min<std::size_t>(static_cast<uint32_t>(key - core::Key::Num_1), colorCnt - 1);
|
||||
m_tileSheetEditor.setPalIdx(idx);
|
||||
} else if (key == core::Key::Num_0 && colorCnt >= 10) {
|
||||
auto idx = ox::min<std::size_t>(static_cast<uint32_t>(key - core::Key::Num_1 + 9), colorCnt - 1);
|
||||
m_tileSheetEditor.setPalIdx(idx);
|
||||
auto pal = model()->pal();
|
||||
if (pal) {
|
||||
const auto colorCnt = pal->colors.size();
|
||||
if (key >= core::Key::Num_1 && key <= core::Key::Num_0 + colorCnt) {
|
||||
auto idx = ox::min<std::size_t>(static_cast<uint32_t>(key - core::Key::Num_1), colorCnt - 1);
|
||||
m_tileSheetEditor.setPalIdx(idx);
|
||||
} else if (key == core::Key::Num_0 && colorCnt >= 10) {
|
||||
auto idx = ox::min<std::size_t>(static_cast<uint32_t>(key - core::Key::Num_1 + 9), colorCnt - 1);
|
||||
m_tileSheetEditor.setPalIdx(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,10 +187,10 @@ void TileSheetEditorImGui::drawSubsheetSelector(TileSheet::SubSheet *subsheet, T
|
||||
auto lbl = ox::sfmt<Str>("{}##{}", subsheet->name, pathStr);
|
||||
const auto rowSelected = *path == model()->activeSubSheetIdx();
|
||||
const auto flags = ImGuiTreeNodeFlags_SpanFullWidth
|
||||
| ImGuiTreeNodeFlags_OpenOnArrow
|
||||
| ImGuiTreeNodeFlags_DefaultOpen
|
||||
| (subsheet->subsheets.size() ? 0 : ImGuiTreeNodeFlags_Leaf)
|
||||
| (rowSelected ? ImGuiTreeNodeFlags_Selected : 0);
|
||||
| ImGuiTreeNodeFlags_OpenOnArrow
|
||||
| ImGuiTreeNodeFlags_DefaultOpen
|
||||
| (subsheet->subsheets.size() ? 0 : ImGuiTreeNodeFlags_Leaf)
|
||||
| (rowSelected ? ImGuiTreeNodeFlags_Selected : 0);
|
||||
ImGui::TableNextColumn();
|
||||
const auto open = ImGui::TreeNodeEx(lbl.c_str(), flags);
|
||||
Str newName = subsheet->name.c_str();
|
||||
@@ -255,7 +258,7 @@ void TileSheetEditorImGui::exportSubhseetToPng() noexcept {
|
||||
const auto &img = model()->img();
|
||||
const auto &s = *model()->activeSubSheet();
|
||||
const auto &pal = model()->pal();
|
||||
err = toPngFile(path, s, pal, img.bpp);
|
||||
err = toPngFile(path, s, *pal, img.bpp);
|
||||
if (err) {
|
||||
oxErrorf("Tilesheet export failed: {}", toStr(err));
|
||||
}
|
||||
@@ -353,24 +356,26 @@ void TileSheetEditorImGui::drawPaletteSelector() noexcept {
|
||||
ImGui::TableSetupColumn("", 0, 0.22);
|
||||
ImGui::TableSetupColumn("Color16", 0, 3);
|
||||
ImGui::TableHeadersRow();
|
||||
for (auto i = 0u; auto c: m_tileSheetEditor.pal().colors) {
|
||||
ImGui::PushID(static_cast<int>(i));
|
||||
// Column: color idx
|
||||
ImGui::TableNextColumn();
|
||||
const auto label = ox::BString<8>() + (i + 1);
|
||||
const auto rowSelected = i == m_tileSheetEditor.palIdx();
|
||||
if (ImGui::Selectable(label.c_str(), rowSelected, ImGuiSelectableFlags_SpanAllColumns)) {
|
||||
m_tileSheetEditor.setPalIdx(i);
|
||||
if (auto pal = m_tileSheetEditor.pal()) {
|
||||
for (auto i = 0u; auto c: pal->colors) {
|
||||
ImGui::PushID(static_cast<int>(i));
|
||||
// Column: color idx
|
||||
ImGui::TableNextColumn();
|
||||
const auto label = ox::BString<8>() + (i + 1);
|
||||
const auto rowSelected = i == m_tileSheetEditor.palIdx();
|
||||
if (ImGui::Selectable(label.c_str(), rowSelected, ImGuiSelectableFlags_SpanAllColumns)) {
|
||||
m_tileSheetEditor.setPalIdx(i);
|
||||
}
|
||||
// Column: color RGB
|
||||
ImGui::TableNextColumn();
|
||||
auto ic = ImGui::GetColorU32(ImVec4(redf(c), greenf(c), bluef(c), 1));
|
||||
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ic);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("(%02d, %02d, %02d)", red16(c), green16(c), blue16(c));
|
||||
ImGui::TableNextRow();
|
||||
ImGui::PopID();
|
||||
++i;
|
||||
}
|
||||
// Column: color RGB
|
||||
ImGui::TableNextColumn();
|
||||
auto ic = ImGui::GetColorU32(ImVec4(redf(c), greenf(c), bluef(c), 1));
|
||||
ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ic);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("(%02d, %02d, %02d)", red16(c), green16(c), blue16(c));
|
||||
ImGui::TableNextRow();
|
||||
ImGui::PopID();
|
||||
++i;
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
const Palette TileSheetEditorModel::s_defaultPalette = {
|
||||
.colors = ox::Vector<Color16>(128),
|
||||
};
|
||||
|
||||
class TileSheetClipboard: public ClipboardObject<TileSheetClipboard> {
|
||||
public:
|
||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetClipboard";
|
||||
@@ -252,12 +256,12 @@ class AddSubSheetCommand: public TileSheetCommand {
|
||||
auto &parent = m_img->getSubSheet(m_parentIdx);
|
||||
if (m_addedSheets.size() < 2) {
|
||||
auto i = parent.subsheets.size();
|
||||
parent.subsheets.emplace_back(ox::sfmt("Subsheet {}", i).c_str(), 1, 1);
|
||||
parent.subsheets.emplace_back(ox::sfmt("Subsheet {}", i).c_str(), 1, 1, m_img->bpp);
|
||||
} else {
|
||||
parent.subsheets.emplace_back("Subsheet 0", parent.columns, parent.rows, std::move(parent.pixels));
|
||||
parent.rows = 0;
|
||||
parent.columns = 0;
|
||||
parent.subsheets.emplace_back("Subsheet 1", 1, 1);
|
||||
parent.subsheets.emplace_back("Subsheet 1", 1, 1, m_img->bpp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,12 +535,14 @@ class PaletteChangeCommand: public TileSheetCommand {
|
||||
};
|
||||
|
||||
|
||||
TileSheetEditorModel::TileSheetEditorModel(Context *ctx, const ox::String &path) {
|
||||
TileSheetEditorModel::TileSheetEditorModel(Context *ctx, ox::String path) {
|
||||
m_ctx = ctx;
|
||||
m_path = path;
|
||||
oxRequireT(img, readObj<TileSheet>(ctx, path.c_str()));
|
||||
m_path = std::move(path);
|
||||
oxRequireT(img, readObj<TileSheet>(ctx, m_path.c_str()));
|
||||
m_img = *img;
|
||||
oxThrowError(readObj<Palette>(ctx, m_img.defaultPalette).moveTo(&m_pal));
|
||||
if (m_img.defaultPalette) {
|
||||
oxThrowError(readObj<Palette>(ctx, m_img.defaultPalette).moveTo(&m_pal));
|
||||
}
|
||||
m_pal.updated.connect(this, &TileSheetEditorModel::markUpdated);
|
||||
m_undoStack.changeTriggered.connect(this, &TileSheetEditorModel::markUpdatedCmdId);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ class TileSheetEditorModel: public ox::SignalHandler {
|
||||
ox::Signal<ox::Error(const TileSheet::SubSheetIdx&)> activeSubsheetChanged;
|
||||
|
||||
private:
|
||||
static const Palette s_defaultPalette;
|
||||
TileSheet m_img;
|
||||
TileSheet::SubSheetIdx m_activeSubsSheetIdx;
|
||||
AssetRef<Palette> m_pal;
|
||||
@@ -33,7 +34,7 @@ class TileSheetEditorModel: public ox::SignalHandler {
|
||||
geo::Bounds m_selectionBounds = {{-1, -1}, {-1, -1}};
|
||||
|
||||
public:
|
||||
TileSheetEditorModel(Context *ctx, const ox::String &path);
|
||||
TileSheetEditorModel(Context *ctx, ox::String path);
|
||||
|
||||
~TileSheetEditorModel() override = default;
|
||||
|
||||
@@ -50,7 +51,7 @@ class TileSheetEditorModel: public ox::SignalHandler {
|
||||
constexpr TileSheet &img() noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const Palette &pal() const noexcept;
|
||||
constexpr const Palette *pal() const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
const ox::FileAddress &palPath() const noexcept;
|
||||
@@ -142,8 +143,11 @@ constexpr TileSheet &TileSheetEditorModel::img() noexcept {
|
||||
return m_img;
|
||||
}
|
||||
|
||||
constexpr const Palette &TileSheetEditorModel::pal() const noexcept {
|
||||
return *m_pal;
|
||||
constexpr const Palette *TileSheetEditorModel::pal() const noexcept {
|
||||
if (m_pal) {
|
||||
return m_pal.get();
|
||||
}
|
||||
return &s_defaultPalette;
|
||||
}
|
||||
|
||||
constexpr studio::UndoStack *TileSheetEditorModel::undoStack() noexcept {
|
||||
|
||||
@@ -80,7 +80,7 @@ class TileSheetEditorView: public ox::SignalHandler {
|
||||
constexpr TileSheet &img() noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const Palette &pal() const noexcept;
|
||||
constexpr const Palette *pal() const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto *model() noexcept {
|
||||
@@ -125,7 +125,7 @@ constexpr TileSheet &TileSheetEditorView::img() noexcept {
|
||||
return m_model.img();
|
||||
}
|
||||
|
||||
constexpr const Palette &TileSheetEditorView::pal() const noexcept {
|
||||
constexpr const Palette *TileSheetEditorView::pal() const noexcept {
|
||||
return m_model.pal();
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ void TileSheetPixels::setPixelBufferObject(const geo::Vec2 &paneSize, unsigned v
|
||||
void TileSheetPixels::setBufferObjects(const geo::Vec2 &paneSize) noexcept {
|
||||
// set buffer lengths
|
||||
const auto subSheet = m_model->activeSubSheet();
|
||||
const auto &pal = m_model->pal();
|
||||
const auto pal = m_model->pal();
|
||||
const auto width = subSheet->columns * TileWidth;
|
||||
const auto height = subSheet->rows * TileHeight;
|
||||
const auto pixels = static_cast<unsigned>(width * height);
|
||||
@@ -93,12 +93,18 @@ void TileSheetPixels::setBufferObjects(const geo::Vec2 &paneSize) noexcept {
|
||||
m_bufferSet.elements.resize(pixels * VertexEboLength);
|
||||
// set pixels
|
||||
subSheet->walkPixels(m_model->img().bpp, [&](std::size_t i, uint8_t p) {
|
||||
auto color = pal.colors[p];
|
||||
auto color = pal->colors[p];
|
||||
const auto pt = idxToPt(static_cast<int>(i), subSheet->columns);
|
||||
const auto fx = static_cast<float>(pt.x);
|
||||
const auto fy = static_cast<float>(pt.y);
|
||||
const auto vbo = &m_bufferSet.vertices[i * VertexVboLength];
|
||||
const auto ebo = &m_bufferSet.elements[i * VertexEboLength];
|
||||
if (i * VertexVboLength + VertexVboLength > m_bufferSet.vertices.size()) {
|
||||
return;
|
||||
}
|
||||
if (i * VertexEboLength + VertexEboLength > m_bufferSet.elements.size()) {
|
||||
return;
|
||||
}
|
||||
if (m_model->pixelSelected(i)) {
|
||||
const auto r = red16(color) / 2;
|
||||
const auto g = (green16(color) + 20) / 2;
|
||||
|
||||
Reference in New Issue
Block a user