Compare commits
26 Commits
5aa133a788
...
hidpi
| Author | SHA1 | Date | |
|---|---|---|---|
| 5b338043aa | |||
| ef1c108b58 | |||
| 6a054cd970 | |||
| 9070e6e109 | |||
| 6cc6e9e7ed | |||
| de859bef77 | |||
| d1a3538e9a | |||
| d10a71f06d | |||
| 9593e7eef9 | |||
| 2f9b9c0842 | |||
| dce09b564c | |||
| 9f485d9496 | |||
| 2c50ce48ed | |||
| 72e16cb285 | |||
| d1e410ac55 | |||
| be32d575f5 | |||
| f24929f421 | |||
| 2d426d2bb3 | |||
| f89af6fcb3 | |||
| 899eaa9dce | |||
| d32b1033c3 | |||
| 1d2814bbd0 | |||
| 2e119b5683 | |||
| 46c6ba2e17 | |||
| c286e3794d | |||
| 45cbede7e2 |
+2
-2
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
cmake_minimum_required(VERSION 3.25)
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0110 NEW) # requires CMake 3.19
|
||||
|
||||
if(BUILDCORE_TARGET STREQUAL "gba")
|
||||
@@ -52,7 +52,7 @@ if(NOT BUILDCORE_TARGET STREQUAL "gba")
|
||||
set(GLFW_BUILD_TESTS OFF)
|
||||
set(GLFW_BUILD_DOCS OFF)
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
set(GLFW_BUILD_WAYLAND OFF)
|
||||
set(GLFW_BUILD_WAYLAND ON)
|
||||
endif()
|
||||
add_subdirectory(deps/glfw)
|
||||
add_subdirectory(deps/glutils)
|
||||
|
||||
@@ -3,6 +3,7 @@ build/gba
|
||||
build/*-asan
|
||||
build/*-debug
|
||||
build/*-release
|
||||
dist
|
||||
.current_build
|
||||
tags
|
||||
compile_commands.json
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
cmake_minimum_required(VERSION 3.25)
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0110 NEW) # requires CMake 3.19
|
||||
|
||||
project(Ox CXX)
|
||||
|
||||
+20
@@ -120,4 +120,24 @@ Result<Buffer> writeClaw(
|
||||
return out;
|
||||
}
|
||||
|
||||
Error writeClaw(
|
||||
auto const &obj,
|
||||
Writer_c auto &writer,
|
||||
ClawFormat const fmt = ClawFormat::Metal) noexcept {
|
||||
OX_RETURN_ERROR(detail::writeClawHeader(writer, &obj, fmt));
|
||||
#ifdef OX_USE_STDLIB
|
||||
if (fmt == ClawFormat::Metal) {
|
||||
OX_RETURN_ERROR(writeMC(writer, obj));
|
||||
} else if (fmt == ClawFormat::Organic) {
|
||||
OX_RETURN_ERROR(writeOC(writer, obj));
|
||||
}
|
||||
#else
|
||||
if (fmt != ClawFormat::Metal) {
|
||||
return ox::Error(1, "OC is not supported in this build");
|
||||
}
|
||||
OX_RETURN_ERROR(writeMC(writer, obj));
|
||||
#endif
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Vendored
-11
@@ -38,17 +38,6 @@ const std::map<ox::StringView, std::function<ox::Error(ox::StringView)>> tests =
|
||||
auto a1 = buffer->malloc(sizeof(String)).value;
|
||||
auto a2 = buffer->malloc(sizeof(String)).value;
|
||||
oxAssert(a1.valid(), "Allocation 1 failed.");
|
||||
oxAssert(a2.valid(), "Allocation 2 failed.");
|
||||
auto s1Buff = buffer->dataOf<String>(a1);
|
||||
auto s2Buff = buffer->dataOf<String>(a2);
|
||||
oxAssert(s1Buff.valid(), "s1 allocation 1 failed.");
|
||||
oxAssert(s2Buff.valid(), "s2 allocation 2 failed.");
|
||||
auto &s1 = *new (s1Buff) String("asdf");
|
||||
auto &s2 = *new (s2Buff) String("aoeu");
|
||||
oxTrace("test") << "s1: " << s1.c_str();
|
||||
oxTrace("test") << "s2: " << s2.c_str();
|
||||
oxAssert(s1 == "asdf", "Allocation 1 not as expected.");
|
||||
oxAssert(s2 == "aoeu", "Allocation 2 not as expected.");
|
||||
oxAssert(buffer->free(a1), "Free failed.");
|
||||
oxAssert(buffer->free(a2), "Free failed.");
|
||||
oxAssert(buffer->setSize(buffer->size() - buffer->available()), "Resize failed.");
|
||||
|
||||
+3
-1
@@ -6,7 +6,9 @@
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#ifdef OX_USE_STDLIB
|
||||
#include <ox/std/defines.hpp>
|
||||
|
||||
#ifndef OX_OS_BareMetal
|
||||
#include <cstdio>
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
+2
-45
@@ -44,15 +44,7 @@ class MetalClawWriter: public ModelHandlerBase<MetalClawWriter<Writer>, OpType::
|
||||
|
||||
constexpr ~MetalClawWriter() noexcept = default;
|
||||
|
||||
constexpr Error field(CString, int8_t const *val) noexcept;
|
||||
constexpr Error field(CString, int16_t const *val) noexcept;
|
||||
constexpr Error field(CString, int32_t const *val) noexcept;
|
||||
constexpr Error field(CString, int64_t const *val) noexcept;
|
||||
|
||||
constexpr Error field(CString, uint8_t const *val) noexcept;
|
||||
constexpr Error field(CString, uint16_t const *val) noexcept;
|
||||
constexpr Error field(CString, uint32_t const *val) noexcept;
|
||||
constexpr Error field(CString, uint64_t const *val) noexcept;
|
||||
constexpr Error field(CString, Integer_c auto const *val) noexcept;
|
||||
|
||||
constexpr Error field(CString, bool const *val) noexcept;
|
||||
|
||||
@@ -133,42 +125,7 @@ constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, Optional<int>
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, int8_t const *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, int16_t const *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, int32_t const *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, int64_t const *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, uint8_t const *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, uint16_t const *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, uint32_t const *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, uint64_t const *val) noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::field(CString, Integer_c auto const *val) noexcept {
|
||||
return appendInteger(*val);
|
||||
}
|
||||
|
||||
|
||||
Vendored
+6
-6
@@ -43,14 +43,14 @@ struct TestStruct {
|
||||
int32_t Int6 = 0;
|
||||
int32_t Int7 = 0;
|
||||
int32_t Int8 = 0;
|
||||
int unionIdx = 1;
|
||||
int32_t unionIdx = 1;
|
||||
TestUnion Union;
|
||||
ox::String String;
|
||||
ox::IString<32> IString = "";
|
||||
uint32_t List[4] = {0, 0, 0, 0};
|
||||
ox::Vector<uint32_t> Vector = {1, 2, 3, 4, 5};
|
||||
ox::Vector<uint32_t> Vector2 = {1, 2, 3, 4, 5};
|
||||
ox::HashMap<ox::String, int> Map;
|
||||
ox::HashMap<ox::String, int32_t> Map;
|
||||
TestStructNest EmptyStruct;
|
||||
TestStructNest Struct;
|
||||
constexpr ~TestStruct() noexcept {
|
||||
@@ -204,7 +204,8 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
std::cout << "val.length: " << val.length << '\n';
|
||||
return ox::Error(1);
|
||||
}
|
||||
ox::LittleEndian<decltype(expected)> decoded = *reinterpret_cast<decltype(expected)*>(&val.data[1]);
|
||||
ox::LittleEndian<decltype(expected)> decoded;
|
||||
ox::memcpy(&decoded, &val.data[1], sizeof(decoded));
|
||||
if (expected != decoded) {
|
||||
std::cout << "decoded: " << decoded << ", expected: " << expected << '\n';
|
||||
return ox::Error(1);
|
||||
@@ -370,7 +371,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
const auto [type, typeErr] = ox::buildTypeDef(typeStore, testIn);
|
||||
oxAssert(typeErr, "Descriptor write failed");
|
||||
ox::BufferReader br({dataBuff, dataBuffLen});
|
||||
OX_RETURN_ERROR(ox::walkModel<ox::MetalClawReader>(type, br,
|
||||
return ox::walkModel<ox::MetalClawReader>(type, br,
|
||||
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error {
|
||||
//std::cout << f.fieldName.c_str() << '\n';
|
||||
auto fieldName = f.fieldName.c_str();
|
||||
@@ -455,8 +456,7 @@ std::map<ox::StringView, ox::Error(*)()> tests = {
|
||||
}
|
||||
return ox::Error(0);
|
||||
}
|
||||
));
|
||||
return ox::Error(0);
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
+21
-62
@@ -126,22 +126,7 @@ class TypeDescWriter {
|
||||
|
||||
private:
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const int8_t *val) const noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const int16_t *val) const noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const int32_t *val) const noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const int64_t *val) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const uint8_t *val) const noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const uint16_t *val) const noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const uint32_t *val) const noexcept;
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const uint64_t *val) const noexcept;
|
||||
constexpr const DescriptorType *type(const Integer_c auto *val) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const bool *val) const noexcept;
|
||||
@@ -295,52 +280,26 @@ constexpr const DescriptorType *TypeDescWriter::type(UnionView<U> val) const noe
|
||||
return t;
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const int8_t*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::SignedInteger;
|
||||
constexpr auto Bytes = 1;
|
||||
return getType(types::Int8, 0, PT, Bytes);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const int16_t*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::SignedInteger;
|
||||
constexpr auto Bytes = 2;
|
||||
return getType(types::Int16, 0, PT, Bytes);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const int32_t*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::SignedInteger;
|
||||
constexpr auto Bytes = 4;
|
||||
return getType(types::Int32, 0, PT, Bytes);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const int64_t*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::SignedInteger;
|
||||
constexpr auto Bytes = 8;
|
||||
return getType(types::Int64, 0, PT, Bytes);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const uint8_t*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::UnsignedInteger;
|
||||
constexpr auto Bytes = 1;
|
||||
return getType(types::Uint8, 0, PT, Bytes);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const uint16_t*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::UnsignedInteger;
|
||||
constexpr auto Bytes = 2;
|
||||
return getType(types::Uint16, 0, PT, Bytes);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const uint32_t*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::UnsignedInteger;
|
||||
constexpr auto Bytes = 4;
|
||||
return getType(types::Uint32, 0, PT, Bytes);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const uint64_t*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::UnsignedInteger;
|
||||
constexpr auto Bytes = 8;
|
||||
return getType(types::Uint64, 0, PT, Bytes);
|
||||
constexpr const DescriptorType *TypeDescWriter::type(Integer_c auto const *val) const noexcept {
|
||||
constexpr auto isSigned = ox::is_signed_v<decltype(*val)>;
|
||||
constexpr auto PT = isSigned ?
|
||||
PrimitiveType::SignedInteger :
|
||||
PrimitiveType::UnsignedInteger;
|
||||
constexpr auto sz = sizeof(*val);
|
||||
constexpr auto bytes = sizeof(*val);
|
||||
return getType([] {
|
||||
switch (sz) {
|
||||
case 1:
|
||||
return isSigned ? types::Int8 : types::Uint8;
|
||||
case 2:
|
||||
return isSigned ? types::Int16 : types::Uint16;
|
||||
case 4:
|
||||
return isSigned ? types::Int32 : types::Uint32;
|
||||
case 8:
|
||||
return isSigned ? types::Int64 : types::Uint64;
|
||||
}
|
||||
return types::Int32;
|
||||
}(), 0, PT, bytes);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const bool*) const noexcept {
|
||||
|
||||
+17
-6
@@ -28,6 +28,7 @@ namespace ox {
|
||||
|
||||
class OrganicClawWriter {
|
||||
|
||||
friend Error writeOC(Writer_c auto &writer, auto const &val) noexcept;
|
||||
friend Result<Buffer> writeOC(const auto &val) noexcept;
|
||||
friend Result<String> writeOCString(const auto &val) noexcept;
|
||||
|
||||
@@ -59,7 +60,7 @@ class OrganicClawWriter {
|
||||
|
||||
Error field(CString const key, int32_t const *val) noexcept {
|
||||
if (targetValid() && (*val || m_json.isArray())) {
|
||||
value(key) = *val;
|
||||
value(key) = static_cast<Json::Int>(*val);
|
||||
}
|
||||
++m_fieldIt;
|
||||
return {};
|
||||
@@ -92,7 +93,7 @@ class OrganicClawWriter {
|
||||
|
||||
Error field(CString const key, uint32_t const *val) noexcept {
|
||||
if (targetValid() && (*val || m_json.isArray())) {
|
||||
value(key) = *val;
|
||||
value(key) = static_cast<Json::UInt>(*val);
|
||||
}
|
||||
++m_fieldIt;
|
||||
return {};
|
||||
@@ -221,9 +222,9 @@ Error OrganicClawWriter::field(CString key, T const *val) noexcept {
|
||||
// the int type needs to be normalized because jsoncpp doesn't
|
||||
// factor in every permutation unsigned long, etc.
|
||||
if constexpr(is_signed_v<T>) {
|
||||
value(key) = static_cast<Int<8 * sizeof(*val)>>(*val);
|
||||
value(key) = static_cast<Json::Int64>(*val);
|
||||
} else {
|
||||
value(key) = static_cast<Uint<8 * sizeof(*val)>>(*val);
|
||||
value(key) = static_cast<Json::UInt64>(*val);
|
||||
}
|
||||
}
|
||||
} else if constexpr(isVector_v<T> || isArray_v<T>) {
|
||||
@@ -254,9 +255,19 @@ Error OrganicClawWriter::field(CString key, UnionView<U, force> val) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
Error writeOC(Writer_c auto &writer, auto const &val) noexcept {
|
||||
OrganicClawWriter ocWriter;
|
||||
ModelHandlerInterface handler(ocWriter);
|
||||
OX_RETURN_ERROR(model(&handler, &val));
|
||||
Json::StreamWriterBuilder const jsonBuilder;
|
||||
auto const str = Json::writeString(jsonBuilder, ocWriter.m_json);
|
||||
OX_RETURN_ERROR(writer.write(str.data(), str.size()));
|
||||
return writer.put('\0');
|
||||
}
|
||||
|
||||
Result<Buffer> writeOC(auto const &val) noexcept {
|
||||
OrganicClawWriter writer;
|
||||
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(writer);
|
||||
ModelHandlerInterface handler(writer);
|
||||
OX_RETURN_ERROR(model(&handler, &val));
|
||||
Json::StreamWriterBuilder const jsonBuilder;
|
||||
auto const str = Json::writeString(jsonBuilder, writer.m_json);
|
||||
@@ -270,7 +281,7 @@ Result<Buffer> writeOC(auto const &val) noexcept {
|
||||
|
||||
Result<String> writeOCString(auto const &val) noexcept {
|
||||
OrganicClawWriter writer;
|
||||
ModelHandlerInterface<OrganicClawWriter, OpType::Write> handler(writer);
|
||||
ModelHandlerInterface handler(writer);
|
||||
OX_RETURN_ERROR(model(&handler, &val));
|
||||
Json::StreamWriterBuilder const jsonBuilder;
|
||||
auto const str = Json::writeString(jsonBuilder, writer.m_json);
|
||||
|
||||
Vendored
+2
-2
@@ -78,10 +78,10 @@ target_compile_definitions(
|
||||
$<$<BOOL:${OX_NODEBUG}>:OX_NODEBUG>
|
||||
)
|
||||
|
||||
if(NOT WIN32)
|
||||
if(NOT WIN32 AND NOT OX_BARE_METAL)
|
||||
target_link_libraries(
|
||||
OxStd PUBLIC
|
||||
$<$<CXX_COMPILER_ID:GNU>:$<$<BOOL:${OX_USE_STDLIB}>:dl>>
|
||||
dl
|
||||
)
|
||||
endif()
|
||||
target_link_libraries(
|
||||
|
||||
+1
@@ -63,6 +63,7 @@ constexpr void oxAssert(const ox::Error&, const char*) noexcept {}
|
||||
#if defined(_MSC_VER)
|
||||
#define ox_alloca(size) _alloca(size)
|
||||
#elif OX_USE_STDLIB
|
||||
#include <alloca.h>
|
||||
#define ox_alloca(size) alloca(size)
|
||||
#else
|
||||
#define ox_alloca(size) __builtin_alloca(size)
|
||||
|
||||
+15
@@ -345,6 +345,21 @@ struct [[nodiscard]] Result {
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Result reoriginate(
|
||||
ErrorCode const pErrCode,
|
||||
CString const pMsg = nullptr,
|
||||
std::source_location const &pSrc = std::source_location::current()) const && noexcept {
|
||||
if (error) {
|
||||
return {std::move(value), Error{pErrCode, pMsg, pSrc}};
|
||||
}
|
||||
return {std::move(value)};
|
||||
}
|
||||
|
||||
constexpr Result reoriginate(
|
||||
std::source_location const &pSrc = std::source_location::current()) const && noexcept {
|
||||
return {std::move(value), Error{error.errCode, error.msg, pSrc}};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
+21
@@ -36,6 +36,27 @@ constexpr StringView substr(StringViewCR str, std::size_t const start, std::size
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr char toUpper(char const c) noexcept {
|
||||
return c & static_cast<char>(0b1101'1111);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int caseInsensitiveStrCmp(StringViewCR a, StringViewCR b) noexcept {
|
||||
auto const sz = ox::min(a.size(), b.size());
|
||||
for (size_t i{}; i < sz; ++i) {
|
||||
auto const ac = toUpper(a[i]);
|
||||
auto const bc = toUpper(b[i]);
|
||||
if (ac < bc) {
|
||||
return -1;
|
||||
}
|
||||
if (ac > bc) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr bool beginsWith(StringViewCR base, char const beginning) noexcept {
|
||||
return base.size() && base[0] == beginning;
|
||||
|
||||
+44
-46
@@ -103,32 +103,33 @@ constexpr bool is_const_v<const T> = true;
|
||||
// is_integral /////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T> struct is_integral: false_type {};
|
||||
template<> struct is_integral<bool> : true_type {};
|
||||
template<> struct is_integral<wchar_t> : true_type {};
|
||||
template<> struct is_integral<int8_t> : true_type {};
|
||||
template<> struct is_integral<uint8_t> : true_type {};
|
||||
template<> struct is_integral<int16_t> : true_type {};
|
||||
template<> struct is_integral<uint16_t>: true_type {};
|
||||
template<> struct is_integral<int32_t> : true_type {};
|
||||
template<> struct is_integral<uint32_t>: true_type {};
|
||||
template<> struct is_integral<const bool> : true_type {};
|
||||
template<> struct is_integral<const wchar_t> : true_type {};
|
||||
template<> struct is_integral<const int8_t> : true_type {};
|
||||
template<> struct is_integral<const uint8_t> : true_type {};
|
||||
template<> struct is_integral<const int16_t> : true_type {};
|
||||
template<> struct is_integral<const uint16_t>: true_type {};
|
||||
template<> struct is_integral<const int32_t> : true_type {};
|
||||
template<> struct is_integral<const uint32_t>: true_type {};
|
||||
|
||||
// some of these need to be done with the actual language syntax because no one
|
||||
// can agree on what an (u)int64_t is...
|
||||
template<> struct is_integral<long>: true_type {};
|
||||
template<> struct is_integral<long long>: true_type {};
|
||||
template<> struct is_integral<unsigned long>: true_type {};
|
||||
template<> struct is_integral<unsigned long long>: true_type {};
|
||||
template<> struct is_integral<const long>: true_type {};
|
||||
template<> struct is_integral<const long long>: true_type {};
|
||||
template<> struct is_integral<const unsigned long>: true_type {};
|
||||
template<> struct is_integral<bool> : true_type {};
|
||||
template<> struct is_integral<wchar_t> : true_type {};
|
||||
template<> struct is_integral<signed char> : true_type {};
|
||||
template<> struct is_integral<unsigned char> : true_type {};
|
||||
template<> struct is_integral<short> : true_type {};
|
||||
template<> struct is_integral<unsigned short> : true_type {};
|
||||
template<> struct is_integral<int> : true_type {};
|
||||
template<> struct is_integral<unsigned int> : true_type {};
|
||||
template<> struct is_integral<long> : true_type {};
|
||||
template<> struct is_integral<long long> : true_type {};
|
||||
template<> struct is_integral<unsigned long> : true_type {};
|
||||
template<> struct is_integral<unsigned long long> : true_type {};
|
||||
|
||||
template<> struct is_integral<const bool> : true_type {};
|
||||
template<> struct is_integral<const wchar_t> : true_type {};
|
||||
template<> struct is_integral<const signed char> : true_type {};
|
||||
template<> struct is_integral<const unsigned char> : true_type {};
|
||||
template<> struct is_integral<const short> : true_type {};
|
||||
template<> struct is_integral<const unsigned short> : true_type {};
|
||||
template<> struct is_integral<const int> : true_type {};
|
||||
template<> struct is_integral<const unsigned int> : true_type {};
|
||||
template<> struct is_integral<const long> : true_type {};
|
||||
template<> struct is_integral<const long long> : true_type {};
|
||||
template<> struct is_integral<const unsigned long> : true_type {};
|
||||
template<> struct is_integral<const unsigned long long>: true_type {};
|
||||
|
||||
template<typename T>
|
||||
@@ -138,29 +139,26 @@ constexpr bool is_integral_v = is_integral<T>::value;
|
||||
// is_integer /////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T> struct is_integer: false_type {};
|
||||
template<> struct is_integer<int8_t> : true_type {};
|
||||
template<> struct is_integer<uint8_t> : true_type {};
|
||||
template<> struct is_integer<int16_t> : true_type {};
|
||||
template<> struct is_integer<uint16_t>: true_type {};
|
||||
template<> struct is_integer<int32_t> : true_type {};
|
||||
template<> struct is_integer<uint32_t>: true_type {};
|
||||
template<> struct is_integer<int8_t const> : true_type {};
|
||||
template<> struct is_integer<uint8_t const> : true_type {};
|
||||
template<> struct is_integer<int16_t const> : true_type {};
|
||||
template<> struct is_integer<uint16_t const>: true_type {};
|
||||
template<> struct is_integer<int32_t const> : true_type {};
|
||||
template<> struct is_integer<uint32_t const>: true_type {};
|
||||
|
||||
// some of these need to be done with the actual language syntax because no one
|
||||
// can agree on what an (u)int64_t is...
|
||||
template<> struct is_integer<long>: true_type {};
|
||||
template<> struct is_integer<long long>: true_type {};
|
||||
template<> struct is_integer<unsigned long>: true_type {};
|
||||
template<> struct is_integer<unsigned long long>: true_type {};
|
||||
template<> struct is_integer<long const>: true_type {};
|
||||
template<> struct is_integer<long long const>: true_type {};
|
||||
template<> struct is_integer<unsigned long const>: true_type {};
|
||||
template<> struct is_integer<unsigned long long const>: true_type {};
|
||||
template<> struct is_integer<signed char> : true_type {};
|
||||
template<> struct is_integer<unsigned char> : true_type {};
|
||||
template<> struct is_integer<short> : true_type {};
|
||||
template<> struct is_integer<unsigned short> : true_type {};
|
||||
template<> struct is_integer<int> : true_type {};
|
||||
template<> struct is_integer<unsigned int> : true_type {};
|
||||
template<> struct is_integer<long> : true_type {};
|
||||
template<> struct is_integer<long long> : true_type {};
|
||||
template<> struct is_integer<unsigned long> : true_type {};
|
||||
template<> struct is_integer<unsigned long long> : true_type {};
|
||||
template<> struct is_integer<const signed char> : true_type {};
|
||||
template<> struct is_integer<const unsigned char> : true_type {};
|
||||
template<> struct is_integer<const short> : true_type {};
|
||||
template<> struct is_integer<const unsigned short> : true_type {};
|
||||
template<> struct is_integer<const int> : true_type {};
|
||||
template<> struct is_integer<const unsigned int> : true_type {};
|
||||
template<> struct is_integer<const long> : true_type {};
|
||||
template<> struct is_integer<const long long> : true_type {};
|
||||
template<> struct is_integer<const unsigned long> : true_type {};
|
||||
template<> struct is_integer<const unsigned long long> : true_type {};
|
||||
|
||||
template<typename T>
|
||||
constexpr bool is_integer_v = is_integer<T>::value;
|
||||
|
||||
@@ -54,6 +54,10 @@ struct VectorAllocator {
|
||||
// this totally idiotic redundant check (&& count <= Size) is required to address a bug in devkitARM,
|
||||
// try removing it later
|
||||
if (!std::is_constant_evaluated()) {
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wstringop-overflow="
|
||||
#endif
|
||||
if (cap <= m_data.size() && count <= m_data.size()) {
|
||||
for (auto i = 0u; i < count; ++i) {
|
||||
auto const srcItem = std::launder(reinterpret_cast<T*>(&src->m_data[i]));
|
||||
@@ -65,6 +69,9 @@ struct VectorAllocator {
|
||||
*items = reinterpret_cast<T*>(m_data.data());
|
||||
}
|
||||
}
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -43,7 +43,7 @@ uint64_t timeMapStrToUuid(int const elemCnt, int const lookups, uint64_t seed =
|
||||
// start
|
||||
auto const startTime = steadyNowMs();
|
||||
for (int i = 0; i < lookups; ++i) {
|
||||
auto const &k = keys[rand.gen() % keys.size()];
|
||||
auto const &k = keys[static_cast<size_t>(rand.gen() % keys.size())];
|
||||
map[k];
|
||||
ox::expect(map[k], ox::UUID::fromString(k).unwrap());
|
||||
}
|
||||
@@ -65,7 +65,7 @@ uint64_t timeMapUuidToStr(int const elemCnt, int const lookups, uint64_t seed =
|
||||
// start
|
||||
auto const startTime = steadyNowMs();
|
||||
for (int i = 0; i < lookups; ++i) {
|
||||
auto const &k = keys[rand.gen() % keys.size()];
|
||||
auto const &k = keys[static_cast<size_t>(rand.gen() % keys.size())];
|
||||
ox::expect(map[k], k.toString());
|
||||
}
|
||||
return steadyNowMs() - startTime;
|
||||
|
||||
+1
-4
@@ -7,6 +7,7 @@
|
||||
#include <ox/clargs/clargs.hpp>
|
||||
#include <ox/std/trace.hpp>
|
||||
|
||||
#include <studio/context.hpp>
|
||||
#include <studio/project.hpp>
|
||||
|
||||
#include <nostalgia/gfx/palette.hpp>
|
||||
@@ -14,10 +15,6 @@
|
||||
|
||||
#include "export-tilesheet.hpp"
|
||||
|
||||
#include "nostalgia/gfx/tilesheet.hpp"
|
||||
#include "studio/context.hpp"
|
||||
|
||||
|
||||
namespace nostalgia::gfx {
|
||||
|
||||
static ox::Vector<uint32_t> normalizePixelSizes(
|
||||
|
||||
@@ -155,19 +155,20 @@ void TileSheetEditorImGui::draw(studio::Context&) noexcept {
|
||||
}
|
||||
}
|
||||
}
|
||||
auto const scale = turbine::scale(m_tctx);
|
||||
auto const paneSize = ImGui::GetContentRegionAvail();
|
||||
auto const tileSheetParentSize = ImVec2{paneSize.x - s_palViewWidth, paneSize.y};
|
||||
auto const fbSize = ox::Vec2{tileSheetParentSize.x - 16, tileSheetParentSize.y - 16};
|
||||
auto const tileSheetParentSize = ImVec2{paneSize.x - s_palViewWidth * scale, paneSize.y};
|
||||
auto const fbSize = ox::Vec2{tileSheetParentSize.x - 16 * scale, tileSheetParentSize.y - 16 * scale};
|
||||
ImGui::BeginChild("TileSheetView", tileSheetParentSize, true);
|
||||
{
|
||||
drawTileSheet(fbSize);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginChild("Controls", {s_palViewWidth - 8, paneSize.y}, true);
|
||||
ImGui::BeginChild("Controls", {(s_palViewWidth - 8) * scale, paneSize.y}, true);
|
||||
{
|
||||
auto const controlsSize = ImGui::GetContentRegionAvail();
|
||||
ImGui::BeginChild("ToolBox", {0, 32}, true);
|
||||
ImGui::BeginChild("ToolBox", {0, 32 * scale}, true);
|
||||
{
|
||||
auto const btnSz = ImVec2{45, 14};
|
||||
if (ImGui::Selectable("Select", m_tool == TileSheetTool::Select, 0, btnSz)) {
|
||||
@@ -193,7 +194,7 @@ void TileSheetEditorImGui::draw(studio::Context&) noexcept {
|
||||
//ig::ComboBox("##Operations", ox::Array<ox::CStringView, 1>{"Operations"}, i);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::BeginChild("OperationsBox", {0, 35}, ImGuiWindowFlags_NoTitleBar);
|
||||
ImGui::BeginChild("OperationsBox", {0, 35 * scale}, ImGuiWindowFlags_NoTitleBar);
|
||||
{
|
||||
if (ImGui::BeginCombo("##Operations", "Operations", 0)) {
|
||||
if (ImGui::Selectable("Flip X", false)) {
|
||||
@@ -216,12 +217,12 @@ void TileSheetEditorImGui::draw(studio::Context&) noexcept {
|
||||
ImGui::EndChild();
|
||||
auto const ySize = controlsSize.y - (38 + ig::BtnSz.y + 21);
|
||||
// draw palette/color picker
|
||||
ImGui::BeginChild("Palette", {s_palViewWidth - 24, ySize / 2.f}, true);
|
||||
ImGui::BeginChild("Palette", {(s_palViewWidth - 24) * scale, ySize / 2.f}, true);
|
||||
{
|
||||
drawPaletteMenu();
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::BeginChild("SubSheets", {s_palViewWidth - 24, ySize / 2.f}, true);
|
||||
ImGui::BeginChild("SubSheets", {(s_palViewWidth - 24) * scale, ySize / 2.f}, true);
|
||||
{
|
||||
static constexpr auto btnHeight = ig::BtnSz.y;
|
||||
auto constexpr btnSize = ImVec2{btnHeight, btnHeight};
|
||||
|
||||
@@ -47,3 +47,5 @@ install(
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION lib
|
||||
)
|
||||
|
||||
add_subdirectory(subcommands)
|
||||
@@ -14,24 +14,69 @@
|
||||
#include <studio/context.hpp>
|
||||
#include <studioapp/studioapp.hpp>
|
||||
|
||||
#include "subcommands/change-format/change-format.hpp"
|
||||
|
||||
#include "configfile.hpp"
|
||||
#include "font.hpp"
|
||||
#include "studioui.hpp"
|
||||
|
||||
namespace studio {
|
||||
|
||||
static ox::Error convertStudioConfigV1ToStudioConfigV2(
|
||||
keel::Context&,
|
||||
StudioConfigV1 &src,
|
||||
StudioConfigV2 &dst) noexcept {
|
||||
dst.projects.emplace_back(StudioConfigV2::ProjectConfig{
|
||||
.projectPath = std::move(src.projectPath),
|
||||
.activeTabItemName = std::move(src.activeTabItemName),
|
||||
.openFiles = std::move(src.openFiles),
|
||||
});
|
||||
dst.showProjectExplorer = src.showProjectExplorer;
|
||||
return {};
|
||||
}
|
||||
|
||||
static struct: Module {
|
||||
ox::String id() const noexcept final {
|
||||
return ox::String{"net.drinkingtea.studio"};
|
||||
}
|
||||
|
||||
ox::Vector<Command> commands() const final {
|
||||
return {
|
||||
{
|
||||
"change-format",
|
||||
cmdChangeFormat,
|
||||
}
|
||||
};
|
||||
}
|
||||
} constexpr mod;
|
||||
|
||||
static struct: keel::Module {
|
||||
ox::String id() const noexcept override {
|
||||
return ox::String{"net.drinkingtea.studio"};
|
||||
}
|
||||
|
||||
ox::Vector<keel::Converter> converters() const noexcept override {
|
||||
return {
|
||||
keel::Converter::make<convertStudioConfigV1ToStudioConfigV2>(),
|
||||
};
|
||||
}
|
||||
} constexpr kmod;
|
||||
|
||||
|
||||
class StudioUIDrawer: public turbine::gl::Drawer {
|
||||
private:
|
||||
StudioUI &m_ui;
|
||||
public:
|
||||
explicit StudioUIDrawer(StudioUI &ui) noexcept: m_ui(ui) {
|
||||
}
|
||||
protected:
|
||||
|
||||
void draw(turbine::Context&) noexcept final {
|
||||
m_ui.draw();
|
||||
}
|
||||
};
|
||||
|
||||
static void keyEventHandler(turbine::Context &ctx, turbine::Key key, bool down) noexcept {
|
||||
auto const sctx = turbine::applicationData<studio::Context>(ctx);
|
||||
static void keyEventHandler(turbine::Context &ctx, turbine::Key const key, bool const down) noexcept {
|
||||
auto const sctx = turbine::applicationData<Context>(ctx);
|
||||
sctx->ui.handleKeyEvent(key, down);
|
||||
}
|
||||
|
||||
@@ -65,6 +110,8 @@ static ox::Error run(
|
||||
ox::StringViewCR appName,
|
||||
ox::StringViewCR projectDataDir,
|
||||
ox::SpanView<ox::CString> const &args) {
|
||||
keel::registerModule(kmod);
|
||||
registerModule(&mod);
|
||||
// seed UUID generator
|
||||
auto const time = std::time(nullptr);
|
||||
ox::UUID::seedGenerator({
|
||||
@@ -83,7 +130,7 @@ static ox::Error run(
|
||||
if (m->id() == moduleId) {
|
||||
for (auto const &c : m->commands()) {
|
||||
if (c.name == subCmd) {
|
||||
auto kctx = keel::init(
|
||||
auto const kctx = keel::init(
|
||||
ox::make_unique<ox::PassThroughFS>(projectDir),
|
||||
c.name);
|
||||
if (kctx.error) {
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/string.hpp>
|
||||
#include <ox/std/vector.hpp>
|
||||
|
||||
#include <ox/model/def.hpp>
|
||||
|
||||
namespace studio {
|
||||
|
||||
struct StudioConfigV1 {
|
||||
static constexpr auto TypeName = "net.drinkingtea.studio.StudioConfig";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
ox::String projectPath;
|
||||
ox::String activeTabItemName;
|
||||
ox::Vector<ox::String> openFiles;
|
||||
bool showProjectExplorer = true;
|
||||
};
|
||||
|
||||
OX_MODEL_BEGIN(StudioConfigV1)
|
||||
OX_MODEL_FIELD_RENAME(activeTabItemName, active_tab_item_name)
|
||||
OX_MODEL_FIELD_RENAME(projectPath, project_path)
|
||||
OX_MODEL_FIELD_RENAME(openFiles, open_files)
|
||||
OX_MODEL_FIELD_RENAME(showProjectExplorer, show_project_explorer)
|
||||
OX_MODEL_END()
|
||||
|
||||
|
||||
struct StudioConfigV2 {
|
||||
static constexpr auto TypeName = "net.drinkingtea.studio.StudioConfig";
|
||||
static constexpr auto TypeVersion = 2;
|
||||
struct ProjectConfig {
|
||||
static constexpr auto TypeName = "net.drinkingtea.studio.ProjectConfig";
|
||||
static constexpr auto TypeVersion = 2;
|
||||
ox::String projectPath;
|
||||
ox::String activeTabItemName;
|
||||
ox::Vector<ox::String> openFiles;
|
||||
};
|
||||
ox::Vector<ProjectConfig> projects;
|
||||
bool showProjectExplorer = true;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ProjectConfig const *project() const {
|
||||
return projects.empty() ? nullptr : &projects[0];
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ProjectConfig *project() {
|
||||
return projects.empty() ? nullptr : &projects[0];
|
||||
}
|
||||
};
|
||||
|
||||
OX_MODEL_BEGIN(StudioConfigV2::ProjectConfig)
|
||||
OX_MODEL_FIELD_RENAME(activeTabItemName, active_tab_item_name)
|
||||
OX_MODEL_FIELD_RENAME(projectPath, project_path)
|
||||
OX_MODEL_FIELD_RENAME(openFiles, open_files)
|
||||
OX_MODEL_END()
|
||||
|
||||
OX_MODEL_BEGIN(StudioConfigV2)
|
||||
OX_MODEL_FIELD(projects)
|
||||
OX_MODEL_FIELD_RENAME(showProjectExplorer, show_project_explorer)
|
||||
OX_MODEL_END()
|
||||
|
||||
using StudioConfig = StudioConfigV2;
|
||||
|
||||
}
|
||||
@@ -132,7 +132,11 @@ StudioUI::StudioUI(turbine::Context &tctx, ox::StringParam projectDataDir) noexc
|
||||
// that it will still be treated as const.
|
||||
// ImGui documentation recognizes that this is a bad design,
|
||||
// and hopefully it will change at some point.
|
||||
io.Fonts->AddFontFromMemoryTTF(const_cast<uint8_t*>(font.data()), static_cast<int>(font.size()), 13, &fontCfg);
|
||||
io.Fonts->AddFontFromMemoryTTF(
|
||||
const_cast<uint8_t*>(font.data()),
|
||||
static_cast<int>(font.size()),
|
||||
13 * turbine::scale(m_tctx),
|
||||
&fontCfg);
|
||||
}
|
||||
auto &kctx = keelCtx(m_tctx);
|
||||
kctx.converters.emplace_back(keel::Converter::make<convertStudioConfigV1ToStudioConfigV2>());
|
||||
@@ -215,7 +219,7 @@ void StudioUI::draw() noexcept {
|
||||
ImGuiFocusedFlags_RootAndChildWindows | ImGuiFocusedFlags_NoPopupHierarchy);
|
||||
if (m_showProjectExplorer) {
|
||||
auto const v = ImGui::GetContentRegionAvail();
|
||||
m_projectExplorer.draw(m_sctx, {300, v.y});
|
||||
m_projectExplorer.draw(m_sctx, {300 * turbine::scale(m_tctx), v.y});
|
||||
ImGui::SameLine();
|
||||
}
|
||||
drawTabBar();
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
target_sources(
|
||||
StudioAppLib PRIVATE
|
||||
change-format/change-format.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
StudioAppLib PUBLIC
|
||||
OxClArgs
|
||||
)
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2016 - 2026 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <ox/clargs/clargs.hpp>
|
||||
#include <ox/std/trace.hpp>
|
||||
|
||||
#include <studio/project.hpp>
|
||||
|
||||
#include "change-format.hpp"
|
||||
|
||||
namespace studio {
|
||||
|
||||
static ox::Error convertFile(
|
||||
ox::FileSystem &fs,
|
||||
ox::TypeStore &ts,
|
||||
ox::StringViewCR path,
|
||||
ox::ClawFormat const fmt) noexcept {
|
||||
OX_REQUIRE_M(buff, fs.read(path).reoriginate(1, "unable to read file"));
|
||||
OX_REQUIRE(uuid, keel::readUuidHeader(buff));
|
||||
OX_REQUIRE(obj, keel::readAsset(ts, buff).reoriginate(1, "unable to parse file"));
|
||||
buff.clear();
|
||||
ox::BufferWriter writer{&buff};
|
||||
OX_RETURN_ERROR(keel::writeUuidHeader(writer, uuid));
|
||||
OX_RETURN_ERROR(ox::writeClaw(obj, writer, fmt));
|
||||
if (fmt == ox::ClawFormat::Organic) {
|
||||
*buff.back().value = '\n';
|
||||
}
|
||||
OX_RETURN_ERROR(fs.write(path, buff).reoriginate(1, "unable to write file"));
|
||||
return {};
|
||||
}
|
||||
|
||||
static void printUsage() noexcept {
|
||||
oxErr("usage: change-format {mc,oc} [files...]\n");
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr ox::Result<ox::ClawFormat> getFmt(ox::StringViewCR fmtStr) noexcept {
|
||||
if (caseInsensitiveStrCmp(fmtStr, "mc") == 0) {
|
||||
return ox::ClawFormat::Metal;
|
||||
} else if (caseInsensitiveStrCmp(fmtStr, "oc") == 0) {
|
||||
return ox::ClawFormat::Organic;
|
||||
}
|
||||
return ox::Error{1, "invalid format"};
|
||||
}
|
||||
|
||||
ox::Error cmdChangeFormat(Project &project, ox::SpanView<ox::CString> const args) noexcept {
|
||||
if (args.size() < 2) {
|
||||
printUsage();
|
||||
return ox::Error{1, "invalid input"};
|
||||
}
|
||||
auto const [fmt, fmtErr] = getFmt(args[0]);
|
||||
if (fmtErr) {
|
||||
printUsage();
|
||||
}
|
||||
auto &fs = project.romFs();
|
||||
auto &ts = project.typeStore();
|
||||
for (auto const &file : args + 1) {
|
||||
auto const err = convertFile(fs, ts, file, fmt);
|
||||
if (err) {
|
||||
oxErrf("Failed to convert {}: {}\n", file, err.msg);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright 2016 - 2026 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <studio/project.hpp>
|
||||
|
||||
namespace studio {
|
||||
|
||||
ox::Error cmdChangeFormat(Project &project, ox::SpanView<ox::CString> args) noexcept;
|
||||
|
||||
}
|
||||
@@ -122,6 +122,16 @@ class Project: public ox::SignalHandler {
|
||||
|
||||
ox::Error writeTypeStore() noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ox::TypeStore &typeStore() noexcept {
|
||||
return m_typeStore;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ox::TypeStore const &typeStore() const noexcept {
|
||||
return m_typeStore;
|
||||
}
|
||||
|
||||
private:
|
||||
void buildFileIndex() noexcept;
|
||||
|
||||
@@ -155,7 +165,7 @@ template<typename T>
|
||||
ox::Error Project::writeObj(ox::StringViewCR path, T const &obj, ox::ClawFormat fmt) noexcept {
|
||||
OX_REQUIRE_M(buff, ox::writeClaw(obj, fmt));
|
||||
if (fmt == ox::ClawFormat::Organic) {
|
||||
buff.pop_back();
|
||||
*buff.back().value = '\n';
|
||||
}
|
||||
// write to FS
|
||||
OX_RETURN_ERROR(mkdir(parentDir(path)));
|
||||
|
||||
@@ -14,13 +14,15 @@
|
||||
namespace studio {
|
||||
|
||||
static_assert(fileExt("main.c").value == "c");
|
||||
static_assert(fileExt("main.cc").value == "cc");
|
||||
static_assert(fileExt("main.cpp").value == "cpp");
|
||||
static_assert(fileExt("a.b.c").value == "c");
|
||||
static_assert(parentDir("/a/b/c") == "/a/b");
|
||||
static_assert(parentDir("/a/b/c/") == "/a/b");
|
||||
|
||||
static void generateTypes(ox::TypeStore &ts) noexcept {
|
||||
for (auto const mod : keel::modules()) {
|
||||
for (auto gen : mod->types()) {
|
||||
for (auto const gen : mod->types()) {
|
||||
oxLogError(gen(ts));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,4 +112,7 @@ void setShutdownHandler(Context &ctx, ShutdownHandler handler) noexcept;
|
||||
// sleep time is a minimum of ~16 milliseconds.
|
||||
void setUpdateHandler(Context &ctx, UpdateHandler) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
float scale(Context const &ctx) noexcept;
|
||||
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ class Context {
|
||||
uint64_t draws = 0;
|
||||
bool running{};
|
||||
ShutdownHandler shutdownHandler{};
|
||||
float scale{};
|
||||
|
||||
Context() noexcept = default;
|
||||
|
||||
|
||||
@@ -339,6 +339,7 @@ ox::Result<ox::UPtr<Context>> init(
|
||||
setMandatoryRefreshPeriod(*ctx, ticksMs(*ctx) + config::MandatoryRefreshPeriod);
|
||||
// init GLFW context
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_SCALE_TO_MONITOR, GLFW_TRUE);
|
||||
glfwSetErrorCallback(handleGlfwError);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
@@ -372,7 +373,13 @@ ox::Result<ox::UPtr<Context>> init(
|
||||
ImGui_ImplGlfw_InitForOpenGL(ctx->window, true);
|
||||
ImGui_ImplOpenGL3_Init();
|
||||
io.IniFilename = nullptr;
|
||||
float xscale{}, yscale{};
|
||||
glfwGetWindowContentScale(ctx->window, &xscale, &yscale);
|
||||
ctx->scale = ox::max(xscale, yscale);
|
||||
io.DisplayFramebufferScale = ImVec2(ctx->scale, ctx->scale);
|
||||
themeImgui();
|
||||
auto &style = ImGui::GetStyle();
|
||||
style.ScaleAllSizes(ctx->scale);
|
||||
#endif
|
||||
return ctx;
|
||||
}
|
||||
@@ -471,4 +478,8 @@ KeyEventHandler keyEventHandler(Context const &ctx) noexcept {
|
||||
return ctx.keyEventHandler;
|
||||
}
|
||||
|
||||
float scale(Context const &ctx) noexcept {
|
||||
return ctx.scale;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user