Compare commits
17 Commits
461e3d61ef
...
e2d5090f44
Author | SHA1 | Date | |
---|---|---|---|
e2d5090f44 | |||
b818c1e3d6 | |||
706f5b345a | |||
22a7ff74ce | |||
d8153e71e1 | |||
4077f0bddc | |||
ad412177ab | |||
1dddf4ad9d | |||
31e9af032a | |||
716b3d6022 | |||
9b36381b00 | |||
839a791ddd | |||
0d040ad752 | |||
b506c5defb | |||
26d6143006 | |||
44f45e64e9 | |||
79d255b63f |
2
deps/buildcore/base.cmake
vendored
2
deps/buildcore/base.cmake
vendored
@ -44,7 +44,7 @@ else()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat=2")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wmissing-field-initializers")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor")
|
||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnull-dereference")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-null-dereference")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wold-style-cast")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Woverloaded-virtual")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
|
||||
|
2
deps/ox/CMakeLists.txt
vendored
2
deps/ox/CMakeLists.txt
vendored
@ -56,7 +56,7 @@ if(NOT MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat=2")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wmissing-field-initializers")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnull-dereference")
|
||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnull-dereference")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wold-style-cast")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Woverloaded-virtual")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
|
||||
|
2
deps/ox/src/ox/mc/write.cpp
vendored
2
deps/ox/src/ox/mc/write.cpp
vendored
@ -15,4 +15,6 @@
|
||||
|
||||
namespace ox {
|
||||
|
||||
template class ModelHandlerInterface<MetalClawWriter>;
|
||||
|
||||
}
|
||||
|
20
deps/ox/src/ox/mc/write.hpp
vendored
20
deps/ox/src/ox/mc/write.hpp
vendored
@ -106,6 +106,22 @@ class MetalClawWriter {
|
||||
constexpr void setTypeInfo(const char *name = T::TypeName, int version = T::TypeVersion,
|
||||
const Vector<String>& = {}, int fields = ModelFieldCount_v<T>) noexcept;
|
||||
|
||||
/**
|
||||
* stringLength is not implemented in MetalClawWriter
|
||||
*/
|
||||
[[nodiscard]]
|
||||
constexpr auto stringLength(const char*) noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* stringLength is not implemented in MetalClawWriter
|
||||
*/
|
||||
[[nodiscard]]
|
||||
constexpr auto arrayLength(const char*, bool = true) noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t size() const noexcept;
|
||||
|
||||
@ -134,6 +150,8 @@ class MetalClawWriter {
|
||||
|
||||
};
|
||||
|
||||
extern template class ModelHandlerInterface<MetalClawWriter>;
|
||||
|
||||
constexpr MetalClawWriter::MetalClawWriter(uint8_t *buff, std::size_t buffLen, int unionIdx) noexcept:
|
||||
m_fieldPresence(buff, buffLen),
|
||||
m_unionIdx(unionIdx),
|
||||
@ -284,7 +302,7 @@ constexpr Error MetalClawWriter::field(const char*, T *val) noexcept {
|
||||
bool fieldSet = false;
|
||||
if (val && (m_unionIdx == -1 || m_unionIdx == m_field)) {
|
||||
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt);
|
||||
ModelHandlerInterface handler{&writer};
|
||||
ModelHandlerInterface<MetalClawWriter> handler{&writer};
|
||||
oxReturnError(model(&handler, val));
|
||||
if (static_cast<std::size_t>(writer.m_fieldPresence.getMaxLen()) < writer.m_buffIt) {
|
||||
m_buffIt += writer.m_buffIt;
|
||||
|
4
deps/ox/src/ox/model/desctypes.hpp
vendored
4
deps/ox/src/ox/model/desctypes.hpp
vendored
@ -30,12 +30,12 @@ static constexpr auto buildTypeId(CRStringView name, int version,
|
||||
const TypeParamPack &typeParams) noexcept {
|
||||
String tp;
|
||||
if (typeParams.size()) {
|
||||
tp = "<";
|
||||
tp = "#";
|
||||
for (const auto &p : typeParams) {
|
||||
tp += p + ",";
|
||||
}
|
||||
tp = tp.substr(0, tp.len() - 1);
|
||||
tp += ">";
|
||||
tp += "#";
|
||||
}
|
||||
return ox::sfmt("{}{};{}", name, tp, version);
|
||||
}
|
||||
|
94
deps/ox/src/ox/model/modelvalue.hpp
vendored
94
deps/ox/src/ox/model/modelvalue.hpp
vendored
@ -13,6 +13,7 @@
|
||||
#include <ox/std/string.hpp>
|
||||
#include <ox/std/trace.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
#include <ox/std/utility.hpp>
|
||||
#include <ox/std/vector.hpp>
|
||||
|
||||
#include "def.hpp"
|
||||
@ -279,6 +280,11 @@ class ModelValueVector {
|
||||
return m_vec.begin();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
auto begin() const noexcept {
|
||||
return m_vec.cbegin();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
auto cbegin() const noexcept {
|
||||
return m_vec.cbegin();
|
||||
@ -299,6 +305,11 @@ class ModelValueVector {
|
||||
return m_vec.end();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
auto end() const noexcept {
|
||||
return m_vec.cend();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
auto cend() const noexcept {
|
||||
return m_vec.cend();
|
||||
@ -321,18 +332,17 @@ consteval bool isVector(const ModelValueVector*) noexcept {
|
||||
}
|
||||
|
||||
class ModelObject {
|
||||
protected:
|
||||
public:
|
||||
struct Field {
|
||||
String name;
|
||||
ModelValue value;
|
||||
};
|
||||
protected:
|
||||
oxModelFriend(ModelObject);
|
||||
friend ModelValue;
|
||||
Vector<UniquePtr<Field>> m_fieldsOrder;
|
||||
HashMap<String, ModelValue*> m_fields;
|
||||
const DescriptorType *m_type = nullptr;
|
||||
String m_typeName;
|
||||
int m_typeVersion = 0;
|
||||
|
||||
public:
|
||||
constexpr ModelObject() noexcept = default;
|
||||
@ -343,16 +353,12 @@ class ModelObject {
|
||||
m_fields[field->name] = &field->value;
|
||||
}
|
||||
m_type = other.m_type;
|
||||
m_typeName = other.m_typeName;
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
}
|
||||
|
||||
constexpr ModelObject(ModelObject &&other) noexcept {
|
||||
m_fields = std::move(other.m_fields);
|
||||
m_type = other.m_type;
|
||||
m_fieldsOrder = std::move(other.m_fieldsOrder);
|
||||
m_typeName = std::move(other.m_typeName);
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@ -424,8 +430,6 @@ class ModelObject {
|
||||
m_fields[field->name] = &field->value;
|
||||
}
|
||||
m_type = other.m_type;
|
||||
m_typeName = other.m_typeName;
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -436,17 +440,35 @@ class ModelObject {
|
||||
m_type = other.m_type;
|
||||
m_fields = std::move(other.m_fields);
|
||||
m_fieldsOrder = std::move(other.m_fieldsOrder);
|
||||
m_typeName = std::move(other.m_typeName);
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr auto &operator[](const std::size_t &i) noexcept {
|
||||
return *m_fieldsOrder[i];
|
||||
template<typename T>
|
||||
constexpr auto set(const std::size_t &i, T &&val) noexcept {
|
||||
auto &f = *m_fieldsOrder[i];
|
||||
f = val;
|
||||
}
|
||||
|
||||
constexpr Result<const ModelValue*> get(const String &k) const noexcept {
|
||||
if (m_fields.contains(k)) {
|
||||
return *m_fields.at(k).value;
|
||||
}
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error set(const String &k, T &&val) noexcept {
|
||||
oxRequire(t, m_fields.at(k));
|
||||
*t = ox::forward<T>(val);
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr auto &operator[](const String &k) noexcept {
|
||||
return *m_fields[k];
|
||||
auto [v, err] = m_fields.at(k);
|
||||
if (err) [[unlikely]] {
|
||||
oxPanic(err, ox::sfmt("field {} does not exist in type {}", k, buildTypeId(*m_type)).c_str());
|
||||
}
|
||||
return **v;
|
||||
}
|
||||
|
||||
constexpr auto &operator[](const std::size_t i) noexcept {
|
||||
@ -454,13 +476,13 @@ class ModelObject {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr StringView typeName() const noexcept {
|
||||
return m_typeName;
|
||||
constexpr CRString typeName() const noexcept {
|
||||
return m_type->typeName;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int typeVersion() const noexcept {
|
||||
return m_typeVersion;
|
||||
return m_type->typeVersion;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@ -473,8 +495,6 @@ class ModelObject {
|
||||
return OxError(1, "Cannot load a non-struct type to ModelObject");
|
||||
}
|
||||
m_type = type;
|
||||
m_typeName = type->typeName;
|
||||
m_typeVersion = type->typeVersion;
|
||||
for (const auto &f : type->fieldList) {
|
||||
auto field = make_unique<Field>();
|
||||
field->name = f.fieldName;
|
||||
@ -498,8 +518,7 @@ class ModelUnion {
|
||||
friend ModelValue;
|
||||
Vector<UniquePtr<Field>> m_fieldsOrder;
|
||||
HashMap<String, Field*> m_fields;
|
||||
String m_typeName;
|
||||
int m_typeVersion = 0;
|
||||
const DescriptorType *m_type = nullptr;
|
||||
int m_unionIdx = -1;
|
||||
|
||||
private:
|
||||
@ -512,16 +531,12 @@ class ModelUnion {
|
||||
m_fields[field->name] = field.get();
|
||||
++i;
|
||||
}
|
||||
m_typeName = other.m_typeName;
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
m_unionIdx = other.m_unionIdx;
|
||||
}
|
||||
|
||||
constexpr ModelUnion(ModelUnion &&other) noexcept {
|
||||
m_fieldsOrder = std::move(other.m_fieldsOrder);
|
||||
m_fields = std::move(other.m_fields);
|
||||
m_typeName = std::move(other.m_typeName);
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
m_unionIdx = other.m_unionIdx;
|
||||
}
|
||||
|
||||
@ -536,7 +551,11 @@ class ModelUnion {
|
||||
}
|
||||
|
||||
constexpr auto &operator[](const String &k) noexcept {
|
||||
return m_fields[k]->value;
|
||||
const auto [v, err] = m_fields.at(k);
|
||||
if (err) [[unlikely]] {
|
||||
oxPanic(err, ox::sfmt("field {} does not exist in type {}", k, buildTypeId(*m_type)).c_str());
|
||||
}
|
||||
return (*v)->value;
|
||||
}
|
||||
|
||||
constexpr auto &operator[](const std::size_t i) noexcept {
|
||||
@ -558,13 +577,17 @@ class ModelUnion {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ModelValue &get(std::size_t i) noexcept {
|
||||
return m_fieldsOrder[i]->value;
|
||||
constexpr Result<const ModelValue*> get(std::size_t i) const noexcept {
|
||||
if (i < m_fieldsOrder.size()) {
|
||||
return &m_fieldsOrder[i]->value;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ModelValue &get(const String &k) noexcept {
|
||||
return (*m_fields.at(k).value)->value;
|
||||
constexpr Result<const ModelValue*> get(const String &k) const noexcept {
|
||||
oxRequire(t, m_fields.at(k));
|
||||
return &(*t)->value;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@ -580,12 +603,12 @@ class ModelUnion {
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const String &typeName() const noexcept {
|
||||
return m_typeName;
|
||||
return m_type->typeName;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int typeVersion() const noexcept {
|
||||
return m_typeVersion;
|
||||
return m_type->typeVersion;
|
||||
}
|
||||
|
||||
constexpr Error setType(const DescriptorType *type) noexcept {
|
||||
@ -594,8 +617,7 @@ class ModelUnion {
|
||||
}
|
||||
m_fields.clear();
|
||||
m_fieldsOrder.clear();
|
||||
m_typeName = type->typeName;
|
||||
m_typeVersion = type->typeVersion;
|
||||
m_type = type;
|
||||
for (auto i = 0; const auto &f : type->fieldList) {
|
||||
auto field = make_unique<Field>();
|
||||
field->name = f.fieldName;
|
||||
@ -744,7 +766,7 @@ constexpr std::size_t alignOf(const ModelValue &t) noexcept {
|
||||
}
|
||||
|
||||
constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept {
|
||||
h->template setTypeInfo<ModelObject>(obj->m_typeName.c_str(), obj->m_typeVersion, {}, static_cast<int>(obj->m_fieldsOrder.size()));
|
||||
h->template setTypeInfo<ModelObject>(obj->typeName().c_str(), obj->typeVersion(), {}, static_cast<int>(obj->m_fieldsOrder.size()));
|
||||
for (auto &f : obj->m_fieldsOrder) {
|
||||
oxReturnError(h->field(f->name.c_str(), &f->value));
|
||||
}
|
||||
@ -752,7 +774,7 @@ constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept {
|
||||
}
|
||||
|
||||
constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept {
|
||||
h->template setTypeInfo<ModelUnion>(obj->m_typeName.c_str(), obj->m_typeVersion, {}, static_cast<int>(obj->m_fieldsOrder.size()));
|
||||
h->template setTypeInfo<ModelUnion>(obj->typeName().c_str(), obj->typeVersion(), {}, static_cast<int>(obj->m_fieldsOrder.size()));
|
||||
for (auto &f : obj->m_fieldsOrder) {
|
||||
oxReturnError(h->field(f->name.c_str(), &f->value));
|
||||
}
|
||||
|
2
deps/ox/src/ox/model/typenamecatcher.hpp
vendored
2
deps/ox/src/ox/model/typenamecatcher.hpp
vendored
@ -25,7 +25,7 @@ struct TypeNameCatcher {
|
||||
constexpr TypeNameCatcher() noexcept = default;
|
||||
|
||||
template<typename T = std::nullptr_t>
|
||||
constexpr void setTypeInfo(const char *n = T::TypeName, const Vector<String>& = {}, int v = 0) noexcept {
|
||||
constexpr void setTypeInfo(const char *n = T::TypeName, int v = T::TypeVersion, const Vector<String>& = {}, int = 0) noexcept {
|
||||
this->name = n;
|
||||
this->version = v;
|
||||
}
|
||||
|
8
deps/ox/src/ox/model/typestore.hpp
vendored
8
deps/ox/src/ox/model/typestore.hpp
vendored
@ -29,7 +29,7 @@ class TypeStore {
|
||||
constexpr virtual ~TypeStore() noexcept = default;
|
||||
|
||||
constexpr Result<const DescriptorType*> get(const auto &name, int typeVersion,
|
||||
const Vector<String> &typeParams) const noexcept {
|
||||
const TypeParamPack &typeParams) const noexcept {
|
||||
const auto typeId = buildTypeId(name, typeVersion, typeParams);
|
||||
oxRequire(out, m_cache.at(typeId));
|
||||
return out->get();
|
||||
@ -71,7 +71,7 @@ class TypeStore {
|
||||
}
|
||||
|
||||
constexpr Result<const DescriptorType*> getLoad(const auto &typeName, auto typeVersion,
|
||||
const Vector<String> &typeParams = {}) noexcept {
|
||||
const TypeParamPack &typeParams = {}) noexcept {
|
||||
return getLoad(buildTypeId(typeName, typeVersion, typeParams));
|
||||
}
|
||||
|
||||
@ -95,7 +95,7 @@ class TypeStore {
|
||||
const auto &keys = m_cache.keys();
|
||||
ox::Vector<DescriptorType*> descs;
|
||||
for (const auto &k : keys) {
|
||||
descs.emplace_back(m_cache.at(k).value->get());
|
||||
descs.emplace_back(m_cache.at(k).unwrap()->get());
|
||||
}
|
||||
return descs;
|
||||
}
|
||||
@ -106,7 +106,7 @@ class TypeStore {
|
||||
}
|
||||
|
||||
Result<UniquePtr<DescriptorType>> loadDescriptor(ox::CRStringView name, int version,
|
||||
const Vector<String> &typeParams) noexcept {
|
||||
const ox::TypeParamPack &typeParams) noexcept {
|
||||
const auto typeId = buildTypeId(name, version, typeParams);
|
||||
return loadDescriptor(typeId);
|
||||
}
|
||||
|
38
deps/ox/src/ox/oc/test/tests.cpp
vendored
38
deps/ox/src/ox/oc/test/tests.cpp
vendored
@ -14,6 +14,14 @@
|
||||
#include <ox/oc/oc.hpp>
|
||||
#include <ox/std/std.hpp>
|
||||
|
||||
template<typename T>
|
||||
union U {
|
||||
T t;
|
||||
int i;
|
||||
};
|
||||
|
||||
U<short> u;
|
||||
|
||||
union TestUnion {
|
||||
static constexpr auto TypeName = "TestUnion";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
@ -204,26 +212,26 @@ const std::map<std::string_view, ox::Error(*)()> tests = {
|
||||
ox::ModelObject testOut;
|
||||
oxReturnError(testOut.setType(type.value));
|
||||
oxAssert(ox::readOC(dataBuff.data(), dataBuff.size(), &testOut), "Data read failed");
|
||||
oxAssert(testOut["Int"].get<int>() == testIn.Int, "testOut.Int failed");
|
||||
oxAssert(testOut["Bool"].get<bool>() == testIn.Bool, "testOut.Bool failed");
|
||||
oxAssert(testOut["String"].get<ox::String>() == testIn.String, "testOut.String failed");
|
||||
auto &testOutStruct = testOut["Struct"].get<ox::ModelObject>();
|
||||
auto &testOutUnion = testOut["Union"].get<ox::ModelUnion>();
|
||||
auto &testOutList = testOut["List"].get<ox::ModelValueVector>();
|
||||
auto testOutStructCopy = testOut["Struct"].get<ox::ModelObject>();
|
||||
auto testOutUnionCopy = testOut["Union"].get<ox::ModelUnion>();
|
||||
auto testOutListCopy = testOut["List"].get<ox::ModelValueVector>();
|
||||
oxAssert(testOut.get("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed");
|
||||
oxAssert(testOut.get("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed");
|
||||
oxAssert(testOut.get("String").unwrap()->get<ox::String>() == testIn.String, "testOut.String failed");
|
||||
auto &testOutStruct = testOut.get("Struct").unwrap()->get<ox::ModelObject>();
|
||||
auto &testOutUnion = testOut.get("Union").unwrap()->get<ox::ModelUnion>();
|
||||
auto &testOutList = testOut.get("List").unwrap()->get<ox::ModelValueVector>();
|
||||
auto testOutStructCopy = testOut.get("Struct").unwrap()->get<ox::ModelObject>();
|
||||
auto testOutUnionCopy = testOut.get("Union").unwrap()->get<ox::ModelUnion>();
|
||||
auto testOutListCopy = testOut.get("List").unwrap()->get<ox::ModelValueVector>();
|
||||
oxAssert(testOutStruct.typeName() == TestStructNest::TypeName, "ModelObject TypeName failed");
|
||||
oxAssert(testOutStruct.typeVersion() == TestStructNest::TypeVersion, "ModelObject TypeVersion failed");
|
||||
oxAssert(testOutStruct["Bool"].get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool failed");
|
||||
oxAssert(testOutStruct["String"].get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String failed");
|
||||
oxAssert(testOut["unionIdx"].get<int>() == testIn.unionIdx, "testOut.unionIdx failed");
|
||||
oxAssert(testOutStruct.get("Bool").unwrap()->get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool failed");
|
||||
oxAssert(testOutStruct.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String failed");
|
||||
oxAssert(testOut.get("unionIdx").unwrap()->get<int>() == testIn.unionIdx, "testOut.unionIdx failed");
|
||||
oxAssert(testOutUnion.unionIdx() == testIn.unionIdx, "testOut.Union idx wrong");
|
||||
oxAssert(testOutUnion["Int"].get<uint32_t>() == testIn.Union.Int, "testOut.Union.Int failed");
|
||||
oxAssert(testOutUnion.get("Int").unwrap()->get<uint32_t>() == testIn.Union.Int, "testOut.Union.Int failed");
|
||||
oxAssert(testOutList[0].get<uint32_t>() == testIn.List[0], "testOut.List[0] failed");
|
||||
oxAssert(testOutList[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] failed");
|
||||
oxAssert(testOutStructCopy["Bool"].get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool (copy) failed");
|
||||
oxAssert(testOutStructCopy["String"].get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed");
|
||||
oxAssert(testOutStructCopy.get("Bool").unwrap()->get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool (copy) failed");
|
||||
oxAssert(testOutStructCopy.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed");
|
||||
oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed");
|
||||
oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed");
|
||||
return OxError(0);
|
||||
|
7
deps/ox/src/ox/std/CMakeLists.txt
vendored
7
deps/ox/src/ox/std/CMakeLists.txt
vendored
@ -57,9 +57,14 @@ target_compile_definitions(
|
||||
$<$<BOOL:${OX_NODEBUG}>:OX_NODEBUG>
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
if(NOT WIN32)
|
||||
target_link_libraries(
|
||||
OxStd PUBLIC
|
||||
$<$<CXX_COMPILER_ID:GNU>:$<$<BOOL:${OX_USE_STDLIB}>:dl>>
|
||||
)
|
||||
endif()
|
||||
target_link_libraries(
|
||||
OxStd PUBLIC
|
||||
$<$<CXX_COMPILER_ID:GNU>:gcc>
|
||||
OxTraceHook
|
||||
)
|
||||
|
4
deps/ox/src/ox/std/memops.hpp
vendored
4
deps/ox/src/ox/std/memops.hpp
vendored
@ -68,6 +68,10 @@ constexpr void *ox_memset(void *ptr, int val, std::size_t size) noexcept {
|
||||
|
||||
namespace ox {
|
||||
|
||||
constexpr void *memcpy(void *dest, const void *src, std::size_t size) noexcept {
|
||||
return ox_memcpy(dest, src, size);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void *memsetElements(T *ptr, T val, std::size_t elements) noexcept {
|
||||
return memset(ptr, val, elements * sizeof(T));
|
||||
|
3
deps/ox/src/ox/std/memory.hpp
vendored
3
deps/ox/src/ox/std/memory.hpp
vendored
@ -247,6 +247,9 @@ class UniquePtr {
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using UPtr = UniquePtr<T>;
|
||||
|
||||
template<typename T>
|
||||
constexpr bool operator==(const UniquePtr<T> &p1, const UniquePtr<T> &p2) noexcept {
|
||||
return p1.get() == p2.get();
|
||||
|
19
deps/ox/src/ox/std/new.hpp
vendored
19
deps/ox/src/ox/std/new.hpp
vendored
@ -8,13 +8,15 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "error.hpp"
|
||||
#include "defines.hpp"
|
||||
#include "types.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <malloc.h>
|
||||
#elif OX_USE_STDLIB
|
||||
#include <stdlib.h>
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
|
||||
|
||||
@ -33,6 +35,21 @@ constexpr void *operator new[](std::size_t, void *addr) noexcept {
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename T, typename ...Args>
|
||||
[[nodiscard]]
|
||||
constexpr T *make(Args &&...args) noexcept {
|
||||
#ifdef __cpp_exceptions
|
||||
try {
|
||||
return new T(ox::forward<Args>(args)...);
|
||||
} catch (...) {
|
||||
oxPanic(OxError(1, "Allocation or constructor failed"), "Allocation or constructor failed");
|
||||
return nullptr;
|
||||
}
|
||||
#else
|
||||
return new T(ox::forward<Args>(args)...);
|
||||
#endif
|
||||
}
|
||||
|
||||
constexpr auto MallocaStackLimit = defines::UseStdLib ? 1024 : 0;
|
||||
|
||||
/**
|
||||
|
6
deps/ox/src/ox/std/stacktrace.cpp
vendored
6
deps/ox/src/ox/std/stacktrace.cpp
vendored
@ -9,8 +9,10 @@
|
||||
#if defined(OX_USE_STDLIB) && __has_include(<unistd.h>)
|
||||
#include <iostream>
|
||||
|
||||
#if __has_include(<execinfo.h>)
|
||||
#include <execinfo.h>
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#if __has_include(<cxxabi.h>)
|
||||
#include <cxxabi.h>
|
||||
@ -30,7 +32,7 @@ static auto symbolicate([[maybe_unused]]char **frames,
|
||||
[[maybe_unused]]const char *linePrefix) {
|
||||
using StrT = BasicString<100>;
|
||||
Vector<StrT, 30> out;
|
||||
#if __has_include(<cxxabi.h>)
|
||||
#if __has_include(<cxxabi.h>) && __has_include(<execinfo.h>)
|
||||
for (auto i = 0u; i < symbolsLen; ++i) {
|
||||
Dl_info info;
|
||||
if (dladdr(frames[i], &info) && info.dli_sname) {
|
||||
@ -49,7 +51,7 @@ static auto symbolicate([[maybe_unused]]char **frames,
|
||||
#endif // defined(OX_USE_STDLIB) && __has_include(<unistd.h>)
|
||||
|
||||
void printStackTrace([[maybe_unused]]unsigned shave) noexcept {
|
||||
#if defined(OX_USE_STDLIB) && __has_include(<unistd.h>)
|
||||
#if defined(OX_USE_STDLIB) && __has_include(<unistd.h>) && __has_include(<execinfo.h>)
|
||||
constexpr auto FrameCnt = 100;
|
||||
Vector<void*, FrameCnt> frames(FrameCnt);
|
||||
frames.resize(static_cast<std::size_t>(backtrace(frames.data(), static_cast<int>(frames.size()))));
|
||||
|
151
deps/ox/src/ox/std/stringview.hpp
vendored
151
deps/ox/src/ox/std/stringview.hpp
vendored
@ -8,8 +8,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "iterator.hpp"
|
||||
#include "strops.hpp"
|
||||
#include "types.hpp"
|
||||
#include "bit.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
@ -20,6 +22,111 @@ template<std::size_t buffLen>
|
||||
class BasicString;
|
||||
|
||||
class StringView {
|
||||
public:
|
||||
template<typename RefType = char&, typename PtrType = char*, bool reverse = false>
|
||||
struct iterator: public Iterator<std::bidirectional_iterator_tag, char> {
|
||||
private:
|
||||
PtrType m_t = nullptr;
|
||||
std::size_t m_offset = 0;
|
||||
std::size_t m_max = 0;
|
||||
|
||||
public:
|
||||
constexpr iterator() noexcept = default;
|
||||
|
||||
constexpr iterator(PtrType t, std::size_t offset, std::size_t max) noexcept {
|
||||
m_t = t;
|
||||
m_offset = offset;
|
||||
m_max = max;
|
||||
}
|
||||
|
||||
constexpr auto offset() const noexcept {
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
constexpr iterator operator+(std::size_t s) const noexcept {
|
||||
if constexpr(reverse) {
|
||||
return iterator(m_t, max<std::size_t>(m_offset - s, 0), m_max);
|
||||
} else {
|
||||
return iterator(m_t, min<std::size_t>(m_offset + s, m_max), m_max);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr auto operator-(const iterator &other) const noexcept {
|
||||
if constexpr(reverse) {
|
||||
return m_offset + other.m_offset;
|
||||
} else {
|
||||
return m_offset - other.m_offset;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr iterator operator-(std::size_t s) const noexcept {
|
||||
if constexpr(reverse) {
|
||||
return iterator(m_t, min<std::size_t>(m_offset + s, m_max), m_max);
|
||||
} else {
|
||||
return iterator(m_t, max<std::size_t>(m_offset - s, 0), m_max);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr iterator &operator+=(std::size_t s) noexcept {
|
||||
if constexpr(reverse) {
|
||||
m_offset = max<std::size_t>(m_offset - s, 0);
|
||||
} else {
|
||||
m_offset = min(m_offset + s, m_max);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr iterator &operator-=(std::size_t s) noexcept {
|
||||
if constexpr(reverse) {
|
||||
m_offset = min(m_offset + s, m_max);
|
||||
} else {
|
||||
m_offset = max<std::size_t>(m_offset - s, 0);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr iterator &operator++() noexcept {
|
||||
return operator+=(1);
|
||||
}
|
||||
|
||||
constexpr iterator &operator--() noexcept {
|
||||
return operator-=(1);
|
||||
}
|
||||
|
||||
constexpr RefType operator*() const noexcept {
|
||||
return m_t[m_offset];
|
||||
}
|
||||
|
||||
constexpr RefType operator[](std::size_t s) const noexcept {
|
||||
return m_t[s];
|
||||
}
|
||||
|
||||
constexpr bool operator<(const iterator &other) const noexcept {
|
||||
return m_offset < other.m_offset;
|
||||
}
|
||||
|
||||
constexpr bool operator>(const iterator &other) const noexcept {
|
||||
return m_offset > other.m_offset;
|
||||
}
|
||||
|
||||
constexpr bool operator<=(const iterator &other) const noexcept {
|
||||
return m_offset <= other.m_offset;
|
||||
}
|
||||
|
||||
constexpr bool operator>=(const iterator &other) const noexcept {
|
||||
return m_offset >= other.m_offset;
|
||||
}
|
||||
|
||||
constexpr bool operator==(const iterator &other) const noexcept {
|
||||
return m_t == other.m_t && m_offset == other.m_offset && m_max == other.m_max;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const iterator &other) const noexcept {
|
||||
return m_t != other.m_t || m_offset != other.m_offset || m_max != other.m_max;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
const char *m_str = nullptr;
|
||||
std::size_t m_len = 0;
|
||||
@ -41,6 +148,46 @@ class StringView {
|
||||
|
||||
constexpr StringView(const char *str, std::size_t len) noexcept: m_str(str), m_len(len) {}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*> begin() const noexcept {
|
||||
return {m_str, 0, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*> end() const noexcept {
|
||||
return {m_str, m_len, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*> cbegin() const noexcept {
|
||||
return {m_str, 0, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*> cend() const noexcept {
|
||||
return {m_str, m_len, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*, true> crbegin() const noexcept {
|
||||
return {m_str, m_len - 1, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*, true> crend() const noexcept {
|
||||
return {m_str, MaxValue<std::size_t>, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*, true> rbegin() const noexcept {
|
||||
return {m_str, m_len - 1, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr iterator<const char&, const char*, true> rend() const noexcept {
|
||||
return {m_str, MaxValue<std::size_t>, m_len};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto bytes() const noexcept {
|
||||
return m_len;
|
||||
@ -66,6 +213,10 @@ class StringView {
|
||||
return m_str[m_len - 1];
|
||||
}
|
||||
|
||||
constexpr auto substr(std::size_t pos) const noexcept {
|
||||
return StringView(m_str + pos, m_len - pos);
|
||||
}
|
||||
|
||||
constexpr auto operator[](std::size_t i) const noexcept {
|
||||
return m_str[i];
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ O1;net.drinkingtea.ox.TypeDescriptor;1;{
|
||||
[
|
||||
{
|
||||
"fieldName" : "name",
|
||||
"typeId" : "net.drinkingtea.ox.BasicString<8>;1"
|
||||
"typeId" : "net.drinkingtea.ox.BasicString#8#;1"
|
||||
},
|
||||
{
|
||||
"fieldName" : "rows",
|
||||
|
BIN
sample_project/Palettes/.npal
Normal file
BIN
sample_project/Palettes/.npal
Normal file
Binary file not shown.
@ -17,7 +17,7 @@ ox::Result<ox::UniquePtr<Context>> init(ox::UniquePtr<ox::FileSystem> fs, const
|
||||
auto ctx = ox::make_unique<Context>();
|
||||
ctx->rom = std::move(fs);
|
||||
ctx->appName = appName;
|
||||
const auto id = new GlfwImplData;
|
||||
const auto id = ox::make<GlfwImplData>();
|
||||
ctx->setWindowerData(id);
|
||||
using namespace std::chrono;
|
||||
id->startTime = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
|
||||
|
@ -16,7 +16,7 @@ ox::Vector<studio::EditorMaker> Module::editors(core::Context *ctx) noexcept {
|
||||
{"ng"},
|
||||
[ctx](const ox::String &path) -> ox::Result<studio::BaseEditor*> {
|
||||
try {
|
||||
return new TileSheetEditorImGui(ctx, path);
|
||||
return ox::make<TileSheetEditorImGui>(ctx, path);
|
||||
} catch (const ox::Exception &ex) {
|
||||
return ex.toError();
|
||||
}
|
||||
@ -33,8 +33,8 @@ 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"));
|
||||
out.emplace_back(ox::make<studio::ItemMakerT<core::TileSheet>>("Tile Sheet", "TileSheets", "ng"));
|
||||
out.emplace_back(ox::make<studio::ItemMakerT<core::Palette>>("Palette", "Palettes", "npal"));
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ ox::Result<PaletteEditorImGui*> PaletteEditorImGui::make(Context *ctx, const ox:
|
||||
const auto lastSlash = std::find(out->m_itemPath.rbegin(), out->m_itemPath.rend(), '/').offset();
|
||||
out->m_itemName = out->m_itemPath.substr(lastSlash + 1);
|
||||
oxRequire(pal, core::readObj<Palette>(out->m_ctx, out->m_itemPath));
|
||||
out->m_pal = *pal.get();
|
||||
out->m_pal = *pal;
|
||||
return out.release();
|
||||
}
|
||||
|
||||
@ -45,20 +45,20 @@ void PaletteEditorImGui::draw(core::Context*) noexcept {
|
||||
{
|
||||
const auto sz = ImVec2(70, 24);
|
||||
if (ImGui::Button("Add", sz)) {
|
||||
undoStack()->push(new AddColorCommand(&m_pal, 0, m_pal.colors.size()));
|
||||
undoStack()->push(ox::make<AddColorCommand>(&m_pal, 0, m_pal.colors.size()));
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginDisabled(m_selectedRow >= m_pal.colors.size());
|
||||
{
|
||||
if (ImGui::Button("Remove", sz)) {
|
||||
undoStack()->push(new RemoveColorCommand(&m_pal, m_pal.colors[static_cast<std::size_t>(m_selectedRow)], m_selectedRow));
|
||||
undoStack()->push(ox::make<RemoveColorCommand>(&m_pal, m_pal.colors[static_cast<std::size_t>(m_selectedRow)], m_selectedRow));
|
||||
m_selectedRow = ox::min(m_pal.colors.size() - 1, m_selectedRow);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginDisabled(m_selectedRow <= 0);
|
||||
{
|
||||
if (ImGui::Button("Move Up", sz)) {
|
||||
undoStack()->push(new MoveColorCommand(&m_pal, m_selectedRow, -1));
|
||||
undoStack()->push(ox::make<MoveColorCommand>(&m_pal, m_selectedRow, -1));
|
||||
--m_selectedRow;
|
||||
}
|
||||
}
|
||||
@ -67,7 +67,7 @@ void PaletteEditorImGui::draw(core::Context*) noexcept {
|
||||
ImGui::BeginDisabled(m_selectedRow >= m_pal.colors.size() - 1);
|
||||
{
|
||||
if (ImGui::Button("Move Down", sz)) {
|
||||
undoStack()->push(new MoveColorCommand(&m_pal, m_selectedRow, 1));
|
||||
undoStack()->push(ox::make<MoveColorCommand>(&m_pal, m_selectedRow, 1));
|
||||
++m_selectedRow;
|
||||
}
|
||||
}
|
||||
@ -127,7 +127,7 @@ void PaletteEditorImGui::draw(core::Context*) noexcept {
|
||||
ImGui::InputInt("Blue", &b, 1, 5);
|
||||
const auto newColor = color16(r, g, b, a);
|
||||
if (c != newColor) {
|
||||
undoStack()->push(new UpdateColorCommand(&m_pal, m_selectedRow, c, newColor));
|
||||
undoStack()->push(ox::make<UpdateColorCommand>(&m_pal, m_selectedRow, c, newColor));
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
@ -197,11 +197,10 @@ void TileSheetEditorImGui::drawSubsheetSelector(TileSheet::SubSheet *subsheet, T
|
||||
const auto flags = ImGuiTreeNodeFlags_SpanFullWidth
|
||||
| ImGuiTreeNodeFlags_OpenOnArrow
|
||||
| ImGuiTreeNodeFlags_DefaultOpen
|
||||
| (subsheet->subsheets.size() ? 0 : ImGuiTreeNodeFlags_Leaf)
|
||||
| (subsheet->subsheets.empty() ? ImGuiTreeNodeFlags_Leaf : 0)
|
||||
| (rowSelected ? ImGuiTreeNodeFlags_Selected : 0);
|
||||
ImGui::TableNextColumn();
|
||||
const auto open = ImGui::TreeNodeEx(lbl.c_str(), flags);
|
||||
Str newName = subsheet->name.c_str();
|
||||
ImGui::SameLine();
|
||||
if (ImGui::IsItemClicked()) {
|
||||
model()->setActiveSubsheet(*path);
|
||||
@ -209,16 +208,16 @@ void TileSheetEditorImGui::drawSubsheetSelector(TileSheet::SubSheet *subsheet, T
|
||||
if (ImGui::IsMouseDoubleClicked(0) && ImGui::IsItemHovered()) {
|
||||
showSubsheetEditor();
|
||||
}
|
||||
if (subsheet->subsheets.size()) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("--");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("--");
|
||||
} else {
|
||||
if (subsheet->subsheets.empty()) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%d", subsheet->columns);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%d", subsheet->rows);
|
||||
} else {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("--");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("--");
|
||||
}
|
||||
if (open) {
|
||||
for (auto i = 0ul; auto &child : subsheet->subsheets) {
|
||||
@ -287,7 +286,7 @@ void TileSheetEditorImGui::drawTileSheet(const geo::Vec2 &fbSize) noexcept {
|
||||
glViewport(0, 0, fbSizei.width, fbSizei.height);
|
||||
m_tileSheetEditor.draw();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
uintptr_t buffId = m_framebuffer.color.id;
|
||||
const uintptr_t buffId = m_framebuffer.color.id;
|
||||
ImGui::Image(
|
||||
reinterpret_cast<void*>(buffId),
|
||||
static_cast<ImVec2>(fbSize),
|
||||
|
@ -565,7 +565,7 @@ void TileSheetEditorModel::cut() {
|
||||
const auto pt1 = m_selectionOrigin == geo::Point(-1, -1) ? geo::Point(0, 0) : m_selectionOrigin;
|
||||
const auto pt2 = geo::Point(s->columns * TileWidth, s->rows * TileHeight);
|
||||
setClipboardObject(m_ctx, std::move(cb));
|
||||
pushCommand(new 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() {
|
||||
@ -594,7 +594,7 @@ void TileSheetEditorModel::paste() {
|
||||
const auto s = activeSubSheet();
|
||||
const auto pt1 = m_selectionOrigin == geo::Point(-1, -1) ? geo::Point(0, 0) : m_selectionOrigin;
|
||||
const auto pt2 = geo::Point(s->columns * TileWidth, s->rows * TileHeight);
|
||||
pushCommand(new CutPasteCommand<CommandId::Paste>(&m_img, m_activeSubsSheetIdx, pt1, pt2, *cb));
|
||||
pushCommand(ox::make<CutPasteCommand<CommandId::Paste>>(&m_img, m_activeSubsSheetIdx, pt1, pt2, *cb));
|
||||
}
|
||||
|
||||
const ox::FileAddress &TileSheetEditorModel::palPath() const noexcept {
|
||||
@ -602,7 +602,7 @@ const ox::FileAddress &TileSheetEditorModel::palPath() const noexcept {
|
||||
}
|
||||
|
||||
ox::Error TileSheetEditorModel::setPalette(const ox::String &path) noexcept {
|
||||
pushCommand(new PaletteChangeCommand(activeSubSheetIdx(), &m_img, path));
|
||||
pushCommand(ox::make<PaletteChangeCommand>(activeSubSheetIdx(), &m_img, path));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
@ -615,7 +615,7 @@ void TileSheetEditorModel::drawCommand(const geo::Point &pt, std::size_t palIdx)
|
||||
if (m_ongoingDrawCommand) {
|
||||
m_updated = m_updated || m_ongoingDrawCommand->append(idx);
|
||||
} else if (activeSubSheet.getPixel(m_img.bpp, idx) != palIdx) {
|
||||
pushCommand(new DrawCommand(&m_img, m_activeSubsSheetIdx, idx, static_cast<int>(palIdx)));
|
||||
pushCommand(ox::make<DrawCommand>(&m_img, m_activeSubsSheetIdx, idx, static_cast<int>(palIdx)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -624,23 +624,23 @@ void TileSheetEditorModel::endDrawCommand() noexcept {
|
||||
}
|
||||
|
||||
void TileSheetEditorModel::addSubsheet(const TileSheet::SubSheetIdx &parentIdx) noexcept {
|
||||
pushCommand(new AddSubSheetCommand(&m_img, parentIdx));
|
||||
pushCommand(ox::make<AddSubSheetCommand>(&m_img, parentIdx));
|
||||
}
|
||||
|
||||
void TileSheetEditorModel::rmSubsheet(const TileSheet::SubSheetIdx &idx) noexcept {
|
||||
pushCommand(new RmSubSheetCommand(&m_img, idx));
|
||||
pushCommand(ox::make<RmSubSheetCommand>(&m_img, idx));
|
||||
}
|
||||
|
||||
void TileSheetEditorModel::insertTiles(const TileSheet::SubSheetIdx &idx, std::size_t tileIdx, std::size_t tileCnt) noexcept {
|
||||
pushCommand(new InsertTilesCommand(&m_img, idx, tileIdx, tileCnt));
|
||||
pushCommand(ox::make<InsertTilesCommand>(&m_img, idx, tileIdx, tileCnt));
|
||||
}
|
||||
|
||||
void TileSheetEditorModel::deleteTiles(const TileSheet::SubSheetIdx &idx, std::size_t tileIdx, std::size_t tileCnt) noexcept {
|
||||
pushCommand(new DeleteTilesCommand(&m_img, idx, tileIdx, tileCnt));
|
||||
pushCommand(ox::make<DeleteTilesCommand>(&m_img, idx, tileIdx, tileCnt));
|
||||
}
|
||||
|
||||
ox::Error TileSheetEditorModel::updateSubsheet(const TileSheet::SubSheetIdx &idx, const ox::String &name, int cols, int rows) noexcept {
|
||||
pushCommand(new UpdateSubSheetCommand(&m_img, idx, name, cols, rows));
|
||||
pushCommand(ox::make<UpdateSubSheetCommand>(&m_img, idx, name, cols, rows));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
@ -670,7 +670,7 @@ void TileSheetEditorModel::fill(const geo::Point &pt, int palIdx) noexcept {
|
||||
if (m_ongoingDrawCommand) {
|
||||
m_updated = m_updated || m_ongoingDrawCommand->append(idxList);
|
||||
} else if (s.getPixel(m_img.bpp, pt) != palIdx) {
|
||||
pushCommand(new DrawCommand(&m_img, m_activeSubsSheetIdx, idxList, palIdx));
|
||||
pushCommand(ox::make<DrawCommand>(&m_img, m_activeSubsSheetIdx, idxList, palIdx));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,9 +42,9 @@ struct TileSheetToCompactTileSheetConverter: public Converter<TileSheet, Compact
|
||||
|
||||
static const auto converters = [] {
|
||||
ox::Vector<ox::UniquePtr<BaseConverter>, 3> converters;
|
||||
converters.emplace_back(new NostalgiaGraphicToTileSheetConverter());
|
||||
converters.emplace_back(new NostalgiaPaletteToPaletteConverter());
|
||||
converters.emplace_back(new TileSheetToCompactTileSheetConverter());
|
||||
converters.emplace_back(ox::make<NostalgiaGraphicToTileSheetConverter>());
|
||||
converters.emplace_back(ox::make<NostalgiaPaletteToPaletteConverter>());
|
||||
converters.emplace_back(ox::make<TileSheetToCompactTileSheetConverter>());
|
||||
return converters;
|
||||
}();
|
||||
|
||||
|
@ -38,16 +38,18 @@ ox::Error loadBgTileSheet(Context *ctx,
|
||||
if (bytesPerTile == 64) { // 8 BPP
|
||||
pixels.resize(tilesheet->pixels.size());
|
||||
for (std::size_t i = 0; i < tilesheet->pixels.size(); ++i) {
|
||||
pixels[i] = toColor32(palette->colors[tilesheet->pixels[i]]);
|
||||
pixels[i] = tilesheet->pixels[i];
|
||||
}
|
||||
} else { // 4 BPP
|
||||
pixels.resize(tilesheet->pixels.size() * 2);
|
||||
for (std::size_t i = 0; i < tilesheet->pixels.size(); ++i) {
|
||||
pixels[i * 2 + 0] = toColor32(palette->colors[tilesheet->pixels[i] & 0xF]);
|
||||
pixels[i * 2 + 1] = toColor32(palette->colors[tilesheet->pixels[i] >> 4]);
|
||||
pixels[i * 2 + 0] = tilesheet->pixels[i] & 0xF;
|
||||
pixels[i * 2 + 1] = tilesheet->pixels[i] >> 4;
|
||||
}
|
||||
}
|
||||
renderer::loadBgTexture(ctx->rendererData<void>(), cbb, pixels.data(), width, height);
|
||||
const auto rd = ctx->rendererData<void>();
|
||||
renderer::loadBgTexture(rd, cbb, pixels.data(), width, height);
|
||||
renderer::loadBgPalette(rd, *palette);
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
|
@ -8,12 +8,18 @@
|
||||
|
||||
#include <nostalgia/core/context.hpp>
|
||||
|
||||
namespace nostalgia::core {
|
||||
struct Palette;
|
||||
}
|
||||
|
||||
namespace nostalgia::core::renderer {
|
||||
|
||||
ox::Error init(Context *ctx, void **rendererData) noexcept;
|
||||
|
||||
void shutdown(Context *ctx, void *rendererData) noexcept;
|
||||
|
||||
void loadBgPalette(void *rendererData, const Palette &pal) noexcept;
|
||||
|
||||
void loadBgTexture(void *rendererData, unsigned cbb, void *pixels, int w, int h) noexcept;
|
||||
|
||||
}
|
||||
|
@ -47,6 +47,8 @@ struct GlImplData {
|
||||
uint64_t draws = 0;
|
||||
ox::Array<CBB, 4> cbbs;
|
||||
ox::Array<Background, 4> backgrounds;
|
||||
static constexpr std::size_t ColorCnt = 256;
|
||||
ox::Array<GLfloat, ColorCnt * 3> palette{};
|
||||
};
|
||||
|
||||
constexpr const GLchar *bgvshad = R"(
|
||||
@ -65,9 +67,11 @@ constexpr const GLchar *bgfshad = R"(
|
||||
out vec4 outColor;
|
||||
in vec2 fTexCoord;
|
||||
uniform sampler2D image;
|
||||
uniform vec3 fPalette[256];
|
||||
void main() {
|
||||
int idx = int(texture(image, fTexCoord).rgb.r * 256);
|
||||
outColor = vec4(fPalette[idx], 1.0);
|
||||
//outColor = vec4(0.0, 0.7, 1.0, 1.0);
|
||||
outColor = texture(image, fTexCoord);
|
||||
})";
|
||||
|
||||
[[nodiscard]]
|
||||
@ -175,7 +179,9 @@ static void drawBackground(CBB *cbb) noexcept {
|
||||
static void drawBackgrounds(GlImplData *id) noexcept {
|
||||
// load background shader and its uniforms
|
||||
glUseProgram(id->bgShader);
|
||||
const auto uniformPalette = static_cast<GLint>(glGetUniformLocation(id->bgShader, "fPalette"));
|
||||
const auto uniformTileHeight = static_cast<GLint>(glGetUniformLocation(id->bgShader, "vTileHeight"));
|
||||
glUniform3fv(uniformPalette, GlImplData::ColorCnt, id->palette.data());
|
||||
for (auto &bg : id->backgrounds) {
|
||||
if (bg.enabled) {
|
||||
auto &cbb = id->cbbs[bg.cbbIdx];
|
||||
@ -205,6 +211,15 @@ void shutdown(Context*, void *rendererData) noexcept {
|
||||
ox::safeDelete(id);
|
||||
}
|
||||
|
||||
void loadBgPalette(void *rendererData, const Palette &pal) noexcept {
|
||||
const auto id = static_cast<GlImplData*>(rendererData);
|
||||
for (auto i = 0u; const auto c : pal.colors) {
|
||||
id->palette[i++] = redf(c);
|
||||
id->palette[i++] = greenf(c);
|
||||
id->palette[i++] = bluef(c);
|
||||
}
|
||||
}
|
||||
|
||||
void loadBgTexture(void *rendererData, unsigned cbbIdx, void *pixels, int w, int h) noexcept {
|
||||
oxTracef("nostalgia::core::gfx::gl", "loadBgTexture: { cbbIdx: {}, w: {}, h: {} }", cbbIdx, w, h);
|
||||
const auto id = static_cast<GlImplData*>(rendererData);
|
||||
|
@ -5,7 +5,9 @@ add_executable(
|
||||
)
|
||||
|
||||
# enable LTO
|
||||
set_property(TARGET nostalgia PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
if(NOT WIN32)
|
||||
set_property(TARGET nostalgia PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
endif()
|
||||
|
||||
if(COMMAND OBJCOPY_FILE)
|
||||
set_target_properties(nostalgia
|
||||
|
@ -3,6 +3,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
add_executable(
|
||||
nostalgia-studio MACOSX_BUNDLE
|
||||
aboutpopup.cpp
|
||||
clawviewer.cpp
|
||||
filedialogmanager.cpp
|
||||
main.cpp
|
||||
newmenu.cpp
|
||||
@ -18,7 +19,7 @@ target_link_libraries(
|
||||
NostalgiaCore-Studio
|
||||
)
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release" AND NOT WIN32)
|
||||
# enable LTO
|
||||
set_property(TARGET nostalgia-studio PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
endif()
|
||||
|
186
src/nostalgia/studio/clawviewer.cpp
Normal file
186
src/nostalgia/studio/clawviewer.cpp
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include "clawviewer.hpp"
|
||||
|
||||
namespace nostalgia {
|
||||
|
||||
ClawEditor::ClawEditor(ox::CRStringView path, ox::ModelObject obj) noexcept:
|
||||
m_itemName(path),
|
||||
m_itemDisplayName(pathToItemName(path)),
|
||||
m_obj(std::move(obj)) {
|
||||
}
|
||||
|
||||
ox::CRString ClawEditor::itemName() const noexcept {
|
||||
return m_itemName;
|
||||
}
|
||||
|
||||
ox::CRString ClawEditor::itemDisplayName() const noexcept {
|
||||
return m_itemDisplayName;
|
||||
}
|
||||
|
||||
void ClawEditor::draw(core::Context*) noexcept {
|
||||
//const auto paneSize = ImGui::GetContentRegionAvail();
|
||||
ImGui::BeginChild("PaletteEditor");
|
||||
static constexpr auto flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
|
||||
if (ImGui::BeginTable("ObjTree", 3, flags)) {
|
||||
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 100);
|
||||
ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed, 250);
|
||||
ImGui::TableSetupColumn("Value", ImGuiTableColumnFlags_NoHide);
|
||||
ImGui::TableHeadersRow();
|
||||
ObjPath objPath;
|
||||
drawTree(&objPath, m_obj);
|
||||
ImGui::EndTable();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
void ClawEditor::drawRow(const ox::ModelValue &value) noexcept {
|
||||
using Str = ox::BasicString<100>;
|
||||
Str val, type;
|
||||
switch (value.type()) {
|
||||
case ox::ModelValue::Type::Undefined:
|
||||
val = "undefined";
|
||||
type = "undefined";
|
||||
break;
|
||||
case ox::ModelValue::Type::Bool:
|
||||
val = value.get<bool>() ? "true" : "false";
|
||||
type = "bool";
|
||||
break;
|
||||
case ox::ModelValue::Type::UnsignedInteger8:
|
||||
val = ox::sfmt<Str>("{}", value.get<uint8_t>());
|
||||
type = "uint8";
|
||||
break;
|
||||
case ox::ModelValue::Type::UnsignedInteger16:
|
||||
val = ox::sfmt<Str>("{}", value.get<uint16_t>());
|
||||
type = "uint16";
|
||||
break;
|
||||
case ox::ModelValue::Type::UnsignedInteger32:
|
||||
val = ox::sfmt<Str>("{}", value.get<uint32_t>());
|
||||
type = "uint32";
|
||||
break;
|
||||
case ox::ModelValue::Type::UnsignedInteger64:
|
||||
val = ox::sfmt<Str>("{}", value.get<uint64_t>());
|
||||
type = "uint64";
|
||||
break;
|
||||
case ox::ModelValue::Type::SignedInteger8:
|
||||
val = ox::sfmt<Str>("{}", value.get<int8_t>());
|
||||
type = "int8";
|
||||
break;
|
||||
case ox::ModelValue::Type::SignedInteger16:
|
||||
val = ox::sfmt<Str>("{}", value.get<int16_t>());
|
||||
type = "int16";
|
||||
break;
|
||||
case ox::ModelValue::Type::SignedInteger32:
|
||||
val = ox::sfmt<Str>("{}", value.get<int32_t>());
|
||||
type = "int32";
|
||||
break;
|
||||
case ox::ModelValue::Type::SignedInteger64:
|
||||
val = ox::sfmt<Str>("{}", value.get<int64_t>());
|
||||
type = "int64";
|
||||
break;
|
||||
case ox::ModelValue::Type::String:
|
||||
val = ox::sfmt<Str>("\"{}\"", value.get<ox::String>());
|
||||
type = "string";
|
||||
break;
|
||||
case ox::ModelValue::Type::Object:
|
||||
type = value.get<ox::ModelObject>().type()->typeName.c_str();
|
||||
break;
|
||||
case ox::ModelValue::Type::Union:
|
||||
type = "union";
|
||||
break;
|
||||
case ox::ModelValue::Type::Vector:
|
||||
type = "list";
|
||||
break;
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s", type.c_str());
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s", val.c_str());
|
||||
}
|
||||
|
||||
void ClawEditor::drawVar(ObjPath *path, ox::CRStringView name, const ox::ModelValue &value) noexcept {
|
||||
using Str = ox::BasicString<100>;
|
||||
path->push_back(name);
|
||||
if (value.type() == ox::ModelValue::Type::Object) {
|
||||
drawTree(path, value.get<ox::ModelObject>());
|
||||
} else if (value.type() == ox::ModelValue::Type::Vector) {
|
||||
const auto &vec = value.get<ox::ModelValueVector>();
|
||||
const auto pathStr = ox::join<Str>("##", *path).unwrap();
|
||||
const auto lbl = ox::sfmt<Str>("{}##{}", name, pathStr);
|
||||
const auto flags = ImGuiTreeNodeFlags_SpanFullWidth
|
||||
| ImGuiTreeNodeFlags_OpenOnArrow
|
||||
| (vec.size() ? 0 : ImGuiTreeNodeFlags_Leaf)
|
||||
| (false ? ImGuiTreeNodeFlags_Selected : 0);
|
||||
const auto open = ImGui::TreeNodeEx(lbl.c_str(), flags);
|
||||
ImGui::SameLine();
|
||||
drawRow(value);
|
||||
if (open) {
|
||||
for (auto i = 0lu; const auto &e: vec) {
|
||||
const auto iStr = ox::sfmt<Str>("{}", i);
|
||||
path->push_back(iStr);
|
||||
ImGui::TableNextRow(0, 5);
|
||||
ImGui::TableNextColumn();
|
||||
drawVar(path, ox::sfmt<Str>("[{}]", i), e);
|
||||
path->pop_back();
|
||||
++i;
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
} else {
|
||||
const auto pathStr = ox::join<Str>("##", *path).unwrap();
|
||||
const auto lbl = ox::sfmt<Str>("{}##{}", name, pathStr);
|
||||
const auto flags = ImGuiTreeNodeFlags_SpanFullWidth
|
||||
| ImGuiTreeNodeFlags_OpenOnArrow
|
||||
| ImGuiTreeNodeFlags_Leaf
|
||||
| (false ? ImGuiTreeNodeFlags_Selected : 0);
|
||||
const auto open = ImGui::TreeNodeEx(lbl.c_str(), flags);
|
||||
ImGui::SameLine();
|
||||
drawRow(value);
|
||||
if (open) {
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
path->pop_back();
|
||||
}
|
||||
|
||||
void ClawEditor::drawTree(ObjPath *path, const ox::ModelObject &obj) noexcept {
|
||||
using Str = ox::BasicString<100>;
|
||||
for (const auto &c : obj) {
|
||||
ImGui::TableNextRow(0, 5);
|
||||
auto pathStr = ox::join<Str>("##", *path).unwrap();
|
||||
auto lbl = ox::sfmt<Str>("{}##{}", c->name, pathStr);
|
||||
const auto rowSelected = false;
|
||||
const auto hasChildren = c->value.type() == ox::ModelValue::Type::Object
|
||||
|| c->value.type() == ox::ModelValue::Type::Vector;
|
||||
const auto flags = ImGuiTreeNodeFlags_SpanFullWidth
|
||||
| ImGuiTreeNodeFlags_OpenOnArrow
|
||||
| (hasChildren ? 0 : ImGuiTreeNodeFlags_Leaf)
|
||||
| (rowSelected ? ImGuiTreeNodeFlags_Selected : 0);
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::IsItemClicked()) {
|
||||
//model()->setActiveSubsheet(*path);
|
||||
}
|
||||
if (ImGui::IsMouseDoubleClicked(0) && ImGui::IsItemHovered()) {
|
||||
//showSubsheetEditor();
|
||||
}
|
||||
path->push_back(c->name);
|
||||
if (c->value.type() == ox::ModelValue::Type::Object) {
|
||||
const auto open = ImGui::TreeNodeEx(lbl.c_str(), flags);
|
||||
ImGui::SameLine();
|
||||
drawRow(c->value);
|
||||
if (open) {
|
||||
drawTree(path, c->value.get<ox::ModelObject>());
|
||||
ImGui::TreePop();
|
||||
}
|
||||
} else {
|
||||
drawVar(path, c->name, c->value);
|
||||
}
|
||||
path->pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
40
src/nostalgia/studio/clawviewer.hpp
Normal file
40
src/nostalgia/studio/clawviewer.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/model/modelvalue.hpp>
|
||||
#include <nostalgia/core/context.hpp>
|
||||
|
||||
#include "lib/editor.hpp"
|
||||
|
||||
namespace nostalgia {
|
||||
|
||||
class ClawEditor: public studio::Editor {
|
||||
private:
|
||||
using ObjPath = ox::Vector<ox::StringView, 8>;
|
||||
ox::String m_itemName;
|
||||
ox::String m_itemDisplayName;
|
||||
ox::ModelObject m_obj;
|
||||
public:
|
||||
ClawEditor(ox::CRStringView path, ox::ModelObject obj) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the name of item being edited.
|
||||
*/
|
||||
ox::CRString itemName() const noexcept final;
|
||||
|
||||
ox::CRString itemDisplayName() const noexcept final;
|
||||
|
||||
void draw(core::Context*) noexcept final;
|
||||
|
||||
private:
|
||||
static void drawRow(const ox::ModelValue &value) noexcept;
|
||||
|
||||
void drawVar(ObjPath *path, ox::CRStringView name, const ox::ModelValue &value) noexcept;
|
||||
|
||||
void drawTree(ObjPath *path, const ox::ModelObject &obj) noexcept;
|
||||
};
|
||||
|
||||
}
|
@ -31,7 +31,7 @@ constexpr auto ConfigDir = [] {
|
||||
case ox::OS::OpenBSD:
|
||||
return "{}/.config/{}";
|
||||
case ox::OS::Windows:
|
||||
return "{}/AppData/Local/{}";
|
||||
return R"({}/AppData/Local/{})";
|
||||
case ox::OS::BareMetal:
|
||||
return "";
|
||||
}
|
||||
@ -73,7 +73,7 @@ ox::Error writeConfig(core::Context *ctx, const auto &name, T *data) noexcept {
|
||||
const auto configPath = ox::sfmt(ConfigDir, homeDir, ctx->appName).toStdString();
|
||||
const auto path = ox::sfmt("{}.json", name).toStdString();
|
||||
ox::PassThroughFS fs(configPath.c_str());
|
||||
if (auto err = fs.mkdir(configPath.c_str(), true)) {
|
||||
if (auto err = fs.mkdir("/", true)) {
|
||||
oxErrf("Could not create config directory: {}\n", toStr(err));
|
||||
return err;
|
||||
}
|
||||
|
@ -100,6 +100,11 @@ class NOSTALGIASTUDIO_EXPORT BaseEditor: public Widget {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static constexpr auto pathToItemName(ox::CRStringView path) noexcept {
|
||||
const auto lastSlash = std::find(path.rbegin(), path.rend(), '/').offset();
|
||||
return path.substr(lastSlash + 1);
|
||||
}
|
||||
|
||||
// signals
|
||||
public:
|
||||
ox::Signal<ox::Error(bool)> unsavedChangesChanged;
|
||||
|
@ -4,11 +4,18 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/defines.hpp>
|
||||
|
||||
namespace nostalgia::studio {
|
||||
|
||||
struct FDFilterItem {
|
||||
ox::String name;
|
||||
ox::String spec;
|
||||
#ifdef OX_OS_Windows
|
||||
using String = ox::BasicString<8, wchar_t>;
|
||||
#else
|
||||
using String = ox::String;
|
||||
#endif
|
||||
String name;
|
||||
String spec;
|
||||
};
|
||||
|
||||
ox::Result<ox::String> saveFile(const ox::Vector<FDFilterItem> &exts) noexcept;
|
||||
|
@ -14,8 +14,14 @@ namespace nostalgia::studio {
|
||||
|
||||
static ox::Result<ox::String> toResult(nfdresult_t r, const NFD::UniquePathN &path) noexcept {
|
||||
switch (r) {
|
||||
case NFD_OKAY:
|
||||
return ox::String(path.get());
|
||||
case NFD_OKAY: {
|
||||
ox::String out;
|
||||
for (auto i = 0u; path.get()[i]; ++i) {
|
||||
const auto c = static_cast<char>(path.get()[i]);
|
||||
oxIgnoreError(out.append(&c, 1));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
case NFD_CANCEL:
|
||||
return OxError(1, "Operation cancelled");
|
||||
default:
|
||||
@ -28,7 +34,8 @@ ox::Result<ox::String> saveFile(const ox::Vector<FDFilterItem> &filters) noexcep
|
||||
NFD::UniquePathN path;
|
||||
ox::Vector<nfdnfilteritem_t, 5> filterItems(filters.size());
|
||||
for (auto i = 0u; const auto &f : filters) {
|
||||
filterItems[i] = {f.name.c_str(), f.spec.c_str()};
|
||||
filterItems[i].name = f.name.c_str();
|
||||
filterItems[i].spec = f.spec.c_str();
|
||||
++i;
|
||||
}
|
||||
return toResult(NFD::SaveDialog(path, filterItems.data(), filterItems.size()), path);
|
||||
|
@ -61,7 +61,7 @@ class NOSTALGIASTUDIO_EXPORT Project {
|
||||
ox::Error writeObj(const ox::String &path, const T *obj, ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept;
|
||||
|
||||
template<typename T>
|
||||
ox::Result<ox::UniquePtr<T>> loadObj(const ox::String &path) const noexcept;
|
||||
ox::Result<T> loadObj(const ox::String &path) const noexcept;
|
||||
|
||||
ox::Result<ox::FileStat> stat(const ox::String &path) const noexcept;
|
||||
|
||||
@ -126,10 +126,13 @@ ox::Error Project::writeObj(const ox::String &path, const T *obj, ox::ClawFormat
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ox::Result<ox::UniquePtr<T>> Project::loadObj(const ox::String &path) const noexcept {
|
||||
auto obj = ox::make_unique<T>();
|
||||
ox::Result<T> Project::loadObj(const ox::String &path) const noexcept {
|
||||
oxRequire(buff, loadBuff(path));
|
||||
if constexpr (ox::is_same_v<T, ox::ModelObject>) {
|
||||
return ox::readClaw(&m_typeStore, buff);
|
||||
} else {
|
||||
return ox::readClaw<T>(buff);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Functor>
|
||||
|
@ -70,12 +70,12 @@ class NewMenu: public studio::Popup {
|
||||
|
||||
template<typename T>
|
||||
void NewMenu::addItemType(ox::String displayName, ox::String parentDir, ox::String fileExt, T itemTempl, ox::ClawFormat pFmt) noexcept {
|
||||
m_types.emplace_back(new studio::ItemMakerT<T>(std::move(displayName), std::move(parentDir), std::move(fileExt), std::move(itemTempl), pFmt));
|
||||
m_types.emplace_back(ox::make<studio::ItemMakerT<T>>(std::move(displayName), std::move(parentDir), std::move(fileExt), std::move(itemTempl), pFmt));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NewMenu::addItemType(ox::String displayName, ox::String parentDir, ox::String fileExt, ox::ClawFormat pFmt) noexcept {
|
||||
m_types.emplace_back(new studio::ItemMakerT<T>(std::move(displayName), std::move(parentDir), std::move(fileExt), pFmt));
|
||||
m_types.emplace_back(ox::make<studio::ItemMakerT<T>>(std::move(displayName), std::move(parentDir), std::move(fileExt), pFmt));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "lib/configio.hpp"
|
||||
#include "builtinmodules.hpp"
|
||||
#include "clawviewer.hpp"
|
||||
#include "filedialogmanager.hpp"
|
||||
#include "studioapp.hpp"
|
||||
|
||||
@ -300,11 +301,11 @@ ox::Error StudioUI::openProject(const ox::String &path) noexcept {
|
||||
return m_projectExplorer->refreshProjectTreeModel();
|
||||
}
|
||||
|
||||
ox::Error StudioUI::openFile(const ox::String &path) noexcept {
|
||||
ox::Error StudioUI::openFile(ox::CRStringView path) noexcept {
|
||||
return openFileActiveTab(path, true);
|
||||
}
|
||||
|
||||
ox::Error StudioUI::openFileActiveTab(const ox::String &path, bool makeActiveTab) noexcept {
|
||||
ox::Error StudioUI::openFileActiveTab(ox::CRStringView path, bool makeActiveTab) noexcept {
|
||||
if (m_openFiles.contains(path)) {
|
||||
for (auto &e : m_editors) {
|
||||
if (makeActiveTab && e->itemName() == path) {
|
||||
@ -317,10 +318,15 @@ ox::Error StudioUI::openFileActiveTab(const ox::String &path, bool makeActiveTab
|
||||
}
|
||||
oxRequire(ext, studio::fileExt(path));
|
||||
// create Editor
|
||||
studio::BaseEditor *editor = nullptr;
|
||||
if (!m_editorMakers.contains(ext)) {
|
||||
auto [obj, err] = m_project->loadObj<ox::ModelObject>(path);
|
||||
if (err) {
|
||||
return OxError(1, "There is no editor for this file extension");
|
||||
}
|
||||
auto [editor, err] = m_editorMakers[ext](path);
|
||||
editor = new ClawEditor(path, std::move(obj));
|
||||
} else {
|
||||
const auto err = m_editorMakers[ext](path).moveTo(&editor);
|
||||
if (err) {
|
||||
if constexpr(!ox::defines::Debug) {
|
||||
oxErrf("Could not open Editor: {}\n", toStr(err));
|
||||
@ -329,6 +335,7 @@ ox::Error StudioUI::openFileActiveTab(const ox::String &path, bool makeActiveTab
|
||||
}
|
||||
return err;
|
||||
}
|
||||
}
|
||||
editor->closed.connect(this, &StudioUI::closeFile);
|
||||
m_editors.emplace_back(editor);
|
||||
m_openFiles.emplace_back(path);
|
||||
|
@ -79,9 +79,9 @@ class StudioUI: public ox::SignalHandler {
|
||||
|
||||
ox::Error openProject(const ox::String &path) noexcept;
|
||||
|
||||
ox::Error openFile(const ox::String &path) noexcept;
|
||||
ox::Error openFile(ox::CRStringView path) noexcept;
|
||||
|
||||
ox::Error openFileActiveTab(const ox::String &path, bool makeActiveTab) noexcept;
|
||||
ox::Error openFileActiveTab(ox::CRStringView path, bool makeActiveTab) noexcept;
|
||||
|
||||
ox::Error closeFile(const ox::String &path) noexcept;
|
||||
};
|
||||
|
@ -6,7 +6,7 @@ target_link_libraries(
|
||||
NostalgiaPack
|
||||
)
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release" AND NOT WIN32)
|
||||
# enable LTO
|
||||
set_property(TARGET nost-pack PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
endif()
|
||||
|
@ -149,11 +149,11 @@ static ox::Error preloadObj(core::TypeStore *ts, ox::FileSystem *romFs, GbaPrelo
|
||||
oxRequireM(obj, ox::readClaw(ts, buff));
|
||||
if (obj.type()->preloadable) {
|
||||
// preload
|
||||
oxReturnError(pl->startAlloc(ox::sizeOf<GbaPlatSpec>(&obj)));
|
||||
auto err = ox::preload<GbaPlatSpec, decltype(obj)>(pl, &obj);
|
||||
oxRequire(a, pl->startAlloc(ox::sizeOf<GbaPlatSpec>(&obj)));
|
||||
const auto err = ox::preload<GbaPlatSpec, decltype(obj)>(pl, &obj);
|
||||
oxReturnError(pl->endAlloc());
|
||||
oxReturnError(err);
|
||||
const core::PreloadPtr p{.preloadAddr = 0};
|
||||
const core::PreloadPtr p{.preloadAddr = static_cast<uint32_t>(a)};
|
||||
oxReturnError(ox::writeMC(&p).moveTo(&buff));
|
||||
} else {
|
||||
// strip the Claw header (it is not needed after preloading) and write back out to dest fs
|
||||
|
@ -14,6 +14,7 @@ struct GbaPlatSpec {
|
||||
using PtrType = uint32_t;
|
||||
using size_t = uint32_t;
|
||||
|
||||
static constexpr auto PtrSize = 4;
|
||||
static constexpr auto PtrAlign = 4;
|
||||
static constexpr PtrType RomStart = 0x08000000;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user