Tidy up footprint of app libray
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
cf8124eb20
commit
ba5bc0674c
529
source/app.cpp
529
source/app.cpp
|
@ -12,270 +12,213 @@ import coral.math;
|
||||||
|
|
||||||
import oar;
|
import oar;
|
||||||
|
|
||||||
namespace app {
|
using native_path = coral::fixed_buffer<4096>;
|
||||||
struct directory : public coral::fs {
|
|
||||||
struct rules {
|
|
||||||
bool can_read;
|
|
||||||
|
|
||||||
bool can_write;
|
struct native_file : public coral::file_reader, public coral::file_writer {
|
||||||
};
|
enum class open_mode {
|
||||||
|
read_only,
|
||||||
virtual rules access_rules() const = 0;
|
overwrite,
|
||||||
|
|
||||||
virtual coral::slice<char const> native_path() const = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct file : public coral::file_reader, public coral::file_writer {
|
enum class [[nodiscard]] close_result {
|
||||||
enum class open_mode {
|
ok,
|
||||||
read_only,
|
io_unavailable,
|
||||||
overwrite,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class [[nodiscard]] close_result {
|
|
||||||
ok,
|
|
||||||
io_unavailable,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class [[nodiscard]] open_result {
|
|
||||||
ok,
|
|
||||||
io_unavailable,
|
|
||||||
access_denied,
|
|
||||||
not_found,
|
|
||||||
};
|
|
||||||
|
|
||||||
file(directory * file_directory) : rw_ops{nullptr} {
|
|
||||||
this->file_directory = file_directory;
|
|
||||||
}
|
|
||||||
|
|
||||||
close_result close() {
|
|
||||||
if (::SDL_RWclose(this->rw_ops) != 0) return close_result::io_unavailable;
|
|
||||||
|
|
||||||
this->rw_ops = nullptr;
|
|
||||||
|
|
||||||
return close_result::ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_open() const {
|
|
||||||
return this->rw_ops != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
open_result open(coral::path const & file_path, open_mode mode) {
|
|
||||||
if (this->is_open()) switch (this->close()) {
|
|
||||||
case close_result::ok: break;
|
|
||||||
case close_result::io_unavailable: return open_result::io_unavailable;
|
|
||||||
default: coral::unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Windows system path max is something like 512 bytes (depending on the version) and
|
|
||||||
// on Linux it's 4096.
|
|
||||||
coral::fixed_buffer<4096> path_buffer{0};
|
|
||||||
|
|
||||||
if (!path_buffer.write(this->file_directory->native_path().as_bytes()).is_ok())
|
|
||||||
// What kind of directory path is being used that would be longer than 4096 bytes?
|
|
||||||
return open_result::not_found;
|
|
||||||
|
|
||||||
if (!path_buffer.write(file_path.as_slice().as_bytes()).is_ok())
|
|
||||||
// This happening is still implausible but slightly more reasonable?
|
|
||||||
return open_result::not_found;
|
|
||||||
|
|
||||||
// No room for zero terminator.
|
|
||||||
if (path_buffer.is_full()) return open_result::not_found;
|
|
||||||
|
|
||||||
switch (mode) {
|
|
||||||
case open_mode::read_only: {
|
|
||||||
if (!this->file_directory->access_rules().can_read)
|
|
||||||
return open_result::access_denied;
|
|
||||||
|
|
||||||
this->rw_ops = ::SDL_RWFromFile(
|
|
||||||
reinterpret_cast<char const *>(path_buffer.begin()), "rb");
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case open_mode::overwrite: {
|
|
||||||
if (!this->file_directory->access_rules().can_write)
|
|
||||||
return open_result::access_denied;
|
|
||||||
|
|
||||||
this->rw_ops = ::SDL_RWFromFile(
|
|
||||||
reinterpret_cast<char const *>(path_buffer.begin()), "wb");
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: coral::unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->rw_ops == nullptr) return open_result::not_found;
|
|
||||||
|
|
||||||
return open_result::ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
coral::expected<coral::usize, coral::io_error> read(coral::slice<coral::u8> const & data) override {
|
|
||||||
if (!this->is_open()) return coral::io_error::unavailable;
|
|
||||||
|
|
||||||
coral::usize const data_read{::SDL_RWread(this->rw_ops, data.pointer, sizeof(uint8_t), data.length)};
|
|
||||||
|
|
||||||
if ((data_read == 0) && (::SDL_GetError() != nullptr)) return coral::io_error::unavailable;
|
|
||||||
|
|
||||||
return data_read;
|
|
||||||
}
|
|
||||||
|
|
||||||
coral::expected<coral::u64, coral::io_error> seek(coral::u64 offset) override {
|
|
||||||
if (!this->is_open()) return coral::io_error::unavailable;
|
|
||||||
|
|
||||||
// TODO: Fix cast.
|
|
||||||
coral::i64 const byte_position{
|
|
||||||
::SDL_RWseek(this->rw_ops, static_cast<coral::i64>(offset), RW_SEEK_SET)};
|
|
||||||
|
|
||||||
if (byte_position == -1) return coral::io_error::unavailable;
|
|
||||||
|
|
||||||
return static_cast<coral::u64>(byte_position);
|
|
||||||
}
|
|
||||||
|
|
||||||
coral::expected<coral::u64, coral::io_error> tell() override {
|
|
||||||
if (!this->is_open()) return coral::io_error::unavailable;
|
|
||||||
|
|
||||||
coral::i64 const byte_position{::SDL_RWseek(this->rw_ops, 0, RW_SEEK_SET)};
|
|
||||||
|
|
||||||
if (byte_position == -1) return coral::io_error::unavailable;
|
|
||||||
|
|
||||||
return static_cast<coral::u64>(byte_position);
|
|
||||||
}
|
|
||||||
|
|
||||||
coral::expected<coral::usize, coral::io_error> write(coral::slice<coral::u8 const> const & data) override {
|
|
||||||
if (!this->is_open()) return coral::io_error::unavailable;
|
|
||||||
|
|
||||||
coral::usize const data_written{::SDL_RWwrite(this->rw_ops, data.pointer, sizeof(uint8_t), data.length)};
|
|
||||||
|
|
||||||
if ((data_written == 0) && (::SDL_GetError() != nullptr)) return coral::io_error::unavailable;
|
|
||||||
|
|
||||||
return data_written;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
directory * file_directory;
|
|
||||||
|
|
||||||
::SDL_RWops * rw_ops;
|
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
struct base_directory : public app::directory {
|
enum class [[nodiscard]] open_result {
|
||||||
base_directory() : directory_path{} {
|
ok,
|
||||||
char * const path{::SDL_GetBasePath()};
|
io_unavailable,
|
||||||
|
access_denied,
|
||||||
|
not_found,
|
||||||
|
};
|
||||||
|
|
||||||
if (path == nullptr) return;
|
native_file() = default;
|
||||||
|
|
||||||
coral::usize path_length{0};
|
close_result close() {
|
||||||
|
if (SDL_RWclose(this->rw_ops) != 0) return close_result::io_unavailable;
|
||||||
|
|
||||||
while (path[path_length] != 0) path_length += 1;
|
this->rw_ops = nullptr;
|
||||||
|
|
||||||
if (path_length == 0) {
|
return close_result::ok;
|
||||||
::SDL_free(path);
|
}
|
||||||
|
|
||||||
return;
|
bool is_open() const {
|
||||||
|
return this->rw_ops != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
open_result open(native_path const & file_path, open_mode mode) {
|
||||||
|
if (this->is_open()) switch (this->close()) {
|
||||||
|
case close_result::ok: break;
|
||||||
|
case close_result::io_unavailable: return open_result::io_unavailable;
|
||||||
|
default: coral::unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->directory_path = {path, path_length};
|
// No room for zero terminator.
|
||||||
|
if (file_path.is_full()) return open_result::not_found;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case open_mode::read_only: {
|
||||||
|
this->rw_ops = SDL_RWFromFile(file_path.as_slice().as_chars().begin(), "rb");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case open_mode::overwrite: {
|
||||||
|
this->rw_ops = SDL_RWFromFile(file_path.as_slice().as_chars().begin(), "wb");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: coral::unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->rw_ops == nullptr) return open_result::not_found;
|
||||||
|
|
||||||
|
return open_result::ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
~base_directory() override {
|
coral::expected<coral::usize, coral::io_error> read(coral::slice<coral::u8> const & data) override {
|
||||||
::SDL_free(this->directory_path.begin());
|
if (!this->is_open()) return coral::io_error::unavailable;
|
||||||
|
|
||||||
|
coral::usize const data_read{SDL_RWread(this->rw_ops, data.pointer, sizeof(uint8_t), data.length)};
|
||||||
|
|
||||||
|
if ((data_read == 0) && (SDL_GetError() != nullptr)) return coral::io_error::unavailable;
|
||||||
|
|
||||||
|
return data_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
rules access_rules() const override {
|
coral::expected<coral::u64, coral::io_error> seek(coral::u64 offset) override {
|
||||||
return {
|
if (!this->is_open()) return coral::io_error::unavailable;
|
||||||
.can_read = true,
|
|
||||||
.can_write = false,
|
// TODO: Fix cast.
|
||||||
};
|
coral::i64 const byte_position{
|
||||||
|
SDL_RWseek(this->rw_ops, static_cast<coral::i64>(offset), RW_SEEK_SET)};
|
||||||
|
|
||||||
|
if (byte_position == -1) return coral::io_error::unavailable;
|
||||||
|
|
||||||
|
return static_cast<coral::u64>(byte_position);
|
||||||
}
|
}
|
||||||
|
|
||||||
coral::slice<const char> native_path() const override {
|
coral::expected<coral::u64, coral::io_error> tell() override {
|
||||||
return this->directory_path;
|
if (!this->is_open()) return coral::io_error::unavailable;
|
||||||
|
|
||||||
|
coral::i64 const byte_position{SDL_RWseek(this->rw_ops, 0, RW_SEEK_SET)};
|
||||||
|
|
||||||
|
if (byte_position == -1) return coral::io_error::unavailable;
|
||||||
|
|
||||||
|
return static_cast<coral::u64>(byte_position);
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_file(coral::path const & file_path, coral::callable<void(coral::file_reader &)> const & then) override {
|
coral::expected<coral::usize, coral::io_error> write(coral::slice<coral::u8 const> const & data) override {
|
||||||
if (this->directory_path.length == 0) return;
|
if (!this->is_open()) return coral::io_error::unavailable;
|
||||||
|
|
||||||
app::file file{this};
|
coral::usize const data_written{SDL_RWwrite(this->rw_ops, data.pointer, sizeof(uint8_t), data.length)};
|
||||||
|
|
||||||
if (file.open(file_path, app::file::open_mode::read_only) != app::file::open_result::ok)
|
if ((data_written == 0) && (SDL_GetError() != nullptr)) return coral::io_error::unavailable;
|
||||||
return;
|
|
||||||
|
|
||||||
then(file);
|
return data_written;
|
||||||
|
|
||||||
if (file.close() != app::file::close_result::ok) return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_file(coral::path const & file_path, coral::callable<void(coral::file_writer &)> const & then) override {
|
private:
|
||||||
// Directory is read-only.
|
SDL_RWops * rw_ops{nullptr};
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
coral::slice<char> directory_path;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct user_directory : public app::directory {
|
struct sandboxed_fs : public coral::fs {
|
||||||
user_directory(coral::path const & title) : directory_path{} {
|
sandboxed_fs() {
|
||||||
char * const path{::SDL_GetPrefPath("ona", title.begin())};
|
char * const path{SDL_GetBasePath()};
|
||||||
|
|
||||||
if (path == nullptr) return;
|
if (path == nullptr) return;
|
||||||
|
|
||||||
coral::usize path_length{0};
|
for (coral::usize index = 0; path[index] != 0; index += 1)
|
||||||
|
this->sandbox_path.put(path[index]);
|
||||||
|
|
||||||
while (path[path_length] != 0) path_length += 1;
|
SDL_free(path);
|
||||||
|
|
||||||
if (path_length == 0) {
|
this->access_rules.can_read = true;
|
||||||
::SDL_free(path);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->directory_path = {path, path_length};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~user_directory() override {
|
sandboxed_fs(coral::path const & organization_name, coral::path const & app_name) {
|
||||||
::SDL_free(this->directory_path.begin());
|
char * const path{SDL_GetPrefPath(organization_name.begin(), app_name.begin())};
|
||||||
|
|
||||||
|
if (path == nullptr) return;
|
||||||
|
|
||||||
|
for (coral::usize index = 0; path[index] != 0; index += 1)
|
||||||
|
this->sandbox_path.put(path[index]);
|
||||||
|
|
||||||
|
SDL_free(path);
|
||||||
|
|
||||||
|
this->access_rules.can_read = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
rules access_rules() const override {
|
access_rules query_access() override {
|
||||||
return {
|
return this->access_rules;
|
||||||
.can_read = true,
|
|
||||||
.can_write = false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
coral::slice<const char> native_path() const override {
|
|
||||||
return this->directory_path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_file(coral::path const & file_path, coral::callable<void(coral::file_reader &)> const & then) override {
|
void read_file(coral::path const & file_path, coral::callable<void(coral::file_reader &)> const & then) override {
|
||||||
if (this->directory_path.length == 0) return;
|
if (!this->access_rules.can_read) return;
|
||||||
|
|
||||||
app::file file{this};
|
native_path sandbox_file_path{0};
|
||||||
|
{
|
||||||
|
coral::expected const written = sandbox_file_path.write(this->sandbox_path.as_slice());
|
||||||
|
|
||||||
if (file.open(file_path, app::file::open_mode::read_only) != app::file::open_result::ok)
|
if (!written.is_ok() || (written.value() != this->sandbox_path.count())) return;
|
||||||
return;
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
coral::expected const written =
|
||||||
|
sandbox_file_path.write(file_path.as_slice().as_bytes());
|
||||||
|
|
||||||
|
if (!written.is_ok() || (written.value() != this->sandbox_path.count())) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
native_file file;
|
||||||
|
|
||||||
|
if (file.open(sandbox_file_path, native_file::open_mode::read_only) !=
|
||||||
|
native_file::open_result::ok) return;
|
||||||
|
|
||||||
then(file);
|
then(file);
|
||||||
|
|
||||||
if (file.close() != app::file::close_result::ok) return;
|
if (file.close() != native_file::close_result::ok)
|
||||||
|
// Error orphaned file handle!
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_file(coral::path const & file_path, coral::callable<void(coral::file_writer &)> const & then) override {
|
void write_file(coral::path const & file_path, coral::callable<void(coral::file_writer &)> const & then) override {
|
||||||
if (this->directory_path.length == 0) return;
|
if (!this->access_rules.can_write) return;
|
||||||
|
|
||||||
app::file file{this};
|
native_path sandbox_file_path{0};
|
||||||
|
{
|
||||||
|
coral::expected const written = sandbox_file_path.write(this->sandbox_path.as_slice());
|
||||||
|
|
||||||
if (file.open(file_path, app::file::open_mode::overwrite) != app::file::open_result::ok)
|
if (!written.is_ok() || (written.value() != this->sandbox_path.count())) return;
|
||||||
return;
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
coral::expected const written =
|
||||||
|
sandbox_file_path.write(file_path.as_slice().as_bytes());
|
||||||
|
|
||||||
|
if (!written.is_ok() || (written.value() != this->sandbox_path.count())) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
native_file file;
|
||||||
|
|
||||||
|
if (file.open(sandbox_file_path, native_file::open_mode::overwrite) !=
|
||||||
|
native_file::open_result::ok) return;
|
||||||
|
|
||||||
then(file);
|
then(file);
|
||||||
|
|
||||||
if (file.close() != app::file::close_result::ok) return;
|
if (file.close() != native_file::close_result::ok)
|
||||||
|
// Error orphaned file handle!
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
coral::slice<char> directory_path;
|
native_path sandbox_path{0};
|
||||||
|
|
||||||
|
access_rules access_rules{
|
||||||
|
.can_read = false,
|
||||||
|
.can_write = false,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export namespace app {
|
export namespace app {
|
||||||
|
@ -285,17 +228,27 @@ export namespace app {
|
||||||
error,
|
error,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct system {
|
struct client {
|
||||||
system(coral::path const & title) : user_directory{title},
|
coral::fs & base() {
|
||||||
res_archive{&base_directory, res_archive_path} {}
|
return this->base_sandbox;
|
||||||
|
}
|
||||||
|
|
||||||
app::directory & base_dir() {
|
void display(coral::u16 screen_width, coral::u16 screen_height) {
|
||||||
return this->base_directory;
|
SDL_SetWindowSize(this->window, screen_width, screen_height);
|
||||||
|
SDL_ShowWindow(this->window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log(log_level level, coral::slice<char const> const & message) {
|
||||||
|
coral::i32 const length{static_cast<coral::i32>(
|
||||||
|
coral::min(message.length, static_cast<size_t>(coral::i32_max)))};
|
||||||
|
|
||||||
|
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION,
|
||||||
|
SDL_LOG_PRIORITY_INFO, "%.*s", length, message.pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool poll() {
|
bool poll() {
|
||||||
while (::SDL_PollEvent(&this->sdl_event) != 0) {
|
while (SDL_PollEvent(&this->event) != 0) {
|
||||||
switch (this->sdl_event.type) {
|
switch (this->event.type) {
|
||||||
case SDL_QUIT: return false;
|
case SDL_QUIT: return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -303,124 +256,62 @@ export namespace app {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
coral::fs & res_fs() {
|
coral::fs & resources() {
|
||||||
return this->res_archive;
|
return this->resources_archive;
|
||||||
}
|
}
|
||||||
|
|
||||||
void log(app::log_level level, coral::slice<char const> const & message) {
|
static int run(coral::path const & title, coral::callable<int(client &)> const & start) {
|
||||||
coral::i32 const length{static_cast<coral::i32>(
|
constexpr int windowpos {SDL_WINDOWPOS_UNDEFINED};
|
||||||
coral::min(message.length, static_cast<size_t>(coral::i32_max)))};
|
constexpr coral::u32 windowflags {SDL_WINDOW_HIDDEN};
|
||||||
|
constexpr int window_width {640};
|
||||||
|
constexpr int window_height {480};
|
||||||
|
|
||||||
::SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION,
|
SDL_Window * const window {SDL_CreateWindow(
|
||||||
SDL_LOG_PRIORITY_INFO, "%.*s", length, message.pointer);
|
title.begin(), windowpos, windowpos, window_width, window_height, windowflags)};
|
||||||
|
|
||||||
|
if (window == nullptr) return 0xff;
|
||||||
|
|
||||||
|
struct : public coral::allocator {
|
||||||
|
coral::u8 * reallocate(coral::u8 * allocation, coral::usize requested_size) override {
|
||||||
|
return reinterpret_cast<coral::u8 *>(SDL_realloc(allocation, requested_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(void * allocation) override {
|
||||||
|
SDL_free(allocation);
|
||||||
|
}
|
||||||
|
} allocator;
|
||||||
|
|
||||||
|
client app_client {&allocator, window, title};
|
||||||
|
|
||||||
|
return start(app_client);
|
||||||
}
|
}
|
||||||
|
|
||||||
coral::allocator & thread_safe_allocator() {
|
coral::allocator & thread_safe_allocator() {
|
||||||
return this->allocator;
|
return *this->allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
app::directory & user_dir() {
|
coral::fs & user() {
|
||||||
return this->user_directory;
|
return this->user_sandbox;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr coral::path res_archive_path{"base.oar"};
|
client(coral::allocator * allocator, SDL_Window * window,
|
||||||
|
coral::path const & title) : user_sandbox{"ona", title} {
|
||||||
|
|
||||||
::SDL_Event sdl_event;
|
this->allocator = allocator;
|
||||||
|
this->window = window;
|
||||||
|
}
|
||||||
|
|
||||||
struct : public coral::allocator {
|
coral::allocator * allocator;
|
||||||
coral::u8 * reallocate(coral::u8 * maybe_allocation, coral::usize requested_size) override {
|
|
||||||
return reinterpret_cast<coral::u8 *>(::SDL_malloc(requested_size));
|
|
||||||
}
|
|
||||||
|
|
||||||
void deallocate(void * allocation) override {
|
SDL_Window * window;
|
||||||
::SDL_free(allocation);
|
|
||||||
}
|
|
||||||
} allocator;
|
|
||||||
|
|
||||||
struct base_directory base_directory;
|
SDL_Event event;
|
||||||
|
|
||||||
struct user_directory user_directory;
|
sandboxed_fs base_sandbox;
|
||||||
|
|
||||||
oar::archive res_archive;
|
sandboxed_fs user_sandbox;
|
||||||
|
|
||||||
|
oar::archive resources_archive{&base_sandbox, "base.oar"};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct graphics {
|
|
||||||
enum class [[nodiscard]] show_result {
|
|
||||||
ok,
|
|
||||||
out_of_memory,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct canvas {
|
|
||||||
coral::color background_color;
|
|
||||||
};
|
|
||||||
|
|
||||||
graphics(coral::path const & title) {
|
|
||||||
this->retitle(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
void present() {
|
|
||||||
if (this->sdl_renderer != nullptr) {
|
|
||||||
::SDL_RenderPresent(this->sdl_renderer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void render(canvas & source_canvas) {
|
|
||||||
if (this->sdl_renderer != nullptr) {
|
|
||||||
SDL_SetRenderDrawColor(this->sdl_renderer, source_canvas.background_color.to_r8(),
|
|
||||||
source_canvas.background_color.to_g8(), source_canvas.background_color.to_b8(),
|
|
||||||
source_canvas.background_color.to_a8());
|
|
||||||
|
|
||||||
SDL_RenderClear(this->sdl_renderer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void retitle(coral::path const & title) {
|
|
||||||
this->title = title;
|
|
||||||
|
|
||||||
if (this->sdl_window != nullptr)
|
|
||||||
::SDL_SetWindowTitle(this->sdl_window, this->title.begin());
|
|
||||||
}
|
|
||||||
|
|
||||||
show_result show(coral::u16 physical_width, coral::u16 physical_height) {
|
|
||||||
if (this->sdl_window == nullptr) {
|
|
||||||
constexpr int sdl_windowpos = SDL_WINDOWPOS_UNDEFINED;
|
|
||||||
constexpr coral::u32 sdl_windowflags = 0;
|
|
||||||
|
|
||||||
this->sdl_window = ::SDL_CreateWindow(this->title.begin(), sdl_windowpos,
|
|
||||||
sdl_windowpos, static_cast<int>(physical_width), static_cast<int>(physical_height),
|
|
||||||
sdl_windowflags);
|
|
||||||
|
|
||||||
if (this->sdl_window == nullptr) return show_result::out_of_memory;
|
|
||||||
} else {
|
|
||||||
::SDL_ShowWindow(this->sdl_window);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->sdl_renderer == nullptr) {
|
|
||||||
constexpr coral::u32 sdl_rendererflags = 0;
|
|
||||||
|
|
||||||
this->sdl_renderer = ::SDL_CreateRenderer(this->sdl_window, -1, sdl_rendererflags);
|
|
||||||
|
|
||||||
if (this->sdl_renderer == nullptr) return show_result::out_of_memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
return show_result::ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
coral::path title;
|
|
||||||
|
|
||||||
::SDL_Window * sdl_window = nullptr;
|
|
||||||
|
|
||||||
::SDL_Renderer * sdl_renderer = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
using graphical_runnable = coral::callable<int(system &, graphics &)>;
|
|
||||||
|
|
||||||
int display(coral::path const & title, graphical_runnable const & run) {
|
|
||||||
system app_system{title};
|
|
||||||
graphics app_graphics{title};
|
|
||||||
|
|
||||||
return run(app_system, app_graphics);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,6 +171,13 @@ export namespace oar {
|
||||||
this->archive_path = archive_path;
|
this->archive_path = archive_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
access_rules query_access() override {
|
||||||
|
return {
|
||||||
|
.can_read = true,
|
||||||
|
.can_write = false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
void read_file(coral::path const & file_path,
|
void read_file(coral::path const & file_path,
|
||||||
coral::callable<void(coral::file_reader &)> const & then) override {
|
coral::callable<void(coral::file_reader &)> const & then) override {
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,12 @@ import coral.math;
|
||||||
import coral.sequence;
|
import coral.sequence;
|
||||||
|
|
||||||
extern "C" int main(int argc, char const * const * argv) {
|
extern "C" int main(int argc, char const * const * argv) {
|
||||||
return app::display("Ona Runtime", [](app::system & system, app::graphics & graphics) -> int {
|
return app::client::run("Ona Runtime", [](app::client & client) -> int {
|
||||||
constexpr coral::path config_path{"config.kym"};
|
constexpr coral::path config_path{"config.kym"};
|
||||||
bool is_config_loaded{false};
|
bool is_config_loaded{false};
|
||||||
|
|
||||||
system.res_fs().read_file(config_path, [&](coral::reader & file) {
|
client.resources().read_file(config_path, [&](coral::reader & file) {
|
||||||
coral::allocator * const allocator{&system.thread_safe_allocator()};
|
coral::allocator * const allocator{&client.thread_safe_allocator()};
|
||||||
|
|
||||||
coral::stack<coral::u8> script_source{allocator};
|
coral::stack<coral::u8> script_source{allocator};
|
||||||
{
|
{
|
||||||
|
@ -24,13 +24,13 @@ extern "C" int main(int argc, char const * const * argv) {
|
||||||
if (!coral::stream(script_writer, file, stream_buffer).is_ok()) return;
|
if (!coral::stream(script_writer, file, stream_buffer).is_ok()) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
system.log(app::log_level::notice, script_source.as_slice().as_chars());
|
client.log(app::log_level::notice, script_source.as_slice().as_chars());
|
||||||
|
|
||||||
is_config_loaded = true;
|
is_config_loaded = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!is_config_loaded) {
|
if (!is_config_loaded) {
|
||||||
coral::stack<coral::u8> error_message{&system.thread_safe_allocator()};
|
coral::stack<coral::u8> error_message{&client.thread_safe_allocator()};
|
||||||
{
|
{
|
||||||
coral::contiguous_writer error_writer{&error_message};
|
coral::contiguous_writer error_writer{&error_message};
|
||||||
|
|
||||||
|
@ -44,11 +44,10 @@ extern "C" int main(int argc, char const * const * argv) {
|
||||||
return coral::u8_max;
|
return coral::u8_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
// app::canvas canvas_2d();
|
client.display(1280, 800);
|
||||||
|
|
||||||
|
while (client.poll()) {
|
||||||
|
|
||||||
while (system.poll()) {
|
|
||||||
// canvas_2d.render(graphics);
|
|
||||||
graphics.present();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue