Commit for 2022.01.02 21-17-17.7z

This commit is contained in:
mrq 2022-01-02 21:17:00 -06:00
parent eef9cac83b
commit c3d320ce1a
30 changed files with 385 additions and 275 deletions

View File

@ -3,7 +3,7 @@ CC = $(shell cat "./bin/exe/default.config")
TARGET_NAME = program TARGET_NAME = program
TARGET_EXTENSION = exe TARGET_EXTENSION = exe
TARGET_LIB_EXTENSION = dll TARGET_LIB_EXTENSION = dll
RENDERER = vulkan RENDERER = opengl
include makefiles/$(ARCH).$(CC).make include makefiles/$(ARCH).$(CC).make
@ -47,11 +47,11 @@ LINKS += $(UF_LIBS) $(EXT_LIBS) $(DEPS)
DEPS += DEPS +=
ifneq (,$(findstring win64,$(ARCH))) ifneq (,$(findstring win64,$(ARCH)))
REQ_DEPS += $(RENDERER) json:nlohmann png zlib openal ogg freetype ncurses curl luajit reactphysics meshoptimizer xatlas simd ctti # openvr draco discord bullet REQ_DEPS += $(RENDERER) json:nlohmann png zlib openal ogg freetype ncurses curl luajit reactphysics meshoptimizer xatlas simd ctti # openvr draco discord bullet ultralight-ux
FLAGS += FLAGS +=
DEPS += -lgdi32 DEPS += -lgdi32
else ifneq (,$(findstring dreamcast,$(ARCH))) else ifneq (,$(findstring dreamcast,$(ARCH)))
REQ_DEPS += opengl gldc json:nlohmann lua reactphysics freetype png zlib ctti ogg openal aldc # bullet ogg openal meshoptimizer draco luajit ultralight-ux ncurses curl openvr discord REQ_DEPS += opengl gldc json:nlohmann lua reactphysics freetype png zlib ctti ogg openal aldc # bullet meshoptimizer draco luajit ultralight-ux ncurses curl openvr discord
endif endif
ifneq (,$(findstring vulkan,$(REQ_DEPS))) ifneq (,$(findstring vulkan,$(REQ_DEPS)))
FLAGS += -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN FLAGS += -DVK_USE_PLATFORM_WIN32_KHR -DUF_USE_VULKAN
@ -89,7 +89,7 @@ ifneq (,$(findstring openal,$(REQ_DEPS)))
ifneq (,$(findstring dreamcast,$(ARCH))) ifneq (,$(findstring dreamcast,$(ARCH)))
ifneq (,$(findstring aldc,$(REQ_DEPS))) ifneq (,$(findstring aldc,$(REQ_DEPS)))
DEPS += -lALdc DEPS += -lALdc
FLAGS += -DUF_USE_OPENGL_ALDC FLAGS += -DUF_USE_OPENAL_ALDC
else else
DEPS += -lAL DEPS += -lAL
endif endif
@ -240,8 +240,9 @@ $(EXT_EX_DLL): $(OBJS_EXT_DLL)
./bin/dreamcast/romdisk.o: ./bin/dreamcast/romdisk.img ./bin/dreamcast/romdisk.o: ./bin/dreamcast/romdisk.img
$(KOS_BASE)/utils/bin2o/bin2o ./bin/dreamcast/romdisk.img romdisk ./bin/dreamcast/romdisk.o $(KOS_BASE)/utils/bin2o/bin2o ./bin/dreamcast/romdisk.img romdisk ./bin/dreamcast/romdisk.o
$(TARGET): $(OBJS) ./bin/dreamcast/romdisk.o $(TARGET): $(OBJS) #./bin/dreamcast/romdisk.o
$(CXX) -O2 -fomit-frame-pointer -ml -m4-single-only -ffunction-sections -fdata-sections $(KOS_INC_PATHS) $(INCS) -D_arch_dreamcast -D_arch_sub_pristine -Wall -fno-builtin -ml -m4-single-only -Wl,-Ttext=0x8c010000 -Wl,--gc-sections -T/opt/dreamcast/kos/utils/ldscripts/shlelf.xc -nodefaultlibs $(KOS_LIB_PATHS) $(LIBS) -o $(TARGET) $(OBJS) ./bin/dreamcast/romdisk.o -Wl,--start-group $(DEPS) -Wl,--end-group # $(CXX) -O2 -fomit-frame-pointer -ml -m4-single-only -ffunction-sections -fdata-sections $(KOS_INC_PATHS) $(INCS) -D_arch_dreamcast -D_arch_sub_pristine -Wall -fno-builtin -ml -m4-single-only -Wl,-Ttext=0x8c010000 -Wl,--gc-sections -T/opt/dreamcast/kos/utils/ldscripts/shlelf.xc -nodefaultlibs $(KOS_LIB_PATHS) $(LIBS) -o $(TARGET) $(OBJS) ./bin/dreamcast/romdisk.o -Wl,--start-group $(DEPS) -Wl,--end-group
$(CXX) -O2 -fomit-frame-pointer -ml -m4-single-only -ffunction-sections -fdata-sections $(KOS_INC_PATHS) $(INCS) -D_arch_dreamcast -D_arch_sub_pristine -Wall -fno-builtin -ml -m4-single-only -Wl,-Ttext=0x8c010000 -Wl,--gc-sections -T/opt/dreamcast/kos/utils/ldscripts/shlelf.xc -nodefaultlibs $(KOS_LIB_PATHS) $(LIBS) -o $(TARGET) $(OBJS) -Wl,--start-group $(DEPS) -Wl,--end-group
./bin/dreamcast/$(TARGET_NAME).cdi: $(TARGET) ./bin/dreamcast/$(TARGET_NAME).cdi: $(TARGET)
cd ./bin/dreamcast/; ./elf2cdi.sh $(TARGET_NAME) cd ./bin/dreamcast/; ./elf2cdi.sh $(TARGET_NAME)

View File

@ -236,14 +236,14 @@
"cursor" : { "cursor" : {
"visible" : true, "visible" : true,
"center" : false, "center" : false,
"sensitivity": [ 2, 2 ] "sensitivity": [ 0.8, 0.8 ]
}, },
"mode" : "windowed", // fullscreen, borderless, windowed "mode" : "windowed", // fullscreen, borderless, windowed
"icon" : "./data/textures/icon.png", "icon" : "./data/textures/icon.png",
// "size" : [ 1920, 1080 ], // "size" : [ 1920, 1080 ],
"size" : [ 1280, 720 ], // "size" : [ 1280, 720 ],
// "size" : [ 960, 540 ], // "size" : [ 960, 540 ],
// "size" : [ 640, 480 ], "size" : [ 640, 480 ],
// "size" : [ 256, 224 ], // "size" : [ 256, 224 ],
"title" : "Grimgram", "title" : "Grimgram",
"visible" : true "visible" : true

View File

@ -9,7 +9,7 @@
"position": [ 0, 0, 0 ], "position": [ 0, 0, 0 ],
"rotation": { "rotation": {
"axis": [ 0, 1, 0 ], "axis": [ 0, 1, 0 ],
"angle": 3.1415926 "angle": 0
}, },
"scale": [ 1, 1, 1 ] "scale": [ 1, 1, 1 ]
}, },

View File

