Compare commits

...

30 Commits

Author SHA1 Message Date
9105b1ece6 [ox/std] Fix Linux build
All checks were successful
Build / build (push) Successful in 2m29s
2024-05-23 01:38:57 -05:00
fbeb08156a [ox/model] Fix type params in buildTypeId 2024-05-23 01:32:41 -05:00
b882a47e58 [ox/std] Fix resize to set null terminator 2024-05-23 01:27:59 -05:00
660f2f5633 [ox/std] Rework FileReader into StreamReader 2024-05-23 00:45:28 -05:00
aa83c2a62b [nostalgia/core/studio] Remove some unnecessary copying 2024-05-22 23:19:01 -05:00
4a2b1fd743 [studio,keel] Make fileChanged emit UUID as well as path, add uuidUrlToUuid 2024-05-22 23:17:28 -05:00
08f958fbac [ox/std] Add IntegerRange_c 2024-05-22 23:14:06 -05:00
a651d45a2f [ox/std] Fix Vector insert functions 2024-05-22 23:13:52 -05:00
9e9f317c13 [studio] Make UndoCommand::mergeWith take a reference 2024-05-22 02:11:58 -05:00
f5a02ce94f [nostalgia/core/gba] Fix build 2024-05-22 00:41:07 -05:00
6971c3109a [studio] Add NoChangeException 2024-05-22 00:35:20 -05:00
c47f48eba7 [keel] Add/cleanup UUID/path lookup functions 2024-05-22 00:32:49 -05:00
76771e7bdd [nostalgia/core] Add tileColumns and tileRows functions 2024-05-22 00:31:10 -05:00
f6a0ae2027 [ox/std] Fix some Windows warnings 2024-05-22 00:26:56 -05:00
752c8c1db3 [glutils] Fix type conversion that happened on Windows 2024-05-22 00:26:03 -05:00
af3bff1a3f [glutils] Add FrameBuffer::sizef 2024-05-22 00:25:03 -05:00
87416e13ee [ox/std] Make MallocaPtr call destructor 2024-05-20 02:46:19 -05:00
047b43968e [ox/std] Make Point and Size members int32_t 2024-05-20 02:06:27 -05:00
40b8da4d3c [studio/modlib] Cleanup 2024-05-19 22:15:54 -05:00
123c41254f [ox/std] Add SmallMap::pairs(), SmallMap model 2024-05-19 22:15:13 -05:00
963ec5d3f7 [ox/std] Add operator-> to SpanIterator 2024-05-19 22:14:28 -05:00
6df77a23ab [glutils] Add size function to FrameBuffer 2024-05-19 22:13:57 -05:00
df412cf8d0 [ox/std] Add missing typenames 2024-05-18 13:01:06 -05:00
ae30ef3609 Merge commit 'b66cef7127e97269fc6072a6f66ccc08990f6d2e' 2024-05-18 12:17:23 -05:00
095a1135e7 Merge commit 'f48824793cfce315971fe2e699ece198c7a79407' 2024-05-11 02:09:10 -05:00
ce1836ab10 Merge commit '1e041bd2ebfe5ace7bed3906faf60345aa98a8bc' 2024-05-10 02:21:42 -05:00
7d1641faee Merge commit '420fa96463f59c4a4a7cd66b16b0ad01ab0d55e6' 2024-05-08 23:55:07 -05:00
423212b2ad [studio] Add missing include 2024-05-06 22:27:20 -05:00
60da1063d1 Merge commit 'bd416f82e25f1b710ab2b7890274571dd3fcd53d' 2024-05-03 23:42:00 -05:00
60d1996f0a [keel] Minor optimization 2024-05-03 23:00:38 -05:00
31 changed files with 190 additions and 101 deletions

View File

