Compare commits
21 Commits
791b7746f3
...
release-d2
Author | SHA1 | Date | |
---|---|---|---|
1b32bdfcad | |||
3544392fa8 | |||
144d234d09 | |||
465fb06f76 | |||
db953dd0d1 | |||
daab4dc4f5 | |||
83cbac5cca | |||
74e518fee0 | |||
6b0ce40c02 | |||
4f55964dd9 | |||
cb597cf92e | |||
6906c66ba7 | |||
ba00d10dfc | |||
cdfbfe48b7 | |||
21ae2a14e9 | |||
81b120b1ce | |||
40938958de | |||
df190c05a0 | |||
3fe3b08eca | |||
ecc5ae6b2f | |||
a863bfc181 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -6,7 +6,7 @@
|
||||
.mypy_cache
|
||||
.stfolder
|
||||
.stignore
|
||||
util/scripts/__pycache__
|
||||
scripts/__pycache__
|
||||
pyenv
|
||||
CMakeLists.txt.user
|
||||
ROM.oxfs
|
||||
|
@ -1,4 +1,4 @@
|
||||
FROM fedora:41
|
||||
FROM fedora:36
|
||||
|
||||
RUN dnf update -y
|
||||
|
3
Makefile
3
Makefile
@ -1,6 +1,5 @@
|
||||
BC_VAR_PROJECT_NAME=nostalgia
|
||||
BC_VAR_PROJECT_NAME_CAP=Nostalgia
|
||||
BC_VAR_DEVENV_ROOT=util
|
||||
BUILDCORE_PATH=deps/buildcore
|
||||
include ${BUILDCORE_PATH}/base.mk
|
||||
|
||||
@ -14,7 +13,7 @@ endif
|
||||
|
||||
.PHONY: pkg-gba
|
||||
pkg-gba: build
|
||||
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME}
|
||||
${BC_CMD_ENVRUN} ${BC_PY3} ./scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME}
|
||||
|
||||
.PHONY: run
|
||||
run: build
|
||||
|
13
deps/glad/CMakeLists.txt
vendored
13
deps/glad/CMakeLists.txt
vendored
@ -1,11 +1,2 @@
|
||||
add_library(glad src/glad.c)
|
||||
|
||||
target_include_directories(glad PUBLIC include)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
glad
|
||||
DESTINATION
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
add_library(glad OBJECT src/glad.c)
|
||||
target_include_directories(glad PUBLIC include)
|
12
deps/imgui/CMakeLists.txt
vendored
12
deps/imgui/CMakeLists.txt
vendored
@ -6,7 +6,7 @@ endif()
|
||||
# DrinkingTea: end
|
||||
|
||||
add_library(
|
||||
imgui
|
||||
imgui OBJECT
|
||||
imgui.cpp
|
||||
imgui_demo.cpp
|
||||
imgui_draw.cpp
|
||||
@ -19,12 +19,4 @@ add_library(
|
||||
target_include_directories(
|
||||
imgui SYSTEM PUBLIC
|
||||
.
|
||||
)
|
||||
|
||||
install(
|
||||
TARGETS
|
||||
imgui
|
||||
DESTINATION
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
)
|
2
deps/ox/src/ox/event/signal.hpp
vendored
2
deps/ox/src/ox/event/signal.hpp
vendored
@ -215,7 +215,7 @@ Error Signal<Args...>::emitCheckError(Args... args) const noexcept {
|
||||
}
|
||||
return ox::Error(0);
|
||||
} catch (const ox::Exception &ex) {
|
||||
return ox::Error(ex.errCode, ex.msg, ex.src);
|
||||
return ox::Error(ex.file, ex.line, ex.errCode, ex.msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
2
deps/ox/src/ox/logconn/def.hpp
vendored
2
deps/ox/src/ox/logconn/def.hpp
vendored
@ -14,7 +14,7 @@
|
||||
{ \
|
||||
const auto loggerErr = (loggerName).initConn(appName); \
|
||||
if (loggerErr) { \
|
||||
oxErrf("Could not connect to logger: {} ({}:{})\n", toStr(loggerErr), loggerErr.src.file_name(), loggerErr.src.line()); \
|
||||
oxErrf("Could not connect to logger: {} ({}:{})\n", toStr(loggerErr), loggerErr.file, loggerErr.line); \
|
||||
} else { \
|
||||
ox::trace::setLogger(&(loggerName)); \
|
||||
} \
|
||||
|
14
deps/ox/src/ox/std/algorithm.hpp
vendored
14
deps/ox/src/ox/std/algorithm.hpp
vendored
@ -9,25 +9,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "def.hpp"
|
||||
#include "error.hpp"
|
||||
|
||||
OX_CLANG_NOWARN_BEGIN(-Wunsafe-buffer-usage)
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename It, typename T>
|
||||
constexpr ox::Result<size_t> findIdx(It begin, It end, T const&value) {
|
||||
auto it = begin;
|
||||
for (; it != end; ++it) {
|
||||
if (*it == value) {
|
||||
return it.offset();
|
||||
}
|
||||
}
|
||||
return ox::Error{1, "item not found"};
|
||||
}
|
||||
|
||||
template<typename It, typename T>
|
||||
constexpr It find(It begin, It end, T const&value) {
|
||||
constexpr It find(It begin, It end, const T &value) {
|
||||
for (; begin != end; ++begin) {
|
||||
if (*begin == value) {
|
||||
return begin;
|
||||
|
8
deps/ox/src/ox/std/assert.cpp
vendored
8
deps/ox/src/ox/std/assert.cpp
vendored
@ -20,8 +20,8 @@ void panic(StringViewCR file, int line, StringViewCR panicMsg, const Error &err)
|
||||
oxErrf("\tError Message:\t{}\n", err.msg);
|
||||
}
|
||||
oxErrf("\tError Code:\t{}\n", static_cast<ErrorCode>(err));
|
||||
if (err.src.file_name() != nullptr) {
|
||||
oxErrf("\tError Location:\t{}:{}\n", err.src.file_name(), err.src.line());
|
||||
if (err.file != nullptr) {
|
||||
oxErrf("\tError Location:\t{}:{}\n", err.file, err.line);
|
||||
}
|
||||
#ifdef OX_USE_STDLIB
|
||||
printStackTrace(2);
|
||||
@ -56,8 +56,8 @@ void assertFailFuncRuntime(StringViewCR file, int line, [[maybe_unused]] const E
|
||||
msg += sfmt("\tError Message:\t{}\n", err.msg);
|
||||
}
|
||||
msg += sfmt("\tError Code:\t{}\n", static_cast<ErrorCode>(err));
|
||||
if (err.src.file_name() != nullptr) {
|
||||
msg += sfmt("\tError Location:\t{}:{}\n", err.src.file_name(), err.src.line());
|
||||
if (err.file != nullptr) {
|
||||
msg += sfmt("\tError Location:\t{}:{}\n", err.file, err.line);
|
||||
}
|
||||
msg += genStackTrace(2);
|
||||
oxErr(msg);
|
||||
|
40
deps/ox/src/ox/std/error.hpp
vendored
40
deps/ox/src/ox/std/error.hpp
vendored
@ -36,16 +36,28 @@ using ErrorCode = uint16_t;
|
||||
|
||||
|
||||
struct [[nodiscard]] Error {
|
||||
std::source_location src;
|
||||
ox::CString msg = nullptr;
|
||||
ox::CString file = nullptr;
|
||||
uint16_t line = 0;
|
||||
ErrorCode errCode = 0;
|
||||
|
||||
constexpr Error() noexcept = default;
|
||||
|
||||
explicit constexpr Error(
|
||||
ox::CString file,
|
||||
uint32_t const line,
|
||||
ErrorCode const errCode,
|
||||
ox::CString msg = nullptr) noexcept:
|
||||
msg{msg},
|
||||
file{file},
|
||||
line{static_cast<uint16_t>(line)},
|
||||
errCode{errCode} {}
|
||||
|
||||
explicit constexpr Error(
|
||||
ErrorCode const errCode,
|
||||
std::source_location const&src = std::source_location::current()) noexcept:
|
||||
src{src},
|
||||
file{src.file_name()},
|
||||
line{static_cast<uint16_t>(src.line())},
|
||||
errCode{errCode}
|
||||
{}
|
||||
|
||||
@ -53,8 +65,9 @@ struct [[nodiscard]] Error {
|
||||
ErrorCode const errCode,
|
||||
ox::CString msg,
|
||||
std::source_location const&src = std::source_location::current()) noexcept:
|
||||
src{src},
|
||||
msg{msg},
|
||||
file{src.file_name()},
|
||||
line{static_cast<uint16_t>(src.line())},
|
||||
errCode{errCode}
|
||||
{}
|
||||
|
||||
@ -76,31 +89,42 @@ constexpr auto toStr(Error const&err) noexcept {
|
||||
}
|
||||
|
||||
struct Exception: public std::exception {
|
||||
std::source_location src;
|
||||
ox::CString msg = nullptr;
|
||||
ox::CString file = nullptr;
|
||||
uint16_t line = 0;
|
||||
ErrorCode errCode = 0;
|
||||
|
||||
explicit inline Exception(ox::CString file, uint32_t line, ErrorCode errCode, char const*msg = "") noexcept {
|
||||
this->file = file;
|
||||
this->line = static_cast<uint16_t>(line);
|
||||
this->msg = msg;
|
||||
this->errCode = errCode;
|
||||
}
|
||||
|
||||
explicit inline Exception(
|
||||
ErrorCode const errCode,
|
||||
std::source_location const&src = std::source_location::current()) noexcept:
|
||||
src{src},
|
||||
file{src.file_name()},
|
||||
line{static_cast<uint16_t>(src.line())},
|
||||
errCode{errCode} {}
|
||||
|
||||
explicit inline Exception(
|
||||
ErrorCode const errCode,
|
||||
ox::CString msg,
|
||||
std::source_location const&src = std::source_location::current()) noexcept:
|
||||
src{src},
|
||||
msg{msg},
|
||||
file{src.file_name()},
|
||||
line{static_cast<uint16_t>(src.line())},
|
||||
errCode{errCode} {}
|
||||
|
||||
explicit inline Exception(Error const&err) noexcept:
|
||||
src{err.src},
|
||||
msg{err.msg ? err.msg : ""},
|
||||
file{err.file},
|
||||
line{err.line},
|
||||
errCode{err.errCode} {}
|
||||
|
||||
constexpr Error toError() const noexcept {
|
||||
return Error(errCode, msg, src);
|
||||
return Error(file, line, errCode, msg);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
|
1
deps/ox/src/ox/std/reader.hpp
vendored
1
deps/ox/src/ox/std/reader.hpp
vendored
@ -31,6 +31,7 @@ concept Reader_c = requires(T v) {
|
||||
class Reader_v {
|
||||
public:
|
||||
virtual constexpr ~Reader_v() noexcept = default;
|
||||
[[nodiscard]]
|
||||
virtual constexpr ox::Result<char> peek() const noexcept = 0;
|
||||
virtual constexpr ox::Result<std::size_t> read(char*, std::size_t) noexcept = 0;
|
||||
virtual constexpr ox::Result<std::size_t> tellg() noexcept = 0;
|
||||
|
54
deps/ox/src/ox/std/smallmap.hpp
vendored
54
deps/ox/src/ox/std/smallmap.hpp
vendored
@ -62,9 +62,6 @@ class SmallMap {
|
||||
[[nodiscard]]
|
||||
constexpr Vector<K> keys() const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Vector<T> values() const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr K const&key(size_t i) const noexcept;
|
||||
|
||||
@ -89,13 +86,10 @@ class SmallMap {
|
||||
|
||||
private:
|
||||
template<typename KK>
|
||||
constexpr Pair const*access(PairVector const&pairs, KK const&key, bool &isNew) const;
|
||||
constexpr Pair const&access(PairVector const&pairs, KK const&key, bool &isNew) const;
|
||||
|
||||
template<typename KK>
|
||||
constexpr Pair *access(PairVector &pairs, KK const&key, bool &isNew);
|
||||
|
||||
template<typename KK>
|
||||
constexpr Pair *accessNoCreate(PairVector &pairs, KK const&key);
|
||||
constexpr Pair &access(PairVector &pairs, KK const&key, bool &isNew);
|
||||
|
||||
};
|
||||
|
||||
@ -135,7 +129,7 @@ constexpr SmallMap<K, T, SmallSz> &SmallMap<K, T, SmallSz>::operator=(SmallMap<K
|
||||
template<typename K, typename T, size_t SmallSz>
|
||||
constexpr T &SmallMap<K, T, SmallSz>::operator[](MaybeView_t<K> const&k) {
|
||||
bool isNew{};
|
||||
auto p = access(m_pairs, k, isNew);
|
||||
auto p = &access(m_pairs, k, isNew);
|
||||
if (isNew) {
|
||||
p->key = k;
|
||||
}
|
||||
@ -144,7 +138,7 @@ constexpr T &SmallMap<K, T, SmallSz>::operator[](MaybeView_t<K> const&k) {
|
||||
|
||||
template<typename K, typename T, size_t SmallSz>
|
||||
constexpr Result<T*> SmallMap<K, T, SmallSz>::at(MaybeView_t<K> const&k) noexcept {
|
||||
auto const p = accessNoCreate(m_pairs, k);
|
||||
auto p = access(m_pairs, k);
|
||||
if (!p) {
|
||||
return {nullptr, ox::Error(1, "value not found for given key")};
|
||||
}
|
||||
@ -153,8 +147,7 @@ constexpr Result<T*> SmallMap<K, T, SmallSz>::at(MaybeView_t<K> const&k) noexcep
|
||||
|
||||
template<typename K, typename T, size_t SmallSz>
|
||||
constexpr Result<const T*> SmallMap<K, T, SmallSz>::at(MaybeView_t<K> const&k) const noexcept {
|
||||
bool isNew{};
|
||||
auto p = access(m_pairs, k, isNew);
|
||||
auto p = access(m_pairs, k);
|
||||
if (!p) {
|
||||
return {nullptr, ox::Error(1, "value not found for given key")};
|
||||
}
|
||||
@ -175,8 +168,7 @@ constexpr void SmallMap<K, T, SmallSz>::erase(MaybeView_t<K> const&k) {
|
||||
|
||||
template<typename K, typename T, size_t SmallSz>
|
||||
constexpr bool SmallMap<K, T, SmallSz>::contains(MaybeView_t<K> const&k) const noexcept {
|
||||
bool isNew{};
|
||||
return access(m_pairs, k, isNew) != nullptr;
|
||||
return access(m_pairs, k) != nullptr;
|
||||
}
|
||||
|
||||
template<typename K, typename T, size_t SmallSz>
|
||||
@ -194,16 +186,6 @@ constexpr Vector<K> SmallMap<K, T, SmallSz>::keys() const noexcept {
|
||||
return keys;
|
||||
}
|
||||
|
||||
template<typename K, typename T, size_t SmallSz>
|
||||
constexpr Vector<T> SmallMap<K, T, SmallSz>::values() const noexcept {
|
||||
ox::Vector<T> keys;
|
||||
keys.reserve(m_pairs.size());
|
||||
for (auto const&p : m_pairs) {
|
||||
keys.emplace_back(p.key);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
template<typename K, typename T, size_t SmallSz>
|
||||
constexpr K const&SmallMap<K, T, SmallSz>::key(size_t i) const noexcept {
|
||||
return m_pairs[i].key;
|
||||
@ -236,42 +218,30 @@ constexpr void SmallMap<K, T, SmallSz>::clear() {
|
||||
|
||||
template<typename K, typename T, size_t SmallSz>
|
||||
template<typename KK>
|
||||
constexpr typename SmallMap<K, T, SmallSz>::Pair const*SmallMap<K, T, SmallSz>::access(
|
||||
constexpr typename SmallMap<K, T, SmallSz>::Pair const&SmallMap<K, T, SmallSz>::access(
|
||||
PairVector const&pairs, KK const&k, bool &isNew) const {
|
||||
for (auto const&p : pairs) {
|
||||
if (p.key == k) {
|
||||
isNew = false;
|
||||
return &p;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
isNew = true;
|
||||
return nullptr;
|
||||
return pairs.emplace_back();
|
||||
}
|
||||
|
||||
template<typename K, typename T, size_t SmallSz>
|
||||
template<typename KK>
|
||||
constexpr typename SmallMap<K, T, SmallSz>::Pair *SmallMap<K, T, SmallSz>::access(
|
||||
constexpr typename SmallMap<K, T, SmallSz>::Pair &SmallMap<K, T, SmallSz>::access(
|
||||
PairVector &pairs, KK const&k, bool &isNew) {
|
||||
for (auto &p : pairs) {
|
||||
if (p.key == k) {
|
||||
isNew = false;
|
||||
return &p;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
isNew = true;
|
||||
return &pairs.emplace_back();
|
||||
}
|
||||
|
||||
template<typename K, typename T, size_t SmallSz>
|
||||
template<typename KK>
|
||||
constexpr typename SmallMap<K, T, SmallSz>::Pair *SmallMap<K, T, SmallSz>::accessNoCreate(
|
||||
PairVector &pairs, KK const&k) {
|
||||
for (auto &p : pairs) {
|
||||
if (p.key == k) {
|
||||
return &p;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return pairs.emplace_back();
|
||||
}
|
||||
|
||||
template<typename T, typename K, typename V, size_t SmallSz>
|
||||
|
2
deps/ox/src/ox/std/test/CMakeLists.txt
vendored
2
deps/ox/src/ox/std/test/CMakeLists.txt
vendored
@ -17,8 +17,6 @@ add_test("[ox/std] String" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "String")
|
||||
add_test("[ox/std] SmallMap" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "SmallMap")
|
||||
add_test("[ox/std] SmallMap2" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "SmallMap2")
|
||||
add_test("[ox/std] Vector" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "Vector")
|
||||
add_test("[ox/std] Vector::shrink_to_fit" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "Vector::shrink_to_fit")
|
||||
add_test("[ox/std] findIdx" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "findIdx")
|
||||
add_test("[ox/std] HashMap" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "HashMap")
|
||||
add_test("[ox/std] HeapMgr" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest malloc)
|
||||
add_test("[ox/std] Serialize-Int" ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/StdTest "Serialize-Int")
|
||||
|
57
deps/ox/src/ox/std/test/tests.cpp
vendored
57
deps/ox/src/ox/std/test/tests.cpp
vendored
@ -237,50 +237,6 @@ OX_CLANG_NOWARN_END
|
||||
return ox::Error(0);
|
||||
}
|
||||
},
|
||||
{
|
||||
"Vector::shrink_to_fit",
|
||||
[] {
|
||||
{
|
||||
ox::Vector<ox::IString<8>> v;
|
||||
v.reserve(50);
|
||||
v.emplace_back("asdf");
|
||||
v.emplace_back("aoeu");
|
||||
auto const origData = v.data();
|
||||
v.shrink_to_fit();
|
||||
oxExpect(v[0], "asdf");
|
||||
oxExpect(v[1], "aoeu");
|
||||
oxExpect(v.capacity(), 2u);
|
||||
oxAssert(origData != v.data(), "shrink_to_fit did not create a new allocation");
|
||||
}
|
||||
{
|
||||
ox::Vector<ox::IString<8>> v;
|
||||
v.reserve(2);
|
||||
v.emplace_back("asdf");
|
||||
v.emplace_back("aoeu");
|
||||
auto const origData = v.data();
|
||||
v.shrink_to_fit();
|
||||
oxExpect(v[0], "asdf");
|
||||
oxExpect(v[1], "aoeu");
|
||||
oxExpect(v.capacity(), 2u);
|
||||
oxAssert(origData == v.data(), "shrink_to_fit inappropriately created a new allocation");
|
||||
}
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
{
|
||||
"findIdx",
|
||||
[] {
|
||||
ox::Vector<ox::IString<8>> const v {"zero", "one", "two", "three", "four"};
|
||||
oxExpect(ox::findIdx(v.begin(), v.end(), "zero").or_value(5), 0u);
|
||||
oxExpect(ox::findIdx(v.begin(), v.end(), "one").or_value(5), 1u);
|
||||
oxExpect(ox::findIdx(v.begin(), v.end(), "two").or_value(5), 2u);
|
||||
oxExpect(ox::findIdx(v.begin(), v.end(), "three").or_value(5), 3u);
|
||||
oxExpect(ox::findIdx(v.begin(), v.end(), "four").or_value(5), 4u);
|
||||
oxExpect(ox::findIdx(v.begin(), v.end(), "five").or_value(5), 5u);
|
||||
oxExpect(ox::findIdx(v.begin(), v.end(), "six").or_value(6), 6u);
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
{
|
||||
"SmallMap",
|
||||
[] {
|
||||
@ -290,18 +246,7 @@ OX_CLANG_NOWARN_END
|
||||
oxExpect(map.size(), 1u);
|
||||
oxExpect(map["aoeu"], "");
|
||||
oxExpect(map.size(), 2u);
|
||||
ox::SmallMap<ox::String, ox::String> cmap;
|
||||
cmap["asdf"] = "aoeu";
|
||||
auto constexpr constTest = [](ox::SmallMap<ox::String, ox::String> const&map) {
|
||||
OX_REQUIRE(asdf, map.at("asdf"));
|
||||
oxExpect(*asdf, "aoeu");
|
||||
oxExpect(map.size(), 1u);
|
||||
auto const aoeu = map.at("aoeu");
|
||||
oxExpect(aoeu.ok(), false);
|
||||
oxExpect(map.size(), 1u);
|
||||
return ox::Error{};
|
||||
};
|
||||
return constTest(cmap);
|
||||
return ox::Error(0);
|
||||
}
|
||||
},
|
||||
{
|
||||
|
8
deps/ox/src/ox/std/trace.hpp
vendored
8
deps/ox/src/ox/std/trace.hpp
vendored
@ -269,8 +269,8 @@ using TraceStream = NullStream;
|
||||
inline void logError(const char *file, int line, const char *fmt, const Error &err) noexcept {
|
||||
if (err) {
|
||||
TraceStream trc(file, line, "ox::error");
|
||||
if (err.src.file_name() != nullptr) {
|
||||
trc << "Error: (" << err.src.file_name() << ":" << err.src.line() << "):";
|
||||
if (err.file != nullptr) {
|
||||
trc << "Error: (" << err.file << ":" << err.line << "):";
|
||||
} else {
|
||||
trc << "Error:";
|
||||
}
|
||||
@ -282,8 +282,8 @@ inline void logError(const char *file, int line, const Error &err) noexcept {
|
||||
if (err) {
|
||||
TraceStream trc(file, line, "ox::error");
|
||||
trc << "Error:" << err;
|
||||
if (err.src.file_name() != nullptr) {
|
||||
trc << "(" << err.src.file_name() << ":" << err.src.line() << ")";
|
||||
if (err.file != nullptr) {
|
||||
trc << "(" << err.file << ":" << err.line << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
21
deps/ox/src/ox/std/vector.hpp
vendored
21
deps/ox/src/ox/std/vector.hpp
vendored
@ -313,8 +313,6 @@ class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
||||
|
||||
constexpr void reserve(std::size_t cap) noexcept(useNoexcept);
|
||||
|
||||
constexpr void shrink_to_fit() noexcept(useNoexcept);
|
||||
|
||||
private:
|
||||
constexpr void reserveInsert(
|
||||
std::size_t cap, std::size_t pos, std::size_t offset = 1) noexcept(useNoexcept);
|
||||
@ -343,7 +341,6 @@ constexpr Vector<T, SmallVectorSize, Allocator>::Vector(std::size_t size) noexce
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Vector<T, SmallVectorSize, Allocator>::Vector(std::initializer_list<T> list) noexcept {
|
||||
reserve(list.size());
|
||||
for (auto &item : list) {
|
||||
emplace_back(std::move(item));
|
||||
}
|
||||
@ -678,24 +675,6 @@ constexpr void Vector<T, SmallVectorSize, Allocator>::reserve(std::size_t cap) n
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::shrink_to_fit() noexcept(useNoexcept) {
|
||||
if (m_size == m_cap) {
|
||||
return;
|
||||
}
|
||||
const auto oldItems = m_items;
|
||||
const auto oldCap = m_cap;
|
||||
m_cap = m_size;
|
||||
this->allocate(&m_items, m_size);
|
||||
if (oldItems) { // move over old items
|
||||
for (std::size_t i = 0; i < m_size; ++i) {
|
||||
std::construct_at(&m_items[i], std::move(oldItems[i]));
|
||||
oldItems[i].~T();
|
||||
}
|
||||
this->deallocate(oldItems, oldCap);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::reserveInsert(
|
||||
std::size_t cap,
|
||||
|
@ -28,11 +28,11 @@ project_name = sys.argv[2]
|
||||
bin = f'./build/{host_env}-{current_build}/bin/'
|
||||
project_bin = f'build/gba-release/bin/{project_name}.bin'
|
||||
project_gba = f'{project_name}.gba'
|
||||
project_manifest = f'{project_name.lower()}-manifest.json'
|
||||
project_manifest = f'{project_name}-manifest.json'
|
||||
|
||||
shutil.copyfile(project_bin, project_gba)
|
||||
subprocess.run([
|
||||
f'{bin}/{project_name.lower()}-pack',
|
||||
f'{bin}/{project_name}-pack',
|
||||
'-src', project_dir,
|
||||
'-rom-bin', project_gba,
|
||||
'-manifest', project_manifest])
|
@ -102,6 +102,8 @@ OX_MODEL_BEGIN(TileSheetSet)
|
||||
OX_MODEL_FIELD(entries)
|
||||
OX_MODEL_END()
|
||||
|
||||
void addEntry(TileSheetSet &set, ox::FileAddress path, int32_t begin = 0, int32_t size = -1) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
int tileColumns(Context&) noexcept;
|
||||
|
||||
|
@ -212,10 +212,6 @@ struct TileSheetV4 {
|
||||
pixels(std::move(pPixels)) {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the dimensional size of the SubSheet (e.g. width * height)
|
||||
*/
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t size() const noexcept {
|
||||
return static_cast<std::size_t>(columns) * static_cast<std::size_t>(rows);
|
||||
@ -237,10 +233,12 @@ struct TileSheetV4 {
|
||||
[[nodiscard]]
|
||||
constexpr bool valid(TileSheetV4::SubSheet const&ss, int bpp) noexcept {
|
||||
auto const bytes = static_cast<size_t>(ss.columns * ss.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1);
|
||||
return ox::all_of(ss.subsheets.begin(), ss.subsheets.end(),
|
||||
[bpp, bytes](TileSheetV4::SubSheet const&s) {
|
||||
return bytes == s.pixels.size() && valid(s, bpp);
|
||||
});
|
||||
return
|
||||
(ss.pixels.empty() || ss.subsheets.empty()) &&
|
||||
ox::all_of(ss.subsheets.begin(), ss.subsheets.end(),
|
||||
[bpp, bytes](TileSheetV4::SubSheet const&s) {
|
||||
return bytes == s.pixels.size() && valid(s, bpp);
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@ -249,8 +247,14 @@ constexpr bool valid(TileSheetV4 const&ts) noexcept {
|
||||
}
|
||||
|
||||
constexpr void repair(TileSheetV4::SubSheet &ss, int bpp) noexcept {
|
||||
auto const bytes = static_cast<size_t>(ss.columns * ss.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1);
|
||||
ss.pixels.resize(bytes);
|
||||
if (ss.subsheets.empty()) {
|
||||
auto const bytes = static_cast<size_t>(ss.columns * ss.rows * PixelsPerTile) / (bpp == 4 ? 2 : 1);
|
||||
ss.pixels.resize(bytes);
|
||||
} else {
|
||||
ss.pixels.clear();
|
||||
ss.columns = -1;
|
||||
ss.rows = -1;
|
||||
}
|
||||
for (auto &s : ss.subsheets) {
|
||||
repair(s, bpp);
|
||||
}
|
||||
@ -277,7 +281,7 @@ size_t getTileCnt(TileSheet const&ts) noexcept;
|
||||
TileSheet::SubSheet const*getSubsheet(TileSheet const&ts, SubSheetId id) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Optional<size_t> getTileIdx(TileSheet const&ts, SubSheetId id) noexcept;
|
||||
size_t getTileIdx(TileSheet const&ts, SubSheetId id) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept;
|
||||
@ -396,8 +400,6 @@ ox::Result<SubSheetId> getIdFor(TileSheet const&ts, ox::StringViewCR path) noexc
|
||||
|
||||
ox::Result<unsigned> getTileOffset(TileSheet const&ts, ox::StringViewCR pNamePath) noexcept;
|
||||
|
||||
ox::Result<uint32_t> getTileOffset(TileSheet const&ts, SubSheetId pId) noexcept;
|
||||
|
||||
ox::Result<ox::StringView> getNameFor(TileSheet::SubSheet const&ss, SubSheetId pId) noexcept;
|
||||
|
||||
ox::Result<ox::StringView> getNameFor(TileSheet const&ts, SubSheetId pId) noexcept;
|
||||
|
@ -48,8 +48,8 @@ OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
oxErrf("\tError Message:\t{}\n", err.msg);
|
||||
}
|
||||
oxErrf("\tError Code:\t{}\n", static_cast<ErrorCode>(err));
|
||||
if (err.src.file_name() != nullptr) {
|
||||
oxErrf("\tError Location:\t{}:{}\n", err.src.file_name(), err.src.line());
|
||||
if (err.file != nullptr) {
|
||||
oxErrf("\tError Location:\t{}:{}\n", err.file, err.line);
|
||||
}
|
||||
// disable all interrupt handling and IntrWait on no interrupts
|
||||
REG_IE = 0;
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
core::InsertTilesCommand::InsertTilesCommand(
|
||||
InsertTilesCommand::InsertTilesCommand(
|
||||
TileSheet &img,
|
||||
TileSheet::SubSheetIdx idx,
|
||||
std::size_t tileIdx,
|
||||
@ -31,9 +31,11 @@ ox::Error InsertTilesCommand::redo() noexcept {
|
||||
auto &s = getSubSheet(m_img, m_idx);
|
||||
auto &p = s.pixels;
|
||||
auto dstPos = m_insertPos + m_insertCnt;
|
||||
auto const dst = &p[dstPos];
|
||||
auto const src = &p[m_insertPos];
|
||||
ox::memmove(dst, src, p.size() - dstPos);
|
||||
if (dstPos < p.size()) {
|
||||
auto const dst = &p[dstPos];
|
||||
ox::memmove(dst, src, p.size() - dstPos);
|
||||
}
|
||||
ox::memset(src, 0, m_insertCnt * sizeof(decltype(p[0])));
|
||||
return {};
|
||||
}
|
||||
@ -41,12 +43,14 @@ ox::Error InsertTilesCommand::redo() noexcept {
|
||||
ox::Error InsertTilesCommand::undo() noexcept {
|
||||
auto &s = getSubSheet(m_img, m_idx);
|
||||
auto &p = s.pixels;
|
||||
auto const srcIdx = m_insertPos + m_insertCnt;
|
||||
auto const src = &p[srcIdx];
|
||||
auto const dst1 = &p[m_insertPos];
|
||||
auto const dst2 = &p[p.size() - m_insertCnt];
|
||||
auto const sz = p.size() - srcIdx;
|
||||
ox::memmove(dst1, src, sz);
|
||||
auto const srcIdx = m_insertPos + m_insertCnt;
|
||||
if (srcIdx < p.size()) {
|
||||
auto const sz = p.size() - srcIdx;
|
||||
auto const src = &p[srcIdx];
|
||||
ox::memmove(dst1, src, sz);
|
||||
}
|
||||
ox::memcpy(dst2, m_deletedPixels.data(), m_deletedPixels.size());
|
||||
return {};
|
||||
}
|
||||
|
@ -9,27 +9,24 @@ namespace nostalgia::core {
|
||||
core::UpdateSubSheetCommand::UpdateSubSheetCommand(
|
||||
TileSheet &img,
|
||||
TileSheet::SubSheetIdx idx,
|
||||
ox::String name,
|
||||
int cols,
|
||||
int rows) noexcept:
|
||||
m_img(img),
|
||||
m_idx(std::move(idx)),
|
||||
m_sheet(getSubSheet(m_img, m_idx)),
|
||||
m_newName(std::move(name)),
|
||||
m_newCols(cols),
|
||||
m_newRows(rows) {
|
||||
ox::StringParam name,
|
||||
int const cols,
|
||||
int const rows):
|
||||
m_img{img},
|
||||
m_idx{std::move(idx)},
|
||||
m_sheet{getSubSheet(m_img, m_idx)} {
|
||||
m_sheet = getSubSheet(m_img, m_idx);
|
||||
m_sheet.name = std::move(name);
|
||||
OX_THROW_ERROR(resizeSubsheet(m_sheet, m_img.bpp, {cols, rows}));
|
||||
}
|
||||
|
||||
ox::Error UpdateSubSheetCommand::redo() noexcept {
|
||||
auto &sheet = getSubSheet(m_img, m_idx);
|
||||
sheet.name = m_newName;
|
||||
oxLogError(resizeSubsheet(sheet, m_img.bpp, {m_newCols, m_newRows}));
|
||||
std::swap(m_sheet, getSubSheet(m_img, m_idx));
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error UpdateSubSheetCommand::undo() noexcept {
|
||||
auto &sheet = getSubSheet(m_img, m_idx);
|
||||
sheet = m_sheet;
|
||||
std::swap(m_sheet, getSubSheet(m_img, m_idx));
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -13,17 +13,14 @@ class UpdateSubSheetCommand: public TileSheetCommand {
|
||||
TileSheet &m_img;
|
||||
TileSheet::SubSheetIdx m_idx;
|
||||
TileSheet::SubSheet m_sheet;
|
||||
ox::String m_newName;
|
||||
int m_newCols = 0;
|
||||
int m_newRows = 0;
|
||||
|
||||
public:
|
||||
UpdateSubSheetCommand(
|
||||
TileSheet &img,
|
||||
TileSheet::SubSheetIdx idx,
|
||||
ox::String name,
|
||||
ox::StringParam name,
|
||||
int cols,
|
||||
int rows) noexcept;
|
||||
int rows);
|
||||
|
||||
ox::Error redo() noexcept final;
|
||||
|
||||
|
@ -188,7 +188,7 @@ void TileSheetEditorImGui::draw(studio::StudioContext&) noexcept {
|
||||
if (ImGui::IsKeyDown(ImGuiKey_ModCtrl)) {
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_A)) {
|
||||
auto const&img = m_model.activeSubSheet();
|
||||
m_model.setSelection({{}, {img.columns * TileWidth, img.rows * TileHeight}});
|
||||
m_model.setSelection({{}, {img.columns * TileWidth - 1, img.rows * TileHeight - 1}});
|
||||
} else if (ImGui::IsKeyPressed(ImGuiKey_G)) {
|
||||
m_model.clearSelection();
|
||||
}
|
||||
@ -544,7 +544,7 @@ void TileSheetEditorImGui::SubSheetEditor::draw(turbine::Context &tctx) noexcept
|
||||
auto const popupHeight = modSize ? 130.f : 85.f;
|
||||
auto const popupSz = ImVec2{popupWidth, popupHeight};
|
||||
if (ig::BeginPopup(tctx, popupName, m_show, popupSz)) {
|
||||
ImGui::InputText("Name", m_name.data(), m_name.cap());
|
||||
ig::InputText("Name", m_name);
|
||||
if (modSize) {
|
||||
ImGui::InputInt("Columns", &m_cols);
|
||||
ImGui::InputInt("Rows", &m_rows);
|
||||
|
@ -26,11 +26,6 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
Palette const TileSheetEditorModel::s_defaultPalette = {
|
||||
.colorNames = {ox::Vector<ox::String>{{}}},
|
||||
.pages = {{"Page 1", ox::Vector<Color16>(128)}},
|
||||
};
|
||||
|
||||
// delete pixels of all non-leaf nodes
|
||||
static void normalizeSubsheets(TileSheet::SubSheet &ss) noexcept {
|
||||
if (ss.subsheets.empty()) {
|
||||
@ -42,7 +37,14 @@ static void normalizeSubsheets(TileSheet::SubSheet &ss) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
TileSheetEditorModel::TileSheetEditorModel(studio::StudioContext &sctx, ox::StringView path, studio::UndoStack &undoStack):
|
||||
|
||||
Palette const TileSheetEditorModel::s_defaultPalette = {
|
||||
.colorNames = {ox::Vector<ox::String>{{}}},
|
||||
.pages = {{"Page 1", ox::Vector<Color16>(128)}},
|
||||
};
|
||||
|
||||
TileSheetEditorModel::TileSheetEditorModel(
|
||||
studio::StudioContext &sctx, ox::StringViewCR path, studio::UndoStack &undoStack):
|
||||
m_sctx(sctx),
|
||||
m_tctx(m_sctx.tctx),
|
||||
m_path(path),
|
||||
@ -62,7 +64,7 @@ void TileSheetEditorModel::cut() {
|
||||
TileSheetClipboard blankCb;
|
||||
auto cb = ox::make_unique<TileSheetClipboard>();
|
||||
auto const&s = activeSubSheet();
|
||||
iterateSelectionRows(*m_selection, [&](int x, int y) {
|
||||
iterateSelectionRows(*m_selection, [&](int const x, int const y) {
|
||||
auto pt = ox::Point{x, y};
|
||||
auto const idx = core::idx(s, pt);
|
||||
auto const c = getPixel(s, m_img.bpp, idx);
|
||||
@ -73,7 +75,8 @@ void TileSheetEditorModel::cut() {
|
||||
auto const pt1 = m_selection->a;
|
||||
auto const pt2 = ox::Point{s.columns * TileWidth, s.rows * TileHeight};
|
||||
turbine::setClipboardObject(m_tctx, std::move(cb));
|
||||
pushCommand(ox::make<CutPasteCommand>(CommandId::Cut, m_img, m_activeSubsSheetIdx, pt1, pt2, blankCb));
|
||||
pushCommand(ox::make<CutPasteCommand>(
|
||||
CommandId::Cut, m_img, m_activeSubsSheetIdx, pt1, pt2, blankCb));
|
||||
}
|
||||
|
||||
void TileSheetEditorModel::copy() {
|
||||
@ -81,7 +84,7 @@ void TileSheetEditorModel::copy() {
|
||||
return;
|
||||
}
|
||||
auto cb = ox::make_unique<TileSheetClipboard>();
|
||||
iterateSelectionRows(*m_selection, [&](int x, int y) {
|
||||
iterateSelectionRows(*m_selection, [&](int const x, int const y) {
|
||||
auto pt = ox::Point{x, y};
|
||||
const auto&s = activeSubSheet();
|
||||
const auto idx = core::idx(s, pt);
|
||||
@ -105,7 +108,8 @@ void TileSheetEditorModel::paste() {
|
||||
auto const&s = activeSubSheet();
|
||||
auto const pt1 = m_selection->a;
|
||||
auto const pt2 = ox::Point{s.columns * TileWidth, s.rows * TileHeight};
|
||||
pushCommand(ox::make<CutPasteCommand>(CommandId::Paste, m_img, m_activeSubsSheetIdx, pt1, pt2, *cb));
|
||||
pushCommand(ox::make<CutPasteCommand>(
|
||||
CommandId::Paste, m_img, m_activeSubsSheetIdx, pt1, pt2, *cb));
|
||||
}
|
||||
|
||||
bool TileSheetEditorModel::acceptsClipboardPayload() const noexcept {
|
||||
@ -120,8 +124,8 @@ ox::StringView TileSheetEditorModel::palPath() const noexcept {
|
||||
}
|
||||
constexpr ox::StringView uuidPrefix = "uuid://";
|
||||
if (ox::beginsWith(path, uuidPrefix)) {
|
||||
auto uuid = ox::StringView(&path[uuidPrefix.bytes()], path.bytes() - uuidPrefix.bytes());
|
||||
auto out = keelCtx(m_tctx).uuidToPath.at(uuid);
|
||||
auto const uuid = ox::StringView(&path[uuidPrefix.bytes()], path.bytes() - uuidPrefix.bytes());
|
||||
auto const out = keelCtx(m_tctx).uuidToPath.at(uuid);
|
||||
if (out.error) {
|
||||
return {};
|
||||
}
|
||||
@ -131,13 +135,14 @@ ox::StringView TileSheetEditorModel::palPath() const noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
ox::Error TileSheetEditorModel::setPalette(ox::StringView path) noexcept {
|
||||
ox::Error TileSheetEditorModel::setPalette(ox::StringViewCR path) noexcept {
|
||||
OX_REQUIRE(uuid, keelCtx(m_tctx).pathToUuid.at(path));
|
||||
pushCommand(ox::make<PaletteChangeCommand>(activeSubSheetIdx(), m_img, uuid->toString()));
|
||||
pushCommand(ox::make<PaletteChangeCommand>(
|
||||
activeSubSheetIdx(), m_img, uuid->toString()));
|
||||
return {};
|
||||
}
|
||||
|
||||
void TileSheetEditorModel::setPalettePage(size_t pg) noexcept {
|
||||
void TileSheetEditorModel::setPalettePage(size_t const pg) noexcept {
|
||||
m_palettePage = ox::clamp<size_t>(pg, 0, m_pal->pages.size() - 1);
|
||||
m_updated = true;
|
||||
}
|
||||
@ -146,7 +151,7 @@ size_t TileSheetEditorModel::palettePage() const noexcept {
|
||||
return m_palettePage;
|
||||
}
|
||||
|
||||
void TileSheetEditorModel::drawCommand(ox::Point const&pt, std::size_t palIdx) noexcept {
|
||||
void TileSheetEditorModel::drawCommand(ox::Point const&pt, std::size_t const palIdx) noexcept {
|
||||
const auto &activeSubSheet = getSubSheet(m_img, m_activeSubsSheetIdx);
|
||||
if (pt.x >= activeSubSheet.columns * TileWidth || pt.y >= activeSubSheet.rows * TileHeight) {
|
||||
return;
|
||||
@ -155,7 +160,8 @@ void TileSheetEditorModel::drawCommand(ox::Point const&pt, std::size_t palIdx) n
|
||||
if (m_ongoingDrawCommand) {
|
||||
m_updated = m_updated || m_ongoingDrawCommand->append(idx);
|
||||
} else if (getPixel(activeSubSheet, m_img.bpp, idx) != palIdx) {
|
||||
pushCommand(ox::make<DrawCommand>(m_img, m_activeSubsSheetIdx, idx, static_cast<int>(palIdx)));
|
||||
pushCommand(ox::make<DrawCommand>(
|
||||
m_img, m_activeSubsSheetIdx, idx, static_cast<int>(palIdx)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -171,16 +177,20 @@ void TileSheetEditorModel::rmSubsheet(TileSheet::SubSheetIdx const&idx) noexcept
|
||||
pushCommand(ox::make<RmSubSheetCommand>(m_img, idx));
|
||||
}
|
||||
|
||||
void TileSheetEditorModel::insertTiles(TileSheet::SubSheetIdx const&idx, std::size_t tileIdx, std::size_t tileCnt) noexcept {
|
||||
void TileSheetEditorModel::insertTiles(
|
||||
TileSheet::SubSheetIdx const&idx, std::size_t const tileIdx, std::size_t const tileCnt) noexcept {
|
||||
pushCommand(ox::make<InsertTilesCommand>(m_img, idx, tileIdx, tileCnt));
|
||||
}
|
||||
|
||||
void TileSheetEditorModel::deleteTiles(TileSheet::SubSheetIdx const&idx, std::size_t tileIdx, std::size_t tileCnt) noexcept {
|
||||
void TileSheetEditorModel::deleteTiles(
|
||||
TileSheet::SubSheetIdx const&idx, std::size_t const tileIdx, std::size_t const tileCnt) noexcept {
|
||||
pushCommand(ox::make<DeleteTilesCommand>(m_img, idx, tileIdx, tileCnt));
|
||||
}
|
||||
|
||||
ox::Error TileSheetEditorModel::updateSubsheet(TileSheet::SubSheetIdx const&idx, ox::StringView const&name, int cols, int rows) noexcept {
|
||||
pushCommand(ox::make<UpdateSubSheetCommand>(m_img, idx, ox::String(name), cols, rows));
|
||||
ox::Error TileSheetEditorModel::updateSubsheet(
|
||||
TileSheet::SubSheetIdx const&idx, ox::StringViewCR name, int const cols, int const rows) noexcept {
|
||||
OX_REQUIRE(cmd, ox::makeCatch<UpdateSubSheetCommand>(m_img, idx, name, cols, rows));
|
||||
pushCommand(cmd);
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -189,7 +199,7 @@ void TileSheetEditorModel::setActiveSubsheet(TileSheet::SubSheetIdx const&idx) n
|
||||
this->activeSubsheetChanged.emit(m_activeSubsSheetIdx);
|
||||
}
|
||||
|
||||
void TileSheetEditorModel::fill(ox::Point const&pt, int palIdx) noexcept {
|
||||
void TileSheetEditorModel::fill(ox::Point const&pt, int const palIdx) noexcept {
|
||||
auto const&activeSubSheet = getSubSheet(m_img, m_activeSubsSheetIdx);
|
||||
// build idx list
|
||||
if (pt.x >= activeSubSheet.columns * TileWidth || pt.y >= activeSubSheet.rows * TileHeight) {
|
||||
@ -197,10 +207,10 @@ void TileSheetEditorModel::fill(ox::Point const&pt, int palIdx) noexcept {
|
||||
}
|
||||
ox::Array<bool, PixelsPerTile> updateMap = {};
|
||||
auto const oldColor = getPixel(activeSubSheet, m_img.bpp, pt);
|
||||
getFillPixels(updateMap, pt, oldColor);
|
||||
getFillPixels(activeSubSheet, updateMap, pt, oldColor);
|
||||
ox::Vector<std::size_t> idxList;
|
||||
auto i = core::idx(activeSubSheet, pt) / PixelsPerTile * PixelsPerTile;
|
||||
for (auto u : updateMap) {
|
||||
for (auto const u : updateMap) {
|
||||
if (u) {
|
||||
idxList.emplace_back(i);
|
||||
}
|
||||
@ -230,7 +240,7 @@ void TileSheetEditorModel::completeSelection() noexcept {
|
||||
m_selTracker.finishSelection();
|
||||
m_selection.emplace(m_selTracker.selection());
|
||||
auto&pt = m_selection->b;
|
||||
auto&s = activeSubSheet();
|
||||
auto const&s = activeSubSheet();
|
||||
pt.x = ox::min(s.columns * TileWidth - 1, pt.x);
|
||||
pt.y = ox::min(s.rows * TileHeight - 1, pt.y);
|
||||
}
|
||||
@ -275,47 +285,44 @@ ox::Error TileSheetEditorModel::saveFile() noexcept {
|
||||
return m_sctx.project->writeObj(m_path, m_img, ox::ClawFormat::Metal);
|
||||
}
|
||||
|
||||
bool TileSheetEditorModel::pixelSelected(std::size_t idx) const noexcept {
|
||||
bool TileSheetEditorModel::pixelSelected(std::size_t const idx) const noexcept {
|
||||
auto const&s = activeSubSheet();
|
||||
auto const pt = idxToPt(static_cast<int>(idx), s.columns);
|
||||
return m_selection && m_selection->contains(pt);
|
||||
}
|
||||
|
||||
void TileSheetEditorModel::getFillPixels(ox::Span<bool> pixels, ox::Point const&pt, int oldColor) const noexcept {
|
||||
const auto &activeSubSheet = this->activeSubSheet();
|
||||
const auto tileIdx = [activeSubSheet](const ox::Point &pt) noexcept {
|
||||
return ptToIdx(pt, activeSubSheet.columns) / PixelsPerTile;
|
||||
};
|
||||
// get points
|
||||
const auto leftPt = pt + ox::Point(-1, 0);
|
||||
const auto rightPt = pt + ox::Point(1, 0);
|
||||
const auto topPt = pt + ox::Point(0, -1);
|
||||
const auto bottomPt = pt + ox::Point(0, 1);
|
||||
// calculate indices
|
||||
const auto idx = ptToIdx(pt, activeSubSheet.columns);
|
||||
const auto leftIdx = ptToIdx(leftPt, activeSubSheet.columns);
|
||||
const auto rightIdx = ptToIdx(rightPt, activeSubSheet.columns);
|
||||
const auto topIdx = ptToIdx(topPt, activeSubSheet.columns);
|
||||
const auto bottomIdx = ptToIdx(bottomPt, activeSubSheet.columns);
|
||||
const auto tile = tileIdx(pt);
|
||||
void TileSheetEditorModel::getFillPixels(
|
||||
TileSheet::SubSheet const&activeSubSheet,
|
||||
ox::Span<bool> pixels,
|
||||
ox::Point const&pt,
|
||||
int const oldColor) const noexcept {
|
||||
auto const idx = ptToIdx(pt, activeSubSheet.columns);
|
||||
auto const relIdx = idx % PixelsPerTile;
|
||||
if (pixels[relIdx] || getPixel(activeSubSheet, m_img.bpp, idx) != oldColor) {
|
||||
return;
|
||||
}
|
||||
// mark pixels to update
|
||||
pixels[idx % PixelsPerTile] = true;
|
||||
if (!pixels[leftIdx % PixelsPerTile] && tile == tileIdx(leftPt) && getPixel(activeSubSheet, m_img.bpp, leftIdx) == oldColor) {
|
||||
getFillPixels(pixels, leftPt, oldColor);
|
||||
pixels[relIdx] = true;
|
||||
if (pt.x % TileWidth != 0) {
|
||||
auto const leftPt = pt + ox::Point{-1, 0};
|
||||
getFillPixels(activeSubSheet, pixels, leftPt, oldColor);
|
||||
}
|
||||
if (!pixels[rightIdx % PixelsPerTile] && tile == tileIdx(rightPt) && getPixel(activeSubSheet, m_img.bpp, rightIdx) == oldColor) {
|
||||
getFillPixels(pixels, rightPt, oldColor);
|
||||
if (pt.x % TileWidth != TileWidth - 1) {
|
||||
auto const rightPt = pt + ox::Point{1, 0};
|
||||
getFillPixels(activeSubSheet, pixels, rightPt, oldColor);
|
||||
}
|
||||
if (!pixels[topIdx % PixelsPerTile] && tile == tileIdx(topPt) && getPixel(activeSubSheet, m_img.bpp, topIdx) == oldColor) {
|
||||
getFillPixels(pixels, topPt, oldColor);
|
||||
if (pt.y % TileHeight != 0) {
|
||||
auto const topPt = pt + ox::Point{0, -1};
|
||||
getFillPixels(activeSubSheet, pixels, topPt, oldColor);
|
||||
}
|
||||
if (!pixels[bottomIdx % PixelsPerTile] && tile == tileIdx(bottomPt) && getPixel(activeSubSheet, m_img.bpp, bottomIdx) == oldColor) {
|
||||
getFillPixels(pixels, bottomPt, oldColor);
|
||||
if (pt.y % TileHeight != TileHeight - 1) {
|
||||
auto const bottomPt = pt + ox::Point{0, 1};
|
||||
getFillPixels(activeSubSheet, pixels, bottomPt, oldColor);
|
||||
}
|
||||
}
|
||||
|
||||
void TileSheetEditorModel::pushCommand(studio::UndoCommand *cmd) noexcept {
|
||||
std::ignore = m_undoStack.push(ox::UPtr<studio::UndoCommand>(cmd));
|
||||
std::ignore = m_undoStack.push(ox::UPtr<studio::UndoCommand>{cmd});
|
||||
m_ongoingDrawCommand = dynamic_cast<DrawCommand*>(cmd);
|
||||
m_updated = true;
|
||||
}
|
||||
|
@ -4,9 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/bounds.hpp>
|
||||
#include <ox/std/point.hpp>
|
||||
#include <ox/std/trace.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
|
||||
#include <studio/studio.hpp>
|
||||
@ -38,7 +36,7 @@ class TileSheetEditorModel: public ox::SignalHandler {
|
||||
bool m_updated = false;
|
||||
|
||||
public:
|
||||
TileSheetEditorModel(studio::StudioContext &sctx, ox::StringView path, studio::UndoStack &undoStack);
|
||||
TileSheetEditorModel(studio::StudioContext &sctx, ox::StringViewCR path, studio::UndoStack &undoStack);
|
||||
|
||||
~TileSheetEditorModel() override = default;
|
||||
|
||||
@ -63,7 +61,7 @@ class TileSheetEditorModel: public ox::SignalHandler {
|
||||
[[nodiscard]]
|
||||
ox::StringView palPath() const noexcept;
|
||||
|
||||
ox::Error setPalette(ox::StringView path) noexcept;
|
||||
ox::Error setPalette(ox::StringViewCR path) noexcept;
|
||||
|
||||
void setPalettePage(size_t pg) noexcept;
|
||||
|
||||
@ -128,7 +126,11 @@ class TileSheetEditorModel: public ox::SignalHandler {
|
||||
bool pixelSelected(std::size_t idx) const noexcept;
|
||||
|
||||
private:
|
||||
void getFillPixels(ox::Span<bool> pixels, ox::Point const&pt, int oldColor) const noexcept;
|
||||
void getFillPixels(
|
||||
TileSheet::SubSheet const&activeSubSheet,
|
||||
ox::Span<bool> pixels,
|
||||
ox::Point const&pt,
|
||||
int oldColor) const noexcept;
|
||||
|
||||
void pushCommand(studio::UndoCommand *cmd) noexcept;
|
||||
|
||||
|
@ -56,8 +56,10 @@ void TileSheetEditorView::scrollH(ox::Vec2 const&paneSz, float wheelh) noexcept
|
||||
}
|
||||
|
||||
void TileSheetEditorView::insertTile(ox::Vec2 const&paneSize, ox::Vec2 const&clickPos) noexcept {
|
||||
auto const pt = clickPoint(paneSize, clickPos);
|
||||
auto pt = clickPoint(paneSize, clickPos);
|
||||
auto const&s = m_model.activeSubSheet();
|
||||
pt.x = ox::min(pt.x, s.columns * TileWidth - 1);
|
||||
pt.y = ox::min(pt.y, s.rows * TileHeight - 1);
|
||||
auto const tileIdx = ptToIdx(pt, s.columns) / PixelsPerTile;
|
||||
m_model.insertTiles(m_model.activeSubSheetIdx(), tileIdx, 1);
|
||||
}
|
||||
|
@ -80,6 +80,11 @@ void TileSheetGrid::setBufferObject(
|
||||
}
|
||||
|
||||
void TileSheetGrid::setBufferObjects(ox::Vec2 const&paneSize, TileSheet::SubSheet const&subsheet) noexcept {
|
||||
if (subsheet.columns < 1 || subsheet.rows < 1) {
|
||||
m_bufferSet.elements.clear();
|
||||
m_bufferSet.vertices.clear();
|
||||
return;
|
||||
}
|
||||
auto const pixSize = pixelSize(paneSize);
|
||||
auto const set = [&](std::size_t i, ox::Point pt1, ox::Point pt2, Color32 c) {
|
||||
auto const vbo = &m_bufferSet.vertices[i * VertexVboLength];
|
||||
|
@ -51,7 +51,7 @@ ox::Error TileSheetPixels::buildShader() noexcept {
|
||||
return glutils::buildShaderProgram(s_programSrc).moveTo(m_shader);
|
||||
}
|
||||
|
||||
void TileSheetPixels::draw(bool update, ox::Vec2 const&scroll) noexcept {
|
||||
void TileSheetPixels::draw(bool const update, ox::Vec2 const&scroll) noexcept {
|
||||
glUseProgram(m_shader);
|
||||
glBindVertexArray(m_bufferSet.vao);
|
||||
if (update) {
|
||||
@ -117,6 +117,11 @@ void TileSheetPixels::setPixelBufferObject(
|
||||
void TileSheetPixels::setBufferObjects(ox::Vec2 const&paneSize) noexcept {
|
||||
// set buffer lengths
|
||||
auto const&subSheet = m_model.activeSubSheet();
|
||||
if (subSheet.columns < 1 || subSheet.rows < 1) {
|
||||
m_bufferSet.vertices.clear();
|
||||
m_bufferSet.elements.clear();
|
||||
return;
|
||||
}
|
||||
auto const&pal = m_model.pal();
|
||||
auto const width = subSheet.columns * TileWidth;
|
||||
auto const height = subSheet.rows * TileHeight;
|
||||
|
@ -66,10 +66,10 @@ static ox::Optional<size_t> getPixelIdx(
|
||||
return ox::Optional<size_t>{};
|
||||
}
|
||||
|
||||
ox::Optional<size_t> getTileIdx(TileSheet const&ts, SubSheetId const id) noexcept {
|
||||
size_t getTileIdx(TileSheet const&ts, SubSheetId const id) noexcept {
|
||||
size_t idx{};
|
||||
auto const out = getPixelIdx(ts.subsheet, id, idx, ts.bpp);
|
||||
return out ? ox::Optional<size_t>{ox::in_place, *out / PixelsPerTile} : out;
|
||||
return out.or_value(0) / PixelsPerTile;
|
||||
}
|
||||
|
||||
uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept {
|
||||
@ -355,12 +355,12 @@ ox::Result<SubSheetId> getIdFor(TileSheet const&ts, ox::StringViewCR path) noexc
|
||||
/**
|
||||
* Gets the offset in tiles of the desired subsheet.
|
||||
*/
|
||||
static ox::Result<uint32_t> getTileOffset(
|
||||
static ox::Result<unsigned> getTileOffset(
|
||||
TileSheet::SubSheet const&ss,
|
||||
ox::SpanView<ox::StringView> const&pNamePath,
|
||||
int8_t pBpp,
|
||||
std::size_t pIt = 0,
|
||||
uint32_t pCurrentTotal = 0) noexcept {
|
||||
unsigned pCurrentTotal = 0) noexcept {
|
||||
// pIt == pNamePath.size() - 1 &&
|
||||
if (ss.name != pNamePath[pIt]) {
|
||||
return ox::Error(2, "Wrong branch");
|
||||
@ -374,14 +374,12 @@ static ox::Result<uint32_t> getTileOffset(
|
||||
if (!err) {
|
||||
return offset;
|
||||
}
|
||||
// Possible bug? Shoud this be usinga a recursive version of
|
||||
// pixelCnt will count pixels in subsheets of sub as well.
|
||||
pCurrentTotal += pixelCnt(sub, pBpp) / PixelsPerTile;
|
||||
}
|
||||
return ox::Error(1, "SubSheet not found");
|
||||
}
|
||||
|
||||
ox::Result<uint32_t> getTileOffset(TileSheet const&ts, ox::StringViewCR pNamePath) noexcept {
|
||||
ox::Result<unsigned> getTileOffset(TileSheet const&ts, ox::StringViewCR pNamePath) noexcept {
|
||||
return core::getTileOffset(ts.subsheet, ox::split<8>(pNamePath, '.'), ts.bpp);
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ target_link_libraries(
|
||||
|
||||
target_compile_definitions(
|
||||
NostalgiaStudio PUBLIC
|
||||
OLYMPIC_APP_VERSION="dev build"
|
||||
OLYMPIC_APP_VERSION="d2024.12.3"
|
||||
)
|
||||
|
||||
install(
|
||||
|
@ -196,15 +196,15 @@ class AssetManager {
|
||||
template<typename T>
|
||||
class AssetTypeManager: public AssetTypeManagerBase {
|
||||
public:
|
||||
using Loader = std::function<ox::Result<T>(ox::StringViewCR assetId)>;
|
||||
using Loader = std::function<ox::Result<T>(ox::StringView assetId)>;
|
||||
private:
|
||||
Loader m_loader{};
|
||||
ox::HashMap<ox::String, ox::UPtr<AssetContainer<T>>> m_cache;
|
||||
|
||||
public:
|
||||
AssetTypeManager(Loader &&loader) noexcept: m_loader(std::move(loader)) {}
|
||||
AssetTypeManager(Loader loader) noexcept: m_loader(loader) {}
|
||||
|
||||
ox::Result<AssetRef<T>> getAsset(ox::StringViewCR assetId) const noexcept {
|
||||
ox::Result<AssetRef<T>> getAsset(ox::StringView const assetId) const noexcept {
|
||||
OX_REQUIRE(out, m_cache.at(assetId));
|
||||
if (!out || !*out) {
|
||||
return ox::Error(1, "asset is null");
|
||||
@ -212,7 +212,7 @@ class AssetManager {
|
||||
return AssetRef<T>(out->get());
|
||||
}
|
||||
|
||||
ox::Result<AssetRef<T>> loadAsset(ox::StringViewCR assetId) noexcept {
|
||||
ox::Result<AssetRef<T>> loadAsset(ox::StringView const assetId) noexcept {
|
||||
auto &p = m_cache[assetId];
|
||||
OX_REQUIRE_M(obj, m_loader(assetId));
|
||||
if (!p) {
|
||||
@ -224,7 +224,7 @@ class AssetManager {
|
||||
return AssetRef<T>(p.get());
|
||||
}
|
||||
|
||||
ox::Error reloadAsset(ox::StringViewCR assetId) noexcept {
|
||||
ox::Error reloadAsset(ox::StringView const assetId) noexcept {
|
||||
auto &p = m_cache[assetId];
|
||||
OX_REQUIRE_M(obj, m_loader(assetId));
|
||||
if (!p) {
|
||||
@ -247,7 +247,7 @@ class AssetManager {
|
||||
};
|
||||
|
||||
ox::HashMap<ox::String, ox::UPtr<AssetTypeManagerBase>> m_assetTypeManagers;
|
||||
ox::HashMap<ox::String, ox::Signal<ox::Error(ox::StringViewCR assetId)>> m_fileUpdated;
|
||||
ox::HashMap<ox::String, ox::Signal<ox::Error(ox::StringView assetId)>> m_fileUpdated;
|
||||
|
||||
template<typename T>
|
||||
ox::Result<AssetTypeManager<T>*> getTypeManager() noexcept {
|
||||
@ -273,18 +273,18 @@ class AssetManager {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ox::Result<AssetRef<T>> getAsset(ox::StringViewCR assetId) noexcept {
|
||||
ox::Result<AssetRef<T>> getAsset(ox::StringView assetId) noexcept {
|
||||
OX_REQUIRE(m, getTypeManager<T>());
|
||||
return m->getAsset(assetId);
|
||||
}
|
||||
|
||||
ox::Error reloadAsset(ox::StringViewCR assetId) noexcept {
|
||||
ox::Error reloadAsset(ox::StringView assetId) noexcept {
|
||||
m_fileUpdated[assetId].emit(assetId);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ox::Result<AssetRef<T>> loadAsset(ox::StringViewCR assetId) noexcept {
|
||||
ox::Result<AssetRef<T>> loadAsset(ox::StringView assetId) noexcept {
|
||||
OX_REQUIRE(m, getTypeManager<T>());
|
||||
OX_REQUIRE(out, m->loadAsset(assetId));
|
||||
m_fileUpdated[assetId].connect(m, &AssetTypeManager<T>::reloadAsset);
|
||||
|
@ -154,13 +154,12 @@ ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::UUID const&uuid) noexce
|
||||
}
|
||||
|
||||
ox::Error reloadAsset(keel::Context &ctx, ox::StringViewCR assetId) noexcept {
|
||||
ox::UUIDStr uuidStr;
|
||||
if (beginsWith(assetId, "uuid://")) {
|
||||
return ctx.assetManager.reloadAsset(substr(assetId, 7));
|
||||
} else {
|
||||
auto const [uuid, uuidErr] = getUuid(ctx, assetId);
|
||||
auto const [uuid, uuidErr] = getUuid(ctx, assetId);
|
||||
if (!uuidErr) {
|
||||
return ctx.assetManager.reloadAsset(uuidStr);
|
||||
return ctx.assetManager.reloadAsset(uuid.toString());
|
||||
} else {
|
||||
return ctx.assetManager.reloadAsset(assetId);
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ void NewProject::draw(studio::StudioContext &ctx) noexcept {
|
||||
|
||||
void NewProject::drawNewProjectName(studio::StudioContext &sctx) noexcept {
|
||||
drawWindow(sctx.tctx, &m_open, [this, &sctx] {
|
||||
ImGui::InputText("Name", m_projectName.data(), m_projectName.cap());
|
||||
ig::InputText("Name", m_projectName);
|
||||
ImGui::Text("Path: %s", m_projectPath.c_str());
|
||||
if (ImGui::Button("Browse")) {
|
||||
oxLogError(studio::chooseDirectory().moveTo(m_projectPath));
|
||||
|
@ -77,7 +77,7 @@ StudioUI::StudioUI(turbine::Context &ctx, ox::StringParam projectDataDir) noexce
|
||||
} else {
|
||||
oxErrf(
|
||||
"Could not open studio config file: {}: {} ({}:{})\n",
|
||||
err.errCode, toStr(err), err.src.file_name(), err.src.line());
|
||||
err.errCode, toStr(err), err.file, err.line);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -227,7 +227,7 @@ void StudioUI::drawTabs() noexcept {
|
||||
try {
|
||||
OX_THROW_ERROR(m_editors.erase(it).moveTo(it));
|
||||
} catch (ox::Exception const&ex) {
|
||||
oxErrf("Editor tab deletion failed: {} ({}:{})\n", ex.what(), ex.src.file_name(), ex.src.line());
|
||||
oxErrf("Editor tab deletion failed: {} ({}:{})\n", ex.what(), ex.file, ex.line);
|
||||
} catch (std::exception const&ex) {
|
||||
oxErrf("Editor tab deletion failed: {}\n", ex.what());
|
||||
}
|
||||
@ -379,7 +379,7 @@ ox::Error StudioUI::openFileActiveTab(ox::StringViewCR path, bool makeActiveTab)
|
||||
if constexpr(!ox::defines::Debug) {
|
||||
oxErrf("Could not open Editor: {}\n", toStr(err));
|
||||
} else {
|
||||
oxErrf("Could not open Editor: {} ({}:{})\n", err.errCode, err.src.file_name(), err.src.line());
|
||||
oxErrf("Could not open Editor: {} ({}:{})\n", err.errCode, err.file, err.line);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ namespace studio {
|
||||
class NoChangesException: public ox::Exception {
|
||||
public:
|
||||
inline NoChangesException(std::source_location sloc = std::source_location::current()):
|
||||
ox::Exception(1, "Command makes no changes.", sloc) {}
|
||||
ox::Exception(sloc.file_name(), sloc.line(), 1, "Command makes no changes.") {}
|
||||
};
|
||||
|
||||
class UndoCommand {
|
||||
|
@ -46,7 +46,7 @@ void BaseEditor::save() noexcept {
|
||||
setUnsavedChanges(false);
|
||||
} else {
|
||||
if constexpr(ox::defines::Debug) {
|
||||
oxErrorf("Could not save file {}: {} ({}:{})", itemPath(), toStr(err), err.src.file_name(), err.src.line());
|
||||
oxErrorf("Could not save file {}: {} ({}:{})", itemPath(), toStr(err), err.file, err.line);
|
||||
} else {
|
||||
oxErrorf("Could not save file {}: {}", itemPath(), toStr(err));
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ target_include_directories(
|
||||
)
|
||||
|
||||
target_sources(
|
||||
Turbine PRIVATE
|
||||
Turbine PUBLIC
|
||||
turbine.cpp
|
||||
)
|
||||
|
||||
|
Reference in New Issue
Block a user