@ -1,7 +1,7 @@
{ {
"type": "Object", "type": "Object",
"name": "Player: Model", "name": "Player: Model",
"ignore": false, "ignore": true,
"assets": [ "assets": [
"/player/bear.glb" "/player/bear.glb"
// { "filename": "/player/bear/graph.json", "delay": 0, "single threaded": false, "category": "models" } // { "filename": "/player/bear/graph.json", "delay": 0, "single threaded": false, "category": "models" }

View File

@ -0,0 +1,16 @@
{
"name": "Craeture",
"behaviors": [ "CraetureBehavior" ],
"assets": [
"./textures/craeture.jpg"
],
"transform": {
"position": [9.62326, 1.1872, -40.8126],
"scale": [8, 8, 8]
},
"metadata": {
"model": {
"cull mode": "none"
}
}
}

View File

@ -5,7 +5,10 @@
// { "filename": "./models/mcdonalds.glb", "delay": 0, "single threaded": false } // { "filename": "./models/mcdonalds.glb", "delay": 0, "single threaded": false }
// { "filename": "./models/mcdonalds/graph.json", "delay": 0, "single threaded": false, "category": "models" } // { "filename": "./models/mcdonalds/graph.json", "delay": 0, "single threaded": false, "category": "models" }
{ "filename": "./models/mcdonalds/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" } // { "filename": "./models/mcdonalds/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
// { "filename": "./models/mini_mcd.glb", "delay": 0, "single threaded": false }
{ "filename": "./models/mini_mcd/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
], ],
"metadata": { "metadata": {
"model": { "model": {

View File

@ -0,0 +1,16 @@
{
"name": "Craeture",
"behaviors": [ "CraetureBehavior" ],
"assets": [
"./textures/craeture.jpg"
],
"transform": {
"position": [19.9875, 1.54269, -2.97276],
"scale": [1.5, 2, 1.5]
},
"metadata": {
"model": {
"cull mode": "none"
}
}
}

View File

@ -1,5 +1,6 @@
{ {
"import": "/light.json", "import": "/light.json",
"ignore": true,
"assets": [ "assets": [
], ],
"transform": { "transform": {

View File

@ -3,6 +3,7 @@
"system": { "system": {
"physics": { "physics": {
"type": "bounding box", "type": "bounding box",
"recenter": true,
"mass": 100, "mass": 100,
"restitution": 0, "restitution": 0,

View File

@ -3,6 +3,14 @@
"assets": [ "assets": [
// { "filename": "/gui/hud/hud.json", "delay": 0 } // { "filename": "/gui/hud/hud.json", "delay": 0 }
], ],
"transform": {
"position": [ 0, 0, 0 ],
"rotation": {
"axis": [ 0, 1, 0 ],
"angle": 3.1415926
},
"scale": [ 1, 1, 1 ]
},
"metadata": { "metadata": {
"overlay": { "overlay": {
"floating": true "floating": true

View File

@ -79,9 +79,9 @@
} }
}, },
"audio": { "audio": {
"mute": true, "mute": false,
"buffers": { "buffers": {
"size": 16384, "size": 4096,
"count": 2 "count": 2
}, },
"volumes": { "volumes": {
@ -111,7 +111,7 @@
}, },
"limiters": { "limiters": {
"deltaTime": 5, "deltaTime": 5,
"framerate": "auto" "framerate": 60
}, },
"threads": { "threads": {
"workers" : "auto", "workers" : "auto",

View File

@ -24,16 +24,25 @@ namespace uf {
pod::Hook::userdata_t userdata{}; pod::Hook::userdata_t userdata{};
ext::json::Value json{}; ext::json::Value json{};
}; };
struct {
size_t mtime = 0;
bool enabled = false;
uf::stl::string source = "";
} hotReload;
struct { struct {
uf::stl::unordered_map<uf::stl::string, uf::stl::vector<size_t>> bound; uf::stl::unordered_map<uf::stl::string, uf::stl::vector<size_t>> bound;
uf::stl::vector<Queued> queue; uf::stl::vector<Queued> queue;
} hooks; } hooks;
struct { struct {
uf::stl::string root = "";
uf::stl::string filename = "";
struct {
size_t mtime = 0;
bool enabled = false;
} hotReload;
bool loaded = false;
struct {
bool ignore = false;
size_t progress{};
size_t total{};
} load;
bool ignoreGraph = false; bool ignoreGraph = false;
} system; } system;
struct { struct {

View File

@ -59,3 +59,4 @@ namespace uf {
#include "object.inl" #include "object.inl"
#include "behavior.h" #include "behavior.h"
#include "payloads.h"

View File

@ -0,0 +1,10 @@
#pragma once
namespace pod {
namespace payloads {
struct Entity {
size_t uid{};
uf::Object* pointer = NULL;
};
}
}

View File

@ -21,6 +21,12 @@
if ( error != AL_NO_ERROR ) UF_MSG_ERROR("AL error: " << ext::al::getError(error) << ": " << #f);\ if ( error != AL_NO_ERROR ) UF_MSG_ERROR("AL error: " << ext::al::getError(error) << ": " << #f);\
} }
#define AL_CHECK_RESULT_ENUM( fun, id, e, ... ) {\
(fun(id, e, __VA_ARGS__));\
ALCenum error = alGetError();\
if ( error != AL_NO_ERROR ) UF_MSG_ERROR("AL error: " << ext::al::getError(error) << ": " #fun "(" << id << ", " << e << ")");\
}
// uf::stl::string errorString = alutGetErrorString(alutGetError()); // uf::stl::string errorString = alutGetErrorString(alutGetError());
// if ( errorString != "No ALUT error found" ) UF_MSG_ERROR("AL error: " << errorString); // if ( errorString != "No ALUT error found" ) UF_MSG_ERROR("AL error: " << errorString);

View File

@ -120,6 +120,7 @@ namespace uf {
template<typename T> typename T::type_t /*UF_API*/ sum( const T& vector ); // Compute the sum of all components template<typename T> typename T::type_t /*UF_API*/ sum( const T& vector ); // Compute the sum of all components
template<typename T> typename T::type_t /*UF_API*/ product( const T& vector ); // Compute the product of all components template<typename T> typename T::type_t /*UF_API*/ product( const T& vector ); // Compute the product of all components
template<typename T> T /*UF_API*/ negate( const T& vector ); // Flip sign of all components template<typename T> T /*UF_API*/ negate( const T& vector ); // Flip sign of all components
template<typename T> T /*UF_API*/ abs( const T& vector );
// Writes to first value // Writes to first value
template<typename T> T& /*UF_API*/ add_( T& left, const T& right ); // Adds two vectors of same type and size together template<typename T> T& /*UF_API*/ add_( T& left, const T& right ); // Adds two vectors of same type and size together
template<typename T> T& /*UF_API*/ add_( T& left, /*const typename T::type_t&*/ typename T::type_t scalar ); // Adds two vectors of same type and size together template<typename T> T& /*UF_API*/ add_( T& left, /*const typename T::type_t&*/ typename T::type_t scalar ); // Adds two vectors of same type and size together

View File

@ -171,6 +171,14 @@ T /*UF_API*/ uf::vector::negate( const T& vector ) {
res[i] = -vector[i]; res[i] = -vector[i];
return res; return res;
} }
template<typename T> //
T /*UF_API*/ uf::vector::abs( const T& vector ) {
alignas(16) T res;
#pragma unroll // GCC unroll T::size
for ( auto i = 0; i < T::size; ++i )
res[i] = abs(vector[i]);
return res;
}
// Writes to first value // Writes to first value
template<typename T> // Adds two vectors of same type and size together template<typename T> // Adds two vectors of same type and size together
T& /*UF_API*/ uf::vector::add_( T& left, const T& right ) { T& /*UF_API*/ uf::vector::add_( T& left, const T& right ) {

View File

@ -192,7 +192,8 @@ uf::Asset::Payload uf::Asset::resolveToPayload( const uf::stl::string& uri, cons
{ "json", uf::Asset::Type::JSON }, { "json", uf::Asset::Type::JSON },
{ "lua", uf::Asset::Type::LUA }, { "lua", uf::Asset::Type::LUA },
#if !UF_ENV_DREAMCAST
#if !UF_USE_OPENGL
{ "glb", uf::Asset::Type::GRAPH }, { "glb", uf::Asset::Type::GRAPH },
{ "gltf", uf::Asset::Type::GRAPH }, { "gltf", uf::Asset::Type::GRAPH },
{ "mdl", uf::Asset::Type::GRAPH }, { "mdl", uf::Asset::Type::GRAPH },

View File

@ -398,10 +398,9 @@ void uf::graph::process( pod::Graph& graph ) {
auto& texture = uf::graph::storage.texture2Ds[keyName]; auto& texture = uf::graph::storage.texture2Ds[keyName];
if ( !texture.generated() ) { if ( !texture.generated() ) {
bool isLightmap = graph.metadata["lightmapped"].as<uf::stl::string>() == keyName; bool isLightmap = graph.metadata["lightmapped"].as<uf::stl::string>() == keyName;
if ( graph.metadata["filter"].as<uf::stl::string>() == "NEAREST" && !isLightmap ) { auto filter = graph.metadata["filter"].as<uf::stl::string>() == "NEAREST" && !isLightmap ? uf::renderer::enums::Filter::NEAREST : uf::renderer::enums::Filter::LINEAR;
texture.sampler.descriptor.filter.min = uf::renderer::enums::Filter::NEAREST; texture.sampler.descriptor.filter.min = filter;
texture.sampler.descriptor.filter.mag = uf::renderer::enums::Filter::NEAREST; texture.sampler.descriptor.filter.mag = filter;
}
texture.loadFromImage( image ); texture.loadFromImage( image );
#if UF_ENV_DREAMCAST #if UF_ENV_DREAMCAST
image.clear(); image.clear();
@ -701,6 +700,9 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
pod::Vector3f center = (max + min) * 0.5f; pod::Vector3f center = (max + min) * 0.5f;
pod::Vector3f corner = (max - min) * 0.5f; pod::Vector3f corner = (max - min) * 0.5f;
corner.x = abs(corner.x);
corner.y = abs(corner.y);
corner.z = abs(corner.z);
metadataJson["system"]["physics"]["center"] = uf::vector::encode( center ); metadataJson["system"]["physics"]["center"] = uf::vector::encode( center );
metadataJson["system"]["physics"]["corner"] = uf::vector::encode( corner ); metadataJson["system"]["physics"]["corner"] = uf::vector::encode( corner );

View File

@ -18,17 +18,22 @@ UF_BEHAVIOR_TRAITS_CPP(uf::ObjectBehavior, ticks = true, renders = false, multit
void uf::ObjectBehavior::initialize( uf::Object& self ) { void uf::ObjectBehavior::initialize( uf::Object& self ) {
auto& scene = uf::scene::getCurrentScene(); auto& scene = uf::scene::getCurrentScene();
auto& assetLoader = scene.getComponent<uf::Asset>(); auto& assetLoader = scene.getComponent<uf::Asset>();
auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
auto& metadataJson = this->getComponent<uf::Serializer>(); auto& metadataJson = this->getComponent<uf::Serializer>();
auto& transform = this->getComponent<pod::Transform<>>(); auto& transform = this->getComponent<pod::Transform<>>();
// //
{ {
size_t assets = metadataJson["system"]["assets"].size(); size_t assets = metadataJson["system"]["assets"].size();
if ( metadataJson["system"]["load"]["ignore"].is<bool>() ) assets = 0;
metadataJson["system"]["load"]["progress"] = 0; if ( metadata.system.load.ignore ) assets = 0;
metadataJson["system"]["load"]["total"] = assets;
metadata.system.load.progress = 0;
metadata.system.load.total = assets;
if ( assets == 0 ) { if ( assets == 0 ) {
auto& parent = this->getParent().as<uf::Object>(); auto& parent = this->getParent().as<uf::Object>();
pod::payloads::assetLoad payload; pod::payloads::assetLoad payload;
payload.uid = this->getUid(); payload.uid = this->getUid();
parent.callHook("asset:Parsed.%UID%", payload); parent.callHook("asset:Parsed.%UID%", payload);
@ -51,15 +56,10 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
this->addHook( "object:Deserialize.%UID%", [&](ext::json::Value& json){ this->addHook( "object:Deserialize.%UID%", [&](ext::json::Value& json){
if ( ext::json::isNull( json ) ) return; if ( ext::json::isNull( json ) ) return;
if ( json["type"].as<uf::stl::string>() == "merge" ) { if ( json["type"].as<uf::stl::string>() == "merge" ) metadataJson.merge(json["value"], true);
metadataJson.merge(json["value"], true); else if ( json["type"].as<uf::stl::string>() == "import" ) metadataJson.import(json["value"]);
} else if ( json["type"].as<uf::stl::string>() == "import" ) { else if ( json["path"].is<uf::stl::string>() ) metadataJson.path(json["path"].as<uf::stl::string>()) = json["value"];
metadataJson.import(json["value"]); else metadataJson.merge(json, true);
} else if ( json["path"].is<uf::stl::string>() ) {
metadataJson.path(json["path"].as<uf::stl::string>()) = json["value"];
} else {
metadataJson.merge(json, true);
}
}); });
this->addHook( "asset:QueueLoad.%UID%", [&](pod::payloads::assetLoad& payload){ this->addHook( "asset:QueueLoad.%UID%", [&](pod::payloads::assetLoad& payload){
uf::stl::string callback = this->formatHookName("asset:FinishedLoad.%UID%"); uf::stl::string callback = this->formatHookName("asset:FinishedLoad.%UID%");
@ -87,10 +87,9 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
}); });
this->addHook( "asset:Parsed.%UID%", [&](pod::payloads::assetLoad& payload){ this->addHook( "asset:Parsed.%UID%", [&](pod::payloads::assetLoad& payload){
int portion = 1; int portion = 1;
auto& total = metadataJson["system"]["load"]["total"]; auto& total = metadata.system.load.total;
auto& progress = metadataJson["system"]["load"]["progress"]; metadata.system.load.progress += portion;
progress = progress.as<int>() + portion; if ( metadata.system.load.progress == metadata.system.load.total ) {
if ( progress.as<int>() == total.as<int>() ) {
auto& parent = this->getParent().as<uf::Object>(); auto& parent = this->getParent().as<uf::Object>();
payload.uid = this->getUid(); payload.uid = this->getUid();
@ -98,8 +97,6 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
} }
}); });
auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
this->addHook( "object:Serialize.%UID%", [&](ext::json::Value& json){ metadata.serialize(self, metadataJson); }); this->addHook( "object:Serialize.%UID%", [&](ext::json::Value& json){ metadata.serialize(self, metadataJson); });
this->addHook( "object:Deserialize.%UID%", [&](ext::json::Value& json){ metadata.deserialize(self, metadataJson); }); this->addHook( "object:Deserialize.%UID%", [&](ext::json::Value& json){ metadata.deserialize(self, metadataJson); });
metadata.deserialize(self, metadataJson); metadata.deserialize(self, metadataJson);
@ -117,7 +114,7 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
pod::Vector3f center = uf::vector::decode( metadataJson["system"]["physics"]["center"], pod::Vector3f{} ); pod::Vector3f center = uf::vector::decode( metadataJson["system"]["physics"]["center"], pod::Vector3f{} );
pod::Vector3f corner = uf::vector::decode( metadataJson["system"]["physics"]["corner"], pod::Vector3f{0.5, 0.5, 0.5} ); pod::Vector3f corner = uf::vector::decode( metadataJson["system"]["physics"]["corner"], pod::Vector3f{0.5, 0.5, 0.5} );
if ( metadataJson["system"]["physics"]["recenter"].as<bool>() ) collider.transform.position = (center - transform.position) * 0.5f; if ( metadataJson["system"]["physics"]["recenter"].as<bool>(true) ) collider.transform.position = (center - transform.position);
uf::physics::impl::create( *this, corner ); uf::physics::impl::create( *this, corner );
} else if ( metadataJson["system"]["physics"]["type"].as<uf::stl::string>() == "capsule" ) { } else if ( metadataJson["system"]["physics"]["type"].as<uf::stl::string>() == "capsule" ) {
@ -193,10 +190,10 @@ void uf::ObjectBehavior::tick( uf::Object& self ) {
metadata.deserialize(self, metadataJson); metadata.deserialize(self, metadataJson);
#endif #endif
// listen for metadata file changes // listen for metadata file changes
if ( metadata.hotReload.enabled ) { if ( metadata.system.hotReload.enabled ) {
size_t mtime = uf::io::mtime( metadata.hotReload.source ); size_t mtime = uf::io::mtime( metadata.system.filename );
if ( metadata.hotReload.mtime < mtime ) { if ( metadata.system.hotReload.mtime < mtime ) {
metadata.hotReload.mtime = mtime; metadata.system.hotReload.mtime = mtime;
this->reload(); this->reload();
} }
} }

View File

@ -16,46 +16,63 @@ UF_BEHAVIOR_REGISTER_CPP(uf::LoadingBehavior)
UF_BEHAVIOR_TRAITS_CPP(uf::LoadingBehavior, ticks = true, renders = false, multithread = false) UF_BEHAVIOR_TRAITS_CPP(uf::LoadingBehavior, ticks = true, renders = false, multithread = false)
#define this (&self) #define this (&self)
void uf::LoadingBehavior::initialize( uf::Object& self ) { void uf::LoadingBehavior::initialize( uf::Object& self ) {
auto& metadata = this->getComponent<uf::Serializer>();
this->addHook( "system:Load.Finished.%UID%", [&](){ this->addHook( "system:Load.Finished.%UID%", [&](){
metadata["system"]["loaded"] = true; auto& scene = uf::scene::getCurrentScene();
// this->removeBehavior(pod::Behavior{.type = uf::LoadingBehavior::type}); auto& parent = this->getParent();
auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
if ( !metadata.system.loaded ) {
UF_MSG_ERROR("invalid hook invocation: system:Load.Finished:" << this->getUid());
return;
}
// unbind loading behavior
this->removeBehavior(pod::Behavior{.type = TYPE(uf::LoadingBehavior::Metadata)}); this->removeBehavior(pod::Behavior{.type = TYPE(uf::LoadingBehavior::Metadata)});
auto& parent = this->getParent(); //
auto& scene = uf::scene::getCurrentScene(); if ( parent.getUid() == scene.getUid() ) return;
if ( parent.getUid() != scene.getUid() ) {
scene.moveChild(*this); // re-parent to main scene
ext::json::Value payload; scene.moveChild(*this);
payload["uid"] = parent.getUid(); // erase previous parent
parent.getParent().removeChild(parent); parent.getParent().removeChild(parent);
parent.process([&]( uf::Entity* entity ) { // ???
if ( !entity || !entity->isValid() || !entity->hasComponent<pod::Transform<>>() ) return; parent.process([&]( uf::Entity* entity ) {
auto& transform = entity->getComponent<pod::Transform<>>(); if ( !entity || !entity->isValid() || !entity->hasComponent<pod::Transform<>>() ) return;
transform.scale = { 0, 0, 0 }; auto& transform = entity->getComponent<pod::Transform<>>();
entity->render(); transform.scale = { 0, 0, 0 };
}); entity->render();
scene.queueHook("system:Destroy", payload); });
} // queue destruction of parent
return; pod::payloads::Entity payload;
payload.uid = parent.getUid();
payload.pointer = (uf::Object*) &parent;
scene.queueHook("system:Destroy", payload);
}); });
} }
void uf::LoadingBehavior::tick( uf::Object& self ) { void uf::LoadingBehavior::tick( uf::Object& self ) {
auto& metadata = this->getComponent<uf::Serializer>(); auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
if ( metadata["system"]["loaded"].as<bool>() ) return; auto& metadataJson = this->getComponent<uf::Serializer>();
if ( metadata.system.loaded ) return;
size_t loading = 0; size_t loading = 0;
size_t loaded = 1; size_t loaded = 1;
this->process([&]( uf::Entity* entity ) { this->process([&]( uf::Entity* entity ) {
if ( !entity || !entity->isValid() || !entity->hasComponent<uf::Serializer>() ) return; if ( !entity || !entity->isValid() || !entity->hasComponent<uf::ObjectBehavior::Metadata>() ) return;
auto& metadata = entity->getComponent<uf::Serializer>(); auto& metadata = entity->getComponent<uf::ObjectBehavior::Metadata>();
if ( metadata["system"]["load"]["ignore"].is<bool>() ) return;
if ( ext::json::isNull( metadata["system"]["load"] ) ) return; if ( metadata.system.load.ignore ) return;
++loading; ++loading;
if ( metadata["system"]["load"]["progress"].as<int>() < metadata["system"]["load"]["total"].as<int>() ) return; // loading not finished
if ( metadata.system.load.progress < metadata.system.load.total ) return;
++loaded; ++loaded;
}); });
if ( loading == loaded ) { if ( loading == loaded ) {
metadata["system"]["loaded"] = true; metadata.system.loaded = true;
this->callHook("system:Load.Finished.%UID%"); this->callHook("system:Load.Finished.%UID%");
} }
} }

View File

@ -84,38 +84,38 @@ uf::stl::string uf::Object::formatHookName( const uf::stl::string& n ) {
bool uf::Object::load( const uf::stl::string& f, bool inheritRoot ) { bool uf::Object::load( const uf::stl::string& f, bool inheritRoot ) {
uf::Serializer json; uf::Serializer json;
uf::stl::string root = ""; uf::stl::string root = "";
if ( inheritRoot && this->hasParent() ) { if ( inheritRoot && this->hasParent() ) {
auto& parent = this->getParent<uf::Object>(); auto& parent = this->getParent<uf::Object>();
uf::Serializer& metadata = parent.getComponent<uf::Serializer>(); auto& metadata = parent.getComponent<uf::ObjectBehavior::Metadata>();
root = metadata["system"]["root"].as<uf::stl::string>(); auto& metadataJson = parent.getComponent<uf::Serializer>();
root = metadata.system.root;
} }
uf::stl::string filename = uf::io::resolveURI( f, root ); uf::stl::string filename = uf::io::resolveURI( f, root );
if ( !json.readFromFile( filename ) ) return false; if ( !json.readFromFile( filename ) ) return false;
json["root"] = uf::io::directory(filename);
json["source"] = filename; json["source"] = filename;
#if UF_ENTITY_METADATA_USE_JSON json["root"] = uf::io::directory(filename);
json["hot reload"]["mtime"] = uf::io::mtime(filename) + 10; json["hot reload"]["mtime"] = uf::io::mtime(filename) + 10;
#else
auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
metadata.hotReload.source = filename;
metadata.hotReload.mtime = uf::io::mtime(filename) + 10;
#endif
return this->load(json); return this->load(json);
} }
bool uf::Object::reload( bool hard ) { bool uf::Object::reload( bool hard ) {
uf::Serializer& metadata = this->getComponent<uf::Serializer>(); auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
if ( !metadata["system"]["source"].is<uf::stl::string>() ) return false; auto& metadataJson = this->getComponent<uf::Serializer>();
if ( metadata.system.filename == "" ) return false;
uf::Serializer json; uf::Serializer json;
uf::stl::string filename = metadata["system"]["source"].as<uf::stl::string>(); if ( !json.readFromFile( metadata.system.filename ) ) return false;
if ( !json.readFromFile( filename ) ) return false; if ( hard ) return this->load(metadata.system.filename);
if ( hard ) return this->load(filename);
ext::json::Value payload; ext::json::Value payload;
payload["old"] = metadata; payload["old"] = metadataJson;
ext::json::forEach( json["metadata"], [&]( const uf::stl::string& key, const ext::json::Value& value ){ ext::json::forEach( json["metadata"], [&]( const uf::stl::string& key, const ext::json::Value& value ){
metadata[key] = value; metadataJson[key] = value;
}); });
// update transform if requested // update transform if requested
if ( ext::json::isObject(json["transform"]) ) { if ( ext::json::isObject(json["transform"]) ) {
@ -124,18 +124,27 @@ bool uf::Object::reload( bool hard ) {
transform = uf::transform::decode( json["transform"], transform ); transform = uf::transform::decode( json["transform"], transform );
transform.reference = reference; transform.reference = reference;
} }
payload["new"] = metadata; payload["new"] = metadataJson;
this->queueHook("object:Reload.%UID%", payload); this->queueHook("object:Reload.%UID%", payload);
return true; return true;
} }
bool uf::Object::load( const uf::Serializer& _json ) { bool uf::Object::load( const uf::Serializer& _json ) {
uf::Serializer& metadata = this->getComponent<uf::Serializer>(); auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
auto& metadataJson = this->getComponent<uf::Serializer>();
uf::Serializer json = _json; uf::Serializer json = _json;
// setup root/source/mtime
if ( json["source"].is<uf::stl::string>() ) {
metadata.system.filename = json["source"].as<uf::stl::string>();
metadata.system.root = uf::io::directory( metadata.system.filename );
metadata.system.hotReload.mtime = uf::io::mtime( metadata.system.filename ) + 10;
} else if ( json["root"].is<uf::stl::string>() ) {
metadata.system.root = json["root"].as<uf::stl::string>();
}
// import // import
if ( json["import"].is<uf::stl::string>() || json["include"].is<uf::stl::string>() ) { if ( json["import"].is<uf::stl::string>() || json["include"].is<uf::stl::string>() ) {
uf::Serializer chain = json; uf::Serializer chain = json;
uf::stl::string root = json["root"].as<uf::stl::string>(); uf::stl::string root = metadata.system.root;
uf::Serializer separated; uf::Serializer separated;
separated["assets"] = json["assets"]; separated["assets"] = json["assets"];
separated["behaviors"] = json["behaviors"]; separated["behaviors"] = json["behaviors"];
@ -169,10 +178,7 @@ bool uf::Object::load( const uf::Serializer& _json ) {
#if UF_ENTITY_METADATA_USE_JSON #if UF_ENTITY_METADATA_USE_JSON
json["hot reload"]["enabled"] = json["system"]["hot reload"]["enabled"]; json["hot reload"]["enabled"] = json["system"]["hot reload"]["enabled"];
#else #else
{ metadata.system.hotReload.enabled = json["system"]["hot reload"]["enabled"].as<bool>();
auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
metadata.hotReload.enabled = json["system"]["hot reload"]["enabled"].as<bool>();
}
#endif #endif
// Basic entity information // Basic entity information
// Set name // Set name
@ -220,19 +226,18 @@ bool uf::Object::load( const uf::Serializer& _json ) {
uf::stl::string assetTypeString = uf::string::lowercase( #type );\ uf::stl::string assetTypeString = uf::string::lowercase( #type );\
uf::Serializer target;\ uf::Serializer target;\
bool override = false;\ bool override = false;\
if ( ext::json::isObject( metadata["system"]["assets"] ) ) {\ if ( ext::json::isObject( metadataJson["system"]["assets"] ) ) {\
target = metadata["system"]["assets"];\ target = metadataJson["system"]["assets"];\
} else if ( ext::json::isArray( json["assets"] ) ) {\ } else if ( ext::json::isArray( json["assets"] ) ) {\
target = json["assets"];\ target = json["assets"];\
} else if ( ext::json::isObject( json["assets"] ) && !ext::json::isNull( json["assets"][assetTypeString] ) ) {\ } else if ( ext::json::isObject( json["assets"] ) && !ext::json::isNull( json["assets"][assetTypeString] ) ) {\
target = json["assets"][assetTypeString];\ target = json["assets"][assetTypeString];\
} }
uf::stl::vector<ext::json::Value> rejects;
#define UF_OBJECT_LOAD_ASSET()\ #define UF_OBJECT_LOAD_ASSET()\
bool isObject = ext::json::isObject( target[i] );\ bool isObject = ext::json::isObject( target[i] );\
uf::stl::string f = isObject ? target[i]["filename"].as<uf::stl::string>() : target[i].as<uf::stl::string>();\ uf::stl::string f = isObject ? target[i]["filename"].as<uf::stl::string>() : target[i].as<uf::stl::string>();\
uf::stl::string filename = uf::io::resolveURI( f, json["root"].as<uf::stl::string>() );\ uf::stl::string filename = uf::io::resolveURI( f, metadata.system.root );\
uf::stl::string mime = isObject ? target[i]["mime"].as<uf::stl::string>("") : "";\ uf::stl::string mime = isObject ? target[i]["mime"].as<uf::stl::string>("") : "";\
uf::Asset::Payload payload = uf::Asset::resolveToPayload( filename, mime );\ uf::Asset::Payload payload = uf::Asset::resolveToPayload( filename, mime );\
if ( !uf::Asset::isExpected( payload, assetType ) ) continue;\ if ( !uf::Asset::isExpected( payload, assetType ) ) continue;\
@ -271,24 +276,14 @@ bool uf::Object::load( const uf::Serializer& _json ) {
if ( bind ) uf::instantiator::bind("LuaBehavior", *this); if ( bind ) uf::instantiator::bind("LuaBehavior", *this);
} }
} }
/*
// Override
{
UF_OBJECT_LOAD_ASSET_HEADER()
override = true;
for ( size_t i = 0; i < target.size(); ++i ) {
UF_OBJECT_LOAD_ASSET()
}
}
*/
// Bind behaviors // Bind behaviors
{ {
if ( json["type"].is<uf::stl::string>() ) uf::instantiator::bind( json["type"].as<uf::stl::string>(), *this ); if ( json["type"].is<uf::stl::string>() ) uf::instantiator::bind( json["type"].as<uf::stl::string>(), *this );
uf::Serializer target; uf::Serializer target;
if ( ext::json::isArray( metadata["system"]["behaviors"] ) ) { if ( ext::json::isArray( metadataJson["system"]["behaviors"] ) ) {
target = metadata["system"]["behaviors"]; target = metadataJson["system"]["behaviors"];
} else if ( ext::json::isArray( json["behaviors"] ) ) { } else if ( ext::json::isArray( json["behaviors"] ) ) {
target = json["behaviors"]; target = json["behaviors"];
} }
@ -296,28 +291,26 @@ bool uf::Object::load( const uf::Serializer& _json ) {
uf::instantiator::bind( target[i].as<uf::stl::string>(), *this ); uf::instantiator::bind( target[i].as<uf::stl::string>(), *this );
} }
} }
uf::Serializer hooks = metadata["system"]["hooks"];
// Metadata // Metadata
if ( !ext::json::isNull( json["metadata"] ) ) { if ( !ext::json::isNull( json["metadata"] ) ) {
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
if ( json["metadata"].is<uf::stl::string>() ) { if ( json["metadata"].is<uf::stl::string>() ) {
uf::stl::string f = json["metadata"].as<uf::stl::string>(); uf::stl::string f = json["metadata"].as<uf::stl::string>();
uf::stl::string filename = uf::io::resolveURI( json["metadata"].as<uf::stl::string>(), json["root"].as<uf::stl::string>() ); uf::stl::string filename = uf::io::resolveURI( json["metadata"].as<uf::stl::string>(), metadata.system.root );
if ( !metadata.readFromFile(filename) ) return false; if ( !metadataJson.readFromFile(filename) ) return false;
} else { } else {
metadata = json["metadata"]; metadataJson = json["metadata"];
} }
} }
metadata["system"] = json; metadataJson["system"] = json;
metadata["system"].erase("metadata"); metadataJson["system"].erase("metadata");
metadata["system"]["hooks"] = hooks;
// check for children // check for children
{ {
UF_OBJECT_LOAD_ASSET_HEADER(JSON) UF_OBJECT_LOAD_ASSET_HEADER(JSON)
for ( size_t i = 0; i < target.size(); ++i ) { for ( size_t i = 0; i < target.size(); ++i ) {
uf::stl::string f = ext::json::isObject( target[i] ) ? target[i]["filename"].as<uf::stl::string>() : target[i].as<uf::stl::string>(); uf::stl::string f = ext::json::isObject( target[i] ) ? target[i]["filename"].as<uf::stl::string>() : target[i].as<uf::stl::string>();
uf::stl::string filename = uf::io::resolveURI( f, json["root"].as<uf::stl::string>() ); uf::stl::string filename = uf::io::resolveURI( f, metadata.system.root );
uf::stl::string mime = ext::json::isObject( target[i] ) ? target[i]["mime"].as<uf::stl::string>() : ""; uf::stl::string mime = ext::json::isObject( target[i] ) ? target[i]["mime"].as<uf::stl::string>() : "";
uf::stl::string hash = ext::json::isObject( target[i] ) ? target[i]["hash"].as<uf::stl::string>() : ""; uf::stl::string hash = ext::json::isObject( target[i] ) ? target[i]["hash"].as<uf::stl::string>() : "";
@ -337,22 +330,17 @@ bool uf::Object::load( const uf::Serializer& _json ) {
uf::Serializer json; uf::Serializer json;
if ( !json.readFromFile(filename, hash) ) continue; if ( !json.readFromFile(filename, hash) ) continue;
json["root"] = uf::io::directory(filename);
json["source"] = filename; json["source"] = filename;
#if UF_ENTITY_METADATA_USE_JSON json["root"] = uf::io::directory(filename);
json["hot reload"]["mtime"] = uf::io::mtime(filename) + 10; json["hot reload"]["mtime"] = uf::io::mtime(filename) + 10;
#else
auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
metadata.hotReload.mtime = uf::io::mtime(filename) + 10;
#endif
if ( this->loadChildUid(json) == -1 ) continue; if ( this->loadChildUid(json) == -1 ) continue;
} }
} }
} }
// Add lights // Add lights
if ( ext::json::isArray( metadata["system"]["lights"] ) ) { if ( ext::json::isArray( metadataJson["system"]["lights"] ) ) {
uf::Serializer target = metadata["system"]["lights"]; uf::Serializer target = metadataJson["system"]["lights"];
auto& pTransform = this->getComponent<pod::Transform<>>(); auto& pTransform = this->getComponent<pod::Transform<>>();
for ( size_t i = 0; i < target.size(); ++i ) { for ( size_t i = 0; i < target.size(); ++i ) {
uf::Serializer json = target[i]; uf::Serializer json = target[i];
@ -373,23 +361,18 @@ bool uf::Object::load( const uf::Serializer& _json ) {
return true; return true;
} }
uf::Object& uf::Object::loadChild( const uf::stl::string& f, bool initialize ) { uf::Object& uf::Object::loadChild( const uf::stl::string& f, bool initialize ) {
uf::Serializer& metadata = this->getComponent<uf::Serializer>(); auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
auto& metadataJson = this->getComponent<uf::Serializer>();
uf::Serializer json; uf::Serializer json;
uf::stl::string filename = uf::io::resolveURI( f, metadata["system"]["root"].as<uf::stl::string>() ); uf::stl::string filename = uf::io::resolveURI( f, metadata.system.root );
if ( !json.readFromFile(filename) ) { if ( !json.readFromFile(filename) ) {
return ::null; return ::null;
} }
json["root"] = uf::io::directory(filename);
json["source"] = filename; json["source"] = filename;
#if UF_ENTITY_METADATA_USE_JSON json["root"] = uf::io::directory(filename);
json["hot reload"]["mtime"] = uf::io::mtime(filename) + 10; json["hot reload"]["mtime"] = uf::io::mtime(filename) + 10;
#else
{
auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
metadata.hotReload.mtime = uf::io::mtime(filename) + 10;
}
#endif
return this->loadChild(json, initialize); return this->loadChild(json, initialize);
} }

View File

@ -9,17 +9,18 @@ UF_BEHAVIOR_TRAITS_CPP(uf::SceneBehavior, ticks = false, renders = false, multit
void uf::SceneBehavior::initialize( uf::Object& self ) { void uf::SceneBehavior::initialize( uf::Object& self ) {
uf::renderer::states::rebuild = true; uf::renderer::states::rebuild = true;
this->addHook( "system:Renderer.QueueRebuild", [&](ext::json::Value& json){ this->addHook( "system:Renderer.QueueRebuild", [&](){
uf::renderer::states::rebuild = true; uf::renderer::states::rebuild = true;
}); });
this->addHook( "system:Destroy", [&](ext::json::Value& json){ this->addHook( "system:Destroy", [&](pod::payloads::Entity& payload){
size_t uid = json["uid"].as<size_t>(); if ( !payload.pointer ) {
if ( uid <= 0 ) return; if ( payload.uid <= 0 ) return;
auto* target = this->findByUid(uid); payload.pointer = (uf::Object*) this->findByUid(payload.uid);
if ( !target ) return; if ( !payload.pointer ) return;
target->destroy(); }
delete target; payload.pointer->destroy();
delete payload.pointer;
payload.pointer = NULL;
this->queueHook("system:Renderer.QueueRebuild"); this->queueHook("system:Renderer.QueueRebuild");
}); });
} }

View File

@ -117,7 +117,7 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
return uf::graph::load( filename, metadata ); return uf::graph::load( filename, metadata );
} }
#if UF_ENV_DREAMCAST #if UF_USE_OPENGL
UF_EXCEPTION("glTF loading is highly discouraged on this platform:" << filename); UF_EXCEPTION("glTF loading is highly discouraged on this platform:" << filename);
return {}; return {};
#endif #endif

View File

@ -43,9 +43,7 @@ namespace binds {
self.callHook( "object:Serialize.%UID%" ); self.callHook( "object:Serialize.%UID%" );
auto& metadata = self.getComponent<uf::Serializer>(); auto& metadata = self.getComponent<uf::Serializer>();
uf::stl::string str = encoded.value(); uf::stl::string str = encoded.value();
uf::Serializer hooks = metadata["system"]["hooks"];
metadata.merge( str, false ); metadata.merge( str, false );
metadata["system"]["hooks"] = hooks;
self.callHook( "object:Deserialize.%UID%" ); self.callHook( "object:Deserialize.%UID%" );
} }
} }

View File

@ -192,13 +192,13 @@ void ext::al::Source::destroy() {
ALuint& ext::al::Source::getIndex() { return this->m_index; } ALuint& ext::al::Source::getIndex() { return this->m_index; }
ALuint ext::al::Source::getIndex() const { return this->m_index; } ALuint ext::al::Source::getIndex() const { return this->m_index; }
void ext::al::Source::get( ALenum name, ALfloat& x ) { AL_CHECK_RESULT(alGetSourcef( this->m_index, name, &x )); } void ext::al::Source::get( ALenum name, ALfloat& x ) { AL_CHECK_RESULT_ENUM(alGetSourcef, this->m_index, name, &x ); }
void ext::al::Source::get( ALenum name, ALfloat& x, ALfloat& y, ALfloat& z ) { AL_CHECK_RESULT(alGetSource3f( this->m_index, name, &x, &y, &z )); } void ext::al::Source::get( ALenum name, ALfloat& x, ALfloat& y, ALfloat& z ) { AL_CHECK_RESULT_ENUM(alGetSource3f, this->m_index, name, &x, &y, &z ); }
void ext::al::Source::get( ALenum name, ALfloat* f ) { AL_CHECK_RESULT(alGetSourcefv( this->m_index, name, f )); } void ext::al::Source::get( ALenum name, ALfloat* f ) { AL_CHECK_RESULT_ENUM(alGetSourcefv, this->m_index, name, f ); }
void ext::al::Source::get( ALenum name, ALint& x ) { AL_CHECK_RESULT(alGetSourcei( this->m_index, name, &x )); } void ext::al::Source::get( ALenum name, ALint& x ) { AL_CHECK_RESULT_ENUM(alGetSourcei, this->m_index, name, &x ); }
void ext::al::Source::get( ALenum name, ALint& x, ALint& y, ALint& z ) { AL_CHECK_RESULT(alGetSource3i( this->m_index, name, &x, &y, &z )); } void ext::al::Source::get( ALenum name, ALint& x, ALint& y, ALint& z ) { AL_CHECK_RESULT_ENUM(alGetSource3i, this->m_index, name, &x, &y, &z ); }
void ext::al::Source::get( ALenum name, ALint* f ) { AL_CHECK_RESULT(alGetSourceiv( this->m_index, name, f )); } void ext::al::Source::get( ALenum name, ALint* f ) { AL_CHECK_RESULT_ENUM(alGetSourceiv, this->m_index, name, f ); }
void ext::al::Source::get( const uf::stl::string& string, ALfloat& x ) { void ext::al::Source::get( const uf::stl::string& string, ALfloat& x ) {
// alSourcef // alSourcef
@ -253,13 +253,13 @@ void ext::al::Source::get( const uf::stl::string& string, ALint* f ) {
if ( string == "DIRECTION" ) return this->get( AL_DIRECTION, f ); if ( string == "DIRECTION" ) return this->get( AL_DIRECTION, f );
UF_MSG_ERROR("AL error: Invalid enum requested: " << string); UF_MSG_ERROR("AL error: Invalid enum requested: " << string);
} }
void ext::al::Source::set( ALenum name, ALfloat x ) { AL_CHECK_RESULT(alSourcef( this->m_index, name, x )); } void ext::al::Source::set( ALenum name, ALfloat x ) { AL_CHECK_RESULT_ENUM( alSourcef, this->m_index, name, x ); }
void ext::al::Source::set( ALenum name, ALfloat x, ALfloat y, ALfloat z ) { AL_CHECK_RESULT(alSource3f( this->m_index, name, x, y, z )); } void ext::al::Source::set( ALenum name, ALfloat x, ALfloat y, ALfloat z ) { AL_CHECK_RESULT_ENUM( alSource3f, this->m_index, name, x, y, z ); }
void ext::al::Source::set( ALenum name, const ALfloat* f ) { AL_CHECK_RESULT(alSourcefv( this->m_index, name, f )); } void ext::al::Source::set( ALenum name, const ALfloat* f ) { AL_CHECK_RESULT_ENUM( alSourcefv, this->m_index, name, f ); }
void ext::al::Source::set( ALenum name, ALint x ) { AL_CHECK_RESULT(alSourcei( this->m_index, name, x )); } void ext::al::Source::set( ALenum name, ALint x ) { AL_CHECK_RESULT_ENUM( alSourcei, this->m_index, name, x ); }
void ext::al::Source::set( ALenum name, ALint x, ALint y, ALint z ) { AL_CHECK_RESULT(alSource3i( this->m_index, name, x, y, z )); } void ext::al::Source::set( ALenum name, ALint x, ALint y, ALint z ) { AL_CHECK_RESULT_ENUM( alSource3i, this->m_index, name, x, y, z ); }
void ext::al::Source::set( ALenum name, const ALint* f ) { AL_CHECK_RESULT(alSourceiv( this->m_index, name, f )); } void ext::al::Source::set( ALenum name, const ALint* f ) { AL_CHECK_RESULT_ENUM( alSourceiv, this->m_index, name, f ); }
void ext::al::Source::set( const uf::stl::string& string, ALfloat x ) { void ext::al::Source::set( const uf::stl::string& string, ALfloat x ) {
// alSourcef // alSourcef

View File

@ -22,9 +22,12 @@ INIT_MALLOCSTATS -- Enable a call to malloc_stats() right before shutdown
#define UF_HOOK_USE_USERDATA 1 #define UF_HOOK_USE_USERDATA 1
#define UF_HOOK_USE_JSON 0 #define UF_HOOK_USE_JSON 0
extern uint8 romdisk[];
KOS_INIT_FLAGS(INIT_DEFAULT | INIT_MALLOCSTATS); KOS_INIT_FLAGS(INIT_DEFAULT | INIT_MALLOCSTATS);
KOS_INIT_ROMDISK(romdisk);
#if UF_USE_ROMDISK
extern uint8 romdisk[];
KOS_INIT_ROMDISK(romdisk);
#endif
namespace { namespace {
struct { struct {

View File

@ -11,6 +11,7 @@
#else #else
bool uf::audio::muted = true; bool uf::audio::muted = true;
#endif #endif
bool uf::audio::streamsByDefault = true; bool uf::audio::streamsByDefault = true;
uint8_t uf::audio::buffers = 4; uint8_t uf::audio::buffers = 4;
size_t uf::audio::bufferSize = 1024 * 16; size_t uf::audio::bufferSize = 1024 * 16;
@ -117,8 +118,15 @@ float uf::Audio::getTime() const {
void uf::Audio::setTime( float v ) { void uf::Audio::setTime( float v ) {
#if UF_USE_OPENAL #if UF_USE_OPENAL
if ( !this->m_metadata ) return; if ( !this->m_metadata ) return;
#if UF_USE_OPENAL_ALDC
if ( v <= 0 ) {
this->stop();
this->play();
}
#else
this->m_metadata->al.source.set( AL_SEC_OFFSET, v ); this->m_metadata->al.source.set( AL_SEC_OFFSET, v );
#endif #endif
#endif
} }
void uf::Audio::setPosition( const pod::Vector3f& v ) { void uf::Audio::setPosition( const pod::Vector3f& v ) {

View File

@ -255,12 +255,10 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
float friction = 0.8f; float friction = 0.8f;
float air = 1.0f; float air = 1.0f;
} speed; { } speed; {
float scale = 1;
speed.rotate = metadata.movement.rotate * uf::physics::time::delta; speed.rotate = metadata.movement.rotate * uf::physics::time::delta;
speed.move = metadata.movement.move * scale; speed.move = metadata.movement.move;
speed.run = metadata.movement.run * scale; speed.run = metadata.movement.run;
speed.walk = metadata.movement.walk * scale; speed.walk = metadata.movement.walk;
speed.friction = metadata.movement.friction; speed.friction = metadata.movement.friction;
speed.air = metadata.movement.air; speed.air = metadata.movement.air;
@ -351,7 +349,9 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
if ( stats.noclipped ) { if ( stats.noclipped ) {
physics.linear.velocity += target * speed.move; physics.linear.velocity += target * speed.move;
} else { } else {
physics.linear.velocity += target * std::clamp( speed.move * factor - uf::vector::dot( physics.linear.velocity, target ), 0.0f, speed.move * 10 * uf::physics::time::delta ); float delta = collider.body ? uf::physics::impl::timescale : uf::physics::time::delta;
physics.linear.velocity += target * std::clamp( speed.move * factor - uf::vector::dot( physics.linear.velocity, target ), 0.0f, speed.move * 10 * delta );
} }
} }
if ( !stats.floored ) stats.walking = false; if ( !stats.floored ) stats.walking = false;

View File

@ -70,7 +70,28 @@ namespace {
} total; } total;
} times; } times;
uf::Serializer& config = ext::config; auto& json = ext::config;
struct {
struct {
struct {
size_t mode;
bool announce;
float every;
} gc;
struct {
struct {
bool enabled;
} ultralight, discord;
} ext;
struct {
bool print;
float every;
} limiter, fps;
} engine;
} config;
} }
void EXT_API ext::load() { void EXT_API ext::load() {
@ -80,7 +101,7 @@ void EXT_API ext::initialize() {
/* Arguments */ { /* Arguments */ {
bool modified = false; bool modified = false;
auto& arguments = ::config["arguments"]; auto& arguments = ::json["arguments"];
for ( auto& arg : ext::arguments ) { for ( auto& arg : ext::arguments ) {
// store raw argument // store raw argument
int i = arguments.size(); int i = arguments.size();
@ -93,13 +114,13 @@ void EXT_API ext::initialize() {
uf::stl::string keyString = match[1].str(); uf::stl::string keyString = match[1].str();
uf::stl::string valueString = match[2].str(); uf::stl::string valueString = match[2].str();
uf::Serializer value; value.deserialize(valueString); uf::Serializer value; value.deserialize(valueString);
::config.path(keyString) = value; ::json.path(keyString) = value;
modified = true; modified = true;
} }
} }
} }
UF_MSG_DEBUG("Arguments: " << uf::Serializer(arguments)); UF_MSG_DEBUG("Arguments: " << uf::Serializer(arguments));
if ( modified ) UF_MSG_DEBUG("New config: " << ::config); if ( modified ) UF_MSG_DEBUG("New config: " << ::json);
} }
/* Seed */ { /* Seed */ {
srand(time(NULL)); srand(time(NULL));
@ -113,12 +134,9 @@ void EXT_API ext::initialize() {
/* Read persistent data */ { /* Read persistent data */ {
// #include "./inits/persistence.inl" // #include "./inits/persistence.inl"
} }
/* Testing scope */ {
}
/* Set memory pool sizes */ { /* Set memory pool sizes */ {
auto& configMemoryPoolJson = ::config["engine"]["memory pool"]; auto& configMemoryPoolJson = ::json["engine"]["memory pool"];
// check if we are even allowed to use memory pools // check if we are even allowed to use memory pools
bool enabled = configMemoryPoolJson["enabled"].as(true); bool enabled = configMemoryPoolJson["enabled"].as(true);
@ -168,12 +186,25 @@ void EXT_API ext::initialize() {
} }
uf::allocator::override = configMemoryPoolJson["override"].as( uf::allocator::override ); uf::allocator::override = configMemoryPoolJson["override"].as( uf::allocator::override );
} }
/* Ext config */ {
::config.engine.gc.every = ::json["engine"]["debug"]["garbage collection"]["every"].as<float>();
::config.engine.gc.mode = ::json["engine"]["debug"]["garbage collection"]["mode"].as<uint64_t>();
::config.engine.gc.announce = ::json["engine"]["debug"]["garbage collection"]["announce"].as<bool>();
::config.engine.ext.ultralight.enabled = ::json["engine"]["ext"]["ultralight"]["enabled"].as<bool>();
::config.engine.ext.discord.enabled = ::json["engine"]["ext"]["discord"]["enabled"].as<bool>();
::config.engine.limiter.print = ::json["engine"]["debug"]["framerate"]["print"].as<bool>();
::config.engine.fps.print = ::json["engine"]["debug"]["framerate"]["print"].as<bool>();
::config.engine.fps.every = ::json["engine"]["debug"]["framerate"]["every"].as<float>();
}
{ {
uf::Mesh::defaultInterleaved = ::config["engine"]["scenes"]["meshes"]["interleaved"].as( uf::Mesh::defaultInterleaved ); uf::Mesh::defaultInterleaved = ::json["engine"]["scenes"]["meshes"]["interleaved"].as( uf::Mesh::defaultInterleaved );
#if 0 && UF_USE_OPENGL #if 0 && UF_USE_OPENGL
uf::matrix::reverseInfiniteProjection = false; uf::matrix::reverseInfiniteProjection = false;
#else #else
uf::matrix::reverseInfiniteProjection = ::config["engine"]["scenes"]["matrix"]["reverseInfinite"].as( uf::matrix::reverseInfiniteProjection ); uf::matrix::reverseInfiniteProjection = ::json["engine"]["scenes"]["matrix"]["reverseInfinite"].as( uf::matrix::reverseInfiniteProjection );
#endif #endif
} }
@ -181,42 +212,45 @@ void EXT_API ext::initialize() {
uf::Scene& scene = uf::instantiator::instantiate<uf::Scene>(); //new uf::Scene; uf::Scene& scene = uf::instantiator::instantiate<uf::Scene>(); //new uf::Scene;
uf::scene::scenes.emplace_back(&scene); uf::scene::scenes.emplace_back(&scene);
auto& metadata = scene.getComponent<uf::Serializer>(); auto& metadata = scene.getComponent<uf::Serializer>();
metadata["system"]["config"] = ::config; metadata["system"]["config"] = ::json;
} }
{ {
uf::Entity::deleteChildrenOnDestroy = ::config["engine"]["debug"]["entity"]["delete children on destroy"].as( uf::Entity::deleteChildrenOnDestroy ); uf::Entity::deleteChildrenOnDestroy = ::json["engine"]["debug"]["entity"]["delete children on destroy"].as( uf::Entity::deleteChildrenOnDestroy );
uf::Entity::deleteComponentsOnDestroy = ::config["engine"]["debug"]["entity"]["delete components on destroy"].as( uf::Entity::deleteComponentsOnDestroy ); uf::Entity::deleteComponentsOnDestroy = ::json["engine"]["debug"]["entity"]["delete components on destroy"].as( uf::Entity::deleteComponentsOnDestroy );
} }
{ {
auto& configEngineLimitersJson = ::config["engine"]["limiters"]; auto& configEngineLimitersJson = ::json["engine"]["limiters"];
if ( configEngineLimitersJson["framerate"].as<uf::stl::string>() == "auto" && ::json["window"]["refresh rate"].is<size_t>() ) {
float scale = 1.0;
size_t refreshRate = ::json["window"]["refresh rate"].as<size_t>();
configEngineLimitersJson["framerate"] = refreshRate * scale;
UF_MSG_DEBUG("Setting framerate cap to " << (int) refreshRate * scale);
}
/* Frame limiter */ { /* Frame limiter */ {
float limit = configEngineLimitersJson["framerate"].as<float>(); float limit = configEngineLimitersJson["framerate"].as<float>();
::times.limiter = limit != 0 ? 1.0 / limit : 0; ::times.limiter = limit != 0 ? 1.0 / limit : 0;
UF_MSG_DEBUG("Limiter set to " << ::times.limiter << "ms");
} }
/* Max delta time */{ /* Max delta time */{
float limit = configEngineLimitersJson["deltaTime"].as<float>(); float limit = configEngineLimitersJson["deltaTime"].as<float>();
uf::physics::time::clamp = limit != 0 ? 1.0 / limit : 0; uf::physics::time::clamp = limit != 0 ? 1.0 / limit : 0;
} }
if ( configEngineLimitersJson["framerate"].as<uf::stl::string>() == "auto" && ::config["window"]["refresh rate"].is<size_t>() ) {
float scale = 1.0;
size_t refreshRate = ::config["window"]["refresh rate"].as<size_t>();
configEngineLimitersJson["framerate"] = refreshRate * scale;
UF_MSG_DEBUG("Setting framerate cap to " << (int) refreshRate * scale);
}
} }
{ {
auto& configEngineThreadJson = ::config["engine"]["threads"]; auto& configEngineThreadJson = ::json["engine"]["threads"];
if ( configEngineThreadJson["frame limiter"].as<uf::stl::string>() == "auto" && ::config["window"]["refresh rate"].is<size_t>() ) { if ( configEngineThreadJson["frame limiter"].as<uf::stl::string>() == "auto" && ::json["window"]["refresh rate"].is<size_t>() ) {
float scale = 2.0; float scale = 2.0;
size_t refreshRate = ::config["window"]["refresh rate"].as<size_t>(); size_t refreshRate = ::json["window"]["refresh rate"].as<size_t>();
configEngineThreadJson["frame limiter"] = refreshRate * scale; configEngineThreadJson["frame limiter"] = refreshRate * scale;
UF_MSG_DEBUG("Setting thread frame limiter to " << (int) refreshRate * scale); UF_MSG_DEBUG("Setting thread frame limiter to " << (int) refreshRate * scale);
} }
/* Thread frame limiter */ { /* Thread frame limiter */ {
float limit = configEngineThreadJson["frame limiter"].as<float>(); float limit = configEngineThreadJson["frame limiter"].as<float>();
uf::thread::limiter = limit != 0 ? 1.0 / limit : 0; uf::thread::limiter = limit != 0 ? 1.0 / limit : 0;
@ -242,7 +276,7 @@ void EXT_API ext::initialize() {
} }
// Audio settings // Audio settings
{ {
auto& configEngineAudioJson = ::config["engine"]["audio"]; auto& configEngineAudioJson = ::json["engine"]["audio"];
uf::audio::muted = configEngineAudioJson["mute"].as( uf::audio::muted ); uf::audio::muted = configEngineAudioJson["mute"].as( uf::audio::muted );
uf::audio::streamsByDefault = configEngineAudioJson["streams by default"].as( uf::audio::streamsByDefault ); uf::audio::streamsByDefault = configEngineAudioJson["streams by default"].as( uf::audio::streamsByDefault );
@ -269,7 +303,7 @@ void EXT_API ext::initialize() {
// set bullet parameters // set bullet parameters
#if UF_USE_BULLET #if UF_USE_BULLET
{ {
auto& configEngineBulletJson = ::config["engine"]["ext"]["bullet"]; auto& configEngineBulletJson = ::json["engine"]["ext"]["bullet"];
ext::bullet::iterations = configEngineBulletJson["iterations"].as( ext::bullet::iterations ); ext::bullet::iterations = configEngineBulletJson["iterations"].as( ext::bullet::iterations );
ext::bullet::substeps = configEngineBulletJson["substeps"].as( ext::bullet::substeps ); ext::bullet::substeps = configEngineBulletJson["substeps"].as( ext::bullet::substeps );
@ -284,7 +318,7 @@ void EXT_API ext::initialize() {
} }
#elif UF_USE_REACTPHYSICS #elif UF_USE_REACTPHYSICS
{ {
auto& configEngineReactJson = ::config["engine"]["ext"]["reactphysics"]; auto& configEngineReactJson = ::json["engine"]["ext"]["reactphysics"];
ext::reactphysics::timescale = configEngineReactJson["timescale"].as( ext::reactphysics::timescale ); ext::reactphysics::timescale = configEngineReactJson["timescale"].as( ext::reactphysics::timescale );
ext::reactphysics::debugDrawEnabled = configEngineReactJson["debug draw"]["enabled"].as( ext::reactphysics::debugDrawEnabled ); ext::reactphysics::debugDrawEnabled = configEngineReactJson["debug draw"]["enabled"].as( ext::reactphysics::debugDrawEnabled );
@ -297,11 +331,11 @@ void EXT_API ext::initialize() {
// renderer settings // renderer settings
{ {
#if UF_USE_VULKAN #if UF_USE_VULKAN
auto& configRenderJson = ::config["engine"]["ext"]["vulkan"]; auto& configRenderJson = ::json["engine"]["ext"]["vulkan"];
#elif UF_USE_OPENGL #elif UF_USE_OPENGL
auto& configRenderJson = ::config["engine"]["ext"]["opengl"]; auto& configRenderJson = ::json["engine"]["ext"]["opengl"];
#else #else
auto& configRenderJson = ::config["engine"]["ext"]["software"]; auto& configRenderJson = ::json["engine"]["ext"]["software"];
#endif #endif
auto& configRenderExperimentalJson = configRenderJson["experimental"]; auto& configRenderExperimentalJson = configRenderJson["experimental"];
@ -367,7 +401,7 @@ void EXT_API ext::initialize() {
#if UF_USE_LUA #if UF_USE_LUA
/* Lua */ { /* Lua */ {
auto& configLuaJson = ::config["engine"]["ext"]["lua"]; auto& configLuaJson = ::json["engine"]["ext"]["lua"];
ext::lua::enabled = configLuaJson["enabled"].as(ext::lua::enabled); ext::lua::enabled = configLuaJson["enabled"].as(ext::lua::enabled);
ext::lua::main = configLuaJson["main"].as(ext::lua::main); ext::lua::main = configLuaJson["main"].as(ext::lua::main);
@ -383,7 +417,7 @@ void EXT_API ext::initialize() {
} }
#if UF_USE_OPENVR #if UF_USE_OPENVR
{ {
auto& configVrJson = ::config["engine"]["ext"]["vr"]; auto& configVrJson = ::json["engine"]["ext"]["vr"];
ext::openvr::enabled = configVrJson["enable"].as( ext::openvr::enabled ); ext::openvr::enabled = configVrJson["enable"].as( ext::openvr::enabled );
ext::openvr::swapEyes = configVrJson["swap eyes"].as( ext::openvr::swapEyes ); ext::openvr::swapEyes = configVrJson["swap eyes"].as( ext::openvr::swapEyes );
@ -396,53 +430,28 @@ void EXT_API ext::initialize() {
ext::openvr::driver.manifest = configVrJson["manifest"].as<uf::stl::string>(); ext::openvr::driver.manifest = configVrJson["manifest"].as<uf::stl::string>();
if ( ext::openvr::enabled ) ::config["engine"]["render modes"]["stereo deferred"] = true; if ( ext::openvr::enabled ) ::json["engine"]["render modes"]["stereo deferred"] = true;
} }
#endif #endif
#if UF_USE_VULKAN
/* Initialize Vulkan */ { /* Initialize Vulkan */ {
#if UF_USE_VULKAN
// setup render mode // setup render mode
if ( ::config["engine"]["render modes"]["gui"].as<bool>(true) ) { if ( ::json["engine"]["render modes"]["gui"].as<bool>(true) ) {
auto* renderMode = new uf::renderer::RenderTargetRenderMode; auto* renderMode = new uf::renderer::RenderTargetRenderMode;
uf::renderer::addRenderMode( renderMode, "Gui" ); uf::renderer::addRenderMode( renderMode, "Gui" );
renderMode->blitter.descriptor.subpass = 1; renderMode->blitter.descriptor.subpass = 1;
} }
if ( ::config["engine"]["render modes"]["deferred"].as<bool>(true) ) { if ( ::json["engine"]["render modes"]["deferred"].as<bool>(true) ) {
uf::renderer::addRenderMode( new uf::renderer::DeferredRenderMode, "" ); uf::renderer::addRenderMode( new uf::renderer::DeferredRenderMode, "" );
auto& renderMode = uf::renderer::getRenderMode("Deferred", true); auto& renderMode = uf::renderer::getRenderMode("Deferred", true);
if ( ::config["engine"]["render modes"]["stereo deferred"].as<bool>() ) { if ( ::json["engine"]["render modes"]["stereo deferred"].as<bool>() ) {
renderMode.metadata.eyes = 2; renderMode.metadata.eyes = 2;
} }
if ( uf::renderer::settings::experimental::culling ) { if ( uf::renderer::settings::experimental::culling ) {
renderMode.metadata.pipelines.emplace_back("culling"); renderMode.metadata.pipelines.emplace_back("culling");
} }
} }
#endif
#if UF_USE_OPENVR
if ( ext::openvr::enabled ) {
ext::openvr::initialize();
uint32_t width, height;
ext::openvr::recommendedResolution( width, height );
auto& renderMode = uf::renderer::getRenderMode("Deferred", true);
renderMode.width = width;
renderMode.height = height;
UF_MSG_DEBUG("Recommended VR Resolution: " << renderMode.width << ", " << renderMode.height);
if ( ::config["engine"]["ext"]["vr"]["scale"].is<float>() ) {
float scale = ::config["engine"]["ext"]["vr"]["scale"].as<float>();
renderMode.width *= scale;
renderMode.height *= scale;
UF_MSG_DEBUG("VR Resolution: " << renderMode.width << ", " << renderMode.height);
}
}
#endif
#if UF_USE_VULKAN
/* Callbacks for 2KHR stuffs */ { /* Callbacks for 2KHR stuffs */ {
uf::hooks.addHook("vulkan:Instance.ExtensionsEnabled", []( const ext::json::Value& json ) { uf::hooks.addHook("vulkan:Instance.ExtensionsEnabled", []( const ext::json::Value& json ) {
// UF_MSG_DEBUG("vulkan:Instance.ExtensionsEnabled: " << json); // UF_MSG_DEBUG("vulkan:Instance.ExtensionsEnabled: " << json);
@ -477,23 +486,45 @@ void EXT_API ext::initialize() {
// UF_MSG_DEBUG("\tmaxMultiviewInstanceIndex = " << extProps.maxMultiviewInstanceIndex); // UF_MSG_DEBUG("\tmaxMultiviewInstanceIndex = " << extProps.maxMultiviewInstanceIndex);
}); });
} }
#endif
} }
#endif
#if UF_USE_OPENVR
if ( ext::openvr::enabled ) {
ext::openvr::initialize();
{ uint32_t width, height;
ext::openvr::recommendedResolution( width, height );
auto& renderMode = uf::renderer::getRenderMode("Deferred", true);
renderMode.width = width;
renderMode.height = height;
UF_MSG_DEBUG("Recommended VR Resolution: " << renderMode.width << ", " << renderMode.height);
if ( ::json["engine"]["ext"]["vr"]["scale"].is<float>() ) {
float scale = ::json["engine"]["ext"]["vr"]["scale"].as<float>();
renderMode.width *= scale;
renderMode.height *= scale;
UF_MSG_DEBUG("VR Resolution: " << renderMode.width << ", " << renderMode.height);
}
}
#endif
/* Initialize Vulkan/OpenGL */ {
uf::renderer::initialize(); uf::renderer::initialize();
} }
pod::Thread& threadMain = uf::thread::has("Main") ? uf::thread::get("Main") : uf::thread::create( "Main", false ); pod::Thread& threadMain = uf::thread::has("Main") ? uf::thread::get("Main") : uf::thread::create( "Main", false );
#if UF_USE_DISCORD #if UF_USE_DISCORD
/* Discord */ if ( ::config["engine"]["ext"]["discord"]["enabled"].as<bool>() ) { /* Discord */ if ( ::config.engine.ext.discord.enabled ) {
ext::discord::initialize(); ext::discord::initialize();
} }
#endif #endif
#if UF_USE_ULTRALIGHT #if UF_USE_ULTRALIGHT
/* Ultralight-UX */ if ( ::config["engine"]["ext"]["ultralight"]["enabled"].as<bool>() ) { /* Ultralight-UX */ if ( ::config.engine.ext.ultralight.enabled ) {
ext::ultralight::scale = ::config["engine"]["ext"]["ultralight"]["scale"].as( ext::ultralight::scale ); ext::ultralight::scale = ::json["engine"]["ext"]["ultralight"]["scale"].as( ext::ultralight::scale );
ext::ultralight::log = ::config["engine"]["ext"]["ultralight"]["log"].as( ext::ultralight::log ); ext::ultralight::log = ::json["engine"]["ext"]["ultralight"]["log"].as( ext::ultralight::log );
ext::ultralight::initialize(); ext::ultralight::initialize();
} }
#endif #endif
@ -507,7 +538,7 @@ void EXT_API ext::initialize() {
auto& scene = uf::scene::loadScene( json["scene"].as<uf::stl::string>() ); auto& scene = uf::scene::loadScene( json["scene"].as<uf::stl::string>() );
auto& metadata = scene.getComponent<uf::Serializer>(); auto& metadata = scene.getComponent<uf::Serializer>();
metadata["system"]["config"] = ::config; metadata["system"]["config"] = ::json;
return 0; return 0;
}; };
@ -525,7 +556,7 @@ void EXT_API ext::initialize() {
/* Initialize root scene*/ { /* Initialize root scene*/ {
ext::json::Value payload; ext::json::Value payload;
payload["scene"] = ::config["engine"]["scenes"]["start"]; payload["scene"] = ::json["engine"]["scenes"]["start"];
payload["immediate"] = true; payload["immediate"] = true;
uf::hooks.call("game:Scene.Load", payload); uf::hooks.call("game:Scene.Load", payload);
} }
@ -608,7 +639,7 @@ void EXT_API ext::tick() {
uf::thread::process( uf::thread::get("Main") ); uf::thread::process( uf::thread::get("Main") );
} }
#if UF_USE_ULTRALIGHT #if UF_USE_ULTRALIGHT
/* Ultralight-UX */ if ( ::config["engine"]["ext"]["ultralight"]["enabled"].as<bool>() ) { /* Ultralight-UX */ if ( ::config.engine.ext.ultralight.enabled ) {
ext::ultralight::tick(); ext::ultralight::tick();
} }
#endif #endif
@ -617,34 +648,24 @@ void EXT_API ext::tick() {
} }
//UF_TIMER_TRACE("ticking renderer"); //UF_TIMER_TRACE("ticking renderer");
#if UF_USE_DISCORD #if UF_USE_DISCORD
/* Discord */ if ( ::config["engine"]["ext"]["discord"]["enable"].as<bool>() ) { /* Discord */ if ( ::config.engine.ext.discord.enabled ) {
ext::discord::tick(); ext::discord::tick();
} }
#endif #endif
{ /* FPS Print */ if ( ::config.engine.fps.print ) {
auto& fps = ::config["engine"]["debug"]["framerate"]; ++::times.frames;
/* FPS Print */ if ( fps["print"].as<bool>() ) { ++::times.total.frames;
++::times.frames; TIMER( ::config.engine.fps.every ) {
++::times.total.frames; UF_MSG_DEBUG("System: " << (::config.engine.fps.every * 1000.0/::times.frames) << " ms/frame | Time: " << time << " | Frames: " << ::times.frames << " | FPS: " << ::times.frames / time);
float every = fps["every"].as<float>(); ::times.frames = 0;
TIMER( every ) {
UF_MSG_DEBUG("System: " << (every * 1000.0/::times.frames) << " ms/frame | Time: " << time << " | Frames: " << ::times.frames << " | FPS: " << ::times.frames / time);
::times.frames = 0;
}
} }
} }
{ {
auto& gc = ::config["engine"]["debug"]["garbage collection"]; TIMER( ::config.engine.gc.every ) {
/* Garbage collection */ if ( gc["enabled"].as<bool>() ) { size_t collected = uf::instantiator::collect( ::config.engine.gc.mode );
float every = gc["every"].as<float>(); if ( collected > 0 ) {
uint8_t mode = gc["mode"].as<uint64_t>(); if ( ::config.engine.gc.announce ) UF_MSG_DEBUG("GC collected " << (int) collected << " unused entities");
bool announce = gc["announce"].as<bool>(); // uf::renderer::states::rebuild = true;
TIMER( every ) {
size_t collected = uf::instantiator::collect( mode );
if ( collected > 0 ) {
if ( announce ) UF_MSG_DEBUG("GC collected " << (int) collected << " unused entities");
// uf::renderer::states::rebuild = true;
}
} }
} }
} }
@ -655,7 +676,7 @@ void EXT_API ext::tick() {
auto elapsed = timer.elapsed().asMilliseconds(); auto elapsed = timer.elapsed().asMilliseconds();
long long sleep = (::times.limiter * 1000) - elapsed; long long sleep = (::times.limiter * 1000) - elapsed;
if ( sleep > 0 ) { if ( sleep > 0 ) {
// if ( ::config["engine"]["debug"]["framerate"]["print"].as<bool>() ) UF_MSG_DEBUG("Frame limiting: " << elapsed << "ms exceeds limit, sleeping for " << elapsed << "ms"); // if ( ::config.engine.limiter.print ) UF_MSG_DEBUG("Frame limiting: " << elapsed << "ms exceeds limit, sleeping for " << elapsed << "ms");
std::this_thread::sleep_for(std::chrono::milliseconds(sleep)); std::this_thread::sleep_for(std::chrono::milliseconds(sleep));
} }
timer.reset(); timer.reset();
@ -664,7 +685,7 @@ void EXT_API ext::tick() {
} }
void EXT_API ext::render() { void EXT_API ext::render() {
#if UF_USE_ULTRALIGHT #if UF_USE_ULTRALIGHT
/* Ultralight-UX */ if ( ::config["engine"]["ext"]["ultralight"]["enabled"].as<bool>() ) { /* Ultralight-UX */ if ( ::config.engine.ext.ultralight.enabled ) {
ext::ultralight::render(); ext::ultralight::render();
} }
#endif #endif
@ -694,7 +715,7 @@ void EXT_API ext::terminate() {
uf::physics::terminate(); uf::physics::terminate();
} }
#if UF_USE_ULTRALIGHT #if UF_USE_ULTRALIGHT
/* Ultralight-UX */ if ( ::config["engine"]["ext"]["ultralight"]["enabled"].as<bool>() ) { /* Ultralight-UX */ if ( ::config.engine.ext.ultralight.enabled ) {
ext::ultralight::terminate(); ext::ultralight::terminate();
} }
#endif #endif
@ -716,10 +737,8 @@ void EXT_API ext::terminate() {
} }
/* Garbage collection */ if ( false ) { /* Garbage collection */ if ( false ) {
uint8_t mode = ::config["engine"]["debug"]["garbage collection"]["mode"].as<uint64_t>(); size_t collected = uf::instantiator::collect( ::config.engine.gc.mode );
bool announce = ::config["engine"]["debug"]["garbage collection"]["announce"].as<bool>(); if ( ::config.engine.gc.announce && collected > 0 ) UF_MSG_DEBUG("GC collected " << (int) collected << " unused entities");
size_t collected = uf::instantiator::collect( mode );
if ( announce && collected > 0 ) UF_MSG_DEBUG("GC collected " << (int) collected << " unused entities");
} }
/* Close vulkan */ { /* Close vulkan */ {