Commit for 2021.12.25 20-34-43.7z
This commit is contained in:
parent
e16f3d77d7
commit
b208cda203
@ -1,7 +1,7 @@
|
||||
{
|
||||
"engine": {
|
||||
"scenes": {
|
||||
"start": "SH2_McDonalds",
|
||||
"start": "SS2",
|
||||
"meshes": { "interleave": false },
|
||||
"matrix": { "reverseInfinite": true },
|
||||
"lights": {
|
||||
@ -72,9 +72,9 @@
|
||||
"deferred alias output to swapchain": false,
|
||||
"vsync": true,
|
||||
"hdr": false,
|
||||
"vxgi": true,
|
||||
"deferred sampling": true,
|
||||
"culling": true,
|
||||
"vxgi": false,
|
||||
"deferred sampling": false,
|
||||
"culling": false,
|
||||
"bloom": true
|
||||
},
|
||||
"formats": {
|
||||
@ -235,7 +235,8 @@
|
||||
},
|
||||
"cursor" : {
|
||||
"visible" : true,
|
||||
"center" : false
|
||||
"center" : false,
|
||||
"sensitivity": [ 2, 2 ]
|
||||
},
|
||||
"mode" : "windowed", // fullscreen, borderless, windowed
|
||||
"icon" : "./data/textures/icon.png",
|
||||
|
||||
16
bin/data/scenes/ss2/craeture.json
Normal file
16
bin/data/scenes/ss2/craeture.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "Craeture",
|
||||
"behaviors": [ "CraetureBehavior" ],
|
||||
"assets": [
|
||||
"./textures/craeture.png"
|
||||
],
|
||||
"transform": {
|
||||
"position": [18.3785, 2.41477, 0.859857],
|
||||
"scale": [8, 8, 8]
|
||||
},
|
||||
"metadata": {
|
||||
"model": {
|
||||
"cull mode": "none"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,8 @@
|
||||
"assets": [
|
||||
// { "filename": "./models/micro_sci.glb", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./models/micro_sci/graph.json", "delay": 0, "single threaded": false, "category": "models" }
|
||||
{ "filename": "./models/micro_sci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" }
|
||||
{ "filename": "./models/micro_sci/graph.json.gz", "delay": 0, "single threaded": false, "category": "models" },
|
||||
{ "filename": "./craeture.json", "delay": 1 }
|
||||
|
||||
// { "filename": "./models/msci.glb", "delay": 0, "single threaded": false, "category": "models" }
|
||||
// { "filename": "./models/msci/graph.json", "delay": 0, "single threaded": false, "category": "models" }
|
||||
|
||||
@ -11,7 +11,7 @@ local transform = ent:getComponent("Transform")
|
||||
local metadata = ent:getComponent("Metadata")
|
||||
local physics = ent:getComponent("Physics")
|
||||
local bullet = ent:getComponent("Bullet")
|
||||
local velocty = physics:linearVelocity()
|
||||
-- local velocty = physics:linearVelocity()
|
||||
local speed = metadata["speed"] or 1.0
|
||||
local starting = transform.position + Vector3f(0,0,0)
|
||||
local ending = transform.position + Vector3f( metadata["delta"][1], metadata["delta"][2], metadata["delta"][3] )
|
||||
|
||||
@ -66,11 +66,11 @@ void client::initialize() {
|
||||
}
|
||||
|
||||
/* Initialize hooks */ {
|
||||
uf::hooks.addHook( "window:Mouse.CursorVisibility", [&]( ext::json::Value& json ){
|
||||
client::window.setCursorVisible(json["state"].as<bool>());
|
||||
client::window.setMouseGrabbed(!json["state"].as<bool>());
|
||||
client::config["mouse"]["visible"] = json["state"].as<bool>();
|
||||
client::config["window"]["mouse"]["center"] = !json["state"].as<bool>();
|
||||
uf::hooks.addHook( "window:Mouse.CursorVisibility", [&]( pod::payloads::windowMouseCursorVisibility& payload ){
|
||||
client::window.setCursorVisible(payload.mouse.visible);
|
||||
client::window.setMouseGrabbed(!payload.mouse.visible);
|
||||
client::config["mouse"]["visible"] = payload.mouse.visible;
|
||||
client::config["window"]["mouse"]["center"] = !payload.mouse.visible;
|
||||
});
|
||||
uf::hooks.addHook( "window:Mouse.Lock", [&]( ext::json::Value& json ){
|
||||
if ( client::window.hasFocus() ) {
|
||||
@ -92,16 +92,15 @@ void client::initialize() {
|
||||
client::window.setTitle(title);
|
||||
}
|
||||
} );
|
||||
uf::hooks.addHook( "window:Resized", [&]( ext::json::Value& json ){
|
||||
pod::Vector2i size = uf::vector::decode( json["window"]["size"], pod::Vector2i{} );
|
||||
if ( size.x == uf::renderer::settings::width && size.y == uf::renderer::settings::height ) return;
|
||||
uf::hooks.addHook( "window:Resized", [&]( pod::payloads::windowResized& payload ){
|
||||
if ( payload.window.size.x == uf::renderer::settings::width && payload.window.size.y == uf::renderer::settings::height ) return;
|
||||
|
||||
if ( json["invoker"] != "os" ) client::window.setSize(size);
|
||||
if ( payload.invoker != "os" ) client::window.setSize(payload.window.size);
|
||||
// Update viewport
|
||||
if ( !ext::json::isArray( client::config["engine"]["ext"]["vulkan"]["framebuffer"]["size"] ) ) {
|
||||
float scale = client::config["engine"]["ext"]["vulkan"]["framebuffer"]["size"].is<double>() ? client::config["engine"]["ext"]["vulkan"]["framebuffer"]["size"].as<float>() : 1;
|
||||
uf::renderer::settings::width = size.x * scale;
|
||||
uf::renderer::settings::height = size.y * scale;
|
||||
uf::renderer::settings::width = payload.window.size.x * scale;
|
||||
uf::renderer::settings::height = payload.window.size.y * scale;
|
||||
}
|
||||
uf::renderer::states::resized = true;
|
||||
} );
|
||||
|
||||
@ -12,14 +12,37 @@ namespace uf {
|
||||
protected:
|
||||
static uf::Asset masterAssetLoader;
|
||||
public:
|
||||
enum Type {
|
||||
UNKNOWN,
|
||||
IMAGE,
|
||||
AUDIO,
|
||||
LUA,
|
||||
JSON,
|
||||
GRAPH,
|
||||
};
|
||||
|
||||
struct Payload {
|
||||
uf::Asset::Type type = {};
|
||||
uf::stl::string filename = "";
|
||||
uf::stl::string mime = "";
|
||||
uf::stl::string hash = "";
|
||||
|
||||
bool initialize = true;
|
||||
bool monoThreaded = false;
|
||||
size_t uid = 0;
|
||||
};
|
||||
|
||||
static uf::Asset::Payload resolveToPayload( const uf::stl::string&, const uf::stl::string& = "" );
|
||||
static bool isExpected( const uf::Asset::Payload&, uf::Asset::Type expected );
|
||||
|
||||
// URL or file path
|
||||
void processQueue();
|
||||
|
||||
void cache( const uf::stl::string&, const uf::stl::string&, const uf::stl::string&, const uf::stl::string& );
|
||||
void load( const uf::stl::string&, const uf::stl::string&, const uf::stl::string&, const uf::stl::string& );
|
||||
void cache( const uf::stl::string&, const uf::Asset::Payload& );
|
||||
void load( const uf::stl::string&, const uf::Asset::Payload& );
|
||||
|
||||
uf::stl::string cache( const uf::stl::string&, const uf::stl::string& = "", const uf::stl::string& = "" );
|
||||
uf::stl::string load( const uf::stl::string&, const uf::stl::string& = "", const uf::stl::string& = "" );
|
||||
uf::stl::string cache( const uf::Asset::Payload& );
|
||||
uf::stl::string load( const uf::Asset::Payload& );
|
||||
|
||||
uf::stl::string getOriginal( const uf::stl::string& );
|
||||
|
||||
@ -37,7 +60,7 @@ namespace uf {
|
||||
bool has( const uf::stl::string& url ) {
|
||||
auto& container = this->getContainer<T>();
|
||||
if ( container.empty() ) return false;
|
||||
uf::stl::string extension = uf::io::extension( url );
|
||||
uf::stl::string extension = uf::io::extension( url, -1 );
|
||||
uf::Serializer& map = this->getComponent<uf::Serializer>();
|
||||
if ( ext::json::isNull( map[extension] ) ) return false;
|
||||
if ( ext::json::isNull( map[extension][url] ) ) return false;
|
||||
@ -51,7 +74,7 @@ namespace uf {
|
||||
}
|
||||
template<typename T>
|
||||
T& get( const uf::stl::string& url ) {
|
||||
uf::stl::string extension = uf::io::extension( url );
|
||||
uf::stl::string extension = uf::io::extension( url, -1 );
|
||||
uf::Serializer& map = this->getComponent<uf::Serializer>();
|
||||
size_t index = map[extension][url]["index"].as<size_t>(0);
|
||||
return this->get<T>(index);
|
||||
@ -59,7 +82,7 @@ namespace uf {
|
||||
|
||||
template<typename T>
|
||||
T& add( const uf::stl::string& url, const T& copy ) {
|
||||
uf::stl::string extension = uf::io::extension( url );
|
||||
uf::stl::string extension = uf::io::extension( url, -1 );
|
||||
uf::Serializer& map = this->getComponent<uf::Serializer>();
|
||||
auto& container = this->getContainer<T>();
|
||||
if ( !ext::json::isNull( map[extension][url]["index"] ) ) return this->get<T>(url);
|
||||
@ -69,7 +92,7 @@ namespace uf {
|
||||
}
|
||||
template<typename T>
|
||||
T& add( const uf::stl::string& url, T&& move ) {
|
||||
uf::stl::string extension = uf::io::extension( url );
|
||||
uf::stl::string extension = uf::io::extension( url, -1 );
|
||||
uf::Serializer& map = this->getComponent<uf::Serializer>();
|
||||
auto& container = this->getContainer<T>();
|
||||
|
||||
@ -84,7 +107,7 @@ namespace uf {
|
||||
if ( !this->has<T>( url ) ) return;
|
||||
auto& container = this->getContainer<T>();
|
||||
|
||||
uf::stl::string extension = uf::io::extension( url );
|
||||
uf::stl::string extension = uf::io::extension( url, -1 );
|
||||
uf::Serializer& map = this->getComponent<uf::Serializer>();
|
||||
std::size_t index = map[extension][url]["index"].as<size_t>();
|
||||
// container.erase( container.begin() + index );
|
||||
@ -101,4 +124,10 @@ namespace uf {
|
||||
return;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace pod {
|
||||
namespace payloads {
|
||||
typedef uf::Asset::Payload assetLoad;
|
||||
}
|
||||
}
|
||||
@ -126,10 +126,12 @@ namespace uf {
|
||||
pod::Matrix4f UF_API local( pod::Graph&, int32_t );
|
||||
pod::Matrix4f UF_API matrix( pod::Graph&, int32_t );
|
||||
|
||||
void UF_API process( uf::Object& entity );
|
||||
// void UF_API process( uf::Object& entity );
|
||||
void UF_API initializeGraphics( pod::Graph& graph, uf::Object& entity );
|
||||
void UF_API process( pod::Graph& graph );
|
||||
void UF_API process( pod::Graph& graph, int32_t, uf::Object& parent );
|
||||
void UF_API cleanup( pod::Graph& graph );
|
||||
void UF_API reload( pod::Graph& );
|
||||
void UF_API initialize( pod::Graph& graph );
|
||||
|
||||
void UF_API override( pod::Graph& );
|
||||
@ -146,10 +148,12 @@ namespace uf {
|
||||
void UF_API destroy();
|
||||
|
||||
pod::Graph UF_API load( const uf::stl::string&, const uf::Serializer& = ext::json::null() );
|
||||
pod::Graph& UF_API convert( uf::Object&, bool = false );
|
||||
void UF_API save( const pod::Graph&, const uf::stl::string& );
|
||||
|
||||
uf::stl::string UF_API print( const pod::Graph& graph );
|
||||
uf::Serializer UF_API stats( const pod::Graph& graph );
|
||||
void UF_API reload();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include <uf/utils/memory/string.h>
|
||||
#include <uf/utils/memory/vector.h>
|
||||
#include <uf/utils/memory/unordered_map.h>
|
||||
#include <uf/utils/hook/hook.h>
|
||||
|
||||
namespace uf {
|
||||
namespace ObjectBehavior {
|
||||
@ -17,8 +18,10 @@ namespace uf {
|
||||
UF_BEHAVIOR_DEFINE_METADATA(
|
||||
struct Queued {
|
||||
uf::stl::string name;
|
||||
ext::json::Value payload;
|
||||
double timeout;
|
||||
pod::Hook::userdata_t userdata;
|
||||
ext::json::Value json;
|
||||
double timeout = 0;
|
||||
int_fast8_t type = 0;
|
||||
};
|
||||
struct {
|
||||
size_t mtime = 0;
|
||||
|
||||
@ -35,10 +35,15 @@ namespace uf {
|
||||
uf::stl::string formatHookName( const uf::stl::string& name );
|
||||
static uf::stl::string formatHookName( const uf::stl::string& name, size_t uid, bool fetch = true );
|
||||
|
||||
void queueHook( const uf::stl::string&, const ext::json::Value& = ext::json::null(), double = 0 );
|
||||
void queueHook( const uf::stl::string&, const ext::json::Value& = ext::json::null(), float = 0 );
|
||||
|
||||
template<typename T>
|
||||
void queueHook( const uf::stl::string&, const T&, float = 0 );
|
||||
|
||||
uf::Hooks::return_t callHook( const uf::stl::string& );
|
||||
uf::Hooks::return_t callHook( const uf::stl::string&, const ext::json::Value& );
|
||||
uf::Hooks::return_t callHook( const uf::stl::string&, const uf::Serializer& );
|
||||
uf::Hooks::return_t callHook( const uf::stl::string&, const pod::Hook::userdata_t& );
|
||||
|
||||
template<typename T> size_t addHook( const uf::stl::string& name, T function );
|
||||
template<typename T> uf::Hooks::return_t callHook( const uf::stl::string& name, const T& payload );
|
||||
|
||||
@ -34,4 +34,18 @@ uf::Hooks::return_t uf::Object::callHook( const uf::stl::string& name, const T&
|
||||
uf::Userdata payload;
|
||||
payload.create<T>(p);
|
||||
return uf::hooks.call( this->formatHookName( name ), payload );
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void uf::Object::queueHook( const uf::stl::string& name, const T& p, float d ) {
|
||||
if ( !uf::Object::timer.running() ) uf::Object::timer.start();
|
||||
double start = uf::Object::timer.elapsed().asDouble();
|
||||
|
||||
auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
|
||||
auto& queue = metadata.hooks.queue.emplace_back(uf::ObjectBehavior::Metadata::Queued{
|
||||
.name = name,
|
||||
.timeout = start + d,
|
||||
.type = 1,
|
||||
});
|
||||
queue.userdata.create<T>(p);
|
||||
}
|
||||
@ -13,6 +13,8 @@
|
||||
#include <uf/utils/serialize/serializer.h>
|
||||
#include <type_traits>
|
||||
|
||||
#include "payloads.h"
|
||||
|
||||
#define UF_HOOK_POINTERED_USERDATA 1
|
||||
|
||||
namespace pod {
|
||||
|
||||
33
engine/inc/uf/utils/hook/payloads.h
Normal file
33
engine/inc/uf/utils/hook/payloads.h
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include <uf/config.h>
|
||||
|
||||
#include <uf/utils/memory/string.h>
|
||||
#include <uf/utils/math/vector.h>
|
||||
|
||||
namespace pod {
|
||||
namespace payloads {
|
||||
struct menuOpen {
|
||||
uf::stl::string name = "";
|
||||
};
|
||||
|
||||
struct worldCollision {
|
||||
size_t hit = 0;
|
||||
float depth = -1;
|
||||
};
|
||||
|
||||
struct vrInputDigital {
|
||||
uf::stl::string type = "";
|
||||
int_fast8_t size{};
|
||||
int_fast8_t state{};
|
||||
};
|
||||
|
||||
struct vrHaptics {
|
||||
float delay;
|
||||
float duration;
|
||||
float frequency;
|
||||
float amplitude;
|
||||
int_fast8_t side;
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -20,12 +20,11 @@ namespace uf {
|
||||
|
||||
typedef pod::Math::num_t num_t;
|
||||
namespace time {
|
||||
|
||||
extern UF_API uf::Timer<> timer;
|
||||
extern UF_API uf::physics::num_t current;
|
||||
extern UF_API uf::physics::num_t previous;
|
||||
extern UF_API uf::physics::num_t delta;
|
||||
extern UF_API uf::physics::num_t clamp;
|
||||
extern UF_API double current;
|
||||
extern UF_API double previous;
|
||||
extern UF_API float delta;
|
||||
extern UF_API float clamp;
|
||||
}
|
||||
void UF_API initialize();
|
||||
void UF_API tick();
|
||||
|
||||
@ -2,8 +2,7 @@
|
||||
|
||||
#include <uf/config.h>
|
||||
|
||||
#include <uf/utils/memory/string.h>
|
||||
#include <uf/utils/math/vector.h>
|
||||
#include <uf/utils/hook/payloads.h>
|
||||
|
||||
namespace pod {
|
||||
namespace payloads {
|
||||
@ -44,16 +43,16 @@ namespace pod {
|
||||
};
|
||||
struct windowMouseWheel : public windowEvent {
|
||||
struct {
|
||||
pod::Vector2ui position{};
|
||||
float delta = 0;
|
||||
pod::Vector2ui position{};
|
||||
float delta = 0;
|
||||
} mouse;
|
||||
};
|
||||
struct windowMouseClick : public windowEvent {
|
||||
struct {
|
||||
pod::Vector2i position = {};
|
||||
pod::Vector2i delta = {};
|
||||
pod::Vector2i position = {};
|
||||
pod::Vector2i delta = {};
|
||||
uf::stl::string button = "";
|
||||
int_fast8_t state = 0;
|
||||
int_fast8_t state = 0;
|
||||
} mouse;
|
||||
};
|
||||
struct windowMouseMoved : public windowResized {
|
||||
@ -63,5 +62,11 @@ namespace pod {
|
||||
int_fast8_t state{};
|
||||
} mouse;
|
||||
};
|
||||
|
||||
struct windowMouseCursorVisibility : public windowEvent {
|
||||
struct {
|
||||
bool visible;
|
||||
} mouse;
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -35,30 +35,39 @@ namespace {
|
||||
uf::io::write( "./" + filename, http.response );
|
||||
return true;
|
||||
}
|
||||
uf::stl::string hashed( const uf::stl::string& uri ) {
|
||||
return uf::string::sha256(uri);
|
||||
/*
|
||||
std::size_t value = std::hash<uf::stl::string>{}( uri );
|
||||
uf::stl::stringstream stream;
|
||||
stream << std::hex << value;
|
||||
return stream.str();
|
||||
*/
|
||||
}
|
||||
|
||||
std::mutex mutex;
|
||||
uint64_t uid = 0;
|
||||
struct Job {
|
||||
uf::stl::string callback;
|
||||
uf::stl::string type;
|
||||
uf::stl::string uri;
|
||||
uf::stl::string hash;
|
||||
uf::stl::string category;
|
||||
uf::Asset::Payload payload;
|
||||
};
|
||||
}
|
||||
|
||||
uf::Asset uf::Asset::masterAssetLoader;
|
||||
|
||||
void uf::Asset::processQueue() {
|
||||
uf::thread::batchWorker( [&](){
|
||||
mutex.lock();
|
||||
auto jobs = std::move(this->getComponent<std::queue<Job>>());
|
||||
while ( !jobs.empty() ) {
|
||||
auto job = jobs.front();
|
||||
jobs.pop();
|
||||
|
||||
uf::stl::string callback = job.callback;
|
||||
uf::stl::string type = job.type;
|
||||
uf::Asset::Payload payload = job.payload;
|
||||
|
||||
if ( payload.filename == "" || callback == "" ) continue;
|
||||
|
||||
uf::stl::string filename = type == "cache" ? this->cache(payload) : this->load(payload);
|
||||
|
||||
if ( callback != "" && filename != "" ) uf::hooks.call(callback, payload);
|
||||
}
|
||||
mutex.unlock();
|
||||
});
|
||||
|
||||
#if 0
|
||||
auto& jobs = this->getComponent<std::queue<Job>>();
|
||||
mutex.lock();
|
||||
@ -69,12 +78,12 @@ void uf::Asset::processQueue() {
|
||||
if ( job.uri == "" || job.callback == "" ) continue;
|
||||
|
||||
tasks.emplace_back([=](){
|
||||
auto filename = job.type == "cache" ? this->cache(job.uri, job.hash, job.category) : this->load(job.uri, job.hash, job.category);
|
||||
auto filename = job.type == "cache" ? this->cache(job.uri, job.hash, job.mime) : this->load(job.uri, job.hash, job.mime);
|
||||
if ( filename == "" ) return;
|
||||
uf::Serializer payload;
|
||||
payload["filename"] = filename;
|
||||
payload["hash"] = job.hash;
|
||||
payload["category"] = job.category;
|
||||
payload["mime"] = job.mime;
|
||||
uf::hooks.call(job.callback, payload);
|
||||
});
|
||||
}
|
||||
@ -90,21 +99,21 @@ void uf::Asset::processQueue() {
|
||||
uf::stl::string type = job.type;
|
||||
uf::stl::string uri = job.uri;
|
||||
uf::stl::string hash = job.hash;
|
||||
uf::stl::string category = job.category;
|
||||
uf::stl::string mime = job.mime;
|
||||
if ( uri == "" || callback == "" ) {
|
||||
continue;
|
||||
}
|
||||
uf::stl::string filename = type == "cache" ? this->cache(uri, hash, category) : this->load(uri, hash, category);
|
||||
uf::stl::string filename = type == "cache" ? this->cache(uri, hash, mime) : this->load(uri, hash, mime);
|
||||
if ( callback != "" && filename != "" ) {
|
||||
uf::Serializer payload;
|
||||
payload["filename"] = filename;
|
||||
payload["hash"] = hash;
|
||||
payload["category"] = category;
|
||||
payload["mime"] = mime;
|
||||
uf::hooks.call(callback, payload);
|
||||
}
|
||||
}
|
||||
mutex.unlock();
|
||||
#elif 1
|
||||
#elif 0
|
||||
uf::thread::batchWorker( [&](){
|
||||
mutex.lock();
|
||||
auto jobs = std::move(this->getComponent<std::queue<Job>>());
|
||||
@ -115,16 +124,16 @@ void uf::Asset::processQueue() {
|
||||
uf::stl::string type = job.type;
|
||||
uf::stl::string uri = job.uri;
|
||||
uf::stl::string hash = job.hash;
|
||||
uf::stl::string category = job.category;
|
||||
uf::stl::string mime = job.mime;
|
||||
if ( uri == "" || callback == "" ) {
|
||||
continue;
|
||||
}
|
||||
uf::stl::string filename = type == "cache" ? this->cache(uri, hash, category) : this->load(uri, hash, category);
|
||||
uf::stl::string filename = type == "cache" ? this->cache(uri, hash, mime) : this->load(uri, hash, mime);
|
||||
if ( callback != "" && filename != "" ) {
|
||||
uf::Serializer payload;
|
||||
payload["filename"] = filename;
|
||||
payload["hash"] = hash;
|
||||
payload["category"] = category;
|
||||
payload["mime"] = mime;
|
||||
uf::hooks.call(callback, payload);
|
||||
}
|
||||
}
|
||||
@ -141,12 +150,12 @@ void uf::Asset::processQueue() {
|
||||
if ( job.uri == "" || job.callback == "" ) continue;
|
||||
|
||||
tasks.emplace_back([=](){
|
||||
auto filename = job.type == "cache" ? this->cache(job.uri, job.hash, job.category) : this->load(job.uri, job.hash, job.category);
|
||||
auto filename = job.type == "cache" ? this->cache(job.uri, job.hash, job.mime) : this->load(job.uri, job.hash, job.mime);
|
||||
if ( filename == "" ) return;
|
||||
uf::Serializer payload;
|
||||
payload["filename"] = filename;
|
||||
payload["hash"] = job.hash;
|
||||
payload["category"] = job.category;
|
||||
payload["mime"] = job.mime;
|
||||
uf::hooks.call(job.callback, payload);
|
||||
});
|
||||
}
|
||||
@ -155,26 +164,61 @@ void uf::Asset::processQueue() {
|
||||
});
|
||||
#endif
|
||||
}
|
||||
void uf::Asset::cache( const uf::stl::string& callback, const uf::stl::string& uri, const uf::stl::string& hash, const uf::stl::string& category ) {
|
||||
void uf::Asset::cache( const uf::stl::string& callback, const uf::Asset::Payload& payload ) {
|
||||
mutex.lock();
|
||||
auto& jobs = this->getComponent<std::queue<Job>>();
|
||||
jobs.push({ callback, "cache", uri, hash, category });
|
||||
jobs.push({ callback, "cache", payload });
|
||||
mutex.unlock();
|
||||
}
|
||||
void uf::Asset::load( const uf::stl::string& callback, const uf::stl::string& uri, const uf::stl::string& hash, const uf::stl::string& category ) {
|
||||
void uf::Asset::load( const uf::stl::string& callback, const uf::Asset::Payload& payload ) {
|
||||
mutex.lock();
|
||||
auto& jobs = this->getComponent<std::queue<Job>>();
|
||||
jobs.push({ callback, "load", uri, hash, category });
|
||||
jobs.push({ callback, "load", payload });
|
||||
mutex.unlock();
|
||||
}
|
||||
uf::stl::string uf::Asset::cache( const uf::stl::string& uri, const uf::stl::string& hash, const uf::stl::string& category ) {
|
||||
uf::stl::string filename = uri;
|
||||
uf::stl::string extension = uf::io::extension( uri );
|
||||
if ( uri.substr(0,5) == "https" ) {
|
||||
uf::stl::string hash = hashed( uri );
|
||||
|
||||
uf::Asset::Payload uf::Asset::resolveToPayload( const uf::stl::string& uri, const uf::stl::string& mime ) {
|
||||
uf::stl::string extension = uf::string::lowercase( uf::io::extension( uri, -1 ) );
|
||||
uf::stl::string basename = uf::string::lowercase( uf::string::replace( uf::io::filename( uri ), ".gz", "" ) );
|
||||
uf::Asset::Payload payload;
|
||||
|
||||
static uf::stl::unordered_map<uf::stl::string,uf::Asset::Type> typemap = {
|
||||
{ "jpg", uf::Asset::Type::IMAGE },
|
||||
{ "jpeg", uf::Asset::Type::IMAGE },
|
||||
{ "png", uf::Asset::Type::IMAGE },
|
||||
|
||||
{ "ogg", uf::Asset::Type::AUDIO },
|
||||
|
||||
{ "json", uf::Asset::Type::JSON },
|
||||
|
||||
{ "lua", uf::Asset::Type::LUA },
|
||||
|
||||
{ "mdl", uf::Asset::Type::GRAPH },
|
||||
};
|
||||
|
||||
payload.filename = uri;
|
||||
payload.mime = mime;
|
||||
|
||||
if ( typemap.count( extension ) == 1 ) payload.type = typemap[extension];
|
||||
if ( basename == "graph.json" ) payload.type = uf::Asset::Type::GRAPH;
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
bool uf::Asset::isExpected( const uf::Asset::Payload& payload, uf::Asset::Type expected ) {
|
||||
if ( payload.filename == "" ) return false;
|
||||
if ( payload.type != expected ) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
uf::stl::string uf::Asset::cache( const uf::Asset::Payload& payload ) {
|
||||
uf::stl::string filename = payload.filename;
|
||||
uf::stl::string extension = uf::io::extension( filename );
|
||||
if ( filename.substr(0,5) == "https" ) {
|
||||
uf::stl::string hash = uf::string::sha256( filename );
|
||||
uf::stl::string cached = uf::io::root + "/cache/http/" + hash + "." + extension;
|
||||
if ( !uf::io::exists( cached ) && !retrieve( uri, cached, hash ) ) {
|
||||
UF_MSG_ERROR("Failed to preload `" + uri + "` (`" + cached + "`): HTTP error");
|
||||
if ( !uf::io::exists( cached ) && !retrieve( filename, cached, hash ) ) {
|
||||
UF_MSG_ERROR("Failed to preload `" + filename + "` (`" + cached + "`): HTTP error");
|
||||
return "";
|
||||
}
|
||||
filename = cached;
|
||||
@ -183,21 +227,22 @@ uf::stl::string uf::Asset::cache( const uf::stl::string& uri, const uf::stl::str
|
||||
UF_MSG_ERROR("Failed to preload `" + filename + "`: Does not exist");
|
||||
return "";
|
||||
}
|
||||
uf::stl::string actual = hash;
|
||||
if ( hash != "" && (actual = uf::io::hash( filename )) != hash ) {
|
||||
UF_MSG_ERROR("Failed to preload `" << filename << "`: Hash mismatch; expected " << hash << ", got " << actual);
|
||||
uf::stl::string actual = payload.hash;
|
||||
if ( payload.hash != "" && (actual = uf::io::hash( filename )) != payload.hash ) {
|
||||
UF_MSG_ERROR("Failed to preload `" << filename << "`: Hash mismatch; expected " << payload.hash << ", got " << actual);
|
||||
return "";
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
uf::stl::string uf::Asset::load( const uf::stl::string& uri, const uf::stl::string& hash, const uf::stl::string& category ) {
|
||||
uf::stl::string filename = uri;
|
||||
uf::stl::string extension = uf::io::extension( uri );
|
||||
if ( uri.substr(0,5) == "https" ) {
|
||||
uf::stl::string hash = hashed( uri );
|
||||
uf::stl::string uf::Asset::load(const uf::Asset::Payload& payload ) {
|
||||
uf::stl::string filename = payload.filename;
|
||||
uf::stl::string extension = uf::string::lowercase(uf::io::extension( payload.filename, -1 ));
|
||||
uf::stl::string basename = uf::string::replace( uf::io::filename( payload.filename ), ".gz", "" );
|
||||
if ( payload.filename.substr(0,5) == "https" ) {
|
||||
uf::stl::string hash = uf::string::sha256( payload.filename );
|
||||
uf::stl::string cached = uf::io::root + "/cache/http/" + hash + "." + extension;
|
||||
if ( !uf::io::exists( cached ) && !retrieve( uri, cached, hash ) ) {
|
||||
UF_MSG_ERROR("Failed to load `" + uri + "` (`" + cached + "`): HTTP error");
|
||||
if ( !uf::io::exists( cached ) && !retrieve( payload.filename, cached, hash ) ) {
|
||||
UF_MSG_ERROR("Failed to load `" + payload.filename + "` (`" + cached + "`): HTTP error");
|
||||
return "";
|
||||
}
|
||||
filename = cached;
|
||||
@ -206,59 +251,61 @@ uf::stl::string uf::Asset::load( const uf::stl::string& uri, const uf::stl::stri
|
||||
UF_MSG_ERROR("Failed to load `" + filename + "`: Does not exist");
|
||||
return "";
|
||||
}
|
||||
uf::stl::string actual = hash;
|
||||
if ( hash != "" && (actual = uf::io::hash( filename )) != hash ) {
|
||||
UF_MSG_ERROR("Failed to load `" << filename << "`: Hash mismatch; expected " << hash << ", got " << actual);
|
||||
uf::stl::string actual = payload.hash;
|
||||
if ( payload.hash != "" && (actual = uf::io::hash( filename )) != payload.hash ) {
|
||||
UF_MSG_ERROR("Failed to load `" << filename << "`: Hash mismatch; expected " << payload.hash << ", got " << actual);
|
||||
return "";
|
||||
}
|
||||
|
||||
auto& map = this->getComponent<uf::Serializer>();
|
||||
#define UF_ASSET_REGISTER(type)\
|
||||
auto& container = this->getContainer<type>();\
|
||||
if ( !ext::json::isNull( map[extension][uri]["index"] ) ) return filename;\
|
||||
if ( !ext::json::isNull( map[extension][payload.filename]["index"] ) ) return filename;\
|
||||
if ( !ext::json::isNull( map[extension][filename]["index"] ) ) return filename;\
|
||||
map[extension][uri]["index"] = container.size();\
|
||||
map[extension][payload.filename]["index"] = container.size();\
|
||||
map[extension][filename]["index"] = container.size();\
|
||||
type& asset = container.emplace_back();
|
||||
|
||||
|
||||
auto& map = this->getComponent<uf::Serializer>();
|
||||
// deduce PNG, load as texture
|
||||
if ( category == "images" || (category == "" && extension == "png") ) {
|
||||
UF_ASSET_REGISTER(uf::Image)
|
||||
asset.open(filename);
|
||||
} else if ( category == "audio" || (category == "" && extension == "ogg") ) {
|
||||
UF_ASSET_REGISTER(uf::Audio)
|
||||
asset.open(filename);
|
||||
} else if ( category == "audio-stream" || (category == "" && extension == "ogg") ) {
|
||||
UF_ASSET_REGISTER(uf::Audio)
|
||||
asset.stream(filename);
|
||||
} else if ( category == "entities" || (category == "" && extension == "json") ) {
|
||||
UF_ASSET_REGISTER(uf::Serializer)
|
||||
asset.readFromFile(filename);
|
||||
#if UF_USE_LUA
|
||||
} else if ( category == "scripts" || (category == "" && extension == "lua") ) {
|
||||
UF_ASSET_REGISTER(pod::LuaScript)
|
||||
asset = ext::lua::script( filename );
|
||||
#endif
|
||||
} else if ( category == "models" || (category == "" && (extension == "gltf" || extension == "glb" || extension == "graph" ) ) ) {
|
||||
UF_ASSET_REGISTER(pod::Graph)
|
||||
auto& metadata = this->getComponent<uf::Serializer>();
|
||||
switch ( payload.type ) {
|
||||
case uf::Asset::Type::IMAGE: {
|
||||
UF_ASSET_REGISTER(uf::Image)
|
||||
asset.open(filename);
|
||||
} break;
|
||||
case uf::Asset::Type::AUDIO: {
|
||||
UF_ASSET_REGISTER(uf::Audio)
|
||||
asset.stream(filename);
|
||||
} break;
|
||||
case uf::Asset::Type::JSON: {
|
||||
UF_ASSET_REGISTER(uf::Serializer)
|
||||
asset.readFromFile(filename);
|
||||
} break;
|
||||
case uf::Asset::Type::LUA: {
|
||||
UF_ASSET_REGISTER(pod::LuaScript)
|
||||
asset = ext::lua::script( filename );
|
||||
} break;
|
||||
case uf::Asset::Type::GRAPH: {
|
||||
UF_ASSET_REGISTER(pod::Graph)
|
||||
auto& metadata = this->getComponent<uf::Serializer>();
|
||||
|
||||
#if UF_USE_OPENGL_FIXED_FUNCTION
|
||||
metadata[uri]["flags"]["ATLAS"] = false;
|
||||
// metadata[uri]["flags"]["SEPARATE"] = true;
|
||||
#elif UF_GRAPH_INDIRECT_DRAW
|
||||
// metadata[uri]["flags"]["ATLAS"] = false;
|
||||
// metadata[uri]["flags"]["SEPARATE"] = false;
|
||||
#endif
|
||||
asset = uf::graph::load( filename, metadata[uri] );
|
||||
uf::graph::process( asset );
|
||||
if ( asset.metadata["debug"]["print stats"].as<bool>() ) UF_MSG_INFO(uf::graph::stats( asset ).dump(1,'\t'));
|
||||
if ( asset.metadata["debug"]["print tree"].as<bool>() ) UF_MSG_INFO(uf::graph::print( asset ));
|
||||
if ( !asset.metadata["debug"]["no cleanup"].as<bool>() ) uf::graph::cleanup( asset );
|
||||
} else {
|
||||
UF_MSG_ERROR("Failed to parse `" + filename + "`: Unimplemented extension: " + extension + " or category: " + category );
|
||||
#if UF_USE_OPENGL_FIXED_FUNCTION
|
||||
metadata[payload.filename]["flags"]["ATLAS"] = false;
|
||||
// metadata[payload.filename]["flags"]["SEPARATE"] = true;
|
||||
#elif UF_GRAPH_INDIRECT_DRAW
|
||||
// metadata[payload.filename]["flags"]["ATLAS"] = false;
|
||||
// metadata[payload.filename]["flags"]["SEPARATE"] = false;
|
||||
#endif
|
||||
asset = uf::graph::load( filename, metadata[payload.filename] );
|
||||
uf::graph::process( asset );
|
||||
if ( asset.metadata["debug"]["print stats"].as<bool>() ) UF_MSG_INFO(uf::graph::stats( asset ).dump(1,'\t'));
|
||||
if ( asset.metadata["debug"]["print tree"].as<bool>() ) UF_MSG_INFO(uf::graph::print( asset ));
|
||||
if ( !asset.metadata["debug"]["no cleanup"].as<bool>() ) uf::graph::cleanup( asset );
|
||||
} break;
|
||||
default: {
|
||||
UF_MSG_ERROR("Failed to parse `" + filename + "`: Unimplemented extension: " + extension );
|
||||
}
|
||||
}
|
||||
|
||||
return filename;
|
||||
}
|
||||
uf::stl::string uf::Asset::getOriginal( const uf::stl::string& uri ) {
|
||||
|
||||
@ -13,8 +13,8 @@ uf::Serializer uf::MasterData::load( const uf::stl::string& table, const uf::stl
|
||||
this->m_key = key;
|
||||
|
||||
uf::stl::string url = uf::string::replace( root, "%TABLE%", table );
|
||||
url = uf::string::replace( url, "%KEY%", key );
|
||||
uf::stl::string filename = assetLoader.cache(url);
|
||||
auto payload = uf::Asset::resolveToPayload( uf::string::replace( url, "%KEY%", key ) );
|
||||
uf::stl::string filename = assetLoader.cache(payload);
|
||||
if ( filename != "" ) this->m_data.readFromFile(filename);
|
||||
return this->get();
|
||||
}
|
||||
|
||||
186
engine/src/engine/graph/convert.cpp
Normal file
186
engine/src/engine/graph/convert.cpp
Normal file
@ -0,0 +1,186 @@
|
||||
#include <uf/engine/graph/graph.h>
|
||||
#include <uf/ext/gltf/gltf.h>
|
||||
#include <uf/utils/math/physics.h>
|
||||
#include <uf/utils/mesh/grid.h>
|
||||
#include <uf/utils/thread/thread.h>
|
||||
#include <uf/utils/string/base64.h>
|
||||
#include <uf/utils/graphic/graphic.h>
|
||||
#include <uf/utils/math/physics.h>
|
||||
#include <uf/utils/camera/camera.h>
|
||||
#include <uf/ext/xatlas/xatlas.h>
|
||||
|
||||
|
||||
namespace {
|
||||
size_t UF_API process( uf::Object& object, pod::Graph& graph, pod::Node& parent ) {
|
||||
// grab relevant IDs
|
||||
size_t nodeID = graph.nodes.size();
|
||||
size_t instanceID = uf::graph::storage.instances.keys.size(); // graph.instances.size();
|
||||
size_t primitiveID = graph.primitives.size();
|
||||
size_t drawCommandID = graph.drawCommands.size();
|
||||
size_t meshID = graph.meshes.size();
|
||||
size_t objectID = uf::graph::storage.entities.keys.size();
|
||||
|
||||
uf::stl::string keyName = graph.name + "[" + std::to_string(nodeID) + "]";
|
||||
// create node
|
||||
auto& node = graph.nodes.emplace_back();
|
||||
node.index = nodeID;
|
||||
node.parent = parent.index;
|
||||
node.entity = &object;
|
||||
node.transform.reference = &object.getComponent<pod::Transform<>>();
|
||||
uf::graph::storage.entities[std::to_string(objectID)] = &object;
|
||||
// grab relevant data
|
||||
if ( object.hasComponent<uf::Graphic>() ) {
|
||||
auto& graphic = object.getComponent<uf::Graphic>();
|
||||
auto& textures = graphic.material.textures;
|
||||
|
||||
// assume we'll only use one material ID for now
|
||||
size_t sub = 0;
|
||||
size_t materialID = graph.materials.size();
|
||||
for ( auto& t : textures ) {
|
||||
size_t textureID = graph.textures.size();
|
||||
size_t texture2DID = graph.texture2Ds.size();
|
||||
|
||||
uf::stl::string subName = keyName + "[" + std::to_string(sub++) + "]";
|
||||
auto& material = uf::graph::storage.materials[graph.materials.emplace_back(subName)];
|
||||
auto& texture = uf::graph::storage.textures[graph.textures.emplace_back(subName)];
|
||||
auto& texture2D = uf::graph::storage.texture2Ds[graph.texture2Ds.emplace_back(subName)];
|
||||
|
||||
material.indexAlbedo = textureID;
|
||||
texture.index = texture2DID;
|
||||
texture2D.aliasTexture(t);
|
||||
}
|
||||
|
||||
|
||||
if ( object.hasComponent<uf::Mesh>() ) {
|
||||
node.mesh = meshID;
|
||||
// import
|
||||
auto& instance = uf::graph::storage.instances[graph.instances.emplace_back(keyName)];
|
||||
auto& drawCommands = uf::graph::storage.drawCommands[graph.drawCommands.emplace_back(keyName)];
|
||||
auto& drawCommand = drawCommands.emplace_back();
|
||||
auto& primitives = uf::graph::storage.primitives[graph.primitives.emplace_back(keyName)];
|
||||
auto& primitive = primitives.emplace_back();
|
||||
auto& mesh = (uf::graph::storage.meshes[graph.meshes.emplace_back(keyName)] = object.getComponent<uf::Mesh>());
|
||||
|
||||
pod::Vector3f boundsMin = { -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max(), -std::numeric_limits<float>::max() };
|
||||
pod::Vector3f boundsMax = { std::numeric_limits<float>::max(), std::numeric_limits<float>::max(), std::numeric_limits<float>::max() };
|
||||
|
||||
// do some position min/maxing
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
instance.materialID = materialID;
|
||||
instance.primitiveID = primitiveID;
|
||||
instance.meshID = meshID;
|
||||
instance.objectID = objectID;
|
||||
instance.bounds.min = boundsMin;
|
||||
instance.bounds.max = boundsMax;
|
||||
|
||||
drawCommand.indices = mesh.index.count;
|
||||
drawCommand.instances = 1;
|
||||
drawCommand.indexID = 0;
|
||||
drawCommand.vertexID = 0;
|
||||
drawCommand.instanceID = instanceID;
|
||||
drawCommand.vertices = mesh.vertex.count;
|
||||
|
||||
primitive.instance = instance;
|
||||
primitive.drawCommand = drawCommand;
|
||||
|
||||
mesh.insertIndirects(drawCommands);
|
||||
mesh.updateDescriptor();
|
||||
|
||||
graphic.initialize();
|
||||
graphic.initializeMesh( mesh );
|
||||
graphic.process = true;
|
||||
|
||||
uf::graph::initializeGraphics( graph, object );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// recurse
|
||||
for ( auto* child : object.getChildren() ) {
|
||||
node.children.emplace_back( process( child->as<uf::Object>(), graph, node ) );
|
||||
}
|
||||
|
||||
return nodeID;
|
||||
}
|
||||
}
|
||||
|
||||
pod::Graph& UF_API uf::graph::convert( uf::Object& object, bool process ) {
|
||||
auto& graph = object.getComponent<pod::Graph>();
|
||||
|
||||
graph.name = object.getName();
|
||||
graph.metadata = object.getComponent<uf::Serializer>()["model"];
|
||||
graph.root.entity = &object;
|
||||
|
||||
::process( object, graph, graph.root );
|
||||
|
||||
// process nodes
|
||||
if ( process ) {
|
||||
for ( auto index : graph.root.children ) uf::graph::process( graph, index, *graph.root.entity );
|
||||
}
|
||||
|
||||
// remap materials->texture IDs
|
||||
for ( auto& name : graph.materials ) {
|
||||
auto& material = uf::graph::storage.materials[name];
|
||||
auto& keys = uf::graph::storage.textures.keys;
|
||||
int32_t* IDs[] = { &material.indexAlbedo, &material.indexNormal, &material.indexEmissive, &material.indexOcclusion, &material.indexMetallicRoughness };
|
||||
for ( auto* pointer : IDs ) {
|
||||
auto& ID = *pointer;
|
||||
if ( !(0 <= ID && ID < graph.materials.size()) ) continue;
|
||||
auto it = std::find( keys.begin(), keys.end(), graph.textures[ID] );
|
||||
UF_ASSERT( it != keys.end() );
|
||||
ID = it - keys.begin();
|
||||
}
|
||||
}
|
||||
// remap textures->images IDs
|
||||
/*
|
||||
for ( auto& name : graph.textures ) {
|
||||
auto& texture = uf::graph::storage.textures[name];
|
||||
auto& keys = uf::graph::storage.images.keys;
|
||||
|
||||
if ( !(0 <= texture.index && texture.index < graph.textures.size()) ) continue;
|
||||
auto it = std::find( keys.begin(), keys.end(), graph.images[texture.index] );
|
||||
UF_ASSERT( it != keys.end() );
|
||||
texture.index = it - keys.begin();
|
||||
}
|
||||
*/
|
||||
// remap instance variables
|
||||
for ( auto& name : graph.instances ) {
|
||||
auto& instance = uf::graph::storage.instances[name];
|
||||
|
||||
if ( 0 <= instance.materialID && instance.materialID < graph.materials.size() ) {
|
||||
auto& keys = /*graph.storage*/uf::graph::storage.materials.keys;
|
||||
auto it = std::find( keys.begin(), keys.end(), graph.materials[instance.materialID] );
|
||||
UF_ASSERT( it != keys.end() );
|
||||
instance.materialID = it - keys.begin();
|
||||
}
|
||||
if ( 0 <= instance.imageID && instance.imageID < graph.images.size() ) {
|
||||
auto& keys = /*graph.storage*/uf::graph::storage.images.keys;
|
||||
auto it = std::find( keys.begin(), keys.end(), graph.images[instance.imageID] );
|
||||
UF_ASSERT( it != keys.end() );
|
||||
instance.imageID = it - keys.begin();
|
||||
}
|
||||
// remap a skinID as an actual jointID
|
||||
if ( 0 <= instance.jointID && instance.jointID < graph.skins.size() ) {
|
||||
auto& name = graph.skins[instance.jointID];
|
||||
instance.jointID = 0;
|
||||
for ( auto key : uf::graph::storage.joints.keys ) {
|
||||
if ( key == name ) break;
|
||||
auto& joints = uf::graph::storage.joints[key];
|
||||
instance.jointID += joints.size();
|
||||
}
|
||||
}
|
||||
if ( 0 <= instance.lightmapID && instance.lightmapID < graph.textures.size() ) {
|
||||
auto& keys = /*graph.storage*/uf::graph::storage.textures.keys;
|
||||
auto it = std::find( keys.begin(), keys.end(), graph.textures[instance.lightmapID] );
|
||||
UF_ASSERT( it != keys.end() );
|
||||
instance.lightmapID = it - keys.begin();
|
||||
}
|
||||
}
|
||||
|
||||
uf::graph::reload();
|
||||
|
||||
return graph;
|
||||
}
|
||||
@ -39,8 +39,33 @@ UF_VERTEX_DESCRIPTOR(uf::graph::mesh::Skinned,
|
||||
UF_VERTEX_DESCRIPTION(uf::graph::mesh::Skinned, R32G32B32A32_SFLOAT, weights)
|
||||
);
|
||||
|
||||
namespace {
|
||||
void initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
|
||||
pod::Matrix4f uf::graph::local( pod::Graph& graph, int32_t index ) {
|
||||
auto& node = 0 < index && index <= graph.nodes.size() ? graph.nodes[index] : graph.root;
|
||||
return
|
||||
uf::matrix::translate( uf::matrix::identity(), node.transform.position ) *
|
||||
uf::quaternion::matrix(node.transform.orientation) *
|
||||
uf::matrix::scale( uf::matrix::identity(), node.transform.scale ) *
|
||||
node.transform.model;
|
||||
}
|
||||
pod::Matrix4f uf::graph::matrix( pod::Graph& graph, int32_t index ) {
|
||||
pod::Matrix4f matrix = local( graph, index );
|
||||
auto& node = *uf::graph::find( graph, index );
|
||||
int32_t parent = node.parent;
|
||||
while ( 0 < parent && parent <= graph.nodes.size() ) {
|
||||
matrix = local( graph, parent ) * matrix;
|
||||
parent = graph.nodes[parent].parent;
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
pod::Node* uf::graph::find( pod::Graph& graph, int32_t index ) {
|
||||
return 0 <= index && index < graph.nodes.size() ? &graph.nodes[index] : NULL;
|
||||
}
|
||||
pod::Node* uf::graph::find( pod::Graph& graph, const uf::stl::string& name ) {
|
||||
for ( auto& node : graph.nodes ) if ( node.name == name ) return &node;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uf::graph::initializeGraphics( pod::Graph& graph, uf::Object& entity ) {
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& sceneTextures = scene.getComponent<pod::SceneTextures>();
|
||||
auto& sceneMetadataJson = scene.getComponent<uf::Serializer>();
|
||||
@ -52,15 +77,11 @@ namespace {
|
||||
graphic.descriptor.frontFace = uf::renderer::enums::Face::CCW;
|
||||
graphic.descriptor.cullMode = !(graph.metadata["flags"]["INVERT"].as<bool>()) ? uf::renderer::enums::CullMode::BACK : uf::renderer::enums::CullMode::FRONT;
|
||||
if ( graph.metadata["cull mode"].is<uf::stl::string>() ) {
|
||||
if ( graph.metadata["cull mode"].as<uf::stl::string>() == "back" ) {
|
||||
graphic.descriptor.cullMode = uf::renderer::enums::CullMode::BACK;
|
||||
} else if ( graph.metadata["cull mode"].as<uf::stl::string>() == "front" ) {
|
||||
graphic.descriptor.cullMode = uf::renderer::enums::CullMode::FRONT;
|
||||
} else if ( graph.metadata["cull mode"].as<uf::stl::string>() == "none" ) {
|
||||
graphic.descriptor.cullMode = uf::renderer::enums::CullMode::NONE;
|
||||
} else if ( graph.metadata["cull mode"].as<uf::stl::string>() == "both" ) {
|
||||
graphic.descriptor.cullMode = uf::renderer::enums::CullMode::BOTH;
|
||||
}
|
||||
const auto mode = graph.metadata["cull mode"].as<uf::stl::string>();
|
||||
if ( mode == "back" ) graphic.descriptor.cullMode = uf::renderer::enums::CullMode::BACK;
|
||||
else if ( mode == "front" ) graphic.descriptor.cullMode = uf::renderer::enums::CullMode::FRONT;
|
||||
else if ( mode == "none" ) graphic.descriptor.cullMode = uf::renderer::enums::CullMode::NONE;
|
||||
else if ( mode == "both" ) graphic.descriptor.cullMode = uf::renderer::enums::CullMode::BOTH;
|
||||
}
|
||||
{
|
||||
for ( auto& i : graph.images ) graphic.material.textures.emplace_back().aliasTexture( uf::graph::storage.texture2Ds.map[i] );
|
||||
@ -159,21 +180,22 @@ namespace {
|
||||
uf::renderer::Buffer* indirect = NULL;
|
||||
for ( auto& buffer : graphic.buffers ) if ( !indirect && buffer.usage & uf::renderer::enums::Buffer::INDIRECT ) indirect = &buffer;
|
||||
UF_ASSERT( indirect );
|
||||
if ( indirect ) {
|
||||
uf::stl::string compShaderFilename = graph.metadata["shaders"]["vertex"].as<uf::stl::string>("/graph/cull.comp.spv");
|
||||
{
|
||||
graphic.material.metadata.autoInitializeUniforms = false;
|
||||
compShaderFilename = entity.grabURI( compShaderFilename, root );
|
||||
graphic.material.attachShader(compShaderFilename, uf::renderer::enums::Shader::COMPUTE, "culling");
|
||||
graphic.material.metadata.autoInitializeUniforms = true;
|
||||
}
|
||||
graphic.descriptor.inputs.dispatch = { graphic.descriptor.inputs.indirect.count, 1, 1 };
|
||||
|
||||
uf::stl::string compShaderFilename = graph.metadata["shaders"]["vertex"].as<uf::stl::string>("/graph/cull.comp.spv");
|
||||
{
|
||||
graphic.material.metadata.autoInitializeUniforms = false;
|
||||
compShaderFilename = entity.grabURI( compShaderFilename, root );
|
||||
graphic.material.attachShader(compShaderFilename, uf::renderer::enums::Shader::COMPUTE, "culling");
|
||||
graphic.material.metadata.autoInitializeUniforms = true;
|
||||
auto& shader = graphic.material.getShader("compute", "culling");
|
||||
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
|
||||
shader.buffers.emplace_back().aliasBuffer( *indirect );
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
|
||||
}
|
||||
graphic.descriptor.inputs.dispatch = { graphic.descriptor.inputs.indirect.count, 1, 1 };
|
||||
|
||||
auto& shader = graphic.material.getShader("compute", "culling");
|
||||
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.camera );
|
||||
shader.buffers.emplace_back().aliasBuffer( *indirect );
|
||||
shader.buffers.emplace_back().aliasBuffer( uf::graph::storage.buffers.instance );
|
||||
}
|
||||
if ( geometryShaderFilename != "" && uf::renderer::device.enabledFeatures.geometryShader ) {
|
||||
geometryShaderFilename = entity.grabURI( geometryShaderFilename, root );
|
||||
@ -318,38 +340,7 @@ namespace {
|
||||
uf::instantiator::bind( "GraphBehavior", entity );
|
||||
uf::instantiator::unbind( "RenderBehavior", entity );
|
||||
}
|
||||
}
|
||||
|
||||
pod::Matrix4f uf::graph::local( pod::Graph& graph, int32_t index ) {
|
||||
auto& node = 0 < index && index <= graph.nodes.size() ? graph.nodes[index] : graph.root;
|
||||
return
|
||||
uf::matrix::translate( uf::matrix::identity(), node.transform.position ) *
|
||||
uf::quaternion::matrix(node.transform.orientation) *
|
||||
uf::matrix::scale( uf::matrix::identity(), node.transform.scale ) *
|
||||
node.transform.model;
|
||||
}
|
||||
pod::Matrix4f uf::graph::matrix( pod::Graph& graph, int32_t index ) {
|
||||
pod::Matrix4f matrix = local( graph, index );
|
||||
auto& node = *uf::graph::find( graph, index );
|
||||
int32_t parent = node.parent;
|
||||
while ( 0 < parent && parent <= graph.nodes.size() ) {
|
||||
matrix = local( graph, parent ) * matrix;
|
||||
parent = graph.nodes[parent].parent;
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
pod::Node* uf::graph::find( pod::Graph& graph, int32_t index ) {
|
||||
return 0 <= index && index < graph.nodes.size() ? &graph.nodes[index] : NULL;
|
||||
}
|
||||
pod::Node* uf::graph::find( pod::Graph& graph, const uf::stl::string& name ) {
|
||||
for ( auto& node : graph.nodes ) if ( node.name == name ) return &node;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uf::graph::process( uf::Object& entity ) {
|
||||
auto& graph = entity.getComponent<pod::Graph>();
|
||||
for ( auto index : graph.root.children ) process( graph, index, entity );
|
||||
}
|
||||
void uf::graph::process( pod::Graph& graph ) {
|
||||
// copy our local storage to global storage
|
||||
|
||||
@ -478,7 +469,7 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
instance.lightmapID = it - keys.begin();
|
||||
}
|
||||
}
|
||||
::newGraphAdded = true;
|
||||
uf::graph::reload();
|
||||
|
||||
// setup combined mesh if requested
|
||||
if ( !(graph.metadata["flags"]["SEPARATE"].as<bool>()) ) {
|
||||
@ -516,7 +507,7 @@ void uf::graph::process( pod::Graph& graph ) {
|
||||
graphic.initializeMesh( mesh );
|
||||
graphic.process = true;
|
||||
|
||||
initializeGraphics( graph, *graph.root.entity );
|
||||
uf::graph::initializeGraphics( graph, *graph.root.entity );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -684,7 +675,7 @@ void uf::graph::process( pod::Graph& graph, int32_t index, uf::Object& parent )
|
||||
graphic.initializeMesh( mesh );
|
||||
graphic.process = true;
|
||||
|
||||
initializeGraphics( graph, entity );
|
||||
uf::graph::initializeGraphics( graph, entity );
|
||||
}
|
||||
|
||||
if ( !ext::json::isNull( graph.metadata["tags"][node.name] ) ) {
|
||||
@ -977,4 +968,7 @@ void uf::graph::destroy() {
|
||||
for ( auto pair : uf::graph::storage.atlases.map ) pair.second.clear();
|
||||
for ( auto pair : uf::graph::storage.images.map ) pair.second.clear();
|
||||
for ( auto pair : uf::graph::storage.meshes.map ) pair.second.destroy();
|
||||
}
|
||||
void uf::graph::reload() {
|
||||
::newGraphAdded = true;
|
||||
}
|
||||
@ -29,8 +29,8 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
|
||||
metadataJson["system"]["load"]["total"] = assets;
|
||||
if ( assets == 0 ) {
|
||||
auto& parent = this->getParent().as<uf::Object>();
|
||||
uf::Serializer payload;
|
||||
payload["uid"] = this->getUid();
|
||||
pod::payloads::assetLoad payload;
|
||||
payload.uid = this->getUid();
|
||||
parent.callHook("asset:Parsed.%UID%", payload);
|
||||
}
|
||||
}
|
||||
@ -60,40 +60,31 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
|
||||
metadataJson.merge(json, true);
|
||||
}
|
||||
});
|
||||
this->addHook( "asset:QueueLoad.%UID%", [&](ext::json::Value& json){
|
||||
uf::stl::string filename = json["filename"].as<uf::stl::string>();
|
||||
uf::stl::string hash = json["hash"].as<uf::stl::string>();
|
||||
uf::stl::string category = json["category"].as<uf::stl::string>();
|
||||
this->addHook( "asset:QueueLoad.%UID%", [&](pod::payloads::assetLoad& payload){
|
||||
uf::stl::string callback = this->formatHookName("asset:FinishedLoad.%UID%");
|
||||
if ( json["single threaded"].as<bool>() ) {
|
||||
assetLoader.load( filename, hash, category );
|
||||
this->queueHook( callback, json );
|
||||
if ( payload.monoThreaded ) {
|
||||
if ( assetLoader.load( payload ) != "" ) this->queueHook( callback, payload );
|
||||
} else {
|
||||
assetLoader.load( callback, filename, hash, category );
|
||||
assetLoader.load( callback, payload );
|
||||
}
|
||||
});
|
||||
this->addHook( "asset:FinishedLoad.%UID%", [&](ext::json::Value& json){
|
||||
this->queueHook("asset:Load.%UID%", json);
|
||||
this->queueHook("asset:Parsed.%UID%", json);
|
||||
this->addHook( "asset:FinishedLoad.%UID%", [&](pod::payloads::assetLoad& payload){
|
||||
this->queueHook("asset:Load.%UID%", payload);
|
||||
this->queueHook("asset:Parsed.%UID%", payload);
|
||||
});
|
||||
this->addHook( "asset:Load.%UID%", [&](ext::json::Value& json){
|
||||
uf::stl::string filename = json["filename"].as<uf::stl::string>();
|
||||
uf::stl::string category = json["category"].as<uf::stl::string>();
|
||||
bool initialize = ext::json::isNull( json["initialize"] ) ? true : json["initialize"].as<bool>();
|
||||
if ( category != "" && category != "entities" ) return;
|
||||
if ( category == "" && uf::io::extension(filename) != "json" ) return;
|
||||
{
|
||||
uf::Serializer json;
|
||||
if ( !json.readFromFile(filename) ) return;
|
||||
this->addHook( "asset:Load.%UID%", [&](pod::payloads::assetLoad& payload){
|
||||
if ( !uf::Asset::isExpected( payload, uf::Asset::Type::JSON ) ) return;
|
||||
|
||||
json["root"] = uf::io::directory(filename);
|
||||
json["source"] = filename;
|
||||
json["hot reload"]["mtime"] = uf::io::mtime( filename ) + 10;
|
||||
uf::Serializer json;
|
||||
if ( !json.readFromFile(payload.filename) ) return;
|
||||
|
||||
if ( this->loadChildUid(json, initialize) == -1 ) return;
|
||||
}
|
||||
json["root"] = uf::io::directory(payload.filename);
|
||||
json["source"] = payload.filename;
|
||||
json["hot reload"]["mtime"] = uf::io::mtime( payload.filename ) + 10;
|
||||
|
||||
if ( this->loadChildUid(json, payload.initialize) == -1 ) return;
|
||||
});
|
||||
this->addHook( "asset:Parsed.%UID%", [&](ext::json::Value& json){
|
||||
this->addHook( "asset:Parsed.%UID%", [&](pod::payloads::assetLoad& payload){
|
||||
int portion = 1;
|
||||
auto& total = metadataJson["system"]["load"]["total"];
|
||||
auto& progress = metadataJson["system"]["load"]["progress"];
|
||||
@ -101,8 +92,7 @@ void uf::ObjectBehavior::initialize( uf::Object& self ) {
|
||||
if ( progress.as<int>() == total.as<int>() ) {
|
||||
auto& parent = this->getParent().as<uf::Object>();
|
||||
|
||||
uf::Serializer payload;
|
||||
payload["uid"] = this->getUid();
|
||||
payload.uid = this->getUid();
|
||||
parent.callHook("asset:Parsed.%UID%", payload);
|
||||
}
|
||||
});
|
||||
@ -218,18 +208,9 @@ void uf::ObjectBehavior::tick( uf::Object& self ) {
|
||||
transform.position = uf::transform::flatten( parentTransform ).position + metadata.transform.initial.position;
|
||||
}
|
||||
|
||||
/*
|
||||
if ( this->hasComponent<pod::PhysicsState>() && this->hasComponent<pod::Physics>() ) {
|
||||
auto& collider = this->getComponent<pod::PhysicsState>();
|
||||
auto& transform = this->getComponent<pod::Transform<>>();
|
||||
auto& physics = this->getComponent<pod::Physics>();
|
||||
UF_MSG_DEBUG( this->getName() << ": " << this->getUid() << " " << uf::vector::toString( physics.linear.velocity ) << " " << uf::vector::toString( transform.position ) );
|
||||
}
|
||||
*/
|
||||
|
||||
auto& queue = metadata.hooks.queue;
|
||||
if ( !uf::Object::timer.running() ) uf::Object::timer.start();
|
||||
float curTime = uf::Object::timer.elapsed().asDouble();
|
||||
double curTime = uf::Object::timer.elapsed().asDouble();
|
||||
|
||||
#if 1
|
||||
decltype(metadata.hooks.queue) unprocessed;
|
||||
@ -239,7 +220,13 @@ void uf::ObjectBehavior::tick( uf::Object& self ) {
|
||||
executeQueue.reserve( metadata.hooks.queue.size() );
|
||||
|
||||
for ( auto& q : queue ) if ( q.timeout < curTime ) executeQueue.emplace_back(q); else unprocessed.emplace_back(q);
|
||||
for ( auto& q : executeQueue ) this->callHook( q.name, q.payload );
|
||||
for ( auto& q : executeQueue ) {
|
||||
if ( q.type == 0 ) {
|
||||
this->callHook( q.name, q.json );
|
||||
} else {
|
||||
this->callHook( q.name, q.userdata );
|
||||
}
|
||||
}
|
||||
queue = std::move(unprocessed);
|
||||
#else
|
||||
for ( auto it = queue.begin(); it != queue.end(); ) {
|
||||
|
||||
@ -25,16 +25,14 @@ void uf::GraphBehavior::initialize( uf::Object& self ) {
|
||||
auto& graph = this->getComponent<pod::Graph>();
|
||||
uf::graph::animate( graph, name );
|
||||
});
|
||||
this->addHook( "asset:Load.%UID%", [&](ext::json::Value& json){
|
||||
uf::stl::string filename = json["filename"].as<uf::stl::string>();
|
||||
uf::stl::string category = json["category"].as<uf::stl::string>();
|
||||
if ( category != "" && category != "models" ) return;
|
||||
if ( category == "" && uf::io::extension(filename) != "gltf" && uf::io::extension(filename) != "glb" && uf::io::extension(filename) != "graph" ) return;
|
||||
this->addHook( "asset:Load.%UID%", [&](pod::payloads::assetLoad& payload){
|
||||
if ( !uf::Asset::isExpected( payload, uf::Asset::Type::GRAPH ) ) return;
|
||||
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
auto& assetLoader = scene.getComponent<uf::Asset>();
|
||||
if ( !assetLoader.has<pod::Graph>(filename) ) return;
|
||||
auto& graph = (this->getComponent<pod::Graph>() = std::move( assetLoader.get<pod::Graph>(filename) ));
|
||||
assetLoader.remove<pod::Graph>(filename);
|
||||
if ( !assetLoader.has<pod::Graph>(payload.filename) ) return;
|
||||
auto& graph = (this->getComponent<pod::Graph>() = std::move( assetLoader.get<pod::Graph>(payload.filename) ));
|
||||
assetLoader.remove<pod::Graph>(payload.filename);
|
||||
|
||||
bool shouldUpdate = false;
|
||||
|
||||
|
||||
@ -19,16 +19,14 @@ void uf::LuaBehavior::initialize( uf::Object& self ) {
|
||||
#if UF_USE_LUA
|
||||
if ( !ext::lua::enabled ) return;
|
||||
|
||||
this->addHook( "asset:Load.%UID%", [&](ext::json::Value& json){
|
||||
uf::stl::string filename = json["filename"].as<uf::stl::string>();
|
||||
uf::stl::string category = json["category"].as<uf::stl::string>();
|
||||
if ( category != "" && category != "scripts" ) return;
|
||||
if ( category == "" && uf::io::extension(filename) != "lua" ) return;
|
||||
this->addHook( "asset:Load.%UID%", [&](pod::payloads::assetLoad& payload){
|
||||
if ( !uf::Asset::isExpected( payload, uf::Asset::Type::LUA ) ) return;
|
||||
|
||||
uf::Scene& scene = uf::scene::getCurrentScene();
|
||||
uf::Asset& assetLoader = scene.getComponent<uf::Asset>();
|
||||
const pod::LuaScript* assetPointer = NULL;
|
||||
if ( !assetLoader.has<pod::LuaScript>(filename) ) return;
|
||||
assetPointer = &assetLoader.get<pod::LuaScript>(filename);
|
||||
if ( !assetLoader.has<pod::LuaScript>(payload.filename) ) return;
|
||||
assetPointer = &assetLoader.get<pod::LuaScript>(payload.filename);
|
||||
if ( !assetPointer ) return;
|
||||
pod::LuaScript script = *assetPointer;
|
||||
script.env["ent"] = &this->as<uf::Object>();
|
||||
|
||||
@ -20,13 +20,13 @@ UF_OBJECT_REGISTER_BEGIN(uf::Object)
|
||||
UF_OBJECT_REGISTER_BEHAVIOR(uf::ObjectBehavior)
|
||||
UF_OBJECT_REGISTER_END()
|
||||
uf::Object::Object() UF_BEHAVIOR_ENTITY_CPP_ATTACH(uf::Object)
|
||||
void uf::Object::queueHook( const uf::stl::string& name, const ext::json::Value& payload, double timeout ) {
|
||||
void uf::Object::queueHook( const uf::stl::string& name, const ext::json::Value& json, float timeout ) {
|
||||
if ( !uf::Object::timer.running() ) uf::Object::timer.start();
|
||||
double start = uf::Object::timer.elapsed().asDouble();
|
||||
#if UF_ENTITY_METADATA_USE_JSON
|
||||
uf::Serializer queue;
|
||||
queue["name"] = name;
|
||||
queue["payload"] = payload;
|
||||
queue["payload"] = json;
|
||||
queue["timeout"] = start + timeout;
|
||||
uf::Serializer& metadata = this->getComponent<uf::Serializer>();
|
||||
metadata["system"]["hooks"]["queue"].emplace_back(queue);
|
||||
@ -34,7 +34,7 @@ void uf::Object::queueHook( const uf::stl::string& name, const ext::json::Value&
|
||||
auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
|
||||
auto& queue = metadata.hooks.queue.emplace_back(uf::ObjectBehavior::Metadata::Queued{
|
||||
.name = name,
|
||||
.payload = payload,
|
||||
.json = json,
|
||||
.timeout = start + timeout,
|
||||
});
|
||||
#endif
|
||||
@ -79,6 +79,9 @@ uf::Hooks::return_t uf::Object::callHook( const uf::stl::string& name, const ext
|
||||
uf::Hooks::return_t uf::Object::callHook( const uf::stl::string& name, const uf::Serializer& serializer ) {
|
||||
return uf::hooks.call( this->formatHookName( name ), (const ext::json::Value&) serializer );
|
||||
}
|
||||
uf::Hooks::return_t uf::Object::callHook( const uf::stl::string& name, const pod::Hook::userdata_t& payload ) {
|
||||
return uf::hooks.call( this->formatHookName( name ), payload );
|
||||
}
|
||||
bool uf::Object::load( const uf::stl::string& f, bool inheritRoot ) {
|
||||
uf::Serializer json;
|
||||
uf::stl::string root = "";
|
||||
@ -214,66 +217,47 @@ bool uf::Object::load( const uf::Serializer& _json ) {
|
||||
}
|
||||
|
||||
#define UF_OBJECT_LOAD_ASSET_HEADER(type)\
|
||||
uf::stl::string assetCategory = #type;\
|
||||
uf::Asset::Type assetType = uf::Asset::Type::type;\
|
||||
uf::stl::string assetTypeString = uf::string::lowercase( #type );\
|
||||
uf::Serializer target;\
|
||||
bool override = false;\
|
||||
if ( ext::json::isObject( metadata["system"]["assets"] ) ) {\
|
||||
target = metadata["system"]["assets"];\
|
||||
} else if ( ext::json::isArray( json["assets"] ) ) {\
|
||||
target = json["assets"];\
|
||||
} else if ( ext::json::isObject( json["assets"] ) && !ext::json::isNull( json["assets"][#type] ) ) {\
|
||||
target = json["assets"][#type];\
|
||||
} else if ( ext::json::isObject( json["assets"] ) && !ext::json::isNull( 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] );\
|
||||
uf::stl::string canonical = "";\
|
||||
uf::stl::string hash = isObject ? target[i]["hash"].as<uf::stl::string>() : "";\
|
||||
uf::stl::string f = isObject ? target[i]["filename"].as<uf::stl::string>() : target[i].as<uf::stl::string>();\
|
||||
float delay = isObject ? target[i]["delay"].as<float>() : 0;\
|
||||
uf::stl::string category = isObject ? target[i]["category"].as<uf::stl::string>() : "";\
|
||||
bool bind = isObject && target[i]["bind"].is<bool>() ? target[i]["bind"].as<bool>() : true;\
|
||||
uf::stl::string filename = uf::io::resolveURI( f, json["root"].as<uf::stl::string>() );\
|
||||
bool singleThreaded = isObject ? target[i]["single threaded"].as<bool>() : false;\
|
||||
bool overriden = isObject ? target[i]["override"].as<bool>() : false;\
|
||||
uf::stl::vector<uf::stl::string> allowedExtensions = {__VA_ARGS__};\
|
||||
uf::stl::string extension = uf::io::extension(filename);\
|
||||
if ( override && overriden ) {\
|
||||
if ( category == "" ) continue;\
|
||||
} else {\
|
||||
if ( category != "" && category != assetCategory ) continue;\
|
||||
if ( category == "" && std::find( allowedExtensions.begin(), allowedExtensions.end(), extension ) == allowedExtensions.end() ) continue;\
|
||||
}\
|
||||
uf::Serializer payload;\
|
||||
if ( isObject ) payload = target[i];\
|
||||
payload["filename"] = filename;\
|
||||
if ( hash != "" ) payload["hash"] = hash;\
|
||||
payload["category"] = assetCategory != "" ? assetCategory : category;\
|
||||
payload["single threaded"] = singleThreaded;\
|
||||
this->queueHook( "asset:QueueLoad.%UID%", payload, delay );\
|
||||
uf::stl::string mime = isObject ? target[i]["mime"].as<uf::stl::string>("") : "";\
|
||||
uf::Asset::Payload payload = uf::Asset::resolveToPayload( filename, mime );\
|
||||
if ( !uf::Asset::isExpected( payload, assetType ) ) continue;\
|
||||
payload.hash = isObject ? target[i]["hash"].as<uf::stl::string>("") : "";\
|
||||
payload.monoThreaded = isObject ? target[i]["single threaded"].as<bool>() : false;\
|
||||
this->queueHook( "asset:QueueLoad.%UID%", payload, isObject ? target[i]["delay"].as<float>() : 0 );\
|
||||
bool bind = isObject && target[i]["bind"].is<bool>() ? target[i]["bind"].as<bool>() : true;\
|
||||
|
||||
// Audio
|
||||
{
|
||||
UF_OBJECT_LOAD_ASSET_HEADER(audio)
|
||||
UF_OBJECT_LOAD_ASSET_HEADER(AUDIO)
|
||||
for ( size_t i = 0; i < target.size(); ++i ) {
|
||||
UF_OBJECT_LOAD_ASSET("ogg")
|
||||
UF_OBJECT_LOAD_ASSET()
|
||||
}
|
||||
}
|
||||
|
||||
// Images
|
||||
{
|
||||
UF_OBJECT_LOAD_ASSET_HEADER(images)
|
||||
UF_OBJECT_LOAD_ASSET_HEADER(IMAGE)
|
||||
for ( size_t i = 0; i < target.size(); ++i ) {
|
||||
UF_OBJECT_LOAD_ASSET("png", "jpg", "jpeg")
|
||||
UF_OBJECT_LOAD_ASSET()
|
||||
}
|
||||
}
|
||||
|
||||
// GLTf models
|
||||
{
|
||||
UF_OBJECT_LOAD_ASSET_HEADER(models)
|
||||
UF_OBJECT_LOAD_ASSET_HEADER(GRAPH)
|
||||
for ( size_t i = 0; i < target.size(); ++i ) {
|
||||
UF_OBJECT_LOAD_ASSET("gltf", "glb", "graph")
|
||||
UF_OBJECT_LOAD_ASSET()
|
||||
if ( bind ) uf::instantiator::bind("GraphBehavior", *this);
|
||||
|
||||
auto& aMetadata = assetLoader.getComponent<uf::Serializer>();
|
||||
@ -281,14 +265,14 @@ bool uf::Object::load( const uf::Serializer& _json ) {
|
||||
aMetadata[filename]["root"] = json["root"];
|
||||
}
|
||||
}
|
||||
// Lua scripts
|
||||
{
|
||||
UF_OBJECT_LOAD_ASSET_HEADER(scripts)
|
||||
UF_OBJECT_LOAD_ASSET_HEADER(LUA)
|
||||
for ( size_t i = 0; i < target.size(); ++i ) {
|
||||
UF_OBJECT_LOAD_ASSET("lua")
|
||||
UF_OBJECT_LOAD_ASSET()
|
||||
if ( bind ) uf::instantiator::bind("LuaBehavior", *this);
|
||||
}
|
||||
}
|
||||
/*
|
||||
// Override
|
||||
{
|
||||
UF_OBJECT_LOAD_ASSET_HEADER()
|
||||
@ -297,6 +281,8 @@ bool uf::Object::load( const uf::Serializer& _json ) {
|
||||
UF_OBJECT_LOAD_ASSET()
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Bind behaviors
|
||||
{
|
||||
if ( json["type"].is<uf::stl::string>() ) uf::instantiator::bind( json["type"].as<uf::stl::string>(), *this );
|
||||
@ -329,22 +315,22 @@ bool uf::Object::load( const uf::Serializer& _json ) {
|
||||
|
||||
// check for children
|
||||
{
|
||||
UF_OBJECT_LOAD_ASSET_HEADER(entities)
|
||||
UF_OBJECT_LOAD_ASSET_HEADER(JSON)
|
||||
for ( size_t i = 0; i < target.size(); ++i ) {
|
||||
uf::stl::string canonical = "";
|
||||
uf::stl::string hash = ext::json::isObject( target[i] ) ? target[i]["hash"].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>();
|
||||
float delay = ext::json::isObject( target[i] ) ? target[i]["delay"].as<float>() : -1;
|
||||
uf::stl::string category = ext::json::isObject( target[i] ) ? target[i]["category"].as<uf::stl::string>() : "";\
|
||||
uf::stl::string filename = uf::io::resolveURI( f, json["root"].as<uf::stl::string>() );
|
||||
if ( category != "" && category != assetCategory ) continue;
|
||||
if ( category == "" && uf::io::extension(filename) != "json" ) continue;
|
||||
if ( (canonical = assetLoader.load( filename, hash )) == "" ) continue;
|
||||
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::Asset::Payload payload = uf::Asset::resolveToPayload( filename, mime );
|
||||
if ( !uf::Asset::isExpected( payload, uf::Asset::Type::JSON ) ) continue;
|
||||
if ( (filename = assetLoader.load( payload )) == "" ) continue;
|
||||
|
||||
float delay = ext::json::isObject( target[i] ) ? target[i]["delay"].as<float>() : -1;
|
||||
if ( delay > -1 ) {
|
||||
uf::Serializer payload;
|
||||
payload["filename"] = canonical;
|
||||
if ( hash != "" ) payload["hash"] = hash;
|
||||
payload["category"] = assetCategory;
|
||||
payload.filename = filename;
|
||||
payload.hash = hash;
|
||||
payload.mime = mime;
|
||||
this->queueHook( "asset:Load.%UID%", payload, delay );
|
||||
continue;
|
||||
}
|
||||
@ -357,10 +343,8 @@ bool uf::Object::load( const uf::Serializer& _json ) {
|
||||
#if UF_ENTITY_METADATA_USE_JSON
|
||||
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;
|
||||
}
|
||||
auto& metadata = this->getComponent<uf::ObjectBehavior::Metadata>();
|
||||
metadata.hotReload.mtime = uf::io::mtime(filename) + 10;
|
||||
#endif
|
||||
|
||||
if ( this->loadChildUid(json) == -1 ) continue;
|
||||
|
||||
@ -289,33 +289,6 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
switch ( accessor.componentType ) {
|
||||
case TINYGLTF_COMPONENT_TYPE_BYTE:
|
||||
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE: {
|
||||
attribute.stride = sizeof(uint8_t);
|
||||
} break;
|
||||
case TINYGLTF_COMPONENT_TYPE_SHORT:
|
||||
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_SHORT: {
|
||||
attribute.stride = sizeof(uint16_t);
|
||||
} break;
|
||||
case TINYGLTF_COMPONENT_TYPE_INT:
|
||||
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_INT: {
|
||||
attribute.stride = sizeof(uint32_t);
|
||||
} break;
|
||||
case TINYGLTF_COMPONENT_TYPE_FLOAT: {
|
||||
attribute.stride = sizeof(float);
|
||||
} break;
|
||||
case TINYGLTF_COMPONENT_TYPE_DOUBLE: {
|
||||
attribute.stride = sizeof(double);
|
||||
} break;
|
||||
default: UF_MSG_ERROR("Unsupported component type");
|
||||
}
|
||||
|
||||
attribute.buffer = &(model.buffers[view.buffer].data[accessor.byteOffset + view.byteOffset]);
|
||||
attribute.components = accessor.ByteStride(view) / attribute.stride;
|
||||
attribute.length = accessor.count * attribute.components;
|
||||
#else
|
||||
switch ( accessor.componentType ) {
|
||||
case TINYGLTF_COMPONENT_TYPE_BYTE:
|
||||
case TINYGLTF_COMPONENT_TYPE_UNSIGNED_BYTE: {
|
||||
@ -346,7 +319,6 @@ pod::Graph ext::gltf::load( const uf::stl::string& filename, const uf::Serialize
|
||||
} break;
|
||||
default: UF_MSG_ERROR("Unsupported component type");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
for ( size_t i = 0; i < vertices.size(); ++i ) {
|
||||
|
||||
@ -8,28 +8,36 @@ namespace binds {
|
||||
uf::stl::string callback = "";
|
||||
uf::stl::string uri = "";
|
||||
uf::stl::string hash = "";
|
||||
uf::stl::string category = "";
|
||||
uf::stl::string mime = "";
|
||||
if ( it != va.end() ) callback = *(it++);
|
||||
if ( it != va.end() ) uri = *(it++);
|
||||
if ( it != va.end() ) hash = *(it++);
|
||||
if ( it != va.end() ) category = *(it++);
|
||||
if ( callback == "" ) asset.load( uri, hash, category );
|
||||
else asset.load( callback, uri, hash, category );
|
||||
if ( it != va.end() ) mime = *(it++);
|
||||
|
||||
auto payload = uf::Asset::resolveToPayload( uri, mime );
|
||||
payload.hash = hash;
|
||||
|
||||
if ( callback == "" ) asset.load( payload );
|
||||
else asset.load( callback, payload );
|
||||
}
|
||||
void cache( uf::Asset& asset, sol::variadic_args va ) {
|
||||
auto it = va.begin();
|
||||
uf::stl::string callback = "";
|
||||
uf::stl::string uri = "";
|
||||
uf::stl::string hash = "";
|
||||
uf::stl::string category = "";
|
||||
uf::stl::string mime = "";
|
||||
if ( it != va.end() ) callback = *(it++);
|
||||
if ( it != va.end() ) uri = *(it++);
|
||||
if ( it != va.end() ) hash = *(it++);
|
||||
if ( it != va.end() ) category = *(it++);
|
||||
if ( it != va.end() ) mime = *(it++);
|
||||
|
||||
auto payload = uf::Asset::resolveToPayload( uri, mime );
|
||||
payload.hash = hash;
|
||||
|
||||
if ( callback == "" )
|
||||
asset.cache( uri, hash, category );
|
||||
asset.cache( payload );
|
||||
else
|
||||
asset.cache( callback, uri, hash, category );
|
||||
asset.cache( callback, payload );
|
||||
}
|
||||
uf::stl::string getOriginal( uf::Asset& asset, const uf::stl::string& n ) {
|
||||
return asset.getOriginal( n );
|
||||
|
||||
@ -2,10 +2,10 @@
|
||||
#include <iostream>
|
||||
|
||||
uf::Timer<> uf::physics::time::timer;
|
||||
uf::physics::num_t uf::physics::time::current;
|
||||
uf::physics::num_t uf::physics::time::previous;
|
||||
uf::physics::num_t uf::physics::time::delta;
|
||||
uf::physics::num_t uf::physics::time::clamp;
|
||||
double uf::physics::time::current = 0;
|
||||
double uf::physics::time::previous = 0;
|
||||
float uf::physics::time::delta = 0;
|
||||
float uf::physics::time::clamp = 0;
|
||||
|
||||
|
||||
void UF_API uf::physics::initialize() {
|
||||
@ -14,6 +14,7 @@ void UF_API uf::physics::initialize() {
|
||||
void UF_API uf::physics::tick() {
|
||||
uf::physics::time::previous = uf::physics::time::current;
|
||||
uf::physics::time::current = uf::physics::time::timer.elapsed();
|
||||
|
||||
uf::physics::time::delta = uf::physics::time::current - uf::physics::time::previous;
|
||||
if ( uf::physics::time::delta > uf::physics::time::clamp ) {
|
||||
uf::physics::time::delta = uf::physics::time::clamp;
|
||||
|
||||
80
ext/behaviors/craeture/behavior.cpp
Normal file
80
ext/behaviors/craeture/behavior.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
#include "behavior.h"
|
||||
|
||||
#include <uf/utils/hook/hook.h>
|
||||
#include <uf/utils/time/time.h>
|
||||
#include <uf/utils/serialize/serializer.h>
|
||||
#include <uf/utils/userdata/userdata.h>
|
||||
#include <uf/utils/window/window.h>
|
||||
#include <uf/utils/window/payloads.h>
|
||||
#include <uf/utils/camera/camera.h>
|
||||
#include <uf/utils/audio/audio.h>
|
||||
#include <uf/ext/openvr/openvr.h>
|
||||
#include <uf/engine/graph/graph.h>
|
||||
#include <uf/engine/asset/asset.h>
|
||||
#include <uf/utils/math/physics.h>
|
||||
#include <uf/spec/controller/controller.h>
|
||||
#include <uf/utils/graphic/graphic.h>
|
||||
#include <uf/utils/io/inputs.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
|
||||
UF_BEHAVIOR_REGISTER_CPP(ext::CraetureBehavior)
|
||||
UF_BEHAVIOR_TRAITS_CPP(ext::CraetureBehavior, ticks = false, renders = false, multithread = false)
|
||||
#define this (&self)
|
||||
namespace {
|
||||
void load( uf::Object& self, uf::Image& image ) {
|
||||
auto& graphic = self.getComponent<uf::Graphic>();
|
||||
auto& texture = graphic.material.textures.emplace_back();
|
||||
texture.loadFromImage( image );
|
||||
|
||||
auto& mesh = self.getComponent<uf::Mesh>();
|
||||
mesh.bindIndirect<pod::DrawCommand>();
|
||||
mesh.bind<uf::graph::mesh::Base, uint16_t>();
|
||||
|
||||
float scaleX = 1;
|
||||
float scaleY = 1;
|
||||
|
||||
mesh.insertVertices<uf::graph::mesh::Base>({
|
||||
{ {-1.0f * scaleX, 1.0f * scaleY, 0.0f}, {}, {0.0f, 1.0f}, {0.0f, 1.0f}, {0.0f, 0.0f, -1.0f} },
|
||||
{ {-1.0f * scaleX, -1.0f * scaleY, 0.0f}, {}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f, -1.0f} },
|
||||
{ {1.0f * scaleX, -1.0f * scaleY, 0.0f}, {}, {1.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 0.0f, -1.0f} },
|
||||
{ {1.0f * scaleX, 1.0f * scaleY, 0.0f}, {}, {1.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, }
|
||||
});
|
||||
mesh.insertIndices<uint16_t>({
|
||||
0, 1, 2, 2, 3, 0
|
||||
});
|
||||
|
||||
uf::graph::convert( self );
|
||||
}
|
||||
}
|
||||
void ext::CraetureBehavior::initialize( uf::Object& self ) {
|
||||
this->addHook( "asset:Load.%UID%", [&](pod::payloads::assetLoad& payload){
|
||||
if ( !uf::Asset::isExpected( payload, uf::Asset::Type::IMAGE ) ) return;
|
||||
UF_MSG_DEBUG( "IMAGE: " << payload.filename );
|
||||
|
||||
uf::Scene& scene = uf::scene::getCurrentScene();
|
||||
uf::Asset& assetLoader = scene.getComponent<uf::Asset>();
|
||||
if ( !assetLoader.has<uf::Image>(payload.filename) ) return;
|
||||
auto& image = assetLoader.get<uf::Image>(payload.filename);
|
||||
::load( self, image );
|
||||
});
|
||||
|
||||
auto& metadata = this->getComponent<ext::CraetureBehavior::Metadata>();
|
||||
auto& metadataJson = this->getComponent<uf::Serializer>();
|
||||
|
||||
this->addHook( "object:UpdateMetadata.%UID%", [&](ext::json::Value& json){
|
||||
metadata.deserialize(self, metadataJson);
|
||||
});
|
||||
metadata.deserialize(self, metadataJson);
|
||||
}
|
||||
void ext::CraetureBehavior::tick( uf::Object& self ) {}
|
||||
void ext::CraetureBehavior::render( uf::Object& self ){}
|
||||
void ext::CraetureBehavior::destroy( uf::Object& self ){}
|
||||
void ext::CraetureBehavior::Metadata::serialize( uf::Object& self, uf::Serializer& serializer ){
|
||||
|
||||
}
|
||||
void ext::CraetureBehavior::Metadata::deserialize( uf::Object& self, uf::Serializer& serializer ){
|
||||
|
||||
}
|
||||
#undef this
|
||||
20
ext/behaviors/craeture/behavior.h
Normal file
20
ext/behaviors/craeture/behavior.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <uf/config.h>
|
||||
#include <uf/ext/ext.h>
|
||||
#include <uf/engine/entity/entity.h>
|
||||
#include <uf/engine/scene/scene.h>
|
||||
#include <uf/utils/math/vector.h>
|
||||
|
||||
namespace ext {
|
||||
namespace CraetureBehavior {
|
||||
UF_BEHAVIOR_DEFINE_TYPE();
|
||||
EXT_BEHAVIOR_DEFINE_TRAITS();
|
||||
EXT_BEHAVIOR_DEFINE_FUNCTIONS();
|
||||
UF_BEHAVIOR_DEFINE_METADATA(
|
||||
struct {
|
||||
float health;
|
||||
} stats;
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -52,8 +52,8 @@ void ext::PlayerHandBehavior::initialize( uf::Object& self ) {
|
||||
if ( !ext::openvr::requestRenderModel(metadata["hands"][key]["controller"]["model"].as<uf::stl::string>()) ) loaded = false;
|
||||
}
|
||||
if ( !loaded ) {
|
||||
this->addHook( "VR:Model.Loaded", [&](ext::json::Value& json){
|
||||
uf::stl::string name = json["name"].as<uf::stl::string>();
|
||||
this->addHook( "VR:Model.Loaded", [&](pod::payloads::assetLoad& payload){
|
||||
uf::stl::string name = payload.filename; // json["name"].as<uf::stl::string>();
|
||||
uf::stl::string side = "";
|
||||
if ( name == metadata["hands"]["left"]["controller"]["model"].as<uf::stl::string>() ) {
|
||||
side = "left";
|
||||
@ -157,38 +157,33 @@ void ext::PlayerHandBehavior::initialize( uf::Object& self ) {
|
||||
uf::stl::vector<uf::Object*> vHands = { ::hands.left, ::hands.right };
|
||||
for ( auto pointer : vHands ) {
|
||||
auto& hand = *pointer;
|
||||
hand.addHook("VR:Input.Digital", [&](ext::json::Value& json){
|
||||
uf::stl::string side = &hand == hands.left ? "left" : "right";
|
||||
if ( json["hand"].as<uf::stl::string>() != side ) return;
|
||||
hand.addHook("VR:Input.Digital", [&]( pod::payloads::vrInputDigital& payload){
|
||||
int_fast8_t side = &hand == hands.left ? -1 : 1;
|
||||
if ( payload.side != side ) return;
|
||||
|
||||
// fire mouse click
|
||||
if ( json["name"].as<uf::stl::string>() == "click" ) {
|
||||
if ( payload.name == "click" ) {
|
||||
pod::payloads::windowMouseClick pload;
|
||||
pload.type = "window:Mouse.Click";
|
||||
pload.invoker = "vr";
|
||||
pload.mouse.position = uf::vector::encode( metadata["hands"][side]["cursor"]["position"], pload.mouse.position );
|
||||
pload.mouse.delta = {};
|
||||
pload.mouse.button = side == -1 ? "Right" : "Left";
|
||||
pload.mouse.state = payload.state;
|
||||
|
||||
uf::Serializer payload;
|
||||
payload["type"] = "window:Mouse.Click";
|
||||
payload["invoker"] = "vr";
|
||||
// payload["mouse"]["position"]["x"] = metadata["hands"][side]["cursor"]["position"][0].as<float>();
|
||||
// payload["mouse"]["position"]["y"] = metadata["hands"][side]["cursor"]["position"][1].as<float>();
|
||||
// payload["mouse"]["delta"]["x"] = 0;
|
||||
// payload["mouse"]["delta"]["y"] = 0;
|
||||
payload["mouse"]["position"] = metadata["hands"][side]["cursor"]["position"];
|
||||
payload["mouse"]["delta"] = uf::vector::encode( pod::Vector2i{0,0} );
|
||||
payload["mouse"]["button"] = side == "left" ? "Right" : "Left";
|
||||
payload["mouse"]["state"] = json["state"].as<bool>() ? "Down": "Up";
|
||||
|
||||
uf::hooks.call( payload["type"].as<uf::stl::string>(), payload );
|
||||
uf::hooks.call( pload.type, payload );
|
||||
}
|
||||
});
|
||||
hand.addHook("world:Collision.%UID%", [&](ext::json::Value& json){
|
||||
|
||||
hand.addHook("world:Collision.%UID%", [&]( pod::payloads::worldCollision& payload){
|
||||
uf::stl::string side = &hand == hands.left ? "left" : "right";
|
||||
|
||||
float mag = json["depth"].as<float>();
|
||||
uf::Serializer payload;
|
||||
payload["delay"] = 0.0f;
|
||||
payload["duration"] = uf::physics::time::delta;
|
||||
payload["frequency"] = 1.0f;
|
||||
payload["amplitude"] = fmin(1.0f, 1000.0f * mag);
|
||||
payload["side"] = side;
|
||||
pod::payloads::vrHaptics pload;
|
||||
pload.delay = 0;
|
||||
pload.duration = uf::physics::time::delta;
|
||||
pload.frequency = 1;
|
||||
pload.amplitude = fmin(1.0f, 1000.0f * payload.depth);
|
||||
plaod.side = &hand == hands.left ? -1 : 1;;
|
||||
uf::hooks.call( "VR:Haptics." + side, payload );
|
||||
});
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ void ext::LightBehavior::initialize( uf::Object& self ) {
|
||||
|
||||
if ( !sceneMetadata["system"]["lights"]["round robin hook bound"].as<bool>() ) {
|
||||
sceneMetadata["system"]["lights"]["round robin hook bound"] = true;
|
||||
scene.addHook("game:Frame.Start", [&]( const ext::json::Value& payload ){
|
||||
scene.addHook("game:Frame.Start", [&]( ext::json::Value& payload ){
|
||||
if ( ++::roundRobin.current >= ::roundRobin.lights.size() ) ::roundRobin.current = 0;
|
||||
});
|
||||
}
|
||||
|
||||
@ -29,6 +29,8 @@ void ext::PlayerBehavior::initialize( uf::Object& self ) {
|
||||
|
||||
auto& camera = this->getComponent<uf::Camera>();
|
||||
auto& cameraTransform = camera.getTransform();
|
||||
|
||||
auto& scene = uf::scene::getCurrentScene();
|
||||
{
|
||||
camera.setStereoscopic(true);
|
||||
|
||||
@ -36,27 +38,29 @@ void ext::PlayerBehavior::initialize( uf::Object& self ) {
|
||||
cameraTransform.scale = uf::vector::decode( metadataJson["camera"]["scale"], cameraTransform.scale );
|
||||
cameraTransform.reference = &transform;
|
||||
|
||||
auto& cameraSettingsJson = metadataJson["camera"]["settings"];
|
||||
|
||||
if ( metadataJson["camera"]["ortho"].as<bool>() ) {
|
||||
float l = metadataJson["camera"]["settings"]["left"].as<float>();
|
||||
float r = metadataJson["camera"]["settings"]["right"].as<float>();
|
||||
float b = metadataJson["camera"]["settings"]["bottom"].as<float>();
|
||||
float t = metadataJson["camera"]["settings"]["top"].as<float>();
|
||||
float n = metadataJson["camera"]["settings"]["near"].as<float>();
|
||||
float f = metadataJson["camera"]["settings"]["far"].as<float>();
|
||||
float l = cameraSettingsJson["left"].as<float>();
|
||||
float r = cameraSettingsJson["right"].as<float>();
|
||||
float b = cameraSettingsJson["bottom"].as<float>();
|
||||
float t = cameraSettingsJson["top"].as<float>();
|
||||
float n = cameraSettingsJson["near"].as<float>();
|
||||
float f = cameraSettingsJson["far"].as<float>();
|
||||
|
||||
camera.setProjection( uf::matrix::orthographic( l, r, b, t, n, f ) );
|
||||
} else {
|
||||
float fov = metadataJson["camera"]["settings"]["fov"].as<float>(120) * (3.14159265358f / 180.0f);
|
||||
pod::Vector2f range = uf::vector::decode( metadataJson["camera"]["settings"]["clip"], pod::Vector2f{ 0.1, 64.0f } );
|
||||
pod::Vector2ui size = uf::vector::decode( metadataJson["camera"]["settings"]["size"], pod::Vector2ui{} );
|
||||
float fov = cameraSettingsJson["fov"].as<float>(120) * (3.14159265358f / 180.0f);
|
||||
pod::Vector2f range = uf::vector::decode( cameraSettingsJson["clip"], pod::Vector2f{ 0.1, 64.0f } );
|
||||
pod::Vector2ui size = uf::vector::decode( cameraSettingsJson["size"], pod::Vector2ui{} );
|
||||
float raidou = (float) size.x / (float) size.y;
|
||||
|
||||
if ( size.x == 0 || size.y == 0 ) {
|
||||
size = uf::vector::decode( ext::config["window"]["size"], pod::Vector2ui{} );
|
||||
raidou = (float) size.x / (float) size.y;
|
||||
this->addHook( "window:Resized", [&, fov, range](ext::json::Value& json){
|
||||
pod::Vector2ui size = uf::vector::decode( json["window"]["size"], pod::Vector2ui{} );
|
||||
float raidou = (float) size.x / (float) size.y;
|
||||
|
||||
this->addHook( "window:Resized", [&, fov, range](pod::payloads::windowResized& payload){
|
||||
float raidou = (float) payload.window.size.x / (float) payload.window.size.y;
|
||||
camera.setProjection( uf::matrix::perspective( fov, raidou, range.x, range.y ) );
|
||||
} );
|
||||
}
|
||||
@ -64,15 +68,17 @@ void ext::PlayerBehavior::initialize( uf::Object& self ) {
|
||||
}
|
||||
camera.update(true);
|
||||
}
|
||||
metadataJson["system"]["control"] = true;
|
||||
this->addHook( "window:Mouse.CursorVisibility", [&](ext::json::Value& json){
|
||||
metadata.system.control = !json["state"].as<bool>();
|
||||
|
||||
// sloppy
|
||||
metadata.mouse.sensitivity = uf::vector::decode( ext::config["window"]["cursor"]["sensitivity"], metadata.mouse.sensitivity );
|
||||
|
||||
this->addHook( "window:Mouse.CursorVisibility", [&](pod::payloads::windowMouseCursorVisibility& payload){
|
||||
metadata.system.control = !payload.mouse.visible;
|
||||
});
|
||||
|
||||
// Rotate Camera
|
||||
this->addHook( "window:Mouse.Moved", [&](pod::payloads::windowMouseMoved& payload ){
|
||||
float sensitivity = metadata.movement.look;
|
||||
pod::Vector2 relta = { (float) sensitivity * payload.mouse.delta.x / payload.window.size.x, (float) sensitivity * payload.mouse.delta.y / payload.window.size.y };
|
||||
pod::Vector2 relta = { (float) metadata.mouse.sensitivity.x * payload.mouse.delta.x / payload.window.size.x, (float) metadata.mouse.sensitivity.y * payload.mouse.delta.y / payload.window.size.y };
|
||||
if ( (payload.mouse.delta.x == 0 && payload.mouse.delta.y == 0) || !metadata.system.control ) return;
|
||||
|
||||
if ( payload.mouse.delta.x != 0 ) {
|
||||
@ -273,8 +279,9 @@ void ext::PlayerBehavior::tick( uf::Object& self ) {
|
||||
if ( stats.menu == "" && keys.paused ) {
|
||||
stats.menu = "paused";
|
||||
metadata.system.control = false;
|
||||
uf::Serializer payload;
|
||||
uf::hooks.call("menu:Pause", payload);
|
||||
pod::payloads::menuOpen payload;
|
||||
payload.name = "pause";
|
||||
uf::hooks.call("menu:Open", payload);
|
||||
}
|
||||
else if ( !metadata.system.control ) {
|
||||
stats.menu = "menu";
|
||||
@ -489,7 +496,7 @@ void ext::PlayerBehavior::Metadata::serialize( uf::Object& self, uf::Serializer&
|
||||
serializerSystemPhysicsMovement["air"] = /*this->*/movement.air;
|
||||
serializerSystemPhysicsMovement["jump"] = uf::vector::encode(/*this->*/movement.jump);
|
||||
serializerSystemPhysicsMovement["crouch"] = /*this->*/movement.crouch;
|
||||
serializerSystemPhysicsMovement["look"] = /*this->*/movement.look;
|
||||
// serializerSystemPhysicsMovement["look"] = /*this->*/movement.look;
|
||||
serializerAudioFootstep["list"] = /*this->*/audio.footstep.list;
|
||||
serializerAudioFootstep["volume"] = /*this->*/audio.footstep.volume;
|
||||
serializerCamera["invert"] = uf::vector::encode(/*this->*/camera.invert);
|
||||
@ -517,7 +524,7 @@ void ext::PlayerBehavior::Metadata::deserialize( uf::Object& self, uf::Serialize
|
||||
/*this->*/movement.air = serializerSystemPhysicsMovement["air"].as<float>();
|
||||
/*this->*/movement.jump = uf::vector::decode(serializerSystemPhysicsMovement["jump"], pod::Vector3f{});
|
||||
/*this->*/movement.crouch = serializerSystemPhysicsMovement["crouch"].as<float>();
|
||||
/*this->*/movement.look = serializerSystemPhysicsMovement["look"].as<float>(1.0f);
|
||||
// /*this->*/movement.look = serializerSystemPhysicsMovement["look"].as<float>(1.0f);
|
||||
ext::json::forEach( serializerAudioFootstep["list"], [&]( const ext::json::Value& value ){
|
||||
/*this->*/audio.footstep.list.emplace_back(value);
|
||||
});
|
||||
|
||||
@ -26,7 +26,6 @@ namespace ext {
|
||||
float walk = 1.0f;
|
||||
float friction = 0.8f;
|
||||
float air = 1.0f;
|
||||
float look = 1.0f;
|
||||
pod::Vector3f jump = {0,8,0};
|
||||
} movement;
|
||||
struct {
|
||||
@ -37,6 +36,9 @@ namespace ext {
|
||||
} limit;
|
||||
pod::Vector3t<bool> invert;
|
||||
} camera;
|
||||
struct {
|
||||
pod::Vector2f sensitivity;
|
||||
} mouse;
|
||||
struct {
|
||||
struct {
|
||||
uf::stl::vector<uf::stl::string> list;
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
#include <uf/ext/gltf/gltf.h>
|
||||
|
||||
#include <uf/utils/math/collision.h>
|
||||
#include <uf/utils/window/payloads.h>
|
||||
|
||||
#include <uf/ext/ext.h>
|
||||
|
||||
@ -38,25 +39,20 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
|
||||
auto& metadata = this->getComponent<ext::ExtSceneBehavior::Metadata>();
|
||||
auto& metadataJson = this->getComponent<uf::Serializer>();
|
||||
|
||||
this->addHook( "system:Quit.%UID%", [&](ext::json::Value& json){
|
||||
UF_MSG_DEBUG(json);
|
||||
this->addHook( "system:Quit.%UID%", [&](ext::json::Value& payload){
|
||||
ext::ready = false;
|
||||
});
|
||||
|
||||
this->addHook( "asset:Load.%UID%", [&](ext::json::Value& json){
|
||||
uf::stl::string filename = json["filename"].as<uf::stl::string>();
|
||||
uf::stl::string category = json["category"].as<uf::stl::string>();
|
||||
this->addHook( "asset:Load.%UID%", [&](pod::payloads::assetLoad& payload){
|
||||
if ( !uf::Asset::isExpected( payload, uf::Asset::Type::AUDIO ) ) return;
|
||||
|
||||
if ( category != "" && (category != "audio" && category != "audio-stream") ) return;
|
||||
if ( category == "" && uf::io::extension(filename) != "ogg" ) return;
|
||||
|
||||
if ( !assetLoader.has<uf::Audio>(filename) ) return;
|
||||
auto& asset = assetLoader.get<uf::Audio>(filename);
|
||||
if ( !assetLoader.has<uf::Audio>(payload.filename) ) return;
|
||||
auto& asset = assetLoader.get<uf::Audio>(payload.filename);
|
||||
auto& audio = this->getComponent<uf::Audio>();
|
||||
|
||||
audio.destroy();
|
||||
audio = std::move(asset);
|
||||
assetLoader.remove<uf::Audio>(filename);
|
||||
assetLoader.remove<uf::Audio>(payload.filename);
|
||||
|
||||
#if UF_AUDIO_MAPPED_VOLUMES
|
||||
audio.setVolume(uf::audio::volumes.count("bgm") > 0 ? uf::audio::volumes.at("bgm") : 1.0);
|
||||
@ -67,26 +63,35 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
|
||||
audio.play();
|
||||
});
|
||||
|
||||
this->addHook( "menu:Pause", [&](ext::json::Value& json){
|
||||
this->addHook( "menu:Open", [&](pod::payloads::menuOpen& payload){
|
||||
TIMER(1, true && ) {
|
||||
uf::Object* manager = (uf::Object*) this->globalFindByName("Gui Manager");
|
||||
if ( !manager ) return;
|
||||
|
||||
uf::stl::string key = payload.name;
|
||||
uf::Object& gui = manager->loadChild(metadataJson["menus"][key].as<uf::stl::string>("/entites/gui/"+key+"/menu.json"), false);
|
||||
uf::Serializer& metadataJson = gui.getComponent<uf::Serializer>();
|
||||
gui.initialize();
|
||||
};
|
||||
/*
|
||||
static uf::Timer<long long> timer(false);
|
||||
if ( !timer.running() ) timer.start( uf::Time<>(-1000000) );
|
||||
if ( timer.elapsed().asDouble() < 1 ) return;
|
||||
timer.reset();
|
||||
uf::Object* manager = (uf::Object*) this->globalFindByName("Gui Manager");
|
||||
if ( !manager ) return;
|
||||
|
||||
uf::Serializer payload;
|
||||
uf::stl::string config = metadataJson["menus"]["pause"].as<uf::stl::string>("/entites/gui/pause/menu.json");
|
||||
uf::Object& gui = manager->loadChild(config, false);
|
||||
payload["uid"] = gui.getUid();
|
||||
uf::Serializer& metadataJson = gui.getComponent<uf::Serializer>();
|
||||
metadataJson["menu"] = json["menu"];
|
||||
metadataJson["menu"] = payload.menu;
|
||||
gui.initialize();
|
||||
*/
|
||||
});
|
||||
this->addHook( "world:Entity.LoadAsset", [&](ext::json::Value& json){
|
||||
uf::stl::string asset = json["asset"].as<uf::stl::string>();
|
||||
uf::stl::string uid = json["uid"].as<uf::stl::string>();
|
||||
|
||||
assetLoader.load(asset, "asset:Load." + uid);
|
||||
this->addHook( "world:Entity.LoadAsset", [&](pod::payloads::assetLoad& payload){
|
||||
assetLoader.load("asset:Load." + payload.uid, payload);
|
||||
});
|
||||
this->addHook( "shader:Update.%UID%", [&](ext::json::Value& json){
|
||||
metadata.shader.mode = json["mode"].as<uint32_t>();
|
||||
@ -100,16 +105,13 @@ void ext::ExtSceneBehavior::initialize( uf::Object& self ) {
|
||||
}
|
||||
});
|
||||
/* store viewport size */
|
||||
this->addHook( "window:Resized", [&](ext::json::Value& json){
|
||||
pod::Vector2ui size = uf::vector::decode( json["window"]["size"], pod::Vector2i{} );
|
||||
|
||||
metadataJson["system"]["window"] = json["system"]["window"];
|
||||
ext::gui::size.current = size;
|
||||
this->addHook( "window:Resized", [&](pod::payloads::windowResized& payload){
|
||||
ext::gui::size.current = payload.window.size;
|
||||
});
|
||||
// lock control
|
||||
{
|
||||
uf::Serializer payload;
|
||||
payload["state"] = false;
|
||||
pod::payloads::windowMouseCursorVisibility payload;
|
||||
payload.mouse.visible = false;
|
||||
uf::hooks.call("window:Mouse.CursorVisibility", payload);
|
||||
uf::hooks.call("window:Mouse.Lock");
|
||||
}
|
||||
@ -301,16 +303,10 @@ void ext::ExtSceneBehavior::tick( uf::Object& self ) {
|
||||
#endif
|
||||
#if !UF_ENV_DREAMCAST
|
||||
/* Regain control if nothing requests it */ {
|
||||
if ( !this->globalFindByName("Gui: Menu") ) {
|
||||
uf::Serializer payload;
|
||||
payload["state"] = false;
|
||||
uf::hooks.call("window:Mouse.CursorVisibility", payload);
|
||||
uf::hooks.call("window:Mouse.Lock");
|
||||
} else {
|
||||
uf::Serializer payload;
|
||||
payload["state"] = true;
|
||||
uf::hooks.call("window:Mouse.CursorVisibility", payload);
|
||||
}
|
||||
pod::payloads::windowMouseCursorVisibility payload;
|
||||
payload.mouse.visible = this->globalFindByName("Gui: Menu");
|
||||
if ( !payload.mouse.visible ) uf::hooks.call("window:Mouse.Lock");
|
||||
uf::hooks.call("window:Mouse.CursorVisibility", payload);
|
||||
}
|
||||
#endif
|
||||
#if UF_ENTITY_METADATA_USE_JSON
|
||||
|
||||
@ -79,17 +79,15 @@ void ext::SoundEmitterBehavior::initialize( uf::Object& self ) {
|
||||
|
||||
audio.play();
|
||||
});
|
||||
this->addHook( "asset:Load.%UID%", [&](ext::json::Value& json){
|
||||
uf::stl::string filename = json["filename"].as<uf::stl::string>();
|
||||
uf::stl::string category = json["category"].as<uf::stl::string>();
|
||||
this->addHook( "asset:Load.%UID%", [&](pod::payloads::assetLoad& payload){
|
||||
if ( !uf::Asset::isExpected( payload, uf::Asset::Type::AUDIO ) ) return;
|
||||
UF_MSG_DEBUG( "AUDIO: " << payload.filename );
|
||||
|
||||
if ( category != "" && (category != "audio" && category != "audio-stream") ) return;
|
||||
if ( category == "" && uf::io::extension(filename) != "ogg" ) return;
|
||||
|
||||
if ( !assetLoader.has<uf::Audio>(filename) ) return;
|
||||
uf::Serializer payload = metadata["audio"];
|
||||
payload["filename"] = filename;
|
||||
this->callHook("sound:Emit.%UID%", payload);
|
||||
if ( !assetLoader.has<uf::Audio>(payload.filename) ) return;
|
||||
|
||||
uf::Serializer json = metadata["audio"];
|
||||
json["filename"] = payload.filename;
|
||||
this->callHook("sound:Emit.%UID%", json);
|
||||
});
|
||||
}
|
||||
void ext::SoundEmitterBehavior::tick( uf::Object& self ) {
|
||||
|
||||
@ -18,18 +18,20 @@
|
||||
#include <uf/engine/scene/scene.h>
|
||||
|
||||
#include <uf/utils/memory/unordered_map.h>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
|
||||
#include <uf/utils/renderer/renderer.h>
|
||||
#include <uf/ext/openvr/openvr.h>
|
||||
|
||||
#include <uf/utils/http/http.h>
|
||||
#include <uf/utils/audio/audio.h>
|
||||
|
||||
#include <uf/utils/window/payloads.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fstream>
|
||||
|
||||
#include <regex>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
|
||||
namespace {
|
||||
#if UF_USE_FREETYPE
|
||||
@ -431,30 +433,27 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
|
||||
});
|
||||
metadata.deserialize(self, metadataJson);
|
||||
|
||||
this->addHook( "asset:Load.%UID%", [&](ext::json::Value& json){
|
||||
uf::stl::string filename = json["filename"].as<uf::stl::string>();
|
||||
uf::stl::string category = json["category"].as<uf::stl::string>();
|
||||
|
||||
if ( category != "" && category != "images" ) return;
|
||||
if ( category == "" && uf::io::extension(filename) != "png" && uf::io::extension(filename) != "jpg" && uf::io::extension(filename) != "jpeg" ) return;
|
||||
this->addHook( "asset:Load.%UID%", [&](pod::payloads::assetLoad& payload){
|
||||
if ( !uf::Asset::isExpected( payload, uf::Asset::Type::IMAGE ) ) return;
|
||||
|
||||
uf::Scene& scene = uf::scene::getCurrentScene();
|
||||
uf::Asset& assetLoader = scene.getComponent<uf::Asset>();
|
||||
if ( !assetLoader.has<uf::Image>(filename) ) return;
|
||||
auto& image = assetLoader.get<uf::Image>(filename);
|
||||
if ( !assetLoader.has<uf::Image>(payload.filename) ) return;
|
||||
auto& image = assetLoader.get<uf::Image>(payload.filename);
|
||||
this->as<ext::Gui>().load( image );
|
||||
});
|
||||
if ( metadataJson["system"]["clickable"].as<bool>() ) {
|
||||
uf::Timer<long long> clickTimer(false);
|
||||
clickTimer.start( uf::Time<>(-1000000) );
|
||||
if ( !clickTimer.running() ) clickTimer.start();
|
||||
this->addHook( "gui:Clicked.%UID%", [&](ext::json::Value& json){
|
||||
|
||||
this->addHook( "gui:Clicked.%UID%", [&](pod::payloads::windowMouseClick& payload){
|
||||
if ( ext::json::isObject( metadataJson["events"]["click"] ) ) {
|
||||
uf::Serializer event = metadataJson["events"]["click"];
|
||||
metadataJson["events"]["click"] = ext::json::array(); //Json::arrayValue;
|
||||
metadataJson["events"]["click"][0] = event;
|
||||
} else if ( !ext::json::isArray( metadataJson["events"]["click"] ) ) {
|
||||
this->getParent().as<uf::Object>().callHook("gui:Clicked.%UID%", json);
|
||||
this->getParent().as<uf::Object>().callHook("gui:Clicked.%UID%", payload);
|
||||
return;
|
||||
}
|
||||
for ( int i = 0; i < metadataJson["events"]["click"].size(); ++i ) {
|
||||
@ -467,19 +466,15 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
|
||||
}
|
||||
}
|
||||
});
|
||||
this->addHook( "window:Mouse.Click", [&](ext::json::Value& json){
|
||||
this->addHook( "window:Mouse.Click", [&](pod::payloads::windowMouseClick& payload){
|
||||
if ( metadata.world ) return;
|
||||
if ( !metadata.box.min && !metadata.box.max ) return;
|
||||
bool down = json["mouse"]["state"].as<uf::stl::string>() == "Down";
|
||||
|
||||
bool clicked = false;
|
||||
if ( down ) {
|
||||
pod::Vector2ui position = uf::vector::decode( json["mouse"]["position"], pod::Vector2ui{} ); {
|
||||
// position.x = json["mouse"]["position"]["x"].as<int>() > 0 ? json["mouse"]["position"]["x"].as<size_t>() : 0;
|
||||
// position.y = json["mouse"]["position"]["y"].as<int>() > 0 ? json["mouse"]["position"]["y"].as<size_t>() : 0;
|
||||
}
|
||||
if ( payload.mouse.state == -1 ) {
|
||||
pod::Vector2f click; {
|
||||
click.x = (float) position.x / (float) ext::gui::size.current.x;
|
||||
click.y = (float) position.y / (float) ext::gui::size.current.y;
|
||||
click.x = (float) payload.mouse.position.x / (float) ext::gui::size.current.x;
|
||||
click.y = (float) payload.mouse.position.y / (float) ext::gui::size.current.y;
|
||||
|
||||
click.x = (click.x * 2.0f) - 1.0f;
|
||||
click.y = (click.y * 2.0f) - 1.0f;
|
||||
@ -487,13 +482,9 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
|
||||
float x = click.x;
|
||||
float y = click.y;
|
||||
|
||||
|
||||
if (json["invoker"] == "vr" ) {
|
||||
pod::Vector3f xy = uf::vector::decode( json["mouse"]["position"], pod::Vector2i{} );
|
||||
x = xy.x;
|
||||
y = xy.y;
|
||||
// x = json["mouse"]["position"]["x"].as<float>();
|
||||
// y = json["mouse"]["position"]["y"].as<float>();
|
||||
if (payload.invoker == "vr" ) {
|
||||
x = payload.mouse.position.x;
|
||||
y = payload.mouse.position.y;
|
||||
}
|
||||
clicked = ( metadata.box.min.x <= x && metadata.box.min.y <= y && metadata.box.max.x >= x && metadata.box.max.y >= y );
|
||||
}
|
||||
@ -501,8 +492,8 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
|
||||
}
|
||||
metadata.clicked = clicked;
|
||||
metadataJson["clicked"] = clicked;
|
||||
if ( clicked ) this->callHook("gui:Clicked.%UID%", json);
|
||||
this->callHook("gui:Mouse.Clicked.%UID%", json);
|
||||
if ( clicked ) this->callHook("gui:Clicked.%UID%", payload);
|
||||
this->callHook("gui:Mouse.Clicked.%UID%", payload);
|
||||
} );
|
||||
}
|
||||
if ( metadataJson["system"]["hoverable"].as<bool>() ) {
|
||||
@ -529,7 +520,7 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
|
||||
}
|
||||
return;
|
||||
});
|
||||
this->addHook( "window:Mouse.Moved", [&](ext::json::Value& json){
|
||||
this->addHook( "window:Mouse.Moved", [&](pod::payloads::windowMouseMoved& payload){
|
||||
if ( this->getUid() == 0 ) return;
|
||||
if ( !this->hasComponent<uf::Mesh>() ) return;
|
||||
|
||||
@ -537,11 +528,10 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
|
||||
if ( !metadata.box.min && !metadata.box.max ) return;
|
||||
|
||||
bool clicked = false;
|
||||
bool down = json["mouse"]["state"].as<uf::stl::string>() == "Down";
|
||||
pod::Vector2ui position = uf::vector::decode( json["mouse"]["position"], pod::Vector2ui{} );
|
||||
bool down = payload.mouse.state == -1;
|
||||
pod::Vector2f click; {
|
||||
click.x = (float) position.x / (float) ext::gui::size.current.x;
|
||||
click.y = (float) position.y / (float) ext::gui::size.current.y;
|
||||
click.x = (float) payload.mouse.position.x / (float) ext::gui::size.current.x;
|
||||
click.y = (float) payload.mouse.position.y / (float) ext::gui::size.current.y;
|
||||
|
||||
click.x = (click.x * 2.0f) - 1.0f;
|
||||
click.y = (click.y * 2.0f) - 1.0f;
|
||||
@ -551,13 +541,12 @@ void ext::GuiBehavior::initialize( uf::Object& self ) {
|
||||
clicked = ( metadata.box.min.x <= x && metadata.box.min.y <= y && metadata.box.max.x >= x && metadata.box.max.y >= y );
|
||||
}
|
||||
metadata.hovered = clicked;
|
||||
metadataJson["hovered"] = clicked;
|
||||
|
||||
if ( clicked && hoverTimer.elapsed().asDouble() >= 1 ) {
|
||||
hoverTimer.reset();
|
||||
this->callHook("gui:Hovered.%UID%", json);
|
||||
this->callHook("gui:Hovered.%UID%", payload);
|
||||
}
|
||||
this->callHook("gui:Mouse.Moved.%UID%", json);
|
||||
this->callHook("gui:Mouse.Moved.%UID%", payload);
|
||||
} );
|
||||
}
|
||||
#if UF_USE_FREETYPE
|
||||
|
||||
@ -17,18 +17,20 @@
|
||||
#include <uf/engine/scene/scene.h>
|
||||
|
||||
#include <uf/utils/memory/unordered_map.h>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
|
||||
#include <uf/utils/renderer/renderer.h>
|
||||
#include <uf/ext/openvr/openvr.h>
|
||||
|
||||
#include <uf/utils/http/http.h>
|
||||
#include <uf/utils/audio/audio.h>
|
||||
|
||||
#include <uf/utils/window/payloads.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fstream>
|
||||
|
||||
#include <regex>
|
||||
#include <locale>
|
||||
#include <codecvt>
|
||||
|
||||
ext::gui::Size ext::gui::size = {
|
||||
.current = {
|
||||
@ -61,19 +63,16 @@ void ext::GuiManagerBehavior::initialize( uf::Object& self ) {
|
||||
auto& metadata = controller.getComponent<ext::GuiManagerBehavior::Metadata>();
|
||||
auto& metadataJson = controller.getComponent<uf::Serializer>();
|
||||
|
||||
this->addHook( "window:Resized", [&](ext::json::Value& json){
|
||||
pod::Vector2ui size = uf::vector::decode( json["window"]["size"], pod::Vector2ui{} );
|
||||
ext::gui::size.current = size;
|
||||
// ext::gui::size.reference = size;
|
||||
this->addHook( "window:Resized", [&](pod::payloads::windowResized& payload){
|
||||
ext::gui::size.current = payload.window.size;
|
||||
// ext::gui::size.reference = payload.window.size;
|
||||
} );
|
||||
this->addHook( "window:Mouse.Moved", [&](ext::json::Value& json){
|
||||
this->addHook( "window:Mouse.Moved", [&](pod::payloads::windowMouseMoved& payload){
|
||||
bool clicked = false;
|
||||
bool down = json["mouse"]["state"].as<uf::stl::string>() == "Down";
|
||||
pod::Vector2ui position = uf::vector::decode( json["mouse"]["position"], pod::Vector2ui{} );
|
||||
|
||||
pod::Vector2f click; {
|
||||
click.x = (float) position.x / (float) ext::gui::size.current.x;
|
||||
click.y = (float) position.y / (float) ext::gui::size.current.y;
|
||||
click.x = (float) payload.mouse.position.x / (float) ext::gui::size.current.x;
|
||||
click.y = (float) payload.mouse.position.y / (float) ext::gui::size.current.y;
|
||||
click.x = (click.x * 2.0f) - 1.0f;
|
||||
click.y = (click.y * 2.0f) - 1.0f;
|
||||
float x = click.x;
|
||||
|
||||
260
ext/main.cpp
260
ext/main.cpp
@ -118,8 +118,10 @@ void EXT_API ext::initialize() {
|
||||
}
|
||||
|
||||
/* Set memory pool sizes */ {
|
||||
auto& configMemoryPoolJson = ::config["engine"]["memory pool"];
|
||||
|
||||
// check if we are even allowed to use memory pools
|
||||
bool enabled = ::config["engine"]["memory pool"]["enabled"].as(true);
|
||||
bool enabled = configMemoryPoolJson["enabled"].as(true);
|
||||
auto deduceSize = [enabled]( const ext::json::Value& value )->size_t{
|
||||
if ( !enabled ) return 0;
|
||||
if ( value.is<size_t>() ) return value.as<size_t>();
|
||||
@ -141,30 +143,30 @@ void EXT_API ext::initialize() {
|
||||
return 0;
|
||||
};
|
||||
// set memory pool alignment requirements
|
||||
uf::memoryPool::alignment = ::config["engine"]["memory pool"]["alignment"].as( uf::memoryPool::alignment );
|
||||
uf::memoryPool::alignment = configMemoryPoolJson["alignment"].as( uf::memoryPool::alignment );
|
||||
// set memory pool sizes
|
||||
size_t size = deduceSize( ::config["engine"]["memory pool"]["size"] );
|
||||
size_t size = deduceSize( configMemoryPoolJson["size"] );
|
||||
UF_MSG_DEBUG("Requesting " << (size_t) size << " bytes for global memory pool: " << &uf::memoryPool::global);
|
||||
uf::memoryPool::global.initialize( size );
|
||||
uf::memoryPool::subPool = ::config["engine"]["memory pool"]["subPools"].as( uf::memoryPool::subPool );
|
||||
uf::memoryPool::subPool = configMemoryPoolJson["subPools"].as( uf::memoryPool::subPool );
|
||||
if ( size <= 0 || uf::memoryPool::subPool ) {
|
||||
{
|
||||
size_t size = deduceSize( ::config["engine"]["memory pool"]["pools"]["component"] );
|
||||
size_t size = deduceSize( configMemoryPoolJson["pools"]["component"] );
|
||||
UF_MSG_DEBUG("Requesting " << (int) size << " bytes for component memory pool: " << &uf::component::memoryPool);
|
||||
uf::component::memoryPool.initialize( size );
|
||||
}
|
||||
{
|
||||
size_t size = deduceSize( ::config["engine"]["memory pool"]["pools"]["userdata"] );
|
||||
size_t size = deduceSize( configMemoryPoolJson["pools"]["userdata"] );
|
||||
UF_MSG_DEBUG("Requesting " << (int) size << " bytes for userdata memory pool: " << &uf::userdata::memoryPool);
|
||||
uf::userdata::memoryPool.initialize( size );
|
||||
}
|
||||
{
|
||||
size_t size = deduceSize( ::config["engine"]["memory pool"]["pools"]["entity"] );
|
||||
size_t size = deduceSize( configMemoryPoolJson["pools"]["entity"] );
|
||||
UF_MSG_DEBUG("Requesting " << (int) size << " bytes for entity memory pool: " << &uf::Entity::memoryPool);
|
||||
uf::Entity::memoryPool.initialize( size );
|
||||
}
|
||||
}
|
||||
uf::allocator::override = ::config["engine"]["memory pool"]["override"].as( uf::allocator::override );
|
||||
uf::allocator::override = configMemoryPoolJson["override"].as( uf::allocator::override );
|
||||
}
|
||||
{
|
||||
uf::Mesh::defaultInterleaved = ::config["engine"]["scenes"]["meshes"]["interleaved"].as( uf::Mesh::defaultInterleaved );
|
||||
@ -187,63 +189,74 @@ void EXT_API ext::initialize() {
|
||||
uf::Entity::deleteComponentsOnDestroy = ::config["engine"]["debug"]["entity"]["delete components on destroy"].as( uf::Entity::deleteComponentsOnDestroy );
|
||||
}
|
||||
|
||||
if ( ::config["engine"]["limiters"]["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>();
|
||||
::config["engine"]["limiters"]["framerate"] = refreshRate * scale;
|
||||
UF_MSG_DEBUG("Setting framerate cap to " << (int) refreshRate * scale);
|
||||
}
|
||||
if ( ::config["engine"]["threads"]["frame limiter"].as<uf::stl::string>() == "auto" && ::config["window"]["refresh rate"].is<size_t>() ) {
|
||||
float scale = 2.0;
|
||||
size_t refreshRate = ::config["window"]["refresh rate"].as<size_t>();
|
||||
::config["engine"]["threads"]["frame limiter"] = refreshRate * scale;
|
||||
UF_MSG_DEBUG("Setting thread frame limiter to " << (int) refreshRate * scale);
|
||||
}
|
||||
/* Frame limiter */ {
|
||||
float limit = ::config["engine"]["limiters"]["framerate"].as<float>();
|
||||
::times.limiter = limit != 0 ? 1.0 / limit : 0;
|
||||
}
|
||||
/* Thread frame limiter */ {
|
||||
float limit = ::config["engine"]["threads"]["frame limiter"].as<float>();
|
||||
uf::thread::limiter = limit != 0 ? 1.0 / limit : 0;
|
||||
}
|
||||
/* Max delta time */{
|
||||
float limit = ::config["engine"]["limiters"]["deltaTime"].as<float>();
|
||||
uf::physics::time::clamp = limit != 0 ? 1.0 / limit : 0;
|
||||
}
|
||||
{
|
||||
auto& configEngineLimitersJson = ::config["engine"]["limiters"];
|
||||
|
||||
// Set worker threads
|
||||
if ( ::config["engine"]["threads"]["workers"].as<uf::stl::string>() == "async" ) {
|
||||
uf::thread::async = true;
|
||||
auto threads = std::max( 1, (int) std::thread::hardware_concurrency() - 1 );
|
||||
::config["engine"]["threads"]["workers"] = threads;
|
||||
uf::thread::workers = ::config["engine"]["threads"]["workers"].as<size_t>();
|
||||
UF_MSG_DEBUG("Using async worker threads");
|
||||
} else if ( ::config["engine"]["threads"]["workers"].as<uf::stl::string>() == "auto" ) {
|
||||
auto threads = std::max( 1, (int) std::thread::hardware_concurrency() - 1 );
|
||||
::config["engine"]["threads"]["workers"] = threads;
|
||||
uf::thread::workers = ::config["engine"]["threads"]["workers"].as<size_t>();
|
||||
UF_MSG_DEBUG("Using " << threads << " worker threads");
|
||||
} else if ( ::config["engine"]["threads"]["workers"].is<size_t>() ) {
|
||||
auto threads = ::config["engine"]["threads"]["workers"].as<size_t>();
|
||||
uf::thread::workers = threads;
|
||||
UF_MSG_DEBUG("Using " << threads << " worker threads");
|
||||
/* Frame limiter */ {
|
||||
float limit = configEngineLimitersJson["framerate"].as<float>();
|
||||
::times.limiter = limit != 0 ? 1.0 / limit : 0;
|
||||
}
|
||||
/* Max delta time */{
|
||||
float limit = configEngineLimitersJson["deltaTime"].as<float>();
|
||||
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"];
|
||||
|
||||
if ( configEngineThreadJson["frame limiter"].as<uf::stl::string>() == "auto" && ::config["window"]["refresh rate"].is<size_t>() ) {
|
||||
float scale = 2.0;
|
||||
size_t refreshRate = ::config["window"]["refresh rate"].as<size_t>();
|
||||
configEngineThreadJson["frame limiter"] = refreshRate * scale;
|
||||
UF_MSG_DEBUG("Setting thread frame limiter to " << (int) refreshRate * scale);
|
||||
}
|
||||
/* Thread frame limiter */ {
|
||||
float limit = configEngineThreadJson["frame limiter"].as<float>();
|
||||
uf::thread::limiter = limit != 0 ? 1.0 / limit : 0;
|
||||
}
|
||||
|
||||
// Set worker threads
|
||||
if ( configEngineThreadJson["workers"].as<uf::stl::string>() == "async" ) {
|
||||
uf::thread::async = true;
|
||||
auto threads = std::max( 1, (int) std::thread::hardware_concurrency() - 1 );
|
||||
configEngineThreadJson["workers"] = threads;
|
||||
uf::thread::workers = configEngineThreadJson["workers"].as<size_t>();
|
||||
UF_MSG_DEBUG("Using async worker threads");
|
||||
} else if ( configEngineThreadJson["workers"].as<uf::stl::string>() == "auto" ) {
|
||||
auto threads = std::max( 1, (int) std::thread::hardware_concurrency() - 1 );
|
||||
configEngineThreadJson["workers"] = threads;
|
||||
uf::thread::workers = configEngineThreadJson["workers"].as<size_t>();
|
||||
UF_MSG_DEBUG("Using " << threads << " worker threads");
|
||||
} else if ( configEngineThreadJson["workers"].is<size_t>() ) {
|
||||
auto threads = configEngineThreadJson["workers"].as<size_t>();
|
||||
uf::thread::workers = threads;
|
||||
UF_MSG_DEBUG("Using " << threads << " worker threads");
|
||||
}
|
||||
}
|
||||
// Audio settings
|
||||
{
|
||||
uf::audio::muted = ::config["engine"]["audio"]["mute"].as( uf::audio::muted );
|
||||
uf::audio::streamsByDefault = ::config["engine"]["audio"]["streams by default"].as( uf::audio::streamsByDefault );
|
||||
uf::audio::bufferSize = ::config["engine"]["audio"]["buffers"]["size"].as( uf::audio::bufferSize );
|
||||
uf::audio::buffers = ::config["engine"]["audio"]["buffers"]["count"].as( uf::audio::buffers );
|
||||
{
|
||||
auto& configEngineAudioJson = ::config["engine"]["audio"];
|
||||
|
||||
uf::audio::muted = configEngineAudioJson["mute"].as( uf::audio::muted );
|
||||
uf::audio::streamsByDefault = configEngineAudioJson["streams by default"].as( uf::audio::streamsByDefault );
|
||||
uf::audio::bufferSize = configEngineAudioJson["buffers"]["size"].as( uf::audio::bufferSize );
|
||||
uf::audio::buffers = configEngineAudioJson["buffers"]["count"].as( uf::audio::buffers );
|
||||
#if UF_AUDIO_MAPPED_VOLUMES
|
||||
ext::json::forEach( ::config["engine"]["audio"]["volumes"], []( const uf::stl::string& key, ext::json::Value& value ){
|
||||
ext::json::forEach( configEngineAudioJson["volumes"], []( const uf::stl::string& key, ext::json::Value& value ){
|
||||
float volume; volume = value.as(volume);
|
||||
uf::audio::volumes[key] = volume;
|
||||
});
|
||||
#else
|
||||
uf::audio::volumes::bgm = ::config["engine"]["audio"]["volumes"]["bgm"].as(uf::audio::volumes::bgm);
|
||||
uf::audio::volumes::sfx = ::config["engine"]["audio"]["volumes"]["sfx"].as(uf::audio::volumes::sfx);
|
||||
uf::audio::volumes::voice = ::config["engine"]["audio"]["volumes"]["voice"].as(uf::audio::volumes::voice);
|
||||
uf::audio::volumes::bgm = configEngineAudioJson["volumes"]["bgm"].as(uf::audio::volumes::bgm);
|
||||
uf::audio::volumes::sfx = configEngineAudioJson["volumes"]["sfx"].as(uf::audio::volumes::sfx);
|
||||
uf::audio::volumes::voice = configEngineAudioJson["volumes"]["voice"].as(uf::audio::volumes::voice);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -256,81 +269,88 @@ void EXT_API ext::initialize() {
|
||||
// set bullet parameters
|
||||
#if UF_USE_BULLET
|
||||
{
|
||||
ext::bullet::iterations = ::config["engine"]["ext"]["bullet"]["iterations"].as( ext::bullet::iterations );
|
||||
ext::bullet::substeps = ::config["engine"]["ext"]["bullet"]["substeps"].as( ext::bullet::substeps );
|
||||
ext::bullet::timescale = ::config["engine"]["ext"]["bullet"]["timescale"].as( ext::bullet::timescale );
|
||||
ext::bullet::defaultMaxCollisionAlgorithmPoolSize = ::config["engine"]["ext"]["bullet"]["pool size"]["max collision algorithm"].as( ext::bullet::defaultMaxCollisionAlgorithmPoolSize );
|
||||
ext::bullet::defaultMaxPersistentManifoldPoolSize = ::config["engine"]["ext"]["bullet"]["pool size"]["max persistent manifold"].as( ext::bullet::defaultMaxPersistentManifoldPoolSize );
|
||||
auto& configEngineBulletJson = ::config["engine"]["ext"]["bullet"];
|
||||
|
||||
ext::bullet::iterations = configEngineBulletJson["iterations"].as( ext::bullet::iterations );
|
||||
ext::bullet::substeps = configEngineBulletJson["substeps"].as( ext::bullet::substeps );
|
||||
ext::bullet::timescale = configEngineBulletJson["timescale"].as( ext::bullet::timescale );
|
||||
ext::bullet::defaultMaxCollisionAlgorithmPoolSize = configEngineBulletJson["pool size"]["max collision algorithm"].as( ext::bullet::defaultMaxCollisionAlgorithmPoolSize );
|
||||
ext::bullet::defaultMaxPersistentManifoldPoolSize = configEngineBulletJson["pool size"]["max persistent manifold"].as( ext::bullet::defaultMaxPersistentManifoldPoolSize );
|
||||
|
||||
ext::bullet::debugDrawEnabled = ::config["engine"]["ext"]["bullet"]["debug draw"]["enabled"].as( ext::bullet::debugDrawEnabled );
|
||||
ext::bullet::debugDrawRate = ::config["engine"]["ext"]["bullet"]["debug draw"]["rate"].as( ext::bullet::debugDrawRate );
|
||||
ext::bullet::debugDrawLayer = ::config["engine"]["ext"]["bullet"]["debug draw"]["layer"].as( ext::bullet::debugDrawLayer );
|
||||
ext::bullet::debugDrawLineWidth = ::config["engine"]["ext"]["bullet"]["debug draw"]["line width"].as( ext::bullet::debugDrawLineWidth );
|
||||
ext::bullet::debugDrawEnabled = configEngineBulletJson["debug draw"]["enabled"].as( ext::bullet::debugDrawEnabled );
|
||||
ext::bullet::debugDrawRate = configEngineBulletJson["debug draw"]["rate"].as( ext::bullet::debugDrawRate );
|
||||
ext::bullet::debugDrawLayer = configEngineBulletJson["debug draw"]["layer"].as( ext::bullet::debugDrawLayer );
|
||||
ext::bullet::debugDrawLineWidth = configEngineBulletJson["debug draw"]["line width"].as( ext::bullet::debugDrawLineWidth );
|
||||
}
|
||||
#elif UF_USE_REACTPHYSICS
|
||||
{
|
||||
ext::reactphysics::timescale = ::config["engine"]["ext"]["reactphysics"]["timescale"].as( ext::reactphysics::timescale );
|
||||
ext::reactphysics::debugDrawEnabled = ::config["engine"]["ext"]["reactphysics"]["debug draw"]["enabled"].as( ext::reactphysics::debugDrawEnabled );
|
||||
ext::reactphysics::debugDrawRate = ::config["engine"]["ext"]["reactphysics"]["debug draw"]["rate"].as( ext::reactphysics::debugDrawRate );
|
||||
ext::reactphysics::debugDrawLayer = ::config["engine"]["ext"]["reactphysics"]["debug draw"]["layer"].as( ext::reactphysics::debugDrawLayer );
|
||||
ext::reactphysics::debugDrawLineWidth = ::config["engine"]["ext"]["reactphysics"]["debug draw"]["line width"].as( ext::reactphysics::debugDrawLineWidth );
|
||||
auto& configEngineReactJson = ::config["engine"]["ext"]["reactphysics"];
|
||||
|
||||
ext::reactphysics::timescale = configEngineReactJson["timescale"].as( ext::reactphysics::timescale );
|
||||
ext::reactphysics::debugDrawEnabled = configEngineReactJson["debug draw"]["enabled"].as( ext::reactphysics::debugDrawEnabled );
|
||||
ext::reactphysics::debugDrawRate = configEngineReactJson["debug draw"]["rate"].as( ext::reactphysics::debugDrawRate );
|
||||
ext::reactphysics::debugDrawLayer = configEngineReactJson["debug draw"]["layer"].as( ext::reactphysics::debugDrawLayer );
|
||||
ext::reactphysics::debugDrawLineWidth = configEngineReactJson["debug draw"]["line width"].as( ext::reactphysics::debugDrawLineWidth );
|
||||
}
|
||||
#endif
|
||||
|
||||
// renderer settings
|
||||
{
|
||||
#if UF_USE_VULKAN
|
||||
const uf::stl::string RENDERER = "vulkan";
|
||||
auto& configRenderJson = ::config["engine"]["ext"]["vulkan"];
|
||||
#elif UF_USE_OPENGL
|
||||
const uf::stl::string RENDERER = "opengl";
|
||||
auto& configRenderJson = ::config["engine"]["ext"]["opengl"];
|
||||
#else
|
||||
const uf::stl::string RENDERER = "software";
|
||||
auto& configRenderJson = ::config["engine"]["ext"]["software"];
|
||||
#endif
|
||||
uf::renderer::settings::validation = ::config["engine"]["ext"][RENDERER]["validation"]["enabled"].as( uf::renderer::settings::validation );
|
||||
uf::renderer::settings::msaa = ::config["engine"]["ext"][RENDERER]["framebuffer"]["msaa"].as( uf::renderer::settings::msaa );
|
||||
auto& configRenderExperimentalJson = configRenderJson["experimental"];
|
||||
|
||||
if ( ::config["engine"]["ext"][RENDERER]["framebuffer"]["size"].is<float>() ) {
|
||||
float scale = ::config["engine"]["ext"][RENDERER]["framebuffer"]["size"].as(1.0f);
|
||||
uf::renderer::settings::validation = configRenderJson["validation"]["enabled"].as( uf::renderer::settings::validation );
|
||||
uf::renderer::settings::msaa = configRenderJson["framebuffer"]["msaa"].as( uf::renderer::settings::msaa );
|
||||
|
||||
if ( configRenderJson["framebuffer"]["size"].is<float>() ) {
|
||||
float scale = configRenderJson["framebuffer"]["size"].as(1.0f);
|
||||
uf::renderer::settings::width *= scale;
|
||||
uf::renderer::settings::height *= scale;
|
||||
} else if ( ext::json::isArray( ::config["engine"]["ext"][RENDERER]["framebuffer"]["size"] ) ) {
|
||||
uf::renderer::settings::width = ::config["engine"]["ext"][RENDERER]["framebuffer"]["size"][0].as<float>();
|
||||
uf::renderer::settings::height = ::config["engine"]["ext"][RENDERER]["framebuffer"]["size"][1].as<float>();
|
||||
uf::stl::string filter = ::config["engine"]["ext"][RENDERER]["framebuffer"]["size"][2].as<uf::stl::string>();
|
||||
if ( uf::string::lowercase( filter ) == "nearest" ) uf::renderer::settings::swapchainUpscaleFilter = uf::renderer::enums::Filter::NEAREST;
|
||||
else if ( uf::string::lowercase( filter ) == "linear" ) uf::renderer::settings::swapchainUpscaleFilter = uf::renderer::enums::Filter::LINEAR;
|
||||
} else if ( ext::json::isArray( configRenderJson["framebuffer"]["size"] ) ) {
|
||||
uf::renderer::settings::width = configRenderJson["framebuffer"]["size"][0].as<float>();
|
||||
uf::renderer::settings::height = configRenderJson["framebuffer"]["size"][1].as<float>();
|
||||
uf::stl::string filter = uf::string::lowercase( configRenderJson["framebuffer"]["size"][2].as<uf::stl::string>() );
|
||||
|
||||
if ( filter == "nearest" ) uf::renderer::settings::swapchainUpscaleFilter = uf::renderer::enums::Filter::NEAREST;
|
||||
else if ( filter == "linear" ) uf::renderer::settings::swapchainUpscaleFilter = uf::renderer::enums::Filter::LINEAR;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < ::config["engine"]["ext"][RENDERER]["validation"]["filters"].size(); ++i ) {
|
||||
uf::renderer::settings::validationFilters.emplace_back( ::config["engine"]["ext"][RENDERER]["validation"]["filters"][i].as<uf::stl::string>() );
|
||||
for ( int i = 0; i < configRenderJson["validation"]["filters"].size(); ++i ) {
|
||||
uf::renderer::settings::validationFilters.emplace_back( configRenderJson["validation"]["filters"][i].as<uf::stl::string>() );
|
||||
}
|
||||
for ( int i = 0; i < ::config["engine"]["ext"][RENDERER]["extensions"]["device"].size(); ++i ) {
|
||||
uf::renderer::settings::requestedDeviceExtensions.emplace_back( ::config["engine"]["ext"][RENDERER]["extensions"]["device"][i].as<uf::stl::string>() );
|
||||
for ( int i = 0; i < configRenderJson["extensions"]["device"].size(); ++i ) {
|
||||
uf::renderer::settings::requestedDeviceExtensions.emplace_back( configRenderJson["extensions"]["device"][i].as<uf::stl::string>() );
|
||||
}
|
||||
for ( int i = 0; i < ::config["engine"]["ext"][RENDERER]["extensions"]["instance"].size(); ++i ) {
|
||||
uf::renderer::settings::requestedInstanceExtensions.emplace_back( ::config["engine"]["ext"][RENDERER]["extensions"]["instance"][i].as<uf::stl::string>() );
|
||||
for ( int i = 0; i < configRenderJson["extensions"]["instance"].size(); ++i ) {
|
||||
uf::renderer::settings::requestedInstanceExtensions.emplace_back( configRenderJson["extensions"]["instance"][i].as<uf::stl::string>() );
|
||||
}
|
||||
for ( int i = 0; i < ::config["engine"]["ext"][RENDERER]["features"].size(); ++i ) {
|
||||
uf::renderer::settings::requestedDeviceFeatures.emplace_back( ::config["engine"]["ext"][RENDERER]["features"][i].as<uf::stl::string>() );
|
||||
for ( int i = 0; i < configRenderJson["features"].size(); ++i ) {
|
||||
uf::renderer::settings::requestedDeviceFeatures.emplace_back( configRenderJson["features"][i].as<uf::stl::string>() );
|
||||
}
|
||||
|
||||
uf::renderer::settings::experimental::rebuildOnTickBegin = ::config["engine"]["ext"][RENDERER]["experimental"]["rebuild on tick begin"].as( uf::renderer::settings::experimental::rebuildOnTickBegin );
|
||||
uf::renderer::settings::experimental::waitOnRenderEnd = ::config["engine"]["ext"][RENDERER]["experimental"]["wait on render end"].as( uf::renderer::settings::experimental::waitOnRenderEnd );
|
||||
uf::renderer::settings::experimental::individualPipelines = ::config["engine"]["ext"][RENDERER]["experimental"]["individual pipelines"].as( uf::renderer::settings::experimental::individualPipelines );
|
||||
uf::renderer::settings::experimental::multithreadedCommandRecording = ::config["engine"]["ext"][RENDERER]["experimental"]["multithreaded command recording"].as( uf::renderer::settings::experimental::multithreadedCommandRecording );
|
||||
uf::renderer::settings::experimental::multithreadedCommandRendering = ::config["engine"]["ext"][RENDERER]["experimental"]["multithreaded command rendering"].as( uf::renderer::settings::experimental::multithreadedCommandRendering );
|
||||
uf::renderer::settings::experimental::deferredMode = ::config["engine"]["ext"][RENDERER]["experimental"]["deferred mode"].as( uf::renderer::settings::experimental::deferredMode );
|
||||
uf::renderer::settings::experimental::deferredReconstructPosition = ::config["engine"]["ext"][RENDERER]["experimental"]["deferred reconstruct position"].as( uf::renderer::settings::experimental::deferredReconstructPosition );
|
||||
uf::renderer::settings::experimental::deferredAliasOutputToSwapchain = ::config["engine"]["ext"][RENDERER]["experimental"]["deferred alias output to swapchain"].as( uf::renderer::settings::experimental::deferredAliasOutputToSwapchain );
|
||||
uf::renderer::settings::experimental::vsync = ::config["engine"]["ext"][RENDERER]["experimental"]["vsync"].as( uf::renderer::settings::experimental::vsync );
|
||||
uf::renderer::settings::experimental::hdr = ::config["engine"]["ext"][RENDERER]["experimental"]["hdr"].as( uf::renderer::settings::experimental::hdr );
|
||||
uf::renderer::settings::experimental::vxgi = ::config["engine"]["ext"][RENDERER]["experimental"]["vxgi"].as( uf::renderer::settings::experimental::vxgi );
|
||||
uf::renderer::settings::experimental::deferredSampling = ::config["engine"]["ext"][RENDERER]["experimental"]["deferred sampling"].as( uf::renderer::settings::experimental::deferredSampling );
|
||||
uf::renderer::settings::experimental::culling = ::config["engine"]["ext"][RENDERER]["experimental"]["culling"].as( uf::renderer::settings::experimental::culling );
|
||||
uf::renderer::settings::experimental::bloom = ::config["engine"]["ext"][RENDERER]["experimental"]["bloom"].as( uf::renderer::settings::experimental::bloom );
|
||||
uf::renderer::settings::experimental::rebuildOnTickBegin = configRenderExperimentalJson["rebuild on tick begin"].as( uf::renderer::settings::experimental::rebuildOnTickBegin );
|
||||
uf::renderer::settings::experimental::waitOnRenderEnd = configRenderExperimentalJson["wait on render end"].as( uf::renderer::settings::experimental::waitOnRenderEnd );
|
||||
uf::renderer::settings::experimental::individualPipelines = configRenderExperimentalJson["individual pipelines"].as( uf::renderer::settings::experimental::individualPipelines );
|
||||
uf::renderer::settings::experimental::multithreadedCommandRecording = configRenderExperimentalJson["multithreaded command recording"].as( uf::renderer::settings::experimental::multithreadedCommandRecording );
|
||||
uf::renderer::settings::experimental::multithreadedCommandRendering = configRenderExperimentalJson["multithreaded command rendering"].as( uf::renderer::settings::experimental::multithreadedCommandRendering );
|
||||
uf::renderer::settings::experimental::deferredMode = configRenderExperimentalJson["deferred mode"].as( uf::renderer::settings::experimental::deferredMode );
|
||||
uf::renderer::settings::experimental::deferredReconstructPosition = configRenderExperimentalJson["deferred reconstruct position"].as( uf::renderer::settings::experimental::deferredReconstructPosition );
|
||||
uf::renderer::settings::experimental::deferredAliasOutputToSwapchain = configRenderExperimentalJson["deferred alias output to swapchain"].as( uf::renderer::settings::experimental::deferredAliasOutputToSwapchain );
|
||||
uf::renderer::settings::experimental::vsync = configRenderExperimentalJson["vsync"].as( uf::renderer::settings::experimental::vsync );
|
||||
uf::renderer::settings::experimental::hdr = configRenderExperimentalJson["hdr"].as( uf::renderer::settings::experimental::hdr );
|
||||
uf::renderer::settings::experimental::vxgi = configRenderExperimentalJson["vxgi"].as( uf::renderer::settings::experimental::vxgi );
|
||||
uf::renderer::settings::experimental::deferredSampling = configRenderExperimentalJson["deferred sampling"].as( uf::renderer::settings::experimental::deferredSampling );
|
||||
uf::renderer::settings::experimental::culling = configRenderExperimentalJson["culling"].as( uf::renderer::settings::experimental::culling );
|
||||
uf::renderer::settings::experimental::bloom = configRenderExperimentalJson["bloom"].as( uf::renderer::settings::experimental::bloom );
|
||||
|
||||
#define JSON_TO_VKFORMAT( key ) if ( ::config["engine"]["ext"][RENDERER]["formats"][#key].is<uf::stl::string>() ) {\
|
||||
uf::stl::string format = ::config["engine"]["ext"][RENDERER]["formats"][#key].as<uf::stl::string>();\
|
||||
#define JSON_TO_VKFORMAT( key ) if ( configRenderJson["formats"][#key].is<uf::stl::string>() ) {\
|
||||
uf::stl::string format = configRenderJson["formats"][#key].as<uf::stl::string>();\
|
||||
format = uf::string::replace( uf::string::uppercase(format), " ", "_" );\
|
||||
uf::renderer::settings::formats::key = uf::renderer::formatFromString( format );\
|
||||
}
|
||||
@ -347,9 +367,11 @@ void EXT_API ext::initialize() {
|
||||
|
||||
#if UF_USE_LUA
|
||||
/* Lua */ {
|
||||
ext::lua::enabled = ::config["engine"]["ext"]["lua"]["enabled"].as(ext::lua::enabled);
|
||||
ext::lua::main = ::config["engine"]["ext"]["lua"]["main"].as(ext::lua::main);
|
||||
ext::json::forEach( ::config["engine"]["ext"]["lua"]["modules"], []( const uf::stl::string& key, ext::json::Value& value ){
|
||||
auto& configLuaJson = ::config["engine"]["ext"]["lua"];
|
||||
|
||||
ext::lua::enabled = configLuaJson["enabled"].as(ext::lua::enabled);
|
||||
ext::lua::main = configLuaJson["main"].as(ext::lua::main);
|
||||
ext::json::forEach( configLuaJson["modules"], []( const uf::stl::string& key, ext::json::Value& value ){
|
||||
ext::lua::modules[key] = value.as<uf::stl::string>();
|
||||
});
|
||||
ext::lua::initialize();
|
||||
@ -361,16 +383,18 @@ void EXT_API ext::initialize() {
|
||||
}
|
||||
#if UF_USE_OPENVR
|
||||
{
|
||||
ext::openvr::enabled = ::config["engine"]["ext"]["vr"]["enable"].as( ext::openvr::enabled );
|
||||
ext::openvr::swapEyes = ::config["engine"]["ext"]["vr"]["swap eyes"].as( ext::openvr::swapEyes );
|
||||
auto& configVrJson = ::config["engine"]["ext"]["vr"];
|
||||
|
||||
ext::openvr::enabled = configVrJson["enable"].as( ext::openvr::enabled );
|
||||
ext::openvr::swapEyes = configVrJson["swap eyes"].as( ext::openvr::swapEyes );
|
||||
|
||||
|
||||
if ( ::config["engine"]["ext"]["vr"]["dominant eye"].is<int>() ) {
|
||||
ext::openvr::dominantEye = ::config["engine"]["ext"]["vr"]["dominant eye"].as<int>();
|
||||
} else if ( ::config["engine"]["ext"]["vr"]["dominant eye"].as<uf::stl::string>() == "left" ) ext::openvr::dominantEye = 0;
|
||||
else if ( ::config["engine"]["ext"]["vr"]["dominant eye"].as<uf::stl::string>() == "right" ) ext::openvr::dominantEye = 1;
|
||||
if ( configVrJson["dominant eye"].is<int>() ) {
|
||||
ext::openvr::dominantEye = configVrJson["dominant eye"].as<int>();
|
||||
} else if ( configVrJson["dominant eye"].as<uf::stl::string>() == "left" ) ext::openvr::dominantEye = 0;
|
||||
else if ( configVrJson["dominant eye"].as<uf::stl::string>() == "right" ) ext::openvr::dominantEye = 1;
|
||||
|
||||
ext::openvr::driver.manifest = ::config["engine"]["ext"]["vr"]["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;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user