@ -13,6 +13,7 @@
#include <ox/std/error.hpp>
#include <ox/std/size.hpp>
#include <ox/std/string.hpp>
#include <ox/std/vec.hpp>
#include <ox/std/vector.hpp>
namespace glutils {
@ -137,6 +138,22 @@ struct FrameBuffer {
constexpr operator const GLuint&() const noexcept {
return fbo.id;
}
[[nodiscard]]
constexpr ox::Vec2 sizef() const noexcept {
return {
static_cast<float>(width),
static_cast<float>(height),
};
}
[[nodiscard]]
constexpr ox::Size size() const noexcept {
return {
width,
height,
};
}
};
class FrameBufferBind {

View File

@ -102,7 +102,7 @@ void setupShaderParams(
ox::Vector<ShaderVarSet> const&vars,
GLsizei vertexRowLen) noexcept {
// setup vars
for (auto lenWritten = 0LU; auto const&v : vars) {
for (size_t lenWritten = 0; auto const&v : vars) {
auto const attr = static_cast<GLuint>(glGetAttribLocation(shader, v.name.c_str()));
glEnableVertexAttribArray(attr);
glVertexAttribPointer(

View File

@ -34,7 +34,8 @@ constexpr auto buildTypeId() noexcept {
return ox::sfmt("{};{}", name, version);
}
static constexpr auto buildTypeId(CRStringView name, int version,
static constexpr auto buildTypeId(
CRStringView name, int version,
const TypeParamPack &typeParams = {}) noexcept {
String tp;
if (!typeParams.empty()) {
@ -42,7 +43,7 @@ static constexpr auto buildTypeId(CRStringView name, int version,
for (const auto &p : typeParams) {
tp += p + ",";
}
tp.resize(tp.len() - 1);
tp.resize(tp.len());
tp += "#";
}
return ox::sfmt("{}{};{}", name, tp, version);

View File

@ -8,6 +8,7 @@
#pragma once
#include "bit.hpp"
#include "typetraits.hpp"
namespace ox {
@ -29,4 +30,6 @@ concept OxString_c = isOxString_v<T>;
template<typename T>
concept Integral_c = ox::is_integral_v<T>;
template<typename T, size_t max>
concept IntegerRange_c = ox::is_integer_v<T> && ox::MaxValue<T> >= max;
}

View File

@ -128,6 +128,10 @@ struct SpanIterator {
return operator-=(1);
}
constexpr PtrType operator->() const noexcept {
return &m_t[m_offset];
}
constexpr RefType operator*() const noexcept {
return m_t[m_offset];
}

View File

@ -102,6 +102,7 @@ class MallocaPtr {
}
constexpr ~MallocaPtr() noexcept {
m_val->~T();
if (m_onHeap && m_val) {
delete[] reinterpret_cast<uint8_t*>(m_val);
}

View File

@ -17,8 +17,8 @@ class Point {
public:
static constexpr auto TypeName = "net.drinkingtea.ox.Point";
static constexpr auto TypeVersion = 1;
int x = 0;
int y = 0;
int32_t x = 0;
int32_t y = 0;
constexpr Point() noexcept = default;

View File

@ -8,7 +8,7 @@
#ifdef OX_USE_STDLIB
#include <cstdio>
#include <istream>
#include "array.hpp"
#include "reader.hpp"
@ -16,41 +16,56 @@
namespace ox {
[[nodiscard]]
constexpr int sdMap(ox::ios_base::seekdir in) noexcept {
constexpr std::ios_base::seekdir sdMap(ox::ios_base::seekdir in) noexcept {
switch (in) {
case ox::ios_base::beg:
return SEEK_SET;
return std::ios_base::beg;
case ox::ios_base::end:
return SEEK_END;
return std::ios_base::end;
case ox::ios_base::cur:
return SEEK_CUR;
return std::ios_base::cur;
}
return -1;
return std::ios_base::beg;
}
ox::Result<char> FileReader::peek() const noexcept {
auto const c = fgetc(m_file);
ox::Result<char> StreamReader::peek() const noexcept {
try {
char c{};
m_strm.get(c);
auto const ok = c != EOF;
if (ok && ungetc(c, m_file)) [[unlikely]] {
if (ok && m_strm.unget()) [[unlikely]] {
return OxError(1, "Unable to unget character");
}
return {static_cast<char>(c), OxError(!ok, "File peek failed")};
} catch (std::exception const&) {
return OxError(1, "peek failed");
}
}
ox::Result<std::size_t> FileReader::read(char *v, std::size_t cnt) noexcept {
return fread(v, 1, cnt, m_file);
ox::Result<std::size_t> StreamReader::read(char *v, std::size_t cnt) noexcept {
return static_cast<size_t>(m_strm.read(v, static_cast<std::streamsize>(cnt)).gcount());
}
ox::Error FileReader::seekg(std::size_t p) noexcept {
return OxError(fseek(m_file, static_cast<int64_t>(p), SEEK_CUR) != 0);
ox::Error StreamReader::seekg(std::size_t p) noexcept {
try {
m_strm.seekg(static_cast<long long int>(p), std::ios_base::cur);
} catch (std::exception const&) {
return OxError(1, "seekg failed");
}
return {};
}
ox::Error FileReader::seekg(int64_t p, ios_base::seekdir sd) noexcept {
return OxError(fseek(m_file, p, sdMap(sd)) != 0);
ox::Error StreamReader::seekg(int64_t p, ios_base::seekdir sd) noexcept {
try {
m_strm.seekg(p, sdMap(sd));
} catch (std::exception const&) {
return OxError(1, "seekg failed");
}
return {};
}
ox::Result<std::size_t> FileReader::tellg() noexcept {
const auto sz = ftell(m_file);
ox::Result<std::size_t> StreamReader::tellg() noexcept {
const auto sz = m_strm.tellg();
return {static_cast<std::size_t>(sz), OxError(sz == -1)};
}

View File

@ -9,7 +9,7 @@
#pragma once
#ifdef OX_USE_STDLIB
#include <cstdio>
#include <istream>
#endif
#include "concepts.hpp"
@ -65,11 +65,11 @@ class ReaderT: public Reader_v {
};
#ifdef OX_USE_STDLIB
class FileReader: public Reader_v {
class StreamReader: public Reader_v {
private:
FILE *m_file = nullptr;
std::istream &m_strm;
public:
constexpr explicit FileReader(FILE *file) noexcept: m_file(file) {}
constexpr explicit StreamReader(std::istream &stream) noexcept: m_strm(stream) {}
ox::Result<char> peek() const noexcept override;
ox::Result<std::size_t> read(char *v, std::size_t cnt) noexcept override;
ox::Error seekg(std::size_t p) noexcept override;

View File

@ -17,8 +17,8 @@ class Size {
public:
static constexpr auto TypeName = "net.drinkingtea.ox.Size";
static constexpr auto TypeVersion = 1;
int width = 0;
int height = 0;
int32_t width = 0;
int32_t height = 0;
constexpr Size() noexcept = default;

View File

@ -8,7 +8,7 @@
#pragma once
#include "algorithm.hpp"
#include "def.hpp"
#include "hash.hpp"
#include "ignore.hpp"
#include "stringview.hpp"
@ -28,7 +28,7 @@ class SmallMap {
T value{};
};
private:
protected:
using PairVector = Vector<Pair, SmallSz>;
PairVector m_pairs;
@ -79,6 +79,11 @@ class SmallMap {
[[nodiscard]]
constexpr Pair &get(size_t i) noexcept;
[[nodiscard]]
constexpr ox::SpanView<Pair> pairs() const noexcept {
return m_pairs;
}
constexpr void clear();
private:
@ -204,12 +209,12 @@ constexpr T &SmallMap<K, T, SmallSz>::value(size_t i) noexcept {
}
template<typename K, typename T, size_t SmallSz>
constexpr SmallMap<K, T, SmallSz>::Pair const&SmallMap<K, T, SmallSz>::get(size_t i) const noexcept {
constexpr typename SmallMap<K, T, SmallSz>::Pair const&SmallMap<K, T, SmallSz>::get(size_t i) const noexcept {
return m_pairs[i];
}
template<typename K, typename T, size_t SmallSz>
constexpr SmallMap<K, T, SmallSz>::Pair &SmallMap<K, T, SmallSz>::get(size_t i) noexcept {
constexpr typename SmallMap<K, T, SmallSz>::Pair &SmallMap<K, T, SmallSz>::get(size_t i) noexcept {
return m_pairs[i];
}
@ -246,4 +251,12 @@ constexpr typename SmallMap<K, T, SmallSz>::Pair &SmallMap<K, T, SmallSz>::acces
return pairs.emplace_back();
}
template<typename T, typename K, typename V, size_t SmallSz>
constexpr Error model(T *io, ox::CommonPtrWith<SmallMap<K, V, SmallSz>> auto *obj) noexcept {
using Map = SmallMap<K, V, SmallSz>;
oxReturnError(io->template setTypeInfo<Map>());
oxReturnError(io->field("pairs", &obj->m_pairs));
return {};
}
}

View File

@ -26,7 +26,7 @@
namespace ox {
#if defined(OX_USE_STDLIB) && __has_include(<unistd.h>)
[[nodiscard]]
[[nodiscard]] [[maybe_unused]]
static auto symbolicate([[maybe_unused]]void **frames,
[[maybe_unused]]std::size_t frameCnt,
[[maybe_unused]]const char *linePrefix) {

View File

@ -194,6 +194,7 @@ class BasicString {
constexpr void resize(size_t sz) noexcept {
m_buff.resize(sz);
m_buff[sz - 1] = 0;
}
[[nodiscard]]

View File

@ -271,7 +271,7 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
constexpr bool contains(MaybeView_t<T> const&) const noexcept;
constexpr iterator<T&, T*, false> insert(
std::size_t pos, std::size_t cnt, T val) noexcept(useNoexcept);
std::size_t pos, std::size_t cnt, T const&val) noexcept(useNoexcept);
constexpr iterator<T&, T*, false> insert(std::size_t pos, T val) noexcept(useNoexcept);
@ -531,29 +531,23 @@ constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(MaybeView_t<T> co
template<typename T, std::size_t SmallVectorSize, typename Allocator>
constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&, T*, false>
Vector<T, SmallVectorSize, Allocator>::insert(
std::size_t pos, std::size_t cnt, T val) noexcept(useNoexcept) {
std::size_t pos, std::size_t cnt, T const&val) noexcept(useNoexcept) {
if (m_size + cnt > m_cap) {
reserveInsert(m_cap ? m_size + cnt : initialCap, pos, cnt);
if (pos < m_size) {
m_items[pos] = std::move(val);
} else {
for (auto i = 0u; i < cnt; ++i) {
std::construct_at(&m_items[pos + i], m_items[pos]);
}
}
} else {
if (pos < m_size) {
for (auto i = m_size + cnt - 1; i > pos; --i) {
std::construct_at(&m_items[i], std::move(m_items[i - cnt]));
}
m_items[pos] = std::move(val);
for (auto i = pos; i < pos + cnt; ++i) {
m_items[i] = val;
}
} else {
for (auto i = 0u; i < cnt; ++i) {
std::construct_at(&m_items[pos + i], m_items[pos]);
}
}
}
++m_size;
m_size += cnt;
return begin() + pos;
}
@ -562,20 +556,14 @@ constexpr typename Vector<T, SmallVectorSize, Allocator>::template iterator<T&,
Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, T val) noexcept(useNoexcept) {
if (m_size == m_cap) {
reserveInsert(m_cap ? m_cap * 2 : initialCap, pos);
if (pos < m_size) {
m_items[pos] = std::move(val);
} else {
std::construct_at(&m_items[pos], m_items[pos]);
}
} else {
if (pos < m_size) {
for (auto i = m_size; i > pos; --i) {
std::construct_at(&m_items[i], std::move(m_items[i - 1]));
}
m_items[pos] = std::move(val);
} else {
std::construct_at(&m_items[pos], m_items[pos]);
}
std::construct_at(&m_items[pos], std::move(val));
}
++m_size;
return begin() + pos;

View File

@ -103,6 +103,12 @@ oxModelEnd()
void addEntry(TileSheetSet &set, ox::FileAddress path, int32_t begin = 0, int32_t size = -1) noexcept;
[[nodiscard]]
int tileColumns(Context&) noexcept;
[[nodiscard]]
int tileRows(Context&) noexcept;
ox::Error loadBgPalette(
Context &ctx,
size_t palBank,

View File

@ -22,8 +22,6 @@
namespace nostalgia::core {
constexpr auto GbaTileColumns = 32;
constexpr auto GbaTileRows = 32;
constexpr auto SpriteCount = 128;
struct GbaTileMapTarget {
@ -284,8 +282,8 @@ ox::Error loadSpriteTileSheet(
return {};
}
void setBgTile(Context&, uint_t bgIdx, int column, int row, BgTile const&tile) noexcept {
auto const tileIdx = static_cast<std::size_t>(row * GbaTileColumns + column);
void setBgTile(Context &ctx, uint_t bgIdx, int column, int row, BgTile const&tile) noexcept {
auto const tileIdx = static_cast<std::size_t>(row * tileColumns(ctx) + column);
// see Tonc 9.3
MEM_BG_MAP[bgIdx][tileIdx] =
static_cast<uint16_t>(tile.tileIdx & 0b1'1111'1111) |
@ -294,8 +292,8 @@ void setBgTile(Context&, uint_t bgIdx, int column, int row, BgTile const&tile) n
static_cast<uint16_t>(tile.palBank << 0xc);
}
void clearBg(Context&, uint_t bgIdx) noexcept {
memset(MEM_BG_MAP[bgIdx].data(), 0, GbaTileRows * GbaTileColumns);
void clearBg(Context &ctx, uint_t bgIdx) noexcept {
memset(MEM_BG_MAP[bgIdx].data(), 0, static_cast<size_t>(tileRows(ctx) * tileColumns(ctx)));
}
uint8_t bgStatus(Context&) noexcept {

View File

@ -6,6 +6,17 @@
namespace nostalgia::core {
constexpr auto GbaTileColumns = 32;
constexpr auto GbaTileRows = 32;
int tileColumns(Context&) noexcept {
return GbaTileColumns;
}
int tileRows(Context&) noexcept {
return GbaTileRows;
}
// map ASCII values to the nostalgia charset
constexpr ox::Array<char, 128> charMap = {
0,

View File

@ -124,11 +124,11 @@ UpdateColorCommand::UpdateColorCommand(
//setObsolete(m_oldColor == m_newColor);
}
bool UpdateColorCommand::mergeWith(const UndoCommand *cmd) noexcept {
if (cmd->commandId() != static_cast<int>(PaletteEditorCommandId::UpdateColor)) {
bool UpdateColorCommand::mergeWith(UndoCommand const&cmd) noexcept {
if (cmd.commandId() != static_cast<int>(PaletteEditorCommandId::UpdateColor)) {
return false;
}
auto ucCmd = static_cast<const UpdateColorCommand*>(cmd);
auto ucCmd = static_cast<UpdateColorCommand const*>(&cmd);
if (m_idx != ucCmd->m_idx) {
return false;
}

View File

@ -140,7 +140,7 @@ class UpdateColorCommand: public studio::UndoCommand {
~UpdateColorCommand() noexcept override = default;
[[nodiscard]]
bool mergeWith(const UndoCommand *cmd) noexcept final;
bool mergeWith(const UndoCommand &cmd) noexcept final;
[[nodiscard]]
int commandId() const noexcept final;

View File

@ -11,19 +11,18 @@ core::RmSubSheetCommand::RmSubSheetCommand(TileSheet &img, TileSheet::SubSheetId
m_idx(std::move(idx)),
m_parentIdx(m_idx) {
m_parentIdx.pop_back();
auto &parent = getSubSheet(m_img, m_parentIdx);
m_sheet = parent.subsheets[*m_idx.back().value];
}
void RmSubSheetCommand::redo() noexcept {
auto &parent = getSubSheet(m_img, m_parentIdx);
m_sheet = std::move(parent.subsheets[*m_idx.back().value]);
oxLogError(parent.subsheets.erase(*m_idx.back().value).error);
}
void RmSubSheetCommand::undo() noexcept {
auto &parent = getSubSheet(m_img, m_parentIdx);
auto i = *m_idx.back().value;
parent.subsheets.insert(i, m_sheet);
auto const i = *m_idx.back().value;
parent.subsheets.insert(i, std::move(m_sheet));
}
int RmSubSheetCommand::commandId() const noexcept {

View File

@ -93,9 +93,17 @@ void createUuidMapping(Context &ctx, ox::StringView filePath, ox::UUID const&uui
ox::Error buildUuidMap(Context &ctx) noexcept;
ox::Result<ox::String> uuidToPath(Context &ctx, ox::CRStringView uuid) noexcept;
ox::Result<ox::UUID> pathToUuid(Context &ctx, ox::CRStringView path) noexcept;
ox::Result<ox::String> uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept;
constexpr ox::Result<ox::UUID> uuidUrlToUuid(ox::StringView uuidUrl) noexcept {
return ox::UUID::fromString(substr(uuidUrl, 7));
}
ox::Result<ox::CStringView> uuidUrlToPath(Context &ctx, ox::StringView uuid) noexcept;
ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::CRStringView uuid) noexcept;
ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept;
ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept;

View File

@ -83,19 +83,29 @@ ox::Result<ox::UUID> pathToUuid(Context &ctx, ox::CRStringView path) noexcept {
#endif
}
ox::Result<ox::String> uuidToPath(Context &ctx, ox::CRStringView uuid) noexcept {
ox::Result<ox::CStringView> uuidUrlToPath(Context &ctx, ox::StringView uuid) noexcept {
uuid = substr(uuid, 7);
#ifndef OX_BARE_METAL
oxRequire(out, ctx.uuidToPath.at(uuid));
return *out;
oxRequireM(out, ctx.uuidToPath.at(uuid));
return ox::CStringView(*out);
#else
return OxError(1, "UUID to path conversion not supported on this platform");
#endif
}
ox::Result<ox::String> uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept {
ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::CRStringView uuid) noexcept {
#ifndef OX_BARE_METAL
oxRequire(out, ctx.uuidToPath.at(uuid.toString()));
return *out;
oxRequireM(out, ctx.uuidToPath.at(uuid));
return ox::CStringView(*out);
#else
return OxError(1, "UUID to path conversion not supported on this platform");
#endif
}
ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept {
#ifndef OX_BARE_METAL
oxRequireM(out, ctx.uuidToPath.at(uuid.toString()));
return ox::CStringView(*out);
#else
return OxError(1, "UUID to path conversion not supported on this platform");
#endif

View File

@ -30,7 +30,7 @@ static ox::Error pathToInode(
}
if (beginsWith(path, "uuid://")) {
auto const uuid = ox::substr(path, 7);
oxReturnError(keel::uuidToPath(ctx, uuid).moveTo(path));
oxReturnError(keel::uuidToPath(ctx, uuid).to<ox::String>().moveTo(path));
}
oxRequire(s, dest.stat(path));
oxReturnError(o.at("type").unwrap()->set(static_cast<int8_t>(ox::FileAddressType::Inode)));

View File

@ -2,6 +2,7 @@
* Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#include <algorithm>
#include <filesystem>
#include <imgui.h>

View File

@ -134,11 +134,13 @@ class Editor: public studio::BaseEditor {
void pushCommand(ox::UPtr<UndoCommand> &&cmd) noexcept;
template<typename UC, typename ...Args>
void pushCommand(Args&&... args) noexcept {
bool pushCommand(Args&&... args) noexcept {
try {
m_undoStack.push(ox::make_unique<UC>(ox::forward<Args>(args)...));
return true;
} catch (ox::Exception const&ex) {
oxLogError(ex.toError());
return false;
}
}

View File

@ -115,7 +115,7 @@ class Project {
// file.
ox::Signal<ox::Error(ox::CRStringView)> fileRecognized;
ox::Signal<ox::Error(ox::CRStringView)> fileDeleted;
ox::Signal<ox::Error(ox::CRStringView)> fileUpdated;
ox::Signal<ox::Error(ox::StringView, ox::UUID)> fileUpdated;
};
@ -135,7 +135,8 @@ ox::Error Project::writeObj(ox::CRStringView path, T const&obj, ox::ClawFormat f
oxReturnError(writeTypeStore());
}
oxReturnError(keel::setAsset(m_ctx, path, obj));
fileUpdated.emit(path);
oxRequire(uuid, pathToUuid(m_ctx, path));
fileUpdated.emit(path, uuid);
return {};
}

View File

@ -4,8 +4,18 @@
#pragma once
#include <source_location>
#include <ox/std/error.hpp>
namespace studio {
class NoChangesException: public ox::Exception {
public:
inline NoChangesException(std::source_location sloc = std::source_location::current()):
ox::Exception(sloc.file_name(), sloc.line(), 1, "Command makes no changes.") {}
};
class UndoCommand {
public:
virtual ~UndoCommand() noexcept = default;
@ -13,7 +23,7 @@ class UndoCommand {
virtual void undo() noexcept = 0;
[[nodiscard]]
virtual int commandId() const noexcept = 0;
virtual bool mergeWith(UndoCommand const*cmd) noexcept;
virtual bool mergeWith(UndoCommand const&cmd) noexcept;
};
}

View File

@ -57,7 +57,7 @@ ox::FileSystem &Project::romFs() noexcept {
ox::Error Project::mkdir(ox::CRStringView path) const noexcept {
oxReturnError(m_fs.mkdir(path, true));
fileUpdated.emit(path);
fileUpdated.emit(path, {});
return {};
}
@ -115,9 +115,9 @@ ox::Error Project::writeBuff(ox::CRStringView path, ox::Buffer const&buff) noexc
ox::Buffer outBuff;
outBuff.reserve(buff.size() + HdrSz);
ox::BufferWriter writer(&outBuff);
auto const [uuid, err] = m_ctx.pathToUuid.at(path);
auto const [uuid, err] = pathToUuid(m_ctx, path);
if (!err) {
oxReturnError(keel::writeUuidHeader(writer, *uuid));
oxReturnError(keel::writeUuidHeader(writer, uuid));
}
oxReturnError(writer.write(buff.data(), buff.size()));
auto const newFile = m_fs.stat(path).error != 0;
@ -126,7 +126,7 @@ ox::Error Project::writeBuff(ox::CRStringView path, ox::Buffer const&buff) noexc
fileAdded.emit(path);
indexFile(path);
} else {
fileUpdated.emit(path);
fileUpdated.emit(path, uuid);
}
return {};
}

View File

@ -3,7 +3,7 @@
namespace studio {
bool UndoCommand::mergeWith(UndoCommand const*) noexcept {
bool UndoCommand::mergeWith(UndoCommand const&) noexcept {
return false;
}

View File

@ -13,7 +13,7 @@ void UndoStack::push(ox::UPtr<UndoCommand> &&cmd) noexcept {
cmd->redo();
redoTriggered.emit(cmd.get());
changeTriggered.emit(cmd.get());
if (m_stack.empty() || !(*m_stack.back().value)->mergeWith(cmd.get())) {
if (m_stack.empty() || !(*m_stack.back().value)->mergeWith(*cmd)) {
m_stack.emplace_back(std::move(cmd));
++m_stackIdx;
}